# Shortcut for making Ansible groups from EC2 tags

**URL:** <https://forum.ansible.com/t/shortcut-for-making-ansible-groups-from-ec2-tags/17078>\
**Category:** Ansible Project\
**Tags:** ubuntu\
**Created:** [December 16, 2014, 6:45pm UTC](https://forum.ansible.com/t/shortcut-for-making-ansible-groups-from-ec2-tags/17078 "2014-12-16T18:45:10Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Quentin\_Stafford-Fra](https://avatars.discourse-cdn.com/v4/letter/q/b2d939/32.png) [@Quentin\_Stafford-Fra](https://forum.ansible.com/u/Quentin_Stafford-Fra)\
**Post date:** [December 16, 2014, 6:45pm UTC](https://forum.ansible.com/t/shortcut-for-making-ansible-groups-from-ec2-tags/17078/1 "2014-12-16T18:45:10Z")

</div>

I spent a long time trying to get this to work, and eventually managed it, so just in case it’s useful for anyone else…

I wanted to tag my EC2 instances with, say ‘webserver: True’ and have them then appear in the ‘webserver’ host group locally, but I wanted to do it as a general case, without having to write special code for every group.

The ec2.py inventory script will put each host into a group called ‘ec2’ and also, for example, into ‘tag\_webserver\_True’.

So this is what I did next:

> * * *
> 
> - hosts: ec2
> 
> remote\_user: ubuntu
> 
> serial: 1
> 
> tasks:
> 
> - name: Add hosts in EC2 tag groups to local groups
> 
> local\_action: add\_host
> 
> name={{inventory\_hostname}}
> 
> groupname={{item[4:-5]}}
> 
> when: item.startswith(‘tag\_’) and item.endswith(‘\_True’) and (inventory\_hostname in groups[item])
> 
> with\_items: group\_names

It took me a couple of hours playing with all sorts of variations on this theme to realise that the **really important bit is to include ‘serial: 1’.**

Adding things to groups using add\_host _does not work reliably_ if there are multiple hosts being processed simultaneously. You will probably find that a single host gets added to the group but no more.

This, however, seems to work fine, and can easily be included in playbooks where it will be ignored if you’re not using any EC2 hosts.

Hope that’s useful for someone!

---

<div class="post-metadata">

**Author:** ![Michael\_Peters](https://avatars.discourse-cdn.com/v4/letter/m/c2a13f/32.png) [@Michael\_Peters](https://forum.ansible.com/u/Michael_Peters)\
**Post date:** [December 16, 2014, 8:15pm UTC](https://forum.ansible.com/t/shortcut-for-making-ansible-groups-from-ec2-tags/17078/2 "2014-12-16T20:15:39Z")

</div>

Another option I've used is to modify the ec2.py that comes in the  
ansible sample inventories. For something simple like this it's not a  
big deal, but when you start having more custom groups based on tags  
and you don't want the ec2\_tag\_ prefix on every group (or are mixing  
EC2 and non-aws instances), it starts to become more of a pain. It's a  
pretty simple python script that's easy to modify. Once we made that  
small leap our playbooks became a lot clearer imo.

---

<div class="post-metadata">

**Author:** ![Quentin\_Stafford-Fra](https://avatars.discourse-cdn.com/v4/letter/q/b2d939/32.png) [@Quentin\_Stafford-Fra](https://forum.ansible.com/u/Quentin_Stafford-Fra)\
**Post date:** [December 17, 2014, 2:22pm UTC](https://forum.ansible.com/t/shortcut-for-making-ansible-groups-from-ec2-tags/17078/3 "2014-12-17T14:22:05Z")

</div>

I added a note to the add\_host docs about this and posted a pull request, but it was rejected on the basis that:

- add\_host is non persistent, it only adds hosts to the in memory inventory for the current run, also it bypasses the host loop so it does NOT run on multiple hosts. Due to it’s nature it makes little sense to run other than on the master.  
which all makes sense, but I think then that a note in the docs to indicate **that** would be helpful! How are we to know, otherwise? More information is always good.

It’s not just when running on multiple hosts that there’s a problem, by the way: it also doesn’t work if you use local\_action or delegate to localhost when the target for the play includes multiple hosts.

Just my tuppence-worth.

---

<div class="post-metadata">

**Author:** ![Quentin\_Stafford-Fra](https://avatars.discourse-cdn.com/v4/letter/q/b2d939/32.png) [@Quentin\_Stafford-Fra](https://forum.ansible.com/u/Quentin_Stafford-Fra)\
**Post date:** [December 17, 2014, 2:37pm UTC](https://forum.ansible.com/t/shortcut-for-making-ansible-groups-from-ec2-tags/17078/4 "2014-12-17T14:37:48Z")

</div>

Ah - and Matt Martz has pointed me at this pull request which says a bit more than mine did. Good stuff…!

[https://github.com/sivel/ansible-modules-core/commit/dcd6ab735abba283cba22d345e233b57ac47f8ac](https://github.com/sivel/ansible-modules-core/commit/dcd6ab735abba283cba22d345e233b57ac47f8ac)

---

<div class="post-metadata">

**Author:** ![George\_Chigrichenko](https://avatars.discourse-cdn.com/v4/letter/g/8c91f0/32.png) [@George\_Chigrichenko](https://forum.ansible.com/u/George_Chigrichenko)\
**Post date:** [April 28, 2016, 7:57pm UTC](https://forum.ansible.com/t/shortcut-for-making-ansible-groups-from-ec2-tags/17078/5 "2016-04-28T19:57:37Z")

</div>

Quentin, really useful post.  
However I had to add two things in order to skip the errors on hosts that were unreachable. I think this might be helpful in case they are not started and you would like to start them later from the ec2 module.  
Tried to suppress the stuff using configuration variables

host\_key\_checking=True

display\_skipped\_hosts=True

but that still getting the  
PLAY \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

messages, which is really annoying.  
It is going to be a good idea to include this playbook in the beginning so other scripts can reuse the dynamic group(s).

- hosts: ec2  
serial: 1

**gather\_facts: false**  
**ignore\_errors: yes**

tasks:

- name: Add host(s) from EC2 tag group to Controller group  
local\_action: add\_host  
name={{inventory\_hostname}}  
groupname=‘Put\_your\_new\_dynamic\_group\_name\_here’  
#when: item.startswith(‘tag\_Name\_’) and item.endswith(_your\_name\_variable_) and (inventory\_hostname in groups[item]) #optional loose matching  
when: item == ‘tag\_Name\_’ + _your\_name\_variable_ and (inventory\_hostname in groups[item])  
with\_items: group\_names

---

<div class="post-metadata">

**Author:** ![Quentin\_Stafford-Fra](https://avatars.discourse-cdn.com/v4/letter/q/b2d939/32.png) [@Quentin\_Stafford-Fra](https://forum.ansible.com/u/Quentin_Stafford-Fra)\
**Post date:** [April 30, 2016, 7:58am UTC](https://forum.ansible.com/t/shortcut-for-making-ansible-groups-from-ec2-tags/17078/6 "2016-04-30T07:58:38Z")

</div>

Ah - interesting idea. I tend to have separate Python scripts to stop and start servers, mostly for this reason. But it would be nice to do everything with Ansible…

---

<div class="post-metadata">

**Author:** ![ddrake2012](https://avatars.discourse-cdn.com/v4/letter/d/9fc348/32.png) [@ddrake2012](https://forum.ansible.com/u/ddrake2012)\
**Post date:** [December 8, 2017, 10:34pm UTC](https://forum.ansible.com/t/shortcut-for-making-ansible-groups-from-ec2-tags/17078/7 "2017-12-08T22:34:58Z")

</div>

Thanks for the posts, very helpful. A couple things a year and a half later:

The dynamic inventory script (ec2.py) now returns ec2\_tag\_Name so for a lot of things you can use the when parameter to say something like “when: ec2\_tag\_Name == your\_tag\_name”

However, this doesn’t work if you want to use run\_once and you get lucky enough to have the first instance in the play hosts (ansible\_play\_batch[0]) not match this when conditional so the task is ran once but skipped. I came up with two solutions that I detailed here:[https://groups.google.com/d/msg/ansible-project/iHRjSvoavww/WDvX\_zmAAQAJ](https://groups.google.com/d/msg/ansible-project/iHRjSvoavww/WDvX_zmAAQAJ)

In general though, I wonder if it might just be easier/possible/cleaner(?) to use the ec2\_instance\_facts module, create in-memory groups using add\_host, and then use delegate\_to with the groups, running everything on localhost.

Dave
