diff --git a/changelogs/fragments/414-ec2_instance-support-controlling-metadata-options.yml b/changelogs/fragments/414-ec2_instance-support-controlling-metadata-options.yml new file mode 100644 index 00000000000..a70b68d02e4 --- /dev/null +++ b/changelogs/fragments/414-ec2_instance-support-controlling-metadata-options.yml @@ -0,0 +1,2 @@ +minor_changes: +- ec2_instance - add support for controlling metadata options (https://github.com/ansible-collections/amazon.aws/pull/414). diff --git a/plugins/modules/ec2_instance.py b/plugins/modules/ec2_instance.py index f4138bc8ff6..fccdf794b1f 100644 --- a/plugins/modules/ec2_instance.py +++ b/plugins/modules/ec2_instance.py @@ -276,6 +276,29 @@ description: - The placement group that needs to be assigned to the instance type: str + metadata_options: + description: + - Modify the metadata options for the instance. + - See U(https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) for more information. + - The two suboptions I(http_endpoint) and I(http_tokens) are supported. + type: dict + version_added: 2.0.0 + suboptions: + http_endpoint: + description: + - Enables or disables the HTTP metadata endpoint on instances. + - If specified a value of disabled, metadata of the instance will not be accessible. + choices: [enabled, disabled] + default: enabled + type: str + http_tokens: + description: + - Set the state of token usage for instance metadata requests. + - If the state is optional (v1 and v2), instance metadata can be retrieved with or without a signed token header on request. + - If the state is required (v2), a signed token header must be sent with any instance metadata retrieval requests. + choices: [optional, required] + default: optional + type: str extends_documentation_fragment: - amazon.aws.aws @@ -385,6 +408,17 @@ tags: Env: "eni_on" instance_type: t2.micro +- name: start an instance with metadata options + amazon.aws.ec2_instance: + name: "public-metadataoptions-instance" + vpc_subnet_id: subnet-5calable + instance_type: t3.small + image_id: ami-123456 + tags: + Environment: Testing + metadata_options: + http_endpoint: enabled + http_tokens: optional ''' RETURN = ''' @@ -1195,6 +1229,12 @@ def build_top_level_options(params): spec['CpuOptions'] = {} spec['CpuOptions']['ThreadsPerCore'] = params.get('cpu_options').get('threads_per_core') spec['CpuOptions']['CoreCount'] = params.get('cpu_options').get('core_count') + if params.get('metadata_options'): + spec['MetadataOptions'] = {} + spec['MetadataOptions']['HttpEndpoint'] = params.get( + 'metadata_options').get('http_endpoint') + spec['MetadataOptions']['HttpTokens'] = params.get( + 'metadata_options').get('http_tokens') return spec @@ -1737,6 +1777,9 @@ def main(): instance_ids=dict(default=[], type='list', elements='str'), network=dict(default=None, type='dict'), volumes=dict(default=None, type='list', elements='dict'), + metadata_options=dict(type='dict', options=dict( + http_endpoint=dict(type='str', choices=['enabled', 'disabled'], default='enabled'), + http_tokens=dict(type='str', choices=['optional', 'required'], default='optional'))), ) # running/present are synonyms # as are terminated/absent diff --git a/tests/integration/targets/ec2_instance/inventory b/tests/integration/targets/ec2_instance/inventory index 1513f3f40e4..bca50fcbb00 100644 --- a/tests/integration/targets/ec2_instance/inventory +++ b/tests/integration/targets/ec2_instance/inventory @@ -4,6 +4,7 @@ version_fail_wrapper ebs_optimized block_devices cpu_options +metadata_options default_vpc_tests external_resource_attach instance_no_wait diff --git a/tests/integration/targets/ec2_instance/roles/ec2_instance/tasks/metadata_options.yml b/tests/integration/targets/ec2_instance/roles/ec2_instance/tasks/metadata_options.yml new file mode 100644 index 00000000000..0b9ac484a1a --- /dev/null +++ b/tests/integration/targets/ec2_instance/roles/ec2_instance/tasks/metadata_options.yml @@ -0,0 +1,64 @@ +- block: + - name: "create t3.nano instance with metadata_options" + ec2_instance: + state: present + name: "{{ resource_prefix }}-test-t3nano-enabled-required" + image_id: "{{ ec2_ami_image }}" + tags: + TestId: "{{ ec2_instance_tag_TestId }}" + vpc_subnet_id: "{{ testing_subnet_a.subnet.id }}" + instance_type: t3.nano + metadata_options: + http_endpoint: enabled + http_tokens: required + wait: false + register: instance_creation + + - name: "instance with metadata_options created with the right options" + assert: + that: + - instance_creation is success + - instance_creation is changed + - "'{{ instance_creation.spec.MetadataOptions.HttpEndpoint }}' == 'enabled'" + - "'{{ instance_creation.spec.MetadataOptions.HttpTokens }}' == 'required'" + + - name: "modify metadata_options on existing instance" + ec2_instance: + state: present + name: "{{ resource_prefix }}-test-t3nano-enabled-required" + image_id: "{{ ec2_ami_image }}" + tags: + TestId: "{{ ec2_instance_tag_TestId }}" + vpc_subnet_id: "{{ testing_subnet_a.subnet.id }}" + instance_type: t3.nano + metadata_options: + http_endpoint: enabled + http_tokens: optional + wait: false + register: metadata_options_update + ignore_errors: yes + + - name: "fact presented ec2 instance" + ec2_instance_info: + filters: + "tag:Name": "{{ resource_prefix }}-test-t3nano-enabled-required" + register: presented_instance_fact + + - name: "modify metadata_options has no effect on existing instance" + assert: + that: + - metadata_options_update is success + - metadata_options_update is not changed + - "{{ presented_instance_fact.instances | length }} > 0" + - "'{{ presented_instance_fact.instances.0.state.name }}' in ['running','pending']" + - "'{{ presented_instance_fact.instances.0.metadata_options.http_endpoint }}' == 'enabled'" + - "'{{ presented_instance_fact.instances.0.metadata_options.http_tokens }}' == 'required'" + + always: + - name: "Terminate metadata_options instances" + ec2_instance: + state: absent + filters: + "tag:TestId": "{{ ec2_instance_tag_TestId }}" + wait: yes + ignore_errors: yes