Skip to content

Variable templating not working correctly when delegating #46600

@jimmymccrory

Description

@jimmymccrory
SUMMARY

When looping through a list of variables and delegating to a templated host, only the first host's variables are templated correctly.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

lib/ansible/vars/manager.py

ANSIBLE VERSION
ansible 2.7.0
  config file = None
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /tmp/ants/local/lib/python2.7/site-packages/ansible
  executable location = /tmp/ants/bin/ansible
  python version = 2.7.12 (default, Dec  4 2017, 14:50:18) [GCC 5.4.0 20160609]
CONFIGURATION
OS / ENVIRONMENT

Ubuntu

STEPS TO REPRODUCE
[group1]
host1 some_var=1 some_other_var=a
host2 some_var=2 some_other_var=b

[group2]
localhost connection=local
---
- hosts: group1
  gather_facts: no
  tasks:
    - file:
        path: "/tmp/{{ item }}"
        state: "directory"
      with_items:
        - "{{ some_var }}"
        - "{{ some_other_var }}"
      delegate_to: "{{ groups['group2'][0] }}"

    - assert:
        that:
          - "'/tmp/1' is directory"
          - "'/tmp/a' is directory"
          - "'/tmp/2' is directory"
          - "'/tmp/b' is directory"
EXPECTED RESULTS

PLAY [group1] **********************************************************************************************************************************************************************************************************************

TASK [file] ************************************************************************************************************************************************************************************************************************
changed: [host1 -> localhost] => (item=1)
changed: [host2 -> localhost] => (item=2)
changed: [host1 -> localhost] => (item=a)
changed: [host2 -> localhost] => (item=b)

TASK [assert] **********************************************************************************************************************************************************************************************************************
ok: [host1] => {
    "changed": false,
    "msg": "All assertions passed"
}
ok: [host2] => {
    "changed": false,
    "msg": "All assertions passed"
}

PLAY RECAP *************************************************************************************************************************************************************************************************************************
host1                      : ok=2    changed=1    unreachable=0    failed=0
host2                      : ok=2    changed=1    unreachable=0    failed=0
ACTUAL RESULTS
ansible-playbook /tmp/play.yml -i /tmp/inventory
PLAY [group1] **********************************************************************************************************************************************************************************************************************

TASK [file] ************************************************************************************************************************************************************************************************************************
changed: [host2 -> localhost] => (item=1)
ok: [host1 -> localhost] => (item=1)
changed: [host2 -> localhost] => (item=a)
ok: [host1 -> localhost] => (item=a)

TASK [assert] **********************************************************************************************************************************************************************************************************************
fatal: [host1]: FAILED! => {
    "assertion": "'/tmp/2' is directory",
    "changed": false,
    "evaluated_to": false,
    "msg": "Assertion failed"
}
fatal: [host2]: FAILED! => {
    "assertion": "'/tmp/2' is directory",
    "changed": false,
    "evaluated_to": false,
    "msg": "Assertion failed"
}
	to retry, use: --limit @/tmp/play.retry

PLAY RECAP *************************************************************************************************************************************************************************************************************************
host1                      : ok=1    changed=0    unreachable=0    failed=1
host2                      : ok=1    changed=1    unreachable=0    failed=1
ansible-playbook /tmp/play.yml -i /tmp/inventory -vvvv
ansible-playbook 2.7.0
  config file = None
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /tmp/ansible27/local/lib/python2.7/site-packages/ansible
  executable location = /tmp/ansible27/bin/ansible-playbook
  python version = 2.7.12 (default, Dec  4 2017, 14:50:18) [GCC 5.4.0 20160609]
No config file found; using defaults
setting up inventory plugins
Set default localhost to localhost
Parsed /tmp/inventory inventory source with ini plugin
Loading callback plugin default of type stdout, v2.0 from /tmp/ansible27/local/lib/python2.7/site-packages/ansible/plugins/callback/default.pyc

PLAYBOOK: play.yml *****************************************************************************************************************************************************************************************************************
1 plays in /tmp/play.yml

PLAY [group1] **********************************************************************************************************************************************************************************************************************
META: ran handlers

