Repository: ansible/ansible

Issue:
delegate_to with remote_user on ansible 2.0
Issue Type: Bug Report (2.0 regression)
Ansible Version: 2.0.0 (devel)
Ansible Configuration: default
Environment: Ubuntu 14.04
Summary:
delegate_to does not use user specified with remote_user.

Steps To Reproduce:
Following playbook works correctly on 1.9.4 with output root and on devel it outputs normal user. 

```

---
- hosts:
    - test-vm
  become: yes

  tasks:
  - command: whoami
    register: whoami
    delegate_to: "test-vm2"
    remote_user: root
    become: false

  - debug: msg="{{ whoami.stdout }}"
```

Expected Results:

```
ok: [test] => {
    "changed": false, 
    "invocation": {
        "module_args": {
            "msg": "root"
        }, 
        "module_name": "debug"
    }, 
    "msg": "root
}

```

Actual Results:

```
ok: [test] => {
    "changed": false, 
    "invocation": {
        "module_args": {
            "msg": "username"
        }, 
        "module_name": "debug"
    }, 
    "msg": "username"
}
```



Discussion:
# Closing This Ticket

Hi!

We believe the above commit should resolve this problem for you. This will also be included in the next major release.

If you continue seeing any problems related to this issue, or if you have any further questions, please let us know by stopping by one of the two mailing lists, as appropriate:
- https://groups.google.com/forum/#!forum/ansible-project - for user questions, tips, and tricks
- https://groups.google.com/forum/#!forum/ansible-devel - for strategy, future planning, and questions about writing code

Because this project is very active, we're unlikely to see comments made on closed tickets, but the mailing list is a great way to ask questions, or post if you don't think this particular issue is resolved.

Thank you!

@jimi-c Your commit does not fix this issue for me.

@pujan14 odd, your example playbook in the same setup worked for me, as well as for another user testing it in IRC. Any other details you can provide?

if the user is set at inventory level for the delegated host, that should override remote_user

@bcoca I do not have delegated host in inventory file but it does go on that host. To connect to that host it uses my user account and not remote_user.
@jimi-c If it's helpful I can send debug log as well. What else I can test/try.

I am installing ansible with "sudo pip install git+https://github.com/ansible/ansible" and that gets me current devel.

I can still reproduce this with devel from today morning (2nd Dec). Can we please reopen this?

@jimi-c  I think I have found another detail that might help. If the delegate_to host is not in inventory it always uses my user but if I add that host in inventory and specify ansible_ssh_user there, it works but that means I can not specify remote_user at playbook level.  

Hrm, I didn't think that the delegated_to host would use the remote_user set at the task level, but I believe we can fix that easily.

@pujan14 / @mgedmin I think this patch should fix this, if you'd like to test it out: https://gist.github.com/jimi-c/a25682ba838e09f1f56c

I've done pretty extensive testing on this, using root/non-root local users and having remote_user set at the task and play levels, as well as via the ansible.cfg, and all scenarios work as expected. Based on that, I'm going to go ahead and merge that fix in now, and if either of you have any further problems let us know.

Merged into both devel and stable-2.0.

Confirming that the fix works for me.

(Thank you for the speedy fix!)

@jimi-c I feel bad about this but this still does not resolve issue for me. Did you test it with playbook I attached here? on ansible 1.9.4 it gives me root but on ansible devel as of now it gives me my username.
Also I checked code on my laptop and even changed "task.remote_user or self.remote_user" to "root" still I got my user. Here's my playbook again.

## ´´´
- hosts:
  - testvm1
    become: yes
  
  tasks:
  - name: test who am i
    shell: whoami
    register: whoami
    delegate_to: "testvm2"
    remote_user: root
    become: false
  - debug: msg="{{ whoami.stdout }}"
    ´´´

Also testvm2 is not part of inventory file, In case that changes anything.

@pujan14 yes, I tested it with both root and non-root local users, and with remote_user set at various places in the playbook.

Here's an example run when `register_user: testing` is in the task:

<pre>
[jamesc@jimi testing]$ cat 13323.yml 
---
- hosts: awxlocal
  gather_facts: no
  become: yes
  tasks:
  - shell: whoami; hostname
    register: whoami
    delegate_to: ubuntu1404
    remote_user: testing
    become: false
  - debug: msg="{{ whoami.stdout }}"
