From fd325c00bd327c0be2f109f30db9991f12747b0b Mon Sep 17 00:00:00 2001 From: Sloane Hertel <19572925+s-hertel@users.noreply.github.com> Date: Mon, 9 Jan 2023 10:59:05 -0500 Subject: [PATCH] ansible-galaxy collection|role init - fix preserving symlinks (#79134) * Preserve symlinks in custom role/collection skeletons * changelog --- .../79134-ansible-galaxy-init-symlinks.yml | 2 + lib/ansible/cli/galaxy.py | 9 ++- .../ansible-galaxy-collection/tasks/init.yml | 59 +++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/79134-ansible-galaxy-init-symlinks.yml diff --git a/changelogs/fragments/79134-ansible-galaxy-init-symlinks.yml b/changelogs/fragments/79134-ansible-galaxy-init-symlinks.yml new file mode 100644 index 00000000000..4ba7ce4cd17 --- /dev/null +++ b/changelogs/fragments/79134-ansible-galaxy-init-symlinks.yml @@ -0,0 +1,2 @@ +bugfixes: + - ansible-galaxy collection/role init - preserve symlinks (https://github.com/ansible/ansible/issues/39334). diff --git a/lib/ansible/cli/galaxy.py b/lib/ansible/cli/galaxy.py index 0e2303c714c..9cb951ff81c 100755 --- a/lib/ansible/cli/galaxy.py +++ b/lib/ansible/cli/galaxy.py @@ -1182,11 +1182,16 @@ class GalaxyCLI(CLI): df.write(b_rendered) else: f_rel_path = os.path.relpath(os.path.join(root, f), obj_skeleton) - shutil.copyfile(os.path.join(root, f), os.path.join(obj_path, f_rel_path)) + shutil.copyfile(os.path.join(root, f), os.path.join(obj_path, f_rel_path), follow_symlinks=False) for d in dirs: b_dir_path = to_bytes(os.path.join(obj_path, rel_root, d), errors='surrogate_or_strict') - if not os.path.exists(b_dir_path): + if os.path.exists(b_dir_path): + continue + b_src_dir = to_bytes(os.path.join(root, d), errors='surrogate_or_strict') + if os.path.islink(b_src_dir): + shutil.copyfile(b_src_dir, b_dir_path, follow_symlinks=False) + else: os.makedirs(b_dir_path) display.display("- %s %s was created successfully" % (galaxy_type.title(), obj_name)) diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/init.yml b/test/integration/targets/ansible-galaxy-collection/tasks/init.yml index 17a000dba0b..c4b5d9c5102 100644 --- a/test/integration/targets/ansible-galaxy-collection/tasks/init.yml +++ b/test/integration/targets/ansible-galaxy-collection/tasks/init.yml @@ -92,6 +92,65 @@ - (init_custom_path_actual.files | map(attribute='path') | list)[2] | basename in ['docs', 'plugins', 'roles', 'meta'] - (init_custom_path_actual.files | map(attribute='path') | list)[3] | basename in ['docs', 'plugins', 'roles', 'meta'] +- name: test using a custom skeleton for collection init + block: + - name: create skeleton directories + file: + path: "{{ galaxy_dir }}/scratch/skeleton/{{ item }}" + state: directory + loop: + - custom_skeleton + - custom_skeleton/plugins + - inventory + + - name: create files + file: + path: "{{ galaxy_dir }}/scratch/skeleton/{{ item }}" + state: touch + loop: + - inventory/foo.py + - galaxy.yml + + - name: create symlinks + file: + path: "{{ galaxy_dir }}/scratch/skeleton/{{ item.link }}" + src: "{{ galaxy_dir }}/scratch/skeleton/{{ item.source }}" + state: link + loop: + - link: custom_skeleton/plugins/inventory + source: inventory + - link: custom_skeleton/galaxy.yml + source: galaxy.yml + + - name: initialize a collection using the skeleton + command: ansible-galaxy collection init ansible_test.my_collection {{ init_path }} {{ skeleton }} + vars: + init_path: '--init-path {{ galaxy_dir }}/scratch/skeleton' + skeleton: '--collection-skeleton {{ galaxy_dir }}/scratch/skeleton/custom_skeleton' + + - name: stat expected collection contents + stat: + path: "{{ galaxy_dir }}/scratch/skeleton/ansible_test/my_collection/{{ item }}" + register: stat_result + loop: + - plugins + - plugins/inventory + - galaxy.yml + - plugins/inventory/foo.py + + - assert: + that: + - stat_result.results[0].stat.isdir + - stat_result.results[1].stat.islnk + - stat_result.results[2].stat.islnk + - stat_result.results[3].stat.isreg + + always: + - name: cleanup + file: + path: "{{ galaxy_dir }}/scratch/skeleton" + state: absent + - name: create collection for ignored files and folders command: ansible-galaxy collection init ansible_test.ignore args: