ansible-galaxy - support resolvelib versions >= 0.5.3, < 0.9.0 (#77649) (#78008)

* ansible-galaxy - support resolvelib versions >= 0.5.3, <= 0.8.1

Test incompatibilities are removed for resolvelib >= 0.6.0

Test against the latest 0.8.x version and fix requirements

* Fix tests - use a venv for testing the range of resolvelib versions

* Update temporary hardcoded fallback for ansible-test

* Update hardcoded upperbound for sanity tests

* Make error check more flexible

(cherry picked from commit 143e7fb45e)
pull/78033/head
Sloane Hertel 2 years ago committed by GitHub
parent 44e249df3a
commit cf5c0c9b06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,3 @@
minor_changes:
- ansible-galaxy - Support resolvelib versions 0.6.x, 0.7.x, and 0.8.x.
The full range of supported versions is now >= 0.5.3, < 0.9.0.

@ -41,7 +41,7 @@ except ImportError:
# TODO: add python requirements to ansible-test's ansible-core distribution info and remove the hardcoded lowerbound/upperbound fallback # TODO: add python requirements to ansible-test's ansible-core distribution info and remove the hardcoded lowerbound/upperbound fallback
RESOLVELIB_LOWERBOUND = SemanticVersion("0.5.3") RESOLVELIB_LOWERBOUND = SemanticVersion("0.5.3")
RESOLVELIB_UPPERBOUND = SemanticVersion("0.6.0") RESOLVELIB_UPPERBOUND = SemanticVersion("0.9.0")
RESOLVELIB_VERSION = SemanticVersion.from_loose_version(LooseVersion(resolvelib_version)) RESOLVELIB_VERSION = SemanticVersion.from_loose_version(LooseVersion(resolvelib_version))
@ -73,11 +73,11 @@ class PinnedCandidateRequests(Set):
return len(self._candidates) return len(self._candidates)
class CollectionDependencyProvider(AbstractProvider): class CollectionDependencyProviderBase(AbstractProvider):
"""Delegate providing a requirement interface for the resolver.""" """Delegate providing a requirement interface for the resolver."""
def __init__( def __init__(
self, # type: CollectionDependencyProvider self, # type: CollectionDependencyProviderBase
apis, # type: MultiGalaxyAPIProxy apis, # type: MultiGalaxyAPIProxy
concrete_artifacts_manager=None, # type: ConcreteArtifactsManager concrete_artifacts_manager=None, # type: ConcreteArtifactsManager
user_requirements=None, # type: t.Iterable[Requirement] user_requirements=None, # type: t.Iterable[Requirement]
@ -180,12 +180,8 @@ class CollectionDependencyProvider(AbstractProvider):
""" """
return requirement_or_candidate.canonical_package_id return requirement_or_candidate.canonical_package_id
def get_preference( def get_preference(self, *args, **kwargs):
self, # type: CollectionDependencyProvider # type: (t.Any, t.Any) -> float | int
resolution, # type: Candidate | None
candidates, # type: list[Candidate]
information, # type: list[t.NamedTuple]
): # type: (...) -> float | int
"""Return sort key function return value for given requirement. """Return sort key function return value for given requirement.
This result should be based on preference that is defined as This result should be based on preference that is defined as
@ -193,6 +189,8 @@ class CollectionDependencyProvider(AbstractProvider):
The lower the return value is, the more preferred this The lower the return value is, the more preferred this
group of arguments is. group of arguments is.
resolvelib >=0.5.3, <0.7.0
:param resolution: Currently pinned candidate, or ``None``. :param resolution: Currently pinned candidate, or ``None``.
:param candidates: A list of possible candidates. :param candidates: A list of possible candidates.
@ -208,6 +206,35 @@ class CollectionDependencyProvider(AbstractProvider):
(dependend on) the requirement, or `None` (dependend on) the requirement, or `None`
to indicate a root requirement. to indicate a root requirement.
resolvelib >=0.7.0, < 0.8.0
:param identifier: The value returned by ``identify()``.
:param resolutions: Mapping of identifier, candidate pairs.
:param candidates: Possible candidates for the identifer.
Mapping of identifier, list of candidate pairs.
:param information: Requirement information of each package.
Mapping of identifier, list of named tuple pairs.
The named tuples have the entries ``requirement`` and ``parent``.
resolvelib >=0.8.0, <= 0.8.1
:param identifier: The value returned by ``identify()``.
:param resolutions: Mapping of identifier, candidate pairs.
:param candidates: Possible candidates for the identifer.
Mapping of identifier, list of candidate pairs.
:param information: Requirement information of each package.
Mapping of identifier, list of named tuple pairs.
The named tuples have the entries ``requirement`` and ``parent``.
:param backtrack_causes: Sequence of requirement information that were
the requirements that caused the resolver to most recently backtrack.
The preference could depend on a various of issues, including The preference could depend on a various of issues, including
(not necessarily in this order): (not necessarily in this order):
@ -229,6 +256,10 @@ class CollectionDependencyProvider(AbstractProvider):
the value is, the more preferred this requirement is (i.e. the the value is, the more preferred this requirement is (i.e. the
sorting function is called with ``reverse=False``). sorting function is called with ``reverse=False``).
""" """
raise NotImplementedError
def _get_preference(self, candidates):
# type: (list[Candidate]) -> t.Union[float, int]
if any( if any(
candidate in self._preferred_candidates candidate in self._preferred_candidates
for candidate in candidates for candidate in candidates
@ -238,8 +269,8 @@ class CollectionDependencyProvider(AbstractProvider):
return float('-inf') return float('-inf')
return len(candidates) return len(candidates)
def find_matches(self, requirements): def find_matches(self, *args, **kwargs):
# type: (list[Requirement]) -> list[Candidate] # type: (t.Any, t.Any) -> list[Candidate]
r"""Find all possible candidates satisfying given requirements. r"""Find all possible candidates satisfying given requirements.
This tries to get candidates based on the requirements' types. This tries to get candidates based on the requirements' types.
@ -251,15 +282,31 @@ class CollectionDependencyProvider(AbstractProvider):
to find concrete candidates for this requirement. Of theres a to find concrete candidates for this requirement. Of theres a
pre-installed candidate, it's prepended in front of others. pre-installed candidate, it's prepended in front of others.
resolvelib >=0.5.3, <0.6.0
:param requirements: A collection of requirements which all of \ :param requirements: A collection of requirements which all of \
the returned candidates must match. \ the returned candidates must match. \
All requirements are guaranteed to have \ All requirements are guaranteed to have \
the same identifier. \ the same identifier. \
The collection is never empty. The collection is never empty.
resolvelib >=0.6.0
:param identifier: The value returned by ``identify()``.
:param requirements: The requirements all returned candidates must satisfy.
Mapping of identifier, iterator of requirement pairs.
:param incompatibilities: Incompatible versions that must be excluded
from the returned list.
:returns: An iterable that orders candidates by preference, \ :returns: An iterable that orders candidates by preference, \
e.g. the most preferred candidate comes first. e.g. the most preferred candidate comes first.
""" """
raise NotImplementedError
def _find_matches(self, requirements):
# type: (list[Requirement]) -> list[Candidate]
# FIXME: The first requirement may be a Git repo followed by # FIXME: The first requirement may be a Git repo followed by
# FIXME: its cloned tmp dir. Using only the first one creates # FIXME: its cloned tmp dir. Using only the first one creates
# FIXME: loops that prevent any further dependency exploration. # FIXME: loops that prevent any further dependency exploration.
@ -438,3 +485,52 @@ class CollectionDependencyProvider(AbstractProvider):
self._make_req_from_dict({'name': dep_name, 'version': dep_req}) self._make_req_from_dict({'name': dep_name, 'version': dep_req})
for dep_name, dep_req in req_map.items() for dep_name, dep_req in req_map.items()
] ]
# Classes to handle resolvelib API changes between minor versions for 0.X
class CollectionDependencyProvider050(CollectionDependencyProviderBase):
def find_matches(self, requirements): # type: ignore[override]
# type: (list[Requirement]) -> list[Candidate]
return self._find_matches(requirements)
def get_preference(self, resolution, candidates, information): # type: ignore[override]
# type: (t.Optional[Candidate], list[Candidate], list[t.NamedTuple]) -> t.Union[float, int]
return self._get_preference(candidates)
class CollectionDependencyProvider060(CollectionDependencyProviderBase):
def find_matches(self, identifier, requirements, incompatibilities): # type: ignore[override]
# type: (str, t.Mapping[str, t.Iterator[Requirement]], t.Mapping[str, t.Iterator[Requirement]]) -> list[Candidate]
return [
match for match in self._find_matches(list(requirements[identifier]))
if not any(match.ver == incompat.ver for incompat in incompatibilities[identifier])
]
def get_preference(self, resolution, candidates, information): # type: ignore[override]
# type: (t.Optional[Candidate], list[Candidate], list[t.NamedTuple]) -> t.Union[float, int]
return self._get_preference(candidates)
class CollectionDependencyProvider070(CollectionDependencyProvider060):
def get_preference(self, identifier, resolutions, candidates, information): # type: ignore[override]
# type: (str, t.Mapping[str, Candidate], t.Mapping[str, t.Iterator[Candidate]], t.Iterator[t.NamedTuple]) -> t.Union[float, int]
return self._get_preference(list(candidates[identifier]))
class CollectionDependencyProvider080(CollectionDependencyProvider060):
def get_preference(self, identifier, resolutions, candidates, information, backtrack_causes): # type: ignore[override]
# type: (str, t.Mapping[str, Candidate], t.Mapping[str, t.Iterator[Candidate]], t.Iterator[t.NamedTuple], t.Sequence) -> t.Union[float, int]
return self._get_preference(list(candidates[identifier]))
def _get_provider(): # type () -> CollectionDependencyProviderBase
if RESOLVELIB_VERSION >= SemanticVersion("0.8.0"):
return CollectionDependencyProvider080
if RESOLVELIB_VERSION >= SemanticVersion("0.7.0"):
return CollectionDependencyProvider070
if RESOLVELIB_VERSION >= SemanticVersion("0.6.0"):
return CollectionDependencyProvider060
return CollectionDependencyProvider050
CollectionDependencyProvider = _get_provider()

@ -10,4 +10,6 @@ packaging
# NOTE: resolvelib 0.x version bumps should be considered major/breaking # NOTE: resolvelib 0.x version bumps should be considered major/breaking
# NOTE: and we should update the upper cap with care, at least until 1.0 # NOTE: and we should update the upper cap with care, at least until 1.0
# NOTE: Ref: https://github.com/sarugaku/resolvelib/issues/69 # NOTE: Ref: https://github.com/sarugaku/resolvelib/issues/69
resolvelib >= 0.5.3, < 0.6.0 # dependency resolver used by ansible-galaxy # NOTE: When updating the upper bound, also update the latest version used
# NOTE: in the ansible-galaxy-collection test suite.
resolvelib >= 0.5.3, < 0.9.0 # dependency resolver used by ansible-galaxy

@ -23,6 +23,10 @@
- include_tasks: ./multi_collection_repo_individual.yml - include_tasks: ./multi_collection_repo_individual.yml
- include_tasks: ./setup_recursive_scm_dependency.yml - include_tasks: ./setup_recursive_scm_dependency.yml
- include_tasks: ./scm_dependency_deduplication.yml - include_tasks: ./scm_dependency_deduplication.yml
- include_tasks: ./test_supported_resolvelib_versions.yml
loop: "{{ supported_resolvelib_versions }}"
loop_control:
loop_var: resolvelib_version
- include_tasks: ./download.yml - include_tasks: ./download.yml
- include_tasks: ./setup_collection_bad_version.yml - include_tasks: ./setup_collection_bad_version.yml
- include_tasks: ./test_invalid_version.yml - include_tasks: ./test_invalid_version.yml

@ -0,0 +1,25 @@
- vars:
venv_cmd: "{{ ansible_python_interpreter ~ ' -m venv' }}"
venv_dest: "{{ galaxy_dir }}/test_venv_{{ resolvelib_version }}"
block:
- name: install another version of resolvelib that is supported by ansible-galaxy
pip:
name: resolvelib
version: "{{ resolvelib_version }}"
state: present
virtualenv_command: "{{ venv_cmd }}"
virtualenv: "{{ venv_dest }}"
virtualenv_site_packages: True
- include_tasks: ./scm_dependency_deduplication.yml
args:
apply:
environment:
PATH: "{{ venv_dest }}/bin:{{ ansible_env.PATH }}"
ANSIBLE_CONFIG: '{{ galaxy_dir }}/ansible.cfg'
always:
- name: remove test venv
file:
path: "{{ venv_dest }}"
state: absent

@ -3,3 +3,9 @@ alt_install_path: "{{ galaxy_dir }}/other_collections/ansible_collections"
scm_path: "{{ galaxy_dir }}/development" scm_path: "{{ galaxy_dir }}/development"
test_repo_path: "{{ galaxy_dir }}/development/ansible_test" test_repo_path: "{{ galaxy_dir }}/development/ansible_test"
test_error_repo_path: "{{ galaxy_dir }}/development/error_test" test_error_repo_path: "{{ galaxy_dir }}/development/error_test"
supported_resolvelib_versions:
- "0.5.3" # Oldest supported
- "0.6.0"
- "0.7.0"
- "0.8.0"

@ -169,3 +169,8 @@
that: that:
- '"Downloading collection ''ansible_test.my_collection:1.0.0'' to" in download_collection.stdout' - '"Downloading collection ''ansible_test.my_collection:1.0.0'' to" in download_collection.stdout'
- download_collection_actual.stat.exists - download_collection_actual.stat.exists
- name: remove test download dir
file:
path: '{{ galaxy_dir }}/download'
state: absent

@ -0,0 +1,45 @@
# resolvelib>=0.6.0 added an 'incompatibilities' parameter to find_matches
# If incompatibilities aren't removed from the viable candidates, this example causes infinite resursion
- name: test resolvelib removes incompatibilites in find_matches and errors quickly (prevent infinite recursion)
block:
- name: create collection dir
file:
dest: "{{ galaxy_dir }}/resolvelib/ns/coll"
state: directory
- name: create galaxy.yml with a dependecy on a galaxy-sourced collection
copy:
dest: "{{ galaxy_dir }}/resolvelib/ns/coll/galaxy.yml"
content: |
namespace: ns
name: coll
authors:
- ansible-core
readme: README.md
version: "1.0.0"
dependencies:
namespace1.name1: "0.0.5"
- name: build the collection
command: ansible-galaxy collection build ns/coll
args:
chdir: "{{ galaxy_dir }}/resolvelib"
- name: install a conflicting version of the dep with the tarfile (expected failure)
command: ansible-galaxy collection install namespace1.name1:1.0.9 ns-coll-1.0.0.tar.gz -vvvvv -s {{ test_name }} -p collections/
args:
chdir: "{{ galaxy_dir }}/resolvelib"
timeout: 30
ignore_errors: yes
register: incompatible
- assert:
that:
- incompatible.failed
- not incompatible.msg.startswith("The command action failed to execute in the expected time frame")
always:
- name: cleanup resolvelib test
file:
dest: "{{ galaxy_dir }}/resolvelib"
state: absent

@ -1,5 +1,5 @@
--- ---
- name: create test collection install directory - {{ test_name }} - name: create test collection install directory - {{ test_id }}
file: file:
path: '{{ galaxy_dir }}/ansible_collections' path: '{{ galaxy_dir }}/ansible_collections'
state: directory state: directory
@ -36,24 +36,24 @@
path: '{{ galaxy_dir }}/ansible_collections/namespace1' path: '{{ galaxy_dir }}/ansible_collections/namespace1'
state: absent state: absent
- name: install simple collection with implicit path - {{ test_name }} - name: install simple collection with implicit path - {{ test_id }}
command: ansible-galaxy collection install namespace1.name1 -s '{{ test_name }}' {{ galaxy_verbosity }} command: ansible-galaxy collection install namespace1.name1 -s '{{ test_name }}' {{ galaxy_verbosity }}
environment: environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
register: install_normal register: install_normal
- name: get installed files of install simple collection with implicit path - {{ test_name }} - name: get installed files of install simple collection with implicit path - {{ test_id }}
find: find:
path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1' path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1'
file_type: file file_type: file
register: install_normal_files register: install_normal_files
- name: get the manifest of install simple collection with implicit path - {{ test_name }} - name: get the manifest of install simple collection with implicit path - {{ test_id }}
slurp: slurp:
path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1/MANIFEST.json' path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1/MANIFEST.json'
register: install_normal_manifest register: install_normal_manifest
- name: assert install simple collection with implicit path - {{ test_name }} - name: assert install simple collection with implicit path - {{ test_id }}
assert: assert:
that: that:
- '"Installing ''namespace1.name1:1.0.9'' to" in install_normal.stdout' - '"Installing ''namespace1.name1:1.0.9'' to" in install_normal.stdout'
@ -63,43 +63,43 @@
- install_normal_files.files[2].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' - (install_normal_manifest.content | b64decode | from_json).collection_info.version == '1.0.9'
- name: install existing without --force - {{ test_name }} - name: install existing without --force - {{ test_id }}
command: ansible-galaxy collection install namespace1.name1 -s '{{ test_name }}' {{ galaxy_verbosity }} command: ansible-galaxy collection install namespace1.name1 -s '{{ test_name }}' {{ galaxy_verbosity }}
environment: environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
register: install_existing_no_force register: install_existing_no_force
- name: assert install existing without --force - {{ test_name }} - name: assert install existing without --force - {{ test_id }}
assert: assert:
that: that:
- '"Nothing to do. All requested collections are already installed" in install_existing_no_force.stdout' - '"Nothing to do. All requested collections are already installed" in install_existing_no_force.stdout'
- name: install existing with --force - {{ test_name }} - name: install existing with --force - {{ test_id }}
command: ansible-galaxy collection install namespace1.name1 -s '{{ test_name }}' --force {{ galaxy_verbosity }} command: ansible-galaxy collection install namespace1.name1 -s '{{ test_name }}' --force {{ galaxy_verbosity }}
environment: environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
register: install_existing_force register: install_existing_force
- name: assert install existing with --force - {{ test_name }} - name: assert install existing with --force - {{ test_id }}
assert: assert:
that: that:
- '"Installing ''namespace1.name1:1.0.9'' to" in install_existing_force.stdout' - '"Installing ''namespace1.name1:1.0.9'' to" in install_existing_force.stdout'
- name: remove test installed collection - {{ test_name }} - name: remove test installed collection - {{ test_id }}
file: file:
path: '{{ galaxy_dir }}/ansible_collections/namespace1' path: '{{ galaxy_dir }}/ansible_collections/namespace1'
state: absent state: absent
- name: install pre-release as explicit version to custom dir - {{ test_name }} - 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 }} 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 register: install_prerelease
- name: get result of install pre-release as explicit version to custom dir - {{ test_name }} - name: get result of install pre-release as explicit version to custom dir - {{ test_id }}
slurp: slurp:
path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1/MANIFEST.json' path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1/MANIFEST.json'
register: install_prerelease_actual register: install_prerelease_actual
- name: assert install pre-release as explicit version to custom dir - {{ test_name }} - name: assert install pre-release as explicit version to custom dir - {{ test_id }}
assert: assert:
that: that:
- '"Installing ''namespace1.name1:1.1.0-beta.1'' to" in install_prerelease.stdout' - '"Installing ''namespace1.name1:1.1.0-beta.1'' to" in install_prerelease.stdout'
@ -110,22 +110,22 @@
path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1' path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1'
state: absent state: absent
- name: install pre-release version with --pre to custom dir - {{ test_name }} - 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 }} command: ansible-galaxy collection install --pre 'namespace1.name1' -s '{{ test_name }}' -p '{{ galaxy_dir }}/ansible_collections' {{ galaxy_verbosity }}
register: install_prerelease register: install_prerelease
- name: get result of install pre-release version with --pre to custom dir - {{ test_name }} - name: get result of install pre-release version with --pre to custom dir - {{ test_id }}
slurp: slurp:
path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1/MANIFEST.json' path: '{{ galaxy_dir }}/ansible_collections/namespace1/name1/MANIFEST.json'
register: install_prerelease_actual register: install_prerelease_actual
- name: assert install pre-release version with --pre to custom dir - {{ test_name }} - name: assert install pre-release version with --pre to custom dir - {{ test_id }}
assert: assert:
that: that:
- '"Installing ''namespace1.name1:1.1.0-beta.1'' to" in install_prerelease.stdout' - '"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' - (install_prerelease_actual.content | b64decode | from_json).collection_info.version == '1.1.0-beta.1'
- name: install multiple collections with dependencies - {{ test_name }} - 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 }} command: ansible-galaxy collection install parent_dep.parent_collection:1.0.0 namespace2.name -s {{ test_name }} {{ galaxy_verbosity }}
args: args:
chdir: '{{ galaxy_dir }}/ansible_collections' chdir: '{{ galaxy_dir }}/ansible_collections'
@ -134,7 +134,7 @@
ANSIBLE_CONFIG: '{{ galaxy_dir }}/ansible.cfg' ANSIBLE_CONFIG: '{{ galaxy_dir }}/ansible.cfg'
register: install_multiple_with_dep register: install_multiple_with_dep
- name: get result of install multiple collections with dependencies - {{ test_name }} - name: get result of install multiple collections with dependencies - {{ test_id }}
slurp: slurp:
path: '{{ galaxy_dir }}/ansible_collections/{{ collection.namespace }}/{{ collection.name }}/MANIFEST.json' path: '{{ galaxy_dir }}/ansible_collections/{{ collection.namespace }}/{{ collection.name }}/MANIFEST.json'
register: install_multiple_with_dep_actual register: install_multiple_with_dep_actual
@ -150,7 +150,7 @@
- namespace: child_dep - namespace: child_dep
name: child_dep2 name: child_dep2
- name: assert install multiple collections with dependencies - {{ test_name }} - name: assert install multiple collections with dependencies - {{ test_id }}
assert: assert:
that: that:
- (install_multiple_with_dep_actual.results[0].content | b64decode | from_json).collection_info.version == '1.0.0' - (install_multiple_with_dep_actual.results[0].content | b64decode | from_json).collection_info.version == '1.0.0'
@ -158,7 +158,7 @@
- (install_multiple_with_dep_actual.results[2].content | b64decode | from_json).collection_info.version == '0.9.9' - (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' - (install_multiple_with_dep_actual.results[3].content | b64decode | from_json).collection_info.version == '1.2.2'
- name: expect failure with dep resolution failure - name: expect failure with dep resolution failure - {{ test_id }}
command: ansible-galaxy collection install fail_namespace.fail_collection -s {{ test_name }} {{ galaxy_verbosity }} command: ansible-galaxy collection install fail_namespace.fail_collection -s {{ test_name }} {{ galaxy_verbosity }}
register: fail_dep_mismatch register: fail_dep_mismatch
failed_when: failed_when:
@ -173,23 +173,23 @@
force_basic_auth: true force_basic_auth: true
register: artifact_url_response register: artifact_url_response
- name: download a collection for an offline install - {{ test_name }} - name: download a collection for an offline install - {{ test_id }}
get_url: get_url:
url: '{{ artifact_url_response.json.download_url }}' url: '{{ artifact_url_response.json.download_url }}'
dest: '{{ galaxy_dir }}/namespace3.tar.gz' dest: '{{ galaxy_dir }}/namespace3.tar.gz'
- name: install a collection from a tarball - {{ test_name }} - name: install a collection from a tarball - {{ test_id }}
command: ansible-galaxy collection install '{{ galaxy_dir }}/namespace3.tar.gz' {{ galaxy_verbosity }} command: ansible-galaxy collection install '{{ galaxy_dir }}/namespace3.tar.gz' {{ galaxy_verbosity }}
register: install_tarball register: install_tarball
environment: environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
- name: get result of install collection from a tarball - {{ test_name }} - name: get result of install collection from a tarball - {{ test_id }}
slurp: slurp:
path: '{{ galaxy_dir }}/ansible_collections/namespace3/name/MANIFEST.json' path: '{{ galaxy_dir }}/ansible_collections/namespace3/name/MANIFEST.json'
register: install_tarball_actual register: install_tarball_actual
- name: assert install a collection from a tarball - {{ test_name }} - name: assert install a collection from a tarball - {{ test_id }}
assert: assert:
that: that:
- '"Installing ''namespace3.name:1.0.0'' to" in install_tarball.stdout' - '"Installing ''namespace3.name:1.0.0'' to" in install_tarball.stdout'
@ -270,22 +270,22 @@
- "{{ galaxy_dir }}/scratch/tmp_parent/" - "{{ galaxy_dir }}/scratch/tmp_parent/"
- "{{ galaxy_dir }}/tmp_parent-name-1.0.0.tar.gz" - "{{ galaxy_dir }}/tmp_parent-name-1.0.0.tar.gz"
- name: setup bad tarball - {{ test_name }} - name: setup bad tarball - {{ test_id }}
script: build_bad_tar.py {{ galaxy_dir | quote }} script: build_bad_tar.py {{ galaxy_dir | quote }}
- name: fail to install a collection from a bad tarball - {{ test_name }} - 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 }} command: ansible-galaxy collection install '{{ galaxy_dir }}/suspicious-test-1.0.0.tar.gz' {{ galaxy_verbosity }}
register: fail_bad_tar 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 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: environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
- name: get result of failed collection install - {{ test_name }} - name: get result of failed collection install - {{ test_id }}
stat: stat:
path: '{{ galaxy_dir }}/ansible_collections\suspicious' path: '{{ galaxy_dir }}/ansible_collections\suspicious'
register: fail_bad_tar_actual register: fail_bad_tar_actual
- name: assert result of failed collection install - {{ test_name }} - name: assert result of failed collection install - {{ test_id }}
assert: assert:
that: that:
- not fail_bad_tar_actual.stat.exists - not fail_bad_tar_actual.stat.exists
@ -298,24 +298,24 @@
force_basic_auth: true force_basic_auth: true
register: artifact_url_response register: artifact_url_response
- name: install a collection from a URI - {{ test_name }} - name: install a collection from a URI - {{ test_id }}
command: ansible-galaxy collection install {{ artifact_url_response.json.download_url}} {{ galaxy_verbosity }} command: ansible-galaxy collection install {{ artifact_url_response.json.download_url}} {{ galaxy_verbosity }}
register: install_uri register: install_uri
environment: environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
- name: get result of install collection from a URI - {{ test_name }} - name: get result of install collection from a URI - {{ test_id }}
slurp: slurp:
path: '{{ galaxy_dir }}/ansible_collections/namespace4/name/MANIFEST.json' path: '{{ galaxy_dir }}/ansible_collections/namespace4/name/MANIFEST.json'
register: install_uri_actual register: install_uri_actual
- name: assert install a collection from a URI - {{ test_name }} - name: assert install a collection from a URI - {{ test_id }}
assert: assert:
that: that:
- '"Installing ''namespace4.name:1.0.0'' to" in install_uri.stdout' - '"Installing ''namespace4.name:1.0.0'' to" in install_uri.stdout'
- (install_uri_actual.content | b64decode | from_json).collection_info.version == '1.0.0' - (install_uri_actual.content | b64decode | from_json).collection_info.version == '1.0.0'
- name: fail to install a collection with an undefined URL - {{ test_name }} - name: fail to install a collection with an undefined URL - {{ test_id }}
command: ansible-galaxy collection install namespace5.name {{ galaxy_verbosity }} command: ansible-galaxy collection install namespace5.name {{ galaxy_verbosity }}
register: fail_undefined_server 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' failed_when: '"No setting was provided for required configuration plugin_type: galaxy_server plugin: undefined" not in fail_undefined_server.stderr'
@ -324,25 +324,25 @@
- when: not requires_auth - when: not requires_auth
block: block:
- name: install a collection with an empty server list - {{ test_name }} - name: install a collection with an empty server list - {{ test_id }}
command: ansible-galaxy collection install namespace5.name -s '{{ test_server }}' {{ galaxy_verbosity }} command: ansible-galaxy collection install namespace5.name -s '{{ test_server }}' {{ galaxy_verbosity }}
register: install_empty_server_list register: install_empty_server_list
environment: environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
ANSIBLE_GALAXY_SERVER_LIST: '' ANSIBLE_GALAXY_SERVER_LIST: ''
- name: get result of a collection with an empty server list - {{ test_name }} - name: get result of a collection with an empty server list - {{ test_id }}
slurp: slurp:
path: '{{ galaxy_dir }}/ansible_collections/namespace5/name/MANIFEST.json' path: '{{ galaxy_dir }}/ansible_collections/namespace5/name/MANIFEST.json'
register: install_empty_server_list_actual register: install_empty_server_list_actual
- name: assert install a collection with an empty server list - {{ test_name }} - name: assert install a collection with an empty server list - {{ test_id }}
assert: assert:
that: that:
- '"Installing ''namespace5.name:1.0.0'' to" in install_empty_server_list.stdout' - '"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' - (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_name }} - name: create test requirements file with both roles and collections - {{ test_id }}
copy: copy:
content: | content: |
collections: collections:
@ -366,13 +366,13 @@
- "'unrecognized arguments: --keyring' in invalid_opt.stderr" - "'unrecognized arguments: --keyring' in invalid_opt.stderr"
# Need to run with -vvv to validate the roles will be skipped msg # Need to run with -vvv to validate the roles will be skipped msg
- name: install collections only with requirements-with-role.yml - {{ test_name }} - 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 command: ansible-galaxy collection install -r '{{ galaxy_dir }}/ansible_collections/requirements-with-role.yml' -s '{{ test_name }}' -vvv
register: install_req_collection register: install_req_collection
environment: environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
- name: get result of install collections only with requirements-with-roles.yml - {{ test_name }} - name: get result of install collections only with requirements-with-roles.yml - {{ test_id }}
slurp: slurp:
path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json' path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json'
register: install_req_collection_actual register: install_req_collection_actual
@ -382,7 +382,7 @@
- namespace6 - namespace6
- namespace7 - namespace7
- name: assert install collections only with requirements-with-role.yml - {{ test_name }} - name: assert install collections only with requirements-with-role.yml - {{ test_id }}
assert: assert:
that: that:
- '"contains roles which will be ignored" in install_req_collection.stdout' - '"contains roles which will be ignored" in install_req_collection.stdout'
@ -391,7 +391,7 @@
- (install_req_collection_actual.results[0].content | b64decode | from_json).collection_info.version == '1.0.0' - (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' - (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_name }} - name: create test requirements file with just collections - {{ test_id }}
copy: copy:
content: | content: |
collections: collections:
@ -399,13 +399,13 @@
- name: namespace9.name - name: namespace9.name
dest: '{{ galaxy_dir }}/ansible_collections/requirements.yaml' dest: '{{ galaxy_dir }}/ansible_collections/requirements.yaml'
- name: install collections with ansible-galaxy install - {{ test_name }} - name: install collections with ansible-galaxy install - {{ test_id }}
command: ansible-galaxy install -r '{{ galaxy_dir }}/ansible_collections/requirements.yaml' -s '{{ test_name }}' command: ansible-galaxy install -r '{{ galaxy_dir }}/ansible_collections/requirements.yaml' -s '{{ test_name }}'
register: install_req register: install_req
environment: environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
- name: get result of install collections with ansible-galaxy install - {{ test_name }} - name: get result of install collections with ansible-galaxy install - {{ test_id }}
slurp: slurp:
path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json' path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json'
register: install_req_actual register: install_req_actual
@ -415,7 +415,7 @@
- namespace8 - namespace8
- namespace9 - namespace9
- name: assert install collections with ansible-galaxy install - {{ test_name }} - name: assert install collections with ansible-galaxy install - {{ test_id }}
assert: assert:
that: that:
- '"Installing ''namespace8.name:1.0.0'' to" in install_req.stdout' - '"Installing ''namespace8.name:1.0.0'' to" in install_req.stdout'
@ -485,7 +485,7 @@
- required_together is failed - required_together is failed
- '"ERROR! Signatures were provided to verify namespace1.name1 but no keyring was configured." in required_together.stderr' - '"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_name }} - 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 ...' # 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 }} command: ansible-galaxy install -r {{ req_file }} -s {{ test_name }} --keyring {{ keyring }} {{ galaxy_verbosity }}
register: install_req register: install_req
@ -497,7 +497,7 @@
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
ANSIBLE_GALAXY_REQUIRED_VALID_SIGNATURE_COUNT: all ANSIBLE_GALAXY_REQUIRED_VALID_SIGNATURE_COUNT: all
- name: assert invalid signature is fatal with ansible-galaxy install - {{ test_name }} - name: assert invalid signature is fatal with ansible-galaxy install - {{ test_id }}
assert: assert:
that: that:
- install_req is failed - install_req is failed
@ -509,7 +509,7 @@
- '"Installing ''namespace9.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 # This command is hardcoded with -vvvv purposefully to evaluate extra verbosity messages
- name: install collections with ansible-galaxy install and --ignore-errors - {{ test_name }} - name: install collections with ansible-galaxy install and --ignore-errors - {{ test_id }}
command: ansible-galaxy install -r {{ req_file }} {{ cli_opts }} -vvvv command: ansible-galaxy install -r {{ req_file }} {{ cli_opts }} -vvvv
register: install_req register: install_req
vars: vars:
@ -520,7 +520,7 @@
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
ANSIBLE_GALAXY_REQUIRED_VALID_SIGNATURE_COUNT: all ANSIBLE_GALAXY_REQUIRED_VALID_SIGNATURE_COUNT: all
- name: get result of install collections with ansible-galaxy install - {{ test_name }} - name: get result of install collections with ansible-galaxy install - {{ test_id }}
slurp: slurp:
path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json' path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json'
register: install_req_actual register: install_req_actual
@ -531,7 +531,7 @@
- namespace9 - namespace9
# SIVEL # SIVEL
- name: assert invalid signature is not fatal with ansible-galaxy install --ignore-errors - {{ test_name }} - name: assert invalid signature is not fatal with ansible-galaxy install --ignore-errors - {{ test_id }}
assert: assert:
that: that:
- install_req is success - install_req is success
@ -558,7 +558,7 @@
- namespace8 - namespace8
- namespace9 - namespace9
- name: install collections with only one valid signature using ansible-galaxy install - {{ test_name }} - 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 }} command: ansible-galaxy install -r {{ req_file }} {{ cli_opts }} {{ galaxy_verbosity }}
register: install_req register: install_req
vars: vars:
@ -568,7 +568,7 @@
environment: environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
- name: get result of install collections with ansible-galaxy install - {{ test_name }} - name: get result of install collections with ansible-galaxy install - {{ test_id }}
slurp: slurp:
path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json' path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json'
register: install_req_actual register: install_req_actual
@ -579,7 +579,7 @@
- namespace8 - namespace8
- namespace9 - namespace9
- name: assert just one valid signature is not fatal with ansible-galaxy install - {{ test_name }} - name: assert just one valid signature is not fatal with ansible-galaxy install - {{ test_id }}
assert: assert:
that: that:
- install_req is success - install_req is success
@ -619,7 +619,7 @@
ANSIBLE_GALAXY_REQUIRED_VALID_SIGNATURE_COUNT: all 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_GALAXY_IGNORE_SIGNATURE_STATUS_CODES: BADSIG # cli option is appended and both status codes are ignored
- name: get result of install collections with ansible-galaxy install - {{ test_name }} - name: get result of install collections with ansible-galaxy install - {{ test_id }}
slurp: slurp:
path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json' path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/name/MANIFEST.json'
register: install_req_actual register: install_req_actual
@ -630,7 +630,7 @@
- namespace8 - namespace8
- namespace9 - namespace9
- name: assert invalid signature is not fatal with ansible-galaxy install - {{ test_name }} - name: assert invalid signature is not fatal with ansible-galaxy install - {{ test_id }}
assert: assert:
that: that:
- install_req is success - install_req is success
@ -675,24 +675,24 @@
# name: cache # name: cache
# version: 1.0.{{ cache_version_build }} # version: 1.0.{{ cache_version_build }}
# #
#- name: make sure the cache version list is ignored on a collection version change - {{ test_name }} #- 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 # command: ansible-galaxy collection install cache.cache -s '{{ test_name }}' --force -vvv
# register: install_cached_update # register: install_cached_update
# environment: # environment:
# ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' # ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
# #
#- name: get result of cache version list is ignored on a collection version change - {{ test_name }} #- name: get result of cache version list is ignored on a collection version change - {{ test_id }}
# slurp: # slurp:
# path: '{{ galaxy_dir }}/ansible_collections/cache/cache/MANIFEST.json' # path: '{{ galaxy_dir }}/ansible_collections/cache/cache/MANIFEST.json'
# register: install_cached_update_actual # register: install_cached_update_actual
# #
#- name: assert cache version list is ignored on a collection version change - {{ test_name }} #- name: assert cache version list is ignored on a collection version change - {{ test_id }}
# assert: # assert:
# that: # that:
# - '"Installing ''cache.cache:1.0.{{ cache_version_build }}'' to" in install_cached_update.stdout' # - '"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 # - (install_cached_update_actual.content | b64decode | from_json).collection_info.version == '1.0.' ~ cache_version_build
- name: install collection with symlink - {{ test_name }} - name: install collection with symlink - {{ test_id }}
command: ansible-galaxy collection install symlink.symlink -s '{{ test_name }}' {{ galaxy_verbosity }} command: ansible-galaxy collection install symlink.symlink -s '{{ test_name }}' {{ galaxy_verbosity }}
environment: environment:
ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections'
@ -703,7 +703,7 @@
recurse: yes recurse: yes
file_type: any file_type: any
- name: get result of install collection with symlink - {{ test_name }} - name: get result of install collection with symlink - {{ test_id }}
stat: stat:
path: '{{ galaxy_dir }}/ansible_collections/symlink/symlink/{{ path }}' path: '{{ galaxy_dir }}/ansible_collections/symlink/symlink/{{ path }}'
register: install_symlink_actual register: install_symlink_actual
@ -717,7 +717,7 @@
- docs-link - docs-link
- docs-link/REÅDMÈ.md - docs-link/REÅDMÈ.md
- name: assert install collection with symlink - {{ test_name }} - name: assert install collection with symlink - {{ test_id }}
assert: assert:
that: that:
- '"Installing ''symlink.symlink:1.0.0'' to" in install_symlink.stdout' - '"Installing ''symlink.symlink:1.0.0'' to" in install_symlink.stdout'
@ -733,18 +733,18 @@
- install_symlink_actual.results[5].stat.islnk - install_symlink_actual.results[5].stat.islnk
- install_symlink_actual.results[5].stat.lnk_target == '../REÅDMÈ.md' - 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_name }} - name: remove install directory for the next test because parent_dep.parent_collection was installed - {{ test_id }}
file: file:
path: '{{ galaxy_dir }}/ansible_collections' path: '{{ galaxy_dir }}/ansible_collections'
state: absent state: absent
- name: install collection and dep compatible with multiple requirements - {{ test_name }} - name: install collection and dep compatible with multiple requirements - {{ test_id }}
command: ansible-galaxy collection install parent_dep.parent_collection parent_dep2.parent_collection command: ansible-galaxy collection install parent_dep.parent_collection parent_dep2.parent_collection
environment: environment:
ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections'
register: install_req register: install_req
- name: assert install collections with ansible-galaxy install - {{ test_name }} - name: assert install collections with ansible-galaxy install - {{ test_id }}
assert: assert:
that: that:
- '"Installing ''parent_dep.parent_collection:1.0.0'' to" in install_req.stdout' - '"Installing ''parent_dep.parent_collection:1.0.0'' to" in install_req.stdout'
@ -760,18 +760,18 @@
state: directory state: directory
path: '{{ galaxy_dir }}/ansible_collections/unrelated_namespace/collection_without_metadata/plugins' path: '{{ galaxy_dir }}/ansible_collections/unrelated_namespace/collection_without_metadata/plugins'
- name: install a collection to the same installation directory - {{ test_name }} - name: install a collection to the same installation directory - {{ test_id }}
command: ansible-galaxy collection install namespace1.name1 command: ansible-galaxy collection install namespace1.name1
environment: environment:
ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections'
register: install_req register: install_req
- name: assert installed collections with ansible-galaxy install - {{ test_name }} - name: assert installed collections with ansible-galaxy install - {{ test_id }}
assert: assert:
that: that:
- '"Installing ''namespace1.name1:1.0.9'' to" in install_req.stdout' - '"Installing ''namespace1.name1:1.0.9'' to" in install_req.stdout'
- name: remove test collection install directory - {{ test_name }} - name: remove test collection install directory - {{ test_id }}
file: file:
path: '{{ galaxy_dir }}/ansible_collections' path: '{{ galaxy_dir }}/ansible_collections'
state: absent state: absent
@ -964,10 +964,10 @@
path: '{{ galaxy_dir }}/ansible_collections/namespace1' path: '{{ galaxy_dir }}/ansible_collections/namespace1'
state: absent state: absent
- name: download collections with pre-release dep - {{ test_name }} - 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' 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_name }} - name: install collection with concrete pre-release dep - {{ test_id }}
command: ansible-galaxy collection install -r '{{ galaxy_dir }}/scratch/requirements.yml' command: ansible-galaxy collection install -r '{{ galaxy_dir }}/scratch/requirements.yml'
args: args:
chdir: '{{ galaxy_dir }}/scratch' chdir: '{{ galaxy_dir }}/scratch'
@ -975,7 +975,7 @@
ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATHS: '{{ galaxy_dir }}/ansible_collections'
register: install_concrete_pre register: install_concrete_pre
- name: get result of install collections with concrete pre-release dep - {{ test_name }} - name: get result of install collections with concrete pre-release dep - {{ test_id }}
slurp: slurp:
path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/MANIFEST.json' path: '{{ galaxy_dir }}/ansible_collections/{{ collection }}/MANIFEST.json'
register: install_concrete_pre_actual register: install_concrete_pre_actual
@ -985,7 +985,7 @@
- namespace1/name1 - namespace1/name1
- dep_with_beta/parent - dep_with_beta/parent
- name: assert install collections with ansible-galaxy install - {{ test_name }} - name: assert install collections with ansible-galaxy install - {{ test_id }}
assert: assert:
that: that:
- '"Installing ''namespace1.name1:1.1.0-beta.1'' to" in install_concrete_pre.stdout' - '"Installing ''namespace1.name1:1.1.0-beta.1'' to" in install_concrete_pre.stdout'
@ -993,7 +993,7 @@
- (install_concrete_pre_actual.results[0].content | b64decode | from_json).collection_info.version == '1.1.0-beta.1' - (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' - (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_name }} - name: remove collection dir after round of testing - {{ test_id }}
file: file:
path: '{{ galaxy_dir }}/ansible_collections' path: '{{ galaxy_dir }}/ansible_collections'
state: absent state: absent

@ -98,6 +98,7 @@
- name: run ansible-galaxy collection install tests for {{ test_name }} - name: run ansible-galaxy collection install tests for {{ test_name }}
include_tasks: install.yml include_tasks: install.yml
vars: vars:
test_id: '{{ item.name }}'
test_name: '{{ item.name }}' test_name: '{{ item.name }}'
test_server: '{{ item.server }}' test_server: '{{ item.server }}'
vX: '{{ "v3/" if item.v3|default(false) else "v2/" }}' vX: '{{ "v3/" if item.v3|default(false) else "v2/" }}'
@ -117,6 +118,16 @@
server: '{{ pulp_server }}published/api/' server: '{{ pulp_server }}published/api/'
v3: true v3: true
- name: test installing and downloading collections with the range of supported resolvelib versions
include_tasks: supported_resolvelib.yml
args:
apply:
environment:
ANSIBLE_CONFIG: '{{ galaxy_dir }}/ansible.cfg'
loop: '{{ supported_resolvelib_versions }}'
loop_control:
loop_var: resolvelib_version
- name: publish collection with a dep on another server - name: publish collection with a dep on another server
setup_collections: setup_collections:
server: secondary server: secondary

@ -0,0 +1,44 @@
- vars:
venv_cmd: "{{ ansible_python_interpreter ~ ' -m venv' }}"
venv_dest: "{{ galaxy_dir }}/test_venv_{{ resolvelib_version }}"
block:
- name: install another version of resolvelib that is supported by ansible-galaxy
pip:
name: resolvelib
version: "{{ resolvelib_version }}"
state: present
virtualenv_command: "{{ venv_cmd }}"
virtualenv: "{{ venv_dest }}"
virtualenv_site_packages: True
- include_tasks: fail_fast_resolvelib.yml
args:
apply:
environment:
PATH: "{{ venv_dest }}/bin:{{ ansible_env.PATH }}"
ANSIBLE_CONFIG: '{{ galaxy_dir }}/ansible.cfg'
- include_tasks: install.yml
vars:
test_name: pulp_v3
test_id: '{{ test_name }} (resolvelib {{ resolvelib_version }})'
test_server: '{{ pulp_server }}published/api/'
vX: "v3/"
requires_auth: false
args:
apply:
environment:
PATH: "{{ venv_dest }}/bin:{{ ansible_env.PATH }}"
ANSIBLE_CONFIG: '{{ galaxy_dir }}/ansible.cfg'
- include_tasks: download.yml
args:
apply:
environment:
PATH: "{{ venv_dest }}/bin:{{ ansible_env.PATH }}"
ANSIBLE_CONFIG: '{{ galaxy_dir }}/ansible.cfg'
always:
- name: remove test venv
file:
path: "{{ venv_dest }}"
state: absent

@ -27,10 +27,12 @@
- assert: - assert:
that: that:
- resolvelib_version_error is failed - resolvelib_version_error is failed
- compat_error in resolvelib_version_error.stderr or import_error in resolvelib_version_error.stderr - resolvelib_version_error.stderr | regex_search(error)
vars: vars:
error: "({{ import_error }}|{{ compat_error }})"
import_error: "Failed to import resolvelib" import_error: "Failed to import resolvelib"
compat_error: "ansible-galaxy requires resolvelib<0.6.0,>=0.5.3" compat_error: "ansible-galaxy requires resolvelib<{{major_minor_patch}},>={{major_minor_patch}}"
major_minor_patch: "[0-9]\\d*\\.[0-9]\\d*\\.[0-9]\\d*"
always: always:
- name: cleanup venv and install directory - name: cleanup venv and install directory

@ -2,10 +2,15 @@ galaxy_verbosity: "{{ '' if not ansible_verbosity else '-' ~ ('v' * ansible_verb
gpg_homedir: "{{ galaxy_dir }}/gpg" gpg_homedir: "{{ galaxy_dir }}/gpg"
supported_resolvelib_versions:
- "0.5.3" # Oldest supported
- "0.6.0"
- "0.7.0"
- "0.8.0"
unsupported_resolvelib_versions: unsupported_resolvelib_versions:
- "0.2.0" # Fails on import - "0.2.0" # Fails on import
- "0.5.1" - "0.5.1"
- "0.6.0" # Fails on dependency resolution
pulp_repositories: pulp_repositories:
- published - published

@ -10,4 +10,6 @@ packaging
# NOTE: resolvelib 0.x version bumps should be considered major/breaking # NOTE: resolvelib 0.x version bumps should be considered major/breaking
# NOTE: and we should update the upper cap with care, at least until 1.0 # NOTE: and we should update the upper cap with care, at least until 1.0
# NOTE: Ref: https://github.com/sarugaku/resolvelib/issues/69 # NOTE: Ref: https://github.com/sarugaku/resolvelib/issues/69
resolvelib >= 0.5.3, < 0.6.0 # dependency resolver used by ansible-galaxy # NOTE: When updating the upper bound, also update the latest version used
# NOTE: in the ansible-galaxy-collection test suite.
resolvelib >= 0.5.3, < 0.9.0 # dependency resolver used by ansible-galaxy

@ -1,6 +1,6 @@
jinja2 jinja2
pyyaml pyyaml
resolvelib < 0.6.0 resolvelib < 0.9.0
sphinx == 4.2.0 sphinx == 4.2.0
sphinx-notfound-page sphinx-notfound-page
sphinx-ansible-theme sphinx-ansible-theme

@ -1,7 +1,7 @@
docutils < 0.18 # match version required by sphinx in the docs-build sanity test docutils < 0.18 # match version required by sphinx in the docs-build sanity test
jinja2 jinja2
pyyaml # ansible-core requirement pyyaml # ansible-core requirement
resolvelib < 0.6.0 resolvelib < 0.9.0
rstcheck rstcheck
straight.plugin straight.plugin
antsibull-changelog antsibull-changelog

Loading…
Cancel
Save