Ansible run same role multiple times using different variable files - ansible

Supose I have a server that is used to serve one static website (e.g. catpics.com). Using Ansible, I have a base role (used to set up firewall, time, user accounts, etc.), a letsencrypt role (gets TLS certificates for a website), and a webserver role (creates web root directory for a website).
Now I want to host another website (e.g. snakepics.com) on this same server. With this new addition, the base role still needs to be run once, but the letsencrypt and webserver roles now need to be run twice. At this point, I have two variable files:
vars/catpics.com:
---
domain_name: catpics.com
# and other variables...
...
vars/snakepics.com:
---
domain_name: snakepics.com
# and other variables...
...
Now that I have these two variable files, how do I run both the letsencrypt and webserver roles twice? (once using the vars/catpics.com variables file, and once using the vars/snakepics.com variables file)

You can use different Host Groups to make it run for each type and achieve your goal. There are 2 types of variables for hosts.
Host Variable which is specific to that individual host that is within a group
Group Variable which is for that whole host group
inventory / hosts file.
[catpics]
catpics.com http_port=301
morecatpics.com http_port=80
[snakepics]
snakepics.com
moresnakepics.com
note the http_port= is a Host Variable that is inline with the hostname declaration, seperated by a space
then in that same file, using the host:vars naming format, you define the Group Variables which is for the whole group. So all snakepics hosts will have those variables and all catpics hosts will have theirs, but keeping their individual Host Variables ie. http_port=
[snakepics:vars]
FQDN= https://www.snake.com
VAR2= something2
[catpics:vars]
FQDN= https://www.cat.com
VAR2= something2
So great, now we've got the hosts setup, we can define what roles are run for each host. The same role will be run
- hosts: catpics
roles:
- letsencrypt
- webserver
- hosts: snakepics
roles:
- letsencrypt
- webserver
or in this case, hosts could simply look like - hosts: all and it will get the vars corresponding to each type of host (snake and cat).
To call the variables is like any other ansible variable fetch {{ variable_name }} when running a task in a role:
-name: Show how variables like this work
domain_name: "{{ FQDN }}"
some_other_task_variable: "{{VAR2}}"
For reference:
Host and Group variables
Now that will solve your issue in the quickest way. The current best practice for using group and host variables uses a seperate file in the group_vars/*role_name_file* directory to automatically fetch all the variables for each Host Group

Related

How can I limit the hosts in a Template on AWX?

The hosts which I address in the Playbook maint-change.yml belong to two Groups (instancegroup1 & instancegroup2 with sveral hosts in each group) like this:
- hosts: "{{ server | default('instancegroup1 instancegroup2') }}"
So if I just want to run the Playbook against one host I will limit with (-e EXTRA_VARS) the variable server and the hostname from the instance:
ansible-playbook maint-change.yml -e server=test.instance2
In that Case the "test.instance2" is listet in the inventory file of instancegroup2 and the playbook will only run against the host "test.instance2" successfully.
But how is is that possible with awx? If I have created the template with the same Playbook "maint-change.yml" which is using the variable server as I mentioned above, it's not possible to paste the "server=test.instance2" in the EXTRA VARIABLES field of the Template. Is there any Solution to set the specific variable server from the Playbook in the EXTRA VARIABLES field from awx's Template?
I believe you are using AWX Job templates. You can use the limit check option in your templates. Here's a screenshot of that -

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

how to run commands on different servers with different users

I have to check the status of my databases which runs on many servers with different user ids for example: on server1 it runs with user1 on server2 it runs with user2 etc. In my playbook, I have the code to check the database status but don't know how to run this on different hosts and different user ids.
I have written playbook which can check the database status but doesn't know how to make this run with different user ids on different servers.
Playbook:
---
- hosts: all
become: true
become_user: db2inst1
tasks:
- name: Start DB2
command: /home/db2inst1/sqllib/adm/db2_ps
Inventory:
[db-servers]
192.168.4.30
You should take a look at the "Connecting to hosts: behavioral inventory parameters" section of Ansible Docs. It explains all the variables you can set to modify Ansible's behavior on each host.
In your case, you are going to have to define the ansible_user variable to use on each host, and the corresponding authentication details (passwords, ssh keys, etc.)
You can configure these variables on your inventory files. For example, suppose that you need to use the user root for some server, and ubuntu for another. You can configure your playbook like this.
[db-servers]
192.168.4.30 ansible_user=root
192.178.4.31 ansible_user=ubuntu
I hope it helps.

Ansible: Include playbook according to inventory variable

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.

Resources