diff --git a/changelogs/fragments/galaxy-use-import-task-url.yml b/changelogs/fragments/galaxy-use-import-task-url.yml new file mode 100644 index 00000000000..f557e67e8ce --- /dev/null +++ b/changelogs/fragments/galaxy-use-import-task-url.yml @@ -0,0 +1,2 @@ +bugfixes: +- ansible-galaxy - Use the provided import task url, instead of parsing to get the task id and reconstructing the URL diff --git a/lib/ansible/galaxy/api.py b/lib/ansible/galaxy/api.py index 0a737c46ffb..60689f44670 100644 --- a/lib/ansible/galaxy/api.py +++ b/lib/ansible/galaxy/api.py @@ -689,10 +689,10 @@ class GalaxyAPI: error_context_msg='Error when publishing collection to %s (%s)' % (self.name, self.api_server)) - return resp['task'] + return urljoin(self.api_server, resp['task']) @g_connect(['v2', 'v3']) - def wait_import_task(self, task_id, timeout=0): + def wait_import_task(self, task_url, timeout=0): """ Waits until the import process on the Galaxy server has completed or the timeout is reached. @@ -703,22 +703,14 @@ class GalaxyAPI: state = 'waiting' data = None - # Construct the appropriate URL per version - if 'v3' in self.available_api_versions: - full_url = _urljoin(self.api_server, self.available_api_versions['v3'], - 'imports/collections', task_id, '/') - else: - full_url = _urljoin(self.api_server, self.available_api_versions['v2'], - 'collection-imports', task_id, '/') - - display.display("Waiting until Galaxy import task %s has completed" % full_url) + display.display("Waiting until Galaxy import task %s has completed" % task_url) start = time.time() wait = C.GALAXY_COLLECTION_IMPORT_POLL_INTERVAL while timeout == 0 or (time.time() - start) < timeout: try: - data = self._call_galaxy(full_url, method='GET', auth_required=True, - error_context_msg='Error when getting import task results at %s' % full_url) + data = self._call_galaxy(task_url, method='GET', auth_required=True, + error_context_msg='Error when getting import task results at %s' % task_url) except GalaxyError as e: if e.http_code != 404: raise @@ -740,7 +732,7 @@ class GalaxyAPI: wait = min(30, wait * C.GALAXY_COLLECTION_IMPORT_POLL_FACTOR) if state == 'waiting': raise AnsibleError("Timeout while waiting for the Galaxy import process to finish, check progress at '%s'" - % to_native(full_url)) + % to_native(task_url)) for message in data.get('messages', []): level = message['level'] @@ -754,7 +746,7 @@ class GalaxyAPI: if state == 'failed': code = to_native(data['error'].get('code', 'UNKNOWN')) description = to_native( - data['error'].get('description', "Unknown error, see %s for more details" % full_url)) + data['error'].get('description', "Unknown error, see %s for more details" % task_url)) raise AnsibleError("Galaxy import process failed: %s (Code: %s)" % (description, code)) @g_connect(['v2', 'v3']) diff --git a/lib/ansible/galaxy/collection/__init__.py b/lib/ansible/galaxy/collection/__init__.py index 3bc0f27ee57..38737468dcd 100644 --- a/lib/ansible/galaxy/collection/__init__.py +++ b/lib/ansible/galaxy/collection/__init__.py @@ -623,24 +623,11 @@ def publish_collection(collection_path, api, wait, timeout): import_uri = api.publish_collection(collection_path) if wait: - # Galaxy returns a url fragment which differs between v2 and v3. The second to last entry is - # always the task_id, though. - # v2: {"task": "https://galaxy-dev.ansible.com/api/v2/collection-imports/35573/"} - # v3: {"task": "/api/automation-hub/v3/imports/collections/838d1308-a8f4-402c-95cb-7823f3806cd8/"} - task_id = None - for path_segment in reversed(import_uri.split('/')): - if path_segment: - task_id = path_segment - break - - if not task_id: - raise AnsibleError("Publishing the collection did not return valid task info. Cannot wait for task status. Returned task info: '%s'" % import_uri) - with _display_progress( "Collection has been published to the Galaxy server " "{api.name!s} {api.api_server!s}".format(api=api), ): - api.wait_import_task(task_id, timeout) + api.wait_import_task(import_uri, timeout) display.display("Collection has been successfully published and imported to the Galaxy server %s %s" % (api.name, api.api_server)) else: diff --git a/test/units/galaxy/test_api.py b/test/units/galaxy/test_api.py index 22d83e43b3c..58985f1bb0e 100644 --- a/test/units/galaxy/test_api.py +++ b/test/units/galaxy/test_api.py @@ -451,15 +451,13 @@ def test_publish_failure(api_version, collection_url, response, expected, collec api.publish_collection(collection_artifact) -@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, import_uri, full_import_uri', [ +@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, full_import_uri', [ ('https://galaxy.server.com/api', 'v2', 'Token', GalaxyToken('my token'), - '1234', 'https://galaxy.server.com/api/v2/collection-imports/1234/'), ('https://galaxy.server.com/api/automation-hub/', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'), - '1234', 'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'), ]) -def test_wait_import_task(server_url, api_version, token_type, token_ins, import_uri, full_import_uri, monkeypatch): +def test_wait_import_task(server_url, api_version, token_type, token_ins, full_import_uri, monkeypatch): api = get_test_galaxy_api(server_url, api_version, token_ins=token_ins) mock_token_get = MagicMock() @@ -473,7 +471,7 @@ def test_wait_import_task(server_url, api_version, token_type, token_ins, import mock_display = MagicMock() monkeypatch.setattr(Display, 'display', mock_display) - api.wait_import_task(import_uri) + api.wait_import_task(full_import_uri) assert mock_open.call_count == 1 assert mock_open.mock_calls[0][1][0] == full_import_uri @@ -483,15 +481,13 @@ def test_wait_import_task(server_url, api_version, token_type, token_ins, import assert mock_display.mock_calls[0][1][0] == 'Waiting until Galaxy import task %s has completed' % full_import_uri -@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, import_uri, full_import_uri', [ +@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, full_import_uri', [ ('https://galaxy.server.com/api/', 'v2', 'Token', GalaxyToken('my token'), - '1234', 'https://galaxy.server.com/api/v2/collection-imports/1234/'), ('https://galaxy.server.com/api/automation-hub', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'), - '1234', 'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'), ]) -def test_wait_import_task_multiple_requests(server_url, api_version, token_type, token_ins, import_uri, full_import_uri, monkeypatch): +def test_wait_import_task_multiple_requests(server_url, api_version, token_type, token_ins, full_import_uri, monkeypatch): api = get_test_galaxy_api(server_url, api_version, token_ins=token_ins) mock_token_get = MagicMock() @@ -513,7 +509,7 @@ def test_wait_import_task_multiple_requests(server_url, api_version, token_type, monkeypatch.setattr(time, 'sleep', MagicMock()) - api.wait_import_task(import_uri) + api.wait_import_task(full_import_uri) assert mock_open.call_count == 2 assert mock_open.mock_calls[0][1][0] == full_import_uri @@ -529,15 +525,13 @@ def test_wait_import_task_multiple_requests(server_url, api_version, token_type, 'Galaxy import process has a status of test, wait 2 seconds before trying again' -@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, import_uri, full_import_uri,', [ +@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, full_import_uri,', [ ('https://galaxy.server.com/api/', 'v2', 'Token', GalaxyToken('my token'), - '1234', 'https://galaxy.server.com/api/v2/collection-imports/1234/'), ('https://galaxy.server.com/api/automation-hub/', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'), - '1234', 'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'), ]) -def test_wait_import_task_with_failure(server_url, api_version, token_type, token_ins, import_uri, full_import_uri, monkeypatch): +def test_wait_import_task_with_failure(server_url, api_version, token_type, token_ins, full_import_uri, monkeypatch): api = get_test_galaxy_api(server_url, api_version, token_ins=token_ins) mock_token_get = MagicMock() @@ -586,7 +580,7 @@ def test_wait_import_task_with_failure(server_url, api_version, token_type, toke expected = to_native(u'Galaxy import process failed: Becäuse I said so! (Code: GW001)') with pytest.raises(AnsibleError, match=re.escape(expected)): - api.wait_import_task(import_uri) + api.wait_import_task(full_import_uri) assert mock_open.call_count == 1 assert mock_open.mock_calls[0][1][0] == full_import_uri @@ -605,15 +599,13 @@ def test_wait_import_task_with_failure(server_url, api_version, token_type, toke assert mock_err.mock_calls[0][1][0] == u'Galaxy import error message: Somé error' -@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, import_uri, full_import_uri', [ +@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, full_import_uri', [ ('https://galaxy.server.com/api/', 'v2', 'Token', GalaxyToken('my_token'), - '1234', 'https://galaxy.server.com/api/v2/collection-imports/1234/'), ('https://galaxy.server.com/api/automation-hub/', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'), - '1234', 'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'), ]) -def test_wait_import_task_with_failure_no_error(server_url, api_version, token_type, token_ins, import_uri, full_import_uri, monkeypatch): +def test_wait_import_task_with_failure_no_error(server_url, api_version, token_type, token_ins, full_import_uri, monkeypatch): api = get_test_galaxy_api(server_url, api_version, token_ins=token_ins) mock_token_get = MagicMock() @@ -658,7 +650,7 @@ def test_wait_import_task_with_failure_no_error(server_url, api_version, token_t expected = 'Galaxy import process failed: Unknown error, see %s for more details \\(Code: UNKNOWN\\)' % full_import_uri with pytest.raises(AnsibleError, match=expected): - api.wait_import_task(import_uri) + api.wait_import_task(full_import_uri) assert mock_open.call_count == 1 assert mock_open.mock_calls[0][1][0] == full_import_uri @@ -677,15 +669,13 @@ def test_wait_import_task_with_failure_no_error(server_url, api_version, token_t assert mock_err.mock_calls[0][1][0] == u'Galaxy import error message: Somé error' -@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, import_uri, full_import_uri', [ +@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, full_import_uri', [ ('https://galaxy.server.com/api', 'v2', 'Token', GalaxyToken('my token'), - '1234', 'https://galaxy.server.com/api/v2/collection-imports/1234/'), ('https://galaxy.server.com/api/automation-hub', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'), - '1234', 'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'), ]) -def test_wait_import_task_timeout(server_url, api_version, token_type, token_ins, import_uri, full_import_uri, monkeypatch): +def test_wait_import_task_timeout(server_url, api_version, token_type, token_ins, full_import_uri, monkeypatch): api = get_test_galaxy_api(server_url, api_version, token_ins=token_ins) mock_token_get = MagicMock() @@ -709,7 +699,7 @@ def test_wait_import_task_timeout(server_url, api_version, token_type, token_ins expected = "Timeout while waiting for the Galaxy import process to finish, check progress at '%s'" % full_import_uri with pytest.raises(AnsibleError, match=expected): - api.wait_import_task(import_uri, 1) + api.wait_import_task(full_import_uri, 1) assert mock_open.call_count > 1 assert mock_open.mock_calls[0][1][0] == full_import_uri diff --git a/test/units/galaxy/test_collection.py b/test/units/galaxy/test_collection.py index 0c00c1884ba..7115a1da44f 100644 --- a/test/units/galaxy/test_collection.py +++ b/test/units/galaxy/test_collection.py @@ -884,7 +884,7 @@ def test_publish_with_wait(galaxy_server, collection_artifact, monkeypatch): assert mock_publish.mock_calls[0][1][0] == artifact_path assert mock_wait.call_count == 1 - assert mock_wait.mock_calls[0][1][0] == '1234' + assert mock_wait.mock_calls[0][1][0] == fake_import_uri assert mock_display.mock_calls[0][1][0] == "Collection has been published to the Galaxy server test_server %s" \ % galaxy_server.api_server