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.
Related
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
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
We have a "periodic" tag in our roles that is intended to be run at regular intervals by our Ansible box for file assurance, etc. Would it be possible to have a playbook for periodic runs that calls the other playbooks with the appropriate host groups and tags?
The only way to execute an Ansible playbook "with the appropriate host groups and tags" is to run ansible-playbook executable. This is the only case in which all the data structures starting from the inventory would be created in isolation from the currently running playbook.
You can simply call the executable using command module on the control machine:
- hosts: localhost
tasks:
- command: ansible-playbook {{ playbook }} --tags {{ tags }}
You can also use local_action or delegate_to.
It might be that you want to include plays, or use roles, however given the problem description in the question, it's impossible to tell.
Here is what we ended up with: It turns out that tags and variables passed on the command-line are inherited all the way down the line. This allowed us to pass this on the command line:
ansible-playbook -t periodic periodic.yml
Which calls a playbook like this:
---
- name: This playbook must be called with the "periodic" tag.
hosts: 127.0.0.1
any_errors_fatal: True
tasks:
- fail:
when: periodic not True
- name: Begin periodic runs for type 1 servers
include: type1-server.yml
vars:
servers:
- host_group1
- host_group2
- ...
- name: Begin periodic runs for type 2 servers
...
Our 'real' playbooks have - hosts: "{{ servers }}" so that they can be inherited from the parent. The tasks in our roles are tagged with "periodic" for things that need to be run on a schedule. We then use SystemD to schedule the runs. You can use cron, but SystemD is better IMHO. Examples can be provided upon request.
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.
Consider if I want to check something quickly. Something that doesn't really need connecting to a host (to check how ansible itself works, like, including of handlers or something). Or localhost will do. I'd probably give up on this, but man page says:
-i PATH, --inventory=PATH
The PATH to the inventory, which defaults to /etc/ansible/hosts. Alternatively, you can use a comma-separated
list of hosts or a single host with a trailing comma host,.
And when I run ansible-playbook without inventory, it says:
[WARNING]: provided hosts list is empty, only localhost is available
Is there an easy way to run playbook against no host, or probably localhost?
Prerequisites. You need to have ssh server running on the host (ssh localhost should let you in).
Then if you want to use password authentication (do note the trailing comma):
$ ansible-playbook playbook.yml -i localhost, -k
In this case you also need sshpass.
In case of public key authentication:
$ ansible-playbook playbook.yml -i localhost,
And the test playbook, to get you started:
- hosts: all
tasks:
- debug: msg=test
You need to have a comma in the localhost, option argument, because otherwise it would be treated as a path to an inventory. The inventory plugin responsible for parsing the value can be found here.
You can define a default inventory with only localhost
See it is explained here:
https://docs.ansible.com/ansible/latest/reference_appendices/config.html#the-configuration-file
And in your playbook add use this
- hosts: all
connection: local
tasks:
- debug: msg=test
It will use local connection so no SSH is required (thus it doesn't expose your machine). It might be quicker unless you need to troubleshoot a ssh issue.
Also for quicker feedback loop you can use: gather_facts: no you already know your target.