From 5b4dc4ace2f1a78c0bde6e611e360ffb827dab06 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 27 Aug 2021 06:32:38 +0200 Subject: [PATCH] parse scw-cli config file for oauth_token (#3250) (#3276) If `api_token` is not set and config file exists, it will try to fetch the value from the activated profile and fallback on default. This should not break existing workflows. (cherry picked from commit cc458f7c376d59455bc4028c25d20a850cb7fd82) Co-authored-by: Nicolas Karolak --- .../fragments/3250-parse-scw-config.yml | 2 + plugins/inventory/scaleway.py | 41 ++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/3250-parse-scw-config.yml 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):