Loop through the children host group ansible is failing - ansible

My inventory file is having below host groups:
[uat1]
123.11.23.22 ansible_user="xxx"
[OS_uat2]
123.45.6.7 ansible_user="yyy"
[uat1_childs:children]
uat1
OS_uat2
I am having the vars file which is having param for below hosts. I am running a playbook to run a shell command. I am passing some parameters with the playbook. I am passing deployment_environment as uat1_childs. This is giving me error. Playbook is:
- name: play to ping test
gather_facts: false
hosts: "{{ deployment_environment }}"
ignore_unreachable: yes
vars_files:
- r_params.yml
vars:
package: "{{ package }}"
tasks:
- set_fact:
env_param: "{{ deployment_environment }}"
- name: ping test
ping:
data: pong
- name: Deploy Services on "{{ deployment_environment }}"
shell: cd "{{ env_select[env_param].script_path }}"; sh "{{ env_select[env_param].script_path }}/deploy.sh" "param1" "param2" "{{ env_select[env_param].repo }}" "{{ artifact_version }}" "{{ env_select[env_param].ENV }}" "{{ arti_username }}" "{{ arti_pass }}" "{{ deployer }}" "{{ package }}" "{{ env_select[env_param].deployment_path }}"
when: (package == "abc")
with_items: "{{ groups[{{ 'deployment_environment' }}] }}"
This is giving me error as:
fatal: [123.11.23.22]: FAILED! =>
{
"msg": "'dict object' has no attribute 'deployment_environment'"
}
fatal: [123.45.6.7]: FAILED! =>
{
"msg": "'dict object' has no attribute 'deployment_environment'"
}
I tried removing apostrophe in with items, still it is giving me error. Cant identify how to run the task in all children host group.

Related

Ansible "item is undefined" when using {{ item }} in "vars" section

I have some codes like below, I want to iterate each host in groups['A'] and groups['B'] to create the group.
- name: Create a group
group:
name: "test_group"
state: "present"
delegate_to: "{{ item }}"
vars:
ansible_ssh_user: "{{ lookup('env', 'USER') }}#user#{{ item }}"
with_items:
- "{{ groups['A'] }}"
- "{{ groups['B'] }}"
Because I want to modify the ansible ssh connection user to connect to the "delegate_to" host, I override the ansible_ssh_user in this task, but it won't work and give me the error message like
FAILED! => {"msg": "'item' is undefined"}
But if I comment out the lines of
vars:
ansible_ssh_user: "{{ lookup('env', 'USER') }}#user#{{ item }}"
It gives no errors.
try changing the var to:
ansible_ssh_user: "{{ lookup('env', 'USER') }}#user#{{ ansible_hostname }}
this works fine for me:
- name: 'install public key on every server'
authorized_key:
user: '{{ myuser}}'
key: "{{ myuser.ssh_public_key }}"
delegate_to: '{{ item }}'
with_items:
- '{{ groups["A"] }}'
- '{{ groups["B"] }}'
- '{{ groups["C"] }}'
maybe you could try
but before I delegated a set_fact and recovered it locally...
Finally, I got a workaround, it involves all groups I need to use in my playbook.
And use "when" condition like
delegate_to: "{{ item }}"
with_items:
- "{{ groups['A'] }}"
- "{{ groups['B'] }}"
when: "inventory_hostname == item"
to let the task only run on the hosts mentioned in the "with_items" section.
It's not a very cool workaround but works for me...
Thank you for looking at this problem!

How to get the status of the each task in include task --playbook?

I am executing below as ansible playbook in loop with_together but need to know the status of the each task which is defined switch-host-config.yaml, but when i print register variable "sw_output" its not showing the task result it shows the with_together defined list...
is there any method or way to identify the task status in defined switch-host-config.yaml playbook.
- hosts: "{{ data_sw_ip1 }}"
connection: local
gather_facts: False
tasks:
- name: sw-host task
include_tasks: switch-host-config.yaml
vars:
- nic1_swport: "{{ item.0 }}"
- nic2_swport: "{{ item.1 }}"
- id_host: "{{ item.2}}"
register: sw_output
with_together:
- "{{ nic1_swport1 }}"
- "{{ nic2_swport }}"
- "{{ id_host }}"
ignore_errors: yes
- debug:
msg: "{{ sw_output }}"

get ansible groups by looping with_items

