From 3499d2939cb772af2bab6728d0b0dfaa6499dac5 Mon Sep 17 00:00:00 2001 From: Joseph Torcasso <87090265+jatorcasso@users.noreply.github.com> Date: Fri, 6 May 2022 08:52:28 -0400 Subject: [PATCH] lambda - fix check mode on creation (#1108) lambda - fix check mode on creation Depends-On: #1116 SUMMARY When adding integration tests for check mode runs, creating a lambda function failed on check mode with the message "Unable to get function information after creating". Added parameter kms_key_arn - testing in integration tests appears difficult as I think we'd need to create an IAM policy to allow for adding kms_key, which would render these tests as unsupported. Added extra waiter for function_update in execute_lambda to resolve occasional integration test failure. Fixes #1111 ISSUE TYPE Feature Pull Request Bugfix Pull Request COMPONENT NAME lambda Reviewed-by: Alina Buzachis Reviewed-by: Markus Bergholz This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/0bde6bbd55bd90c7d8585bb7d7a36c147f70bb56 --- plugins/modules/lambda.py | 21 +++- .../integration/targets/lambda/tasks/main.yml | 99 ++++++++++++++++++- 2 files changed, 116 insertions(+), 4 deletions(-) diff --git a/plugins/modules/lambda.py b/plugins/modules/lambda.py index 8ad45785f21..ff469c5bc71 100644 --- a/plugins/modules/lambda.py +++ b/plugins/modules/lambda.py @@ -107,6 +107,11 @@ description: - Tag dict to apply to the function. type: dict + kms_key_arn: + description: + - The KMS key ARN used to encrypt the function's environment variables. + type: str + version_added: 3.3.0 author: - 'Steyn Huizinga (@steynovich)' extends_documentation_fragment: @@ -451,6 +456,7 @@ def main(): vpc_security_group_ids=dict(type='list', elements='str'), environment_variables=dict(type='dict'), dead_letter_arn=dict(), + kms_key_arn=dict(type='str', no_log=False), tracing_mode=dict(choices=['Active', 'PassThrough']), tags=dict(type='dict'), ) @@ -488,6 +494,7 @@ def main(): dead_letter_arn = module.params.get('dead_letter_arn') tracing_mode = module.params.get('tracing_mode') tags = module.params.get('tags') + kms_key_arn = module.params.get('kms_key_arn') check_mode = module.check_mode changed = False @@ -543,6 +550,8 @@ def main(): func_kwargs.update({'DeadLetterConfig': {'TargetArn': dead_letter_arn}}) if tracing_mode and (current_config.get('TracingConfig', {}).get('Mode', 'PassThrough') != tracing_mode): func_kwargs.update({'TracingConfig': {'Mode': tracing_mode}}) + if kms_key_arn: + func_kwargs.update({'KMSKeyArn': kms_key_arn}) # If VPC configuration is desired if vpc_subnet_ids: @@ -674,17 +683,23 @@ def main(): if tracing_mode: func_kwargs.update({'TracingConfig': {'Mode': tracing_mode}}) + if kms_key_arn: + func_kwargs.update({'KMSKeyArn': kms_key_arn}) + # If VPC configuration is given if vpc_subnet_ids: func_kwargs.update({'VpcConfig': {'SubnetIds': vpc_subnet_ids, 'SecurityGroupIds': vpc_security_group_ids}}) + # Function would have been created if not check mode + if check_mode: + module.exit_json(changed=True) + # Finally try to create function current_version = None try: - if not check_mode: - response = client.create_function(aws_retry=True, **func_kwargs) - current_version = response['Version'] + response = client.create_function(aws_retry=True, **func_kwargs) + current_version = response['Version'] changed = True except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg="Trying to create function") diff --git a/tests/integration/targets/lambda/tasks/main.yml b/tests/integration/targets/lambda/tasks/main.yml index a7a1680d9e6..ecce54a3236 100644 --- a/tests/integration/targets/lambda/tasks/main.yml +++ b/tests/integration/targets/lambda/tasks/main.yml @@ -93,6 +93,19 @@ - '"parameters are required together" in result.msg' # Prepare minimal Lambda + - name: test state=present - upload the lambda (check mode) + lambda: + name: '{{ lambda_function_name }}' + runtime: python3.6 + handler: mini_lambda.handler + role: '{{ lambda_role_name }}' + zip_file: '{{ zip_res.dest }}' + register: result + check_mode: yes + - name: assert lambda upload succeeded + assert: + that: + - result.changed - name: test state=present - upload the lambda lambda: @@ -105,7 +118,7 @@ - name: assert lambda upload succeeded assert: that: - - result is not failed + - result.changed - result.configuration.tracing_config.mode == "PassThrough" # Test basic operation of Uploaded lambda @@ -122,6 +135,25 @@ - result.result.output.message == "hello Mr Ansible Tests" # Test updating Lambda + - name: test lambda config updates (check mode) + lambda: + name: '{{lambda_function_name}}' + runtime: nodejs14.x + tracing_mode: Active + handler: mini_lambda.handler + role: '{{ lambda_role_name }}' + tags: + CamelCase: 'ACamelCaseValue' + snake_case: 'a_snake_case_value' + 'Spaced key': 'A value with spaces' + register: update_result + check_mode: yes + - name: assert that update succeeded + assert: + that: + - update_result is not failed + - update_result.changed == True + - name: test lambda config updates lambda: name: '{{lambda_function_name}}' @@ -142,6 +174,25 @@ - update_result.configuration.runtime == 'nodejs14.x' - update_result.configuration.tracing_config.mode == 'Active' + - name: test no changes are made with the same parameters repeated (check mode) + lambda: + name: '{{lambda_function_name}}' + runtime: nodejs14.x + tracing_mode: Active + handler: mini_lambda.handler + role: '{{ lambda_role_name }}' + tags: + CamelCase: 'ACamelCaseValue' + snake_case: 'a_snake_case_value' + 'Spaced key': 'A value with spaces' + register: update_result + check_mode: yes + - name: assert that update succeeded + assert: + that: + - update_result is not failed + - update_result.changed == False + - name: test no changes are made with the same parameters repeated lambda: name: '{{lambda_function_name}}' @@ -184,6 +235,7 @@ name: '{{ lambda_function_name }}' query: all register: lambda_infos_all + check_mode: yes - name: lambda_info | Assert successfull retrieval of all information assert: that: @@ -278,6 +330,23 @@ - result is not failed - result.changed == False + - name: test putting an environment variable changes lambda (check mode) + lambda: + name: '{{lambda_function_name}}' + runtime: python3.6 + handler: mini_lambda.handler + role: '{{ lambda_role_name }}' + zip_file: '{{zip_res.dest}}' + environment_variables: + EXTRA_MESSAGE: I think you are great!! + register: result + check_mode: yes + - name: assert lambda upload succeeded + assert: + that: + - result is not failed + - result.changed == True + - name: test putting an environment variable changes lambda lambda: name: '{{lambda_function_name}}' @@ -293,6 +362,8 @@ that: - result is not failed - result.changed == True + - result.configuration.environment.variables.extra_message == "I think you are great!!" + - name: test lambda works execute_lambda: name: '{{lambda_function_name}}' @@ -306,6 +377,19 @@ - result.result.output.message == "hello Mr Ansible Tests. I think you are great!!" # Deletion behavious + - name: test state=absent (expect changed=True) (check mode) + lambda: + name: '{{lambda_function_name}}' + state: absent + register: result + check_mode: yes + + - name: assert state=absent + assert: + that: + - result is not failed + - result is changed + - name: test state=absent (expect changed=True) lambda: name: '{{lambda_function_name}}' @@ -318,6 +402,19 @@ - result is not failed - result is changed + - name: test state=absent (expect changed=False) when already deleted (check mode) + lambda: + name: '{{lambda_function_name}}' + state: absent + register: result + check_mode: yes + + - name: assert state=absent + assert: + that: + - result is not failed + - result is not changed + - name: test state=absent (expect changed=False) when already deleted lambda: name: '{{lambda_function_name}}'