diff options
Diffstat (limited to 'test/integration/targets/ansible-galaxy-collection/tasks/install.yml')
-rw-r--r-- | test/integration/targets/ansible-galaxy-collection/tasks/install.yml | 1035 |
1 files changed, 1035 insertions, 0 deletions
diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/install.yml b/test/integration/targets/ansible-galaxy-collection/tasks/install.yml new file mode 100644 index 0000000..8916faf --- /dev/null +++ b/test/integration/targets/ansible-galaxy-collection/tasks/install.yml @@ -0,0 +1,1035 @@ +--- +- name: create test collection install directory - {{ test_id }} + file: + path: '{{ galaxy_dir }}/ansible_collections' + state: directory + +- name: install simple collection from first accessible server + command: ansible-galaxy collection install namespace1.name1 {{ galaxy_verbosity }} + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + register: from_first_good_server + +- name: get installed files of install simple collection from first good server + find: + path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1' + file_type: file + register: install_normal_files + +- name: get the manifest of install simple collection from first good server + slurp: + path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1/MANIFEST.json' + register: install_normal_manifest + +- name: assert install simple collection from first good server + assert: + that: + - '"Installing ''namespace1.name1:1.0.9'' to" in from_first_good_server.stdout' + - install_normal_files.files | length == 3 + - install_normal_files.files[0].path | basename in ['MANIFEST.json', 'FILES.json', 'README.md'] + - install_normal_files.files[1].path | basename in ['MANIFEST.json', 'FILES.json', 'README.md'] + - install_normal_files.files[2].path | basename in ['MANIFEST.json', 'FILES.json', 'README.md'] + - (install_normal_manifest.content | b64decode | from_json).collection_info.version == '1.0.9' + +- name: Remove the collection + file: + path: '{{ galaxy_dir }}/ansible_collections/namespace1' + state: absent + +- name: install simple collection with implicit path - {{ test_id }} + command: ansible-galaxy collection install namespace1.name1 -s '{{ test_name }}' {{ galaxy_verbosity }} + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + register: install_normal + +- name: get installed files of install simple collection with implicit path - {{ test_id }} + find: + path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1' + file_type: file + register: install_normal_files + +- name: get the manifest of install simple collection with implicit path - {{ test_id }} + slurp: + path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1/MANIFEST.json' + register: install_normal_manifest + +- name: assert install simple collection with implicit path - {{ test_id }} + assert: + that: + - '"Installing ''namespace1.name1:1.0.9'' to" in install_normal.stdout' + - install_normal_files.files | length == 3 + - install_normal_files.files[0].path | basename in ['MANIFEST.json', 'FILES.json', 'README.md'] + - install_normal_files.files[1].path | basename in ['MANIFEST.json', 'FILES.json', 'README.md'] + - install_normal_files.files[2].path | basename in ['MANIFEST.json', 'FILES.json', 'README.md'] + - (install_normal_manifest.content | b64decode | from_json).collection_info.version == '1.0.9' + +- name: install existing without --force - {{ test_id }} + command: ansible-galaxy collection install namespace1.name1 -s '{{ test_name }}' {{ galaxy_verbosity }} + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + register: install_existing_no_force + +- name: assert install existing without --force - {{ test_id }} + assert: + that: + - '"Nothing to do. All requested collections are already installed" in install_existing_no_force.stdout' + +- name: install existing with --force - {{ test_id }} + command: ansible-galaxy collection install namespace1.name1 -s '{{ test_name }}' --force {{ galaxy_verbosity }} + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + register: install_existing_force + +- name: assert install existing with --force - {{ test_id }} + assert: + that: + - '"Installing ''namespace1.name1:1.0.9'' to" in install_existing_force.stdout' + +- name: remove test installed collection - {{ test_id }} + file: + path: '{{ galaxy_dir }}/ansible_collections/namespace1' + state: absent + +- name: install pre-release as explicit version to custom dir - {{ test_id }} + command: ansible-galaxy collection install 'namespace1.name1:1.1.0-beta.1' -s '{{ test_name }}' -p '{{ galaxy_dir }}/ansible_collections' {{ galaxy_verbosity }} + register: install_prerelease + +- name: get result of install pre-release as explicit version to custom dir - {{ test_id }} + slurp: + path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1/MANIFEST.json' + register: install_prerelease_actual + +- name: assert install pre-release as explicit version to custom dir - {{ test_id }} + assert: + that: + - '"Installing ''namespace1.name1:1.1.0-beta.1'' to" in install_prerelease.stdout' + - (install_prerelease_actual.content | b64decode | from_json).collection_info.version == '1.1.0-beta.1' + +- name: Remove beta + file: + path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1' + state: absent + +- name: install pre-release version with --pre to custom dir - {{ test_id }} + command: ansible-galaxy collection install --pre 'namespace1.name1' -s '{{ test_name }}' -p '{{ galaxy_dir }}/ansible_collections' {{ galaxy_verbosity }} + register: install_prerelease + +- name: get result of install pre-release version with --pre to custom dir - {{ test_id }} + slurp: + path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1/MANIFEST.json' + register: install_prerelease_actual + +- name: assert install pre-release version with --pre to custom dir - {{ test_id }} + assert: + that: + - '"Installing ''namespace1.name1:1.1.0-beta.1'' to" in install_prerelease.stdout' + - (install_prerelease_actual.content | b64decode | from_json).collection_info.version == '1.1.0-beta.1' + +- name: install multiple collections with dependencies - {{ test_id }} + command: ansible-galaxy collection install parent_dep.parent_collection:1.0.0 namespace2.name -s {{ test_name }} {{ galaxy_verbosity }} + args: + chdir: '{{ galaxy_dir }}/ansible_collections' + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + ANSIBLE_CONFIG: '{{ galaxy_dir }}/ansible.cfg' + register: install_multiple_with_dep + +- name: get result of install multiple collections with dependencies - {{ test_id }} + slurp: + path: '{{ galaxy_dir }}/ansible_collections/{{ collection.namespace }}/{{ collection.name }}/MANIFEST.json' + register: install_multiple_with_dep_actual + loop_control: + loop_var: collection + loop: + - namespace: namespace2 + name: name + - namespace: parent_dep + name: parent_collection + - namespace: child_dep + name: child_collection + - namespace: child_dep + name: child_dep2 + +- name: assert install multiple collections with dependencies - {{ test_id }} + assert: + that: + - (install_multiple_with_dep_actual.results[0].content | b64decode | from_json).collection_info.version == '1.0.0' + - (install_multiple_with_dep_actual.results[1].content | b64decode | from_json).collection_info.version == '1.0.0' + - (install_multiple_with_dep_actual.results[2].content | b64decode | from_json).collection_info.version == '0.9.9' + - (install_multiple_with_dep_actual.results[3].content | b64decode | from_json).collection_info.version == '1.2.2' + +- name: expect failure with dep resolution failure - {{ test_id }} + command: ansible-galaxy collection install fail_namespace.fail_collection -s {{ test_name }} {{ galaxy_verbosity }} + register: fail_dep_mismatch + failed_when: + - '"Could not satisfy the following requirements" not in fail_dep_mismatch.stderr' + - '" fail_dep2.name:<0.0.5 (dependency of fail_namespace.fail_collection:2.1.2)" not in fail_dep_mismatch.stderr' + +- name: Find artifact url for namespace3.name + uri: + url: '{{ test_server }}{{ vX }}collections/namespace3/name/versions/1.0.0/' + user: '{{ pulp_user }}' + password: '{{ pulp_password }}' + force_basic_auth: true + register: artifact_url_response + +- name: download a collection for an offline install - {{ test_id }} + get_url: + url: '{{ artifact_url_response.json.download_url }}' + dest: '{{ galaxy_dir }}/namespace3.tar.gz' + +- name: install a collection from a tarball - {{ test_id }} + command: ansible-galaxy collection install '{{ galaxy_dir }}/namespace3.tar.gz' {{ galaxy_verbosity }} + register: install_tarball + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + +- name: get result of install collection from a tarball - {{ test_id }} + slurp: + path: '{{ galaxy_dir }}/ansible_collections/namespace3/name/MANIFEST.json' + register: install_tarball_actual + +- name: assert install a collection from a tarball - {{ test_id }} + assert: + that: + - '"Installing ''namespace3.name:1.0.0'' to" in install_tarball.stdout' + - (install_tarball_actual.content | b64decode | from_json).collection_info.version == '1.0.0' + +- name: write a requirements file using the artifact and a conflicting version + copy: + content: | + collections: + - name: {{ galaxy_dir }}/namespace3.tar.gz + version: 1.2.0 + dest: '{{ galaxy_dir }}/test_req.yml' + +- name: install the requirements file with mismatched versions + command: ansible-galaxy collection install -r '{{ galaxy_dir }}/test_req.yml' {{ galaxy_verbosity }} + ignore_errors: True + register: result + environment: + ANSIBLE_NOCOLOR: True + ANSIBLE_FORCE_COLOR: False + +- name: remove the requirements file + file: + path: '{{ galaxy_dir }}/test_req.yml' + state: absent + +- assert: + that: error == expected_error + vars: + error: "{{ result.stderr | regex_replace('\\n', ' ') }}" + expected_error: >- + ERROR! Failed to resolve the requested dependencies map. + Got the candidate namespace3.name:1.0.0 (direct request) + which didn't satisfy all of the following requirements: + * namespace3.name:1.2.0 + +- name: test error for mismatched dependency versions + vars: + error: "{{ result.stderr | regex_replace('\\n', ' ') }}" + expected_error: >- + ERROR! Failed to resolve the requested dependencies map. + Got the candidate namespace3.name:1.0.0 (dependency of tmp_parent.name:1.0.0) + which didn't satisfy all of the following requirements: + * namespace3.name:1.2.0 + environment: + ANSIBLE_NOCOLOR: True + ANSIBLE_FORCE_COLOR: False + block: + - name: init a new parent collection + command: ansible-galaxy collection init tmp_parent.name --init-path '{{ galaxy_dir }}/scratch' + + - name: replace the dependencies + lineinfile: + path: "{{ galaxy_dir }}/scratch/tmp_parent/name/galaxy.yml" + regexp: "^dependencies:*" + line: "dependencies: { '{{ galaxy_dir }}/namespace3.tar.gz': '1.2.0' }" + + - name: build the new artifact + command: ansible-galaxy collection build {{ galaxy_dir }}/scratch/tmp_parent/name + args: + chdir: "{{ galaxy_dir }}" + + - name: install the artifact to verify the error is handled + command: ansible-galaxy collection install '{{ galaxy_dir }}/tmp_parent-name-1.0.0.tar.gz' + ignore_errors: yes + register: result + + - debug: msg="Actual - {{ error }}" + + - debug: msg="Expected - {{ expected_error }}" + + - assert: + that: error == expected_error + always: + - name: clean up collection skeleton and artifact + file: + state: absent + path: "{{ item }}" + loop: + - "{{ galaxy_dir }}/scratch/tmp_parent/" + - "{{ galaxy_dir }}/tmp_parent-name-1.0.0.tar.gz" + +- name: setup bad tarball - {{ test_id }} + script: build_bad_tar.py {{ galaxy_dir | quote }} + +- name: fail to install a collection from a bad tarball - {{ test_id }} + command: ansible-galaxy collection install '{{ galaxy_dir }}/suspicious-test-1.0.0.tar.gz' {{ galaxy_verbosity }} + register: fail_bad_tar + failed_when: fail_bad_tar.rc != 1 and "Cannot extract tar entry '../../outside.sh' as it will be placed outside the collection directory" not in fail_bad_tar.stderr + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + +- name: get result of failed collection install - {{ test_id }} + stat: + path: '{{ galaxy_dir }}/ansible_collections\suspicious' + register: fail_bad_tar_actual + +- name: assert result of failed collection install - {{ test_id }} + assert: + that: + - not fail_bad_tar_actual.stat.exists + +- name: Find artifact url for namespace4.name + uri: + url: '{{ test_server }}{{ vX }}collections/namespace4/name/versions/1.0.0/' + user: '{{ pulp_user }}' + password: '{{ pulp_password }}' + force_basic_auth: true + register: artifact_url_response + +- name: install a collection from a URI - {{ test_id }} + command: ansible-galaxy collection install {{ artifact_url_response.json.download_url}} {{ galaxy_verbosity }} + register: install_uri + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + +- name: get result of install collection from a URI - {{ test_id }} + slurp: + path: '{{ galaxy_dir }}/ansible_collections/namespace4/name/MANIFEST.json' + register: install_uri_actual + +- name: assert install a collection from a URI - {{ test_id }} + assert: + that: + - '"Installing ''namespace4.name:1.0.0'' to" in install_uri.stdout' + - (install_uri_actual.content | b64decode | from_json).collection_info.version == '1.0.0' + +- name: fail to install a collection with an undefined URL - {{ test_id }} + command: ansible-galaxy collection install namespace5.name {{ galaxy_verbosity }} + register: fail_undefined_server + failed_when: '"No setting was provided for required configuration plugin_type: galaxy_server plugin: undefined" not in fail_undefined_server.stderr' + environment: + ANSIBLE_GALAXY_SERVER_LIST: undefined + +- when: not requires_auth + block: + - name: install a collection with an empty server list - {{ test_id }} + command: ansible-galaxy collection install namespace5.name -s '{{ test_server }}' {{ galaxy_verbosity }} + register: install_empty_server_list + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + ANSIBLE_GALAXY_SERVER_LIST: '' + + - name: get result of a collection with an empty server list - {{ test_id }} + slurp: + path: '{{ galaxy_dir }}/ansible_collections/namespace5/name/MANIFEST.json' + register: install_empty_server_list_actual + + - name: assert install a collection with an empty server list - {{ test_id }} + assert: + that: + - '"Installing ''namespace5.name:1.0.0'' to" in install_empty_server_list.stdout' + - (install_empty_server_list_actual.content | b64decode | from_json).collection_info.version == '1.0.0' + +- name: create test requirements file with both roles and collections - {{ test_id }} + copy: + content: | + collections: + - namespace6.name + - name: namespace7.name + roles: + - skip.me + dest: '{{ galaxy_dir }}/ansible_collections/requirements-with-role.yml' + +- name: install roles from requirements file with collection-only keyring option + command: ansible-galaxy role install -r {{ req_file }} -s {{ test_name }} --keyring {{ keyring }} + vars: + req_file: '{{ galaxy_dir }}/ansible_collections/requirements-with-role.yml' + keyring: "{{ gpg_homedir }}/pubring.kbx" + ignore_errors: yes + register: invalid_opt + +- assert: + that: + - invalid_opt is failed + - "'unrecognized arguments: --keyring' in invalid_opt.stderr" + +# Need to run with -vvv to validate the roles will be skipped msg +- name: install collections only with requirements-with-role.yml - {{ test_id }} + command: ansible-galaxy collection install -r '{{ galaxy_dir }}/ansible_collections/requirements-with-role.yml' -s '{{ test_name }}' -vvv + register: install_req_collection + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + +- name: get result of install collections only with requirements-with-roles.yml - {{ test_id }} + slurp: + path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json' + register: install_req_collection_actual + loop_control: + loop_var: collection + loop: + - namespace6 + - namespace7 + +- name: assert install collections only with requirements-with-role.yml - {{ test_id }} + assert: + that: + - '"contains roles which will be ignored" in install_req_collection.stdout' + - '"Installing ''namespace6.name:1.0.0'' to" in install_req_collection.stdout' + - '"Installing ''namespace7.name:1.0.0'' to" in install_req_collection.stdout' + - (install_req_collection_actual.results[0].content | b64decode | from_json).collection_info.version == '1.0.0' + - (install_req_collection_actual.results[1].content | b64decode | from_json).collection_info.version == '1.0.0' + +- name: create test requirements file with just collections - {{ test_id }} + copy: + content: | + collections: + - namespace8.name + - name: namespace9.name + dest: '{{ galaxy_dir }}/ansible_collections/requirements.yaml' + +- name: install collections with ansible-galaxy install - {{ test_id }} + command: ansible-galaxy install -r '{{ galaxy_dir }}/ansible_collections/requirements.yaml' -s '{{ test_name }}' + register: install_req + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + +- name: get result of install collections with ansible-galaxy install - {{ test_id }} + slurp: + path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json' + register: install_req_actual + loop_control: + loop_var: collection + loop: + - namespace8 + - namespace9 + +- name: assert install collections with ansible-galaxy install - {{ test_id }} + assert: + that: + - '"Installing ''namespace8.name:1.0.0'' to" in install_req.stdout' + - '"Installing ''namespace9.name:1.0.0'' to" in install_req.stdout' + - (install_req_actual.results[0].content | b64decode | from_json).collection_info.version == '1.0.0' + - (install_req_actual.results[1].content | b64decode | from_json).collection_info.version == '1.0.0' + +- name: Test deviations on -r and --role-file without collection or role sub command + command: '{{ cmd }}' + loop: + - ansible-galaxy install -vr '{{ galaxy_dir }}/ansible_collections/requirements.yaml' -s '{{ test_name }}' -vv + - ansible-galaxy install --role-file '{{ galaxy_dir }}/ansible_collections/requirements.yaml' -s '{{ test_name }}' -vvv + - ansible-galaxy install --role-file='{{ galaxy_dir }}/ansible_collections/requirements.yaml' -s '{{ test_name }}' -vvv + loop_control: + loop_var: cmd + +- name: uninstall collections for next requirements file test + file: + path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name' + state: absent + loop_control: + loop_var: collection + loop: + - namespace7 + - namespace8 + - namespace9 + +- name: rewrite requirements file with collections and signatures + copy: + content: | + collections: + - name: namespace7.name + version: "1.0.0" + signatures: + - "{{ not_mine }}" + - "{{ also_not_mine }}" + - "file://{{ gpg_homedir }}/namespace7-name-1.0.0-MANIFEST.json.asc" + - namespace8.name + - name: namespace9.name + signatures: + - "file://{{ gpg_homedir }}/namespace9-name-1.0.0-MANIFEST.json.asc" + dest: '{{ galaxy_dir }}/ansible_collections/requirements.yaml' + vars: + not_mine: "file://{{ gpg_homedir }}/namespace1-name1-1.0.0-MANIFEST.json.asc" + also_not_mine: "file://{{ gpg_homedir }}/namespace1-name1-1.0.9-MANIFEST.json.asc" + +- name: installing only roles does not fail if keyring for collections is not provided + command: ansible-galaxy role install -r {{ galaxy_dir }}/ansible_collections/requirements.yaml + register: roles_only + +- assert: + that: + - roles_only is success + +- name: installing only roles implicitly does not fail if keyring for collections is not provided + # if -p/--roles-path are specified, only roles are installed + command: ansible-galaxy install -r {{ galaxy_dir }}/ansible_collections/requirements.yaml }} -p {{ galaxy_dir }} + register: roles_only + +- assert: + that: + - roles_only is success + +- name: installing roles and collections requires keyring if collections have signatures + command: ansible-galaxy install -r {{ galaxy_dir }}/ansible_collections/requirements.yaml }} + ignore_errors: yes + register: collections_and_roles + +- assert: + that: + - collections_and_roles is failed + - "'no keyring was configured' in collections_and_roles.stderr" + +- name: install collection with mutually exclusive options + command: ansible-galaxy collection install -r {{ req_file }} -s {{ test_name }} {{ cli_signature }} + vars: + req_file: "{{ galaxy_dir }}/ansible_collections/requirements.yaml" + # --signature is an ansible-galaxy collection install subcommand, but mutually exclusive with -r + cli_signature: "--signature file://{{ gpg_homedir }}/namespace7-name-1.0.0-MANIFEST.json.asc" + ignore_errors: yes + register: mutually_exclusive_opts + +- assert: + that: + - mutually_exclusive_opts is failed + - expected_error in actual_error + vars: + expected_error: >- + The --signatures option and --requirements-file are mutually exclusive. + Use the --signatures with positional collection_name args or provide a + 'signatures' key for requirements in the --requirements-file. + actual_error: "{{ mutually_exclusive_opts.stderr }}" + +- name: install a collection with user-supplied signatures for verification but no keyring + command: ansible-galaxy collection install namespace1.name1:1.0.0 {{ cli_signature }} + vars: + cli_signature: "--signature file://{{ gpg_homedir }}/namespace1-name1-1.0.0-MANIFEST.json.asc" + ignore_errors: yes + register: required_together + +- assert: + that: + - required_together is failed + - '"ERROR! Signatures were provided to verify namespace1.name1 but no keyring was configured." in required_together.stderr' + +- name: install collections with ansible-galaxy install -r with invalid signatures - {{ test_id }} + # Note that --keyring is a valid option for 'ansible-galaxy install -r ...', not just 'ansible-galaxy collection ...' + command: ansible-galaxy install -r {{ req_file }} -s {{ test_name }} --keyring {{ keyring }} {{ galaxy_verbosity }} + register: install_req + ignore_errors: yes + vars: + req_file: "{{ galaxy_dir }}/ansible_collections/requirements.yaml" + keyring: "{{ gpg_homedir }}/pubring.kbx" + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + ANSIBLE_GALAXY_REQUIRED_VALID_SIGNATURE_COUNT: all + +- name: assert invalid signature is fatal with ansible-galaxy install - {{ test_id }} + assert: + that: + - install_req is failed + - '"Installing ''namespace7.name:1.0.0'' to" in install_req.stdout' + - '"Not installing namespace7.name because GnuPG signature verification failed" in install_req.stderr' + # The other collections shouldn't be installed because they're listed + # after the failing collection and --ignore-errors was not provided + - '"Installing ''namespace8.name:1.0.0'' to" not in install_req.stdout' + - '"Installing ''namespace9.name:1.0.0'' to" not in install_req.stdout' + +# This command is hardcoded with -vvvv purposefully to evaluate extra verbosity messages +- name: install collections with ansible-galaxy install and --ignore-errors - {{ test_id }} + command: ansible-galaxy install -r {{ req_file }} {{ cli_opts }} -vvvv + register: install_req + vars: + req_file: "{{ galaxy_dir }}/ansible_collections/requirements.yaml" + cli_opts: "-s {{ test_name }} --keyring {{ keyring }} --ignore-errors" + keyring: "{{ gpg_homedir }}/pubring.kbx" + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + ANSIBLE_GALAXY_REQUIRED_VALID_SIGNATURE_COUNT: all + ANSIBLE_NOCOLOR: True + ANSIBLE_FORCE_COLOR: False + +- name: get result of install collections with ansible-galaxy install - {{ test_id }} + slurp: + path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json' + register: install_req_actual + loop_control: + loop_var: collection + loop: + - namespace8 + - namespace9 + +# SIVEL +- name: assert invalid signature is not fatal with ansible-galaxy install --ignore-errors - {{ test_id }} + assert: + that: + - install_req is success + - '"Installing ''namespace7.name:1.0.0'' to" in install_req.stdout' + - '"Signature verification failed for ''namespace7.name'' (return code 1)" in install_req.stdout' + - '"Not installing namespace7.name because GnuPG signature verification failed." in install_stderr' + - '"Failed to install collection namespace7.name:1.0.0 but skipping due to --ignore-errors being set." in install_stderr' + - '"Installing ''namespace8.name:1.0.0'' to" in install_req.stdout' + - '"Installing ''namespace9.name:1.0.0'' to" in install_req.stdout' + - (install_req_actual.results[0].content | b64decode | from_json).collection_info.version == '1.0.0' + - (install_req_actual.results[1].content | b64decode | from_json).collection_info.version == '1.0.0' + vars: + install_stderr: "{{ install_req.stderr | regex_replace('\\n', ' ') }}" + +- name: clean up collections from last test + file: + path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name' + state: absent + loop_control: + loop_var: collection + loop: + - namespace8 + - namespace9 + +- name: install collections with only one valid signature using ansible-galaxy install - {{ test_id }} + command: ansible-galaxy install -r {{ req_file }} {{ cli_opts }} {{ galaxy_verbosity }} + register: install_req + vars: + req_file: "{{ galaxy_dir }}/ansible_collections/requirements.yaml" + cli_opts: "-s {{ test_name }} --keyring {{ keyring }}" + keyring: "{{ gpg_homedir }}/pubring.kbx" + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + ANSIBLE_NOCOLOR: True + ANSIBLE_FORCE_COLOR: False + +- name: get result of install collections with ansible-galaxy install - {{ test_id }} + slurp: + path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json' + register: install_req_actual + loop_control: + loop_var: collection + loop: + - namespace7 + - namespace8 + - namespace9 + +- name: assert just one valid signature is not fatal with ansible-galaxy install - {{ test_id }} + assert: + that: + - install_req is success + - '"Installing ''namespace7.name:1.0.0'' to" in install_req.stdout' + - '"Signature verification failed for ''namespace7.name'' (return code 1)" not in install_req.stdout' + - '"Not installing namespace7.name because GnuPG signature verification failed." not in install_stderr' + - '"Installing ''namespace8.name:1.0.0'' to" in install_req.stdout' + - '"Installing ''namespace9.name:1.0.0'' to" in install_req.stdout' + - (install_req_actual.results[0].content | b64decode | from_json).collection_info.version == '1.0.0' + - (install_req_actual.results[1].content | b64decode | from_json).collection_info.version == '1.0.0' + - (install_req_actual.results[2].content | b64decode | from_json).collection_info.version == '1.0.0' + vars: + install_stderr: "{{ install_req.stderr | regex_replace('\\n', ' ') }}" + +- name: clean up collections from last test + file: + path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name' + state: absent + loop_control: + loop_var: collection + loop: + - namespace7 + - namespace8 + - namespace9 + +- name: install collections with only one valid signature by ignoring the other errors + command: ansible-galaxy install -r {{ req_file }} {{ cli_opts }} {{ galaxy_verbosity }} --ignore-signature-status-code FAILURE + register: install_req + vars: + req_file: "{{ galaxy_dir }}/ansible_collections/requirements.yaml" + cli_opts: "-s {{ test_name }} --keyring {{ keyring }}" + keyring: "{{ gpg_homedir }}/pubring.kbx" + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + ANSIBLE_GALAXY_REQUIRED_VALID_SIGNATURE_COUNT: all + ANSIBLE_GALAXY_IGNORE_SIGNATURE_STATUS_CODES: BADSIG # cli option is appended and both status codes are ignored + ANSIBLE_NOCOLOR: True + ANSIBLE_FORCE_COLOR: False + +- name: get result of install collections with ansible-galaxy install - {{ test_id }} + slurp: + path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json' + register: install_req_actual + loop_control: + loop_var: collection + loop: + - namespace7 + - namespace8 + - namespace9 + +- name: assert invalid signature is not fatal with ansible-galaxy install - {{ test_id }} + assert: + that: + - install_req is success + - '"Installing ''namespace7.name:1.0.0'' to" in install_req.stdout' + - '"Signature verification failed for ''namespace7.name'' (return code 1)" not in install_req.stdout' + - '"Not installing namespace7.name because GnuPG signature verification failed." not in install_stderr' + - '"Installing ''namespace8.name:1.0.0'' to" in install_req.stdout' + - '"Installing ''namespace9.name:1.0.0'' to" in install_req.stdout' + - (install_req_actual.results[0].content | b64decode | from_json).collection_info.version == '1.0.0' + - (install_req_actual.results[1].content | b64decode | from_json).collection_info.version == '1.0.0' + - (install_req_actual.results[2].content | b64decode | from_json).collection_info.version == '1.0.0' + vars: + install_stderr: "{{ install_req.stderr | regex_replace('\\n', ' ') }}" + +- name: clean up collections from last test + file: + path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name' + state: absent + loop_control: + loop_var: collection + loop: + - namespace7 + - namespace8 + - namespace9 + +# Uncomment once pulp container is at pulp>=0.5.0 +#- name: install cache.cache at the current latest version +# command: ansible-galaxy collection install cache.cache -s '{{ test_name }}' -vvv +# environment: +# ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' +# +#- set_fact: +# cache_version_build: '{{ (cache_version_build | int) + 1 }}' +# +#- name: publish update for cache.cache test +# setup_collections: +# server: galaxy_ng +# collections: +# - namespace: cache +# name: cache +# version: 1.0.{{ cache_version_build }} +# +#- name: make sure the cache version list is ignored on a collection version change - {{ test_id }} +# command: ansible-galaxy collection install cache.cache -s '{{ test_name }}' --force -vvv +# register: install_cached_update +# environment: +# ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' +# +#- name: get result of cache version list is ignored on a collection version change - {{ test_id }} +# slurp: +# path: '{{ galaxy_dir }}/ansible_collections/cache/cache/MANIFEST.json' +# register: install_cached_update_actual +# +#- name: assert cache version list is ignored on a collection version change - {{ test_id }} +# assert: +# that: +# - '"Installing ''cache.cache:1.0.{{ cache_version_build }}'' to" in install_cached_update.stdout' +# - (install_cached_update_actual.content | b64decode | from_json).collection_info.version == '1.0.' ~ cache_version_build + +- name: install collection with symlink - {{ test_id }} + command: ansible-galaxy collection install symlink.symlink -s '{{ test_name }}' {{ galaxy_verbosity }} + environment: + ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections' + register: install_symlink + +- find: + paths: '{{ galaxy_dir }}/ansible_collections/symlink/symlink' + recurse: yes + file_type: any + +- name: get result of install collection with symlink - {{ test_id }} + stat: + path: '{{ galaxy_dir }}/ansible_collections/symlink/symlink/{{ path }}' + register: install_symlink_actual + loop_control: + loop_var: path + loop: + - REÅDMÈ.md-link + - docs/REÅDMÈ.md + - plugins/REÅDMÈ.md + - REÅDMÈ.md-outside-link + - docs-link + - docs-link/REÅDMÈ.md + +- name: assert install collection with symlink - {{ test_id }} + assert: + that: + - '"Installing ''symlink.symlink:1.0.0'' to" in install_symlink.stdout' + - install_symlink_actual.results[0].stat.islnk + - install_symlink_actual.results[0].stat.lnk_target == 'REÅDMÈ.md' + - install_symlink_actual.results[1].stat.islnk + - install_symlink_actual.results[1].stat.lnk_target == '../REÅDMÈ.md' + - install_symlink_actual.results[2].stat.islnk + - install_symlink_actual.results[2].stat.lnk_target == '../REÅDMÈ.md' + - install_symlink_actual.results[3].stat.isreg + - install_symlink_actual.results[4].stat.islnk + - install_symlink_actual.results[4].stat.lnk_target == 'docs' + - install_symlink_actual.results[5].stat.islnk + - install_symlink_actual.results[5].stat.lnk_target == '../REÅDMÈ.md' + +- name: remove install directory for the next test because parent_dep.parent_collection was installed - {{ test_id }} + file: + path: '{{ galaxy_dir }}/ansible_collections' + state: absent + +- name: install collection and dep compatible with multiple requirements - {{ test_id }} + command: ansible-galaxy collection install parent_dep.parent_collection parent_dep2.parent_collection + environment: + ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections' + register: install_req + +- name: assert install collections with ansible-galaxy install - {{ test_id }} + assert: + that: + - '"Installing ''parent_dep.parent_collection:1.0.0'' to" in install_req.stdout' + - '"Installing ''parent_dep2.parent_collection:1.0.0'' to" in install_req.stdout' + - '"Installing ''child_dep.child_collection:0.5.0'' to" in install_req.stdout' + +- name: install a collection to a directory that contains another collection with no metadata + block: + + # Collections are usable in ansible without a galaxy.yml or MANIFEST.json + - name: create a collection directory + file: + state: directory + path: '{{ galaxy_dir }}/ansible_collections/unrelated_namespace/collection_without_metadata/plugins' + + - name: install a collection to the same installation directory - {{ test_id }} + command: ansible-galaxy collection install namespace1.name1 + environment: + ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections' + register: install_req + + - name: assert installed collections with ansible-galaxy install - {{ test_id }} + assert: + that: + - '"Installing ''namespace1.name1:1.0.9'' to" in install_req.stdout' + +- name: remove test collection install directory - {{ test_id }} + file: + path: '{{ galaxy_dir }}/ansible_collections' + state: absent + +# This command is hardcoded with -vvvv purposefully to evaluate extra verbosity messages +- name: install collection with signature with invalid keyring + command: ansible-galaxy collection install namespace1.name1 -vvvv {{ signature_option }} {{ keyring_option }} + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + ANSIBLE_NOCOLOR: True + ANSIBLE_FORCE_COLOR: False + vars: + signature_option: "--signature file://{{ gpg_homedir }}/namespace1-name1-1.0.9-MANIFEST.json.asc" + keyring_option: '--keyring {{ gpg_homedir }}/i_do_not_exist.kbx' + ignore_errors: yes + register: keyring_error + +- assert: + that: + - keyring_error is failed + - expected_errors[0] in actual_error + - expected_errors[1] in actual_error + - expected_errors[2] in actual_error + - unexpected_warning not in actual_warning + vars: + keyring: "{{ gpg_homedir }}/i_do_not_exist.kbx" + expected_errors: + - "Signature verification failed for 'namespace1.name1' (return code 2):" + - "* The public key is not available." + - >- + * It was not possible to check the signature. This may be caused + by a missing public key or an unsupported algorithm. A RC of 4 + indicates unknown algorithm, a 9 indicates a missing public key. + unexpected_warning: >- + The GnuPG keyring used for collection signature + verification was not configured but signatures were + provided by the Galaxy server to verify authenticity. + Configure a keyring for ansible-galaxy to use + or disable signature verification. + Skipping signature verification. + actual_warning: "{{ keyring_error.stderr | regex_replace('\\n', ' ') }}" + # Remove formatting from the reason so it's one line + actual_error: "{{ keyring_error.stdout | regex_replace('\"') | regex_replace('\\n') | regex_replace(' ', ' ') }}" + +# TODO: Uncomment once signatures are provided by pulp-galaxy-ng +#- name: install collection with signature provided by Galaxy server (no keyring) +# command: ansible-galaxy collection install namespace1.name1 {{ galaxy_verbosity }} +# environment: +# ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' +# ANSIBLE_NOCOLOR: True +# ANSIBLE_FORCE_COLOR: False +# ignore_errors: yes +# register: keyring_warning +# +#- name: assert a warning was given but signature verification did not occur without configuring the keyring +# assert: +# that: +# - keyring_warning is not failed +# - - '"Installing ''namespace1.name1:1.0.9'' to" in keyring_warning.stdout' +# # TODO: Don't just check the stdout, make sure the collection was installed. +# - expected_warning in actual_warning +# vars: +# expected_warning: >- +# The GnuPG keyring used for collection signature +# verification was not configured but signatures were +# provided by the Galaxy server to verify authenticity. +# Configure a keyring for ansible-galaxy to use +# or disable signature verification. +# Skipping signature verification. +# actual_warning: "{{ keyring_warning.stderr | regex_replace('\\n', ' ') }}" + +- name: install simple collection from first accessible server with valid detached signature + command: ansible-galaxy collection install namespace1.name1 {{ galaxy_verbosity }} {{ signature_options }} + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + vars: + signature_options: "--signature {{ signature }} --keyring {{ keyring }}" + signature: "file://{{ gpg_homedir }}/namespace1-name1-1.0.9-MANIFEST.json.asc" + keyring: "{{ gpg_homedir }}/pubring.kbx" + register: from_first_good_server + +- name: get installed files of install simple collection from first good server + find: + path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1' + file_type: file + register: install_normal_files + +- name: get the manifest of install simple collection from first good server + slurp: + path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1/MANIFEST.json' + register: install_normal_manifest + +- name: assert install simple collection from first good server + assert: + that: + - '"Installing ''namespace1.name1:1.0.9'' to" in from_first_good_server.stdout' + - install_normal_files.files | length == 3 + - install_normal_files.files[0].path | basename in ['MANIFEST.json', 'FILES.json', 'README.md'] + - install_normal_files.files[1].path | basename in ['MANIFEST.json', 'FILES.json', 'README.md'] + - install_normal_files.files[2].path | basename in ['MANIFEST.json', 'FILES.json', 'README.md'] + - (install_normal_manifest.content | b64decode | from_json).collection_info.version == '1.0.9' + +- name: Remove the collection + file: + path: '{{ galaxy_dir }}/ansible_collections/namespace1' + state: absent + +# This command is hardcoded with -vvvv purposefully to evaluate extra verbosity messages +- name: install simple collection with invalid detached signature + command: ansible-galaxy collection install namespace1.name1 -vvvv {{ signature_options }} + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + ANSIBLE_NOCOLOR: True + ANSIBLE_FORCE_COLOR: False + vars: + signature_options: "--signature {{ signature }} --keyring {{ keyring }}" + signature: "file://{{ gpg_homedir }}/namespace2-name-1.0.0-MANIFEST.json.asc" + keyring: "{{ gpg_homedir }}/pubring.kbx" + ignore_errors: yes + register: invalid_signature + +- assert: + that: + - invalid_signature is failed + - "'Not installing namespace1.name1 because GnuPG signature verification failed.' in invalid_signature.stderr" + - expected_errors[0] in install_stdout + - expected_errors[1] in install_stdout + vars: + expected_errors: + - "* This is the counterpart to SUCCESS and used to indicate a program failure." + - "* The signature with the keyid has not been verified okay." + # Remove formatting from the reason so it's one line + install_stdout: "{{ invalid_signature.stdout | regex_replace('\"') | regex_replace('\\n') | regex_replace(' ', ' ') }}" + +- name: validate collection directory was not created + file: + path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1' + state: absent + register: collection_dir + check_mode: yes + failed_when: collection_dir is changed + +- name: disable signature verification and install simple collection with invalid detached signature + command: ansible-galaxy collection install namespace1.name1 {{ galaxy_verbosity }} {{ signature_options }} + environment: + ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' + vars: + signature_options: "--signature {{ signature }} --keyring {{ keyring }} --disable-gpg-verify" + signature: "file://{{ gpg_homedir }}/namespace2-name-1.0.0-MANIFEST.json.asc" + keyring: "{{ gpg_homedir }}/pubring.kbx" + ignore_errors: yes + register: ignore_invalid_signature + +- assert: + that: + - ignore_invalid_signature is success + - '"Installing ''namespace1.name1:1.0.9'' to" in ignore_invalid_signature.stdout' + +- name: use lenient signature verification (default) without providing signatures + command: ansible-galaxy collection install namespace1.name1:1.0.0 -vvvv --keyring {{ gpg_homedir }}/pubring.kbx --force + environment: + ANSIBLE_GALAXY_REQUIRED_VALID_SIGNATURE_COUNT: "all" + register: missing_signature + +- assert: + that: + - missing_signature is success + - missing_signature.rc == 0 + - '"namespace1.name1:1.0.0 was installed successfully" in missing_signature.stdout' + - '"Signature verification failed for ''namespace1.name1'': no successful signatures" not in missing_signature.stdout' + +- name: use strict signature verification without providing signatures + command: ansible-galaxy collection install namespace1.name1:1.0.0 -vvvv --keyring {{ gpg_homedir }}/pubring.kbx --force + environment: + ANSIBLE_GALAXY_REQUIRED_VALID_SIGNATURE_COUNT: "+1" + ignore_errors: yes + register: missing_signature + +- assert: + that: + - missing_signature is failed + - missing_signature.rc == 1 + - '"Signature verification failed for ''namespace1.name1'': no successful signatures" in missing_signature.stdout' + - '"Not installing namespace1.name1 because GnuPG signature verification failed" in missing_signature.stderr' + +- name: Remove the collection + file: + path: '{{ galaxy_dir }}/ansible_collections/namespace1' + state: absent + +- name: download collections with pre-release dep - {{ test_id }} + command: ansible-galaxy collection download dep_with_beta.parent namespace1.name1:1.1.0-beta.1 -p '{{ galaxy_dir }}/scratch' + +- name: install collection with concrete pre-release dep - {{ test_id }} + command: ansible-galaxy collection install -r '{{ galaxy_dir }}/scratch/requirements.yml' + args: + chdir: '{{ galaxy_dir }}/scratch' + environment: + ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections' + register: install_concrete_pre + +- name: get result of install collections with concrete pre-release dep - {{ test_id }} + slurp: + path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/MANIFEST.json' + register: install_concrete_pre_actual + loop_control: + loop_var: collection + loop: + - namespace1/name1 + - dep_with_beta/parent + +- name: assert install collections with ansible-galaxy install - {{ test_id }} + assert: + that: + - '"Installing ''namespace1.name1:1.1.0-beta.1'' to" in install_concrete_pre.stdout' + - '"Installing ''dep_with_beta.parent:1.0.0'' to" in install_concrete_pre.stdout' + - (install_concrete_pre_actual.results[0].content | b64decode | from_json).collection_info.version == '1.1.0-beta.1' + - (install_concrete_pre_actual.results[1].content | b64decode | from_json).collection_info.version == '1.0.0' + +- name: remove collection dir after round of testing - {{ test_id }} + file: + path: '{{ galaxy_dir }}/ansible_collections' + state: absent |