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 -
Related
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"
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).
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
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.
I'm running an ansible playbook on a list of hosts with a host file:
[consul]
${HOST1} ansible_ssh_host=${HOST1} ansible_ssh_user=devops ansible_ssh_pass=blabla
${HOST2} ansible_ssh_host=${HOST2} ansible_ssh_user=devops ansible_ssh_pass=blabla
.......so on...
The thing is that I need to pass a different variable for each host.
I know of the flag -e that allows me to send a variable with the ansible-playbook command but it's not for each of the hosts.
I'm running the playbook with this:
ansible-playbook -vvvv site.yml
How can I pass a different var for each host?
Thanks!
Note: I'm using ansible 1.7.1
Two ways you should be able to do this:
1) Include the variable in your host file:
[consul]
${HOST1} ansible_ssh_host=${HOST1} .... myvar=x
${HOST2} ansible_ssh_host=${HOST2} .... myvar=y
2) Or use the include_vars task to load a file based on the host name
include_vars: "{{ ansible_ssh_host }}.yml"
The second method is good if you have a lot of variables to load for a host.
For more complex cases the lookups module might help:
http://docs.ansible.com/ansible/playbooks_lookups.html