# Setting host vars programmatically with dynamic inventory

**URL:** <https://forum.ansible.com/t/setting-host-vars-programmatically-with-dynamic-inventory/16186>\
**Category:** Ansible Project\
**Created:** [September 11, 2014, 7:03pm UTC](https://forum.ansible.com/t/setting-host-vars-programmatically-with-dynamic-inventory/16186 "2014-09-11T19:03:06Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ches\_Martin](https://avatars.discourse-cdn.com/v4/letter/c/e495f1/32.png) [@Ches\_Martin](https://forum.ansible.com/u/Ches_Martin)\
**Post date:** [September 11, 2014, 7:03pm UTC](https://forum.ansible.com/t/setting-host-vars-programmatically-with-dynamic-inventory/16186/1 "2014-09-11T19:03:06Z")

</div>

Hi folks,

I’ve been trying to come up with a solution to what essentially boils down to this:

Say I’m writing, or simply using, a role which depends on a host var being set for all targeted hosts. An example is ZooKeeper, where each member of an ensemble needs a unique ID configured, and needs to enumerate all the other members in its config file (common for host in groups / hostvars pattern). I’d like to achieve this with an EC2 tag on each host, but say that the role already references a specific hostvar name (which naturally isn’t ec2\_tag\_the\_key\_name\_i\_want).

Can anyone suggest a programmatic way to map values to a particular host var name during a run? set\_fact only appears applicable to the context of a single host as it executes a run (a with\_items: groups[foo] loop does not work). I don’t particularly want to juggle names in DNS for these hosts in order to use named files in host\_vars.

Thanks for your help!

Regards,  
Ches

---

<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:** [September 11, 2014, 11:31pm UTC](https://forum.ansible.com/t/setting-host-vars-programmatically-with-dynamic-inventory/16186/2 "2014-09-11T23:31:31Z")

</div>

> Hi folks,
> 
> I've been trying to come up with a solution to what essentially boils down  
> to this:
> 
> Say I'm writing, or simply using, a role which depends on a host var being  
> set for all targeted hosts. An example is ZooKeeper, where each member of  
> an ensemble needs a unique ID configured, and needs to enumerate all the  
> other members in its config file (common for host in groups / hostvars  
> pattern). I'd like to achieve this with an EC2 tag on each host, but say  
> that the role already references a specific hostvar name (which naturally  
> isn't ec2\_tag\_the\_key\_name\_i\_want).
> 
> Can anyone suggest a programmatic way to map values to a particular host  
> var name during a run? set\_fact only appears applicable to the context of  
> a single host as it executes a run (a with\_items: groups[foo] loop does  
> not work). I don't particularly want to juggle names in DNS for these hosts  
> in order to use named files in host\_vars.

I'm somewhat unclear on this one as the playbook parts and the dynamic  
inventory parts are different things.

Can you elaborate on what "map values to a particular host var name" would  
mean?

If I may guess at the question, group\_vars/\<groupname\> does in fact work  
with dynamic groups, if you want everything in ec2\_tag\_the\_key\_name\_I\_want  
to get a value like x: 42.

(set\_fact looping over a with\_items doesn't allow you to set vars for other  
hosts, true, it just makes the value of "item" be different in each  
iteration of the loop is all)

Let me know more info and I can perhaps get a bit closer, but I \*think\*  
group\_vars is what you want.

---

<div class="post-metadata">

**Author:** ![Ches\_Martin](https://avatars.discourse-cdn.com/v4/letter/c/e495f1/32.png) [@Ches\_Martin](https://forum.ansible.com/u/Ches_Martin)\
**Post date:** [September 12, 2014, 8:08am UTC](https://forum.ansible.com/t/setting-host-vars-programmatically-with-dynamic-inventory/16186/3 "2014-09-12T08:08:40Z")

</div>

Thanks for your help Michael.

group\_vars can actually solve _part_ of the problem in a kludgy way, I’m not sure if this is what you had in mind. Let me elaborate the ZooKeeper example, it’s concrete for me, though there are some other cases where I want essentially the same thing. Here’s the snippet of a zoo.cfg template for enumerating cluster members, pretty standard stuff:

`  
{% for host in groups[zookeeper\_ensemble\_group] %}  
server.{{ hostvars[host].zookeeper\_myid }}={{ hostvars[host].zookeeper\_bind\_address }}:2888:3888  
{% endfor %}

`

So, what I meant by “map values to a particular host var name” is that I effectively want to assign/alias zookeeper\_myid = ec2\_tag\_zookeeper\_id and zookeeper\_bind\_address = ec2\_private\_ip\_address for each host in the group, before this zookeeper role runs. I was hoping for a way to do this without having to modify an upstream role, or in writing my own shareable roles to not have them coupled to choices of a particular inventory source, so users can simply consistently override a sensibly-named variable.

After you mentioned it, group\_vars does partly help, in a very redundant way via the dynamic groups that include tag values along with key:

`

---

<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:** [September 12, 2014, 1:57pm UTC](https://forum.ansible.com/t/setting-host-vars-programmatically-with-dynamic-inventory/16186/4 "2014-09-12T13:57:06Z")

</div>

You could modify your dynamic inventory. I think in the past it's been  
said that the ec2.py, etc are starting points for your own dynamic  
inventory scripts. This way you can do what you want with your  
ec2\_tag\_\* variables and makes it easier when part of your  
infrastructure isn't even on EC2.

---

<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:** [September 12, 2014, 2:30pm UTC](https://forum.ansible.com/t/setting-host-vars-programmatically-with-dynamic-inventory/16186/5 "2014-09-12T14:30:15Z")

</div>

“is that I effectively want to assign/alias zookeeper\_myid = ec2\_tag\_zookeeper\_id andzookeeper\_bind\_address = ec2\_private\_ip\_address for each host in the group”

Are you saying you wish to add them to another group?

The add\_host module is good for that.

---

<div class="post-metadata">

**Author:** ![Ches\_Martin](https://avatars.discourse-cdn.com/v4/letter/c/e495f1/32.png) [@Ches\_Martin](https://forum.ansible.com/u/Ches_Martin)\
**Post date:** [September 12, 2014, 3:08pm UTC](https://forum.ansible.com/t/setting-host-vars-programmatically-with-dynamic-inventory/16186/6 "2014-09-12T15:08:10Z")

</div>

No, these are _host_ variables, since they’re both unique to a given host (in a cluster). I just want to be able to assign the values from my inventory (ec2\_ hostvar names) to the specific hostvar variable names that a role is looking for. Without changing the role—assuming it’s vendor code and should remain general anyway.

Basically, assuming this were possible somehow, it’s what I want to do (note the same dict key on both sides of assignment):

`hostvars[host].zookeeper_myid = hostvars[host].ec2_private_ip_address`

-Ches

---

<div class="post-metadata">

**Author:** ![Josh\_Smift1](https://avatars.discourse-cdn.com/v4/letter/j/bcef8e/32.png) [@Josh\_Smift1](https://forum.ansible.com/u/Josh_Smift1)\
**Post date:** [September 12, 2014, 6:20pm UTC](https://forum.ansible.com/t/setting-host-vars-programmatically-with-dynamic-inventory/16186/7 "2014-09-12T18:20:11Z")

</div>

> Basically, assuming this were possible somehow, it's what I want to do  
> (note the same dict key on both sides of assignment):
> 
> hostvars[host].zookeeper\_myid = hostvars[host].ec2\_private\_ip\_address

This seems like the thing that someone else helped me figure out how to  
do, e.g. I now have as part of my aws-launch.yml playbook:

&nbsp;&nbsp;- name: Add new instance to a temporary group  
&nbsp;&nbsp;&nbsp;&nbsp;local\_action:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module: add\_host  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name: "{{ item.public\_ip }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;groups: newly\_launched  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ec2\_tag\_Name: "{{ instance\_hostname }}"  
&nbsp;&nbsp;&nbsp;&nbsp;with\_items: ec2.instances

Does that help? (instance\_hostname is a variable that I passed in to the  
playbook on the command line, which gets set for real at AWS with

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;instance\_tags:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name: "{{ instance\_hostname }}"

in the ec2 launch task.)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-Josh (jbs@care.com)

This email is intended for the person(s) to whom it is addressed and may contain information that is PRIVILEGED or CONFIDENTIAL. Any unauthorized use, distribution, copying, or disclosure by any person other than the addressee(s) is strictly prohibited. If you have received this email in error, please notify the sender immediately by return email and delete the message and any attachments from your system.

---

<div class="post-metadata">

**Author:** ![Ches\_Martin](https://avatars.discourse-cdn.com/v4/letter/c/e495f1/32.png) [@Ches\_Martin](https://forum.ansible.com/u/Ches_Martin)\
**Post date:** [September 13, 2014, 12:08pm UTC](https://forum.ansible.com/t/setting-host-vars-programmatically-with-dynamic-inventory/16186/8 "2014-09-13T12:08:02Z")

</div>

Thanks for the suggestion Josh, that seems like a promising lead, I didn’t realize until now that add\_host can _add host variables_, not just add hosts to groups. Except that, so far, I’m not sure that it works to set _new_ host variables if the referenced host already existed in inventory. I’ve tried this:

`

- name: Set hostvar aliases  
add\_host: \>  
name=‘{{ item }}’  
zookeeper\_myid=‘{{ hostvars[item].ec2\_tag\_ZooKeeperID }}’  
zookeeper\_bind\_address=‘{{ hostvars[item].ec2\_private\_ip\_address }}’  
with\_items: groups[zookeeper\_ensemble\_group]

`

which would get me what I’m wanting pretty readably, but it doesn’t seem to work.

I tried changing hash\_behaviour to “merge” just to see if that could allow this work, no dice. I’ll have to dig further in implementation to understand, and this issue might be relevant since the above is a local action:

[https://github.com/ansible/ansible/issues/5791](https://github.com/ansible/ansible/issues/5791)

-Ches
