Ansible: How can I access a variable of other host? - ansible

How can I access a variable of other host? I'd like to access the slack_token varaiable of my localhost on the working_host.
- hosts: localhost
vars:
slack_token: 123123123
tasks:
- block:
- name: test
debug: msg="{{ slack_token }}"
- hosts: "{{ working_host }}"
vars:
slack_token: "{{ hostvars['localhost']['slack_token'] }}"
tasks:
- block:
- name: test2
debug: msg={{ slack_token }}
The error message:
fatal: [localhost]: FAILED! => {"failed": true, "msg": "the field
'args' has an invalid value, which appears to include a variable that
is undefined. The error was: {{ hostvars['localhost']['slack_token']
}}: 'dict object' has no attribute 'slack_token'
Any idea?

Just answered a somewhat same question in my previous post.
Here's what I used:
set_fact:
myVar: "{{ hostvars[groups['all'][0]]['slack_token'] | default(False) }}"
But you're using two plays in a playbook.
You can also try to copy a file to a machine stating the fact.

To access slack_token from everywhere, either:
pass it as extra variable with -e slack_token=zzzz
define it in your inventory under all group

Related

Loop through the children host group ansible is failing

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.

Ansible nested braces or nested quotes

Using ansible 2.9 I set a variable like this to store part of a group name
- name: set group
set_fact:
ansible_group: aaaa
I then want to use this variable in the following with_items clause:
- name: get
uri:
url: "http://{{ item }}:5324/kjhfg"
with_items: "{{ groups['thisgroup_{{ ansible_group }}'] }}"
However, using nested curly braces gives me the following error:
FAILED! => {"msg": "'dict object' has no attribute 'thisgroup_{{ ansible_group }}'"}
I also tried the following syntax variations
with_items: "{{ groups['thisgroup_ansible_group'] }}"
with_items: "groups['thisgroup_{{ ansible_group }}']"
with_items: "{{ groups['thisgroup_hostvars['localhost']['ansible_group']'] }}"
with_items: "{{ groups['thisgroup_hostvars[''localhost''][''ansible_group'']'] }}"
with_items: "{{ groups['thisgroup_hostvars[`localhost`][`ansible_group`]'] }}"
and probably one hundred other variations which all of them produced various errors
Can someone help me figure out the right syntax?
Simply concatenate the name of the group, e.g. given the inventory
shell> cat hosts
[thisgroup_aaaa]
host1
host2
host3
the playbook
- hosts: all
gather_facts: false
vars:
ansible_group: aaaa
_group: "{{ groups['thisgroup_' ~ ansible_group] }}"
tasks:
- debug:
var: item
loop: "{{ _group }}"
run_once: true
gives
item: host1
item: host2
item: host3

Ansible hostvars variable undefined when debugging/templating etc

I'm trying to dynamically generate part of an /etc/hosts file with ansible, by gathering facts from all the hosts and looping through the resulting hostvars to grab the IP of the second interface (I need a private IP on this interface, rather than the public IP of the other interface)
I can grab this information from a single host using the following plays:
- name: play 1
hosts: all
- name: play 2
hosts: localhost
connection: local
become: no
tasks:
- debug:
var: hostvars['mysinglehost'].ansible_all_ipv4_addresses[1]
...but what I'd like to do is loop through all the hosts and get this value from every host, eventually writing this information to my hosts file, but I'd settle for just getting some debug information :)
I tried
...
- debug:
var: hostvars[item].ansible_all_ipv4_addresses[1]
with_inventory_hostnames:
- all
...
...which gives the output I expect, yet when I try to output a msg with this debug task:
...
- debug:
msg: "{{ hostvars[item].ansible_all_ipv4_addresses[1] }}"
with_inventory_hostnames:
- all
...
I get the following error (as I do when I attempt to e.g. write to a file using lineinfile):
fatal: [localhost]: FAILED! =>
msg: |-
The task includes an option with an undefined variable. The error was: 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'ansible_all_ipv4_addresses'
I'm not sure why this is happening, as it's trying to reference the exact same variable. Is there a way to do this?
I've not tested this, but in principle, perhaps this would work?
- hosts: all
- hosts: localhost
gather_facts: false
tasks:
- set_fact:
my_hosts: |
{
{% for a_host in hostvars | dict2items %}
"{{ a_host.key }}": "{{ a_host.value.ansible_all_ipv4_addresses[1] }}",
{% endfor %}
}
Then, instead of looping over hostvars, you just loop over my_hosts?

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] }}"

iteration using with_items and register

Looking for help with a problem I've been struggling with for a few hours. I want to iterate over a list, run a command, register the output for each command and then iterate with debug over each unique registers {{ someregister }}.stdout
For example, the following code will spit out "msg": "1" and "msg": "2"
---
- hosts: localhost
gather_facts: false
vars:
numbers:
- name: "first"
int: "1"
- name: "second"
int: "2"
tasks:
- name: Register output
command: "/bin/echo {{ item.int }}"
register: result
with_items: "{{ numbers }}"
- debug: msg={{ item.stdout }}
with_items: "{{ result.results }}"
If however, I try and capture the output of a command in a register variable that is named using with_list, I am having trouble accessing the list or the elements within it. For example, altering the code slightly to:
---
- hosts: localhost
gather_facts: false
vars:
numbers:
- name: "first"
int: "1"
- name: "second"
int: "2"
tasks:
- name: Register output
command: "/bin/echo {{ item.int }}"
register: "{{ item.name }}"
with_items: "{{ numbers }}"
- debug: var={{ item.name.stdout }}
with_items: "{{ numbers }}"
Gives me:
TASK [debug]
> ******************************************************************* fatal: [localhost]: FAILED! => {"failed": true, "msg": "'unicode
> object' has no attribute 'stdout'"}
Is it not possible to dynamically name the register the output of a command which can then be called later on in the play? I would like each iteration of the command and its subsequent register name to be accessed uniquely, e.g, given the last example I would expect there to be variables registered called "first" and "second" but there aren't.
Taking away the with_items from the debug stanza, and just explicitly defining the var or message using first.stdout returns "undefined".
Ansible version is 2.0.2.0 on Centos 7_2.
Thanks in advance.
OK so I found a post on stackoverflow that helped me better understand what is going on here and how to access the elements in result.results.
The resultant code I ended up with was:
---
- hosts: localhost
gather_facts: false
vars:
numbers:
- name: "first"
int: "1"
- name: "second"
int: "2"
tasks:
- name: Register output
command: "/bin/echo {{ item.int }}"
register: echo_out
with_items: "{{ numbers }}"
- debug: msg="item.item={{item.item.name}}, item.stdout={{item.stdout}}"
with_items: "{{ echo_out.results }}"
Which gave me the desired result:
"msg": "item.item=first, item.stdout=1"
"msg": "item.item=second, item.stdout=2"
I am not sure if I understand the question correctly, but maybe this can help:
- debug: msg="{{ item.stdout }}"
with_items: echo_out.results
Please note that Ansible will print each item and the msg both - so you need to look carefully for a line that looks like "msg": "2".

Resources