# loops and variables

**URL:** <https://forum.ansible.com/t/loops-and-variables/15302>\
**Category:** Ansible Project\
**Created:** [May 22, 2014, 12:21pm UTC](https://forum.ansible.com/t/loops-and-variables/15302 "2014-05-22T12:21:35Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Makimoto\_Marakatti](https://avatars.discourse-cdn.com/v4/letter/m/e19adc/32.png) [@Makimoto\_Marakatti](https://forum.ansible.com/u/Makimoto_Marakatti)\
**Post date:** [May 22, 2014, 12:21pm UTC](https://forum.ansible.com/t/loops-and-variables/15302/1 "2014-05-22T12:21:35Z")

</div>

Hi all

Could someone lend me a hand to figure looping over variables?

I’ve got a number of hosts which are grouped in the inventory quite strictly in a rather traditional way:

`  
dev-group1  
hostA  
hostB  
tst-group1  
hostC  
hostD  
pre-group1  
hostE  
hostF  
pro-group1  
hostG  
hostH  
dev-group2  
hostI  
hostJ  
tst-group2  
hostK  
hostL  
and so on…

`

I’m about to replace/template a great number of files in them and I’d like to have local backups first 😉  
The only requirement is that the files have to be fetched to an already established structure that mimics the inventory:

`  
/backup/dev-group1/  
/backup/tst-group1/  
etc…

`

So I made an attempt to loop over each group:

`  
$ ansible-playbook fetch\_from\_server.yml -sK --extra-vars “@fetch\_loop\_vars.yml” -v

`

fetch\_loop\_vars.yml looks like this:

`

---

<div class="post-metadata">

**Author:** ![Abhijit\_Menon-Sen2](https://avatars.discourse-cdn.com/v4/letter/a/ea5d25/32.png) [@Abhijit\_Menon-Sen2](https://forum.ansible.com/u/Abhijit_Menon-Sen2)\
**Post date:** [May 22, 2014, 12:40pm UTC](https://forum.ansible.com/t/loops-and-variables/15302/2 "2014-05-22T12:40:03Z")

</div>

This task isn't actually using a loop in the Ansible sense. You need to  
provide a list to iterate over using with\_items: or similar. For a more  
detailed explanation, see [http://docs.ansible.com/playbooks\_loops.html](http://docs.ansible.com/playbooks_loops.html)  
(it has lots of examples).

That said, I don't know the best way to iterate over the hosts in a  
subset of all your groups in quite the way you describe. Perhaps the  
examples on the following page will prove helpful:

[http://docs.ansible.com/playbooks\_variables.html#magic-variables-and-how-to-access-information-about-other-hosts](http://docs.ansible.com/playbooks_variables.html#magic-variables-and-how-to-access-information-about-other-hosts)

-- ams

---

<div class="post-metadata">

**Author:** ![Abhijit\_Menon-Sen2](https://avatars.discourse-cdn.com/v4/letter/a/ea5d25/32.png) [@Abhijit\_Menon-Sen2](https://forum.ansible.com/u/Abhijit_Menon-Sen2)\
**Post date:** [May 22, 2014, 1:04pm UTC](https://forum.ansible.com/t/loops-and-variables/15302/3 "2014-05-22T13:04:59Z")

</div>

I'm sorry, my earlier answer was short-sighted. I started thinking about  
loops because your Subject said "loop", but you were right to not use an  
Ansible loop in the first place—at least not over groups/hosts.

As I understand it, trying to write a single task that loops over groups  
and hosts isn't the way to do things in Ansible. One should write a task  
that fetches the desired files, and run it against the desired hosts by  
using the existing host-selection mechanism, as described in  
[http://docs.ansible.com/intro\_patterns.html](http://docs.ansible.com/intro_patterns.html)

So you could do something like:

&nbsp;&nbsp;&nbsp;&nbsp;- name: fetch files from the server  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fetch: src={{ item }}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dest=/backup/{{ group\_names[0] }}/{{ inventory\_hostname }}/{{ item | basename }}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with\_items:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- /root/.bash\_profile  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- /some/other/file

Note that group\_names is a list variable that contains the name of all  
groups that the current host is in. If your hosts aren't in multiple  
groups, this should not matter to you. If they are, then the backups  
will be stored only in the directory of the first group by this task.

Hope this helps.

-- ams

---

<div class="post-metadata">

**Author:** ![Makimoto\_Marakatti](https://avatars.discourse-cdn.com/v4/letter/m/e19adc/32.png) [@Makimoto\_Marakatti](https://forum.ansible.com/u/Makimoto_Marakatti)\
**Post date:** [May 22, 2014, 1:21pm UTC](https://forum.ansible.com/t/loops-and-variables/15302/4 "2014-05-22T13:21:28Z")

</div>

Thanks for the insightful answer. I’m definitely going to try this and will write here how it goes

---

<div class="post-metadata">

**Author:** ![Makimoto\_Marakatti](https://avatars.discourse-cdn.com/v4/letter/m/e19adc/32.png) [@Makimoto\_Marakatti](https://forum.ansible.com/u/Makimoto_Marakatti)\
**Post date:** [May 22, 2014, 2:57pm UTC](https://forum.ansible.com/t/loops-and-variables/15302/5 "2014-05-22T14:57:10Z")

</div>

Well it does work… but for the ‘wrong’ groups.

Let me explain:  
There’s another layer of groups in the inventory to define in which datacentre a particular host is.  
So in a group like dev-group1 we might have 2 machines in datacentre-A and other 2 hosts in datacentre-B.  
In this case I’m not interested in where a box is. I need to refer to it by it’s role. (Not the ansible role, but what it does 🙂 )

So that is why I had this arbitrary list of groups read from a variable. And that is still what I would need.  
I’m thinking to make a play to define those vars and including another one so I can use the “with\_items” construct.

If someone has come across something like this before, I would love to hear about it!

We have a number of defined groups which we need

---

<div class="post-metadata">

**Author:** ![Brian\_Coca1](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@Brian\_Coca1](https://forum.ansible.com/u/Brian_Coca1)\
**Post date:** [May 22, 2014, 3:51pm UTC](https://forum.ansible.com/t/loops-and-variables/15302/6 "2014-05-22T15:51:54Z")

</div>

you can try just rewriting my\_groups this way:

my\_groups: “0dm-sap:dev-sap:tst-sap:pre-sap:pro-sap”

---

<div class="post-metadata">

**Author:** ![Makimoto\_Marakatti](https://avatars.discourse-cdn.com/v4/letter/m/e19adc/32.png) [@Makimoto\_Marakatti](https://forum.ansible.com/u/Makimoto_Marakatti)\
**Post date:** [May 23, 2014, 10:05am UTC](https://forum.ansible.com/t/loops-and-variables/15302/7 "2014-05-23T10:05:25Z")

</div>

Brian:  
Unfortunately that yields this:

`  
changed: [hostA] =\> {“changed”: true, “dest”: “/backup/ **0dm-sap:dev-sap:tst-sap:pre-sap:pro-sap/hostA/hostA** /root/.bash\_profile”, “md5sum”: “bab9333347e752b87add49020919a078”, “remote\_md5sum”: “bab9333347e752b87add49020919a078”}

`

I also failed to make this work declaring vars and including another play.

So I guess it’s back to the usual: roles.  
But for this particular task, that seems so inelegant…

thanks to all

---

<div class="post-metadata">

**Author:** ![Brian\_Coca1](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@Brian\_Coca1](https://forum.ansible.com/u/Brian_Coca1)\
**Post date:** [May 23, 2014, 12:16pm UTC](https://forum.ansible.com/t/loops-and-variables/15302/8 "2014-05-23T12:16:23Z")

</div>

yeah, didn’t realize you were reusing it for the task also, my ‘fix’ would work only for hosts: entry.​

---

<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:** [May 23, 2014, 12:44pm UTC](https://forum.ansible.com/t/loops-and-variables/15302/9 "2014-05-23T12:44:41Z")

</div>

Or make a group that contains those groups as children, so it’s cleaner 🙂

---

<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:** [May 23, 2014, 12:47pm UTC](https://forum.ansible.com/t/loops-and-variables/15302/10 "2014-05-23T12:47:28Z")

</div>

You could make a backup role and do something like this:

- hosts: group1  
roles:

- { role: backup, path: ‘group1’ }

- hosts: group2  
roles:

- { role: backup, path: ‘group2’ }

A host can be in lots of groups, so you shouldn’t rely on the group\_names variable to tell you what you are looping over.

For instance, a host could be in a group based on purpose and another based on geography.

---

<div class="post-metadata">

**Author:** ![Makimoto\_Marakatti](https://avatars.discourse-cdn.com/v4/letter/m/e19adc/32.png) [@Makimoto\_Marakatti](https://forum.ansible.com/u/Makimoto_Marakatti)\
**Post date:** [May 23, 2014, 12:54pm UTC](https://forum.ansible.com/t/loops-and-variables/15302/11 "2014-05-23T12:54:06Z")

</div>

> A host can be in lots of groups, so you shouldn’t rely on the group\_names variable to tell you what you are looping over.

Well that was why I was using “my\_groups”. I do have a lot of groups in the inventory…

Your suggestion seems to be like something that could work. I’ll try to adapt that and report back.

Thanks!

---

<div class="post-metadata">

**Author:** ![Dimon](https://avatars.discourse-cdn.com/v4/letter/d/eb8c5e/32.png) [@Dimon](https://forum.ansible.com/u/Dimon)\
**Post date:** [May 23, 2014, 8:04pm UTC](https://forum.ansible.com/t/loops-and-variables/15302/12 "2014-05-23T20:04:55Z")

</div>

Why not “with\_nested”?

as per ams:

- name: fetch files from the server  
fetch: src={{ item }}  
dest=/backup/{{ item[1] }}/{{ inventory\_hostname }}/{{ item[0] | basename }}  
with\_nested:

- [/root/.bash\_profile, /some/other/file]

- group\_names

better yet - provide list of files as a variable.

---

<div class="post-metadata">

**Author:** ![Makimoto\_Marakatti](https://avatars.discourse-cdn.com/v4/letter/m/e19adc/32.png) [@Makimoto\_Marakatti](https://forum.ansible.com/u/Makimoto_Marakatti)\
**Post date:** [May 26, 2014, 10:19am UTC](https://forum.ansible.com/t/loops-and-variables/15302/13 "2014-05-26T10:19:40Z")

</div>

Just seen this today.  
Will give it a try soon…

Thanks!
