From 5dbc6e3014c9f8e82cf72498ad5993f95357ab97 Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Tue, 23 Apr 2024 12:44:07 -0400 Subject: [PATCH] config, integrate dynamic galaxy servers --- lib/ansible/cli/config.py | 20 ++++++++++- lib/ansible/cli/galaxy.py | 57 ++----------------------------- lib/ansible/config/manager.py | 64 ++++++++++++++++++++++++++++++++--- 3 files changed, 80 insertions(+), 61 deletions(-) diff --git a/lib/ansible/cli/config.py b/lib/ansible/cli/config.py index 995649c3b12..300f03d3f47 100755 --- a/lib/ansible/cli/config.py +++ b/lib/ansible/cli/config.py @@ -149,6 +149,10 @@ class ConfigCLI(CLI): super(ConfigCLI, self).run() + # initialize galaxy server options + self._galaxy_servers = [s for s in C.GALAXY_SERVER_LIST or [] if s] # clean list + C.config.load_galaxy_server_defs(self._galaxy_servers, C.GALAXY_SERVER_TIMEOUT) + if context.CLIARGS['config_file']: self.config_file = unfrackpath(context.CLIARGS['config_file'], follow=False) b_config = to_bytes(self.config_file) @@ -267,6 +271,10 @@ class ConfigCLI(CLI): # this dumps main/common configs config_entries = self.config.get_configuration_definitions(ignore_private=True) + # for base and all, we include galaxy servers + for server in self._galaxy_servers: + config_entries.update(C.config.get_plugin_options('galaxy_server', server)) + if context.CLIARGS['type'] != 'base': config_entries['PLUGINS'] = {} @@ -476,11 +484,21 @@ class ConfigCLI(CLI): return entries def _get_global_configs(self): - config = self.config.get_configuration_definitions(ignore_private=True).copy() + + # Add base + config = self.config.get_configuration_definitions(ignore_private=True) + # convert to settings for setting in config.keys(): v, o = C.config.get_config_value_and_origin(setting, cfile=self.config_file, variables=get_constants()) config[setting] = Setting(setting, v, o, None) + # Add galaxy, which is dynamic + for server in self._galaxy_servers: + s_config= C.config.get_plugin_options('galaxy_server', server) + for setting in s_config.keys(): + v, o = C.config.get_config_value_and_origin(setting, plugin_type='galaxy_server', plugin_name=server, cfile=self.config_file, variables=get_constants()) + config[setting] = Setting(setting, v, o, None) + return self._render_settings(config) def _get_plugin_configs(self, ptype, plugins): diff --git a/lib/ansible/cli/galaxy.py b/lib/ansible/cli/galaxy.py index 805bd650372..2e48615c3b0 100755 --- a/lib/ansible/cli/galaxy.py +++ b/lib/ansible/cli/galaxy.py @@ -66,28 +66,6 @@ from ansible.utils.vars import load_extra_vars display = Display() urlparse = six.moves.urllib.parse.urlparse -# config definition by position: name, required, type -SERVER_DEF = [ - ('url', True, 'str'), - ('username', False, 'str'), - ('password', False, 'str'), - ('token', False, 'str'), - ('auth_url', False, 'str'), - ('api_version', False, 'int'), - ('validate_certs', False, 'bool'), - ('client_id', False, 'str'), - ('timeout', False, 'int'), -] - -# config definition fields -SERVER_ADDITIONAL = { - 'api_version': {'default': None, 'choices': [2, 3]}, - 'validate_certs': {'cli': [{'name': 'validate_certs'}]}, - 'timeout': {'default': C.GALAXY_SERVER_TIMEOUT, 'cli': [{'name': 'timeout'}]}, - 'token': {'default': None}, -} - - def with_collection_artifacts_manager(wrapped_method): """Inject an artifacts manager if not passed explicitly. @@ -618,45 +596,14 @@ class GalaxyCLI(CLI): self.galaxy = Galaxy() - def server_config_def(section, key, required, option_type): - config_def = { - 'description': 'The %s of the %s Galaxy server' % (key, section), - 'ini': [ - { - 'section': 'galaxy_server.%s' % section, - 'key': key, - } - ], - 'env': [ - {'name': 'ANSIBLE_GALAXY_SERVER_%s_%s' % (section.upper(), key.upper())}, - ], - 'required': required, - 'type': option_type, - } - if key in SERVER_ADDITIONAL: - config_def.update(SERVER_ADDITIONAL[key]) - - return config_def - - galaxy_options = {} - for optional_key in ['clear_response_cache', 'no_cache']: - if optional_key in context.CLIARGS: - galaxy_options[optional_key] = context.CLIARGS[optional_key] - - config_servers = [] + C.config.load_galaxy_server_defs(C.GALAXY_SERVER_LIST, C.GALAXY_SERVER_TIMEOUT) # Need to filter out empty strings or non truthy values as an empty server list env var is equal to ['']. server_list = [s for s in C.GALAXY_SERVER_LIST or [] if s] for server_priority, server_key in enumerate(server_list, start=1): - # Abuse the 'plugin config' by making 'galaxy_server' a type of plugin - # Config definitions are looked up dynamically based on the C.GALAXY_SERVER_LIST entry. We look up the - # section [galaxy_server.] for the values url, username, password, and token. - config_dict = dict((k, server_config_def(server_key, k, req, ensure_type)) for k, req, ensure_type in SERVER_DEF) - defs = AnsibleLoader(yaml_dump(config_dict)).get_single_data() - C.config.initialize_plugin_configuration_definitions('galaxy_server', server_key, defs) # resolve the config created options above with existing config and user options - server_options = C.config.get_plugin_options('galaxy_server', server_key) + server_options = C.config.get_plugin_options(plugin_type='galaxy_server', name=server_key) # auth_url is used to create the token, but not directly by GalaxyAPI, so # it doesn't need to be passed as kwarg to GalaxyApi, same for others we pop here diff --git a/lib/ansible/config/manager.py b/lib/ansible/config/manager.py index b8dada4ba4a..81e892bad3c 100644 --- a/lib/ansible/config/manager.py +++ b/lib/ansible/config/manager.py @@ -29,6 +29,26 @@ Setting = namedtuple('Setting', 'name value origin type') INTERNAL_DEFS = {'lookup': ('_terms',)} +GALAXY_SERVER_DEF = [ + ('url', True, 'str'), + ('username', False, 'str'), + ('password', False, 'str'), + ('token', False, 'str'), + ('auth_url', False, 'str'), + ('api_version', False, 'int'), + ('validate_certs', False, 'bool'), + ('client_id', False, 'str'), + ('timeout', False, 'int'), +] + +# config definition fields +GALAXY_SERVER_ADDITIONAL = { + 'api_version': {'default': None, 'choices': [2, 3]}, + 'validate_certs': {'cli': [{'name': 'validate_certs'}]}, + 'timeout': {'cli': [{'name': 'timeout'}]}, + 'token': {'default': None}, +} + def _get_entry(plugin_type, plugin_name, config): ''' construct entry for requested config ''' @@ -302,6 +322,41 @@ class ConfigManager(object): # ensure we always have config def entry self._base_defs['CONFIG_FILE'] = {'default': None, 'type': 'path'} + def load_galaxy_server_defs(self, server_list, default_timeout): + + def server_config_def(section, key, required, option_type): + config_def = { + 'description': 'The %s of the %s Galaxy server' % (key, section), + 'ini': [ + { + 'section': 'galaxy_server.%s' % section, + 'key': key, + } + ], + 'env': [ + {'name': 'ANSIBLE_GALAXY_SERVER_%s_%s' % (section.upper(), key.upper())}, + ], + 'required': required, + 'type': option_type, + } + if key in GALAXY_SERVER_ADDITIONAL: + config_def.update(GALAXY_SERVER_ADDITIONAL[key]) + # handle default timeout by inheriting from passed in default_timeout + if key == 'timeout' and 'default' not in config_def: + config_def['default'] = default_timeout + + return config_def + + for server_key in server_list: + if not server_key: + # To filter out empty strings or non truthy values as an empty server list env var is equal to ['']. + continue + + # Config definitions are looked up dynamically based on the C.GALAXY_SERVER_LIST entry. We look up the + # section [galaxy_server.] for the values url, username, password, and token. + defs = dict((k, server_config_def(server_key, k, req, value_type)) for k, req, value_type in GALAXY_SERVER_DEF) + self.initialize_plugin_configuration_definitions('galaxy_server', server_key, defs) + def template_default(self, value, variables): if isinstance(value, string_types) and (value.startswith('{{') and value.endswith('}}')) and variables is not None: # template default values if possible @@ -357,7 +412,7 @@ class ConfigManager(object): def get_plugin_options(self, plugin_type, name, keys=None, variables=None, direct=None): options = {} - defs = self.get_configuration_definitions(plugin_type, name) + defs = self.get_configuration_definitions(plugin_type=plugin_type, name=name) for option in defs: options[option] = self.get_config_value(option, plugin_type=plugin_type, plugin_name=name, keys=keys, variables=variables, direct=direct) @@ -366,7 +421,7 @@ class ConfigManager(object): def get_plugin_vars(self, plugin_type, name): pvars = [] - for pdef in self.get_configuration_definitions(plugin_type, name).values(): + for pdef in self.get_configuration_definitions(plugin_type=plugin_type, name=name).values(): if 'vars' in pdef and pdef['vars']: for var_entry in pdef['vars']: pvars.append(var_entry['name']) @@ -375,7 +430,7 @@ class ConfigManager(object): def get_plugin_options_from_var(self, plugin_type, name, variable): options = [] - for option_name, pdef in self.get_configuration_definitions(plugin_type, name).items(): + for option_name, pdef in self.get_configuration_definitions(plugin_type=plugin_type, name=name).items(): if 'vars' in pdef and pdef['vars']: for var_entry in pdef['vars']: if variable == var_entry['name']: @@ -417,7 +472,6 @@ class ConfigManager(object): for cdef in list(ret.keys()): if cdef.startswith('_'): del ret[cdef] - return ret def _loop_entries(self, container, entry_list): @@ -472,7 +526,7 @@ class ConfigManager(object): origin = None origin_ftype = None - defs = self.get_configuration_definitions(plugin_type, plugin_name) + defs = self.get_configuration_definitions(plugin_type=plugin_type, name=plugin_name) if config in defs: aliases = defs[config].get('aliases', [])