galaxy: handle missing 'results' key in cached Galaxy API responses. (#85972)

* galaxy: handle missing 'results' key in cached Galaxy API responses.

* galaxy: clarified AnsibleError message for missing cache results.

* Modified AnsibleError message and added a regression test.

* Fixed formatting issue in test/units/galaxy/test_api.py

* Added a changelog entry.

* Modified changelog.
pull/85939/head
Jason K Hall 1 month ago committed by GitHub
parent d6051b18dd
commit 192948434c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,6 @@
---
bugfixes:
- galaxy - previously, some corrupted cache files could cause Ansible Galaxy to fail
with a traceback. This has been corrected to display a clear error message explaining
how to resolve the problem.
(https://github.com/ansible/ansible/issues/85918)

@ -363,7 +363,15 @@ class GalaxyAPI:
res['results'].append(result)
else:
res = path_cache['results']
try:
res = path_cache['results']
except KeyError as cache_miss_error:
raise AnsibleError(
f"Missing expected 'results' in ansible-galaxy cache: {path_cache!r}. "
"This may indicate cache corruption (for example, from concurrent ansible-galaxy runs) "
"or a bug in how the cache was generated. "
"Try running with --clear-response-cache or --no-cache to work around the issue."
) from cache_miss_error
return res

@ -1265,3 +1265,37 @@ def test_clear_cache(cache_dir):
def test_cache_id(url, expected):
actual = galaxy_api.get_cache_id(url)
assert actual == expected
def test_cache_missing_results_raises_descriptive_error(mocker):
api = GalaxyAPI(None, "test", "https://galaxy.ansible.com/api/")
mock_cache_entry = {
'expires': '2023-01-02T12:00:00Z',
'paginated': False
}
api._cache = {'galaxy.ansible.com': {'/api/v1/roles/': mock_cache_entry}}
mocker.patch('ansible.galaxy.api.urlparse')
mocker.patch('ansible.galaxy.api.parse_qs', return_value={})
mocker.patch('ansible.galaxy.api.get_cache_id',
return_value='galaxy.ansible.com')
mock_datetime = mocker.patch('ansible.galaxy.api.datetime')
mock_comparison = mocker.Mock()
mock_comparison.__bool__ = mocker.Mock(return_value=True)
mock_now = mocker.Mock()
mock_expires = mocker.Mock()
mock_now.__lt__ = mocker.Mock(return_value=True)
mock_datetime.datetime.now.return_value = mock_now
mock_datetime.datetime.strptime.return_value = mock_expires
with pytest.raises(AnsibleError, match="Missing expected 'results' in ansible-galaxy cache"):
api._call_galaxy(
url='https://galaxy.ansible.com/api/v1/roles/',
cache=True,
cache_key='/api/v1/roles/'
)

Loading…
Cancel
Save