# Roles with multiple OS versions

**URL:** <https://forum.ansible.com/t/roles-with-multiple-os-versions/16033>\
**Category:** Ansible Project\
**Created:** [August 25, 2014, 3:00pm UTC](https://forum.ansible.com/t/roles-with-multiple-os-versions/16033 "2014-08-25T15:00:40Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Anand\_Buddhdev2](https://avatars.discourse-cdn.com/v4/letter/a/48db29/32.png) [@Anand\_Buddhdev2](https://forum.ansible.com/u/Anand_Buddhdev2)\
**Post date:** [August 25, 2014, 3:00pm UTC](https://forum.ansible.com/t/roles-with-multiple-os-versions/16033/1 "2014-08-25T15:00:40Z")

</div>

Hello ansible folk,

I have a custom role called “firewall” that I currently use with CentOS 6. It managed the ip(6)tables rules files and reloads iptables as needed.

Now I have a CentOS 7 server, on which firewalling is done by firewalld, so all my tasks and handlers and everything has to change. I was looking for a way to use the same role to work with both CentOS 6 and 7. I wanted to have:

roles/  
firewall/  
tasks/  
main.yml  
CentOS6.yml  
CentOS7.yml

And then in main.yml, have something like:

- include: ‘{{ansible\_distribution}}{{ansible\_distribution\_major\_version}}.yml’

However, this is not allowed, as I discovered in the documentation.

Is there any way I can keep a single role, and make it work simply with both OS versions?

Regards,

Anand

---

<div class="post-metadata">

**Author:** ![Tom\_Bamford1](https://avatars.discourse-cdn.com/v4/letter/t/43a26b/32.png) [@Tom\_Bamford1](https://forum.ansible.com/u/Tom_Bamford1)\
**Post date:** [August 25, 2014, 4:23pm UTC](https://forum.ansible.com/t/roles-with-multiple-os-versions/16033/2 "2014-08-25T16:23:09Z")

</div>

I approach this with conditional includes

- include: centos6.yml  
&nbsp;&nbsp;when: ansible\_distribution == "CentOS" and  
ansible\_distribution\_version|int == 6  
- include: centos7.yml  
&nbsp;&nbsp;when: ansible\_distribution == "CentOS" and  
ansible\_distribution\_version|int == 7

The 'int' filter may not actually be required. It might look inelegant but  
it's very clear to read. The only issue for me is that ansible-playbook  
displays a skipped status for each task it doesn't run for a host instead  
of just ignoring them.

---

<div class="post-metadata">

**Author:** ![Anand\_Buddhdev2](https://avatars.discourse-cdn.com/v4/letter/a/48db29/32.png) [@Anand\_Buddhdev2](https://forum.ansible.com/u/Anand_Buddhdev2)\
**Post date:** [August 25, 2014, 4:32pm UTC](https://forum.ansible.com/t/roles-with-multiple-os-versions/16033/3 "2014-08-25T16:32:32Z")

</div>

Hi Tom,

> 

Thanks for your suggestion. That does work, but as you said, ansible still evaluates and skips all the tasks if the when: condition evaluates to false. With a long task list that results in a lot of unnecessary skips.

I’m hoping the developers have some clever ideas to solve this.

Anand

---

<div class="post-metadata">

**Author:** ![Tomasz\_Kontusz](https://avatars.discourse-cdn.com/v4/letter/t/bc79bd/32.png) [@Tomasz\_Kontusz](https://forum.ansible.com/u/Tomasz_Kontusz)\
**Post date:** [August 25, 2014, 4:43pm UTC](https://forum.ansible.com/t/roles-with-multiple-os-versions/16033/4 "2014-08-25T16:43:41Z")

</div>

Anand Buddhdev \<arhbkb@gmail.com\> napisał:

> Hi Tom,
> 
> The only issue for me is that ansible-playbook displays a skipped  
> status
> 
> > for each task it doesn't run for a host instead of just ignoring
> 
> them.
> 
> > 
> 
> Thanks for your suggestion. That does work, but as you said, ansible  
> still  
> evaluates and skips all the tasks if the when: condition evaluates to  
> false. With a long task list that results in a lot of unnecessary  
> skips.
> 
> I'm hoping the developers have some clever ideas to solve this.
> 
> Anand

Another way to do this is to split your role in two, and have separate plays for CentOS 6 and 7. You can still have Ansible detect which host should run which play by grouping them with group\_by:

- hosts: all  
&nbsp;&nbsp;tasks:  
&nbsp;&nbsp;- group\_by: key=CentOS\_{{ansible\_distribution\_version}}

- hosts: CentOS\_7  
&nbsp;&nbsp;roles:  
&nbsp;&nbsp;- firewalld

- hosts: all  
&nbsp;&nbsp;roles:  
&nbsp;&nbsp;- firewall\_iptables

---

<div class="post-metadata">

**Author:** ![Tomasz\_Kontusz](https://avatars.discourse-cdn.com/v4/letter/t/bc79bd/32.png) [@Tomasz\_Kontusz](https://forum.ansible.com/u/Tomasz_Kontusz)\
**Post date:** [August 25, 2014, 4:45pm UTC](https://forum.ansible.com/t/roles-with-multiple-os-versions/16033/5 "2014-08-25T16:45:00Z")

</div>

Tomasz Kontusz \<tomasz.kontusz@gmail.com\> napisał:

> Anand Buddhdev \<arhbkb@gmail.com\> napisał:
> 
> > Hi Tom,
> > 
> > The only issue for me is that ansible-playbook displays a skipped  
> > status
> > 
> > > for each task it doesn't run for a host instead of just ignoring
> > 
> > them.
> > 
> > > 
> > 
> > Thanks for your suggestion. That does work, but as you said, ansible  
> > still  
> > evaluates and skips all the tasks if the when: condition evaluates to  
> > false. With a long task list that results in a lot of unnecessary  
> > skips.
> > 
> > I'm hoping the developers have some clever ideas to solve this.
> > 
> > Anand
> 
> Another way to do this is to split your role in two, and have separate  
> plays for CentOS 6 and 7. You can still have Ansible detect which host  
> should run which play by grouping them with group\_by:
> 
> - hosts: all  
> tasks:  
> - group\_by: key=CentOS\_{{ansible\_distribution\_version}}
> 
> - hosts: CentOS\_7  
> roles:  
> - firewalld
> 
> - hosts: all

Ugh, hosts: CentOS\_6 obviously 🙂

---

<div class="post-metadata">

**Author:** ![Anand\_Buddhdev2](https://avatars.discourse-cdn.com/v4/letter/a/48db29/32.png) [@Anand\_Buddhdev2](https://forum.ansible.com/u/Anand_Buddhdev2)\
**Post date:** [August 25, 2014, 4:56pm UTC](https://forum.ansible.com/t/roles-with-multiple-os-versions/16033/6 "2014-08-25T16:56:39Z")

</div>

Hi Tomasz,

> Another way to do this is to split your role in two, and have separate plays for CentOS 6 and 7. You can still have Ansible detect which host should run which play by grouping them with group\_by:

Thanks for this. I tried it and it also works. It does mean that every ansible run always shows “changed=1” even if nothing ever changed, because group\_by is not idempotent. This bothers the idempotence purist in me 🙂

Anand

---

<div class="post-metadata">

**Author:** ![Tomasz\_Kontusz](https://avatars.discourse-cdn.com/v4/letter/t/bc79bd/32.png) [@Tomasz\_Kontusz](https://forum.ansible.com/u/Tomasz_Kontusz)\
**Post date:** [August 25, 2014, 5:20pm UTC](https://forum.ansible.com/t/roles-with-multiple-os-versions/16033/7 "2014-08-25T17:20:10Z")

</div>

Anand Buddhdev \<arhbkb@gmail.com\> napisał:

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [August 25, 2014, 5:31pm UTC](https://forum.ansible.com/t/roles-with-multiple-os-versions/16033/8 "2014-08-25T17:31:42Z")

</div>

“Thanks for your suggestion. That does work, but as you said, ansible still evaluates and skips all the tasks if the when: condition evaluates to false. With a long task list that results in a lot of unnecessary skips.”

You can turn off the skipped output in ansible.cfg.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [August 25, 2014, 5:32pm UTC](https://forum.ansible.com/t/roles-with-multiple-os-versions/16033/9 "2014-08-25T17:32:56Z")

</div>

It’s entirely idempotent (which is a confusing word BTW) – it doesn’t make any changes when no changes need to be made.

F(x) = F(F(x))

However, it does return a changed boolean because it doesn’t track when the size of the group changes. there’s a ticket about that.

Attaching a handler to a group\_by, however, is very uncommon.

---

<div class="post-metadata">

**Author:** ![Anand\_Buddhdev2](https://avatars.discourse-cdn.com/v4/letter/a/48db29/32.png) [@Anand\_Buddhdev2](https://forum.ansible.com/u/Anand_Buddhdev2)\
**Post date:** [August 25, 2014, 7:30pm UTC](https://forum.ansible.com/t/roles-with-multiple-os-versions/16033/10 "2014-08-25T19:30:21Z")

</div>

Hey Tomasz,

> > Thanks for this. I tried it and it also works. It does mean that every  
> > ansible run always shows "changed=1" even if nothing ever changed,  
> > because  
> > group\_by is not idempotent. This bothers the idempotence purist in me  
> > 🙂
> 
> Oh, it's as idempotent as you can get. But you are right, it's a pretty useless change notification - you can just put changed\_when: no on it

Ok, perfect! This does the trick! I like this approach, and I'm going  
to use it to dynamically create a CentOS6 and a CentOS7 group, and  
apply roles selectively to them. I'll probably just create separate  
"firewall\_c7" and "firewall\_c6" roles.

Regards,

Anand
