# How to have each node get a different variable from an array

**URL:** <https://forum.ansible.com/t/how-to-have-each-node-get-a-different-variable-from-an-array/12464>\
**Category:** Ansible Project\
**Created:** [March 6, 2013, 11:40pm UTC](https://forum.ansible.com/t/how-to-have-each-node-get-a-different-variable-from-an-array/12464 "2013-03-06T23:40:14Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Peter\_Sankauskas](https://avatars.discourse-cdn.com/v4/letter/p/ea666f/32.png) [@Peter\_Sankauskas](https://forum.ansible.com/u/Peter_Sankauskas)\
**Post date:** [March 6, 2013, 11:40pm UTC](https://forum.ansible.com/t/how-to-have-each-node-get-a-different-variable-from-an-array/12464/1 "2013-03-06T23:40:14Z")

</div>

Hi,

I am creating a playbook that creates a valid cassandra.yaml file for each node in a new cluster using a jinja2 template. What this file needs is a different token for each node, but I do not know how to do this with Ansible.

So the part of the template in question looks like this:

> initial\_token: {{ token }}

In this example, I have 6 nodes. I can generate the tokens for each using this script:

> $ ./tokenbuilder.py 6  
> {  
> “0”: {  
> “0”: 0,  
> “1”: 28356863910078205288614550619314017621,  
> “2”: 56713727820156410577229101238628035242,  
> “3”: 85070591730234615865843651857942052864,  
> “4”: 113427455640312821154458202477256070485,  
> “5”: 141784319550391026443072753096570088106  
> }  
> }

I believe there is a way to get the output of that script into a variable in Ansible so that I can access it by {{ tokens[0] }}. (Any tips appreciated).

In any case, I can use a playbook that has

> vars:
> 
> tokens:
> 
> 0: 0
> 
> 1: 28356863910078205288614550619314017621
> 
> 2: 56713727820156410577229101238628035242

> …

> tasks:
> 
> - name: Copy over the templated cassandra.yaml config file  
> template: src=templates/cassandra.yaml.j2 dest=/etc/cassandra/cassandra.yaml

to do the same thing.

The question is, how can I then get each of the 6 hosts to use one of these array values in the template? So that when the template is evaluated:

> host1 has token = tokens[0] = 0  
> host2 has token = tokens[1] = 28356863910078205288614550619314017621  
> host3 has token = tokens[2] = 56713727820156410577229101238628035242  
> host4 has token = tokens[3] = 85070591730234615865843651857942052864  
> host5 has token = tokens[4] = 113427455640312821154458202477256070485
> 
> host6 has token = tokens[5] = 141784319550391026443072753096570088106

All hosts are part of the same group in the inventory. Is there a trick to get the index of a host in a group?

I would really appreciate anyone pointing me in the right direction.

Thanks,  
Peter

---

<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:** [March 6, 2013, 11:50pm UTC](https://forum.ansible.com/t/how-to-have-each-node-get-a-different-variable-from-an-array/12464/2 "2013-03-06T23:50:41Z")

</div>

you can call a task that calls the script and outputs a token per  
host, register the variable and then use that in the template.

---

<div class="post-metadata">

**Author:** ![Peter\_Sankauskas](https://avatars.discourse-cdn.com/v4/letter/p/ea666f/32.png) [@Peter\_Sankauskas](https://forum.ansible.com/u/Peter_Sankauskas)\
**Post date:** [March 6, 2013, 11:58pm UTC](https://forum.ansible.com/t/how-to-have-each-node-get-a-different-variable-from-an-array/12464/3 "2013-03-06T23:58:13Z")

</div>

Perhaps, but how?

How does ansible know which “host number in the group” it is running on?

This isn’t serial, all 6 hosts have the ansible playbook running simultaneously, so it is not a matter of maintaining a stack between each host where I pop off each token for each host.

To be clear, the tokens aren’t random, they are calculated based on the number of hosts (in this example, 6).

---

<div class="post-metadata">

**Author:** ![benno\_joy](https://avatars.discourse-cdn.com/v4/letter/b/73ab20/32.png) [@benno\_joy](https://forum.ansible.com/u/benno_joy)\
**Post date:** [March 7, 2013, 2:13am UTC](https://forum.ansible.com/t/how-to-have-each-node-get-a-different-variable-from-an-array/12464/4 "2013-03-07T02:13:18Z")

</div>

Hey Pete,

I am an newbie, so there might be better ways to do it, how about set the vars as  
vars:  
: 1234  
: 456456  
etc…

in in your template referece it as  
token = {{ ansible\_hostname }}

or maybe  
set a custom facter in each host ‘hostnumber’ and then in template evaluate this value and set token accordingly

Regards,  
Benno Joy

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [March 7, 2013, 5:14am UTC](https://forum.ansible.com/t/how-to-have-each-node-get-a-different-variable-from-an-array/12464/5 "2013-03-07T05:14:39Z")

</div>

I like Benno's solution of the hash table, though you could also try  
something like this to derive the token from the hostname:

- shell: echo $hostname | md5sum -t  
&nbsp;&nbsp;register: host\_token

And then you could just loop over the hosts in your template::

{% for host in groups['groupname'] %}  
&nbsp;&nbsp;&nbsp;&nbsp;{{ hostvars[host]['host\_token'] }}  
{% endfor %}

---

<div class="post-metadata">

**Author:** ![Peter\_Sankauskas](https://avatars.discourse-cdn.com/v4/letter/p/ea666f/32.png) [@Peter\_Sankauskas](https://forum.ansible.com/u/Peter_Sankauskas)\
**Post date:** [March 7, 2013, 9:23pm UTC](https://forum.ansible.com/t/how-to-have-each-node-get-a-different-variable-from-an-array/12464/6 "2013-03-07T21:23:53Z")

</div>

Thanks for the suggestions. I believe both of those will work.

However, both suggestions push variables for one template in one playbook far up the stack and into the inventory. I am looking for a way to encapsulate all of this inside just the playbook itself without extra dependencies.

The other issue is that I don’t have named hosts (I am using the AWS EC2 inventory plugin). The hostnames are not unique and unpredictable.

To have a solution that is both encapsulated, and dynamic, I have come up with some Ansible/Jinja trickery.

Using this yaml file to store the pre-computed tokens for clusters of size 1 to 10 nodes: [https://gist.github.com/pas256/5111146](https://gist.github.com/pas256/5111146)

I can use this in the my cassandra.yaml.j2 template:

> # Cassandra storage config YAML
> 
> {% set seeds = %}
> 
> {% for host in groups[‘tag\_Name\_cassandra’] -%}
> 
> {# This is in an if block even though it is just a variable assignment because
> 
> the only other way to append to an array is with the ‘do’ Jinja2 extension
> 
> -#}
> 
> {% if seeds.append(hostvars[host][‘ansible\_eth0’][‘ipv4’][‘address’]) -%}{% endif -%}
> 
> {% endfor -%}
> 
> {% set num\_hosts = seeds|length -%}
> 
> …
> 
> {% for ip in seeds|sort -%}
> 
> {% if ansible\_eth0[“ipv4”][“address”] == ip -%}
> 
> initial\_token: {{ initial\_tokens[num\_hosts][loop.index0] }}
> 
> {% endif -%}
> 
> {% endfor -%}

What I am doing is building an array of all nodes in the group, where the array entry is the ip address. Then further down the template, I can loop though that array looking for the IP address of the hosts that is running the template, and use the loop index as the index into the initial\_tokens variable. To ensure consistency, the array is always sorted.

Not sure if there is a simpler way of doing this, but is does solve both my concerns, and has all the logic in the 1 place.

---

<div class="post-metadata">

**Author:** ![Mark\_Casey](https://avatars.discourse-cdn.com/v4/letter/m/b4bc9f/32.png) [@Mark\_Casey](https://forum.ansible.com/u/Mark_Casey)\
**Post date:** [February 7, 2014, 3:58pm UTC](https://forum.ansible.com/t/how-to-have-each-node-get-a-different-variable-from-an-array/12464/7 "2014-02-07T15:58:36Z")

</div>

Thanks for sharing this… just saved me quite a bit of frustration.

I was trying something along these lines ([https://groups.google.com/d/msg/ansible-project/YTF6Up3kaKw/xHASvMROhegJ](https://groups.google.com/d/msg/ansible-project/YTF6Up3kaKw/xHASvMROhegJ)) to get a list of private IPs for a MySQL cluster config, and have ended up with:

---

<div class="post-metadata">

**Author:** ![skr989](https://avatars.discourse-cdn.com/v4/letter/s/50afbb/32.png) [@skr989](https://forum.ansible.com/u/skr989)\
**Post date:** [October 6, 2014, 3:12pm UTC](https://forum.ansible.com/t/how-to-have-each-node-get-a-different-variable-from-an-array/12464/8 "2014-10-06T15:12:19Z")

</div>

Hello,

Replying to an old thread but this is relevant to what I am trying to do.

I have defined the tokens as a dictionary in the vars\_file as below.

tokens:  
192.168.56.1: 0  
192.168.56.2: 56713727820156410577229101238628035242  
192.168.56.3: 113427455640312821154458202477256070485

192.168.56.x hosts are coming in from inventory file  
and in the cassandra.yaml I have the following  
initial\_token: {{ tokens[‘{{ inventory\_hostname}}’] }}

tokens[“{{ inventory\_hostname}}”] is evaluated but not {{ tokens[‘{{ inventory\_hostname}}’] }}

How do I get it done with jinja2? Where am I going wrong? Any help is much appreciated.

-SR
