#!/usr/bin/python3 # Copyright 2023 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 copy import datetime import os import shutil import sys import yaml from io import StringIO from tripleo_common.image import kolla_builder from tripleoclient import utils def parse_opts(argv): parser = argparse.ArgumentParser( description='Tool to help to create the multi-rhel container image file') parser.add_argument( "--output-env-file", dest="output_env_file", metavar='', required=True, help="File to write environment file containing default " "ContainerImagePrepare value.", ) parser.add_argument( '--local-push-destination', dest='push_destination', action='store_true', default=False, help='Include a push_destination to trigger upload to a local ' 'registry.' ) parser.add_argument( '--enable-registry-login', dest='registry_login', action='store_true', default=False, help='Use this flag to enable the flag to have systems attempt ' 'to login to a remote registry prior to pulling their ' 'containers. This flag should be used when ' '--local-push-destination is *NOT* used and the target ' 'systems will have network connectivity to the remote ' 'registries. Do not use this for an overcloud that ' 'may not have network connectivity to a remote registry.' ) parser.add_argument( '--enable-multi-rhel', dest='multi_rhel', action='store_true', default=False, help='Use this flag to enable multi-rhel' ) parser.add_argument( '--excludes', dest='excludes', action='append', default=[], help='List of services to include/exclude' ) parser.add_argument( '--major-override', dest='major', action='store', default='{}', help='The override parameters for major release' ) parser.add_argument( '--minor-override', dest='minor', action='store', default='{}', help='The override parameters for minor release' ) parser.add_argument( '--role', dest='roles', action='append', default=[], help='List of roles' ) parser.add_argument( '--role-file', dest='rolefile', action='store', default='', help='role_data.yaml file' ) opts = parser.parse_args(argv[1:]) return opts def build_env_file(params): f = StringIO() f.write('# Generated with the following on %s\n#\n' % datetime.datetime.now().isoformat()) yaml.safe_dump({'parameter_defaults': params}, f, default_flow_style=False, sort_keys=False) return f.getvalue() parsed_args = parse_opts(sys.argv) auth_required = False cip = copy.deepcopy(kolla_builder.CONTAINER_IMAGE_PREPARE_PARAM) if parsed_args.push_destination: for entry in cip: entry['push_destination'] = True params = { 'ContainerImagePrepare': cip } if parsed_args.registry_login: if parsed_args.push_destination: print('[WARNING] --local-push-destination was used ' 'with --enable-registry-login. Please make ' 'sure you understand the use of these ' 'parameters together as they can cause ' 'deployment failures.') print('[NOTE] Make sure to update the paramter_defaults' ' with ContainerImageRegistryCredentials for the ' 'registries requiring authentication.') params['ContainerImageRegistryLogin'] = True if parsed_args.multi_rhel: cip_exc = copy.deepcopy(cip) cip_inc = copy.deepcopy(cip) # set default ceph image to 5 always, otherwise cephv6 images will be considered # as default from CONTAINER_IMAGE_PREPARE_PARAM cip_inc[0]['set']["ceph_image"] = "rhceph-5-rhel8" cip_exc[0]['set']["ceph_image"] = "rhceph-5-rhel8" params['ContainerImagePrepare'][0]['set']["ceph_image"] = "rhceph-5-rhel8" if parsed_args.major is not None: major = yaml.safe_load(parsed_args.major) if len(parsed_args.excludes) > 0: cip_exc[0]['excludes'] = copy.deepcopy(parsed_args.excludes) cip_inc[0]['includes'] = copy.deepcopy(parsed_args.excludes) if parsed_args.minor is not None: minor = yaml.safe_load(parsed_args.minor) for key in minor.keys(): if key in cip_inc[0]['set'].keys(): cip_inc[0]['set'][key] = minor[key] if parsed_args.major is not None: major = yaml.safe_load(parsed_args.major) for key in major.keys(): if key in cip_exc[0]['set'].keys(): cip_exc[0]['set'][key] = major[key] params_set = params['ContainerImagePrepare'][0]['set'] if key in params_set.keys(): params_set[key] = major[key] base_role = [cip_exc[0], cip_inc[0]] if parsed_args.rolefile != '': read_roles = [] if os.path.exists(parsed_args.rolefile): with open(parsed_args.rolefile) as file: roles_f = yaml.safe_load(file) for role in roles_f: read_roles.append(role['name']) else: print('[ERROR] {} role file does' ' not exits'.format(parsed_args.rolefile)) roles = read_roles else: roles = parsed_args.roles params['MultiRhelRoleContainerImagePrepare'] = base_role for role in roles: params[('{}ContainerImagePrepare').format(role)] = base_role env_data = build_env_file(params) if parsed_args.output_env_file: if os.path.exists(parsed_args.output_env_file): print("Output env file exists, " "moving it to backup.") shutil.move(parsed_args.output_env_file, parsed_args.output_env_file + ".backup") utils.safe_write(parsed_args.output_env_file, env_data)