diff --git a/changelogs/fragments/3250-parse-scw-config.yml b/changelogs/fragments/3250-parse-scw-config.yml new file mode 100644 index 0000000000..8c96c55e47 --- /dev/null +++ b/changelogs/fragments/3250-parse-scw-config.yml @@ -0,0 +1,2 @@ +minor_changes: + - scaleway plugin inventory - parse scw-cli config file for ``oauth_token`` (https://github.com/ansible-collections/community.general/pull/3250). diff --git a/plugins/inventory/scaleway.py b/plugins/inventory/scaleway.py index 86140124c5..fa65eae321 100644 --- a/plugins/inventory/scaleway.py +++ b/plugins/inventory/scaleway.py @@ -13,6 +13,8 @@ DOCUMENTATION = r''' short_description: Scaleway inventory source description: - Get inventory hosts from Scaleway. + requirements: + - PyYAML options: plugin: description: Token that ensures this is a source file for the 'scaleway' plugin. @@ -30,9 +32,10 @@ DOCUMENTATION = r''' description: Filter results on a specific tag. type: list oauth_token: - required: True description: - Scaleway OAuth token. + - If not explicitly defined or in environment variables, it will try to lookup in the scaleway-cli configuration file + (C($SCW_CONFIG_PATH), C($XDG_CONFIG_HOME/scw/config.yaml), or C(~/.config/scw/config.yaml)). - More details on L(how to generate token, https://www.scaleway.com/en/docs/generate-api-keys/). env: # in order of precedence @@ -95,13 +98,22 @@ variables: ansible_user: "'admin'" ''' +import os import json +try: + import yaml +except ImportError as exc: + YAML_IMPORT_ERROR = exc +else: + YAML_IMPORT_ERROR = None + from ansible.errors import AnsibleError from ansible.plugins.inventory import BaseInventoryPlugin, Constructable from ansible_collections.community.general.plugins.module_utils.scaleway import SCALEWAY_LOCATION, parse_pagination_link from ansible.module_utils.urls import open_url from ansible.module_utils.common.text.converters import to_native, to_text +from ansible.module_utils.six import raise_from import ansible.module_utils.six.moves.urllib.parse as urllib_parse @@ -278,13 +290,38 @@ class InventoryModule(BaseInventoryPlugin, Constructable): # Composed variables self._set_composite_vars(self.get_option('variables'), host_infos, hostname, strict=False) + def get_oauth_token(self): + oauth_token = self.get_option('oauth_token') + + if 'SCW_CONFIG_PATH' in os.environ: + scw_config_path = os.getenv('SCW_CONFIG_PATH') + elif 'XDG_CONFIG_HOME' in os.environ: + scw_config_path = os.path.join(os.getenv('XDG_CONFIG_HOME'), 'scw', 'config.yaml') + else: + scw_config_path = os.path.join(os.path.expanduser('~'), '.config', 'scw', 'config.yaml') + + if not oauth_token and os.path.exists(scw_config_path): + with open(scw_config_path) as fh: + scw_config = yaml.safe_load(fh) + active_profile = scw_config.get('active_profile', 'default') + if active_profile == 'default': + oauth_token = scw_config.get('secret_key') + else: + oauth_token = scw_config['profiles'][active_profile].get('secret_key') + + return oauth_token + def parse(self, inventory, loader, path, cache=True): + if YAML_IMPORT_ERROR: + raise_from(AnsibleError('PyYAML is probably missing'), YAML_IMPORT_ERROR) super(InventoryModule, self).parse(inventory, loader, path) self._read_config_data(path=path) config_zones = self.get_option("regions") tags = self.get_option("tags") - token = self.get_option("oauth_token") + token = self.get_oauth_token() + if not token: + raise AnsibleError("'oauth_token' value is null, you must configure it either in inventory, envvars or scaleway-cli config.") hostname_preference = self.get_option("hostnames") for zone in self._get_zones(config_zones):