summaryrefslogtreecommitdiffstats
path: root/ansible_collections/amazon/aws/tests/unit/plugins
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-05 16:18:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-05 16:18:41 +0000
commitb643c52cf29ce5bbab738b43290af3556efa1ca9 (patch)
tree21d5c53d7a9b696627a255777cefdf6f78968824 /ansible_collections/amazon/aws/tests/unit/plugins
parentReleasing progress-linux version 9.5.1+dfsg-1~progress7.99u1. (diff)
downloadansible-b643c52cf29ce5bbab738b43290af3556efa1ca9.tar.xz
ansible-b643c52cf29ce5bbab738b43290af3556efa1ca9.zip
Merging upstream version 10.0.0+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/amazon/aws/tests/unit/plugins')
-rw-r--r--ansible_collections/amazon/aws/tests/unit/plugins/modules/test_lambda_event.py544
1 files changed, 544 insertions, 0 deletions
diff --git a/ansible_collections/amazon/aws/tests/unit/plugins/modules/test_lambda_event.py b/ansible_collections/amazon/aws/tests/unit/plugins/modules/test_lambda_event.py
new file mode 100644
index 000000000..c292329b4
--- /dev/null
+++ b/ansible_collections/amazon/aws/tests/unit/plugins/modules/test_lambda_event.py
@@ -0,0 +1,544 @@
+#
+# (c) 2024 Red Hat Inc.
+#
+# This file is part of Ansible
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from contextlib import nullcontext as does_not_raise
+from copy import deepcopy
+from unittest.mock import MagicMock
+from unittest.mock import patch
+
+import pytest
+
+from ansible_collections.amazon.aws.plugins.modules.lambda_event import get_qualifier
+from ansible_collections.amazon.aws.plugins.modules.lambda_event import lambda_event_stream
+from ansible_collections.amazon.aws.plugins.modules.lambda_event import set_default_values
+from ansible_collections.amazon.aws.plugins.modules.lambda_event import validate_params
+
+mock_get_qualifier = "ansible_collections.amazon.aws.plugins.modules.lambda_event.get_qualifier"
+mock_camel_dict_to_snake_dict = "ansible_collections.amazon.aws.plugins.modules.lambda_event.camel_dict_to_snake_dict"
+
+
+@pytest.fixture
+def ansible_aws_module():
+ module = MagicMock()
+ module.check_mode = False
+ module.params = {
+ "state": "present",
+ "lambda_function_arn": None,
+ "event_source": "sqs",
+ "source_params": {
+ "source_arn": "arn:aws:sqs:us-east-2:123456789012:ansible-test-sqs",
+ "batch_size": 200,
+ "starting_position": "LATEST",
+ },
+ "alias": None,
+ "version": 0,
+ }
+ module.exit_json = MagicMock()
+ module.exit_json.side_effect = SystemExit(1)
+ module.fail_json_aws = MagicMock()
+ module.fail_json_aws.side_effect = SystemExit(2)
+ module.fail_json = MagicMock()
+ module.fail_json.side_effect = SystemExit(2)
+ module.client = MagicMock()
+ module.client.return_value = MagicMock()
+ module.boolean = MagicMock()
+ module.boolean.side_effect = lambda x: x.lower() in ["true", "1", "t", "y", "yes"]
+ return module
+
+
+@pytest.mark.parametrize(
+ "module_params,expected",
+ [
+ ({"version": 1}, "1"),
+ ({"alias": "ansible-test"}, "ansible-test"),
+ ({"version": 1, "alias": "ansible-test"}, "1"),
+ ({}, None),
+ ],
+)
+def test_get_qualifier(ansible_aws_module, module_params, expected):
+ ansible_aws_module.params.update(module_params)
+ assert get_qualifier(ansible_aws_module) == expected
+
+
+@pytest.mark.parametrize(
+ "function_name,error_msg",
+ [
+ (
+ "invalid+function+name",
+ "Function name invalid+function+name is invalid. Names must contain only alphanumeric characters and hyphens.",
+ ),
+ (
+ "this_invalid_function_name_has_more_than_64_character_limit_this_is_not_allowed_by_the_module",
+ 'Function name "this_invalid_function_name_has_more_than_64_character_limit_this_is_not_allowed_by_the_module" exceeds 64 character limit',
+ ),
+ (
+ "arn:aws:lambda:us-east-2:123456789012:function:ansible-test-ansible-test-ansible-test-sqs-lambda-function:"
+ "ansible-test-ansible-test-ansible-test-sqs-lambda-function-alias",
+ 'ARN "arn:aws:lambda:us-east-2:123456789012:function:ansible-test-ansible-test-ansible-test-sqs-lambda-function:'
+ 'ansible-test-ansible-test-ansible-test-sqs-lambda-function-alias" exceeds 140 character limit',
+ ),
+ ],
+)
+def test_validate_params_function_name_errors(ansible_aws_module, function_name, error_msg):
+ ansible_aws_module.params.update({"lambda_function_arn": function_name})
+ client = MagicMock()
+ client.get_function = MagicMock()
+ client.get_function.return_value = {}
+ with pytest.raises(SystemExit):
+ validate_params(ansible_aws_module, client)
+
+ ansible_aws_module.fail_json.assert_called_once_with(msg=error_msg)
+
+
+@pytest.mark.parametrize(
+ "qualifier",
+ [None, "ansible-test"],
+)
+@patch(mock_get_qualifier)
+def test_validate_params_with_function_arn(m_get_qualifier, ansible_aws_module, qualifier):
+ function_name = "arn:aws:lambda:us-east-2:123456789012:function:sqs_consumer"
+ ansible_aws_module.params.update({"lambda_function_arn": function_name})
+ m_get_qualifier.return_value = qualifier
+
+ client = MagicMock()
+ client.get_function = MagicMock()
+ client.get_function.return_value = {}
+
+ params = deepcopy(ansible_aws_module.params)
+ params["lambda_function_arn"] = f"{function_name}:{qualifier}" if qualifier else function_name
+
+ validate_params(ansible_aws_module, client)
+ assert params == ansible_aws_module.params
+ m_get_qualifier.assert_called_once()
+
+
+@pytest.mark.parametrize(
+ "qualifier",
+ [None, "ansible-test"],
+)
+@patch(mock_get_qualifier)
+def test_validate_params_with_function_name(m_get_qualifier, ansible_aws_module, qualifier):
+ function_arn = "arn:aws:lambda:us-east-2:123456789012:function:sqs_consumer"
+ function_name = "sqs_consumer"
+ ansible_aws_module.params.update({"lambda_function_arn": function_name})
+ m_get_qualifier.return_value = qualifier
+
+ client = MagicMock()
+ client.get_function = MagicMock()
+ client.get_function.return_value = {
+ "Configuration": {"FunctionArn": function_arn},
+ }
+
+ params = deepcopy(ansible_aws_module.params)
+ params["lambda_function_arn"] = function_arn
+
+ validate_params(ansible_aws_module, client)
+
+ assert params == ansible_aws_module.params
+ m_get_qualifier.assert_called_once()
+ api_params = {"FunctionName": function_name}
+ if qualifier:
+ api_params.update({"Qualifier": qualifier})
+ client.get_function.assert_called_once_with(**api_params)
+
+
+EventSourceMappings = [
+ {
+ "BatchSize": 10,
+ "EventSourceArn": "arn:aws:sqs:us-east-2:123456789012:sqs_consumer",
+ "FunctionArn": "arn:aws:lambda:us-east-2:123456789012:function:sqs_consumer",
+ "LastModified": "2024-02-08T15:24:57.014000+01:00",
+ "MaximumBatchingWindowInSeconds": 0,
+ "State": "Enabled",
+ "StateTransitionReason": "USER_INITIATED",
+ "UUID": "3ab96d4c-b0c4-4885-87d0-f58cb9c0a4cc",
+ }
+]
+
+
+@pytest.mark.parametrize(
+ "check_mode",
+ [True, False],
+)
+@pytest.mark.parametrize(
+ "existing_event_source",
+ [True, False],
+)
+@patch(mock_camel_dict_to_snake_dict)
+def test_lambda_event_stream_with_state_absent(
+ mock_camel_dict_to_snake_dict, ansible_aws_module, check_mode, existing_event_source
+):
+ function_name = "sqs_consumer"
+ ansible_aws_module.params.update({"lambda_function_arn": function_name, "state": "absent"})
+ ansible_aws_module.check_mode = check_mode
+
+ client = MagicMock()
+ client.list_event_source_mappings = MagicMock()
+
+ client.list_event_source_mappings.return_value = {
+ "EventSourceMappings": EventSourceMappings if existing_event_source else []
+ }
+ client.delete_event_source_mapping = MagicMock()
+ event_source_deleted = {"msg": "event source successfully deleted."}
+ client.delete_event_source_mapping.return_value = event_source_deleted
+ mock_camel_dict_to_snake_dict.side_effect = lambda x: x
+
+ events = []
+ changed = False
+ result = lambda_event_stream(ansible_aws_module, client)
+ changed = existing_event_source
+ if existing_event_source:
+ events = EventSourceMappings
+ if not check_mode:
+ events = event_source_deleted
+ client.delete_event_source_mapping.assert_called_once_with(UUID=EventSourceMappings[0]["UUID"])
+ else:
+ client.delete_event_source_mapping.assert_not_called()
+ assert dict(changed=changed, events=events) == result
+
+
+def test_lambda_event_stream_create_event_missing_starting_position(ansible_aws_module):
+ ansible_aws_module.params = {
+ "state": "present",
+ "lambda_function_arn": "sqs_consumer",
+ "event_source": "stream",
+ "source_params": {
+ "source_arn": "arn:aws:sqs:us-east-2:123456789012:ansible-test-sqs",
+ "maximum_batching_window_in_seconds": 1,
+ "batch_size": 200,
+ },
+ "alias": None,
+ "version": 0,
+ }
+
+ client = MagicMock()
+ client.list_event_source_mappings = MagicMock()
+ client.list_event_source_mappings.return_value = {"EventSourceMappings": []}
+
+ error_message = "Source parameter 'starting_position' is required for stream event notification."
+ with pytest.raises(SystemExit):
+ lambda_event_stream(ansible_aws_module, client)
+ ansible_aws_module.fail_json.assert_called_once_with(msg=error_message)
+
+
+@pytest.mark.parametrize(
+ "check_mode",
+ [True, False],
+)
+@pytest.mark.parametrize(
+ "module_params,api_params",
+ [
+ (
+ {
+ "state": "present",
+ "lambda_function_arn": "sqs_consumer",
+ "event_source": "stream",
+ "source_params": {
+ "source_arn": "arn:aws:sqs:us-east-2:123456789012:ansible-test-sqs",
+ "maximum_batching_window_in_seconds": 1,
+ "batch_size": 250,
+ "starting_position": "END",
+ "function_response_types": ["ReportBatchItemFailures"],
+ },
+ "alias": None,
+ "version": 0,
+ },
+ {
+ "FunctionName": "sqs_consumer",
+ "EventSourceArn": "arn:aws:sqs:us-east-2:123456789012:ansible-test-sqs",
+ "StartingPosition": "END",
+ "Enabled": True,
+ "MaximumBatchingWindowInSeconds": 1,
+ "BatchSize": 250,
+ "FunctionResponseTypes": ["ReportBatchItemFailures"],
+ },
+ ),
+ (
+ {
+ "state": "present",
+ "lambda_function_arn": "sqs_consumer",
+ "event_source": "stream",
+ "source_params": {
+ "source_arn": "arn:aws:sqs:us-east-2:123456789012:ansible-test-sqs",
+ "maximum_batching_window_in_seconds": 1,
+ "batch_size": 250,
+ "starting_position": "END",
+ "function_response_types": ["ReportBatchItemFailures"],
+ "enabled": "no",
+ },
+ "alias": None,
+ "version": 0,
+ },
+ {
+ "FunctionName": "sqs_consumer",
+ "EventSourceArn": "arn:aws:sqs:us-east-2:123456789012:ansible-test-sqs",
+ "StartingPosition": "END",
+ "Enabled": False,
+ "MaximumBatchingWindowInSeconds": 1,
+ "BatchSize": 250,
+ "FunctionResponseTypes": ["ReportBatchItemFailures"],
+ },
+ ),
+ (
+ {
+ "state": "present",
+ "lambda_function_arn": "sqs_consumer",
+ "event_source": "sqs",
+ "source_params": {
+ "source_arn": "arn:aws:sqs:us-east-2:123456789012:ansible-test-sqs",
+ "maximum_batching_window_in_seconds": 1,
+ "batch_size": 101,
+ },
+ "alias": None,
+ "version": 0,
+ },
+ {
+ "FunctionName": "sqs_consumer",
+ "EventSourceArn": "arn:aws:sqs:us-east-2:123456789012:ansible-test-sqs",
+ "Enabled": True,
+ "MaximumBatchingWindowInSeconds": 1,
+ "BatchSize": 101,
+ },
+ ),
+ ],
+)
+@patch(mock_camel_dict_to_snake_dict)
+def test_lambda_event_stream_create_event(
+ mock_camel_dict_to_snake_dict, ansible_aws_module, check_mode, module_params, api_params
+):
+ ansible_aws_module.params = module_params
+ ansible_aws_module.check_mode = check_mode
+
+ client = MagicMock()
+ client.list_event_source_mappings = MagicMock()
+ client.list_event_source_mappings.return_value = {"EventSourceMappings": []}
+
+ client.create_event_source_mapping = MagicMock()
+ event_source_created = {"msg": "event source successfully created."}
+ client.create_event_source_mapping.return_value = event_source_created
+ mock_camel_dict_to_snake_dict.side_effect = lambda x: x
+
+ result = lambda_event_stream(ansible_aws_module, client)
+
+ events = []
+
+ if not check_mode:
+ events = event_source_created
+ client.create_event_source_mapping.assert_called_once_with(**api_params)
+ else:
+ client.create_event_source_mapping.assert_not_called()
+
+ assert dict(changed=True, events=events) == result
+
+
+@pytest.mark.parametrize(
+ "check_mode",
+ [True, False],
+)
+@pytest.mark.parametrize(
+ "module_source_params,current_mapping,api_params",
+ [
+ (
+ {"batch_size": 100, "enabled": "false"},
+ {"BatchSize": 120, "State": "Enabled"},
+ {"BatchSize": 100, "Enabled": False},
+ ),
+ (
+ {"batch_size": 100, "enabled": "true"},
+ {"BatchSize": 100, "State": "Enabled"},
+ {},
+ ),
+ ],
+)
+@patch(mock_camel_dict_to_snake_dict)
+def test_lambda_event_stream_update_event(
+ mock_camel_dict_to_snake_dict, ansible_aws_module, check_mode, module_source_params, current_mapping, api_params
+):
+ function_name = "ansible-test-update-event-function"
+ ansible_aws_module.params.update({"lambda_function_arn": function_name})
+ ansible_aws_module.params["source_params"].update(module_source_params)
+ ansible_aws_module.check_mode = check_mode
+
+ client = MagicMock()
+ client.list_event_source_mappings = MagicMock()
+ existing_event_source = deepcopy(EventSourceMappings)
+ existing_event_source[0].update(current_mapping)
+ client.list_event_source_mappings.return_value = {"EventSourceMappings": existing_event_source}
+
+ client.update_event_source_mapping = MagicMock()
+ event_source_updated = {"msg": "event source successfully updated."}
+ client.update_event_source_mapping.return_value = event_source_updated
+ mock_camel_dict_to_snake_dict.side_effect = lambda x: x
+
+ result = lambda_event_stream(ansible_aws_module, client)
+ if not api_params:
+ assert dict(changed=False, events=existing_event_source) == result
+ client.update_event_source_mapping.assert_not_called()
+ elif check_mode:
+ assert dict(changed=True, events=existing_event_source) == result
+ client.update_event_source_mapping.assert_not_called()
+ else:
+ api_params.update({"FunctionName": function_name, "UUID": existing_event_source[0]["UUID"]})
+ assert dict(changed=True, events=event_source_updated) == result
+ client.update_event_source_mapping.assert_called_once_with(**api_params)
+
+
+@pytest.mark.parametrize(
+ "params, expected, exception, message, source_type",
+ [
+ (
+ {
+ "source_arn": "arn:aws:sqs:us-east-1:123456789012:ansible-test-28277052.fifo",
+ "enabled": True,
+ "batch_size": 100,
+ "starting_position": None,
+ "function_response_types": None,
+ "maximum_batching_window_in_seconds": None,
+ },
+ None,
+ pytest.raises(SystemExit),
+ "For FIFO queues the maximum batch_size is 10.",
+ "sqs",
+ ),
+ (
+ {
+ "source_arn": "arn:aws:sqs:us-east-1:123456789012:ansible-test-28277052.fifo",
+ "enabled": True,
+ "batch_size": 10,
+ "starting_position": None,
+ "function_response_types": None,
+ "maximum_batching_window_in_seconds": 1,
+ },
+ None,
+ pytest.raises(SystemExit),
+ "maximum_batching_window_in_seconds is not supported by Amazon SQS FIFO event sources.",
+ "sqs",
+ ),
+ (
+ {
+ "source_arn": "arn:aws:sqs:us-east-1:123456789012:ansible-test-28277052.fifo",
+ "enabled": True,
+ "batch_size": 10,
+ "starting_position": None,
+ "function_response_types": None,
+ "maximum_batching_window_in_seconds": None,
+ },
+ {
+ "source_arn": "arn:aws:sqs:us-east-1:123456789012:ansible-test-28277052.fifo",
+ "enabled": True,
+ "batch_size": 10,
+ "starting_position": None,
+ "function_response_types": None,
+ "maximum_batching_window_in_seconds": None,
+ },
+ does_not_raise(),
+ None,
+ "sqs",
+ ),
+ (
+ {
+ "source_arn": "arn:aws:sqs:us-east-1:123456789012:ansible-test-28277052",
+ "enabled": True,
+ "batch_size": 11000,
+ "starting_position": None,
+ "function_response_types": None,
+ "maximum_batching_window_in_seconds": None,
+ },
+ None,
+ pytest.raises(SystemExit),
+ "For standard queue batch_size must be lower than 10000.",
+ "sqs",
+ ),
+ (
+ {
+ "source_arn": "arn:aws:sqs:us-east-1:123456789012:ansible-test-28277052",
+ "enabled": True,
+ "batch_size": 100,
+ "starting_position": None,
+ "function_response_types": None,
+ "maximum_batching_window_in_seconds": None,
+ },
+ {
+ "source_arn": "arn:aws:sqs:us-east-1:123456789012:ansible-test-28277052",
+ "enabled": True,
+ "batch_size": 100,
+ "starting_position": None,
+ "function_response_types": None,
+ "maximum_batching_window_in_seconds": 1,
+ },
+ does_not_raise(),
+ None,
+ "sqs",
+ ),
+ (
+ {
+ "source_arn": "arn:aws:sqs:us-east-1:123456789012:ansible-test-28277052",
+ "enabled": True,
+ "starting_position": None,
+ "function_response_types": None,
+ "maximum_batching_window_in_seconds": None,
+ },
+ {
+ "source_arn": "arn:aws:sqs:us-east-1:123456789012:ansible-test-28277052",
+ "enabled": True,
+ "batch_size": 100,
+ "starting_position": None,
+ "function_response_types": None,
+ "maximum_batching_window_in_seconds": 1,
+ },
+ does_not_raise(),
+ None,
+ "stream",
+ ),
+ (
+ {
+ "source_arn": "arn:aws:sqs:us-east-1:123456789012:ansible-test-28277052",
+ "enabled": True,
+ "starting_position": None,
+ "function_response_types": None,
+ },
+ {
+ "source_arn": "arn:aws:sqs:us-east-1:123456789012:ansible-test-28277052",
+ "enabled": True,
+ "batch_size": 10,
+ "starting_position": None,
+ "function_response_types": None,
+ },
+ does_not_raise(),
+ None,
+ "sqs",
+ ),
+ (
+ {
+ "source_arn": "arn:aws:sqs:us-east-1:123456789012:ansible-test-28277052",
+ "enabled": True,
+ "batch_size": 10,
+ "starting_position": None,
+ "function_response_types": None,
+ "maximum_batching_window_in_seconds": None,
+ },
+ None,
+ pytest.raises(SystemExit),
+ "batch_size for streams must be between 100 and 10000",
+ "stream",
+ ),
+ ],
+)
+def test__set_default_values(params, expected, exception, message, source_type):
+ result = None
+ module = MagicMock()
+ module.check_mode = False
+ module.params = {
+ "event_source": source_type,
+ "source_params": params,
+ }
+ module.fail_json = MagicMock()
+ module.fail_json.side_effect = SystemExit(message)
+ with exception as e:
+ result = set_default_values(module, params)
+ assert message is None or message in str(e)
+ if expected is not None:
+ assert result == expected