TASK [file] ************************************************************************************************************************************************************************************************************************
task path: /tmp/play.yml:5
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root
<localhost> EXEC /bin/sh -c 'echo ~root && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1538925580.98-215028109547484 `" && echo ansible-tmp-1538925580.98-215028109547484="` echo /root/.ansible/tmp/ansible-tmp-1538925580.98-215028109547484 `" ) && sleep 0'
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root
<localhost> EXEC /bin/sh -c 'echo ~root && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1538925580.99-197840915774272 `" && echo ansible-tmp-1538925580.99-197840915774272="` echo /root/.ansible/tmp/ansible-tmp-1538925580.99-197840915774272 `" ) && sleep 0'
Using module file /tmp/ansible27/local/lib/python2.7/site-packages/ansible/modules/files/file.py
Using module file /tmp/ansible27/local/lib/python2.7/site-packages/ansible/modules/files/file.py
<localhost> PUT /root/.ansible/tmp/ansible-local-29097PyqY1S/tmpAmGzBD TO /root/.ansible/tmp/ansible-tmp-1538925580.98-215028109547484/AnsiballZ_file.py
<localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1538925580.98-215028109547484/ /root/.ansible/tmp/ansible-tmp-1538925580.98-215028109547484/AnsiballZ_file.py && sleep 0'
<localhost> PUT /root/.ansible/tmp/ansible-local-29097PyqY1S/tmp31OJ_0 TO /root/.ansible/tmp/ansible-tmp-1538925580.99-197840915774272/AnsiballZ_file.py
<localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1538925580.99-197840915774272/ /root/.ansible/tmp/ansible-tmp-1538925580.99-197840915774272/AnsiballZ_file.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1538925580.98-215028109547484/AnsiballZ_file.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1538925580.99-197840915774272/AnsiballZ_file.py && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1538925580.99-197840915774272/ > /dev/null 2>&1 && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1538925580.98-215028109547484/ > /dev/null 2>&1 && sleep 0'
changed: [host1 -> localhost] => (item=1) => {
    "changed": true,
    "diff": {
        "after": {
            "path": "/tmp/1",
            "state": "directory"
        },
        "before": {
            "path": "/tmp/1",
            "state": "absent"
        }
    },
    "gid": 0,
    "group": "root",
    "invocation": {
        "module_args": {
            "_diff_peek": null,
            "_original_basename": null,
            "access_time": null,
            "access_time_format": "%Y%m%d%H%M.%S",
            "attributes": null,
            "backup": null,
            "content": null,
            "delimiter": null,
            "directory_mode": null,
            "follow": true,
            "force": false,
            "group": null,
            "mode": null,
            "modification_time": null,
            "modification_time_format": "%Y%m%d%H%M.%S",
            "owner": null,
            "path": "/tmp/1",
            "recurse": false,
            "regexp": null,
            "remote_src": null,
            "selevel": null,
            "serole": null,
            "setype": null,
            "seuser": null,
            "src": null,
            "state": "directory",
            "unsafe_writes": null
        }
    },
    "item": 1,
    "mode": "0755",
    "owner": "root",
    "path": "/tmp/1",
    "size": 4096,
    "state": "directory",
    "uid": 0
}
ok: [host2 -> localhost] => (item=1) => {
    "changed": false,
    "diff": {
        "after": {
            "path": "/tmp/1"
        },
        "before": {
            "path": "/tmp/1"
        }
    },
    "gid": 0,
    "group": "root",
    "invocation": {
        "module_args": {
            "_diff_peek": null,
            "_original_basename": null,
            "access_time": null,
            "access_time_format": "%Y%m%d%H%M.%S",
            "attributes": null,
            "backup": null,
            "content": null,
            "delimiter": null,
            "directory_mode": null,
            "follow": true,
            "force": false,
            "group": null,
            "mode": null,
            "modification_time": null,
            "modification_time_format": "%Y%m%d%H%M.%S",
            "owner": null,
            "path": "/tmp/1",
            "recurse": false,
            "regexp": null,
            "remote_src": null,
            "selevel": null,
            "serole": null,
            "setype": null,
            "seuser": null,
            "src": null,
            "state": "directory",
            "unsafe_writes": null
        }
    },
    "item": 1,
    "mode": "0755",
    "owner": "root",
    "path": "/tmp/1",
    "size": 4096,
    "state": "directory",
    "uid": 0
}
<localhost> EXEC /bin/sh -c 'echo ~root && sleep 0'
<localhost> EXEC /bin/sh -c 'echo ~root && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1538925581.22-128641467257659 `" && echo ansible-tmp-1538925581.22-128641467257659="` echo /root/.ansible/tmp/ansible-tmp-1538925581.22-128641467257659 `" ) && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1538925581.22-257782839693869 `" && echo ansible-tmp-1538925581.22-257782839693869="` echo /root/.ansible/tmp/ansible-tmp-1538925581.22-257782839693869 `" ) && sleep 0'
Using module file /tmp/ansible27/local/lib/python2.7/site-packages/ansible/modules/files/file.py
Using module file /tmp/ansible27/local/lib/python2.7/site-packages/ansible/modules/files/file.py
<localhost> PUT /root/.ansible/tmp/ansible-local-29097PyqY1S/tmpJOnbc9 TO /root/.ansible/tmp/ansible-tmp-1538925581.22-128641467257659/AnsiballZ_file.py
<localhost> PUT /root/.ansible/tmp/ansible-local-29097PyqY1S/tmpm3ebfA TO /root/.ansible/tmp/ansible-tmp-1538925581.22-257782839693869/AnsiballZ_file.py
<localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1538925581.22-128641467257659/ /root/.ansible/tmp/ansible-tmp-1538925581.22-128641467257659/AnsiballZ_file.py && sleep 0'
<localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1538925581.22-257782839693869/ /root/.ansible/tmp/ansible-tmp-1538925581.22-257782839693869/AnsiballZ_file.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1538925581.22-128641467257659/AnsiballZ_file.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1538925581.22-257782839693869/AnsiballZ_file.py && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1538925581.22-257782839693869/ > /dev/null 2>&1 && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1538925581.22-128641467257659/ > /dev/null 2>&1 && sleep 0'
changed: [host2 -> localhost] => (item=a) => {
    "changed": true,
    "diff": {
        "after": {
            "path": "/tmp/a",
            "state": "directory"
        },
        "before": {
            "path": "/tmp/a",
            "state": "absent"
        }
    },
    "gid": 0,
    "group": "root",
    "invocation": {
        "module_args": {
            "_diff_peek": null,
            "_original_basename": null,
            "access_time": null,
            "access_time_format": "%Y%m%d%H%M.%S",
            "attributes": null,
            "backup": null,
            "content": null,
            "delimiter": null,
            "directory_mode": null,
            "follow": true,
            "force": false,
            "group": null,
            "mode": null,
            "modification_time": null,
            "modification_time_format": "%Y%m%d%H%M.%S",
            "owner": null,
            "path": "/tmp/a",
            "recurse": false,
            "regexp": null,
            "remote_src": null,
            "selevel": null,
            "serole": null,
            "setype": null,
            "seuser": null,
            "src": null,
            "state": "directory",
            "unsafe_writes": null
        }
    },
    "item": "a",
    "mode": "0755",
    "owner": "root",
    "path": "/tmp/a",
    "size": 4096,
    "state": "directory",
    "uid": 0
}
ok: [host1 -> localhost] => (item=a) => {
    "changed": false,
    "diff": {
        "after": {
            "path": "/tmp/a",
            "state": "directory"
        },
        "before": {
            "path": "/tmp/a",
            "state": "absent"
        }
    },
    "gid": 0,
    "group": "root",
    "invocation": {
        "module_args": {
            "_diff_peek": null,
            "_original_basename": null,
            "access_time": null,
            "access_time_format": "%Y%m%d%H%M.%S",
            "attributes": null,
            "backup": null,
            "content": null,
            "delimiter": null,
            "directory_mode": null,
            "follow": true,
            "force": false,
            "group": null,
            "mode": null,
            "modification_time": null,
            "modification_time_format": "%Y%m%d%H%M.%S",
            "owner": null,
            "path": "/tmp/a",
            "recurse": false,
            "regexp": null,
            "remote_src": null,
            "selevel": null,
            "serole": null,
            "setype": null,
            "seuser": null,
            "src": null,
            "state": "directory",
            "unsafe_writes": null
        }
    },
    "item": "a",
    "mode": "0755",
    "owner": "root",
    "path": "/tmp/a",
    "size": 4096,
    "state": "directory",
    "uid": 0
}

TASK [assert] **********************************************************************************************************************************************************************************************************************
task path: /tmp/play.yml:13
fatal: [host1]: FAILED! => {
    "assertion": "'/tmp/2' is directory",
    "changed": false,
    "evaluated_to": false,
    "msg": "Assertion failed"
}
fatal: [host2]: FAILED! => {
    "assertion": "'/tmp/2' is directory",
    "changed": false,
    "evaluated_to": false,
    "msg": "Assertion failed"
}
	to retry, use: --limit @/tmp/play.retry

PLAY RECAP *************************************************************************************************************************************************************************************************************************
host1                      : ok=1    changed=1    unreachable=0    failed=1
host2                      : ok=1    changed=1    unreachable=0    failed=1

Metadata

Metadata

Assignees

No one assigned

    Labels

    affects_2.7This issue/PR affects Ansible v2.7bugThis issue/PR relates to a bug.support:coreThis issue/PR relates to code supported by the Ansible Engineering Team.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions