ansible.posix
ansible.posix copied to clipboard
`synchronize` fails to accept `ansible_port` as string
SUMMARY
When ansible is launched with -e ansible_port=1234, the ansible_port variable will be of type str, which is not accepted by the module and no -o Port=1234 is passed down to rsync. If the same variable is defined as int type, it works as expected.
ISSUE TYPE
- Bug Report
COMPONENT NAME
ansible.posix.synchronize
ANSIBLE VERSION
ansible [core 2.13.4]
config file = None
configured module search path = ['/Users/name/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.10/site-packages/ansible
ansible collection location = /Users/name/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/local/bin/ansible
python version = 3.10.8 (main, Nov 15 2022, 05:25:54) [Clang 14.0.0 (clang-1400.0.29.202)]
jinja version = 3.1.2
libyaml = True
COLLECTION VERSION
Collection Version
------------- -------
ansible.posix 1.4.0
CONFIGURATION
<empty>
OS / ENVIRONMENT
macOS 13
STEPS TO REPRODUCE
- hosts: all
tasks:
- ansible.posix.synchronize:
src: "./"
dest: "/opt/app/"
Run via ansible-playbook -i 127.0.0.1, -vvv -e ansible_port=1234 playbook.yml, observe no -o Port=1234 being passed.
EXPECTED RESULTS
success
ACTUAL RESULTS
fails as it tries to ssh to localhost port 22:
fatal: [127.0.0.1]: FAILED! => {"changed": false, "cmd": "/usr/local/bin/rsync --delay-updates -F --compress --archive --rsync-path='sudo -u root rsync' --out-format='<<CHANGED>>%i %n%L' /Users/user/app/ /opt/app/", "msg": "rsync: [Receiver] mkdir \"/opt/app\" failed: Permission denied (13)\nrsync error: error in file IO (code 11) at main.c(793) [Receiver=3.2.7]\n", "rc": 11}
Hello, @silverwind. I've tried to run playbook as you pointed out and got this error on 'gather facts' task:
fatal: [127.0.0.1]: UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: ssh: connect to host 127.0.0.1 port 1234: Connection refused",
"unreachable": true
}
I reproduced your error with connection: local. Task failed because you don't have permissions to create files. There is no problems with ports otherwise you would get error on 'gather facts' task as I mentioned earlier. If you add options --ask-become-pass --become it will work:
ansible-playbook --ask-become-pass --become -i 127.0.0.1, -vvv -e ansible_port=1234 playbook.yml
You need a SSH daemon listening on localhost:1234. In my case it's a Vagrant VM which has my SSH key installed. --ask-become-pass should therefore be unnecessary as it authorizes with SSH key, there are no passwords involved.
You should be able to reproduce if you disable gather_facts, so it goes directly to the synchronize step, and in that case you don't need anything listening on localhost:1234 to observe the missing rsync option -o Port=1234 in the debug.
Here is a repo to reproduce. There is str.sh and int.sh, the only difference between them is that str.sh passes the port on the command line, while int.sh passes it via vars.
As int -o Port=1234 is present:
./int.sh
...
"msg": "ansible_port is type int"
...
fatal: [127.0.0.1]: FAILED! => {"changed": false, "cmd": "/usr/local/bin/rsync --delay-updates -F --compress --archive --rsh='/usr/local/bin/ssh -S none -o Port=1234 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' --out-format='<<CHANGED>>%i %n%L' /Users/silverwind/git/ansible-synchronize-port/ 127.0.0.1:/opt/app/", "msg": "ssh: connect to host 127.0.0.1 port 1234: Connection refused\r\nrsync: connection unexpectedly closed (0 bytes received so far) [sender]\nrsync error: unexplained error (code 255) at io.c(231) [sender=3.2.7]\n", "rc": 255}
As str is it absent (and it goes to localhost:22):
./str.sh
...
"msg": "ansible_port is type str"
...
fatal: [127.0.0.1]: FAILED! => {"changed": false, "cmd": "/usr/local/bin/rsync --delay-updates -F --compress --archive --out-format='<<CHANGED>>%i %n%L' /Users/silverwind/git/ansible-synchronize-port/ /opt/app/", "msg": "rsync: [Receiver] mkdir \"/opt/app\" failed: Permission denied (13)\nrsync error: error in file IO (code 11) at main.c(793) [Receiver=3.2.7]\n", "rc": 11}
I think https://github.com/ansible-collections/ansible.posix/issues/376 is the same root cause where ansible_port is passed as string.
I suppose difference in how ansible-playbook choose connection type. With gather_facts: false connection is local otherwise it's ssh.
There should not be any SSH connection intiated by ansible-core in this playbook. The first connection is from the synchronize module and I see it actually fails to pass the whole --rsh argument to rsync when ansible_port is str.
I've tried to run playbook without ansible_port at all and in this case connection is local.
I believe there is difference between passing ansible_port in playbook or in cli.
Try to pass ansible_port like this ansible-playbook -i 127.0.0.1, -vvv -e '{"ansible_port":1234}' playbook.yml and you will see:
ok: [127.0.0.1] => {
"msg": "ansible_port is type int"
}
but connection is still local.
It should not matter whether connection is local or not. The reproduction demonstrates the the module goes haywire and fails to pass options to rsync as soon as type is str.
And yeah, there are various workarounds, https://github.com/ansible-collections/ansible.posix/issues/376#issuecomment-1222046195 is another one.
It's matter because module decides whether rsh is needed or not like this https://github.com/ansible-collections/ansible.posix/blob/main/plugins/modules/synchronize.py#L383. Module doesn't go haywire as soon as type is str. I've showed it in previous comment.
You are right, if I change 127.0.0.1 to 1.2.3.4, the bug does not show and the --rsh option is present even if port is str.
Interesting that it only triggers when local and port is str.