From 5693b52e5a8ce8a0893ce6e6f83f0d3275b69490 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Tue, 28 Jun 2022 10:08:35 +0200 Subject: [PATCH] Remove old lookup unit tests (#902) Remove old lookup unit tests 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: Alina Buzachis --- 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)