Execute playbook with different sudo users on different hosts - ansible

There are two hosts in the host list DEV and QA host
I need to execute playbook with dev_sudo_user for development env and qa_sudo_user for QA environment parallely
inventory details
[hostlist]
host1 ansible_become_user=dev_sudo_user
host2 ansible_become_user=qa_sudo_user
---
- hosts: hostlist
connection: ssh
gather_facts: false
remote_user: abcd
serial: 1
become: true
tasks:
- name: run Script
shell: python apps.py
register: result
- debug: var=result
I am able to get result for one host. I want result for both hosts

you have to use the become and become_user arguments. see example and output below.
hosts files with the variable as you had:
[test_group]
rhel-green become_user=root
rhel-blue become_user=devops
playbook:
- hosts: test_group
gather_facts: false
tasks:
- name: step 1
shell: "id"
register: shell_output
become_user: "{{ become_user }}"
become: true
- debug:
var: shell_output.stdout
execution output:
[root#ansible]# ansible-playbook -i hosts become_loop.yml
PLAY [test_group] ***************************************************************************************************************************************************************************************************
TASK [step 1] *******************************************************************************************************************************************************************************************************
changed: [rhel-blue]
changed: [rhel-green]
TASK [debug] ********************************************************************************************************************************************************************************************************
ok: [rhel-green] => {
"shell_output.stdout": "uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023"
}
ok: [rhel-blue] => {
"shell_output.stdout": "uid=1000(devops) gid=1000(devops) groups=1000(devops) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023"
}
PLAY RECAP **********************************************************************************************************************************************************************************************************
rhel-blue : ok=2 changed=1 unreachable=0 failed=0
rhel-green : ok=2 changed=1 unreachable=0 failed=0
[root#ansible]#

Related

How to execute on multiple hosts in ansible

I have a script that will execute in two parts. First it will execute on localhost and query a database table to get a hostname. second part of the script should run on the host which was registered in the query before. I am not able to set the host with the set_fact I did in the first part of the code.
this is what iam trying to do:
- hosts: localhost
gather_facts: false
become: yes
become_user: oracle
vars_files:
- vars/main.yml
tasks:
- name: Get new hostname
tempfile:
state: file
register: tf
- name: create sql file
template:
src: get_hostname.sql.j2
dest:"{{ tf.path }}"
mode: 0775
- name: login
command:
argv:
- "sqlplus"
- -s
- "#{{ tf.path }}"
environment:
ORACLE_HOME: "oracle/home"
register: command_out
- set_fact:
NEW_HOST: "{{ command_out.stdout }}"
- hosts: "{{ NEW_HOST }}"
gather_facts: false
become: yes
become_user: oracle
vars_file:
- vars/main.yml
tasks:
- name: debug
command: hostname
register: new_host_out
- debug:
msg: "new host is {{ new_host_out.stdout }}"
Everything works fine in the first part of the code, but errors out at the second part saying it cannot find the NEW_HOST.
Use hostvars to reference such a variable. Create a dummy host to keep this variable. For example, given the inventory
shell> cat hosts
dummy
[test]
test_11
test_12
test_13
The playbook creates the variable. See Delegated facts
shell> cat pb.yml
- hosts: localhost
tasks:
- set_fact:
NEW_HOST: test_12
delegate_to: dummy
delegate_facts: true
- debug:
var: hostvars.dummy.NEW_HOST
- hosts: "{{ hostvars.dummy.NEW_HOST }}"
gather_facts: false
tasks:
- debug:
var: inventory_hostname
gives
shell> ansible-playbook pb.yml
PLAY [localhost] ****************************************************************************
TASK [set_fact] *****************************************************************************
ok: [localhost -> dummy]
TASK [debug] ********************************************************************************
ok: [localhost] =>
hostvars.dummy.NEW_HOST: test_12
PLAY [test_12] ******************************************************************************
TASK [debug] ********************************************************************************
ok: [test_12] =>
inventory_hostname: test_12
PLAY RECAP **********************************************************************************
localhost: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
test_12 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
You can use localhost for this purpose as well. The playbook below works as expected
- hosts: localhost
tasks:
- set_fact:
NEW_HOST: test_12
- hosts: "{{ hostvars.localhost.NEW_HOST }}"
gather_facts: false
tasks:
- debug:
var: inventory_hostname

Ansible vars_prompt and msg usage prints hello world

Based on input from Zeitounator I have updated the original question. The following works
root#devenv:~/scripts/uia# cat addVlanTest.yml
---
- name: PLAY 111 Add Vlan ;
hosts: all
vars_prompt:
- name: vlanIdToAdd
prompt: vlan ID to add
private: no
default: "50"
tasks:
- name: "Debug task Take 1"
ansible.builtin.debug:
var: vlanIdToAdd
- name: "Debug task Take 2"
ansible.builtin.debug:
msg: "{{ vlanIdToAdd }}"
- name: "Debug task Take 3"
ansible.builtin.debug:
msg: "Creating vlan {{ vlanIdToAdd }}"
Correct:
msg: "Creating vlan {{ vlanIdToAdd }}"
Incorrect:
msg:"Creating vlan {{ vlanIdToAdd }}"
What is the scope ? Variables do not survive after plays. If you need to use it in a different play save it.
root#devenv:~/scripts/uia# cat addVlanTest.yml
---
- name: PLAY 111 Add Vlan ;
hosts: all
vars_prompt:
- name: vlanIdToAdd
prompt: vlan ID to add
private: no
default: "50"
tasks:
- name: "Debug vars Take 1"
debug:
var=vlanIdToAdd
- name: "Debug vars Take 1"
set_fact:
new_vlan_id="{{ vlanIdToAdd }}"
- name: PLAY 112 Add Vlan - IOS;
hosts: ios
tasks:
- name: "Debug vars Take 2"
debug:
var=new_vlan_id
As reported in my comment, vars_prompt are only available inside a given play as this is their scope. This is explained in plabooks variable documentation
From my suggestion, you have tried to use set_fact. As you will see in the same documentation, those vars are scoped to host and are only available while playing a task on host having the given fact. Meanwhile, you can access facts from other host using the hostvars magic variable
Here is one way to work arround this kind of chicken-egg problem. It might not be exactly what you are looking for but will hopefully give you some ideas for your best solution. I tried to make it self explanatory.
The following test.yml playbook:
---
- name: Play dedicated to vars_prompt and storing facts in localhost
hosts: localhost
gather_facts: false
vars_prompt:
- name: my_prompt
prompt: enter a value
private: no
tasks:
- name: store prompt in fact
set_fact:
my_prompt: "{{ my_prompt }}"
- name: Use fact on host a by directly calling it in a task
hosts: a
gather_facts: false
tasks:
- name: display the fact
debug:
msg: "{{ hostvars['localhost'].my_prompt }}"
- name: Use the fact on host b by first assigning to a play var
hosts: b
gather_facts: false
vars:
my_prompt: "{{ hostvars['localhost'].my_prompt }}"
tasks:
- name: display the fact
debug:
msg: "{{ my_prompt }}"
Gives:
$ ansible-playbook -i a,b, test.yml
enter a value: toto
PLAY [Play dedicated to vars_prompt and storing facts in localhost] ************************************************************************************************************************************************
TASK [store prompt in fact] ***************************************************************************************************************************************************************************************
ok: [localhost]
PLAY [Use fact on host a by directly calling it in a task] ********************************************************************************************************************************************************
TASK [display the fact] *******************************************************************************************************************************************************************************************
ok: [a] => {
"msg": "toto"
}
PLAY [Use the fact on host b by first assigning to a play var] ****************************************************************************************************************************************************
TASK [display the fact] *******************************************************************************************************************************************************************************************
ok: [b] => {
"msg": "toto"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
a : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
b : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Meanwhile, if this is possible in your scenario, you can as well set the fact on all hosts in your inventory so as to reuse it anywhere, this makes a much simpler playbook:
---
- name: Play dedicated to vars_prompt and storing facts on all host (except implicit localhost)
hosts: all
gather_facts: false
vars_prompt:
- name: my_prompt
prompt: enter a value
private: no
tasks:
- name: store prompt in fact
set_fact:
my_prompt: "{{ my_prompt }}"
- name: Use fact on host a
hosts: a
gather_facts: false
tasks:
- name: display the fact
debug:
msg: "{{ my_prompt }}"
- name: Use the fact on host b
hosts: b
gather_facts: false
tasks:
- name: display the fact
debug:
msg: "{{ my_prompt }}"
- name: Simple demo implicit localhost is not part of the all group and does not have the fact
hosts: localhost
gather_facts: false
tasks:
- name: show fact is undefined on localhost
debug:
var: my_prompt
Gives:
$ ansible-playbook -i a,b, test.yml
enter a value: titi
PLAY [Play dedicated to vars_prompt and storing facts on all host (except implicit localhost)] ********************************************************************************************************************
TASK [store prompt in fact] ***************************************************************************************************************************************************************************************
ok: [a]
ok: [b]
PLAY [Use fact on host a] *****************************************************************************************************************************************************************************************
TASK [display the fact] *******************************************************************************************************************************************************************************************
ok: [a] => {
"msg": "titi"
}
PLAY [Use the fact on host b] *************************************************************************************************************************************************************************************
TASK [display the fact] *******************************************************************************************************************************************************************************************
ok: [b] => {
"msg": "titi"
}
PLAY [Simple demo implicit localhost is not part of the all group and does not have the fact] *********************************************************************************************************************
TASK [show fact is undefined on localhost] ************************************************************************************************************************************************************************
ok: [localhost] => {
"my_prompt": "VARIABLE IS NOT DEFINED!"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
a : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
b : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Ansible delegate_to: localhost task running on remote host

I have paly to copy the web server logs from remote machine to Ansible machine. At the end of the playbook, I want to find the file with pattern and remove it. in the task I have defined delegate_to: 127.0.0.1 but this task is running one of the remote machine.
How to make these task run on only localhost and run once:
- name: Finds files and folders
find:
paths: "/tmp/"
patterns: "access-*.tar.gz"
recurse: no
use_regex: yes
register: result
delegate_to: 127.0.0.1
run_once: true
tags:
- pulllogs
- name: display filename
debug:
msg: "{{ result }}"
delegate_to: 127.0.0.1
run_once: true
tags:
- pulllogs
Output:
TASK [operate : Finds files and folders] ***********************************************************************************************************************************************
ok: [host01]
TASK [operate : display filename] ******************************************************************************************************************************************************
ok: [host01] =>
msg:
changed: false
examined: 640
failed: false
files: []
matched: 0
msg: ''
In Ansible 2.10 the delegation works as expected. In the output, I can't see the delegation either. But both plays, running at localhost and at delegated localhost respectively, show the same results. For example, given the archive at localhost
shell> sudo find /tmp -name 'access-*.tar.gz'
/tmp/access-01.tar.gz
and no archives at the remote host
shell> ssh admin#test_11 sudo find /tmp -name 'access-*.tar.gz'
the playbook
- hosts: localhost
tasks:
- find:
paths: /tmp
patterns: "access-*.tar.gz"
recurse: false
use_regex: false
register: result
- debug:
msg: "{{ result.files|map(attribute='path')|list }}"
- hosts: test_11,test_12,test_13
tasks:
- block:
- find:
paths: /tmp
patterns: "access-*.tar.gz"
recurse: false
use_regex: false
register: result
- debug:
msg: "{{ result.files|map(attribute='path')|list }}"
delegate_to: 127.0.0.1
run_once: true
shows the same results at localhost and delegated localhost
PLAY [localhost] **********************************************************
TASK [find] ***************************************************************
ok: [localhost]
TASK [debug] **************************************************************
ok: [localhost] =>
msg:
- /tmp/access-01.tar.gz
PLAY [test_11,test_12,test_13] ********************************************
TASK [find] ***************************************************************
ok: [test_11]
TASK [debug] **************************************************************
ok: [test_11] =>
msg:
- /tmp/access-01.tar.gz
PLAY RECAP ****************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
test_11 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Ansible hosts to be set to a substring of a passed variable

I have a play like this:
- name: Perform an action on a Runtime
hosts: all
roles:
- role: mule_action_on_Runtime
A variable at invocation (--extra-vars 'mule_runtime=MuleS01-3.7.3-Testing') has a prefix of the host needed (MuleS01). I want to set hosts: MuleS01. How do I do this?
Given that your pattern is always PartIWant-PartIDonCareAbout-AnotherPartAfterOtherDash you could use the split method of Python, then get the first item of the list via the Jinja filter first.
Here is full working playbook as example:
- hosts: local
gather_facts: no
tasks:
- debug:
msg: "{{ mule_runtime.split('-') | first }}"
This yield the recap:
play.yml --extra-vars 'mule_runtime=MuleS01-3.7.3-Testing'
PLAY [local] *******************************************************************
TASK [debug] *******************************************************************
ok: [local] => {
"msg": "MuleS01"
}
PLAY RECAP *********************************************************************
local : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
With the inventory
shell> cat hosts
MuleS01
MuleS02
MuleS03
this playbook
shell> cat pb.yml
- hosts: all
tasks:
- debug:
msg: Set {{ mule_runtime }}
when: mule_runtime.split('-').0 == inventory_hostname
gives
skipping: [MuleS02]
ok: [MuleS01] => {
"msg": "Set MuleS01-3.7.3-Testing"
}
skipping: [MuleS03]

Need to use host variables in Ansible (ansible engine 2.8 & ansible tower 3.5)

Need your help in achieving below:
- use variables provided inline with hostIP (i.e. host variables) in Ansible inventory
my inventory:
[ora_patch]
10.24.29.14 SID=orcl,orcl2
my playbook:
---
- hosts: [ora_patch]
tasks:
- debug:
var: "{{ hostvars[ansible_host]['SID'] }}"
Output ** I GET **:
PLAY [ora_patch] ************************************************************
TASK [patch_ora_si_122 : debug] *****************************************
ok: [10.24.29.14] => {
"orcl,orcl2": "(Undefined, Undefined)"
}
PLAY RECAP ******************************************************************
10.24.29.14 : ok=1 changed=0 unreachable=0 failed=0
Output ** I want ** :
PLAY [ora_patch] ***********************************************************
TASK [patch_ora_si_122 : debug] ****************************************
ok: [10.24.29.14] => {
"SID": "orcl,orcl2"
}
PLAY RECAP *****************************************************************
10.24.29.14 : ok=1 changed=0 unreachable=0 failed=0
Command I execute:
ansible-playbook -i inventory patch_ora_si_122.yml
Your playbook is slightly wrong. You are trying to use the content of the hostvar "{{ hostvars[ansible_host]['SID'] }}" as a variable name to display with debug: var=....
Simply change your playbook to
---
- hosts: ora_patch
tasks:
- debug:
msg: "SID: {{ hostvars[ansible_host]['SID'] }}"
or you could also use the variable name directly:
---
- hosts: ora_patch
tasks:
- debug:
var: SID
Ansible inventory.ini follows beloe format.
[hosts]
[hosts:vars]
The below should work:
[ora_patch]
10.24.29.14 SID=orcl,orcl2
[ora_patch:vars]
SID=orcl,orcl2

Resources