[jamesc@jimi testing]$ ansible-playbook -vvv 13323.yml 
Using /etc/ansible/ansible.cfg as config file
1 plays in 13323.yml
PLAY ***************************************************************************
TASK [command] *****************************************************************
task path: /home/jamesc/testing/13323.yml:7
<192.168.122.113> ESTABLISH SSH CONNECTION FOR USER: testing
<192.168.122.113> SSH: EXEC ssh -C -q -o ControlMaster=auto -o ControlPersist=60s -o ControlPath=/tmp/ansible-ssh-%h-%p-%r -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=testing -o ConnectTimeout=10 192.168.122.113 LANG=en_US.utf8 LC_ALL=en_US.utf8 LC_MESSAGES=en_US.utf8 /usr/bin/python
changed: [awxlocal -> None] => {"changed": true, "cmd": "whoami; hostname", "delta": "0:00:00.002009", "end": "2015-12-04 13:02:39.307393", "invocation": {"module_args": {"_raw_params": "whoami; hostname", "_uses_shell": true}, "module_name": "command"}, "rc": 0, "start": "2015-12-04 13:02:39.305384", "stderr": "", "stdout": "testing\nubuntu1404", "stdout_lines": ["testing", "ubuntu1404"], "warnings": []}
TASK [debug msg={{ whoami.stdout }}] *******************************************
task path: /home/jamesc/testing/13323.yml:13
ok: [awxlocal] => {
    "changed": false, 
    "invocation": {
        "module_args": {
            "msg": "testing\nubuntu1404"
        }, 
        "module_name": "debug"
    }, 
    "msg": "testing\nubuntu1404"
}
PLAY RECAP *********************************************************************
awxlocal                   : ok=2    changed=1    unreachable=0    failed=0   
</pre>

My local user is jamesc, but you can see the remote user from whoami is coming back as `testing` (which is correct).

```
Using $home/.ansible.cfg as config file
 [WARNING]: provided hosts list is empty, only localhost is available

Loaded callback default of type stdout, v2.0
1 plays in $home/test.yml

PLAY ***************************************************************************

TASK [setup] *******************************************************************
ESTABLISH LOCAL CONNECTION FOR USER: username
127.0.0.1 EXEC ( umask 22 && mkdir -p "$( echo $HOME/.ansible/tmp/ansible-tmp-1449475553.85-242439720574036 )" && echo "$( echo $HOME/.ansible/tmp/ansible-tmp-1449475553.85-242439720574036 )" )
127.0.0.1 PUT /tmp/tmpP8kX6z TO $home/.ansible/tmp/ansible-tmp-1449475553.85-242439720574036/setup
127.0.0.1 EXEC /bin/sh -c 'sudo -H -S -n -u root /bin/sh -c '"'"'echo BECOME-SUCCESS-eyobmnxejduvocbnyhmnwwvkprugebas; LANG=C LC_ALL=C LC_MESSAGES=C /usr/bin/python $home/.ansible/tmp/ansible-tmp-1449475553.85-242439720574036/setup; rm -rf "$home/.ansible/tmp/ansible-tmp-1449475553.85-242439720574036/" > /dev/null 2>&1'"'"''
ok: [localhost]

TASK [test] ********************************************************************
task path: $home/test.yml:7
<testvm2> ESTABLISH SSH CONNECTION FOR USER: None
<testvm2> SSH: ansible.cfg set ssh_args: (-o)(ControlMaster=auto)(-o)(ControlPersist=60s)
<testvm2> SSH: ANSIBLE_REMOTE_PORT/remote_port/ansible_port set: (-o)(Port=22)
<testvm2> SSH: ansible_password/ansible_ssh_pass not set: (-o)(KbdInteractiveAuthentication=no)(-o)(PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey)(-o)(PasswordAuthentication=no)
<testvm2> SSH: ANSIBLE_TIMEOUT/timeout set: (-o)(ConnectTimeout=10)
<testvm2> SSH: PlayContext set ssh_common_args: ()
<testvm2> SSH: PlayContext set ssh_extra_args: ()
<testvm2> SSH: found only ControlPersist; added ControlPath: (-o)(ControlPath=~/.ssh/ansible-ssh-%h-%p-%r)
<testvm2> SSH: EXEC ssh -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o Port=22 -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath=~/.ssh/ansible-ssh-%h-%p-%r' testvm2 LANG=C LC_ALL=C LC_MESSAGES=C /usr/bin/python
changed: [localhost -> testvm2] => {"changed": true, "cmd": "whoami", "delta": "0:00:00.004343", "end": "2015-12-07 09:05:54.407689", "invocation": {"module_args": {"_raw_params": "whoami", "_uses_shell": true}, "module_name": "command"}, "rc": 0, "start": "2015-12-07 09:05:54.403346", "stderr": "", "stdout": "username", "stdout_lines": ["username"], "warnings": []}

TASK [debug msg={{ whoami.stdout }}] *******************************************
task path: $home/test.yml:14
ok: [localhost] => {
    "changed": false, 
    "invocation": {
        "module_args": {
            "msg": "username"
        }, 
        "module_name": "debug"
    }, 
    "msg": "username"
}

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0   
```

