diff --git a/changelogs/fragments/galaxy-install-no-colon.yml b/changelogs/fragments/galaxy-install-no-colon.yml new file mode 100644 index 00000000000..b84ee706c2f --- /dev/null +++ b/changelogs/fragments/galaxy-install-no-colon.yml @@ -0,0 +1,3 @@ +minor_changes: +- ansible-galaxy - Add ability to specify collection versions on the CLI without the need for a colon. + Such as ``namespace.name==1.2.3`` vs ``namespace.name:1.2.3``. diff --git a/lib/ansible/galaxy/dependency_resolution/dataclasses.py b/lib/ansible/galaxy/dependency_resolution/dataclasses.py index 16fd6318f86..ac1edc77356 100644 --- a/lib/ansible/galaxy/dependency_resolution/dataclasses.py +++ b/lib/ansible/galaxy/dependency_resolution/dataclasses.py @@ -29,6 +29,7 @@ if t.TYPE_CHECKING: from ansible.errors import AnsibleError from ansible.galaxy.api import GalaxyAPI +from ansible.galaxy.collection import HAS_PACKAGING, PkgReq from ansible.module_utils._text import to_bytes, to_native, to_text from ansible.module_utils.common.arg_spec import ArgumentSpecValidator from ansible.utils.collection_loader import AnsibleCollectionRef @@ -268,13 +269,25 @@ class _ComputedReqKindsMixin: @classmethod def from_string(cls, collection_input, artifacts_manager, supplemental_signatures): req = {} - if _is_concrete_artifact_pointer(collection_input): - # Arg is a file path or URL to a collection + if _is_concrete_artifact_pointer(collection_input) or AnsibleCollectionRef.is_valid_collection_name(collection_input): + # Arg is a file path or URL to a collection, or just a collection req['name'] = collection_input - else: + elif ':' in collection_input: req['name'], _sep, req['version'] = collection_input.partition(':') if not req['version']: del req['version'] + else: + if not HAS_PACKAGING: + raise AnsibleError("Failed to import packaging, check that a supported version is installed") + try: + pkg_req = PkgReq(collection_input) + except Exception as e: + # packaging doesn't know what this is, let it fly, better errors happen in from_requirement_dict + req['name'] = collection_input + else: + req['name'] = pkg_req.name + if pkg_req.specifier: + req['version'] = to_text(pkg_req.specifier) req['signatures'] = supplemental_signatures return cls.from_requirement_dict(req, artifacts_manager) diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/upgrade.yml b/test/integration/targets/ansible-galaxy-collection/tasks/upgrade.yml index 893ea8033b5..debd70bc8ef 100644 --- a/test/integration/targets/ansible-galaxy-collection/tasks/upgrade.yml +++ b/test/integration/targets/ansible-galaxy-collection/tasks/upgrade.yml @@ -142,7 +142,7 @@ - directory - name: install a collection - command: ansible-galaxy collection install namespace1.name1:0.0.1 {{ galaxy_verbosity }} + command: ansible-galaxy collection install namespace1.name1==0.0.1 {{ galaxy_verbosity }} register: result failed_when: - '"namespace1.name1:0.0.1 was installed successfully" not in result.stdout_lines'