diff --git a/plugins/module_utils/_api/utils/utils.py b/plugins/module_utils/_api/utils/utils.py index 8e4cb47e..30a2bf5a 100644 --- a/plugins/module_utils/_api/utils/utils.py +++ b/plugins/module_utils/_api/utils/utils.py @@ -240,9 +240,23 @@ def convert_service_networks( def parse_repository_tag(repo_name: str) -> tuple[str, str | None]: + # Check for digest (@ separator) first parts = repo_name.rsplit("@", 1) if len(parts) == 2: - return tuple(parts) # type: ignore + # We have a digest, but there might also be a tag before it + repo_and_tag = parts[0] + digest = parts[1] + + # Check if there's a tag in the part before the digest + tag_parts = repo_and_tag.rsplit(":", 1) + if len(tag_parts) == 2 and "/" not in tag_parts[1]: + # We have both tag and digest: return repo and "tag@digest" + return tag_parts[0], f"{tag_parts[1]}@{digest}" + else: + # Only digest, no tag: return repo and digest + return repo_and_tag, digest + + # No digest, check for tag only parts = repo_name.rsplit(":", 1) if len(parts) == 2 and "/" not in parts[1]: return tuple(parts) # type: ignore diff --git a/tests/unit/plugins/module_utils/_api/utils/test_utils.py b/tests/unit/plugins/module_utils/_api/utils/test_utils.py index 5c91196b..5070b7b0 100644 --- a/tests/unit/plugins/module_utils/_api/utils/test_utils.py +++ b/tests/unit/plugins/module_utils/_api/utils/test_utils.py @@ -359,6 +359,24 @@ class ParseRepositoryTagTest(unittest.TestCase): f"sha256:{self.sha}", ) + def test_index_image_tag_and_sha(self) -> None: + assert parse_repository_tag(f"root:tag@sha256:{self.sha}") == ( + "root", + f"tag@sha256:{self.sha}", + ) + + def test_index_user_image_tag_and_sha(self) -> None: + assert parse_repository_tag(f"user/repo:tag@sha256:{self.sha}") == ( + "user/repo", + f"tag@sha256:{self.sha}", + ) + + def test_private_reg_image_tag_and_sha(self) -> None: + assert parse_repository_tag(f"url:5000/repo:tag@sha256:{self.sha}") == ( + "url:5000/repo", + f"tag@sha256:{self.sha}", + ) + class ParseDeviceTest(unittest.TestCase): def test_dict(self) -> None: