synchronize complains that it needs a password to do a sudo

When executing a synchronize I get the following error.

This the executed code

  • name: Restore repositories
    synchronize: src=“{{ item }}” mode=push dest=“/home/git”
    with_lines: “find /home/git/*.git -type d -maydepth 0”
    tags: restore

This is the error message I get with each directory.

failed: [srv01] => (item=/home/git/XXX.git) => {“failed”: true, “invocation”: {“module_args”: {“_local_rsync_path”: “rsync”, “dest”: “XXX@XX.XX.XX.XX:/home/git”, “dest_port”: XX, “mode”: “push”, “private_key”: “id_rsa_XXX”, “rsync_path”: “"sudo rsync"”, “src”: “/home/git/DIR.git”}, “module_name”: “synchronize”}, “item”: “/home/git/DIR.git”, “module_stderr”: “sudo: sorry, a password is required to run sudo\n”, “module_stdout”: “”, “msg”: “MODULE FAILURE”, “parsed”: false}

The remote user XXX has a passwordless sudo to root. It works since I can install packages. So why does it complain that sudo requires a password ?

I get the same error message even if I add rsync_path=“rsync” to the synchronize action. So I don’t see who is trying to do a sudo and where (locally or remotely).

The error persist even if I do a local “sudo rsync” just to give the root password.

I changed the find instruction to a more correct one, but the synchronize still fails because some sudo requires a password.
This is the instruction I used.

with_lines: find /home/git/ -maxdepth 1 -name “*.git” -type d

I finally fixed the problem after reading the doc on synchronize. I found the following note:

The user and permissions for the synchronize are those of the user running the Ansible task on the local host, or the if is active. synchronize will attempt to escalate privileges to the become_user .

This is changing the semantic of the become and become_user parameters.

Normally, as I understood it, it is to define the behavior remotely. For this reason I defined it globally to yes in my playbook.

But synchronize use it to control the identity change locally. This is inconsistent and confusing.

As a consequence I don’t know what synchronize is doing. I’m running the playbook as user A. In the inventory I defined the variable ansible_user=B. In the playbook I defined become:yes and become_method: sudo.

So I assumed that while running the playbook as user A, ansible will connect remotely as user B and run the tasks after performing a sudo. I have configured it to be a password less sudo to root. This is apparently how things work as I deduced by trial and error.

Now synchronize hijacks the parameter become and change it’s purpose. For synchronize it now specify if the identity should be changed locally and become_user would specify to what. But then how is the remote identity and privilege escalation define ?

It looks like there is still a confusing mix up in the way to define the different identities and change method and optional password. It’s not yet fully orthogonal.

It should be possible to define a local identity change and a remote identity as the ssh user identity (ansible_user?) and authentication method. The hack made by synchronize about this is really confusing.

I forgot the solution. Here it is:

  • name: Restore repositories
    synchronize: src=“{{ item }}” dest=“/home/git”
    with_lines: find /home/git/ -maxdepth 1 -name “*.git” -type d
    become: no
    tags: restore

This will attempt a synchronize by executing the rsync as the user who executes the playbook. This works in my case.

If you want to change the identity of the user executing locally the rsync, you have to set become: yes, become_user: X where X is the new local user identity.
If switching the local user identity to X with su or sudo requires a password, you are doomed. Note that running the command as root which in principle should allow changing the local user identity without password didn’t work. So I’m not fully sure if my current understanding is correct.

The command line parameter --ask-become-pass applies to the change of the remote user identity. There is currently no support for changing the local user identity.

You're right about this being the wrong thing for synchronize to do.
My fault for not understanding sooner that this wasn't the behaviour
in 1.9.x. We consider it a bug in 2.0.0.x and I'm working on a fix to
it for 2.0.1 right now. Progress on the fix is here:
https://github.com/ansible/ansible/issues/13825

I'll be pushing a documentation update in a few hours so that the
website documentation no longer says that it is expected that
synchronize works this way (and that it is a bug in 2.0.0.x only).

-Toshio

Note that in 1.9.x (and in the code I'm working on to fix this for
2.0.1) I believe it's impossible to define a local identity change
within ansible. But you can sudo first and then run ansible to
workaround that.

-Toshio

Thank you very much for fixing this. In most uses cases it works provided become is set to no.

It might still be useful to change the local user identity when synchronizing, but the way to do it seem to be lacking in the current interface.

Thank you very much for the synchronize module. It is a very powerful and useful module.

Thank you very much for taking the time to answer and also for this great module. It is very useful.
Being able to change the local user identity would indeed be a useful addition to ansible.
The synchronize module does need it.
It could also be useful for with_lines: which execute a command locally. i.e. accessing a database on the localhost.