#!/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 pprint import sys def eprint(msg): sys.stderr.write(msg) sys.stderr.write("\n") 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.') parser.add_argument('--debug', dest='debug', action="store_true", help="Enable debugging output") args, extra = parser.parse_known_args() if args.debug: logging.basicConfig(level=logging.DEBUG) if not args.element and not args.pkg_map: eprint('Please specify an --element argument.') sys.exit(1) if args.element and args.pkg_map: eprint('Specify either --element or --pkg-map') sys.exit(1) if not args.distro: eprint('Please specify a --distro argument or set DISTRO_NAME.') sys.exit(1) if args.pkg_map: map_file = args.pkg_map else: map_file = '/usr/share/pkg-map/%s' % args.element logging.debug("Map file is %s" % map_file) if not os.path.exists(map_file): if os.environ.get('DIB_DEBUG_TRACE', '0') != '0': eprint('Map file for %s element does not exist.' % args.element) if args.missing_ok: for name in extra: print(name) sys.exit(0) sys.exit(2) with open(map_file) as fd: try: package_names = json.loads(fd.read()) logging.debug(pprint.pformat(package_names)) except ValueError: eprint('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 for name in extra: pkg_name = name_map.get(name) if pkg_name: print(pkg_name) elif name in name_map: continue else: err_msg = 'Missing package name for distro/element: %s/%s' eprint(err_msg % (args.distro, args.element)) if args.missing_ok: print(name) else: sys.exit(1) sys.exit(0) if __name__ == '__main__': main()