From 42e4139b811f35f45a65ac0316b404225708c35e Mon Sep 17 00:00:00 2001 From: Joseph Torcasso Date: Thu, 19 May 2022 16:50:32 -0400 Subject: [PATCH 1/6] refactor to fix bug when querying all lambdas --- plugins/modules/lambda_info.py | 210 +++++++++--------- .../integration/targets/lambda/tasks/main.yml | 26 ++- 2 files changed, 123 insertions(+), 113 deletions(-) diff --git a/plugins/modules/lambda_info.py b/plugins/modules/lambda_info.py index c76ecba3d1e..5c70e36e65e 100644 --- a/plugins/modules/lambda_info.py +++ b/plugins/modules/lambda_info.py @@ -13,8 +13,8 @@ short_description: Gathers AWS Lambda function details description: - Gathers various details related to Lambda functions, including aliases, versions and event source mappings. - - Use module M(community.aws.lambda) to manage the lambda function itself, M(community.aws.lambda_alias) to manage function aliases and - M(community.aws.lambda_event) to manage lambda event source mappings. + - Use module M(community.aws.lambda) to manage the lambda function itself, M(community.aws.lambda_alias) to manage function aliases, + M(community.aws.lambda_event) to manage lambda event source mappings, and M(community.aws.lambda_policy) to manage policy statements. options: @@ -48,17 +48,20 @@ query: all function_name: myFunction register: my_function_details + # List all versions of a function - name: List function versions community.aws.lambda_info: query: versions function_name: myFunction register: my_function_versions -# List all lambda function versions -- name: List all function + +# List all info for all functions +- name: List all functions community.aws.lambda_info: query: all register: output + - name: show Lambda information ansible.builtin.debug: msg: "{{ output['function'] }}" @@ -120,108 +123,118 @@ def fix_return(node): return node_value -def alias_details(client, module): +def alias_details(client, module, function_name): """ Returns list of aliases for a specified function. :param client: AWS API client reference (boto3) :param module: Ansible module reference + :param function_name (str): Name of Lambda function to query :return dict: """ lambda_info = dict() - function_name = module.params.get('function_name') - if function_name: - try: - lambda_info.update(aliases=_paginate(client, 'list_aliases', FunctionName=function_name)['Aliases']) - except is_boto3_error_code('ResourceNotFoundException'): - lambda_info.update(aliases=[]) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except - module.fail_json_aws(e, msg="Trying to get aliases") - else: - module.fail_json(msg='Parameter function_name required for query=aliases.') + try: + lambda_info.update(aliases=_paginate(client, 'list_aliases', FunctionName=function_name)['Aliases']) + except is_boto3_error_code('ResourceNotFoundException'): + lambda_info.update(aliases=[]) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except + module.fail_json_aws(e, msg="Trying to get aliases") - return {function_name: camel_dict_to_snake_dict(lambda_info)} + return camel_dict_to_snake_dict(lambda_info) -def all_details(client, module): +def list_lambdas(client, module): """ - Returns all lambda related facts. + Returns queried facts for a specified function (or all functions). :param client: AWS API client reference (boto3) :param module: Ansible module reference :return dict: """ - lambda_info = dict() - + # Function name is specified - retrieve info on that function function_name = module.params.get('function_name') if function_name: - lambda_info[function_name] = {} - lambda_info[function_name].update(config_details(client, module)[function_name]) - lambda_info[function_name].update(alias_details(client, module)[function_name]) - lambda_info[function_name].update(policy_details(client, module)[function_name]) - lambda_info[function_name].update(version_details(client, module)[function_name]) - lambda_info[function_name].update(mapping_details(client, module)[function_name]) - lambda_info[function_name].update(tags_details(client, module)[function_name]) - else: - lambda_info.update(config_details(client, module)) + function_names = [function_name] + + # Function name is not specified - retrieve all function names + all_function_info = _paginate(client, 'list_functions')['Functions'] + function_names = [function_info['FunctionName'] for function_info in all_function_info] + + query = module.params['query'] + lambdas = dict() - return lambda_info + for function_name in function_names: + lambdas[function_name] = {} + if query == 'all': + lambdas[function_name].update(config_details(client, module, function_name)) + lambdas[function_name].update(alias_details(client, module, function_name)) + lambdas[function_name].update(policy_details(client, module, function_name)) + lambdas[function_name].update(version_details(client, module, function_name)) + lambdas[function_name].update(mapping_details(client, module, function_name)) + lambdas[function_name].update(tags_details(client, module, function_name)) -def config_details(client, module): + elif query == 'config': + lambdas[function_name].update(config_details(client, module, function_name)) + + elif query == 'aliases': + lambdas[function_name].update(alias_details(client, module, function_name)) + + elif query == 'policy': + lambdas[function_name].update(policy_details(client, module, function_name)) + + elif query == 'versions': + lambdas[function_name].update(version_details(client, module, function_name)) + + elif query == 'mappings': + lambdas[function_name].update(mapping_details(client, module, function_name)) + + elif query == 'tags': + lambdas[function_name].update(tags_details(client, module, function_name)) + + + return lambdas + + +def config_details(client, module, function_name): """ - Returns configuration details for one or all lambda functions. + Returns configuration details for a lambda function. :param client: AWS API client reference (boto3) :param module: Ansible module reference + :param function_name (str): Name of Lambda function to query :return dict: """ lambda_info = dict() - function_name = module.params.get('function_name') - if function_name: - try: - lambda_info.update(client.get_function_configuration(aws_retry=True, FunctionName=function_name)) - except is_boto3_error_code('ResourceNotFoundException'): - lambda_info.update(function={}) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except - module.fail_json_aws(e, msg="Trying to get {0} configuration".format(function_name)) - else: - try: - lambda_info.update(function_list=_paginate(client, 'list_functions')['Functions']) - except is_boto3_error_code('ResourceNotFoundException'): - lambda_info.update(function_list=[]) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except - module.fail_json_aws(e, msg="Trying to get function list") - - functions = dict() - for func in lambda_info.pop('function_list', []): - func['tags'] = client.get_function(FunctionName=func['FunctionName']).get('Tags', {}) - functions[func['FunctionName']] = camel_dict_to_snake_dict(func) - return functions + try: + lambda_info.update(client.get_function_configuration(aws_retry=True, FunctionName=function_name)) + except is_boto3_error_code('ResourceNotFoundException'): + lambda_info.update(function={}) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except + module.fail_json_aws(e, msg="Trying to get {0} configuration".format(function_name)) - return {function_name: camel_dict_to_snake_dict(lambda_info)} + return camel_dict_to_snake_dict(lambda_info) -def mapping_details(client, module): +def mapping_details(client, module, function_name): """ Returns all lambda event source mappings. :param client: AWS API client reference (boto3) :param module: Ansible module reference + :param function_name (str): Name of Lambda function to query :return dict: """ lambda_info = dict() params = dict() - function_name = module.params.get('function_name') - if function_name: - params['FunctionName'] = module.params.get('function_name') + params['FunctionName'] = function_name if module.params.get('event_source_arn'): params['EventSourceArn'] = module.params.get('event_source_arn') @@ -233,86 +246,74 @@ def mapping_details(client, module): except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except module.fail_json_aws(e, msg="Trying to get source event mappings") - if function_name: - return {function_name: camel_dict_to_snake_dict(lambda_info)} - return camel_dict_to_snake_dict(lambda_info) -def policy_details(client, module): +def policy_details(client, module, function_name): """ Returns policy attached to a lambda function. :param client: AWS API client reference (boto3) :param module: Ansible module reference + :param function_name (str): Name of Lambda function to query :return dict: """ lambda_info = dict() - function_name = module.params.get('function_name') - if function_name: - try: - # get_policy returns a JSON string so must convert to dict before reassigning to its key - lambda_info.update(policy=json.loads(client.get_policy(aws_retry=True, FunctionName=function_name)['Policy'])) - except is_boto3_error_code('ResourceNotFoundException'): - lambda_info.update(policy={}) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except - module.fail_json_aws(e, msg="Trying to get {0} policy".format(function_name)) - else: - module.fail_json(msg='Parameter function_name required for query=policy.') + try: + # get_policy returns a JSON string so must convert to dict before reassigning to its key + lambda_info.update(policy=json.loads(client.get_policy(aws_retry=True, FunctionName=function_name)['Policy'])) + except is_boto3_error_code('ResourceNotFoundException'): + lambda_info.update(policy={}) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except + module.fail_json_aws(e, msg="Trying to get {0} policy".format(function_name)) - return {function_name: camel_dict_to_snake_dict(lambda_info)} + return camel_dict_to_snake_dict(lambda_info) -def version_details(client, module): +def version_details(client, module, function_name): """ Returns all lambda function versions. :param client: AWS API client reference (boto3) :param module: Ansible module reference + :param function_name (str): Name of Lambda function to query :return dict: """ lambda_info = dict() - function_name = module.params.get('function_name') - if function_name: - try: - lambda_info.update(versions=_paginate(client, 'list_versions_by_function', FunctionName=function_name)['Versions']) - except is_boto3_error_code('ResourceNotFoundException'): - lambda_info.update(versions=[]) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except + try: + lambda_info.update(versions=_paginate(client, 'list_versions_by_function', FunctionName=function_name)['Versions']) + except is_boto3_error_code('ResourceNotFoundException'): + lambda_info.update(versions=[]) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except module.fail_json_aws(e, msg="Trying to get {0} versions".format(function_name)) - else: - module.fail_json(msg='Parameter function_name required for query=versions.') - return {function_name: camel_dict_to_snake_dict(lambda_info)} + return camel_dict_to_snake_dict(lambda_info) -def tags_details(client, module): +def tags_details(client, module, function_name): """ - Returns tag details for one or all lambda functions. + Returns tag details for a lambda function. :param client: AWS API client reference (boto3) :param module: Ansible module reference + :param function_name (str): Name of Lambda function to query :return dict: """ lambda_info = dict() - function_name = module.params.get('function_name') - if function_name: - try: - lambda_info.update(tags=client.get_function(aws_retry=True, FunctionName=function_name).get('Tags', {})) - except is_boto3_error_code('ResourceNotFoundException'): - lambda_info.update(function={}) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except - module.fail_json_aws(e, msg="Trying to get {0} tags".format(function_name)) - else: - module.fail_json(msg='Parameter function_name required for query=tags.') + try: + lambda_info.update(tags=client.get_function(aws_retry=True, FunctionName=function_name).get('Tags', {})) + except is_boto3_error_code('ResourceNotFoundException'): + lambda_info.update(function={}) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except + module.fail_json_aws(e, msg="Trying to get {0} tags".format(function_name)) - return {function_name: camel_dict_to_snake_dict(lambda_info)} + return camel_dict_to_snake_dict(lambda_info) def main(): @@ -346,18 +347,7 @@ def main(): client = module.client('lambda', retry_decorator=AWSRetry.jittered_backoff()) - invocations = dict( - aliases='alias_details', - all='all_details', - config='config_details', - mappings='mapping_details', - policy='policy_details', - versions='version_details', - tags='tags_details', - ) - - this_module_function = globals()[invocations[module.params['query']]] - all_facts = fix_return(this_module_function(client, module)) + all_facts = fix_return(list_lambdas(client, module)) results = dict(function=all_facts, changed=False) diff --git a/tests/integration/targets/lambda/tasks/main.yml b/tests/integration/targets/lambda/tasks/main.yml index 65e1f9bc858..c73e6f2985f 100644 --- a/tests/integration/targets/lambda/tasks/main.yml +++ b/tests/integration/targets/lambda/tasks/main.yml @@ -253,10 +253,8 @@ - result.configuration.tracing_config.mode == 'PassThrough' # Query the Lambda - - name: lambda_info | Gather all infos for given lambda function + - name: lambda_info | Gather all infos for all lambda functions lambda_info: - name: '{{ lambda_function_name }}' - query: all register: lambda_infos_all check_mode: yes - name: lambda_info | Assert successfull retrieval of all information @@ -285,6 +283,10 @@ - lambda_infos_versions is not failed - lambda_infos_versions.function[lambda_function_name].versions|length > 0 - lambda_infos_versions.function[lambda_function_name].function_name is undefined + - lambda_infos_versions.function[lambda_function_name].policy is undefined + - lambda_infos_versions.function[lambda_function_name].aliases is undefined + - lambda_infos_versions.function[lambda_function_name].mappings is undefined + - lambda_infos_versions.function[lambda_function_name].tags is undefined - name: lambda_info | Gather config infos for given lambda function lambda_info: @@ -298,6 +300,10 @@ - lambda_infos_config.function[lambda_function_name].function_name == lambda_function_name - lambda_infos_config.function[lambda_function_name].description is defined - lambda_infos_config.function[lambda_function_name].versions is undefined + - lambda_infos_config.function[lambda_function_name].policy is undefined + - lambda_infos_config.function[lambda_function_name].aliases is undefined + - lambda_infos_config.function[lambda_function_name].mappings is undefined + - lambda_infos_config.function[lambda_function_name].tags is undefined - name: lambda_info | Gather policy infos for given lambda function lambda_info: @@ -310,6 +316,10 @@ - lambda_infos_policy is not failed - lambda_infos_policy.function[lambda_function_name].policy is defined - lambda_infos_policy.function[lambda_function_name].versions is undefined + - lambda_infos_policy.function[lambda_function_name].function_name is undefined + - lambda_infos_policy.function[lambda_function_name].aliases is undefined + - lambda_infos_policy.function[lambda_function_name].mappings is undefined + - lambda_infos_policy.function[lambda_function_name].tags is undefined - name: lambda_info | Gather aliases infos for given lambda function lambda_info: @@ -321,6 +331,11 @@ that: - lambda_infos_aliases is not failed - lambda_infos_aliases.function[lambda_function_name].aliases is defined + - lambda_infos_aliases.function[lambda_function_name].versions is undefined + - lambda_infos_aliases.function[lambda_function_name].function_name is undefined + - lambda_infos_aliases.function[lambda_function_name].policy is undefined + - lambda_infos_aliases.function[lambda_function_name].mappings is undefined + - lambda_infos_aliases.function[lambda_function_name].tags is undefined - name: lambda_info | Gather mappings infos for given lambda function lambda_info: @@ -332,6 +347,11 @@ that: - lambda_infos_mappings is not failed - lambda_infos_mappings.function[lambda_function_name].mappings is defined + - lambda_infos_mappings.function[lambda_function_name].versions is undefined + - lambda_infos_mappings.function[lambda_function_name].function_name is undefined + - lambda_infos_mappings.function[lambda_function_name].aliases is undefined + - lambda_infos_mappings.function[lambda_function_name].policy is undefined + - lambda_infos_mappings.function[lambda_function_name].tags is undefined # More Lambda update tests - name: test state=present with all nullable variables explicitly set to null From 42087030f2c76833c1ae196100fb1c1d5c436855 Mon Sep 17 00:00:00 2001 From: Joseph Torcasso Date: Thu, 19 May 2022 18:20:07 -0400 Subject: [PATCH 2/6] minor logic fix --- plugins/modules/lambda_info.py | 12 ++++++------ tests/integration/targets/lambda/tasks/main.yml | 8 +++++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/plugins/modules/lambda_info.py b/plugins/modules/lambda_info.py index 5c70e36e65e..266b94b0285 100644 --- a/plugins/modules/lambda_info.py +++ b/plugins/modules/lambda_info.py @@ -154,14 +154,15 @@ def list_lambdas(client, module): :return dict: """ - # Function name is specified - retrieve info on that function function_name = module.params.get('function_name') if function_name: + # Function name is specified - retrieve info on that function function_names = [function_name] - # Function name is not specified - retrieve all function names - all_function_info = _paginate(client, 'list_functions')['Functions'] - function_names = [function_info['FunctionName'] for function_info in all_function_info] + else: + # Function name is not specified - retrieve all function names + all_function_info = _paginate(client, 'list_functions')['Functions'] + function_names = [function_info['FunctionName'] for function_info in all_function_info] query = module.params['query'] lambdas = dict() @@ -195,7 +196,6 @@ def list_lambdas(client, module): elif query == 'tags': lambdas[function_name].update(tags_details(client, module, function_name)) - return lambdas @@ -289,7 +289,7 @@ def version_details(client, module, function_name): except is_boto3_error_code('ResourceNotFoundException'): lambda_info.update(versions=[]) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except - module.fail_json_aws(e, msg="Trying to get {0} versions".format(function_name)) + module.fail_json_aws(e, msg="Trying to get {0} versions".format(function_name)) return camel_dict_to_snake_dict(lambda_info) diff --git a/tests/integration/targets/lambda/tasks/main.yml b/tests/integration/targets/lambda/tasks/main.yml index c73e6f2985f..f8f37b09dfd 100644 --- a/tests/integration/targets/lambda/tasks/main.yml +++ b/tests/integration/targets/lambda/tasks/main.yml @@ -252,7 +252,7 @@ - result.configuration.runtime == 'python3.6' - result.configuration.tracing_config.mode == 'PassThrough' - # Query the Lambda + # Test lambda_info - name: lambda_info | Gather all infos for all lambda functions lambda_info: register: lambda_infos_all @@ -261,6 +261,7 @@ assert: that: - lambda_infos_all is not failed + - lambda_infos_all.function | length > 0 - lambda_infos_all.function[lambda_function_name].function_name == lambda_function_name - lambda_infos_all.function[lambda_function_name].runtime == "python3.6" - lambda_infos_all.function[lambda_function_name].versions is defined @@ -281,6 +282,7 @@ assert: that: - lambda_infos_versions is not failed + - lambda_infos_versions.function | length == 1 - lambda_infos_versions.function[lambda_function_name].versions|length > 0 - lambda_infos_versions.function[lambda_function_name].function_name is undefined - lambda_infos_versions.function[lambda_function_name].policy is undefined @@ -297,6 +299,7 @@ assert: that: - lambda_infos_config is not failed + - lambda_infos_config.function | length == 1 - lambda_infos_config.function[lambda_function_name].function_name == lambda_function_name - lambda_infos_config.function[lambda_function_name].description is defined - lambda_infos_config.function[lambda_function_name].versions is undefined @@ -314,6 +317,7 @@ assert: that: - lambda_infos_policy is not failed + - lambda_infos_policy.function | length == 1 - lambda_infos_policy.function[lambda_function_name].policy is defined - lambda_infos_policy.function[lambda_function_name].versions is undefined - lambda_infos_policy.function[lambda_function_name].function_name is undefined @@ -330,6 +334,7 @@ assert: that: - lambda_infos_aliases is not failed + - lambda_infos_aliases.function | length == 1 - lambda_infos_aliases.function[lambda_function_name].aliases is defined - lambda_infos_aliases.function[lambda_function_name].versions is undefined - lambda_infos_aliases.function[lambda_function_name].function_name is undefined @@ -346,6 +351,7 @@ assert: that: - lambda_infos_mappings is not failed + - lambda_infos_mappings.function | length == 1 - lambda_infos_mappings.function[lambda_function_name].mappings is defined - lambda_infos_mappings.function[lambda_function_name].versions is undefined - lambda_infos_mappings.function[lambda_function_name].function_name is undefined From ce0b649e30a83a67e9133a70dbd40e5f1541d1bc Mon Sep 17 00:00:00 2001 From: Joseph Torcasso Date: Thu, 19 May 2022 18:23:26 -0400 Subject: [PATCH 3/6] add changelog --- changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml diff --git a/changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml b/changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml new file mode 100644 index 00000000000..592047a9dad --- /dev/null +++ b/changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml @@ -0,0 +1,2 @@ +bugfixes: + - lambda_info - fix bug that forces query=config when getting info for all lambdas (https://github.com/ansible-collections/community.aws/pull/1152). From cc604f344e3595690a112d4a391f4ea965678bec Mon Sep 17 00:00:00 2001 From: Joseph Torcasso Date: Thu, 19 May 2022 22:34:10 -0400 Subject: [PATCH 4/6] add extra cleanup --- tests/integration/targets/lambda/tasks/main.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/integration/targets/lambda/tasks/main.yml b/tests/integration/targets/lambda/tasks/main.yml index f8f37b09dfd..8838eef279c 100644 --- a/tests/integration/targets/lambda/tasks/main.yml +++ b/tests/integration/targets/lambda/tasks/main.yml @@ -549,11 +549,19 @@ - result is not failed always: - - name: ensure function is absent at end of test + + - name: ensure functions are absent at end of test lambda: - name: '{{lambda_function_name}}' + name: "{{ item }}" state: absent ignore_errors: true + with_items: + - "{{ lambda_function_name }}" + - "{{ lambda_function_name }}_1" + - "{{ lambda_function_name }}_2" + - "{{ lambda_function_name }}_3" + - "{{ lambda_function_name }}_4" + - name: ensure role has been removed at end of test iam_role: name: '{{ lambda_role_name }}' From 1ce1874f931a4237002819ed7fc2557441fd2349 Mon Sep 17 00:00:00 2001 From: Joseph Torcasso Date: Mon, 23 May 2022 12:20:49 -0400 Subject: [PATCH 5/6] change query default values --- .../1152-lambda_info-bugfix-all-lambdas.yml | 3 +- plugins/modules/lambda_info.py | 16 +++++-- .../integration/targets/lambda/tasks/main.yml | 43 +++++++++++++++++-- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml b/changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml index 592047a9dad..9b31aabd9f5 100644 --- a/changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml +++ b/changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml @@ -1,2 +1,3 @@ bugfixes: - - lambda_info - fix bug that forces query=config when getting info for all lambdas (https://github.com/ansible-collections/community.aws/pull/1152). + - lambda_info - fix bug that forces query=config when getting info for all lambdas. Now, if function name is specified, query will default to all. + If function name is not specified, query will default to config (https://github.com/ansible-collections/community.aws/pull/1152). diff --git a/plugins/modules/lambda_info.py b/plugins/modules/lambda_info.py index 266b94b0285..1ad2749c5f8 100644 --- a/plugins/modules/lambda_info.py +++ b/plugins/modules/lambda_info.py @@ -20,9 +20,10 @@ options: query: description: - - Specifies the resource type for which to gather information. Leave blank to retrieve all information. + - Specifies the resource type for which to gather information. + - Defaults to C(all) when I(function_name) is specified. + - Defaults to C(config) when I(function_name) is NOT specified. choices: [ "aliases", "all", "config", "mappings", "policy", "versions", "tags" ] - default: "all" type: str function_name: description: @@ -324,7 +325,7 @@ def main(): """ argument_spec = dict( function_name=dict(required=False, default=None, aliases=['function', 'name']), - query=dict(required=False, choices=['aliases', 'all', 'config', 'mappings', 'policy', 'versions', 'tags'], default='all'), + query=dict(required=False, choices=['aliases', 'all', 'config', 'mappings', 'policy', 'versions', 'tags'], default=None), event_source_arn=dict(required=False, default=None), ) @@ -345,6 +346,15 @@ def main(): if len(function_name) > 64: module.fail_json(msg='Function name "{0}" exceeds 64 character limit'.format(function_name)) + # create default values for query if not specified. + # if function name exists, query should default to 'all'. + # if function name does not exist, query should default to 'config' to limit the runtime when listing all lambdas. + if not module.params.get('query'): + if function_name: + module.params['query'] = 'all' + else: + module.params['query'] = 'config' + client = module.client('lambda', retry_decorator=AWSRetry.jittered_backoff()) all_facts = fix_return(list_lambdas(client, module)) diff --git a/tests/integration/targets/lambda/tasks/main.yml b/tests/integration/targets/lambda/tasks/main.yml index 8838eef279c..6ce1d7bae14 100644 --- a/tests/integration/targets/lambda/tasks/main.yml +++ b/tests/integration/targets/lambda/tasks/main.yml @@ -255,6 +255,7 @@ # Test lambda_info - name: lambda_info | Gather all infos for all lambda functions lambda_info: + query: all register: lambda_infos_all check_mode: yes - name: lambda_info | Assert successfull retrieval of all information @@ -264,15 +265,51 @@ - lambda_infos_all.function | length > 0 - lambda_infos_all.function[lambda_function_name].function_name == lambda_function_name - lambda_infos_all.function[lambda_function_name].runtime == "python3.6" + - lambda_infos_all.function[lambda_function_name].description == "" + - lambda_infos_all.function[lambda_function_name].function_arn is defined + - lambda_infos_all.function[lambda_function_name].handler == "mini_lambda.handler" - lambda_infos_all.function[lambda_function_name].versions is defined - lambda_infos_all.function[lambda_function_name].aliases is defined - lambda_infos_all.function[lambda_function_name].policy is defined - lambda_infos_all.function[lambda_function_name].mappings is defined - - lambda_infos_all.function[lambda_function_name].description == "" - - lambda_infos_all.function[lambda_function_name].function_arn is defined - - lambda_infos_all.function[lambda_function_name].handler == "mini_lambda.handler" - lambda_infos_all.function[lambda_function_name].tags is defined + - name: lambda_info | Ensure default query value is 'config' when function name omitted + lambda_info: + register: lambda_infos_query_config + check_mode: yes + - name: lambda_info | Assert successfull retrieval of all information + assert: + that: + - lambda_infos_query_config is not failed + - lambda_infos_query_config.function | length > 0 + - lambda_infos_query_config.function[lambda_function_name].function_name == lambda_function_name + - lambda_infos_query_config.function[lambda_function_name].runtime == "python3.6" + - lambda_infos_query_config.function[lambda_function_name].description == "" + - lambda_infos_query_config.function[lambda_function_name].function_arn is defined + - lambda_infos_query_config.function[lambda_function_name].handler == "mini_lambda.handler" + - lambda_infos_query_config.function[lambda_function_name].versions is not defined + - lambda_infos_query_config.function[lambda_function_name].aliases is not defined + - lambda_infos_query_config.function[lambda_function_name].policy is not defined + - lambda_infos_query_config.function[lambda_function_name].mappings is not defined + - lambda_infos_query_config.function[lambda_function_name].tags is not defined + + - name: lambda_info | Ensure default query value is 'all' when function name specified + lambda_info: + name: '{{ lambda_function_name }}' + register: lambda_infos_query_all + - name: lambda_info | Assert successfull retrieval of all information + assert: + that: + - lambda_infos_query_all is not failed + - lambda_infos_query_all.function | length == 1 + - lambda_infos_query_all.function[lambda_function_name].versions|length > 0 + - lambda_infos_query_all.function[lambda_function_name].function_name is defined + - lambda_infos_query_all.function[lambda_function_name].policy is defined + - lambda_infos_query_all.function[lambda_function_name].aliases is defined + - lambda_infos_query_all.function[lambda_function_name].mappings is defined + - lambda_infos_query_all.function[lambda_function_name].tags is defined + - name: lambda_info | Gather version infos for given lambda function lambda_info: name: '{{ lambda_function_name }}' From abb35523eb071ed60c4b8b4a2554b9bf3683f3af Mon Sep 17 00:00:00 2001 From: Joseph Torcasso <87090265+jatorcasso@users.noreply.github.com> Date: Tue, 24 May 2022 20:00:59 -0400 Subject: [PATCH 6/6] Update changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml Co-authored-by: Jill R <4121322+jillr@users.noreply.github.com> --- changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml b/changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml index 9b31aabd9f5..01f5ec80972 100644 --- a/changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml +++ b/changelogs/fragments/1152-lambda_info-bugfix-all-lambdas.yml @@ -1,3 +1,3 @@ bugfixes: - - lambda_info - fix bug that forces query=config when getting info for all lambdas. Now, if function name is specified, query will default to all. + - lambda_info - fix bug that forces query=config when getting info for all lambdas. Now, if function name is specified, query will default to all. This may have a performance impact when querying a large number of lambdas. If function name is not specified, query will default to config (https://github.com/ansible-collections/community.aws/pull/1152).