I'm trying to get the inventory host group names by below process which is not working
- debug:
msg: "{{ groups['{{ item }}'] }}"
with_items: "{{ vm.stdout_lines }}"
this is what actually I'm trying to do
I will get a list of servers by a shell script
- name: Getting the servers list
shell: |
sh getServers.sh
register: vm
Then adding them into inventory by add_host
- name: Creating Logical host_group for each server
add_host:
name: "{{ item }}"
groups: ["{{item }}"]
with_items: "{{ vm.stdout_lines }}"
register: inv
Here I'm trying to get the only groups I've added in above step instead of all groups
- debug:
msg: "{{ groups['{{ item }}'] }}"
with_items: "{{ vm.stdout_lines }}"
Error is
{"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute '{{ item }}'
Appreciate help on this!
Fix the syntax
msg: "{{ groups[item] }}"

Setting become_user conditionally

I am trying to shutdown databases in a loop, the catch is some databases run as a different user and others just run as oracle. I login as oracle user and run the playbook and if the database is run as oracle user it goes through fine. If it is running as a different user I would like to become that user (oracle user has permissions to do that).
Here is my main playbook:
[oracle#ansctrlsrv.localdomain epd3]$ cat test.yml
---
- hosts: testdrive
tasks:
- set_fact:
db_list: "{{ lookup('file', 'vars/' ~ inventory_hostname ~ '.dblist')|from_yaml }}"
- name: Shutdown running databases
include_tasks: shutdowndb.yml
loop: "{{ db_list }}"
DB list is as follows:
[oracle#ansctrlsrv.localdomain epd3]$ cat vars/dbsrv.localdomain.dblist
- ebs1
- ebs2
- ndb1
[oracle#ansctrlsrv.localdomain epd3]$ cat shutdowndb.yml
---
- debug: msg='Shutting down {{ item }}'
- name: Execute shutdown
shell: id "{{ item }}"
register: shutdown_output
become: "{{ item is search('ebs') | ternary('yes','no') }}"
become_user: "{{ item }}"
- debug: msg="{{ shutdown_output.stdout }}"
[oracle#ansctrlsrv.localdomain epd3]$ cat inventory
[testdrive]
dbsrv.localdomain
[oracle#ansctrlsrv.localdomain epd3]$ ansible-playbook -i inventory test.yml
TASK [Execute shutdown] ***
fatal: [dbsrv1.localdomain]: FAILED! => {"changed": false, "module_stderr": "Shared connection to dbsrv1.localdomain closed.\r\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1} ...ignoring
I tried this question on another thread but got closed, so trying another hand after realizing a few issues myself such as being unable to run blocks of code with a loop, etc.
Appreciate any help.
Set become user conditionally
Fix the line
shell: id "{{ item }}"
correct syntax (use shell only when necessary)
command: "id {{ item }}"
The playbook below
- hosts: testdrive
tasks:
- set_fact:
db_list: "{{ lookup('file', 'vars/' ~ inventory_hostname ~ '.dblist')|from_yaml }}"
- name: Shutdown running databases
include_tasks: shutdowndb.yml
loop: "{{ db_list }}"
with the included tasks
$ cat shutdowndb.yml
- debug:
msg:
- "shell: {{ 'shutdown.sh ' ~ item }}"
- "become: {{ item is search('ebs')|ternary('yes', 'no') }}"
- "become_user: {{ item }}"
give
"msg": [
"shell: shutdown.sh ebs1",
"become: yes",
"become_user: ebs1"
]
"msg": [
"shell: shutdown.sh ebs2",
"become: yes",
"become_user: ebs2"
]
"msg": [
"shell: shutdown.sh ndb1",
"become: no",
"become_user: ndb1"
]
Q: "Why the command whoami is still giving oracle rather than ebs1?"
A: Short answer: Because become is not set to True.
Debugging
1) Is it possible to become all of the users in db_list? Yes.
- hosts: test_01
become: no
remote_user: admin
vars:
db_list: ['ebs1', 'ebs2', 'ndb1']
tasks:
- command: whoami
become_user: "{{ item }}"
become: true
register: result
loop: "{{ db_list }}"
- debug:
msg: "{{ result.results|json_query('[].stdout') }}"
give
"msg": [
"ebs1",
"ebs2",
"ndb1"
]
2) Does search and ternary work properly? Yes.
- debug:
msg: "{{ item is search('ebs')|ternary(true, false) }}"
loop: "{{ db_list }}"
gives
"msg": true
"msg": true
"msg": false
3) Does become and become_user work properly?. Yes.
- command: whoami
become_user: "{{ item }}"
become: "{{ item is search('ebs')|ternary(true, false) }}"
register: result
loop: "{{ db_list }}"
- debug:
msg: "{{ result.results|json_query('[].stdout') }}"
give
"msg": [
"ebs1",
"ebs2",
"admin"
]

Variable with_items and hostvars

I need to pass a dynamic group name info with_items so that i can access a specific fact that is ran from another host. I cannot hard code the group name
I tried to set a generic variable that is passed as 'GroupName' a few different ways. Including
with_items: "{{ groups['{{GROUPNAME}}'] }}"
- name: Name of task
debug:
msg: "{{ hostvars[item]['ansible_check_mode'] }}"
with_items: "{{ groups['GROUPNAME'] }}"
fatal: [localhost]: FAILED! => {"msg": "'dict object' has no attribute '{{ GROUPNAME }}'"}
Get the list of the hosts in the group and loop them
vars:
my_group: GROUPNAME
tasks:
- set_fact:
my_hosts: "{{ groups|
dict2items|
selectattr('key', 'match', my_group)|
map(attribute='value')|
list|
flatten }}"
- debug:
msg: "{{ hostvars[item]['ansible_check_mode'] }}"
loop: "{{ my_hosts }}"
(not tested)

Resources