28ebd24844
This causes problems for other projects incorporating dib; we don't have a specific need for a cap. Fix a few issues, mostly spacing or regex matches. No functional changes. W503 and W504 relate to leaving artithmetic operators at the start or end of lines, and are mutually exclusive and, due to "ignore" overriding the defaults both get enabled. It seems everyone gets this wrong (https://gitlab.com/pycqa/flake8/issues/466). Don't take a position on this and ignore both. Use double # around comments including YAML snippets using "# type: " which now gets detected as PEP484/mypy type hints. Change-Id: I8b7ce6dee02dcce31c82427a2441c931d136ef57
200 lines
6.5 KiB
Text
Executable file
200 lines
6.5 KiB
Text
Executable file
#!/usr/local/bin/dib-python
|
|
|
|
# Copyright 2014 Red Hat Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import argparse
|
|
import json
|
|
import logging
|
|
import os
|
|
import sys
|
|
|
|
|
|
log = logging.getLogger()
|
|
|
|
|
|
def os_family(distro):
|
|
family = None
|
|
if distro in ['fedora', 'rhel', 'rhel7', 'centos', 'centos7']:
|
|
family = 'redhat'
|
|
elif distro in ['debian', 'ubuntu']:
|
|
family = 'debian'
|
|
elif distro == 'opensuse':
|
|
family = 'suse'
|
|
elif distro == 'gentoo':
|
|
family = 'gentoo'
|
|
|
|
return family
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="Translate package name to distro specific name."
|
|
" Exits with 1 if error is encountered, 2 if no pkg-map"
|
|
" file is found. Otherwise exits with 0.")
|
|
parser.add_argument('--element', default='',
|
|
help='The element (namespace) to use for translation.')
|
|
parser.add_argument('--pkg-map', default='',
|
|
help='Path to specific pkg-map file. '
|
|
'(Useful for testing)')
|
|
parser.add_argument('--distro', default=os.environ.get('DISTRO_NAME'),
|
|
help='The distro name to use for translation.'
|
|
' Defaults to DISTRO_NAME')
|
|
parser.add_argument('--release', default=os.environ.get('DIB_RELEASE'),
|
|
help='A more specfic name for distribution release')
|
|
parser.add_argument('--missing-ok', action="store_true",
|
|
help='Do not consider missing mappings an error.'
|
|
' Causes packages where no mapping is set to be'
|
|
' printed.')
|
|
# This tool has traditionally output status and debug messages on
|
|
# stderr. The problem is if a caller has stderr > stdout then
|
|
# actual output gets messed in with the logs. This allows callers
|
|
# to disambiguate actual output by specifying a unique prefix.
|
|
parser.add_argument('--prefix', default='',
|
|
help='Output mapped packages with this prefix')
|
|
parser.add_argument('--debug', dest='debug', action="store_true",
|
|
help="Enable debugging output")
|
|
|
|
args, extra = parser.parse_known_args()
|
|
|
|
# Logs have traditionally gone to stderr with this tool. Maintain
|
|
# compatibility
|
|
level = logging.DEBUG if args.debug else logging.INFO
|
|
logging.basicConfig(stream=sys.stderr, level=level)
|
|
|
|
if not args.element and not args.pkg_map:
|
|
log.error('Please specify an --element argument.')
|
|
sys.exit(1)
|
|
|
|
if args.element and args.pkg_map:
|
|
log.error('Specify either --element or --pkg-map')
|
|
sys.exit(1)
|
|
|
|
if not args.distro:
|
|
log.error('Please specify a --distro argument or set DISTRO_NAME.')
|
|
sys.exit(1)
|
|
|
|
if args.pkg_map:
|
|
# specifying the pkg-map by hand is just for manual testing
|
|
element = "<%s>" % args.pkg_map
|
|
map_file = args.pkg_map
|
|
else:
|
|
element = args.element
|
|
map_file = '/usr/share/pkg-map/%s' % element
|
|
|
|
log.info("Mapping for %s : %s" % (element, ' '.join(extra)))
|
|
|
|
if not os.path.exists(map_file):
|
|
if args.missing_ok:
|
|
log.info("No package map for %s, done" % element)
|
|
for name in extra:
|
|
print('%s%s' % (args.prefix, name))
|
|
sys.exit(0)
|
|
else:
|
|
log.error('Required pkg-map for %s element does not exist.'
|
|
% args.element)
|
|
sys.exit(2)
|
|
|
|
with open(map_file) as fd:
|
|
try:
|
|
package_names = json.loads(fd.read())
|
|
# log.debug(pprint.pformat(package_names))
|
|
except ValueError:
|
|
log.error('Unable to parse %s' % map_file)
|
|
raise
|
|
|
|
# Parse mapping data in this form using release/distro/family/default
|
|
# Most specific takes priority; order is
|
|
# - release
|
|
# - distro
|
|
# - family
|
|
# - default
|
|
# An empty package list can be provided.
|
|
#
|
|
# Example for Nova and Glance (using fictitious name for Fedora and SUSE
|
|
# and package mapping for SUSE family)
|
|
# {
|
|
# "release": {
|
|
# "fedora" : {
|
|
# "23" : {
|
|
# "nova_package": "openstack-compute-foo"
|
|
# }
|
|
# }
|
|
# }
|
|
# "distro": {
|
|
# "fedora": {
|
|
# "nova_package": "openstack-compute",
|
|
# "glance_package": "openstack-image"
|
|
# }
|
|
# },
|
|
# "family": {
|
|
# "redhat": {
|
|
# "nova_package": "openstack-nova",
|
|
# "glance_package": "openstack-glance"
|
|
# },
|
|
# "suse": {
|
|
# "nova_package": ""
|
|
# }
|
|
# },
|
|
# "default": {
|
|
# "nova_package": "nova",
|
|
# "glance_package": "glance"
|
|
# }
|
|
# }
|
|
name_map = package_names.get('default', {})
|
|
if 'family' in package_names:
|
|
family_map = package_names['family'].get(os_family(args.distro))
|
|
if family_map:
|
|
name_map.update(family_map)
|
|
if 'distro' in package_names:
|
|
distro_map = package_names['distro'].get(args.distro)
|
|
if distro_map:
|
|
name_map.update(distro_map)
|
|
if 'release' in package_names:
|
|
try:
|
|
# release is a sub-concept of distro
|
|
release_map = package_names['release'][args.distro][args.release]
|
|
name_map.update(release_map)
|
|
except KeyError:
|
|
pass
|
|
|
|
# log.debug(pprint.pformat(name_map))
|
|
|
|
for name in extra:
|
|
pkg_name = name_map.get(name)
|
|
if pkg_name:
|
|
log.debug("map %s -> %s" % (name, pkg_name))
|
|
print('%s%s' % (args.prefix, pkg_name))
|
|
elif name in name_map:
|
|
log.debug("map %s -> <skip>" % (name))
|
|
continue
|
|
else:
|
|
if args.missing_ok:
|
|
log.debug("pass -> %s" % (name))
|
|
print('%s%s' % (args.prefix, name))
|
|
else:
|
|
log.error("%s has no valid mapping for package %s" %
|
|
(element, name))
|
|
sys.exit(1)
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
|
|
# Tell emacs to use python-mode
|
|
# Local variables:
|
|
# mode: python
|
|
# End:
|