Inventory with both a hostname and IP address pattern - ansible

I'm using the vmware_guest module to create a bunch of vms.
Is there anyway to use a pattern for both the hostname and IP address?
For example I want to create 5 master vms with hostname/IP like:
master1 10.123.0.1
master2 10.123.0.2
master3 10.123.0.3
etc.
So an inventory yaml with something like the following:
all:
children:
Elvis:
children:
masterNodes:
hosts:
master[1-5]:
ansible_host: 10.123.0.[1-5]
slaveNodes:
hosts:
slave[1-10]:
ansible_host: 10.124.0.[1-10]
Also, is there a way to run a playbook for a specific parent:child group?
How can I run a play for Elvis:masterNodes only? If for instance, the same inventory yaml has another parent child group Bono:masterNodes

Is there anyway to use a pattern for both the hostname and IP address?
No. Instead, Ansible allows running a script to generate an inventory - it is trivial to implement a loop populating inventory-hostname along with IP address in Python (apparently it was made clear as early as in July 2013, although in the same thread someone suggested a workaround).
Also, is there a way to run a playbook for a specific parent:child group?
No. There is no hierarchy in Ansible inventory; the namespace is flat; there are no child groups; Ansible operates on host/group sets.
In effect, you can't have distinct (sub)groups bearing the same name. The contents of those (sub)groups will be merged. So if Elvis contains a group masterNodes and you execute a play with hosts:Elvis declaration, it will run on all hosts defined for masterNodes anywhere (including in Bono:masterNodes).

Related

how to get the current executing host group_name not group_names in ansible?

I have read How do you get group name of the executing role in ansible
I also read https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html
but I can't understand it.
If the same host IP in different host_groups, I think: "ansible is separated execute when executing the host, it should belong to only one group_name, not group_names".
How can I get current executing host gorup_name, not group_names?
It sounds like you want want the group equivalent to inventory_hostname. Unfortunately, it doesn't exist. You might consider setting an extra variable during execution as a workaround. Example: --extra-vars targetgroup=group1
This would work well if you typically only target one group. If targeting multiple groups, consider creating a new parent group for each combination and then targeting that.
First,
you can write one host in several groups.
Second,
In my opinion, Getting the 'group_name' of executing host make no sense
Whatever you using ad-hoc(playbook), you must declare which group of hosts you want to execute command(role), all group must be written in your ansible command(role) even if you want to execute on all hosts.
So when the command(role) are running, you have already know which group is running now.
Third,
Even if you run command(role) on two groups which have the same hosts, why do you want to know the host is from which group.
UPDATE:
1.Like my origin reply, you can define many groups include the same host.
For instance, this is the inventory file
[production]
machine01
machine02
[staging]
mchines01
And Using this judging condition in tasks.
when:
- inventory_hostname in groups['production']
2.And you also can add tags for the specific tasks.
For instance
- name: set hostname
hostname:
name: machine03
tags:
- production
- staging
- name: reboot
reboot:
reboot_timeout: 1200
tags:
- staging
Running ansible-playbook commond with -t option
-t TAGS, --tags=TAGS only run plays and tasks tagged with these values

How to prevent Ansible from merging host variables?

I have a host under two group names (in the example below). If group_1 is called I want it to connect to it via ssh, but if group_2 is called I want it to be a local connection. However, ansible seems to be merging the two hosts variables together even though they're in different groups? It's using a local connection for group_1.
How can I prevent this?
[group_1]
example.com ansible_user=ansible ansible_ssh_private_key_file="{{ lookup('env','PATH_TO_KEYS') }}"/my.pem
[group_2]
example.com ansible_port=8081 ansible_connection=local
The inventory hostname can be arbitrary but it is the key identifier for the host so the vars will aggregated as described here: https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable
We can use the arbitrary string combined with ansible_host to kind of game the system to do what you want. https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#hosts-and-non-standard-ports
Also, note that the ansible_connection=local is going to execute code on your localhost without use of any connections or service daemon (ssh or otherwise) so the ansible_port is not necessary.
[group_1]
example_ssh ansible_host=example.com ansible_user=ansible ansible_ssh_private_key_file="{{ lookup('env','PATH_TO_KEYS') }}"/my.pem
[group_2]
example_local_8081 ansible_host=example.com ansible_port=8081 ansible_connection=local

Making a hosts file group into an input in Ansible playbook

I have an ansible playbook that calls an API. I have a delegate_to: localhost.
I want to run my playbook "against" every host in a group Linux.
I want the API call to do 2 things.
I want it to run once for every host in the Linux group
For every run, it should have a different host IP/hostname as the input
linux looks like:
[linux]
10.234.0.13
10.234.0.12
I run my like this: ansible-playbook -i linux my_playbook
How do I make the inventory group an input?
when ansible executes on the remote host it collects some meta data of the hosts. One of the meta data is ip address. The meta data is called ansible facts. There is an ansible fact to get the ip address
ansible_default_ipv4.address

Ansible - Change target to IP in task

I'm writing a role thats creates virtual machines & configures them. I need to perform a few tasks on the VM's before their DNS entries are created.
How can I get the task to connect to a known IP address instead of the usual ansible_host variable (FQDN)? I can't set it in the inventory file since the IP is not known when it is created.
TIA
The inventory file can use IP addresses. See the jumper example in https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html.
The way you typically handle this is to use Ansible's add_host module, which lets you create inventory entries dynamically during your playbook run. A task looks something like:
- name: add host to inventory
add_host:
name: my_new_host
ansible_host: "{{ new_host_ipaddr }}"
groups: [webservers]
You can see an example of this in action here (just search for add_host).

Can I dump the inventory to a remote machine in a task?

I have an Ansible role where I need to create an inventory file on the remote machine. I want to use the current inventory file, but with one single group removed.
For example, if I have the following inventory:
[operator]
host1.example.com
[control]
host2.example.com
host3.example.com
[compute]
host4.example.com some_var=value
host5.example.com
# some comment
[foo:children]
control
compute
[bar:vars]
var1=value
#var2=value
Then I need something that copies this:
- hosts: operator
tasks:
- name: Create inventory
...
With the following result on host1.example.com:
[control]
host2.example.com
host3.example.com
[compute]
host4.example.com some_var=value
host5.example.com
# some comment
[foo:children]
control
compute
[bar:vars]
var1=value
#var2=value
Split the current inventory file into two:
one containing the operator group only,
one containing the rest.
Copy only the latter to the target system.
You know that you can point to a directory containing multiple files as your inventory, right?

Resources