Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ec2_metadata_facts - fix AttributeError when running on older managed hosts #1359

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelogs/fragments/1358-ec2_metadata_facts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bugfixes:
- ec2_metadata_facts - fix ``AttributeError`` when running the ec2_metadata_facts module on Python 2 managed nodes
(https://github.com/ansible-collections/amazon.aws/issues/1358).
10 changes: 9 additions & 1 deletion plugins/modules/ec2_metadata_facts.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,14 @@

socket.setdefaulttimeout(5)

# The ec2_metadata_facts module is a special case, while we generally dropped support for Python < 3.6
# this module doesn't depend on the SDK and still has valid use cases for folks working with older
# OSes.
try:
json_decode_error = json.JSONDecodeError
except AttributeError:
json_decode_error = ValueError


class Ec2Metadata:
ec2_metadata_token_uri = 'http://169.254.169.254/latest/api/token'
Expand Down Expand Up @@ -543,7 +551,7 @@ def fetch(self, uri, recurse=True):
self._data['%s' % (new_uri)] = content
for (key, value) in json_dict.items():
self._data['%s:%s' % (new_uri, key.lower())] = value
except (json.JSONDecodeError, AttributeError):
except (json_decode_error, AttributeError):
self._data['%s' % (new_uri)] = content # not a stringified JSON string

def fix_invalid_varnames(self, data):
Expand Down
40 changes: 39 additions & 1 deletion tests/integration/targets/ec2_metadata_facts/playbooks/setup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@
subnet_cidr: '10.{{ 256 | random(seed=vpc_seed) }}.32.0/24'

tasks:
- set_fact:
# As lookup plugins don't have access to module_defaults
connection_args:
region: "{{ aws_region }}"
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
aws_session_token: "{{ security_token | default(omit) }}"

- include_role:
name: '../setup_sshkey'
Expand Down Expand Up @@ -126,13 +133,39 @@
tags:
snake_case_key: a_snake_case_value
camelCaseKey: aCamelCaseValue
wait: True
register: ec2_instance
vars:
ansible_python_interpreter: "{{ botocore_virtualenv_interpreter }}"

- set_fact:
ec2_ami_id_py2: "{{ lookup('aws_ssm', '/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2', **connection_args) }}"
ec2_ami_ssh_user_py2: "ec2-user"

- name: Create an instance to test with using Python 2
ec2_instance:
state: running
name: "{{ resource_prefix }}-ec2-metadata-facts-py2"
image_id: "{{ ec2_ami_id_py2 }}"
vpc_subnet_id: "{{ vpc_subnet_id }}"
security_group: "{{ vpc_sg_id }}"
instance_type: t2.micro
key_name: "{{ ec2_key_name }}"
network:
assign_public_ip: true
delete_on_termination: true
metadata_options:
instance_metadata_tags: enabled
tags:
snake_case_key: a_snake_case_value
camelCaseKey: aCamelCaseValue
wait: True
register: ec2_instance_py2
vars:
ansible_python_interpreter: "{{ botocore_virtualenv_interpreter }}"

- set_fact:
ec2_instance_id: "{{ ec2_instance.instances[0].instance_id }}"
ec2_instance_id_py2: "{{ ec2_instance_py2.instances[0].instance_id }}"

- name: Create inventory file
template:
Expand All @@ -143,3 +176,8 @@
port: 22
host: '{{ ec2_instance.instances[0].public_ip_address }}'
timeout: 1200

- wait_for:
port: 22
host: '{{ ec2_instance_py2.instances[0].public_ip_address }}'
timeout: 1200
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
state: absent
instance_ids:
- "{{ ec2_instance_id }}"
- "{{ ec2_instance_id_py2 }}"
wait: True
ignore_errors: true
retries: 5
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
[testhost]
[testhost_py3]
"{{ ec2_instance.instances[0].public_ip_address }}"

[testhost_py2]
"{{ ec2_instance_py2.instances[0].public_ip_address }}"

[testhost:children]
testhost_py3
testhost_py2

[testhost:vars]
ansible_user={{ ec2_ami_ssh_user }}
ansible_ssh_private_key_file="{{ sshkey }}"
ansible_python_interpreter=/usr/bin/env python

[testhost_py3:vars]
ansible_user="{{ ec2_ami_ssh_user }}"
image_id="{{ ec2_ami_id }}"

[testhost_py2:vars]
ansible_user="{{ ec2_ami_ssh_user_py2 }}"
image_id="{{ ec2_ami_id_py2 }}"

[all:vars]
# Template vars that will need to be used in used in tests and teardown
vpc_id="{{ vpc_id }}"
Expand All @@ -16,5 +30,5 @@ vpc_igw="{{ vpc_igw_id }}"
vpc_route_table_id="{{ vpc_route_table_id }}"
ec2_key_name="{{ ec2_key_name }}"
availability_zone="{{ availability_zone }}"
image_id="{{ ec2_ami_id }}"
ec2_instance_id="{{ ec2_instance_id }}"
ec2_instance_id_py2="{{ ec2_instance_id_py2 }}"