diff --git a/changelogs/fragments/1239-lambda_info-return_list.yml b/changelogs/fragments/1239-lambda_info-return_list.yml new file mode 100644 index 00000000000..26710c0d132 --- /dev/null +++ b/changelogs/fragments/1239-lambda_info-return_list.yml @@ -0,0 +1,8 @@ +minor_changes: +- lambda_info - add return key ``functions`` which returns a list of dictionaries instead of the previously returned + ``function``, which returned a dictionary of dictionaries (https://github.com/ansible-collections/community.aws/pull/1239). +- lambda_info - now returns basic configuration information of each lambda function, regardless of query (https://github.com/ansible-collections/community.aws/pull/1239). + +deprecated_features: +- lambda_info - The ``function`` return key returns a dictionary of dictionaries and has been deprecated. In a release after 2025-01-01, this key will + be removed in favor of ``functions``, which returns a list of dictionaries (https://github.com/ansible-collections/community.aws/pull/1239). diff --git a/plugins/modules/lambda_info.py b/plugins/modules/lambda_info.py index 1ad2749c5f8..e3d00ab08cc 100644 --- a/plugins/modules/lambda_info.py +++ b/plugins/modules/lambda_info.py @@ -71,16 +71,197 @@ RETURN = ''' --- function: - description: lambda function list + description: + - lambda function list. + - C(function) has been deprecated in will be removed in the next major release after 2025-01-01. returned: success type: dict function.TheName: - description: lambda function information, including event, mapping, and version information + description: + - lambda function information, including event, mapping, and version information. + - C(function) has been deprecated in will be removed in the next major release after 2025-01-01. returned: success type: dict +functions: + description: List of information for each lambda function matching the query. + returned: always + type: list + elements: dict + version_added: 4.1.0 + contains: + aliases: + description: The aliases associated with the function. + returned: when C(query) is I(aliases) or I(all) + type: list + elements: str + code_sha256: + description: The SHA256 hash of the function's deployment package. + returned: success + type: str + sample: 'zOAGfF5JLFuzZoSNirUtOrQp+S341IOA3BcoXXoaIaU=' + code_size: + description: The size of the function's deployment package in bytes. + returned: success + type: int + sample: 123 + dead_letter_config: + description: The function's dead letter queue. + returned: when the function has a dead letter queue configured + type: dict + sample: { 'target_arn': arn:aws:lambda:us-east-1:123456789012:function:myFunction:1 } + contains: + target_arn: + description: The ARN of an SQS queue or SNS topic. + returned: when the function has a dead letter queue configured + type: str + sample: arn:aws:lambda:us-east-1:123456789012:function:myFunction:1 + description: + description: The function's description. + returned: success + type: str + sample: 'My function' + environment: + description: The function's environment variables. + returned: when environment variables exist + type: dict + contains: + variables: + description: Environment variable key-value pairs. + returned: when environment variables exist + type: dict + sample: {'key': 'value'} + error: + description: Error message for environment variables that could not be applied. + returned: when there is an error applying environment variables + type: dict + contains: + error_code: + description: The error code. + returned: when there is an error applying environment variables + type: str + message: + description: The error message. + returned: when there is an error applying environment variables + type: str + function_arn: + description: The function's Amazon Resource Name (ARN). + returned: on success + type: str + sample: 'arn:aws:lambda:us-east-1:123456789012:function:myFunction:1' + function_name: + description: The function's name. + returned: on success + type: str + sample: 'myFunction' + handler: + description: The function Lambda calls to begin executing your function. + returned: on success + type: str + sample: 'index.handler' + last_modified: + description: The date and time that the function was last updated, in ISO-8601 format (YYYY-MM-DDThh:mm:ssTZD). + returned: on success + type: str + sample: '2017-08-01T00:00:00.000+0000' + mappings: + description: List of configuration information for each event source mapping. + returned: when C(query) is I(all) or I(mappings) + type: list + elements: dict + contains: + uuid: + description: The AWS Lambda assigned opaque identifier for the mapping. + returned: on success + type: str + batch_size: + description: The largest number of records that AWS Lambda will retrieve from the event source at the time of invoking the function. + returned: on success + type: int + event_source_arn: + description: The ARN of the Amazon Kinesis or DyanmoDB stream that is the source of events. + returned: on success + type: str + function_arn: + description: The Lambda function to invoke when AWS Lambda detects an event on the poll-based source. + returned: on success + type: str + last_modified: + description: The UTC time string indicating the last time the event mapping was updated. + returned: on success + type: str + last_processing_result: + description: The result of the last AWS Lambda invocation of your Lambda function. + returned: on success + type: str + state: + description: The state of the event source mapping. + returned: on success + type: str + state_transition_reason: + description: The reason the event source mapping is in its current state. + returned: on success + type: str + memory_size: + description: The memory allocated to the function. + returned: on success + type: int + sample: 128 + policy: + description: The policy associated with the function. + returned: when C(query) is I(all) or I(policy) + type: dict + revision_id: + description: The latest updated revision of the function or alias. + returned: on success + type: str + sample: 'a2x9886d-d48a-4a0c-ab64-82abc005x80c' + role: + description: The function's execution role. + returned: on success + type: str + sample: 'arn:aws:iam::123456789012:role/lambda_basic_execution' + runtime: + description: The funtime environment for the Lambda function. + returned: on success + type: str + sample: 'nodejs6.10' + tracing_config: + description: The function's AWS X-Ray tracing configuration. + returned: on success + type: dict + sample: { 'mode': 'Active' } + contains: + mode: + description: The tracing mode. + returned: on success + type: str + sample: 'Active' + timeout: + description: The amount of time that Lambda allows a function to run before terminating it. + returned: on success + type: int + sample: 3 + version: + description: The version of the Lambda function. + returned: on success + type: str + sample: '1' + versions: + description: List of Lambda function versions. + returned: when C(query) is I(all) or I(versions) + type: list + elements: dict + vpc_config: + description: The function's networking configuration. + returned: on success + type: dict + sample: { + 'security_group_ids': [], + 'subnet_ids': [], + 'vpc_id': '123' + } ''' import json -import datetime import re try: @@ -101,29 +282,6 @@ def _paginate(client, function, **params): return paginator.paginate(**params).build_full_result() -def fix_return(node): - """ - fixup returned dictionary - - :param node: - :return: - """ - - if isinstance(node, datetime.datetime): - node_value = str(node) - - elif isinstance(node, list): - node_value = [fix_return(item) for item in node] - - elif isinstance(node, dict): - node_value = dict([(item, fix_return(node[item])) for item in node.keys()]) - - else: - node_value = node - - return node_value - - def alias_details(client, module, function_name): """ Returns list of aliases for a specified function. @@ -146,13 +304,12 @@ def alias_details(client, module, function_name): return camel_dict_to_snake_dict(lambda_info) -def list_lambdas(client, module): +def list_functions(client, module): """ Returns queried facts for a specified function (or all functions). :param client: AWS API client reference (boto3) :param module: Ansible module reference - :return dict: """ function_name = module.params.get('function_name') @@ -166,38 +323,40 @@ def list_lambdas(client, module): function_names = [function_info['FunctionName'] for function_info in all_function_info] query = module.params['query'] - lambdas = dict() + functions = [] + + # keep returning deprecated response (dict of dicts) until removed + all_facts = {} for function_name in function_names: - lambdas[function_name] = {} + function = {} - 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)) + # query = 'config' returns info such as FunctionName, FunctionArn, Description, etc + # these details should be returned regardless of the query + function.update(config_details(client, module, function_name)) - elif query == 'config': - lambdas[function_name].update(config_details(client, module, function_name)) + if query in ['all', 'aliases']: + function.update(alias_details(client, module, function_name)) - elif query == 'aliases': - lambdas[function_name].update(alias_details(client, module, function_name)) + if query in ['all', 'policy']: + function.update(policy_details(client, module, function_name)) - elif query == 'policy': - lambdas[function_name].update(policy_details(client, module, function_name)) + if query in ['all', 'versions']: + function.update(version_details(client, module, function_name)) - elif query == 'versions': - lambdas[function_name].update(version_details(client, module, function_name)) + if query in ['all', 'mappings']: + function.update(mapping_details(client, module, function_name)) - elif query == 'mappings': - lambdas[function_name].update(mapping_details(client, module, function_name)) + if query in ['all', 'tags']: + function.update(tags_details(client, module, function_name)) - elif query == 'tags': - lambdas[function_name].update(tags_details(client, module, function_name)) + all_facts[function['function_name']] = function - return lambdas + # add current lambda to list of lambdas + functions.append(function) + + # return info + module.exit_json(function=all_facts, functions=functions, changed=False) def config_details(client, module, function_name): @@ -357,14 +516,15 @@ def main(): client = module.client('lambda', retry_decorator=AWSRetry.jittered_backoff()) - all_facts = fix_return(list_lambdas(client, module)) - - results = dict(function=all_facts, changed=False) - - if module.check_mode: - results['msg'] = 'Check mode set but ignored for fact gathering only.' + # Deprecate previous return key of `function`, as it was a dict of dicts, as opposed to a list of dicts + module.deprecate( + "The returned key 'function', which returned a dictionary of dictionaries, is deprecated and will be replaced by 'functions'," + " which returns a list of dictionaries. Both keys are returned for now.", + date='2025-01-01', + collection_name='community.aws' + ) - module.exit_json(**results) + list_functions(client, module) if __name__ == '__main__': diff --git a/tests/integration/targets/lambda/tasks/main.yml b/tests/integration/targets/lambda/tasks/main.yml index 96f3aec1506..8ebb3910754 100644 --- a/tests/integration/targets/lambda/tasks/main.yml +++ b/tests/integration/targets/lambda/tasks/main.yml @@ -264,17 +264,17 @@ 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 == lambda_python_runtime - - 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 == lambda_python_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].tags is defined + - lambda_infos_all.functions | length > 0 + - lambda_infos_all.functions[0].function_name == lambda_function_name + - lambda_infos_all.functions[0].runtime == lambda_python_runtime + - lambda_infos_all.functions[0].description == "" + - lambda_infos_all.functions[0].function_arn is defined + - lambda_infos_all.functions[0].handler == lambda_python_handler + - lambda_infos_all.functions[0].versions is defined + - lambda_infos_all.functions[0].aliases is defined + - lambda_infos_all.functions[0].policy is defined + - lambda_infos_all.functions[0].mappings is defined + - lambda_infos_all.functions[0].tags is defined - name: lambda_info | Ensure default query value is 'config' when function name omitted lambda_info: @@ -284,17 +284,17 @@ 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 == lambda_python_runtime - - 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 == lambda_python_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 + - lambda_infos_query_config.functions | length > 0 + - lambda_infos_query_config.functions[0].function_name == lambda_function_name + - lambda_infos_query_config.functions[0].runtime == lambda_python_runtime + - lambda_infos_query_config.functions[0].description == "" + - lambda_infos_query_config.functions[0].function_arn is defined + - lambda_infos_query_config.functions[0].handler == lambda_python_handler + - lambda_infos_query_config.functions[0].versions is not defined + - lambda_infos_query_config.functions[0].aliases is not defined + - lambda_infos_query_config.functions[0].policy is not defined + - lambda_infos_query_config.functions[0].mappings is not defined + - lambda_infos_query_config.functions[0].tags is not defined - name: lambda_info | Ensure default query value is 'all' when function name specified lambda_info: @@ -304,13 +304,13 @@ 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 + - lambda_infos_query_all.functions | length == 1 + - lambda_infos_query_all.functions[0].versions|length > 0 + - lambda_infos_query_all.functions[0].function_name is defined + - lambda_infos_query_all.functions[0].policy is defined + - lambda_infos_query_all.functions[0].aliases is defined + - lambda_infos_query_all.functions[0].mappings is defined + - lambda_infos_query_all.functions[0].tags is defined - name: lambda_info | Gather version infos for given lambda function lambda_info: @@ -321,13 +321,13 @@ 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 - - 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 + - lambda_infos_versions.functions | length == 1 + - lambda_infos_versions.functions[0].versions|length > 0 + - lambda_infos_versions.functions[0].function_name == lambda_function_name + - lambda_infos_versions.functions[0].policy is undefined + - lambda_infos_versions.functions[0].aliases is undefined + - lambda_infos_versions.functions[0].mappings is undefined + - lambda_infos_versions.functions[0].tags is undefined - name: lambda_info | Gather config infos for given lambda function lambda_info: @@ -338,14 +338,14 @@ 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 - - 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 + - lambda_infos_config.functions | length == 1 + - lambda_infos_config.functions[0].function_name == lambda_function_name + - lambda_infos_config.functions[0].description is defined + - lambda_infos_config.functions[0].versions is undefined + - lambda_infos_config.functions[0].policy is undefined + - lambda_infos_config.functions[0].aliases is undefined + - lambda_infos_config.functions[0].mappings is undefined + - lambda_infos_config.functions[0].tags is undefined - name: lambda_info | Gather policy infos for given lambda function lambda_info: @@ -356,13 +356,13 @@ 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 - - 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 + - lambda_infos_policy.functions | length == 1 + - lambda_infos_policy.functions[0].policy is defined + - lambda_infos_policy.functions[0].versions is undefined + - lambda_infos_policy.functions[0].function_name == lambda_function_name + - lambda_infos_policy.functions[0].aliases is undefined + - lambda_infos_policy.functions[0].mappings is undefined + - lambda_infos_policy.functions[0].tags is undefined - name: lambda_info | Gather aliases infos for given lambda function lambda_info: @@ -373,13 +373,13 @@ 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 - - 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 + - lambda_infos_aliases.functions | length == 1 + - lambda_infos_aliases.functions[0].aliases is defined + - lambda_infos_aliases.functions[0].versions is undefined + - lambda_infos_aliases.functions[0].function_name == lambda_function_name + - lambda_infos_aliases.functions[0].policy is undefined + - lambda_infos_aliases.functions[0].mappings is undefined + - lambda_infos_aliases.functions[0].tags is undefined - name: lambda_info | Gather mappings infos for given lambda function lambda_info: @@ -390,13 +390,13 @@ 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 - - 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 + - lambda_infos_mappings.functions | length == 1 + - lambda_infos_mappings.functions[0].mappings is defined + - lambda_infos_mappings.functions[0].versions is undefined + - lambda_infos_mappings.functions[0].function_name == lambda_function_name + - lambda_infos_mappings.functions[0].aliases is undefined + - lambda_infos_mappings.functions[0].policy is undefined + - lambda_infos_mappings.functions[0].tags is undefined # More Lambda update tests - name: test state=present with all nullable variables explicitly set to null