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'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.
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:
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.
“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?
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):
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:
- name: Add new instance to a temporary group
local_action:
module: add_host
name: "{{ item.public_ip }}"
groups: newly_launched
ec2_tag_Name: "{{ instance_hostname }}"
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
instance_tags:
Name: "{{ instance_hostname }}"
in the ec2 launch task.)
-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.
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:
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: