| ... | ... |
@@ -549,7 +549,7 @@ class GalaxyCLI(CLI): |
| 549 | 549 |
**galaxy_options |
| 550 | 550 |
)) |
| 551 | 551 |
|
| 552 |
- context.CLIARGS['func']() |
|
| 552 |
+ return context.CLIARGS['func']() |
|
| 553 | 553 |
|
| 554 | 554 |
@property |
| 555 | 555 |
def api(self): |
| ... | ... |
@@ -1091,13 +1091,16 @@ class GalaxyCLI(CLI): |
| 1091 | 1091 |
|
| 1092 | 1092 |
resolved_paths = [validate_collection_path(GalaxyCLI._resolve_path(path)) for path in search_paths] |
| 1093 | 1093 |
|
| 1094 |
- verify_collections( |
|
| 1094 |
+ results = verify_collections( |
|
| 1095 | 1095 |
requirements, resolved_paths, |
| 1096 | 1096 |
self.api_servers, ignore_errors, |
| 1097 | 1097 |
local_verify_only=local_verify_only, |
| 1098 | 1098 |
artifacts_manager=artifacts_manager, |
| 1099 | 1099 |
) |
| 1100 | 1100 |
|
| 1101 |
+ if any(result for result in results if not result.success): |
|
| 1102 |
+ return 1 |
|
| 1103 |
+ |
|
| 1101 | 1104 |
return 0 |
| 1102 | 1105 |
|
| 1103 | 1106 |
@with_collection_artifacts_manager |
| ... | ... |
@@ -131,16 +131,26 @@ MANIFEST_FILENAME = 'MANIFEST.json' |
| 131 | 131 |
ModifiedContent = namedtuple('ModifiedContent', ['filename', 'expected', 'installed'])
|
| 132 | 132 |
|
| 133 | 133 |
|
| 134 |
+# FUTURE: expose actual verify result details for a collection on this object, maybe reimplement as dataclass on py3.8+ |
|
| 135 |
+class CollectionVerifyResult: |
|
| 136 |
+ def __init__(self, collection_name): # type: (str) -> None |
|
| 137 |
+ self.collection_name = collection_name # type: str |
|
| 138 |
+ self.success = True # type: bool |
|
| 139 |
+ |
|
| 140 |
+ |
|
| 134 | 141 |
def verify_local_collection( |
| 135 | 142 |
local_collection, remote_collection, |
| 136 | 143 |
artifacts_manager, |
| 137 |
-): # type: (Candidate, Optional[Candidate], ConcreteArtifactsManager) -> None |
|
| 144 |
+): # type: (Candidate, Optional[Candidate], ConcreteArtifactsManager) -> CollectionVerifyResult |
|
| 138 | 145 |
"""Verify integrity of the locally installed collection. |
| 139 | 146 |
|
| 140 | 147 |
:param local_collection: Collection being checked. |
| 141 | 148 |
:param remote_collection: Upstream collection (optional, if None, only verify local artifact) |
| 142 | 149 |
:param artifacts_manager: Artifacts manager. |
| 150 |
+ :return: a collection verify result object. |
|
| 143 | 151 |
""" |
| 152 |
+ result = CollectionVerifyResult(local_collection.fqcn) |
|
| 153 |
+ |
|
| 144 | 154 |
b_collection_path = to_bytes( |
| 145 | 155 |
local_collection.src, errors='surrogate_or_strict', |
| 146 | 156 |
) |
| ... | ... |
@@ -188,7 +198,8 @@ def verify_local_collection( |
| 188 | 188 |
) |
| 189 | 189 |
) |
| 190 | 190 |
display.display(err) |
| 191 |
- return |
|
| 191 |
+ result.success = False |
|
| 192 |
+ return result |
|
| 192 | 193 |
|
| 193 | 194 |
# Verify the downloaded manifest hash matches the installed copy before verifying the file manifest |
| 194 | 195 |
manifest_hash = get_hash_from_validation_source(MANIFEST_FILENAME) |
| ... | ... |
@@ -214,6 +225,7 @@ def verify_local_collection( |
| 214 | 214 |
_verify_file_hash(b_collection_path, manifest_data['name'], expected_hash, modified_content) |
| 215 | 215 |
|
| 216 | 216 |
if modified_content: |
| 217 |
+ result.success = False |
|
| 217 | 218 |
display.display( |
| 218 | 219 |
'Collection {fqcn!s} contains modified content '
|
| 219 | 220 |
'in the following files:'. |
| ... | ... |
@@ -229,6 +241,8 @@ def verify_local_collection( |
| 229 | 229 |
format(coll=local_collection, what=what), |
| 230 | 230 |
) |
| 231 | 231 |
|
| 232 |
+ return result |
|
| 233 |
+ |
|
| 232 | 234 |
|
| 233 | 235 |
def build_collection(u_collection_path, u_output_path, force): |
| 234 | 236 |
# type: (Text, Text, bool) -> Text |
| ... | ... |
@@ -574,7 +588,7 @@ def verify_collections( |
| 574 | 574 |
ignore_errors, # type: bool |
| 575 | 575 |
local_verify_only, # type: bool |
| 576 | 576 |
artifacts_manager, # type: ConcreteArtifactsManager |
| 577 |
-): # type: (...) -> None |
|
| 577 |
+): # type: (...) -> List[CollectionVerifyResult] |
|
| 578 | 578 |
r"""Verify the integrity of locally installed collections. |
| 579 | 579 |
|
| 580 | 580 |
:param collections: The collections to check. |
| ... | ... |
@@ -583,7 +597,10 @@ def verify_collections( |
| 583 | 583 |
:param ignore_errors: Whether to ignore any errors when verifying the collection. |
| 584 | 584 |
:param local_verify_only: When True, skip downloads and only verify local manifests. |
| 585 | 585 |
:param artifacts_manager: Artifacts manager. |
| 586 |
+ :return: list of CollectionVerifyResult objects describing the results of each collection verification |
|
| 586 | 587 |
""" |
| 588 |
+ results = [] # type: List[CollectionVerifyResult] |
|
| 589 |
+ |
|
| 587 | 590 |
api_proxy = MultiGalaxyAPIProxy(apis, artifacts_manager) |
| 588 | 591 |
|
| 589 | 592 |
with _display_progress(): |
| ... | ... |
@@ -656,11 +673,13 @@ def verify_collections( |
| 656 | 656 |
) |
| 657 | 657 |
raise |
| 658 | 658 |
|
| 659 |
- verify_local_collection( |
|
| 659 |
+ result = verify_local_collection( |
|
| 660 | 660 |
local_collection, remote_collection, |
| 661 | 661 |
artifacts_manager, |
| 662 | 662 |
) |
| 663 | 663 |
|
| 664 |
+ results.append(result) |
|
| 665 |
+ |
|
| 664 | 666 |
except AnsibleError as err: |
| 665 | 667 |
if ignore_errors: |
| 666 | 668 |
display.warning( |
| ... | ... |
@@ -672,6 +691,8 @@ def verify_collections( |
| 672 | 672 |
else: |
| 673 | 673 |
raise |
| 674 | 674 |
|
| 675 |
+ return results |
|
| 676 |
+ |
|
| 675 | 677 |
|
| 676 | 678 |
@contextmanager |
| 677 | 679 |
def _tempdir(): |
| ... | ... |
@@ -16,11 +16,11 @@ |
| 16 | 16 |
- name: test verifying a tarfile |
| 17 | 17 |
command: ansible-galaxy collection verify {{ galaxy_dir }}/ansible_test-verify-1.0.0.tar.gz
|
| 18 | 18 |
register: verify |
| 19 |
- ignore_errors: yes |
|
| 19 |
+ failed_when: verify.rc == 0 |
|
| 20 | 20 |
|
| 21 | 21 |
- assert: |
| 22 | 22 |
that: |
| 23 |
- - verify.failed |
|
| 23 |
+ - verify.rc != 0 |
|
| 24 | 24 |
- >- |
| 25 | 25 |
"ERROR! 'file' type is not supported. The format namespace.name is expected." in verify.stderr |
| 26 | 26 |
|
| ... | ... |
@@ -48,11 +48,11 @@ |
| 48 | 48 |
- name: verify a collection that doesn't appear to be installed |
| 49 | 49 |
command: ansible-galaxy collection verify ansible_test.verify:1.0.0 |
| 50 | 50 |
register: verify |
| 51 |
- ignore_errors: true |
|
| 51 |
+ failed_when: verify.rc == 0 |
|
| 52 | 52 |
|
| 53 | 53 |
- assert: |
| 54 | 54 |
that: |
| 55 |
- - verify.failed |
|
| 55 |
+ - verify.rc != 0 |
|
| 56 | 56 |
- "'Collection ansible_test.verify is not installed in any of the collection paths.' in verify.stderr" |
| 57 | 57 |
|
| 58 | 58 |
- name: create a modules directory |
| ... | ... |
@@ -86,9 +86,11 @@ |
| 86 | 86 |
environment: |
| 87 | 87 |
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}'
|
| 88 | 88 |
register: verify |
| 89 |
+ failed_when: verify.rc == 0 |
|
| 89 | 90 |
|
| 90 | 91 |
- assert: |
| 91 | 92 |
that: |
| 93 |
+ - verify.rc != 0 |
|
| 92 | 94 |
- '"ansible_test.verify has the version ''1.0.0'' but is being compared to ''2.0.0''" in verify.stdout' |
| 93 | 95 |
|
| 94 | 96 |
- name: install the new version from the server |
| ... | ... |
@@ -147,9 +149,11 @@ |
| 147 | 147 |
register: verify |
| 148 | 148 |
environment: |
| 149 | 149 |
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}'
|
| 150 |
+ failed_when: verify.rc == 0 |
|
| 150 | 151 |
|
| 151 | 152 |
- assert: |
| 152 | 153 |
that: |
| 154 |
+ - verify.rc != 0 |
|
| 153 | 155 |
- "'Collection ansible_test.verify contains modified content in the following files:\n plugins/modules/test_module.py' in verify.stdout" |
| 154 | 156 |
|
| 155 | 157 |
- name: modify the FILES.json to match the new checksum |
| ... | ... |
@@ -165,9 +169,11 @@ |
| 165 | 165 |
register: verify |
| 166 | 166 |
environment: |
| 167 | 167 |
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}'
|
| 168 |
+ failed_when: verify.rc == 0 |
|
| 168 | 169 |
|
| 169 | 170 |
- assert: |
| 170 | 171 |
that: |
| 172 |
+ - verify.rc != 0 |
|
| 171 | 173 |
- "'Collection ansible_test.verify contains modified content in the following files:\n FILES.json' in verify.stdout" |
| 172 | 174 |
|
| 173 | 175 |
- name: get the checksum of the FILES.json |
| ... | ... |
@@ -187,9 +193,11 @@ |
| 187 | 187 |
register: verify |
| 188 | 188 |
environment: |
| 189 | 189 |
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}'
|
| 190 |
+ failed_when: verify.rc == 0 |
|
| 190 | 191 |
|
| 191 | 192 |
- assert: |
| 192 | 193 |
that: |
| 194 |
+ - verify.rc != 0 |
|
| 193 | 195 |
- "'Collection ansible_test.verify contains modified content in the following files:\n MANIFEST.json' in verify.stdout" |
| 194 | 196 |
|
| 195 | 197 |
- name: remove the artifact metadata to test verifying a collection without it |
| ... | ... |
@@ -215,11 +223,11 @@ |
| 215 | 215 |
register: verify |
| 216 | 216 |
environment: |
| 217 | 217 |
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}'
|
| 218 |
- ignore_errors: yes |
|
| 218 |
+ failed_when: verify.rc == 0 |
|
| 219 | 219 |
|
| 220 | 220 |
- assert: |
| 221 | 221 |
that: |
| 222 |
- - verify.failed |
|
| 222 |
+ - verify.rc != 0 |
|
| 223 | 223 |
- "'Collection ansible_test.verify does not have a MANIFEST.json' in verify.stderr" |
| 224 | 224 |
|
| 225 | 225 |
- name: update the collection version to something not present on the server |
| ... | ... |
@@ -260,9 +268,10 @@ |
| 260 | 260 |
register: verify |
| 261 | 261 |
environment: |
| 262 | 262 |
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}'
|
| 263 |
- ignore_errors: yes |
|
| 263 |
+ failed_when: verify.rc == 0 |
|
| 264 | 264 |
|
| 265 | 265 |
- assert: |
| 266 | 266 |
that: |
| 267 |
+ - verify.rc != 0 |
|
| 267 | 268 |
- "'Collection ansible_test.verify contains modified content in the following files:' in verify.stdout" |
| 268 | 269 |
- "'plugins/modules/test_module.py' in verify.stdout" |