Even today it did not resolve for me. I will test this today from other control machine. Looking at output, it looks like with my playbook ansible does not specify User=abc for ssh connection. I wonder why. Anyway if this bug is not reproducible, I'll use a work around and just specify this things at inventory level. Thanks for stinking with this :+1: 

So for the record, I am also hitting a similar problem, or a variation of. I have a server called karona.example.org, with a login 'misc', the same as the local control laptop. If I use this:

```
---
- hosts: all
  tasks:
  - command: id
    delegate_to: karona.example.org
    remote_user: mscherer
```

and I run it with:

```
ansible-playbook -c local  -i '127.0.0.1,' e.yml
```

, it should fail (since the remote _user is wrong).

However, it do connect using my local login ('misc') and thus succeed.
But it should fail.

If I use: 

```
ansible-playbook -c local  -i 'karona.example.org,' e.yml
```

 it fail as expected (since it try to connect using mscherer, rather than misc).

So the code likely change the remote_user only if the host is in the inventory, and do nothing if it isn't, hence the differing result we see.

@jimi-c I am facing this problem again.
I have specified remote_user in playbook and ansible_user in inventory and both are ignored.
But this happens only when my real host is windows machine.

@pujan14 could you please create a new issue for this? It most likely has a different root cause.

I added issue https://github.com/ansible/ansible/issues/15259 which resembles pujan14's case.

This is happening to me with Ansible 2.0.2.0. If `delegate_to` is set to a host that isn't in the inventory, the `remote_user` parameter is completely ignored. If the host is added to the inventory, then the `remote_user` parameter is used.

We are seeing the same issue as @btobolaski 

Same problem here:
ansible 2.0.0.2
ubuntu 16.04

Whenever i try to run a playbook and the task arrive to one that i have the argument delegate_to, using -vvvv i can see that on this task ansible choose to try to log with user None, meanwhile the other task where executed as another user.
I've tried to put delegate_to and remote_user ansible but still don't works.

I think why you some of you could reproduce the bug. 
I use the instroction:
      delegate_to: "{{ item }}"
      with_items: '{{ hosts }}'

so, when host wich is a group made for example like this:
[servers]
server1
server2

The tasks fails, because use the user None to do the task.
But when servers only have only one machine like this:
[servers]
server1
Then the tasks works correctly and it's executed as user ansible wich is the user that i use to run playbooks


Resolving patch:
diff --git a/lib/ansible/playbook/play_context.py b/lib/ansible/playbook/play_context.py
--- a/lib/ansible/playbook/play_context.py
+++ b/lib/ansible/playbook/play_context.py
@@ -356,7 +356,7 @@ def set_task_and_variable_override(self, task, variables, templar):
 
             # and likewise for the remote user
             for user_var in MAGIC_VARIABLE_MAPPING.get('remote_user'):
-                if user_var in delegated_vars:
+                if user_var in delegated_vars and delegated_vars[user_var]:
                     break
             else:
                 delegated_vars['ansible_user'] = task.remote_user or self.remote_user


Test patch: