ansible.posix icon indicating copy to clipboard operation
ansible.posix copied to clipboard

Allow bypassing rsync built-in transport check for custom ssh-based transports

Open toadjaune opened this issue 1 year ago • 0 comments

SUMMARY

When using synchronize between the ansible controller and a remote target host, using a custom transport plugin, synchronize refuses to run, and exits with an error message.

While this is a good default behavior, there are situations where it could be made to work with proper manual configuration (for example, using ssh_connection_multiplexing or rsync_opts).

Adding a configuration parameter to the synchronize module would allow those situations to work.

ISSUE TYPE

  • Feature Idea

COMPONENT NAME

ansible.posix.synchronize

ADDITIONAL INFORMATION

The custom transport I'm using is eci, it extends the ssh transport mechanism to handle authentication through EC2 Instance Connect.

I'm therefore still connecting through ssh under the hood, but ansible doesn't know that. And even if it did, the current behavior is the correct default behavior, because authentication through eci uses a temporary ssh key, only valid 60s.

I could however easily make rsync re-use the ssh connection and work as expected.

This would also be useful for any custom transport able to provide a socket between hosts, doing something similar to this workaround (before it was natively supported).

Example configuration

Put all following files in the current working directory :

# inventory
<xx.xx.xx.xx> ansible_connection=eci aws_profile=<your_profile> aws_region=<your_aws_region> ansible_user=ubuntu
# ansible.cfg
[defaults]
connection_plugins=plugins/connection

copy eci.py in plugins/connection/

# playbook.yml
- hosts: all
  tasks:
    - synchronize:
        src: plugins/connection # or any existing directory on the controller
        dest: . # or any existing directory on the remote

Run :

$ ansible-playbook -i inventory playbook.yml -vvv
[...]
TASK [ansible.posix.synchronize] ***********************************************************************************************************************************************************************************
task path: /path/to/playbook.yml:3
fatal: [wordpress-production]: FAILED! => {
    "changed": false,
    "msg": "synchronize uses rsync to function. rsync needs to connect to the remote host via ssh, docker client or a direct filesystem copy. This remote host is being accessed via eci instead so it cannot work."
}

Ansible version with which this test was run :

ansible [core 2.15.0]
  python version = 3.10.11 (main, May 29 2023, 00:00:00) [GCC 13.1.1 20230511 (Red Hat 13.1.1-2)]
  jinja version = 3.0.3
  libyaml = True

Fix suggestions

Long-term fix

In my opinion, a "proper" long-term fix would be something along the lines of :

  • Expanding the transport plugin API, so that a transport plugin may provide ansible with the ability to create a bidirectional socket between controller and target hosts
  • When encountering an unknown transport plugin, synchronize would check if it implements this API, and if so, uses it instead of erroring

This would allow any custom transport to make transparent use of synchronize (and, I'm assuming, other modules currently suffering from the same limitations).

In the long run, we could even imagine transitioning existing standard transport plugins to this mechanism, removing most of the logic from this module, and relying on the transport plugin to implement it instead.

Short-term fix

Adding a new configuration option in the synchronize module (for example named bypass_transport_compatibility, defaulting to false), which would just bypass the check, and use the module just like if the transport used was ssh ; allowing a user to make use of ssh_connection_multiplexing or rsync_opts to use synchronize.

If this option sounds reasonable in terms of design and user interface, I would gladly try to provide a PR implementing it !

toadjaune avatar Jun 13 '23 12:06 toadjaune