For many of my AWS-specific Ansible playbooks, I need to have some operations (e.g. AWS inspector agent, or special information lookups) run when the playbook is run inside AWS, but not run if it's being run on a local test VM or in my CI environment.
In the past, I would set up a global playbook variable like aws_environment: False
, and set it manually to True
when running the playbook against live AWS EC2 instances. But managing vars like aws_environment
can get tiresome because if you forget to set it to the correct value, a playbook run can fail.
So instead, I'm now using the existence of AWS' internal instance metadata URL as a check for whether the playbook is being run inside AWS:
- hosts: all
pre_tasks:
- name: Check if inside AWS.
uri:
url: http://169.254.169.254/latest/meta-data
timeout: 2
register: aws_uri_check
failed_when: False
- set_fact:
is_aws_environment: "{{ aws_uri_check.status == 200 }}"
That way, I can use when: is_aws_environment
as the condition for any AWS-specific tasks, e.g.:
tasks:
- include: aws-inspector.yml
when: is_aws_environment
It's possible the http://169.254.169.254/latest/meta-data
may return a 200
inside other infrastructure environments, but it doesn't seem to do so in DigitalOcean, Linode, or other hosting environments I currently use, so this is a bit safer than relying on an instance hostname (which I know many people do).
Comments
Hi Jeff,
Thanks for your post. This is something I had to tackle recently and (since this post was not written yet :) ) I settled for using the bios version of an instance to check if the playbook is running inside AWS or not:
"'amazon' in ansible_bios_version"
Do you have thoughts on this approach?
Thank you,
Mark
Not all EC2 hosts have ansible_bios_version fact.
This is exactly what I was looking for. However, on Hetzner Cloud this also gives a http 200 status.
A check on http://169.254.169.254/latest/meta-data/ami-id looks a more reliable way to identify AWS though.
There are better options to check this
"ansible_system_vendor": "Amazon EC2",
That assumes that
gather_facts
is enabled, but it can be a helpful way too.