diff --git a/changelogs/fragments/1108-lambda-checkmode-fix-kms_key_arn-param.yml b/changelogs/fragments/1108-lambda-checkmode-fix-kms_key_arn-param.yml new file mode 100644 index 00000000000..29a46721b45 --- /dev/null +++ b/changelogs/fragments/1108-lambda-checkmode-fix-kms_key_arn-param.yml @@ -0,0 +1,5 @@ +minor_changes: + - lambda - add kms_key_arn parameter (https://github.com/ansible-collections/community.aws/pull/1108). +bugfixes: + - lambda - fix check mode on creation (https://github.com/ansible-collections/community.aws/pull/1108). + - execute_lamba - add waiter for function_updated (https://github.com/ansible-collections/community.aws/pull/1108). diff --git a/plugins/modules/execute_lambda.py b/plugins/modules/execute_lambda.py index b4cbb4a53de..b599b6636ca 100644 --- a/plugins/modules/execute_lambda.py +++ b/plugins/modules/execute_lambda.py @@ -260,8 +260,10 @@ def main(): def wait_for_lambda(client, module, name): try: - waiter = client.get_waiter('function_active') - waiter.wait(FunctionName=name) + client_active_waiter = client.get_waiter('function_active') + client_updated_waiter = client.get_waiter('function_updated') + client_active_waiter.wait(FunctionName=name) + client_updated_waiter.wait(FunctionName=name) except botocore.exceptions.WaiterError as e: module.fail_json_aws(e, msg='Timeout while waiting on lambda to be Active') except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: diff --git a/plugins/modules/lambda.py b/plugins/modules/lambda.py index 923b1646c3d..bbdac1c3642 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: @@ -350,6 +355,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'), ) @@ -387,6 +393,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 @@ -442,6 +449,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: @@ -573,17 +582,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}}'