Intersections in templates and variables?

Hi,

I have an inventory setup where instances have roles with a cloud. Because there are multiple clouds I use intersections to select roles within a cloud, and pass in the cloud name as an extra variable at the command line. This seems to work well for selecting hosts, but I’m struggling to use intersections in templates or variables. For instance, I have three core nodes and I’d like to put the IP addresses in /etc/hosts. I have been trying variations of:

{{hostvars[set(groups[‘Core1’]).intersection(set(groups[cloud])).pop()].ansible_eth0.ipv4.address}}

but nothing works.

Alternatively, is there a way for hosts to register global variables? In that case I’d just connect and register these up front.

Thanks,

Tristan

This makes my eyes kind of bleed.

In general when you are modelling something and it gets this ugly, step back and think about the use case – things in Ansible should never look like this. The project exists to avoid such things :slight_smile:

“I use intersections to select roles within the cloud” doesn’t make sense to me, unfortunately, can you explain more and show your command line use case and a bit more info?

Michael,

Yes, I figure I’m not doing this the “Ansible Way” and my eyes are bleeding as well. I’m writing Ansible scripts to manage multiple Hadoop clusters. I had 4 roles: core1, core2, core3, and slaves. I organized my inventory into these groups and also had a “cloud” group, which is just a particular Hadoop cluster. I would then select things like “hosts:core1:&$cloud” where I pass in $cloud as a command line extra-vars. I’ve tried changing my inventory scheme and use “hosts: ${cloud}core1”, but this also is awkward.

I am struggling with the best way to access variables of another host, namely the ip address of core1,core2,core3. I do not have fixed hostnames, so I was trying to use groups. I’m not sure how to do it in the first inventory scheme, because can’t do intersections, but in the second I could do:

{{ hostvars[groups[cloud+‘core1’][0]][‘ansible_eth0’][‘ipv4’][‘address’] }}

I feel like I’m missing some way to define dynamic global variables. I looked at set_fact, but it doesn’t seem to stick around for my entire playbook. Is there a way to set a global variable that persists across the entire playbook.yml (multiple hosts: selections). Or is there a better way to get some dynamic facts and use them across hosts?

Feedback very much appreciated.

Tristan

“I am struggling with the best way to access variables of another host, namely the ip address of core1,core2,core3”

This should be all you need to get the first host in “core1”

hostvars[groups[“core1”][0]][“variable_name”]

Michael,

Right, but I need the core1 associated with a particular cluster. This is why I was trying to use an intersection. But I can’t easily use the intersection syntax, hosts: core1&:$cloud, to select from hostvars. As a result, I’ve tried renaming my inventory so that they are named ${cloud}core1. Then I select variables with with hostvars[groups[cloud + “core1”][0]][‘variable_name’]. Is there a better way?

Tristan

I would be inclined to do this in inventory:

[core:children]
core-cluster1
core-cluster2

[core-cluster1]
asdf.example.com
bar.example.com

[core-cluster2]
baz.example.com
glorp.example.com

Then you can just specify “core-cluster2” as the group name.

Sorry for necro’ing an old thread, but I’m having a similar problem: I’m playing with an EC2 inventory, and I have several “environments”, with machines in these environments having a specific “class”. Is there a way to template the ip of the machine that has both ‘tag_environment_myenv’ and ‘tag_class_database’?

" Is there a way to template the ip of the machine that has both ‘tag_environment_myenv’ and ‘tag_class_database’?"

I don’t quite understand what you mean by templating the IP. Can you elaborate a bit more?

This is really looking for an alternative solution for the other thread (the one tagged [newbie]):

  • my inventory has orthogonal, EC2-tag-based groups which are “env” (the environment) and “class” (the function of the machine in that env). In this case, I’m adding a new “node” to the environment, and I need to modify an installation xml file (I’m using a Jinja template) to contain the IP of the VM tagged “tag_class_database” in the same environment (say “tag_env_myenv”).

I googled some examples of how to get the IP for the machine meeting a single tag (https://coderwall.com/p/jerwwg), but I need an intersection between the “class” and “env” tags. Is there any way to do that?

Tags become groups as you can test by running

./ec2.py --list

So generically, in Ansible

You can do things like:

when: inventory_hostname in groups.foo and inventory_hostname in groups.bar

or you can just specify this in your host specificaition:

hosts: group1:&group2

This is in a Jinja template. I was reading a bit more in Jinja and I think I can do a double loop with an if condition.

Thanks.

Just for documentation purposes, here’s my working solution:


Thank you