I have a very complex Ansible setup with thousands of servers and hundreds of groups various servers are member of (dynamic inventory file).
Is there any way to easily display all groups that a specific host is member of?
I know how to list all groups and their members:
ansible localhost -m debug -a 'var=groups'
But I want to do this not for ALL hosts, but only for a single one.
Create a playbook called 'showgroups' (executable file) containing:
#!/usr/bin/env ansible-playbook
- hosts: all
gather_facts: no
tasks:
- name: show the groups the host(s) are in
debug:
msg: "{{group_names}}"
You can run it like this to show the groups of one particular host (-l) in your inventory (-i):
./showgroups -i develop -l jessie.fritz.box
There is group_names magic variable:
Additionally, group_names is a list (array) of all the groups the current host is in. This can be used in templates using Jinja2 syntax to make template source files that vary based on the group membership (or role) of the host
cat /etc/ansible/hosts | grep -e [[] && ansible all --list-hosts
Related
In my playbook I use var group[inventory_group]. And I need to use my dynamic inventory script. In the documentation I found:
Like above, it is possible to pass an additional inventory file (or
even dynamic inventory script), using the hosts key. Ansible will
automatically merge this inventory with the one generated by molecule.
This can be useful if you want to define extra hosts that are not
managed by Molecule.
But I didn't find any examples.
So, how do I "pass an additional inventory file (or even dynamic inventory script), using the hosts key" ?
Perhaps you could execute the dynamic inventory script in create or prepare steps in the molecule scenario, and then use the add_host module to add the hosts to the in memory inventory?
So something like:
- command:
cmd: /path/to/your_dynamic_inventory_scri.pt
delegate_to: localhost
register: dynamic_inventory
- add_host:
name: "{{ item }}"
loop: "{{ dynamic_inventory.stdout_lines }}"
I get my network inventory for ansible dynamicly from the netbox plugin and I want to use this data to edit the /etc/hosts file and run a script on a special host (librenms) to add all the network devices there.
Has anyone an idea how to run a playbook only on the librenms host with the data of the netbox inventory plugin?
Here my inventory (the librenms host is not part of it)
plugin: netbox
api_endpoint: https://netbox.mydomain.com
token: abcdefghijklmopqrstuvwxyz
validate_certs: False
config_context: True
group_by:
- device_roles
query_filters:
- role: test-switch
- has_primary_ip: True
Many, many thanks in advance!
If the host you want to run the playbook on is not part of your dynamic inventory and at the same time you want to use variables defined in the dynamic inventory in a play for that host, you have to construct an "hybrid" inventory containing both your dynamic inventory ans other static entries.
This is covered in the documentation on inventories: Using multiple inventory sources.
Very basically you have two solutions:
Use two different inventories on the command line:
ansible-playbook -i dynamic_inventory -i static_inventory your_playbook.yml
Create a compound inventory with different sources in a directory. See chapter "Aggregating inventory sources with a directory" in the above documentation.
I am trying to play a yml on other host than configured, using -l option.. but skipping: no hosts matched .
The scenario is where a host associated playbook is needed to be exceptionally used for some other host. (and for safety reasons, the playbook cannot have hosts:all and be left to the admin to limit the target(s))
What is the correct way to do this (if there is any)?
L.E. So, in the end, the answer of #mdaniel gave me the idea o a bash wrapper that creates a temp yml where the host: field is replaced with the argument.. it's not pretty but it works. (same works for a dynamical generation of a playbook from a series of tasks)
and the proper ansible way to do it i just found it here:
https://stackoverflow.com/a/18195217/624734
What is the correct way to do this?
Use all as the target of the playbook, and then constrain the hosts it applies to via the inventory, or the --limit that you mentioned
- hosts: all
# and now the rest of your playbook
You can try the below approach if you want to restrict hosts:all in your ansible script.
- hosts: "{{ host_group }}"
# Rest of your playbook
And you can have a specific group in your hosts file which you can use for testing.
For example,
[test]
192.168.1.1 # Test host
# Rest of your inventory file
And trigger the ansible playbook in the following order,
ansible-playbook -i hosts main.yml -e host_group="test"
What does ":&" mean in an Ansible/Jinja2 YAML file?
For example, in this line:
hosts: test-instances:&{{ target_host | default('None') }}
It is an intersection of two hosts groups in Ansible (it is not a Jinja2 syntax and is not used except for the hosts declaration).
In your example, the play will run only on the host (or host group) specified in the target_host variable as long as it is listed in the test-instances inventory group.
If target_host is not specified or target_host is not listed in the test-instances, the play will be skipped (assuming there is no host named None).
Per Working with Patterns:
You can also specify the intersection of two groups. This would mean the hosts must be in the group webservers and the host must also be in the group staging:
webservers:&staging
I am trying to set up Ansible to be able to run a playbook according to what inventory group the host is in. For example, in the inventory, we have:
[group1]
host1.sub.domain.tld ansible_host=10.0.0.2
...
[group1:vars]
whatsmyplaybook=build-server.yml
Then we want to make a simple playbook that will more or less redirect to the playbook that is in the inventory:
---
- name: Load Playbook from inventory
include: "{{hostvars[server].whatsmyplaybook}}"
Where the "server" variable would be the host's FQDN, passed in from the command line:
ansible-playbook whatsmyplaybook.yml -e "server=host1.sub.domain.tld"
Our reasoning for this would be to have a server bootstrap itself from a fresh installation (PXE boot), where it will only really know its FQDN, then have a firstboot script SSH to our Ansible host and kick off the above command. However, when we do this, we get the below error:
ERROR! 'hostvars' is undefined
This suggests that the inventory is not parsed until a host list is provided, which sucks a lot. Is there another way to accomplish this?
A bit strange workflow, honestly.
Your setup doesn't work, because most of variables are not defined during playbook parse time.
You may be more lucky with defining single playbook with different plays for different groups (no need to set group var, just use correct host pattern (group name in my example)) and execute it limiting to specific host:
site.yml:
---
- hosts: group1
tasks:
- include: build-web-server-tasks.yml
- hosts: group2
tasks:
- include: build-db-server-tasks2.yml
command to provision specific server:
ansible-playbook -l host1.sub.domain.tld site.yml
You can develop your own dynamic inventory file so that all machines which needs to be bootstrapped will automatically added into your inventory and group respectively with out an manual entry in to the inventory file.
For developing dynamic inventory you can follow the below link:
http://docs.ansible.com/ansible/latest/dev_guide/developing_inventory.html
You can include multiple playbooks targeted to different groups as follows.
---
- hosts: all
tasks:
- include: build-web-server-tasks.yml
where: inventory_hostname in groups['group1']
- include: build-db-server-tasks2.yml
where: inventory_hostname in groups['group2']
inventory_hostname is the name of the hostname as configured in Ansible’s inventory host file. This can be useful for when you don’t want to rely on the discovered hostname ansible_hostname or for other mysterious reasons. If you have a long FQDN, inventory_hostname_short also contains the part up to the first period, without the rest of the domain.