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

Synchronize cannot find directories from sub roles like copy does

Open Zocker1999NET opened this issue 1 year ago • 3 comments

SUMMARY

When role A includes role B as dependency, role B can access files & templates from role A's directories using a relative path if this path does not exists in its own directories. This works for nearly all builtin modules from Ansible (EDIT: found the documentation, see here). This also works for the copy module but not for synchronize.

I marked it as a feature request, because this feature is nowhere stated for synchronize itself.

ISSUE TYPE
  • Feature Idea
COMPONENT NAME

ansible.posix.synchronize

ADDITIONAL INFORMATION

This feature helps to e.g. create a role managing a docker-compose project in general (upload repo with docker-compose.yml and Dockerfiles, build & launch compose, configure other stuff required, …), further called "role_b", which can be reused by multiple roles holding the repo with docker-compose.yml and Dockerfiles for certain services, further called "role_a".

The multi file example I describe below shows what works with copy and what I want to do with synchronize:

Example files with contents

site.yml

# run example locally
- hosts: localhost
  connection: local
  gather_facts: no
  roles:
    - role: role_a

roles/role_a/meta/main.yml

# this role holds a repo in its files/ directory

dependencies:
  # include role with copy/synchronize
  - name: role_b

roles/role_a/files/repo/docker-compose.yml

# Imagine a docker-compose.yml using multiple Dockerfiles …

roles/role_a/files/repo/Dockerfile

# Imagine multiple Dockerfiles used by docker-compose.yml

roles/role_b/tasks/main.yml

# check_mode so nothing will be applied

# this works
- name: Copy temp
  check_mode: yes
  ansible.builtin.copy:
    src: repo/
    dest: /tmp

# this not
- name: Sync temp
  check_mode: yes
  ansible.posix.synchronize:
    mode: push
    src: repo/
    dest: /tmp
  ignore_errors: yes

Zocker1999NET avatar Jul 18 '22 18:07 Zocker1999NET

Looked into the module and how Ansible solved that. The relatively simple patch below fixed it in my case. When I have the time, I can run the tests of this repository and submit a PR. If someone has more time than me to test it, please submit it yourself:

diff --git a/plugins/action/synchronize.py b/plugins/action/synchronize.py
index a5752b9..d8eacab 100644
--- a/plugins/action/synchronize.py
+++ b/plugins/action/synchronize.py
@@ -48,10 +48,7 @@ class ActionModule(ActionBase):
         if ':' in path or path.startswith('/'):
             return path
 
-        if self._task._role is not None:
-            path = self._loader.path_dwim_relative(self._task._role._role_path, 'files', path)
-        else:
-            path = self._loader.path_dwim_relative(self._loader.get_basedir(), 'files', path)
+        path = self._find_needle('files', path)
 
         if original_path and original_path[-1] == '/' and path[-1] != '/':
             # make sure the dwim'd path ends in a trailing "/"

I discovered that the native Ansible modules like copy do not call DataLoader.path_dwim_relative or *_stack itself, but the call the method ActionBase.find_needle, which then calls the stack method. The stack method does check for parent roles as well, like the documentation describes it.

Zocker1999NET avatar Jul 19 '22 12:07 Zocker1999NET

@Zocker1999NET I pushed up your change into a PR since it's been quite a few months since you brought it up :)

mnaser avatar Mar 21 '23 22:03 mnaser

@mnaser Thanks, I already forgot about that :+1:

Zocker1999NET avatar Mar 22 '23 08:03 Zocker1999NET