ansible / ansible

Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy and maintain. Automate everything from code deployment to network configuration to cloud management, in a language that approaches plain English, using SSH, with no agents to install on remote systems. https://docs.ansible.com.
https://www.ansible.com/
GNU General Public License v3.0
61.75k stars 23.75k forks source link

remote_user used with a loop results in fatal "item is undefined" #83467

Closed cortadosaxophone closed 2 weeks ago

cortadosaxophone commented 2 weeks ago

Summary

I am trying to run a small set of commands that override the playbook's normal user and nodes, using a list of dictionaries. While I can loop through and assign item.host to delegate_to, I am unable to assign item.user to remote_user. The play terminates with item is undefined.

Issue Type

Bug Report

Component Name

ssh

Ansible Version

$ ansible --version

ansible [core 2.16.3]
[redacted]
  python version = 3.11.2 (main, Mar  9 2023, 03:21:57) [GCC 12.2.0] 
  jinja version = 3.1.2

Configuration

# if using a version older than ansible-core 2.12 you should omit the '-t all'
$ ansible-config dump --only-changed -t all
[redacted]
CONNECTION:
==========

local:
_____
pipelining([redacted]/ansible.cfg) = True

paramiko_ssh:
____________
ssh_args(env: ANSIBLE_SSH_ARGS) = -F [redacted]/.ssh/config -C -o ControlMaster=auto -o ControlPersist=30m

psrp:
____
pipelining([redacted]/ansible.cfg) = True

ssh:
___
pipelining([redacted]/ansible.cfg) = True
scp_if_ssh([redacted]/ansible.cfg) = true
ssh_args(env: ANSIBLE_SSH_ARGS) = -F [redacted]/.ssh/config -C -o ControlMaster=auto -o ControlPersist=30m

winrm:
_____
pipelining([redacted]/ansible.cfg) = True

OS / Environment

RHEL 8.6

Steps to Reproduce

- name: "test delegation with touch"
  ansible.builtin.file:
    path: "/touch/some/file.txt"
    state: "touch"
    mode: "0644"
  remote_user: "{{ item.user }}"
  delegate_to: "{{ item.host }}"
  loop:
    - user: "valid_user1"
      host: "reachable_host1"
    - user: "valid_user2"
      host: "reachable_host2"
  run_once: true

Expected Results

Note that this is output when I set remote_user to a value.

TASK [playbook : test delegation with touch] **********************************************************************************************************************
--- before
+++ after
@@ -1,6 +1,6 @@
 {
-    "atime": 1718677057.5355608,
-    "mtime": 1718677057.5355608,
+    "atime": 1718677956.9187803,
+    "mtime": 1718677956.9187803,
     "path": "/touch/some/file.txt",
-    "state": "file"
+    "state": "touch"
 }

changed: [playbook_host -> reachable_host1] => (item={'user': 'valid_user1', 'host': 'reachable_host1'})
--- before
+++ after
@@ -1,6 +1,6 @@
 {
-    "atime": 1718677057.8688674,
-    "mtime": 1718677057.8688674,
+    "atime": 1718677957.2842903,
+    "mtime": 1718677957.2842903,
     "path": "/touch/some/file.txt",
-    "state": "file"
+    "state": "touch"
 }

changed: [playbook_host1 -> reachable_host2] => (item={'user': 'valid_user2', 'host': 'reachable_host2'})

Actual Results

TASK [playbook : test delegation with touch] **********************************************************************************************************************
fatal: [playbook_host1-> {{ item.host }}]: FAILED! => {"msg": "'item' is undefined. 'item' is undefined"}


### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct
ansibot commented 2 weeks ago

Files identified in the description:

If these files are incorrect, please update the component name section of the description or use the component bot command.

cortadosaxophone commented 2 weeks ago

Also note that this fails the same way with this:

vars:
  ansible_user: “{{ item.user }}”
bcoca commented 2 weeks ago

please show the -vvv output of the error

cortadosaxophone commented 2 weeks ago

Closing this as it is a duplicate of at least #16776. Sorry to be of any trouble. Thank you for reaching out @bcoca. This is working as designed, and I found a solution to my specific problem to accommodate existing org ansible structure (as in, within a task file called in a one-entry-point playbook:

# assume I have created a list of {user: some_user, host: some_host} dicts
- name: "use inventory to get mirror hosts"
  ansible.builtin.add_host:
    ansible_ssh_host: "{{ item.host }}"
    ansible_ssh_user: "{{ item.user }}"
    inventory_hostname: "{{ item.host }}"
    groups: "mirror_hosts"
    name: "{{ item.host }}"
  loop:
    "{{ mirror_config }}"

# run_once is called because this is a task in a playbook using N hosts
- name: "do something with group"
  ansible.builtin.file:
    path: "/home/{{ ansible_ssh_user }}/touchfile.txt"
    state: "touch"
    mode: "0644"
  loop:
    "{{ groups['mirror_hosts'] }}"
  run_once: true
  delegate_to: "{{ item }}"

A colleague also sent this to me this morning: https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_delegation.html#templating-in-delegation-context