Pointing to a specific host under a group, Ansible - ansible

I have multiple host details under one group in my Ansible hosts file. Like below,
[web-server]
10.0.0.1 name=apache ansible_ssh_user=username
10.0.0.2 name=nginx ansible_ssh_user=username
My ansible playbook,
---
- hosts: web-server[0]
roles:
- role: apache
These details gets added dynamically in the hosts file and I have no control over the order of lines getting added under a group. Hence I can't use the logic web-server[0] or web-server[1]
I want to mention the host by filtering based on the "name" parameter in the playbook since name will be unique. Is there a way to do this, Kindly help.

If you can modify inventory file generation process, make it like this:
[web-server]
apache ansible_host=10.0.0.1 ansible_ssh_user=username
nginx ansible_host=10.0.0.2 ansible_ssh_user=username
And then use:
- hosts: apache

Related

How to set common ansible_user to all hosts in a group?

Does anyone know if ansible enables users share the same ansible_user settings across all hosts included in a group? This feature would be particularly useful when using some cloud computing platforms such as OpenStack, which enables users to launch multiple instances that share the same config, such as user accounts and SSH keys.
There are several behavioral parameters you can configure to modify the way Ansible connects to your host. Among them is the ansible_user variable. You can set it per host pr per group. You can also define a general ansible_user variable under the all hosts group, that you override at the group or host level.
If you were writing your inventory in just one hosts.yml file you'd do it like this:
all:
children:
ubuntu_linux:
hosts:
ubuntu_linux_1:
ubuntu_linux_2:
aws_linux:
hosts:
aws_linux_host_1:
aws_linux_host_2:
aws_linux_host_3:
vars:
ansible_user: ec2-user
vars:
ansible_host: ubuntu
And, if you are using a directory to create your inventory, you can set it inside the ./inventory/group/vars.yml file.
Check the "Connecting to hosts: behavioral inventory parameters" section of Ansible docs to see what other parameters you can configure.
I hope it helps

Ansible group variable evaluation with local actions

I have an an Ansible playbook that includes a role for creating some Azure cloud resources. Group variables are used to set parameters for the creation of those resources. An inventory file contains multiple groups which reference that play as a descendant node.
The problem is that since the target is localhost for running the cloud actions, all the group variables are picked up at once. Here is the inventory:
[cloud:children]
cloud_instance_a
cloud_instance_b
[cloud_instance_a:children]
azure_infrastructure
[cloud_instance_b:children]
azure_infrastructure
[azure_infrastructure]
127.0.0.1 ansible_connection=local ansible_python_interpreter=python
The playbook contains an azure_infrastructure play that references the actual role to be run.
What happens is that this role is run twice against localhost, but each time the group variables from cloud_instance_a and cloud_instance_b have both been loaded. I want it to run twice, but with cloud_instance_a variables loaded the first time, and cloud_instance_b variables loaded the second.
Is there anyway to do this? In essence, I'm looking for a pseudo-host for localhost that makes it think these are different targets. The only way I've been able to workaround this is to create two different inventories.
It's a bit hard to guess how you playbook look like, anyway...
Keep in mind that inventory host/group variables are host-bound, so any host always have only one set of inventory variables (variables defined in different groups overwrite each other).
If you want to execute some tasks or plays on your control machine, you can use connection: local for plays or local_action: for tasks.
For example, for this hosts file:
[group1]
server1
[group2]
server2
[group1:vars]
testvar=aaa
[group2:vars]
testvar=zzz
You can do this:
- hosts: group1:group2
connection: local
tasks:
- name: provision
azure: ...
- hosts: group1:group2
tasks:
- name: install things
apk: ...
Or this:
- hosts: group1:group2
gather_facts: no
tasks:
- name: provision
local_action: azure: ...
- name: gather facts
setup:
- name: install things
apk:
In this examples testvar=aaa for server1 and testvar=zzz for server2.
Still azure action is executed from control host.
In the second example you should turn off fact gathering and call setup manually to prevent Ansible from connecting to possibly unprovisioned servers.

Can I force current hosts group to be identified as another in a playbook include?

The current case is this:
I have a playbook which provisions a bunch of servers and installs apps to these servers.
One of these apps already has it's own ansible playbook which I wanted to use. Now my problem arises from this playbook, as it's limited to hosts: [prod] and the host groups I have in the upper-level playbook are different.
I know I could just use add_host to add the needed hosts to a prod group, but that is a solution which I don't like.
So my question is: Is there a way to add the current hosts to a new host group in the include statement?
Something like - include: foo.yml prod={{ ansible_host_group }}
Or can I somehow include only the tasks from a playbook?
No, there's no direct way to do this.
Now my problem arises from this playbook, as it's limited to
hosts: [prod]
You can setup host's more flexible via extra vars:
- name: add role fail2ban
hosts: '{{ target }}'
remote_user: root
roles:
- fail2ban
Run it:
ansible-playbook testplaybook.yml --extra-vars "target=10.0.190.123"
ansible-playbook testplaybook.yml --extra-vars "target=webservers"
Is this workaround suitable for you?

Use Ansible control master's IP address in Jinja template

I would like to insert an IP address in to a J2 template which is used by an Ansible playbook. That IP adress is not the address of the host which is being provisioned, but the IP of the host from which the provisioning is done. Everything I have found so far covers using variables/facts related to the hosts being provisioned.
In other words: the IP I’d like to insert is the one in ['ansible_default_ipv4']['address'] when executing ansible -m setup 127.0.0.1.
I think that I could use a local playbook to write a dynamically generated template file containing the IP, but I was hoping that this might be possible “the Ansible way”.
Just use this:
{{ ansible_env["SSH_CLIENT"].split()[0] }}
You can force Ansible to fetch facts about the control host by running the setup module locally by using either a local_action or delegate_to. You can then either register that output and parse it or simply use set_fact to give it a useful name to use later in your template.
An example play might look something like:
tasks:
- name: setup
setup:
delegate_to: 127.0.0.1
- name: set ansible control host IP fact
set_fact:
ansible_control_host_address: "{{ hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address'] }}"
delegate_to: 127.0.0.1
- name: template file with ansible control host IP
template:
src: /path/to/template.j2
dest: /path/to/destination/file
And then use the ansible_control_host_address variable in your template as normal:
...
Ansible control host IP: {{ ansible_control_host_address }}
...
This is how I solved the same problem (Ansible 2.7):
- name: Get local IP address
setup:
delegate_to: 127.0.0.1
delegate_facts: yes
- name: Add to hosts file
become: yes
lineinfile:
line: "{{ hostvars['127.0.0.1']['ansible_default_ipv4']['address'] }} myhost"
path: /etc/hosts
Seems to work like a charm. :-)

How to put condition for hosts in ansible playbook using ec2 dynamic inventory

In my Ansible playbook I want to use host with condition. For example: if the tag_Name_WebServer and tage_Environment_development.
So it should return me the list of the servers which are belongs to development environment and should have the Name tag as Webserver. Please help me to fix it.
I have tried with:
---
- name: Development WebServer Configuration
hosts: tag_Name_WebServer:tag_Name_Development
But the result I am getting is the instance list of all from WebServer and all from Environment Development. How to put the proper condition?
Got the solution. The condition should be like below:
---
- name: Development WebServer Configuration
hosts: tag_Name_WebServer:&tag_Name_Development
You will get the intersection of the two group in this case.

Resources