diff --git a/plugins/lookup/gcp_parameter_manager.py b/plugins/lookup/gcp_parameter_manager.py new file mode 100644 index 00000000..43cae101 --- /dev/null +++ b/plugins/lookup/gcp_parameter_manager.py @@ -0,0 +1,315 @@ +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = ''' + name: gcp_parameter_manager + author: Google Inc. (@googlecloudplatform) + + short_description: Get Parameters from Google Cloud as a Lookup plugin + description: + - retrieve parameter keys in parameter Manager for use in playbooks + - see https://cloud.google.com/iam/docs/service-account-creds for details on creating + credentials for Google Cloud and the format of such credentials + - once a parameter value is retreived, it is returned decoded. It is up to the developer + to maintain secrecy of this value once returned. + - if location option is defined, then it deals with the regional parameters of the + location + + options: + key: + description: + - the name of the parameter to look up in parameter Manager + type: str + required: True + aliases: + - name + - parameter + - parameter_id + project: + description: + - The name of the google cloud project + - defaults to OS env variable GCP_PROJECT if not present + type: str + location: + description: + - If provided, it defines the location of the regional parameter. + type: str + render_secret: + description: + - support for rendering secrets + - defaults to false if not present + type: bool + auth_kind: + description: + - the type of authentication to use with Google Cloud (i.e. serviceaccount or machineaccount) + - defaults to OS env variable GCP_AUTH_KIND if not present + type: str + version: + description: + - the version name of your parameter to retrieve + type: str + required: False + service_account_email: + description: + - email associated with the service account + - defaults to OS env variable GCP_SERVICE_ACCOUNT_EMAIL if not present + type: str + required: False + service_account_file: + description: + - JSON Credential file obtained from Google Cloud + - defaults to OS env variable GCP_SERVICE_ACCOUNT_FILE if not present + - see https://cloud.google.com/iam/docs/service-account-creds for details + type: str + required: False + service_account_info: + description: + - JSON Object representing the contents of a service_account_file obtained from Google Cloud + - defaults to OS env variable GCP_SERVICE_ACCOUNT_INFO if not present + type: dict + required: False + access_token: + description: + - support for GCP Access Token + - defaults to OS env variable GCP_ACCESS_TOKEN if not present + type: str + required: False + on_error: + description: + - how to handle errors + - strict means raise an exception + - warn means warn, and return none + - ignore means just return none + type: str + required: False + choices: + - 'strict' + - 'warn' + - 'ignore' + default: 'strict' + scopes: + description: + - Authenticaiton scopes for Google parameter Manager + type: list + elements: str + default: ["https://www.googleapis.com/auth/cloud-platform"] +''' + + +EXAMPLES = ''' +- name: Test parameter using env variables for credentials + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key='parameter_key', version='test_version') }}" + +- name: Test parameter using explicit credentials + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key='parameter_key', version='test_version', project='project', auth_kind='serviceaccount', + service_account_file='file.json') }}" + +- name: Test getting specific version of a parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key='parameter_key', version='test-version') }}" + +- name: Test getting latest version of a parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key='parameter_key') }}" + +- name: Test render specific version of a parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key='parameter_key', version='test-version', render_secret=True) }}" + +- name: Test render latest version of a parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key='parameter_key', render_secret=True) }}" + +- name: Test regional parameter using env variables for credentials + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key='parameter_key', location='us-central1', version='test_version') }}" + +- name: Test regional parameter using explicit credentials + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key='parameter_key', location='us-central1', version='test_version', project='project', + auth_kind='serviceaccount', service_account_file='file.json') }}" + +- name: Test getting specific version of a regional parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key='parameter_key', location='us-central1', version='test_version') }}" + +- name: Test getting latest version of a regional parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key='parameter_key', location='us-central1') }}" + +- name: Test render specific version of a regional parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key='parameter_key', location='us-central1', version='test_version', render_secret=True) }}" + +- name: Test render latest version of a regional parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key='parameter_key', location='us-central1', render_secret=True) }}" +''' + +RETURN = ''' + _raw: + description: the contents of the parameter requested (please use "no_log" to not expose this parameter) + type: list + elements: str +''' + + +################################################################################ +# Imports +################################################################################ + +import os +import base64 + +from ansible.plugins.lookup import LookupBase +from ansible.errors import AnsibleError +from ansible.utils.display import Display + +try: + import requests + HAS_REQUESTS = True +except ImportError: + HAS_REQUESTS = False + +try: + from ansible_collections.google.cloud.plugins.module_utils.gcp_utils import ( + GcpSession, + ) + HAS_GOOGLE_CLOUD_COLLECTION = True +except ImportError: + HAS_GOOGLE_CLOUD_COLLECTION = False + + +class GcpLookupException(Exception): + pass + + +class GcpMockModule(object): + def __init__(self, params): + self.params = params + + def fail_json(self, *args, **kwargs): + raise AnsibleError(kwargs["msg"]) + + def raise_for_status(self, response): + try: + response.raise_for_status() + except getattr(requests.exceptions, "RequestException"): + self.fail_json(msg="GCP returned error: %s" % response.json()) + + +class LookupModule(LookupBase): + def run(self, terms=None, variables=None, **kwargs): + self._display = Display() + if not HAS_GOOGLE_CLOUD_COLLECTION: + raise AnsibleError( + """gcp_parameter lookup needs a supported version of the google.cloud + collection installed. Use `ansible-galaxy collection install google.cloud` + to install it""" + ) + self.set_options(var_options=variables, direct=kwargs) + params = { + "key": self.get_option("key"), + "location": self.get_option("location"), + "version": self.get_option("version"), + "access_token": self.get_option("access_token"), + "scopes": self.get_option("scopes"), + "render_secret": self.get_option("render_secret"), + "on_error": self.get_option("on_error") + } + + params['name'] = params['key'] + + # support GCP_* env variables for some parameters + for param in ["project", "auth_kind", "service_account_file", "service_account_info", "service_account_email", "access_token"]: + params[param] = self.fallback_from_env(param) + + self._display.vvv(msg=f"Module Parameters: {params}") + fake_module = GcpMockModule(params) + result = self.get_parameter(fake_module) + return [base64.b64decode(result)] + + def fallback_from_env(self, arg): + if self.get_option(arg): + return self.get_option(arg) + else: + env_name = f"GCP_{arg.upper()}" + if env_name in os.environ: + self.set_option(arg, os.environ[env_name]) + return self.get_option(arg) + + def raise_error(self, module, msg): + if module.params.get('on_error') == 'strict': + raise GcpLookupException(msg) + elif module.params.get('on_error') == 'warn': + self._display.warning(msg) + + return None + + def get_latest_version(self, module, auth): + url = (self.make_url_prefix(module) + "parameters/{name}/versions?orderBy=create_time desc&filter=disabled=false").format( + **module.params + ) + response = auth.get(url) + self._display.vvv(msg=f"List Version Response: {response.status_code} for {response.request.url}: {response.json()}") + if response.status_code != 200: + self.raise_error(module, f"unable to list versions of parameter {response.status_code}") + version_list = response.json() + if "parameterVersions" in version_list and len(version_list["parameterVersions"]) > 0: + # Extract name from the first index + version_name = version_list["parameterVersions"][0]["name"] + return version_name.split('/')[-1] + else: + self.raise_error(module, f"unable to list parameter versions via {response.request.url}: {response.json()}") + + def get_parameter(self, module): + auth = GcpSession(module, "parametermanager") + + if module.params.get('project') is None: + self.raise_error(module, "The project is required. Please specify the Google Cloud project to use.") + + if module.params.get('version') == 'latest' or module.params.get('version') is None: + module.params['version'] = self.get_latest_version(module, auth) + + if module.params.get('render_secret') is None: + module.params['render_secret'] = False + + # there was an error listing parameter versions + if module.params.get('version') is None: + return '' + + if module.params.get('render_secret') is not None: + url = (self.make_url_prefix(module) + "parameters/{name}/versions/{version}:render").format( + **module.params + ) + else: + url = (self.make_url_prefix(module) + "parameters/{name}/versions/{version}").format( + **module.params + ) + response = auth.get(url) + self._display.vvv(msg=f"Response: {response.status_code} for {response.request.url}: {response.json()}") + if response.status_code != 200: + self.raise_error(module, f"Failed to lookup parameter value via {response.request.url} {response.status_code}") + return '' + + response_json = response.json() + if module.params.get('render_secret') is not None: + if 'renderedPayload' not in response_json: + self.raise_error(module, "The parameter version is disabled or the response does not contain the 'renderedPayload' field.") + return '' + return response_json['renderedPayload'] + else: + if 'payload' not in response_json or 'data' not in response_json['payload']: + self.raise_error(module, "The parameter version is disabled or the response does not contain the 'data' field.") + return '' + return response_json['payload']['data'] + + def make_url_prefix(self, module): + if module.params.get('location') and module.params.get('location') != 'global': + return "https://parametermanager.{location}.rep.googleapis.com/v1/projects/{project}/locations/{location}/" + return "https://parametermanager.googleapis.com/v1/projects/{project}/locations/global/" diff --git a/plugins/modules/gcp_parameter_manager.py b/plugins/modules/gcp_parameter_manager.py new file mode 100644 index 00000000..fbc07ae2 --- /dev/null +++ b/plugins/modules/gcp_parameter_manager.py @@ -0,0 +1,649 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt +# or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +################################################################################ +# Documentation +################################################################################ + + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ["preview"], 'supported_by': 'community'} + +DOCUMENTATION = ''' +--- +module: gcp_parameter_manager +description: +- Access and Update Google Cloud Parameter Manager objects +- Create new parameters. +- Create new parameters with format. +- Create new parameters with labels. +- Create new parameters with format and labels. +- Add/Remove parameter version. +- Remove parameter. +short_description: Access and Update Google Cloud Parameter Manager objects +author: Google Inc. (@googlecloudplatform) +requirements: +- python >= 3.7 +- requests >= 2.32.3 +- google-auth >= 2.39.0 +options: + project: + description: + - The Google Cloud Platform project to use. Defaults to OS env variable + GCP_PROJECT if not present + type: str + auth_kind: + description: + - The type of credential used. + type: str + required: true + choices: + - application + - machineaccount + - serviceaccount + - accesstoken + service_account_contents: + description: + - The contents of a Service Account JSON file, either in a dictionary or as a + JSON string that represents it. + type: jsonarg + service_account_file: + description: + - The path of a Service Account JSON file if serviceaccount is selected as type. + type: path + service_account_email: + description: + - An optional service account email address if machineaccount is selected and + the user does not wish to use the default email. + type: str + access_token: + description: + - An OAuth2 access token if credential type is accesstoken. + type: str + scopes: + description: + - Array of scopes to be used + type: list + elements: str + env_type: + description: + - Specifies which Ansible environment you're running this module within. + - This should not be set unless you know what you're doing. + - This only alters the User Agent string for any API requests. + type: str + name: + description: + - Name of the parameter to be used + type: str + required: true + aliases: + - key + - parameter + - parameter_id + format: + description: + - Format of the parameter to be used. + type: str + default: UNFORMATTED + choices: + - UNFORMATTED + - JSON + - YAML + location: + description: + - Location of the parameter to be used + type: str + default: global + version: + description: + - Name of the parameter to be used + type: str + required: false + aliases: + - version_id + - parameter_version_id + value: + description: + - The parameter value that the parameter should have + - this will be set upon create + - If the parameter value is not this, a new version will be added with this value + type: str + state: + description: + - whether the parameter should exist + default: present + choices: + - absent + - present + type: str + return_value: + description: + - if true, the value of the parameter will be returned unencrypted to Ansible + - if false, no value will be returned or decrypted + type: bool + default: true + labels: + description: + - A set of key-value pairs to assign as labels to a parameter + - only used in creation + - Note that the "value" piece of a label must contain only readable chars + type: dict + default: {} +''' + +EXAMPLES = ''' +- name: Create a new parameter + google.cloud.gcp_parameter_manager: + name: parameter_key + state: present + auth_kind: serviceaccount + service_account_file: service_account_creds.json + +- name: Create a new parameter with version + google.cloud.gcp_parameter_manager: + name: parameter_key + version: version_key + value: super_parameter + state: present + auth_kind: serviceaccount + service_account_file: service_account_creds.json + +- name: Create a new structured parameter + google.cloud.gcp_parameter_manager: + name: parameter_key + version: version_key + format: JSON + value: '{"key":"value"}' + state: present + auth_kind: serviceaccount + service_account_file: service_account_creds.json + +- name: Create a parameter with labels + google.cloud.gcp_parameter_manager: + name: parameter_key + version: version_key + value: super_parameter + state: present + auth_kind: serviceaccount + service_account_file: service_account_creds.json + labels: + key_name: "ansible_rox" + +- name: Create a structured parameter with labels + google.cloud.gcp_parameter_manager: + name: parameter_key + version: version_key + format: JSON + value: '{"key":"value"}' + state: present + auth_kind: serviceaccount + service_account_file: service_account_creds.json + labels: + key_name: "ansible_rox" + +- name: Ensure the parameter exists, fail otherwise and return the value + google.cloud.gcp_parameter_manager: + name: parameter_key + state: present + +- name: Ensure parameter exists but don't return the value + google.cloud.gcp_parameter_manager: + name: parameter_key + state: present + return_value: false + +- name: Add a new version of a parameter + google.cloud.gcp_parameter_manager: + name: parameter_key + version: version_key + value: updated super parameter + state: present + +- name: Delete version 1 of a parameter (but not the parameter itself) + google.cloud.gcp_parameter_manager: + name: parameter_key + version: version_key + state: absent + +- name: Delete parameter + google.cloud.gcp_parameter_manager: + name: parameter_key + state: absent + +- name: Create a new regional parameter + google.cloud.gcp_parameter_manager: + name: parameter_key + state: present + auth_kind: serviceaccount + service_account_file: service_account_creds.json + +- name: Create a new regional parameter with version + google.cloud.gcp_parameter_manager: + name: parameter_key + version: version_key + value: super_parameter + state: present + auth_kind: serviceaccount + service_account_file: service_account_creds.json + +- name: Create a new structured regional parameter + google.cloud.gcp_parameter_manager: + name: parameter_key + version: version_key + format: JSON + value: '{"key":"value"}' + state: present + auth_kind: serviceaccount + service_account_file: service_account_creds.json + +- name: Create a regional parameter with labels + google.cloud.gcp_parameter_manager: + name: parameter_key + version: version_key + value: super_parameter + state: present + auth_kind: serviceaccount + service_account_file: service_account_creds.json + labels: + key_name: "ansible_rox" + +- name: Create a structured regional parameter with labels + google.cloud.gcp_parameter_manager: + name: parameter_key + version: version_key + format: JSON + value: '{"key":"value"}' + state: present + auth_kind: serviceaccount + service_account_file: service_account_creds.json + labels: + key_name: "ansible_rox" + +- name: Ensure the regional parameter exists, fail otherwise and return the value + google.cloud.gcp_parameter_manager: + name: parameter_key + state: present + +- name: Ensure regional parameter exists but don't return the value + google.cloud.gcp_parameter_manager: + name: parameter_key + state: present + return_value: false + +- name: Add a new version of a regional parameter + google.cloud.gcp_parameter_manager: + name: parameter_key + version: version_key + value: updated super parameter + state: present + +- name: Delete version 1 of a regional parameter (but not the regional parameter itself) + google.cloud.gcp_parameter_manager: + name: parameter_key + version: version_key + state: absent + +- name: Delete parameter + google.cloud.gcp_parameter_manager: + name: parameter_key + state: absent +''' + +RETURN = ''' +resources: + description: List of resources + returned: always + type: complex + contains: + name: + description: + - The name of the parameter + returned: success + type: str + location: + description: + - The location of the regional parameter + returned: success + type: str + version: + description: + - the version of the parameter returned + returned: success + type: str + url: + description: + - the Google Cloud URL used to make the request + returned: success + type: str + status_code: + description: + - the HTTP status code of the response to Google Cloud + returned: success + type: str + msg: + description: + - A message indicating what was done (or not done) + returned: success, failure + type: str + value: + description: + - The decrypted parameter data value, please use care with this + returned: success + type: str + payload: + description: + - The base 64 parameter payload + returned: success + type: dict +''' + + +################################################################################ +# Imports +################################################################################ + +from ansible_collections.google.cloud.plugins.module_utils.gcp_utils import ( + navigate_hash, + GcpSession, + GcpModule +) + +# for decoding and validating parameters +import json +import base64 + + +def get_auth(module): + return GcpSession(module, 'parameter-manager') + + +def make_url_prefix(module): + if module.params.get('location') is not None and module.params.get('location') != 'global': + return "https://parametermanager.{location}.rep.googleapis.com/v1/projects/{project}/locations/{location}/" + return "https://parametermanager.googleapis.com/v1/projects/{project}/locations/global/" + + +def self_parameter_link(module): + return (make_url_prefix(module) + "parameters/{name}").format(**module.params) + + +def self_parameter_version_link(module): + return (make_url_prefix(module) + "parameters/{name}/versions/{version}").format(**module.params) + + +def self_parameter_list_link(module): + return (make_url_prefix(module) + "parameters").format(**module.params) + + +def self_parameter_version_list_link(module): + return (make_url_prefix(module) + "parameters/{name}/versions").format(**module.params) + + +def check_parameter_exist(module, allow_not_found=True): + auth = get_auth(module) + param_list = list_parameters(module) + if param_list is None: + return None + + link = self_parameter_link(module) + access_obj = return_if_object(module, auth.get(link), allow_not_found) + if access_obj is None: + return None + return access_obj + + +def check_parameter_version_exist(module, allow_not_found=True): + auth = get_auth(module) + version_list = list_parameter_versions(module) + if version_list is None: + return None + + link = self_parameter_version_link(module) + access_obj = return_if_object(module, auth.get(link), allow_not_found) + if access_obj is None: + return None + return access_obj + + +def create_parameter(module): + # build the payload + payload = dict() + if module.params.get('format'): + payload['format'] = module.params.get('format') + if module.params.get('labels'): + payload['labels'] = module.params.get('labels') + + url = (make_url_prefix(module) + "parameters?parameter_id={name}").format(**module.params) + auth = get_auth(module) + # validate create + return return_if_object(module, auth.post(url, payload), False) + + +def create_parameter_version(module): + # build the payload + b64_value = base64.b64encode(module.params.get('value').encode("utf-8")).decode("utf-8") + payload = { + u'payload': { + u'data': b64_value + } + } + auth = get_auth(module) + url = (make_url_prefix(module) + "parameters/{name}/versions?parameter_version_id={version}").format(**module.params) + # validate create + return return_if_object(module, auth.post(url, payload), False) + + +def list_parameters(module): + url = self_parameter_list_link(module) + auth = get_auth(module) + return return_if_object(module, auth.get(url), True) + + +def list_parameter_versions(module): + # filter by only enabled parameter version + url = self_parameter_version_list_link(module) + auth = get_auth(module) + return return_if_object(module, auth.get(url), True) + + +def delete_parameter(module): + auth = get_auth(module) + url = self_parameter_link(module) + return return_if_object(module, auth.delete(url), True) + + +def delete_parameter_version(module): + auth = get_auth(module) + url = self_parameter_version_link(module) + return return_if_object(module, auth.delete(url), True) + + +def return_if_object(module, response, allow_not_found=False): + # If not found, return nothing. + if allow_not_found and response.status_code == 404: + return None + + if response.status_code == 409: + module.params['info'] = "exists already" + return None + + # probably a code error + if response.status_code == 400: + module.fail_json(msg="unexpected REST failure: %s" % response.json()['error']) + + # If no content, return nothing. + if response.status_code == 204: + return None + + try: + module.raise_for_status(response) + result = response.json() + result['url'] = response.request.url + result['status_code'] = response.status_code + if "name" in result: + result['location'] = result['name'].split("/")[3] + result['name'] = result['name'].split("/")[5] + if len(result['name'].split("/")) == 8: + result['version'] = result['name'].split("/")[-1] + + # base64 decode the value + if "payload" in result and "data" in result['payload']: + result['value'] = base64.b64decode(result['payload']['data']).decode("utf-8") + + except getattr(json.decoder, 'JSONDecodeError', ValueError): + module.fail_json(msg="Invalid JSON response with error: %s" % response.text) + + if navigate_hash(result, ['error', 'errors']): + module.fail_json(msg=navigate_hash(result, ['error', 'errors'])) + + return result + + +def main(): + module = GcpModule( + argument_spec=dict( + state=dict(default='present', choices=['present', 'absent'], type='str'), + name=dict(required=True, type='str', aliases=['key', 'parameter', 'parameter_id']), + version=dict(required=False, type='str', aliases=['version_id', 'parameter_version_id']), + location=dict(required=False, type='str', default='global'), + value=dict(required=False, type='str'), + format=dict(required=False, type='str', default='UNFORMATTED', choices=['UNFORMATTED', 'JSON', 'YAML']), + return_value=dict(required=False, type='bool', default=True), + labels=dict(required=False, type='dict', default=dict()) + ) + ) + + try : + if module.params.get('scopes') is None: + module.params['scopes'] = ["https://www.googleapis.com/auth/cloud-platform"] + + if module.params.get('project') is None: + module.fail_json(msg="The project is required. Please specify the Google Cloud project to use.") + + state = module.params.get('state') + changed = False + fetch = check_parameter_exist(module, allow_not_found=True) + fetch_version = None + if fetch: + fetch_version = check_parameter_version_exist(module, allow_not_found=True) + + if state == 'present': + # if parameter not exist + if not fetch: + # doesn't exist, must create + if module.params.get('version') and module.params.get('value'): + # create a new parameter + fetch = create_parameter(module) + fetch = create_parameter_version(module) + changed = True + # specified present and verison is provided but value is not provided + elif module.params.get('version') and module.params.get('value') is None: + module.fail_json( + msg="parameter '{name}' not present in '{project}' and no value for the parameter version is provided".format(**module.params) + ) + # specified present and verison is not provided + # that no parameter could be created without a version + elif module.params.get('value'): + module.fail_json(msg="parameter '{name}' not present in '{project}' and no version for the parameter is provided".format(**module.params)) + # specified present but no value + # that no parameter version could be created without a value to encrypt + else: + fetch = create_parameter(module) + changed = True + + elif not fetch_version: + # doesn't exist, must create + if module.params.get('version') and module.params.get('value'): + fetch = create_parameter_version(module) + changed = True + # specified present and verison is provided but value is not provided + elif module.params.get('version') and module.params.get('value') is None: + module.fail_json(msg="parameter '{name}' present in '{project}' and no value for the parameter version is provided".format(**module.params)) + # specified present and verison is not provided + # that no parameter could be created without a version + elif module.params.get('value'): + module.fail_json(msg="parameter '{name}' present in '{project}' and no version for the parameter is provided".format(**module.params)) + # specified present but no value + # that no parameter could be created without a value to encrypt + else: + module.fail_json( + msg="parameter '{name}' present in '{project}' and no value and version for the parameter is provided".format(**module.params) + ) + + else: + # parameter and parameter version both exist + # check if the value is the same + # if not, delete the version and create new one + # if the value is the same, do nothing + if "value" in fetch_version and module.params.get('value', '') is not None: + if fetch_version['value'] != module.params.get('value'): + fetch['msg'] = 'values not identical, but parameter version name is same' + # Delete existing version and create new one + fetch = delete_parameter_version(module) + fetch = create_parameter_version(module) + changed = True + else: + module.exit_json(msg="parameter '{name}' is already exist and value is the same".format(**module.params)) + elif module.params.get('value', '') is None: + module.fail_json(msg="parameter '{name}' present in '{project}' and no value for the parameter version is provided".format(**module.params)) + + else: + if fetch is None: + fetch = {} + module.exit_json(msg="parameter {name} is not exist".format(**module.params)) + + if fetch_version is None and module.params.get('version'): + fetch = {} + module.exit_json(msg="parameter version {version} is not exist".format(**module.params)) + + if module.params.get('version'): + version = delete_parameter_version(module) + if version is not None: + fetch = version + changed = True + else: + module.exit_json(msg="parameter version {version} is already deleted".format(**module.params)) + else: + versions = list_parameter_versions(module) + if versions is not None: + version = versions.get('parameterVersions', None) + if version is None: + param = delete_parameter(module) + if param is not None: + changed = True + fetch = param + else: + module.exit_json(msg="parameter {name} is already deleted".format(**module.params)) + else: + module.fail_json(msg="parameter {name} has nested version resources".format(**module.params)) + else: + module.exit_json(msg="parameter {name} is not exist".format(**module.params)) + + # # pop value data if return_value == false + if module.params.get('return_value') is False: + if "value" in fetch: + fetch.pop('value') + if "payload" in fetch: + fetch.pop('payload') + if "msg" in fetch: + fetch['msg'] = "{} | not returning parameter value since 'return_value' is set to false".format(fetch['msg']) + else: + fetch['msg'] = "not returning parameter value since 'return_value' is set to false" + + fetch['changed'] = changed + fetch['name'] = module.params.get('name') + except Exception as e: + module.fail_json(msg=f"An unexpected error occurred: {str(e)}") + + module.exit_json(**fetch) + + +if __name__ == "__main__": + main() diff --git a/tests/integration/targets/gcp_parameter_manager/aliases b/tests/integration/targets/gcp_parameter_manager/aliases new file mode 100644 index 00000000..0e4419e3 --- /dev/null +++ b/tests/integration/targets/gcp_parameter_manager/aliases @@ -0,0 +1 @@ +cloud/gcp \ No newline at end of file diff --git a/tests/integration/targets/gcp_parameter_manager/defaults/main.yml b/tests/integration/targets/gcp_parameter_manager/defaults/main.yml new file mode 100644 index 00000000..61fa8b04 --- /dev/null +++ b/tests/integration/targets/gcp_parameter_manager/defaults/main.yml @@ -0,0 +1,3 @@ +--- +resource_name: "{{ resource_prefix }}" +lookup_resource_name: "{{ resource_prefix }}_lookup" diff --git a/tests/integration/targets/gcp_parameter_manager/meta/main.yml b/tests/integration/targets/gcp_parameter_manager/meta/main.yml new file mode 100644 index 00000000..e69de29b diff --git a/tests/integration/targets/gcp_parameter_manager/tasks/main.yml b/tests/integration/targets/gcp_parameter_manager/tasks/main.yml new file mode 100644 index 00000000..5083cdee --- /dev/null +++ b/tests/integration/targets/gcp_parameter_manager/tasks/main.yml @@ -0,0 +1,9 @@ +--- +- name: Parameters tests + ansible.builtin.include_tasks: parameters.yml +- name: Regional Parameters tests + ansible.builtin.include_tasks: regionalparameters.yml +- name: Parameters lookup tests + ansible.builtin.include_tasks: parameterslookup.yml +- name: Regional Parameters lookup tests + ansible.builtin.include_tasks: regionalparameterslookup.yml diff --git a/tests/integration/targets/gcp_parameter_manager/tasks/parameters.yml b/tests/integration/targets/gcp_parameter_manager/tasks/parameters.yml new file mode 100644 index 00000000..38f7c13f --- /dev/null +++ b/tests/integration/targets/gcp_parameter_manager/tasks/parameters.yml @@ -0,0 +1,343 @@ +# Copyright 2025 Google 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. + +--- +# Pre-test setup +- name: Delete the test parameter if it exists + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent +# ---------------------------------------------------------- +- name: Create a parameter + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Create a parameter with version + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-1" + version: "test_version" + value: "ansible-test-parameter-value" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Create a parameter with labels + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-2" + version: "test_version" + value: "ansible-test-parameter-value" + labels: + key1: "val1" + key2: "val2" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Create a parameter with format + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-3" + version: "test_version" + format: JSON + value: "{\"key\":\"ansible-test-parameter-value\"}" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Create a parameter with format and labels + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-4" + version: "test_version" + value: "{\"key\":\"ansible-test-parameter-value\"}" + labels: + key1: "val1" + key2: "val2" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Create a parameter that already exists + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-1" + version: "test_version" + value: "ansible-test-parameter-value" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is false + ansible.builtin.assert: + that: + - result.changed == false +# ---------------------------------------------------------- +- name: Add a new version to a parameter + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + version: "test_version" + value: "ansible-test-parameter-value-updated" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Add a new version to a parameter with same version name but different value + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + version: "test_version" + value: "ansible-test-parameter-value-new-updated" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Add a new version to a parameter with same value but different version name + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + version: "test_version_1" + value: "ansible-test-parameter-value-updated" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Add a version that exists to a parameter + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + project: "{{ gcp_project }}" + version: "test_version" + value: "ansible-test-parameter-value-new-updated" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is false + ansible.builtin.assert: + that: + - result.changed == false +# ---------------------------------------------------------- +- name: Ensure the parameter version exists + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + version: "test_version" + value: "ansible-test-parameter-value-new-updated" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is false + ansible.builtin.assert: + that: + - result.changed == false +# ---------------------------------------------------------- +# CLEANUP +# ---------------------------------------------------------- +- name: Delete the parameter version + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + version: "test_version_1" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter version + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + version: "test_version" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter version + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-1" + version: "test_version" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-1" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter version with labels + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-2" + version: "test_version" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter with labels + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-2" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter version with format + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-3" + version: "test_version" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter with format + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-3" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter version with format and labels + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-4" + version: "test_version" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter with format and labels + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-4" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true diff --git a/tests/integration/targets/gcp_parameter_manager/tasks/parameterslookup.yml b/tests/integration/targets/gcp_parameter_manager/tasks/parameterslookup.yml new file mode 100644 index 00000000..d352a7e9 --- /dev/null +++ b/tests/integration/targets/gcp_parameter_manager/tasks/parameterslookup.yml @@ -0,0 +1,108 @@ +# Copyright 2025 Google 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. + +--- +# Pre-test setup +- name: Delete the test parameter if it exists + google.cloud.gcp_parameter_manager: + name: "{{ lookup_resource_name }}" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent +- name: Create a parameter + google.cloud.gcp_parameter_manager: + name: "{{ lookup_resource_name }}" + version: "test_version" + value: "ansible lookup test parameter value" + labels: + key1: "val1" + key2: "val2" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present +- name: Add a new version to a parameter + google.cloud.gcp_parameter_manager: + name: "{{ lookup_resource_name }}" + version: "test_version_1" + value: "ansible lookup test parameter value updated" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present +# ---------------------------------------------------------- +- name: Retrieve the latest parameter version of a parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key=lookup_resource_name, project=gcp_project, auth_kind=gcp_cred_kind, service_account_file=gcp_cred_file | default(omit)) }}" + register: result +- name: Assert parameter value + ansible.builtin.assert: + that: + - result.msg == "ansible lookup test parameter value updated" +# ---------------------------------------------------------- +- name: Retrieve the specified parameter version of a parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key=lookup_resource_name, version='test_version', project=gcp_project, auth_kind=gcp_cred_kind, service_account_file=gcp_cred_file | default(omit)) }}" + register: result +- name: Assert parameter value + ansible.builtin.assert: + that: + - result.msg == "ansible lookup test parameter value" +# --------------------------------------------------------- +- name: Render the latest parameter version of a parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key=lookup_resource_name, project=gcp_project, auth_kind=gcp_cred_kind, render_secret=True, service_account_file=gcp_cred_file | default(omit)) }}" + register: result +- name: Assert parameter value + ansible.builtin.assert: + that: + - result.msg == "ansible lookup test parameter value updated" +# ---------------------------------------------------------- +- name: Render the specified parameter version of a parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key=lookup_resource_name, version='test_version', project=gcp_project, auth_kind=gcp_cred_kind, render_secret=True, service_account_file=gcp_cred_file | default(omit)) }}" + register: result +- name: Assert parameter value + ansible.builtin.assert: + that: + - result.msg == "ansible lookup test parameter value" +# --------------------------------------------------------- +# Post-test teardown +# If errors happen, don't crash the playbook! +- name: Delete the test parameter version + google.cloud.gcp_parameter_manager: + name: "{{ lookup_resource_name }}" + project: "{{ gcp_project }}" + version: "test_version" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + ignore_errors: true +- name: Delete the test parameter version + google.cloud.gcp_parameter_manager: + name: "{{ lookup_resource_name }}" + project: "{{ gcp_project }}" + version: "test_version_1" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + ignore_errors: true +- name: Delete the test parameter + google.cloud.gcp_parameter_manager: + name: "{{ lookup_resource_name }}" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + ignore_errors: true diff --git a/tests/integration/targets/gcp_parameter_manager/tasks/regionalparameters.yml b/tests/integration/targets/gcp_parameter_manager/tasks/regionalparameters.yml new file mode 100644 index 00000000..45066850 --- /dev/null +++ b/tests/integration/targets/gcp_parameter_manager/tasks/regionalparameters.yml @@ -0,0 +1,366 @@ +# Copyright 2025 Google 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. + +--- +# Pre-test setup +- name: Delete the test parameter if it exists + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + project: "{{ gcp_project }}" + location: "us-central1" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent +# ---------------------------------------------------------- +- name: Create a parameter + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + project: "{{ gcp_project }}" + location: "us-central1" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Create a parameter with version + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-1" + version: "test_version" + value: "ansible-test-parameter-value" + location: "us-central1" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Create a parameter with lables + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-2" + location: "us-central1" + version: "test_version" + value: "ansible-test-parameter-value" + labels: + key1: "val1" + key2: "val2" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Create a parameter with format + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-3" + location: "us-central1" + version: "test_version" + format: JSON + value: "{\"key\":\"ansible-test-parameter-value\"}" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Create a parameter with format and lables + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-4" + version: "test_version" + location: "us-central1" + value: "{\"key\":\"ansible-test-parameter-value\"}" + labels: + key1: "val1" + key2: "val2" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Create a parameter that already exists + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-1" + version: "test_version" + location: "us-central1" + value: "ansible-test-parameter-value" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is false + ansible.builtin.assert: + that: + - result.changed == false +# ---------------------------------------------------------- +- name: Add a new version to a parameter + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + version: "test_version" + location: "us-central1" + value: "ansible-test-parameter-value-updated" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Add a new version to a parameter with same version name but different value + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + version: "test_version" + location: "us-central1" + value: "ansible-test-parameter-value-new-updated" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Add a new version to a parameter with same value but different version name + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + location: "us-central1" + version: "test_version_1" + value: "ansible-test-parameter-value-updated" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Add a version that exists to a parameter + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + location: "us-central1" + project: "{{ gcp_project }}" + version: "test_version" + value: "ansible-test-parameter-value-new-updated" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is false + ansible.builtin.assert: + that: + - result.changed == false +# ---------------------------------------------------------- +- name: Ensure the parameter version exists + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + location: "us-central1" + version: "test_version" + value: "ansible-test-parameter-value-new-updated" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present + register: result +- name: Assert changed is false + ansible.builtin.assert: + that: + - result.changed == false +# ---------------------------------------------------------- +# CLEANUP +# ---------------------------------------------------------- +- name: Delete the parameter version + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + location: "us-central1" + version: "test_version_1" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter version + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + location: "us-central1" + version: "test_version" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}" + location: "us-central1" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter version + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-1" + location: "us-central1" + version: "test_version" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-1" + location: "us-central1" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter version with labels + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-2" + location: "us-central1" + version: "test_version" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter with labels + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-2" + location: "us-central1" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter version with format + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-3" + location: "us-central1" + version: "test_version" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter with format + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-3" + location: "us-central1" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter version with format and labels + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-4" + location: "us-central1" + version: "test_version" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true +# ---------------------------------------------------------- +- name: Delete the parameter with format and labels + google.cloud.gcp_parameter_manager: + name: "{{ resource_name }}-4" + location: "us-central1" + project: "{{ gcp_project }}" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + register: result +- name: Assert changed is true + ansible.builtin.assert: + that: + - result.changed == true diff --git a/tests/integration/targets/gcp_parameter_manager/tasks/regionalparameterslookup.yml b/tests/integration/targets/gcp_parameter_manager/tasks/regionalparameterslookup.yml new file mode 100644 index 00000000..2cd3c745 --- /dev/null +++ b/tests/integration/targets/gcp_parameter_manager/tasks/regionalparameterslookup.yml @@ -0,0 +1,114 @@ +# Copyright 2025 Google 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. + +--- +# Pre-test setup +- name: Delete the test regional parameter if it exists + google.cloud.gcp_parameter_manager: + name: "{{ lookup_resource_name }}" + project: "{{ gcp_project }}" + location: "us-central1" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent +- name: Create a regional parameter + google.cloud.gcp_parameter_manager: + name: "{{ lookup_resource_name }}" + version: "test_version" + value: "ansible lookup test regional parameter value" + labels: + key1: "val1" + key2: "val2" + project: "{{ gcp_project }}" + location: "us-central1" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present +- name: Add a new version to a regional parameter + google.cloud.gcp_parameter_manager: + name: "{{ lookup_resource_name }}" + version: "test_version_1" + value: "ansible lookup test regional parameter value updated" + project: "{{ gcp_project }}" + location: "us-central1" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: present +# ---------------------------------------------------------- +- name: Retrieve the latest regional parameter version of a regional parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key=lookup_resource_name, project=gcp_project, location='us-central1', auth_kind=gcp_cred_kind, service_account_file=gcp_cred_file | default(omit)) }}" + register: result +- name: Assert regional parameter value + ansible.builtin.assert: + that: + - result.msg == "ansible lookup test regional parameter value updated" +# ---------------------------------------------------------- +- name: Retrieve the specified regional parameter version of a regional parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key=lookup_resource_name, version='test_version', location='us-central1', project=gcp_project, auth_kind=gcp_cred_kind, service_account_file=gcp_cred_file | default(omit)) }}" + register: result +- name: Assert regional parameter value + ansible.builtin.assert: + that: + - result.msg == "ansible lookup test regional parameter value" +# --------------------------------------------------------- +- name: Render the latest regional parameter version of a regional parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key=lookup_resource_name, project=gcp_project, location='us-central1', auth_kind=gcp_cred_kind, render_secret=True, service_account_file=gcp_cred_file | default(omit)) }}" + register: result +- name: Assert regional parameter value + ansible.builtin.assert: + that: + - result.msg == "ansible lookup test regional parameter value updated" +# ---------------------------------------------------------- +- name: Render the specified regional parameter version of a regional parameter + ansible.builtin.debug: + msg: "{{ lookup('google.cloud.gcp_parameter_manager', key=lookup_resource_name, version='test_version', location='us-central1', project=gcp_project, auth_kind=gcp_cred_kind, render_secret=True, service_account_file=gcp_cred_file | default(omit)) }}" + register: result +- name: Assert regional parameter value + ansible.builtin.assert: + that: + - result.msg == "ansible lookup test regional parameter value" +# --------------------------------------------------------- +# Post-test teardown +# If errors happen, don't crash the playbook! +- name: Delete the test regional parameter version + google.cloud.gcp_parameter_manager: + name: "{{ lookup_resource_name }}" + version: "test_version" + project: "{{ gcp_project }}" + location: "us-central1" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + ignore_errors: true +- name: Delete the test regional parameter version + google.cloud.gcp_parameter_manager: + name: "{{ lookup_resource_name }}" + version: "test_version_1" + project: "{{ gcp_project }}" + location: "us-central1" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + ignore_errors: true +- name: Delete the test regional parameter + google.cloud.gcp_parameter_manager: + name: "{{ lookup_resource_name }}" + project: "{{ gcp_project }}" + location: "us-central1" + auth_kind: "{{ gcp_cred_kind }}" + service_account_file: "{{ gcp_cred_file | default(omit) }}" + state: absent + ignore_errors: true