From 9c117c66e8d42ced37af078fcd07d812c5fd33cb Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 28 Jun 2022 08:30:37 +0000 Subject: [PATCH] Remove old lookup unit tests (#902) (#905) [PR #902/5693b52e backport][stable-4] Remove old lookup unit tests This is a backport of PR #902 as merged into main (5693b52). SUMMARY Remove the unit tests for the aws_ssm and aws_secret lookup plugins. These unit tests weren't testing individual functions, they were testing the 'whole' module, and as such are brittle and break if the underlying implementation is updated (such as a refactor). Since we now have supported integration tests, remove the unit tests. ISSUE TYPE Feature Pull Request COMPONENT NAME plugins/lookup/aws_ssm.py plugins/lookup/aws_secret.py ADDITIONAL INFORMATION Reviewed-by: Mark Chappell --- tests/unit/plugins/lookup/__init__.py | 0 tests/unit/plugins/lookup/fixtures/avi.json | 104 ------ tests/unit/plugins/lookup/test_aws_secret.py | 288 ---------------- tests/unit/plugins/lookup/test_aws_ssm.py | 342 ------------------- 4 files changed, 734 deletions(-) delete mode 100644 tests/unit/plugins/lookup/__init__.py delete mode 100644 tests/unit/plugins/lookup/fixtures/avi.json delete mode 100644 tests/unit/plugins/lookup/test_aws_secret.py delete mode 100644 tests/unit/plugins/lookup/test_aws_ssm.py diff --git a/tests/unit/plugins/lookup/__init__.py b/tests/unit/plugins/lookup/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/unit/plugins/lookup/fixtures/avi.json b/tests/unit/plugins/lookup/fixtures/avi.json deleted file mode 100644 index ae89ca689c3..00000000000 --- a/tests/unit/plugins/lookup/fixtures/avi.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "mock_single_obj": { - "_last_modified": "", - "cloud_ref": "https://192.0.2.132/api/cloud/cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "dhcp_enabled": true, - "exclude_discovered_subnets": false, - "name": "PG-123", - "synced_from_se": true, - "tenant_ref": "https://192.0.2.132/api/tenant/admin", - "url": "https://192.0.2.132/api/network/dvportgroup-2084-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "uuid": "dvportgroup-2084-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "vcenter_dvs": true, - "vimgrnw_ref": "https://192.0.2.132/api/vimgrnwruntime/dvportgroup-2084-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "vrf_context_ref": "https://192.0.2.132/api/vrfcontext/vrfcontext-31f1b55f-319c-44eb-862f-69d79ffdf295" - }, - "mock_multiple_obj": { - "results": [ - { - "_last_modified": "", - "cloud_ref": "https://192.0.2.132/api/cloud/cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "dhcp_enabled": true, - "exclude_discovered_subnets": false, - "name": "J-PG-0682", - "synced_from_se": true, - "tenant_ref": "https://192.0.2.132/api/tenant/admin", - "url": "https://192.0.2.132/api/network/dvportgroup-2084-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "uuid": "dvportgroup-2084-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "vcenter_dvs": true, - "vimgrnw_ref": "https://192.0.2.132/api/vimgrnwruntime/dvportgroup-2084-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "vrf_context_ref": "https://192.0.2.132/api/vrfcontext/vrfcontext-31f1b55f-319c-44eb-862f-69d79ffdf295" - }, - { - "_last_modified": "", - "cloud_ref": "https://192.0.2.132/api/cloud/cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "dhcp_enabled": true, - "exclude_discovered_subnets": false, - "name": "J-PG-0231", - "synced_from_se": true, - "tenant_ref": "https://192.0.2.132/api/tenant/admin", - "url": "https://192.0.2.132/api/network/dvportgroup-1627-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "uuid": "dvportgroup-1627-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "vcenter_dvs": true, - "vimgrnw_ref": "https://192.0.2.132/api/vimgrnwruntime/dvportgroup-1627-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "vrf_context_ref": "https://192.0.2.132/api/vrfcontext/vrfcontext-31f1b55f-319c-44eb-862f-69d79ffdf295" - }, - { - "_last_modified": "", - "cloud_ref": "https://192.0.2.132/api/cloud/cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "dhcp_enabled": true, - "exclude_discovered_subnets": false, - "name": "J-PG-0535", - "synced_from_se": true, - "tenant_ref": "https://192.0.2.132/api/tenant/admin", - "url": "https://192.0.2.132/api/network/dvportgroup-1934-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "uuid": "dvportgroup-1934-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "vcenter_dvs": true, - "vimgrnw_ref": "https://192.0.2.132/api/vimgrnwruntime/dvportgroup-1934-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "vrf_context_ref": "https://192.0.2.132/api/vrfcontext/vrfcontext-31f1b55f-319c-44eb-862f-69d79ffdf295" - }, - { - "_last_modified": "", - "cloud_ref": "https://192.0.2.132/api/cloud/cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "dhcp_enabled": true, - "exclude_discovered_subnets": false, - "name": "J-PG-0094", - "synced_from_se": true, - "tenant_ref": "https://192.0.2.132/api/tenant/admin", - "url": "https://192.0.2.132/api/network/dvportgroup-1458-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "uuid": "dvportgroup-1458-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "vcenter_dvs": true, - "vimgrnw_ref": "https://192.0.2.132/api/vimgrnwruntime/dvportgroup-1458-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "vrf_context_ref": "https://192.0.2.132/api/vrfcontext/vrfcontext-31f1b55f-319c-44eb-862f-69d79ffdf295" - }, - { - "_last_modified": "", - "cloud_ref": "https://192.0.2.132/api/cloud/cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "dhcp_enabled": true, - "exclude_discovered_subnets": false, - "name": "J-PG-0437", - "synced_from_se": true, - "tenant_ref": "https://192.0.2.132/api/tenant/admin", - "url": "https://192.0.2.132/api/network/dvportgroup-1836-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "uuid": "dvportgroup-1836-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "vcenter_dvs": true, - "vimgrnw_ref": "https://192.0.2.132/api/vimgrnwruntime/dvportgroup-1836-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "vrf_context_ref": "https://192.0.2.132/api/vrfcontext/vrfcontext-31f1b55f-319c-44eb-862f-69d79ffdf295" - }, - { - "_last_modified": "", - "cloud_ref": "https://192.0.2.132/api/cloud/cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "dhcp_enabled": true, - "exclude_discovered_subnets": false, - "name": "J-PG-0673", - "synced_from_se": true, - "tenant_ref": "https://192.0.2.132/api/tenant/admin", - "url": "https://192.0.2.132/api/network/dvportgroup-2075-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "uuid": "dvportgroup-2075-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "vcenter_dvs": true, - "vimgrnw_ref": "https://192.0.2.132/api/vimgrnwruntime/dvportgroup-2075-cloud-4d063be1-99c2-44cf-8b28-977bd970524c", - "vrf_context_ref": "https://192.0.2.132/api/vrfcontext/vrfcontext-31f1b55f-319c-44eb-862f-69d79ffdf295" - } - ] - } -} diff --git a/tests/unit/plugins/lookup/test_aws_secret.py b/tests/unit/plugins/lookup/test_aws_secret.py deleted file mode 100644 index bed1b354b20..00000000000 --- a/tests/unit/plugins/lookup/test_aws_secret.py +++ /dev/null @@ -1,288 +0,0 @@ -# (c) 2019 Robert Williams -# -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . - -# Make coding more python3-ish -from __future__ import (absolute_import, division, print_function) - -__metaclass__ = type - -import pytest -import datetime -from copy import copy - -from ansible.errors import AnsibleError -from ansible.plugins.loader import lookup_loader - -from ansible_collections.amazon.aws.plugins.lookup import aws_secret - -try: - import boto3 - from botocore.exceptions import ClientError -except ImportError: - pytestmark = pytest.mark.skip("This test requires the boto3 and botocore Python libraries") - - -@pytest.fixture -def dummy_credentials(): - dummy_credentials = {} - dummy_credentials['boto_profile'] = None - dummy_credentials['aws_secret_key'] = "notasecret" - dummy_credentials['aws_access_key'] = "notakey" - dummy_credentials['aws_security_token'] = None - dummy_credentials['region'] = 'eu-west-1' - return dummy_credentials - - -simple_variable_success_response = { - 'Name': 'secret', - 'VersionId': 'cafe8168-e6ce-4e59-8830-5b143faf6c52', - 'SecretString': '{"secret":"simplesecret"}', - 'VersionStages': ['AWSCURRENT'], - 'ResponseMetadata': { - 'RequestId': '21099462-597c-490a-800f-8b7a41e5151c', - 'HTTPStatusCode': 200, - 'HTTPHeaders': { - 'date': 'Thu, 04 Apr 2019 10:43:12 GMT', - 'content-type': 'application/x-amz-json-1.1', - 'content-length': '252', - 'connection': 'keep-alive', - 'x-amzn-requestid': '21099462-597c-490a-800f-8b7a41e5151c' - }, - 'RetryAttempts': 0 - } -} - - -def test_lookup_variable(mocker, dummy_credentials): - dateutil_tz = pytest.importorskip("dateutil.tz") - lookup = lookup_loader.get('amazon.aws.aws_secret') - boto3_double = mocker.MagicMock() - boto3_double.Session.return_value.client.return_value.get_secret_value.return_value = copy( - simple_variable_success_response) - boto3_client_double = boto3_double.Session.return_value.client - - mocker.patch.object(boto3, 'session', boto3_double) - retval = lookup.run(["simple_variable"], None, **dummy_credentials) - assert (retval[0] == '{"secret":"simplesecret"}') - boto3_client_double.assert_called_with('secretsmanager', 'eu-west-1', aws_access_key_id='notakey', - aws_secret_access_key="notasecret", aws_session_token=None) - - -error_response_missing = {'Error': {'Code': 'ResourceNotFoundException', 'Message': 'Fake Not Found Error'}} -error_response_denied = {'Error': {'Code': 'AccessDeniedException', 'Message': 'Fake Denied Error'}} -operation_name = 'FakeOperation' - - -def test_on_missing_option(mocker, dummy_credentials): - boto3_double = mocker.MagicMock() - boto3_double.Session.return_value.client.return_value.get_secret_value.side_effect = ClientError(error_response_missing, operation_name) - - with pytest.raises(AnsibleError, match="ResourceNotFound"): - mocker.patch.object(boto3, 'session', boto3_double) - lookup_loader.get('amazon.aws.aws_secret').run(["missing_secret"], None, **dummy_credentials) - - mocker.patch.object(boto3, 'session', boto3_double) - args = copy(dummy_credentials) - args["on_missing"] = 'skip' - retval = lookup_loader.get('amazon.aws.aws_secret').run(["missing_secret"], None, **args) - assert(retval == []) - - mocker.patch.object(boto3, 'session', boto3_double) - args = copy(dummy_credentials) - args["on_missing"] = 'warn' - retval = lookup_loader.get('amazon.aws.aws_secret').run(["missing_secret"], None, **args) - assert(retval == []) - - -def test_on_denied_option(mocker, dummy_credentials): - boto3_double = mocker.MagicMock() - boto3_double.Session.return_value.client.return_value.get_secret_value.side_effect = ClientError(error_response_denied, operation_name) - - with pytest.raises(AnsibleError, match="AccessDenied"): - mocker.patch.object(boto3, 'session', boto3_double) - lookup_loader.get('amazon.aws.aws_secret').run(["denied_secret"], None, **dummy_credentials) - - mocker.patch.object(boto3, 'session', boto3_double) - args = copy(dummy_credentials) - args["on_denied"] = 'skip' - retval = lookup_loader.get('amazon.aws.aws_secret').run(["denied_secret"], None, **args) - assert(retval == []) - - mocker.patch.object(boto3, 'session', boto3_double) - args = copy(dummy_credentials) - args["on_denied"] = 'warn' - retval = lookup_loader.get('amazon.aws.aws_secret').run(["denied_secret"], None, **args) - assert(retval == []) - - -def test_nested_lookup_variable(mocker, dummy_credentials): - dateutil_tz = pytest.importorskip("dateutil.tz") - simple_variable_success_response = { - 'Name': 'simple_variable', - 'VersionId': 'cafe8168-e6ce-4e59-8830-5b143faf6c52', - 'SecretString': '{"key1": {"key2": {"key3": 1 } } }', - 'VersionStages': ['AWSCURRENT'], - 'CreatedDate': datetime.datetime(2019, 4, 4, 11, 41, 0, 878000, tzinfo=dateutil_tz.tzlocal()), - 'ResponseMetadata': { - 'RequestId': '21099462-597c-490a-800f-8b7a41e5151c', - 'HTTPStatusCode': 200, - 'HTTPHeaders': { - 'date': 'Thu, 04 Apr 2019 10:43:12 GMT', - 'content-type': 'application/x-amz-json-1.1', - 'content-length': '252', - 'connection': 'keep-alive', - 'x-amzn-requestid': '21099462-597c-490a-800f-8b7a41e5151c' - }, - 'RetryAttempts': 0 - } - } - lookup = lookup_loader.get('amazon.aws.aws_secret') - boto3_double = mocker.MagicMock() - boto3_double.Session.return_value.client.return_value.get_secret_value.return_value = simple_variable_success_response - boto3_client_double = boto3_double.Session.return_value.client - - mocker.patch.object(boto3, 'session', boto3_double) - dummy_credentials["nested"] = 'true' - retval = lookup.run(["simple_variable.key1.key2.key3"], None, **dummy_credentials) - assert(retval[0] == '1') - boto3_client_double.assert_called_with('secretsmanager', 'eu-west-1', aws_access_key_id='notakey', - aws_secret_access_key="notasecret", aws_session_token=None) - - -def test_path_lookup_variable(mocker, dummy_credentials, record_property): - lookup = aws_secret.LookupModule() - lookup._load_name = "aws_secret" - - path_list_secrets_success_response = { - 'SecretList': [ - { - 'Name': '/testpath/too', - }, - { - 'Name': '/testpath/won', - } - ], - 'ResponseMetadata': { - 'RequestId': '21099462-597c-490a-800f-8b7a41e5151c', - 'HTTPStatusCode': 200, - 'HTTPHeaders': { - 'date': 'Thu, 04 Apr 2019 10:43:12 GMT', - 'content-type': 'application/x-amz-json-1.1', - 'content-length': '252', - 'connection': 'keep-alive', - 'x-amzn-requestid': '21099462-597c-490a-800f-8b7a41e5151c' - }, - 'RetryAttempts': 0 - } - } - - boto3_double = mocker.MagicMock() - list_secrets_fn = boto3_double.Session.return_value.client.return_value.list_secrets - list_secrets_fn.return_value = path_list_secrets_success_response - - get_secret_value_fn = boto3_double.Session.return_value.client.return_value.get_secret_value - first_path = copy(simple_variable_success_response) - first_path['SecretString'] = 'simple_value_too' - second_path = copy(simple_variable_success_response) - second_path['SecretString'] = 'simple_value_won' - get_secret_value_fn.side_effect = [ - first_path, - second_path - ] - - boto3_client_double = boto3_double.Session.return_value.client - boto3_client_get_paginator_double = boto3_double.Session.return_value.client.return_value.get_paginator - boto3_paginate_double = boto3_client_get_paginator_double.return_value.paginate - boto3_paginate_double.return_value = [path_list_secrets_success_response] - - mocker.patch.object(boto3, 'session', boto3_double) - dummy_credentials["bypath"] = 'true' - dummy_credentials["boto_profile"] = 'test' - dummy_credentials["aws_profile"] = 'test' - retval = lookup.run(["/testpath"], {}, **dummy_credentials) - boto3_paginate_double.assert_called_once() - boto3_client_get_paginator_double.assert_called_once() - boto3_client_get_paginator_double.assert_called_once_with('list_secrets') - - record_property('KEY', retval) - assert (retval[0]["/testpath/won"] == "simple_value_won") - assert (retval[0]["/testpath/too"] == "simple_value_too") - boto3_client_double.assert_called_with('secretsmanager', 'eu-west-1', aws_access_key_id='notakey', - aws_secret_access_key="notasecret", aws_session_token=None) - boto3_paginate_double.assert_called_with(Filters=[{'Key': 'name', 'Values': ['/testpath']}]) - - -def test_path_lookup_variable_paginated(mocker, dummy_credentials, record_property): - lookup = aws_secret.LookupModule() - lookup._load_name = "aws_secret" - - def secret(value): - return {"Name": f"/testpath_paginated/{value}"} - - def get_secret_list(value): - return [secret(f"{value}{i}") for i in range(0, 6)] - path_list_secrets_paginated_success_response = { - 'SecretList': [ - item for pair in zip(get_secret_list("too"), get_secret_list("won")) for item in pair - ], - 'ResponseMetadata': { - 'RequestId': '21099462-597c-490a-800f-8b7a41e5151c', - 'HTTPStatusCode': 200, - 'HTTPHeaders': { - 'date': 'Thu, 04 Apr 2019 10:43:12 GMT', - 'content-type': 'application/x-amz-json-1.1', - 'content-length': '252', - 'connection': 'keep-alive', - 'x-amzn-requestid': '21099462-597c-490a-800f-8b7a41e5151c' - }, - 'RetryAttempts': 0 - } - } - boto3_double = mocker.MagicMock() - list_secrets_fn = boto3_double.Session.return_value.client.return_value.list_secrets - list_secrets_fn.return_value = path_list_secrets_paginated_success_response - get_secret_value_fn = boto3_double.Session.return_value.client.return_value.get_secret_value - - def secret_string(val): - path = copy(simple_variable_success_response) - path["SecretString"] = f"simple_value_{val}" - return path - - def _get_secret_list(value): - return [secret_string(f"{value}{i}") for i in range(0, 6)] - get_secret_value_fn.side_effect = [ - item for pair in zip(_get_secret_list("too"), _get_secret_list("won")) for item in pair - ] - boto3_client_double = boto3_double.Session.return_value.client - boto3_client_get_paginator_double = boto3_double.Session.return_value.client.return_value.get_paginator - boto3_paginate_double = boto3_client_get_paginator_double.return_value.paginate - boto3_paginate_double.return_value = [path_list_secrets_paginated_success_response] - mocker.patch.object(boto3, 'session', boto3_double) - dummy_credentials["bypath"] = 'true' - dummy_credentials["boto_profile"] = 'test' - dummy_credentials["aws_profile"] = 'test' - retval = lookup.run(["/testpath_paginated"], {}, **dummy_credentials) - boto3_paginate_double.assert_called_once() - boto3_client_get_paginator_double.assert_called_once() - boto3_client_get_paginator_double.assert_called_once_with('list_secrets') - record_property('KEY', retval) - assert (retval[0]["/testpath_paginated/won0"] == "simple_value_won0") - assert (retval[0]["/testpath_paginated/too0"] == "simple_value_too0") - assert (len(retval[0]) == 12) - boto3_client_double.assert_called_with('secretsmanager', 'eu-west-1', aws_access_key_id='notakey', - aws_secret_access_key="notasecret", aws_session_token=None) - boto3_paginate_double.assert_called_with(Filters=[{'Key': 'name', 'Values': ['/testpath_paginated']}]) diff --git a/tests/unit/plugins/lookup/test_aws_ssm.py b/tests/unit/plugins/lookup/test_aws_ssm.py deleted file mode 100644 index b224740a693..00000000000 --- a/tests/unit/plugins/lookup/test_aws_ssm.py +++ /dev/null @@ -1,342 +0,0 @@ -# -# (c) 2017 Michael De La Rue -# -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . - -# Make coding more python3-ish -from __future__ import (absolute_import, division, print_function) - -__metaclass__ = type - -import pytest -from unittest.mock import ANY -from copy import copy - -from ansible.errors import AnsibleError - -from ansible_collections.amazon.aws.plugins.lookup import aws_ssm - -try: - import boto3 - from botocore.exceptions import ClientError -except ImportError: - pytestmark = pytest.mark.skip("This test requires the boto3 and botocore Python libraries") - -simple_variable_success_response = { - 'Parameter': { - 'Name': 'simple_variable', - 'Type': 'String', - 'Value': 'simplevalue', - 'Version': 1 - }, - 'ResponseMetadata': { - 'RequestId': '12121212-3434-5656-7878-9a9a9a9a9a9a', - 'HTTPStatusCode': 200, - 'HTTPHeaders': { - 'x-amzn-requestid': '12121212-3434-5656-7878-9a9a9a9a9a9a', - 'content-type': 'application/x-amz-json-1.1', - 'content-length': '116', - 'date': 'Tue, 23 Jan 2018 11:04:27 GMT' - }, - 'RetryAttempts': 0 - } -} - -path_success_response = copy(simple_variable_success_response) -path_success_response['Parameters'] = [ - {'Name': '/testpath/too', 'Type': 'String', 'Value': 'simple_value_too', 'Version': 1}, - {'Name': '/testpath/won', 'Type': 'String', 'Value': 'simple_value_won', 'Version': 1} -] - -simple_response = copy(simple_variable_success_response) -simple_response['Parameter'] = { - 'Name': 'simple', - 'Type': 'String', - 'Value': 'simple_value', - 'Version': 1 -} - -simple_won_response = copy(simple_variable_success_response) -simple_won_response['Parameter'] = { - 'Name': '/testpath/won', - 'Type': 'String', - 'Value': 'simple_value_won', - 'Version': 1 -} - -dummy_credentials = {} -dummy_credentials['boto_profile'] = None -dummy_credentials['aws_secret_key'] = "notasecret" -dummy_credentials['aws_access_key'] = "notakey" -dummy_credentials['aws_security_token'] = None -dummy_credentials['region'] = 'eu-west-1' - - -def mock_get_parameter(**kwargs): - if kwargs.get('Name') == 'simple': - return simple_response - elif kwargs.get('Name') == '/testpath/won': - return simple_won_response - elif kwargs.get('Name') == 'missing_variable': - warn_response = {'Error': {'Code': 'ParameterNotFound', 'Message': 'Parameter not found'}} - operation_name = 'FakeOperation' - raise ClientError(warn_response, operation_name) - elif kwargs.get('Name') == 'denied_variable': - error_response = {'Error': {'Code': 'AccessDeniedException', 'Message': 'Fake Testing Error'}} - operation_name = 'FakeOperation' - raise ClientError(error_response, operation_name) - elif kwargs.get('Name') == 'notfound_variable': - error_response = {'Error': {'Code': 'ResourceNotFoundException', 'Message': 'Fake Testing Error'}} - operation_name = 'FakeOperation' - raise ClientError(error_response, operation_name) - else: - warn_response = {'Error': {'Code': 'ParameterNotFound', 'Message': 'Parameter not found'}} - operation_name = 'FakeOperation' - raise ClientError(warn_response, operation_name) - - -def test_lookup_variable(mocker): - lookup = aws_ssm.LookupModule() - lookup._load_name = "aws_ssm" - - boto3_double = mocker.MagicMock() - boto3_double.Session.return_value.client.return_value.get_parameter.return_value = simple_variable_success_response - boto3_client_double = boto3_double.Session.return_value.client - - mocker.patch.object(boto3, 'session', boto3_double) - retval = lookup.run(["simple_variable"], {}, **dummy_credentials) - assert(isinstance(retval, list)) - assert(len(retval) == 1) - assert(retval[0] == "simplevalue") - boto3_client_double.assert_called_with( - 'ssm', - region_name='eu-west-1', - aws_access_key_id='notakey', - aws_secret_access_key="notasecret", - aws_session_token=None, - endpoint_url=None, - config=ANY, - verify=None, - ) - - -def test_path_lookup_variable(mocker): - lookup = aws_ssm.LookupModule() - lookup._load_name = "aws_ssm" - - boto3_double = mocker.MagicMock() - get_paginator_fn = boto3_double.Session.return_value.client.return_value.get_paginator - paginator = get_paginator_fn.return_value - paginator.paginate.return_value.build_full_result.return_value = path_success_response - boto3_client_double = boto3_double.Session.return_value.client - - mocker.patch.object(boto3, 'session', boto3_double) - args = copy(dummy_credentials) - args["bypath"] = True - args["recursive"] = True - retval = lookup.run(["/testpath"], {}, **args) - assert(retval[0]["/testpath/won"] == "simple_value_won") - assert(retval[0]["/testpath/too"] == "simple_value_too") - boto3_client_double.assert_called_with( - 'ssm', - region_name='eu-west-1', - aws_access_key_id='notakey', - aws_secret_access_key="notasecret", - aws_session_token=None, - endpoint_url=None, - config=ANY, - verify=None, - ) - get_paginator_fn.assert_called_with('get_parameters_by_path') - paginator.paginate.assert_called_with(Path="/testpath", Recursive=True, WithDecryption=True) - paginator.paginate.return_value.build_full_result.assert_called_with() - - -def test_warn_on_missing_match_retvals_to_call_params_with_some_missing_variables(mocker): - """If we get a complex list of variables with some missing and some - not, and on_missing is warn, we still have to return a list which - matches with the original variable list. - - """ - lookup = aws_ssm.LookupModule() - lookup._load_name = "aws_ssm" - - boto3_double = mocker.MagicMock() - - boto3_double.Session.return_value.client.return_value.get_parameter.side_effect = mock_get_parameter - - mocker.patch.object(boto3, 'session', boto3_double) - args = copy(dummy_credentials) - args["on_missing"] = 'warn' - retval = lookup.run(["simple", "missing_variable", "/testpath/won", "simple"], {}, **args) - assert(isinstance(retval, list)) - assert(retval == ["simple_value", None, "simple_value_won", "simple_value"]) - - -def test_skip_on_missing_match_retvals_to_call_params_with_some_missing_variables(mocker): - """If we get a complex list of variables with some missing and some - not, and on_missing is skip, we still have to return a list which - matches with the original variable list. - - """ - lookup = aws_ssm.LookupModule() - lookup._load_name = "aws_ssm" - - boto3_double = mocker.MagicMock() - - boto3_double.Session.return_value.client.return_value.get_parameter.side_effect = mock_get_parameter - - mocker.patch.object(boto3, 'session', boto3_double) - args = copy(dummy_credentials) - args["on_missing"] = 'skip' - retval = lookup.run(["simple", "missing_variable", "/testpath/won", "simple"], {}, **args) - assert(isinstance(retval, list)) - assert(retval == ["simple_value", None, "simple_value_won", "simple_value"]) - - -def test_warn_notfound_resource(mocker): - lookup = aws_ssm.LookupModule() - lookup._load_name = "aws_ssm" - - boto3_double = mocker.MagicMock() - boto3_double.Session.return_value.client.return_value.get_parameter.side_effect = mock_get_parameter - - with pytest.raises(AnsibleError): - mocker.patch.object(boto3, 'session', boto3_double) - lookup.run(["notfound_variable"], {}, **dummy_credentials) - - -def test_on_missing_wrong_value(mocker): - lookup = aws_ssm.LookupModule() - lookup._load_name = "aws_ssm" - - boto3_double = mocker.MagicMock() - boto3_double.Session.return_value.client.return_value.get_parameter.side_effect = mock_get_parameter - - with pytest.raises(AnsibleError) as exc: - missing_credentials = copy(dummy_credentials) - missing_credentials['on_missing'] = "fake_value_on_missing" - mocker.patch.object(boto3, 'session', boto3_double) - lookup.run(["simple"], {}, **missing_credentials) - - assert exc.match('"on_missing" must be a string and one of "error", "warn" or "skip"') - - -def test_error_on_missing_variable(mocker): - lookup = aws_ssm.LookupModule() - lookup._load_name = "aws_ssm" - - boto3_double = mocker.MagicMock() - boto3_double.Session.return_value.client.return_value.get_parameter.side_effect = mock_get_parameter - - with pytest.raises(AnsibleError) as exc: - missing_credentials = copy(dummy_credentials) - missing_credentials['on_missing'] = "error" - mocker.patch.object(boto3, 'session', boto3_double) - lookup.run(["missing_variable"], {}, **missing_credentials) - - assert exc.match(r"Failed to find SSM parameter missing_variable \(ResourceNotFound\)") - - -def test_warn_on_missing_variable(mocker): - lookup = aws_ssm.LookupModule() - lookup._load_name = "aws_ssm" - - boto3_double = mocker.MagicMock() - boto3_double.Session.return_value.client.return_value.get_parameter.side_effect = mock_get_parameter - - missing_credentials = copy(dummy_credentials) - missing_credentials['on_missing'] = "warn" - mocker.patch.object(boto3, 'session', boto3_double) - retval = lookup.run(["missing_variable"], {}, **missing_credentials) - assert(isinstance(retval, list)) - assert(retval[0] is None) - - -def test_skip_on_missing_variable(mocker): - lookup = aws_ssm.LookupModule() - lookup._load_name = "aws_ssm" - - boto3_double = mocker.MagicMock() - boto3_double.Session.return_value.client.return_value.get_parameter.side_effect = mock_get_parameter - - missing_credentials = copy(dummy_credentials) - missing_credentials['on_missing'] = "skip" - mocker.patch.object(boto3, 'session', boto3_double) - retval = lookup.run(["missing_variable"], {}, **missing_credentials) - assert(isinstance(retval, list)) - assert(retval[0] is None) - - -def test_on_denied_wrong_value(mocker): - lookup = aws_ssm.LookupModule() - lookup._load_name = "aws_ssm" - - boto3_double = mocker.MagicMock() - boto3_double.Session.return_value.client.return_value.get_parameter.side_effect = mock_get_parameter - - with pytest.raises(AnsibleError) as exc: - denied_credentials = copy(dummy_credentials) - denied_credentials['on_denied'] = "fake_value_on_denied" - mocker.patch.object(boto3, 'session', boto3_double) - lookup.run(["simple"], {}, **denied_credentials) - - assert exc.match('"on_denied" must be a string and one of "error", "warn" or "skip"') - - -def test_error_on_denied_variable(mocker): - lookup = aws_ssm.LookupModule() - lookup._load_name = "aws_ssm" - - boto3_double = mocker.MagicMock() - boto3_double.Session.return_value.client.return_value.get_parameter.side_effect = mock_get_parameter - - with pytest.raises(AnsibleError) as exc: - denied_credentials = copy(dummy_credentials) - denied_credentials['on_denied'] = "error" - mocker.patch.object(boto3, 'session', boto3_double) - lookup.run(["denied_variable"], {}, **denied_credentials) - assert exc.match(r"Failed to access SSM parameter denied_variable \(AccessDenied\)") - - -def test_warn_on_denied_variable(mocker): - lookup = aws_ssm.LookupModule() - lookup._load_name = "aws_ssm" - - boto3_double = mocker.MagicMock() - boto3_double.Session.return_value.client.return_value.get_parameter.side_effect = mock_get_parameter - - denied_credentials = copy(dummy_credentials) - denied_credentials['on_denied'] = "warn" - mocker.patch.object(boto3, 'session', boto3_double) - retval = lookup.run(["denied_variable"], {}, **denied_credentials) - assert(isinstance(retval, list)) - assert(retval[0] is None) - - -def test_skip_on_denied_variable(mocker): - lookup = aws_ssm.LookupModule() - lookup._load_name = "aws_ssm" - - boto3_double = mocker.MagicMock() - boto3_double.Session.return_value.client.return_value.get_parameter.side_effect = mock_get_parameter - - denied_credentials = copy(dummy_credentials) - denied_credentials['on_denied'] = "skip" - mocker.patch.object(boto3, 'session', boto3_double) - retval = lookup.run(["denied_variable"], {}, **denied_credentials) - assert(isinstance(retval, list)) - assert(retval[0] is None)