Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug Report: Accessing variables of other hosts does not work from j2 template #9260

Closed
kosmodromov opened this issue Oct 3, 2014 · 25 comments
Closed

Comments

@kosmodromov
Copy link

@kosmodromov kosmodromov commented Oct 3, 2014

Issue Type:

Bug Report: Accessing variables of other hosts does not work from j2 template

Ansible Version:

ansible 1.7.2

Environment:

Running ansible from mac os mavericks, manage CentOS 7

Summary:

I can't get variables from other hosts from j2 template through {{hostvars[servers]['ansible_default_ipv4']['address']}} construction.

This is code from template.

{% if inventory_hostname in groups['haproxy_front'] %}
{% for servers in groups['front'] %}
    server  {{servers}} {{hostvars[servers]['ansible_default_ipv4']['address']}}:80 check
{% endfor %}
{% endif %}

Check this variables on hosts in 'front' group

ansible front -m setup |grep ansible_default_ipv4
        "ansible_default_ipv4": {
        "ansible_default_ipv4": {

Got this error when run playbook

fatal: [orion.host.ru] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'dict object' has no attribute 'ansible_default_ipv4'", 'failed': True}
fatal: [orion.host.ru] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'dict object' has no attribute 'ansible_default_ipv4'", 'failed': True}

Code from playbook

- name: Copy config
  template: src=haproxy.cfg.j2 dest=/etc/haproxy/haproxy.cfg owner=root group=root mode=0644
Steps To Reproduce:

Expected Results:

Get ip addresses from hosts in group 'front' with construction {{hostvars[servers]['ansible_default_ipv4']['address']}}

Actual Results:
fatal: [orion.host.ru] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'dict object' has no attribute 'ansible_default_ipv4'", 'failed': True}
fatal: [orion.host.ru] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'dict object' has no attribute 'ansible_default_ipv4'", 'failed': True}
@mpdehaan

This comment has been minimized.

Copy link
Contributor

@mpdehaan mpdehaan commented Oct 3, 2014

List Information

Hi!

Thanks very much for your interest in Ansible. It sincerely means a lot to us.

This appears to be a user question, and we'd like to direct these kinds of things to either the mailing list or the IRC channel.

If you can stop by there, we'd appreciate it. This allows us to keep the issue tracker for bugs, pull requests, RFEs and the like.

Thank you once again and we look forward to seeing you on the list or IRC. Thanks!

@mpdehaan mpdehaan closed this Oct 3, 2014
@soulmachine

This comment has been minimized.

Copy link

@soulmachine soulmachine commented Mar 6, 2015

Today I bumped into this bug too. As follows:

- debug: msg="{{ hostvars[inventory_hostname].ansible_default_ipv4.address }} {{ hostvars[inventory_hostname]["ansible_fqdn"] }} {{ hostvars[inventory_hostname]["ansible_hostname"] }}"

This line runs fine.

But if I put this line into a template,

{% for host in groups['all'] %}
{{ hostvars[host]["ansible_default_ipv4"].address }} {{ hostvars[host]["ansible_fqdn"] }} {{ hostvars[host]["ansible_hostname"] }}
{% endfor %}

It will complain:

fatal: [us0701aopc172018080143] => {'msg': "One or more undefined variables: 'dict' object has no attribute 'ansible_default_ipv4'", 'failed': True}

My ansible version is 1.5.5, after I upgrade to 1.9, my template runs fine.

@drzraf

This comment has been minimized.

Copy link
Contributor

@drzraf drzraf commented Apr 21, 2015

Ansible 1.7.2: bug is here

@jaytaylor

This comment has been minimized.

Copy link
Contributor

@jaytaylor jaytaylor commented Apr 24, 2015

I am also running into this issue.

fatal: [a.b.c.d] => One or more undefined variables: 'dict object' has no attribute 'ansible_default_ipv4'

Code:

- name: "Build hosts file (cloud)"
  lineinfile: dest=/etc/hosts regexp=".*(?:{{ item }}|{{ hostvars[item].hostname }}).*$" line="{{ hostvars[item].ansible_default_ipv4.address }} {{ hostvars[item].hostname }} {{ hostvars[item].hostname }}-{{ region_name }}.{{ domain_name }}" state=present
  with_items: groups["all"]
  when: (env is not defined or env != "lan") and hostvars[item].hostname is defined and hostvars[item].hostname != "" and item != inventory_hostname
  tags:
    - etc-hosts

Even when I have specified gather_facts: yes beforehand, this error still occurs.

My Ansible version is 1.9.0.

_UPDATE_

I narrowed the cause down to running ansible-playbook with --limit host1,host2. When it is run this way, it appears that information about the other hosts is not available.

I don't think there is a real bug here per sé, it seems more likely to be a user expectation vs. reality impedance mismatch.

@drzraf

This comment has been minimized.

Copy link
Contributor

@drzraf drzraf commented Apr 25, 2015

I think it's a bug that ipv4/ipv6 of other hosts (and only these specific facts) aren't known.
Public ip are known from the inventory, or .ssh/config or even DNS requests, Ansible should provides this facts without having to "gather"" anything. About the other facts, well, that's another story (for which workaround alreadys exists like running a no-op task on said machines)

@jayunit100

This comment has been minimized.

Copy link

@jayunit100 jayunit100 commented Jul 2, 2015

is this still a bug ? I see it in 1.9?

@kosmodromov

This comment has been minimized.

Copy link
Author

@kosmodromov kosmodromov commented Jul 3, 2015

In my case it was my fault because before using facts you will need to take them from hosts. You may take them by running this code in beginning of your playbook.

- hosts: all
  tasks: []
@rk-git

This comment has been minimized.

Copy link

@rk-git rk-git commented Sep 4, 2015

Why is this not a defect? How do I collect an attribute, say default IPv4 address, from each host to emit a configuration?

The "- host: all, tasks: []' method did not work as well.

Thanks,

Rk

@kosmodromov

This comment has been minimized.

Copy link
Author

@kosmodromov kosmodromov commented Sep 5, 2015

It works for me and I can get any available attribute from any host after that.

@visik7

This comment has been minimized.

Copy link

@visik7 visik7 commented Oct 16, 2015

It works for me but I sophisticated a bit to be more usefull indeed

# Allow all host to be hitted even if nothing is executed
- hosts: all
  tasks:
     - name: Ping 
       ping:
@visik7

This comment has been minimized.

Copy link

@visik7 visik7 commented Oct 17, 2015

not working with ansible ad-hoc command:

bin/ansible all -m debug -a var=myvar -i inventory/test3.ini

myvar is:

myvar: "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST={{ hostvars[groups['oracle_servers'][0]]['ansible_fqdn'] }})(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=ACME)))"

Expected Result:

server01.lan.test3.dev.acme.com | FAILED! => {
    "failed": true, 
    "msg": "ERROR! ERROR! ERROR! 'dict object' has no attribute 'ansible_fqdn'"
}

Actual Result:

server01.lan.test3.dev.acme.com | success >> {
    "myvar": "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=dbms01.lan.test3.dev.acme.com)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=ACME)))"
}

Version tested

  • 1.9.4
  • v2.0.0-0.3.beta1 (devel)
@zstarer

This comment has been minimized.

Copy link

@zstarer zstarer commented Oct 20, 2015

ad hoc works for me, doesn't work in a .j2 template at the moment.

on 1.8.4

@javiervegas

This comment has been minimized.

Copy link

@javiervegas javiervegas commented Nov 6, 2015

Yes, this used to work in a .j2 template in ansible 1.7 but is broken in 1.8 and 1.9.

@AAbouZaid

This comment has been minimized.

Copy link

@AAbouZaid AAbouZaid commented Mar 24, 2016

This issue still affect Ansible 2.0.1.0!
@kosmodromov 's workaround worked for me, but I think we need to more standard way to do this.

joe1chen added a commit to joe1chen/Apollo that referenced this issue Mar 28, 2016
…nning ansible from Mac OS X systems. The underlying bug is a problem with ansible (ansible/ansible#9260).  This bug is responsible for Capgemini#679.
@sadsfae

This comment has been minimized.

Copy link

@sadsfae sadsfae commented Jun 23, 2016

I still see this behavior on 2.1.0.
The proposed workaround works for me if add the following to my playbook.

- hosts: all
  remote_user: root
  tasks: []
sadsfae added a commit to sadsfae/ansible-nagios that referenced this issue Jun 23, 2016
We are currently hitting two Ansible bugs that prevent the
template-driven generation of config files from working properly.

ansible/ansible#9260
ansible/ansible#15525
@ftaeger

This comment has been minimized.

Copy link

@ftaeger ftaeger commented Nov 1, 2016

Same here with 2.1.2.0 on mac os x sierra

this is really breaking my /etc/hosts depoyments of large scale setups. This is just bad!

@mahesh-kore

This comment has been minimized.

Copy link

@mahesh-kore mahesh-kore commented Nov 4, 2016

Any update/fix for this..??

@jarosite

This comment has been minimized.

Copy link

@jarosite jarosite commented Nov 4, 2016

I faced with same issue, but now I think it is not right way to use ansible for managing /etc/hosts or for service discovery in large scale setup. By the way, workaround still works for me.

@mahesh-kore

This comment has been minimized.

Copy link

@mahesh-kore mahesh-kore commented Nov 4, 2016

what is the workaround you have tried.?

@eagleusb

This comment has been minimized.

Copy link

@eagleusb eagleusb commented Nov 23, 2016

I had the same issue, in my understanding hostvars can't output facts of machines outside of the targets.

That's why you need to gather the facts of all your hosts by running an empty list of tasks against all the hosts.

See https://docs.ansible.com/ansible/playbooks_variables.html#magic-variables-and-how-to-access-information-about-other-hosts

@DanSlutzky

This comment has been minimized.

Copy link

@DanSlutzky DanSlutzky commented Jun 24, 2017

I solved this problem by using this

  • hosts: server
    serial: 10

before it was "serial: 1" but in my case I have several instances.

@ghost

This comment has been minimized.

Copy link

@ghost ghost commented Aug 10, 2017

Unfortunately gathering facts does not work:

(env) Yves-iMac:ansible-provisioning Yves$ ansible-playbook backuppc-servers.yml  --diff --tags backuppc-clients

PLAY [host1.example.com] *************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************************************************************************************************************************************
ok: [host1.example.com]

PLAY [backuppc-servers] *******************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************************************************************************************************************************************
ok: [another.example.org]

TASK [backuppc : Configure BackupPC clients] **********************************************************************************************************************************************************************************************************************************
failed: [another.example.org] (item=host1.example.com) => {"failed": true, "item": "host1.example.com", "msg": "AnsibleUndefinedVariable: 'ansible.vars.hostvars.HostVars object' has no attribute u'host1.example.com'"}
	to retry, use: --limit @/Users/Yves/Infrastructure/ansible-provisioning/backuppc-servers.retry

PLAY RECAP ********************************************************************************************************************************************************************************************************************************************************************
host1.example.com     : ok=1    changed=0    unreachable=0    failed=0   
another.example.org : ok=1    changed=0    unreachable=0    failed=1  

That's the template.

# {{ ansible_managed }}

$Conf{RsyncdUserName} = "{{ backuppc_clients[item].config.username }}";
$Conf{RsyncdPasswd} = "{{ (hostvars[item].rsyncd.users | selectattr('name', 'equalto', backuppc_clients[item].config.username) | first).password }}";
$Conf{RsyncShareName} = "{{ backuppc_clients[item].config.share | default('root') }}";
ansible -m debug -a "var=hostvars['host1.example.com']" localhost
localhost | SUCCESS => {
    "hostvars['host1.example.com']": {
        "ansible_check_mode": false, 
        "ansible_playbook_python": "/Users/Yves/Infrastructure/ansible-provisioning/env/bin/python", 
        "ansible_user": "vogl", 
        "ansible_version": {
            "full": "2.3.1.0", 
            "major": 2, 
            "minor": 3, 
            "revision": 1, 
            "string": "2.3.1.0"
        }, 
        (…)
        "inventory_dir": "/Users/Yves/Infrastructure/ansible-provisioning/inventories", 
        "inventory_file": null, 
        "inventory_hostname": "host1.example.com", 
        "inventory_hostname_short": "host1", 
        "omit": "__omit_place_holder__5a1606e776bc49129dffad56e629d9fae8206a16", 
        "playbook_dir": "."
    }
}

To me it looks like a bug in ansible 2.3.1.0

@MPW1412

This comment has been minimized.

Copy link

@MPW1412 MPW1412 commented Sep 15, 2017

Still doesn't work inansible 2.3.2.0. Can someone please fix this? @mpdehaan

@danielmotaleite

This comment has been minimized.

Copy link

@danielmotaleite danielmotaleite commented Sep 15, 2017

People having problems with hostvars, please check the above documentation ticket, specially the
https://docs.ansible.com/ansible/latest/playbooks_variables.html#fact-caching , as it should solve most problems.

Notice that this documentation is when hostvars is requesting a hostname that do not belong to the current server group. If your hostname do exists in the current server group and you are not using --limit= then it should be a different problem

@MPW1412

This comment has been minimized.

Copy link

@MPW1412 MPW1412 commented Sep 16, 2017

I didn't notice, that I was accessing hostvars from another group. Preloading those facts with

- name: get hostvars information
  hosts: other_groupname
  remote_user: root
  tasks: []

as first lines in my yml worked! Thanks for all the tips!

@ansible ansible locked and limited conversation to collaborators Apr 25, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
You can’t perform that action at this time.