ansible-galaxy - remove deprecated v2 API (#85830)

* ansible-galaxy - remove deprecated v2 API

Update unit tests exercising the v2 Galaxy API

Remove v2 API integration tests

* Remove internal test configuration for servers which support API v2 and v3

* Update and simplify verify tests by using the configured server list
pull/85867/head
Sloane Hertel 3 months ago committed by GitHub
parent e30da51731
commit ced362a50d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,2 @@
removed_features:
- ansible-galaxy - removed the v2 Galaxy server API. Galaxy servers hosting collections must support v3.

@ -654,23 +654,10 @@ class GalaxyCLI(CLI):
client_secret = server_options.pop('client_secret') client_secret = server_options.pop('client_secret')
token_val = server_options['token'] or NoTokenSentinel token_val = server_options['token'] or NoTokenSentinel
username = server_options['username'] username = server_options['username']
api_version = server_options.pop('api_version')
if server_options['validate_certs'] is None: if server_options['validate_certs'] is None:
server_options['validate_certs'] = context.CLIARGS['resolved_validate_certs'] server_options['validate_certs'] = context.CLIARGS['resolved_validate_certs']
validate_certs = server_options['validate_certs'] validate_certs = server_options['validate_certs']
# This allows a user to explicitly force use of an API version when
# multiple versions are supported. This was added for testing
# against pulp_ansible and I'm not sure it has a practical purpose
# outside of this use case. As such, this option is not documented
# as of now
if api_version:
display.warning(
f'The specified "api_version" configuration for the galaxy server "{server_key}" is '
'not a public configuration, and may be removed at any time without warning.'
)
server_options['available_api_versions'] = {'v%s' % api_version: '/v%s' % api_version}
# default case if no auth info is provided. # default case if no auth info is provided.
server_options['token'] = None server_options['token'] = None
@ -697,12 +684,6 @@ class GalaxyCLI(CLI):
)) ))
cmd_server = context.CLIARGS['api_server'] cmd_server = context.CLIARGS['api_server']
if context.CLIARGS['api_version']:
api_version = context.CLIARGS['api_version']
display.warning(
'The --api-version is not a public argument, and may be removed at any time without warning.'
)
galaxy_options['available_api_versions'] = {'v%s' % api_version: '/v%s' % api_version}
cmd_token = GalaxyToken(token=context.CLIARGS['api_key']) cmd_token = GalaxyToken(token=context.CLIARGS['api_key'])

@ -36,7 +36,6 @@ GALAXY_SERVER_DEF = [
('password', False, 'str'), ('password', False, 'str'),
('token', False, 'str'), ('token', False, 'str'),
('auth_url', False, 'str'), ('auth_url', False, 'str'),
('api_version', False, 'int'),
('validate_certs', False, 'bool'), ('validate_certs', False, 'bool'),
('client_id', False, 'str'), ('client_id', False, 'str'),
('client_secret', False, 'str'), ('client_secret', False, 'str'),
@ -45,7 +44,6 @@ GALAXY_SERVER_DEF = [
# config definition fields # config definition fields
GALAXY_SERVER_ADDITIONAL = { GALAXY_SERVER_ADDITIONAL = {
'api_version': {'default': None, 'choices': [2, 3]},
'validate_certs': {'cli': [{'name': 'validate_certs'}]}, 'validate_certs': {'cli': [{'name': 'validate_certs'}]},
'timeout': {'cli': [{'name': 'timeout'}]}, 'timeout': {'cli': [{'name': 'timeout'}]},
'token': {'default': None}, 'token': {'default': None},

@ -113,13 +113,7 @@ def g_connect(versions):
# url + '/api/' appended. # url + '/api/' appended.
self.api_server = n_url self.api_server = n_url
# Default to only supporting v1, if only v1 is returned we also assume that v2 is available even though self._available_api_versions = available_versions = data['available_versions']
# it isn't returned in the available_versions dict.
available_versions = data.get('available_versions', {u'v1': u'v1/'})
if list(available_versions.keys()) == [u'v1']:
available_versions[u'v2'] = u'v2/'
self._available_api_versions = available_versions
display.vvvv("Found API version '%s' with Galaxy server %s (%s)" display.vvvv("Found API version '%s' with Galaxy server %s (%s)"
% (', '.join(available_versions.keys()), self.name, self.api_server)) % (', '.join(available_versions.keys()), self.name, self.api_server))
@ -131,15 +125,6 @@ def g_connect(versions):
% (method.__name__, ", ".join(versions), ", ".join(available_versions), % (method.__name__, ", ".join(versions), ", ".join(available_versions),
self.name, self.api_server)) self.name, self.api_server))
# Warn only when we know we are talking to a collections API
if common_versions == {'v2'}:
display.deprecated(
'The v2 Ansible Galaxy API is deprecated and no longer supported. '
'Ensure that you have configured the ansible-galaxy CLI to utilize an '
'updated and supported version of Ansible Galaxy.',
version='2.20',
)
return method(self, *args, **kwargs) return method(self, *args, **kwargs)
return wrapped return wrapped
return decorator return decorator
@ -213,11 +198,7 @@ class GalaxyError(AnsibleError):
err_info = {} err_info = {}
url_split = self.url.split('/') url_split = self.url.split('/')
if 'v2' in url_split: if 'v3' in url_split:
galaxy_msg = err_info.get('message', http_error.reason)
code = err_info.get('code', 'Unknown')
full_error_msg = u"%s (HTTP Code: %d, Message: %s Code: %s)" % (message, self.http_code, galaxy_msg, code)
elif 'v3' in url_split:
errors = err_info.get('errors', []) errors = err_info.get('errors', [])
if not errors: if not errors:
errors = [{}] # Defaults are set below, we just need to make sure 1 error is present. errors = [{}] # Defaults are set below, we just need to make sure 1 error is present.
@ -339,7 +320,7 @@ class GalaxyAPI:
return self._priority > other_galaxy_api._priority return self._priority > other_galaxy_api._priority
@property # type: ignore[misc] # https://github.com/python/mypy/issues/1362 @property # type: ignore[misc] # https://github.com/python/mypy/issues/1362
@g_connect(['v1', 'v2', 'v3']) @g_connect(['v1', 'v3'])
def available_api_versions(self): def available_api_versions(self):
# Calling g_connect will populate self._available_api_versions # Calling g_connect will populate self._available_api_versions
return self._available_api_versions return self._available_api_versions
@ -644,7 +625,7 @@ class GalaxyAPI:
# Collection APIs # # Collection APIs #
@g_connect(['v2', 'v3']) @g_connect(['v3'])
def publish_collection(self, collection_path): def publish_collection(self, collection_path):
""" """
Publishes a collection to a Galaxy server and returns the import task URI. Publishes a collection to a Galaxy server and returns the import task URI.
@ -679,18 +660,14 @@ class GalaxyAPI:
'Content-length': len(b_form_data), 'Content-length': len(b_form_data),
} }
if 'v3' in self.available_api_versions: n_url = _urljoin(self.api_server, self.available_api_versions['v3'], 'artifacts', 'collections') + '/'
n_url = _urljoin(self.api_server, self.available_api_versions['v3'], 'artifacts', 'collections') + '/'
else:
n_url = _urljoin(self.api_server, self.available_api_versions['v2'], 'collections') + '/'
resp = self._call_galaxy(n_url, args=b_form_data, headers=headers, method='POST', auth_required=True, resp = self._call_galaxy(n_url, args=b_form_data, headers=headers, method='POST', auth_required=True,
error_context_msg='Error when publishing collection to %s (%s)' error_context_msg='Error when publishing collection to %s (%s)'
% (self.name, self.api_server)) % (self.name, self.api_server))
return urljoin(self.api_server, resp['task']) return urljoin(self.api_server, resp['task'])
@g_connect(['v2', 'v3']) @g_connect(['v3'])
def wait_import_task(self, task_url, 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. Waits until the import process on the Galaxy server has completed or the timeout is reached.
@ -748,7 +725,7 @@ class GalaxyAPI:
data['error'].get('description', "Unknown error, see %s for more details" % task_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)) raise AnsibleError("Galaxy import process failed: %s (Code: %s)" % (description, code))
@g_connect(['v2', 'v3']) @g_connect(['v3'])
def get_collection_metadata(self, namespace, name): def get_collection_metadata(self, namespace, name):
""" """
Gets the collection information from the Galaxy server about a specific Collection. Gets the collection information from the Galaxy server about a specific Collection.
@ -757,18 +734,11 @@ class GalaxyAPI:
:param name: The collection name. :param name: The collection name.
return: CollectionMetadata about the collection. return: CollectionMetadata about the collection.
""" """
if 'v3' in self.available_api_versions: api_path = self.available_api_versions['v3']
api_path = self.available_api_versions['v3'] field_map = [
field_map = [ ('created_str', 'created_at'),
('created_str', 'created_at'), ('modified_str', 'updated_at'),
('modified_str', 'updated_at'), ]
]
else:
api_path = self.available_api_versions['v2']
field_map = [
('created_str', 'created'),
('modified_str', 'modified'),
]
info_url = _urljoin(self.api_server, api_path, 'collections', namespace, name, '/') info_url = _urljoin(self.api_server, api_path, 'collections', namespace, name, '/')
error_context_msg = 'Error when getting the collection info for %s.%s from %s (%s)' \ error_context_msg = 'Error when getting the collection info for %s.%s from %s (%s)' \
@ -781,7 +751,7 @@ class GalaxyAPI:
return CollectionMetadata(namespace, name, **metadata) return CollectionMetadata(namespace, name, **metadata)
@g_connect(['v2', 'v3']) @g_connect(['v3'])
def get_collection_version_metadata(self, namespace, name, version): def get_collection_version_metadata(self, namespace, name, version):
""" """
Gets the collection information from the Galaxy server about a specific Collection version. Gets the collection information from the Galaxy server about a specific Collection version.
@ -791,7 +761,7 @@ class GalaxyAPI:
:param version: Version of the collection to get the information for. :param version: Version of the collection to get the information for.
:return: CollectionVersionMetadata about the collection at the version requested. :return: CollectionVersionMetadata about the collection at the version requested.
""" """
api_path = self.available_api_versions.get('v3', self.available_api_versions.get('v2')) api_path = self.available_api_versions['v3']
url_paths = [self.api_server, api_path, 'collections', namespace, name, 'versions', version, '/'] url_paths = [self.api_server, api_path, 'collections', namespace, name, 'versions', version, '/']
n_collection_url = _urljoin(*url_paths) n_collection_url = _urljoin(*url_paths)
@ -815,7 +785,7 @@ class GalaxyAPI:
download_url, data['artifact']['sha256'], download_url, data['artifact']['sha256'],
data['metadata']['dependencies'], data['href'], signatures) data['metadata']['dependencies'], data['href'], signatures)
@g_connect(['v2', 'v3']) @g_connect(['v3'])
def get_collection_versions(self, namespace, name): def get_collection_versions(self, namespace, name):
""" """
Gets a list of available versions for a collection on a Galaxy server. Gets a list of available versions for a collection on a Galaxy server.
@ -824,17 +794,10 @@ class GalaxyAPI:
:param name: The collection name. :param name: The collection name.
:return: A list of versions that are available. :return: A list of versions that are available.
""" """
relative_link = False api_path = self.available_api_versions['v3']
if 'v3' in self.available_api_versions: pagination_path = ['links', 'next']
api_path = self.available_api_versions['v3']
pagination_path = ['links', 'next']
relative_link = True # AH pagination results are relative an not an absolute URI.
else:
api_path = self.available_api_versions['v2']
pagination_path = ['next']
page_size_name = 'limit' if 'v3' in self.available_api_versions else 'page_size' versions_url = _urljoin(self.api_server, api_path, 'collections', namespace, name, 'versions', '/?limit=%d' % COLLECTION_PAGE_SIZE)
versions_url = _urljoin(self.api_server, api_path, 'collections', namespace, name, 'versions', '/?%s=%d' % (page_size_name, COLLECTION_PAGE_SIZE))
versions_url_info = urlparse(versions_url) versions_url_info = urlparse(versions_url)
cache_key = versions_url_info.path cache_key = versions_url_info.path
@ -889,11 +852,10 @@ class GalaxyAPI:
if not next_link: if not next_link:
break break
elif relative_link: next_link_info = urlparse(next_link)
next_link_info = urlparse(next_link) if not next_link_info.scheme and not next_link_info.path.startswith('/'):
if not next_link_info.scheme and not next_link_info.path.startswith('/'): raise AnsibleError(f'Invalid non absolute pagination link: {next_link}')
raise AnsibleError(f'Invalid non absolute pagination link: {next_link}') next_link = urljoin(self.api_server, next_link)
next_link = urljoin(self.api_server, next_link)
data = self._call_galaxy(to_native(next_link, errors='surrogate_or_strict'), data = self._call_galaxy(to_native(next_link, errors='surrogate_or_strict'),
error_context_msg=error_context_msg, cache=True, cache_key=cache_key) error_context_msg=error_context_msg, cache=True, cache_key=cache_key)
@ -901,7 +863,7 @@ class GalaxyAPI:
return versions return versions
@g_connect(['v2', 'v3']) @g_connect(['v3'])
def get_collection_signatures(self, namespace, name, version): def get_collection_signatures(self, namespace, name, version):
""" """
Gets the collection signatures from the Galaxy server about a specific Collection version. Gets the collection signatures from the Galaxy server about a specific Collection version.
@ -911,7 +873,7 @@ class GalaxyAPI:
:param version: Version of the collection to get the information for. :param version: Version of the collection to get the information for.
:return: A list of signature strings. :return: A list of signature strings.
""" """
api_path = self.available_api_versions.get('v3', self.available_api_versions.get('v2')) api_path = self.available_api_versions['v3']
url_paths = [self.api_server, api_path, 'collections', namespace, name, 'versions', version, '/'] url_paths = [self.api_server, api_path, 'collections', namespace, name, 'versions', version, '/']
n_collection_url = _urljoin(*url_paths) n_collection_url = _urljoin(*url_paths)

@ -73,9 +73,6 @@
password: password:
value: my_pass value: my_pass
origin: role_path ~ "/files/galaxy_server.ini" origin: role_path ~ "/files/galaxy_server.ini"
api_version:
value: None
origin: default
release_galaxy: release_galaxy:
test_galaxy: test_galaxy:
my_galaxy_ng: my_galaxy_ng:
@ -120,7 +117,6 @@
auth_url: auth_url:
username: username:
password: password:
api_version:
timeout: timeout:
origin: '{{ role_path ~ "/files/galaxy_server.ini" }}' origin: '{{ role_path ~ "/files/galaxy_server.ini" }}'
gs_keys: '{{ gs.keys()|list|sort }}' gs_keys: '{{ gs.keys()|list|sort }}'

@ -337,27 +337,6 @@
environment: environment:
ANSIBLE_GALAXY_SERVER_LIST: bogus ANSIBLE_GALAXY_SERVER_LIST: bogus
# pulp_v2 doesn't require auth
- when: v2|default(false)
block:
- name: install a collection with an empty server list - {{ test_id }}
command: ansible-galaxy collection install namespace5.name -s '{{ test_server }}' --api-version 2 {{ galaxy_verbosity }}
register: install_empty_server_list
environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
ANSIBLE_GALAXY_SERVER_LIST: ''
- name: get result of a collection with an empty server list - {{ test_id }}
slurp:
path: '{{ galaxy_dir }}/ansible_collections/namespace5/name/MANIFEST.json'
register: install_empty_server_list_actual
- name: assert install a collection with an empty server list - {{ test_id }}
assert:
that:
- '"Installing ''namespace5.name:1.0.0'' to" in install_empty_server_list.stdout'
- (install_empty_server_list_actual.content | b64decode | from_json).collection_info.version == '1.0.0'
- name: create test requirements file with both roles and collections - {{ test_id }} - name: create test requirements file with both roles and collections - {{ test_id }}
copy: copy:
content: | content: |
@ -764,40 +743,38 @@
- namespace8 - namespace8
- namespace9 - namespace9
- when: not v2|default(false) - name: install cache.cache at the current latest version
block: command: ansible-galaxy collection install cache.cache -s '{{ test_name }}' -vvv
- name: install cache.cache at the current latest version environment:
command: ansible-galaxy collection install cache.cache -s '{{ test_name }}' -vvv ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
- set_fact: - set_fact:
cache_version_build: '{{ (cache_version_build | int) + 1 }}' cache_version_build: '{{ (cache_version_build | int) + 1 }}'
- name: publish update for cache.cache test - name: publish update for cache.cache test
setup_collections: setup_collections:
server: galaxy_ng server: galaxy_ng
collections: collections:
- namespace: cache - namespace: cache
name: cache name: cache
version: 1.0.{{ cache_version_build }} version: 1.0.{{ cache_version_build }}
- name: make sure the cache version list is ignored on a collection version change - {{ test_id }} - name: make sure the cache version list is ignored on a collection version change - {{ test_id }}
command: ansible-galaxy collection install cache.cache -s '{{ test_name }}' --force -vvv command: ansible-galaxy collection install cache.cache -s '{{ test_name }}' --force -vvv
register: install_cached_update register: install_cached_update
environment: environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/ansible_collections'
- name: get result of cache version list is ignored on a collection version change - {{ test_id }} - name: get result of cache version list is ignored on a collection version change - {{ test_id }}
slurp: slurp:
path: '{{ galaxy_dir }}/ansible_collections/cache/cache/MANIFEST.json' path: '{{ galaxy_dir }}/ansible_collections/cache/cache/MANIFEST.json'
register: install_cached_update_actual register: install_cached_update_actual
- name: assert cache version list is ignored on a collection version change - {{ test_id }} - name: assert cache version list is ignored on a collection version change - {{ test_id }}
assert: assert:
that: that:
- '"Installing ''cache.cache:1.0." ~ cache_version_build ~ "'' to" in install_cached_update.stdout' - '"Installing ''cache.cache:1.0." ~ cache_version_build ~ "'' to" in install_cached_update.stdout'
- (install_cached_update_actual.content | b64decode | from_json).collection_info.version == '1.0.' ~ cache_version_build - (install_cached_update_actual.content | b64decode | from_json).collection_info.version == '1.0.' ~ cache_version_build
- name: install collection with symlink - {{ test_id }} - name: install collection with symlink - {{ test_id }}
command: ansible-galaxy collection install symlink.symlink -s '{{ test_name }}' {{ galaxy_verbosity }} command: ansible-galaxy collection install symlink.symlink -s '{{ test_name }}' {{ galaxy_verbosity }}

@ -74,13 +74,8 @@
test_server: '{{ item.server }}' test_server: '{{ item.server }}'
test_api_server: '{{ item.api_server|default(item.server) }}' test_api_server: '{{ item.api_server|default(item.server) }}'
loop: loop:
- name: pulp_v2
api_server: '{{ galaxy_ng_server }}'
server: '{{ pulp_server }}primary/api/'
v2: true
- name: galaxy_ng - name: galaxy_ng
server: '{{ galaxy_ng_server }}' server: '{{ galaxy_ng_server }}'
v3: true
- include_tasks: setup_gpg.yml - include_tasks: setup_gpg.yml
@ -109,7 +104,6 @@
test_server: '{{ item.server }}' test_server: '{{ item.server }}'
test_api_server: '{{ item.api_server|default(item.server) }}' test_api_server: '{{ item.api_server|default(item.server) }}'
requires_auth: '{{ item.requires_auth|default(false) }}' requires_auth: '{{ item.requires_auth|default(false) }}'
v2: '{{ item.v2|default(false) }}'
args: args:
apply: apply:
environment: environment:
@ -117,12 +111,7 @@
loop: loop:
- name: galaxy_ng - name: galaxy_ng
server: '{{ galaxy_ng_server }}' server: '{{ galaxy_ng_server }}'
v3: true
requires_auth: true requires_auth: true
- name: pulp_v2
server: '{{ pulp_server }}primary/api/'
api_server: '{{ galaxy_ng_server }}'
v2: true
- name: test installing and downloading collections with the range of supported resolvelib versions - name: test installing and downloading collections with the range of supported resolvelib versions
include_tasks: supported_resolvelib.yml include_tasks: supported_resolvelib.yml
@ -184,7 +173,7 @@
- >- - >-
"'secondary.name:1.0.0' obtained from server secondary" "'secondary.name:1.0.0' obtained from server secondary"
in install_cross_dep.stdout in install_cross_dep.stdout
# pulp_v2 is highest in the list so it will find it there first # galaxy_ng is highest in the list so it will find it there first
- >- - >-
"'parent_dep.parent_collection:1.0.0' obtained from server galaxy_ng" "'parent_dep.parent_collection:1.0.0' obtained from server galaxy_ng"
in install_cross_dep.stdout in install_cross_dep.stdout
@ -214,9 +203,9 @@
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}'
ANSIBLE_CONFIG: '{{ galaxy_dir }}/ansible.cfg' ANSIBLE_CONFIG: '{{ galaxy_dir }}/ansible.cfg'
vars: vars:
test_api_fallback: 'galaxy_ng' test_api_fallback: 'secondary'
test_api_fallback_versions: 'v3, pulp-v3, v1' test_api_fallback_versions: 'v3, pulp-v3, v1'
test_name: 'pulp_v2' test_name: 'galaxy_ng'
- name: run ansible-galaxy collection list tests - name: run ansible-galaxy collection list tests
include_tasks: list.yml include_tasks: list.yml

@ -13,8 +13,8 @@
args: args:
chdir: '{{ galaxy_dir }}' chdir: '{{ galaxy_dir }}'
- name: publish collection - {{ test_name }} - name: publish to fallback server {{ test_api_fallback }}
command: ansible-galaxy collection publish ansible_test-verify-1.0.0.tar.gz -s {{ test_name }} {{ galaxy_verbosity }} command: ansible-galaxy collection publish ansible_test-verify-1.0.0.tar.gz -s {{ test_api_fallback }} {{ galaxy_verbosity }}
args: args:
chdir: '{{ galaxy_dir }}' chdir: '{{ galaxy_dir }}'
@ -28,25 +28,23 @@
- verify.rc != 0 - verify.rc != 0
- verify.stderr is contains "'file' type is not supported. The format namespace.name is expected." - verify.stderr is contains "'file' type is not supported. The format namespace.name is expected."
- name: install the collection from the server - name: install the collection from the secondary server
command: ansible-galaxy collection install ansible_test.verify:1.0.0 -s {{ test_api_fallback }} {{ galaxy_verbosity }} command: ansible-galaxy collection install ansible_test.verify:1.0.0 {{ galaxy_verbosity }}
# This command is hardcoded with -vvvv purposefully to evaluate extra verbosity messages # This command is hardcoded with -vvvv purposefully to evaluate extra verbosity messages
- name: verify the collection against the first valid server - name: verify the collection against the first valid server
command: ansible-galaxy collection verify ansible_test.verify:1.0.0 -vvvv {{ galaxy_verbosity }} command: ansible-galaxy collection verify ansible_test.verify:1.0.0 -vvvv {{ galaxy_verbosity }}
register: verify register: verify
vars:
# This sets a specific precedence that the tests are expecting
ANSIBLE_GALAXY_SERVER_LIST: offline,secondary,pulp_v2,galaxy_ng
- assert: - assert:
that: that:
- verify is success - verify is success
- >- - verify.stdout is search(msg)
"Found API version '" + test_api_fallback_versions + "' with Galaxy server " + test_api_fallback in verify.stdout vars:
msg: "Found API version '{{ test_api_fallback_versions }}' with Galaxy server {{ test_api_fallback }}"
- name: verify the installed collection against the server - name: verify the installed collection against the server
command: ansible-galaxy collection verify ansible_test.verify:1.0.0 -s {{ test_name }} {{ galaxy_verbosity }} command: ansible-galaxy collection verify ansible_test.verify:1.0.0 {{ galaxy_verbosity }}
register: verify register: verify
- assert: - assert:
@ -55,10 +53,10 @@
- "'Collection ansible_test.verify contains modified content' not in verify.stdout" - "'Collection ansible_test.verify contains modified content' not in verify.stdout"
- name: verify the installed collection against the server, with unspecified version in CLI - name: verify the installed collection against the server, with unspecified version in CLI
command: ansible-galaxy collection verify ansible_test.verify -s {{ test_name }} {{ galaxy_verbosity }} command: ansible-galaxy collection verify ansible_test.verify {{ galaxy_verbosity }}
- name: verify a collection that doesn't appear to be installed - name: verify a collection that doesn't appear to be installed
command: ansible-galaxy collection verify ansible_test.verify:1.0.0 -s {{ test_name }} {{ galaxy_verbosity }} command: ansible-galaxy collection verify ansible_test.verify:1.0.0 {{ galaxy_verbosity }}
environment: environment:
ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/nonexistent_dir' ANSIBLE_COLLECTIONS_PATH: '{{ galaxy_dir }}/nonexistent_dir'
register: verify register: verify
@ -90,13 +88,13 @@
args: args:
chdir: '{{ galaxy_dir }}' chdir: '{{ galaxy_dir }}'
- name: publish the new version - name: publish to primary server {{ test_name }}
command: ansible-galaxy collection publish ansible_test-verify-2.0.0.tar.gz -s {{ test_name }} {{ galaxy_verbosity }} command: ansible-galaxy collection publish ansible_test-verify-2.0.0.tar.gz -s {{ test_name }} {{ galaxy_verbosity }}
args: args:
chdir: '{{ galaxy_dir }}' chdir: '{{ galaxy_dir }}'
- name: verify a version of a collection that isn't installed - name: verify a version of a collection that isn't installed
command: ansible-galaxy collection verify ansible_test.verify:2.0.0 -s {{ test_name }} {{ galaxy_verbosity }} command: ansible-galaxy collection verify ansible_test.verify:2.0.0 {{ galaxy_verbosity }}
register: verify register: verify
failed_when: verify.rc == 0 failed_when: verify.rc == 0
@ -106,10 +104,10 @@
- '"ansible_test.verify has the version ''1.0.0'' but is being compared to ''2.0.0''" in verify.stdout' - '"ansible_test.verify has the version ''1.0.0'' but is being compared to ''2.0.0''" in verify.stdout'
- name: install the new version from the server - name: install the new version from the server
command: ansible-galaxy collection install ansible_test.verify:2.0.0 --force -s {{ test_name }} {{ galaxy_verbosity }} command: ansible-galaxy collection install ansible_test.verify:2.0.0 --force {{ galaxy_verbosity }}
- name: verify the installed collection against the server - name: verify the installed collection against the server
command: ansible-galaxy collection verify ansible_test.verify:2.0.0 -s {{ test_name }} {{ galaxy_verbosity }} command: ansible-galaxy collection verify ansible_test.verify:2.0.0 {{ galaxy_verbosity }}
register: verify register: verify
- assert: - assert:
@ -153,7 +151,7 @@
- "updated_file.stat.checksum != file.stat.checksum" - "updated_file.stat.checksum != file.stat.checksum"
- name: test verifying checksums of the modified collection - name: test verifying checksums of the modified collection
command: ansible-galaxy collection verify ansible_test.verify:2.0.0 -s {{ test_name }} {{ galaxy_verbosity }} command: ansible-galaxy collection verify ansible_test.verify:2.0.0 {{ galaxy_verbosity }}
register: verify register: verify
failed_when: verify.rc == 0 failed_when: verify.rc == 0
@ -171,7 +169,7 @@
diff: true diff: true
- name: ensure a modified FILES.json is validated - name: ensure a modified FILES.json is validated
command: ansible-galaxy collection verify ansible_test.verify:2.0.0 -s {{ test_name }} {{ galaxy_verbosity }} command: ansible-galaxy collection verify ansible_test.verify:2.0.0 {{ galaxy_verbosity }}
register: verify register: verify
failed_when: verify.rc == 0 failed_when: verify.rc == 0
@ -193,7 +191,7 @@
line: ' "chksum_sha256": "{{ manifest_info.stat.checksum }}",' line: ' "chksum_sha256": "{{ manifest_info.stat.checksum }}",'
- name: ensure the MANIFEST.json is validated against the uncorrupted file from the server - name: ensure the MANIFEST.json is validated against the uncorrupted file from the server
command: ansible-galaxy collection verify ansible_test.verify:2.0.0 -s {{ test_name }} {{ galaxy_verbosity }} command: ansible-galaxy collection verify ansible_test.verify:2.0.0 {{ galaxy_verbosity }}
register: verify register: verify
failed_when: verify.rc == 0 failed_when: verify.rc == 0
@ -221,7 +219,7 @@
dest: '{{ galaxy_dir }}/ansible_collections/ansible_test/verify/galaxy.yml' dest: '{{ galaxy_dir }}/ansible_collections/ansible_test/verify/galaxy.yml'
- name: test we only verify collections containing a MANIFEST.json with the version on the server - name: test we only verify collections containing a MANIFEST.json with the version on the server
command: ansible-galaxy collection verify ansible_test.verify:2.0.0 -s {{ test_name }} {{ galaxy_verbosity }} command: ansible-galaxy collection verify ansible_test.verify:2.0.0 {{ galaxy_verbosity }}
register: verify register: verify
failed_when: verify.rc == 0 failed_when: verify.rc == 0

@ -1,17 +1,11 @@
[galaxy] [galaxy]
# Ensures subsequent unstable reruns don't use the cached information causing another failure # Ensures subsequent unstable reruns don't use the cached information causing another failure
cache_dir={{ remote_tmp_dir }}/galaxy_cache cache_dir={{ remote_tmp_dir }}/galaxy_cache
server_list=offline,galaxy_ng,secondary,pulp_v2 server_list=offline,galaxy_ng,secondary
[galaxy_server.offline] [galaxy_server.offline]
url={{ offline_server }} url={{ offline_server }}
[galaxy_server.pulp_v2]
url={{ pulp_server }}primary/api/
username={{ pulp_user }}
password={{ pulp_password }}
api_version=2
[galaxy_server.galaxy_ng] [galaxy_server.galaxy_ng]
url={{ galaxy_ng_server }}content/primary/ url={{ galaxy_ng_server }}content/primary/
token={{ galaxy_ng_token.json.token }} token={{ galaxy_ng_token.json.token }}

@ -229,4 +229,3 @@ test/integration/targets/ansible-test-sanity-pylint/deprecated_thing.py pylint:a
test/integration/targets/ansible-test-sanity-pylint/deprecated_thing.py pylint:ansible-deprecated-date-not-permitted # required to verify plugin against core test/integration/targets/ansible-test-sanity-pylint/deprecated_thing.py pylint:ansible-deprecated-date-not-permitted # required to verify plugin against core
test/integration/targets/ansible-test-sanity-pylint/deprecated_thing.py pylint:ansible-deprecated-unnecessary-collection-name # required to verify plugin against core test/integration/targets/ansible-test-sanity-pylint/deprecated_thing.py pylint:ansible-deprecated-unnecessary-collection-name # required to verify plugin against core
test/integration/targets/ansible-test-sanity-pylint/deprecated_thing.py pylint:ansible-deprecated-collection-name-not-permitted # required to verify plugin against core test/integration/targets/ansible-test-sanity-pylint/deprecated_thing.py pylint:ansible-deprecated-collection-name-not-permitted # required to verify plugin against core
lib/ansible/galaxy/api.py pylint:ansible-deprecated-version # TODO: 2.20

@ -126,37 +126,32 @@ def get_v3_collection_versions(namespace='namespace', name='collection'):
def get_collection_versions(namespace='namespace', name='collection'): def get_collection_versions(namespace='namespace', name='collection'):
base_url = 'https://galaxy.server.com/api/v2/collections/{0}/{1}/'.format(namespace, name) base_url = f'/api/v3/plugin/ansible/content/published/collections/index/{namespace}/{name}/'
versions_url = base_url + 'versions/' versions_url = f'{base_url}versions/'
# Response for collection info # Response for collection info
responses = [ responses = [
{ {
"id": 1000,
"href": base_url, "href": base_url,
"name": name, "name": name,
"namespace": { "namespace": namespace,
"id": 30000, "highest_version": {
"href": "https://galaxy.ansible.com/api/v1/namespaces/30000/", "href": f"{versions_url}1.0.5",
"name": namespace,
},
"versions_url": versions_url,
"latest_version": {
"version": "1.0.5", "version": "1.0.5",
"href": versions_url + "1.0.5/"
}, },
"versions_url": versions_url,
"deprecated": False, "deprecated": False,
"created": "2021-02-09T16:55:42.749915-05:00", "created_at": "2021-02-09T16:55:42.749915-05:00",
"modified": "2021-02-09T16:55:42.749915-05:00", "updated_at": "2021-02-09T16:55:42.749915-05:00",
} }
] ]
# Paginated responses for versions # Paginated responses for versions
page_versions = (('1.0.0', '1.0.1',), ('1.0.2', '1.0.3',), ('1.0.4', '1.0.5'),) page_versions = (('1.0.0', '1.0.1',), ('1.0.2', '1.0.3',), ('1.0.4', '1.0.5'),)
last_page = None prev_page = None
for page in range(1, len(page_versions) + 1): for page in range(1, len(page_versions) + 1):
if page < len(page_versions): if page < len(page_versions):
next_page = versions_url + '?page={0}'.format(page + 1) next_page = f'{versions_url}?limit=2&offset={page + 1}'
else: else:
next_page = None next_page = None
@ -168,13 +163,19 @@ def get_collection_versions(namespace='namespace', name='collection'):
responses.append( responses.append(
{ {
'count': 6, 'meta': {
'next': next_page, 'count': 6,
'previous': last_page, },
'results': version_results, 'links': {
'first': f'{versions_url}?limit=2&offset=0',
'next': next_page,
'previous': prev_page,
'last': f'{versions_url}?limit=2&offset={len(page_versions)}',
},
'data': version_results,
} }
) )
last_page = page prev_page = page
return responses return responses
@ -265,9 +266,8 @@ def test_initialise_galaxy(monkeypatch):
api = GalaxyAPI(None, "test", "https://galaxy.ansible.com/api/") api = GalaxyAPI(None, "test", "https://galaxy.ansible.com/api/")
actual = api.authenticate("github_token") actual = api.authenticate("github_token")
assert len(api.available_api_versions) == 2 assert len(api.available_api_versions) == 1
assert api.available_api_versions['v1'] == u'v1/' assert api.available_api_versions['v1'] == u'v1/'
assert api.available_api_versions['v2'] == u'v2/'
assert actual == {u'token': u'my token'} assert actual == {u'token': u'my token'}
assert mock_open.call_count == 2 assert mock_open.call_count == 2
assert mock_open.mock_calls[0][1][0] == 'https://galaxy.ansible.com/api/' assert mock_open.mock_calls[0][1][0] == 'https://galaxy.ansible.com/api/'
@ -288,9 +288,8 @@ def test_initialise_galaxy_with_auth(monkeypatch):
api = GalaxyAPI(None, "test", "https://galaxy.ansible.com/api/", token=GalaxyToken(token='my_token')) api = GalaxyAPI(None, "test", "https://galaxy.ansible.com/api/", token=GalaxyToken(token='my_token'))
actual = api.authenticate("github_token") actual = api.authenticate("github_token")
assert len(api.available_api_versions) == 2 assert len(api.available_api_versions) == 1
assert api.available_api_versions['v1'] == u'v1/' assert api.available_api_versions['v1'] == u'v1/'
assert api.available_api_versions['v2'] == u'v2/'
assert actual == {u'token': u'my token'} assert actual == {u'token': u'my token'}
assert mock_open.call_count == 2 assert mock_open.call_count == 2
assert mock_open.mock_calls[0][1][0] == 'https://galaxy.ansible.com/api/' assert mock_open.mock_calls[0][1][0] == 'https://galaxy.ansible.com/api/'
@ -303,7 +302,7 @@ def test_initialise_galaxy_with_auth(monkeypatch):
def test_initialise_automation_hub(monkeypatch): def test_initialise_automation_hub(monkeypatch):
mock_open = MagicMock() mock_open = MagicMock()
mock_open.side_effect = [ mock_open.side_effect = [
StringIO(u'{"available_versions":{"v2": "v2/", "v3":"v3/"}}'), StringIO(u'{"available_versions":{"v3":"v3/"}}'),
] ]
monkeypatch.setattr(galaxy_api, 'open_url', mock_open) monkeypatch.setattr(galaxy_api, 'open_url', mock_open)
token = KeycloakToken(auth_url='https://api.test/') token = KeycloakToken(auth_url='https://api.test/')
@ -313,8 +312,7 @@ def test_initialise_automation_hub(monkeypatch):
api = GalaxyAPI(None, "test", "https://galaxy.ansible.com/api/", token=token) api = GalaxyAPI(None, "test", "https://galaxy.ansible.com/api/", token=token)
assert len(api.available_api_versions) == 2 assert len(api.available_api_versions) == 1
assert api.available_api_versions['v2'] == u'v2/'
assert api.available_api_versions['v3'] == u'v3/' assert api.available_api_versions['v3'] == u'v3/'
assert mock_open.mock_calls[0][1][0] == 'https://galaxy.ansible.com/api/' assert mock_open.mock_calls[0][1][0] == 'https://galaxy.ansible.com/api/'
@ -341,7 +339,7 @@ def test_initialise_unknown(monkeypatch):
def test_get_available_api_versions(monkeypatch): def test_get_available_api_versions(monkeypatch):
mock_open = MagicMock() mock_open = MagicMock()
mock_open.side_effect = [ mock_open.side_effect = [
StringIO(u'{"available_versions":{"v1":"v1/","v2":"v2/"}}'), StringIO(u'{"available_versions":{"v1":"v1/","v3":"v3/"}}'),
] ]
monkeypatch.setattr(galaxy_api, 'open_url', mock_open) monkeypatch.setattr(galaxy_api, 'open_url', mock_open)
@ -349,7 +347,7 @@ def test_get_available_api_versions(monkeypatch):
actual = api.available_api_versions actual = api.available_api_versions
assert len(actual) == 2 assert len(actual) == 2
assert actual['v1'] == u'v1/' assert actual['v1'] == u'v1/'
assert actual['v2'] == u'v2/' assert actual['v3'] == u'v3/'
assert mock_open.call_count == 1 assert mock_open.call_count == 1
assert mock_open.mock_calls[0][1][0] == 'https://galaxy.ansible.com/api/' assert mock_open.mock_calls[0][1][0] == 'https://galaxy.ansible.com/api/'
@ -360,7 +358,7 @@ def test_publish_collection_missing_file():
fake_path = u'/fake/ÅÑŚÌβŁÈ/path' fake_path = u'/fake/ÅÑŚÌβŁÈ/path'
expected = to_native("The collection path specified '%s' does not exist." % fake_path) expected = to_native("The collection path specified '%s' does not exist." % fake_path)
api = get_test_galaxy_api("https://galaxy.ansible.com/api/", "v2") api = get_test_galaxy_api("https://galaxy.ansible.com/api/", "v3")
with pytest.raises(AnsibleError, match=expected): with pytest.raises(AnsibleError, match=expected):
api.publish_collection(fake_path) api.publish_collection(fake_path)
@ -369,7 +367,7 @@ def test_publish_collection_not_a_tarball():
expected = "The collection path specified '{0}' is not a tarball, use 'ansible-galaxy collection build' to " \ expected = "The collection path specified '{0}' is not a tarball, use 'ansible-galaxy collection build' to " \
"create a proper release artifact." "create a proper release artifact."
api = get_test_galaxy_api("https://galaxy.ansible.com/api/", "v2") api = get_test_galaxy_api("https://galaxy.ansible.com/api/", "v3")
with tempfile.NamedTemporaryFile(prefix=u'ÅÑŚÌβŁÈ') as temp_file: with tempfile.NamedTemporaryFile(prefix=u'ÅÑŚÌβŁÈ') as temp_file:
temp_file.write(b"\x00") temp_file.write(b"\x00")
temp_file.flush() temp_file.flush()
@ -378,7 +376,7 @@ def test_publish_collection_not_a_tarball():
def test_publish_collection_unsupported_version(): def test_publish_collection_unsupported_version():
expected = "Galaxy action publish_collection requires API versions 'v2, v3' but only 'v1' are available on test " \ expected = "Galaxy action publish_collection requires API versions 'v3' but only 'v1' are available on test " \
"https://galaxy.ansible.com/api/" "https://galaxy.ansible.com/api/"
api = get_test_galaxy_api("https://galaxy.ansible.com/api/", "v1") api = get_test_galaxy_api("https://galaxy.ansible.com/api/", "v1")
@ -387,7 +385,6 @@ def test_publish_collection_unsupported_version():
@pytest.mark.parametrize('api_version, collection_url', [ @pytest.mark.parametrize('api_version, collection_url', [
('v2', 'collections'),
('v3', 'artifacts/collections'), ('v3', 'artifacts/collections'),
]) ])
def test_publish_collection(api_version, collection_url, collection_artifact, monkeypatch): def test_publish_collection(api_version, collection_url, collection_artifact, monkeypatch):
@ -410,12 +407,6 @@ def test_publish_collection(api_version, collection_url, collection_artifact, mo
@pytest.mark.parametrize('api_version, collection_url, response, expected', [ @pytest.mark.parametrize('api_version, collection_url, response, expected', [
('v2', 'collections', {},
'Error when publishing collection to test (%s) (HTTP Code: 500, Message: msg Code: Unknown)'),
('v2', 'collections', {
'message': u'Galaxy error messäge',
'code': 'GWE002',
}, u'Error when publishing collection to test (%s) (HTTP Code: 500, Message: Galaxy error messäge Code: GWE002)'),
('v3', 'artifact/collections', {}, ('v3', 'artifact/collections', {},
'Error when publishing collection to test (%s) (HTTP Code: 500, Message: msg Code: Unknown)'), 'Error when publishing collection to test (%s) (HTTP Code: 500, Message: msg Code: Unknown)'),
('v3', 'artifact/collections', { ('v3', 'artifact/collections', {
@ -452,8 +443,6 @@ def test_publish_failure(api_version, collection_url, response, expected, collec
@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, 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'),
'https://galaxy.server.com/api/v2/collection-imports/1234/'),
('https://galaxy.server.com/api/automation-hub/', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'), ('https://galaxy.server.com/api/automation-hub/', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'),
'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'), 'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'),
]) ])
@ -482,8 +471,6 @@ def test_wait_import_task(server_url, api_version, token_type, token_ins, full_i
@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, 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'),
'https://galaxy.server.com/api/v2/collection-imports/1234/'),
('https://galaxy.server.com/api/automation-hub', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'), ('https://galaxy.server.com/api/automation-hub', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'),
'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'), 'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'),
]) ])
@ -526,8 +513,6 @@ def test_wait_import_task_multiple_requests(server_url, api_version, token_type,
@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, 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'),
'https://galaxy.server.com/api/v2/collection-imports/1234/'),
('https://galaxy.server.com/api/automation-hub/', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'), ('https://galaxy.server.com/api/automation-hub/', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'),
'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'), 'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'),
]) ])
@ -600,8 +585,6 @@ def test_wait_import_task_with_failure(server_url, api_version, token_type, toke
@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, 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'),
'https://galaxy.server.com/api/v2/collection-imports/1234/'),
('https://galaxy.server.com/api/automation-hub/', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'), ('https://galaxy.server.com/api/automation-hub/', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'),
'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'), 'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'),
]) ])
@ -670,8 +653,6 @@ def test_wait_import_task_with_failure_no_error(server_url, api_version, token_t
@pytest.mark.parametrize('server_url, api_version, token_type, token_ins, 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'),
'https://galaxy.server.com/api/v2/collection-imports/1234/'),
('https://galaxy.server.com/api/automation-hub', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'), ('https://galaxy.server.com/api/automation-hub', 'v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'),
'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'), 'https://galaxy.server.com/api/automation-hub/v3/imports/collections/1234/'),
]) ])
@ -725,7 +706,6 @@ def test_wait_import_task_timeout(server_url, api_version, token_type, token_ins
@pytest.mark.parametrize('api_version, token_type, version, token_ins', [ @pytest.mark.parametrize('api_version, token_type, version, token_ins', [
('v2', None, 'v2.1.13', None),
('v3', 'Bearer', 'v1.0.0', KeycloakToken(auth_url='https://api.test/api/automation-hub/')), ('v3', 'Bearer', 'v1.0.0', KeycloakToken(auth_url='https://api.test/api/automation-hub/')),
]) ])
def test_get_collection_version_metadata_no_version(api_version, token_type, version, token_ins, monkeypatch): def test_get_collection_version_metadata_no_version(api_version, token_type, version, token_ins, monkeypatch):
@ -777,11 +757,11 @@ def test_get_collection_version_metadata_no_version(api_version, token_type, ver
assert mock_open.mock_calls[0][2]['headers']['Authorization'] == '%s my token' % token_type assert mock_open.mock_calls[0][2]['headers']['Authorization'] == '%s my token' % token_type
@pytest.mark.parametrize('api_version, token_type, token_ins, version', [ @pytest.mark.parametrize('api_version, token_type, token_ins', [
('v2', None, None, '2.1.13'), ('v3', None, None),
('v3', 'Bearer', KeycloakToken(auth_url='https://api.test/api/automation-hub/'), '1.0.0'), ('v3', 'Bearer', KeycloakToken(auth_url='https://api.test/api/automation-hub/')),
]) ])
def test_get_collection_signatures_backwards_compat(api_version, token_type, token_ins, version, monkeypatch): def test_get_collection_signatures_backwards_compat(api_version, token_type, token_ins, monkeypatch):
api = get_test_galaxy_api('https://galaxy.server.com/api/', api_version, token_ins=token_ins) api = get_test_galaxy_api('https://galaxy.server.com/api/', api_version, token_ins=token_ins)
if token_ins: if token_ins:
@ -795,23 +775,23 @@ def test_get_collection_signatures_backwards_compat(api_version, token_type, tok
] ]
monkeypatch.setattr(galaxy_api, 'open_url', mock_open) monkeypatch.setattr(galaxy_api, 'open_url', mock_open)
actual = api.get_collection_signatures('namespace', 'collection', version) actual = api.get_collection_signatures('namespace', 'collection', '1.0.0')
assert actual == [] assert actual == []
assert mock_open.call_count == 1 assert mock_open.call_count == 1
assert mock_open.mock_calls[0][1][0] == '%s%s/collections/namespace/collection/versions/%s/' \ assert mock_open.mock_calls[0][1][0] == '%s%s/collections/namespace/collection/versions/1.0.0/' \
% (api.api_server, api_version, version) % (api.api_server, api_version)
# v2 calls dont need auth, so no authz header or token_type # v3 calls dont need auth, so no authz header or token_type
if token_type: if token_type:
assert mock_open.mock_calls[0][2]['headers']['Authorization'] == '%s my token' % token_type assert mock_open.mock_calls[0][2]['headers']['Authorization'] == '%s my token' % token_type
@pytest.mark.parametrize('api_version, token_type, token_ins, version', [ @pytest.mark.parametrize('api_version, token_type, token_ins', [
('v2', None, None, '2.1.13'), ('v3', None, None),
('v3', 'Bearer', KeycloakToken(auth_url='https://api.test/api/automation-hub/'), '1.0.0'), ('v3', 'Bearer', KeycloakToken(auth_url='https://api.test/api/automation-hub/')),
]) ])
def test_get_collection_signatures(api_version, token_type, token_ins, version, monkeypatch): def test_get_collection_signatures(api_version, token_type, token_ins, monkeypatch):
api = get_test_galaxy_api('https://galaxy.server.com/api/', api_version, token_ins=token_ins) api = get_test_galaxy_api('https://galaxy.server.com/api/', api_version, token_ins=token_ins)
if token_ins: if token_ins:
@ -840,7 +820,7 @@ def test_get_collection_signatures(api_version, token_type, token_ins, version,
] ]
monkeypatch.setattr(galaxy_api, 'open_url', mock_open) monkeypatch.setattr(galaxy_api, 'open_url', mock_open)
actual = api.get_collection_signatures('namespace', 'collection', version) actual = api.get_collection_signatures('namespace', 'collection', '1.0.0')
assert actual == [ assert actual == [
"-----BEGIN PGP SIGNATURE-----\nSIGNATURE1\n-----END PGP SIGNATURE-----\n", "-----BEGIN PGP SIGNATURE-----\nSIGNATURE1\n-----END PGP SIGNATURE-----\n",
@ -848,48 +828,41 @@ def test_get_collection_signatures(api_version, token_type, token_ins, version,
] ]
assert mock_open.call_count == 1 assert mock_open.call_count == 1
assert mock_open.mock_calls[0][1][0] == '%s%s/collections/namespace/collection/versions/%s/' \ assert mock_open.mock_calls[0][1][0] == '%s%s/collections/namespace/collection/versions/1.0.0/' \
% (api.api_server, api_version, version) % (api.api_server, api_version)
# v2 calls dont need auth, so no authz header or token_type # v3 calls dont need auth, so no authz header or token_type
if token_type: if token_type:
assert mock_open.mock_calls[0][2]['headers']['Authorization'] == '%s my token' % token_type assert mock_open.mock_calls[0][2]['headers']['Authorization'] == '%s my token' % token_type
@pytest.mark.parametrize('api_version, token_type, token_ins, response', [ @pytest.mark.parametrize('api_version, token_type, token_ins', [
('v2', None, None, { ('v3', None, None),
'count': 2, ('v3', 'Bearer', KeycloakToken(auth_url='https://ah.test/'))
'next': None, ])
'previous': None, def test_get_collection_versions(api_version, token_type, token_ins, monkeypatch):
'results': [ response = {
{ 'meta': {
'version': '1.0.0', 'count': 2
'href': 'https://galaxy.server.com/api/v2/collections/namespace/collection/versions/1.0.0', },
}, 'links': {
{ 'first': '/api/v3/plugin/ansible/content/published/collections/index/ns/col/versions/?limit=100&offset=0',
'version': '1.0.1', 'previous': None,
'href': 'https://galaxy.server.com/api/v2/collections/namespace/collection/versions/1.0.1', 'next': None,
}, 'last': '/api/v3/plugin/ansible/content/published/collections/index/ns/col/versions/?limit=100&offset=0'
], },
}),
# TODO: Verify this once Automation Hub is actually out
('v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'), {
'count': 2,
'next': None,
'previous': None,
'data': [ 'data': [
{ {
'version': '1.0.0', 'version': '1.0.0',
'href': 'https://galaxy.server.com/api/v2/collections/namespace/collection/versions/1.0.0', 'href': '/api/v3/plugin/ansible/content/published/collections/index/ns/col/versions/1.0.0/',
}, },
{ {
'version': '1.0.1', 'version': '1.0.1',
'href': 'https://galaxy.server.com/api/v2/collections/namespace/collection/versions/1.0.1', 'href': '/api/v3/plugin/ansible/content/pubished/collections/index/ns/col/versions/1.0.1/',
}, },
], ],
}), }
])
def test_get_collection_versions(api_version, token_type, token_ins, response, monkeypatch):
api = get_test_galaxy_api('https://galaxy.server.com/api/', api_version, token_ins=token_ins) api = get_test_galaxy_api('https://galaxy.server.com/api/', api_version, token_ins=token_ins)
if token_ins: if token_ins:
@ -906,7 +879,7 @@ def test_get_collection_versions(api_version, token_type, token_ins, response, m
actual = api.get_collection_versions('namespace', 'collection') actual = api.get_collection_versions('namespace', 'collection')
assert actual == [u'1.0.0', u'1.0.1'] assert actual == [u'1.0.0', u'1.0.1']
page_query = '?limit=100' if api_version == 'v3' else '?page_size=100' page_query = '?limit=100'
assert mock_open.call_count == 1 assert mock_open.call_count == 1
assert mock_open.mock_calls[0][1][0] == 'https://galaxy.server.com/api/%s/collections/namespace/collection/' \ assert mock_open.mock_calls[0][1][0] == 'https://galaxy.server.com/api/%s/collections/namespace/collection/' \
'versions/%s' % (api_version, page_query) 'versions/%s' % (api_version, page_query)
@ -915,53 +888,6 @@ def test_get_collection_versions(api_version, token_type, token_ins, response, m
@pytest.mark.parametrize('api_version, token_type, token_ins, responses', [ @pytest.mark.parametrize('api_version, token_type, token_ins, responses', [
('v2', None, None, [
{
'count': 6,
'next': 'https://galaxy.server.com/api/v2/collections/namespace/collection/versions/?page=2&page_size=100',
'previous': None,
'results': [ # Pay no mind, using more manageable results than page_size would indicate
{
'version': '1.0.0',
'href': 'https://galaxy.server.com/api/v2/collections/namespace/collection/versions/1.0.0',
},
{
'version': '1.0.1',
'href': 'https://galaxy.server.com/api/v2/collections/namespace/collection/versions/1.0.1',
},
],
},
{
'count': 6,
'next': 'https://galaxy.server.com/api/v2/collections/namespace/collection/versions/?page=3&page_size=100',
'previous': 'https://galaxy.server.com/api/v2/collections/namespace/collection/versions',
'results': [
{
'version': '1.0.2',
'href': 'https://galaxy.server.com/api/v2/collections/namespace/collection/versions/1.0.2',
},
{
'version': '1.0.3',
'href': 'https://galaxy.server.com/api/v2/collections/namespace/collection/versions/1.0.3',
},
],
},
{
'count': 6,
'next': None,
'previous': 'https://galaxy.server.com/api/v2/collections/namespace/collection/versions/?page=2&page_size=100',
'results': [
{
'version': '1.0.4',
'href': 'https://galaxy.server.com/api/v2/collections/namespace/collection/versions/1.0.4',
},
{
'version': '1.0.5',
'href': 'https://galaxy.server.com/api/v2/collections/namespace/collection/versions/1.0.5',
},
],
},
]),
('v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'), [ ('v3', 'Bearer', KeycloakToken(auth_url='https://api.test/'), [
{ {
'count': 6, 'count': 6,
@ -1034,14 +960,9 @@ def test_get_collection_versions_pagination(api_version, token_type, token_ins,
assert mock_open.call_count == 3 assert mock_open.call_count == 3
if api_version == 'v3': query_1 = 'limit=100'
query_1 = 'limit=100' query_2 = 'limit=100&offset=100'
query_2 = 'limit=100&offset=100' query_3 = 'limit=100&offset=200'
query_3 = 'limit=100&offset=200'
else:
query_1 = 'page_size=100'
query_2 = 'page=2&page_size=100'
query_3 = 'page=3&page_size=100'
assert mock_open.mock_calls[0][1][0] == 'https://galaxy.server.com/api/%s/collections/namespace/collection/' \ assert mock_open.mock_calls[0][1][0] == 'https://galaxy.server.com/api/%s/collections/namespace/collection/' \
'versions/?%s' % (api_version, query_1) 'versions/?%s' % (api_version, query_1)
@ -1160,7 +1081,7 @@ def test_cache_complete_pagination(cache_dir, monkeypatch):
responses = get_collection_versions() responses = get_collection_versions()
cache_file = os.path.join(cache_dir, 'api.json') cache_file = os.path.join(cache_dir, 'api.json')
api = get_test_galaxy_api('https://galaxy.server.com/api/', 'v2', no_cache=False) api = get_test_galaxy_api('https://galaxy.server.com/api/', 'v3', no_cache=False)
mock_open = MagicMock( mock_open = MagicMock(
side_effect=[ side_effect=[
@ -1177,7 +1098,7 @@ def test_cache_complete_pagination(cache_dir, monkeypatch):
final_cache = json.loads(fd.read()) final_cache = json.loads(fd.read())
cached_server = final_cache['galaxy.server.com:'] cached_server = final_cache['galaxy.server.com:']
cached_collection = cached_server['/api/v2/collections/namespace/collection/versions/'] cached_collection = cached_server['/api/v3/collections/namespace/collection/versions/']
cached_versions = [r['version'] for r in cached_collection['results']] cached_versions = [r['version'] for r in cached_collection['results']]
assert final_cache == api._cache assert final_cache == api._cache
@ -1218,14 +1139,14 @@ def test_cache_flaky_pagination(cache_dir, monkeypatch):
responses = get_collection_versions() responses = get_collection_versions()
cache_file = os.path.join(cache_dir, 'api.json') cache_file = os.path.join(cache_dir, 'api.json')
api = get_test_galaxy_api('https://galaxy.server.com/api/', 'v2', no_cache=False) api = get_test_galaxy_api('https://galaxy.server.com/api/', 'v3', no_cache=False)
# First attempt, fail midway through # First attempt, fail midway through
mock_open = MagicMock( mock_open = MagicMock(
side_effect=[ side_effect=[
StringIO(to_text(json.dumps(responses[0]))), StringIO(to_text(json.dumps(responses[0]))),
StringIO(to_text(json.dumps(responses[1]))), StringIO(to_text(json.dumps(responses[1]))),
urllib.error.HTTPError(responses[1]['next'], 500, 'Error', {}, StringIO()), urllib.error.HTTPError(responses[1]['links']['next'], 500, 'Error', {}, StringIO()),
StringIO(to_text(json.dumps(responses[3]))), StringIO(to_text(json.dumps(responses[3]))),
] ]
) )
@ -1246,13 +1167,13 @@ def test_cache_flaky_pagination(cache_dir, monkeypatch):
'version': 1, 'version': 1,
'galaxy.server.com:': { 'galaxy.server.com:': {
'modified': { 'modified': {
'namespace.collection': responses[0]['modified'] 'namespace.collection': responses[0]['updated_at']
} }
} }
} }
# Reset API # Reset API
api = get_test_galaxy_api('https://galaxy.server.com/api/', 'v2', no_cache=False) api = get_test_galaxy_api('https://galaxy.server.com/api/', 'v3', no_cache=False)
# Second attempt is successful so cache should be populated # Second attempt is successful so cache should be populated
mock_open = MagicMock( mock_open = MagicMock(
@ -1270,7 +1191,7 @@ def test_cache_flaky_pagination(cache_dir, monkeypatch):
final_cache = json.loads(fd.read()) final_cache = json.loads(fd.read())
cached_server = final_cache['galaxy.server.com:'] cached_server = final_cache['galaxy.server.com:']
cached_collection = cached_server['/api/v2/collections/namespace/collection/versions/'] cached_collection = cached_server['/api/v3/collections/namespace/collection/versions/']
cached_versions = [r['version'] for r in cached_collection['results']] cached_versions = [r['version'] for r in cached_collection['results']]
assert cached_versions == actual_versions assert cached_versions == actual_versions

@ -846,7 +846,7 @@ def test_publish_no_wait(galaxy_server, collection_artifact, monkeypatch):
monkeypatch.setattr(Display, 'display', mock_display) monkeypatch.setattr(Display, 'display', mock_display)
artifact_path, mock_open = collection_artifact artifact_path, mock_open = collection_artifact
fake_import_uri = 'https://galaxy.server.com/api/v2/import/1234' fake_import_uri = 'https://galaxy.server.com/api/v3/import/1234'
mock_publish = MagicMock() mock_publish = MagicMock()
mock_publish.return_value = fake_import_uri mock_publish.return_value = fake_import_uri
@ -869,7 +869,7 @@ def test_publish_with_wait(galaxy_server, collection_artifact, monkeypatch):
monkeypatch.setattr(Display, 'display', mock_display) monkeypatch.setattr(Display, 'display', mock_display)
artifact_path, mock_open = collection_artifact artifact_path, mock_open = collection_artifact
fake_import_uri = 'https://galaxy.server.com/api/v2/import/1234' fake_import_uri = 'https://galaxy.server.com/api/v3/import/1234'
mock_publish = MagicMock() mock_publish = MagicMock()
mock_publish.return_value = fake_import_uri mock_publish.return_value = fake_import_uri

Loading…
Cancel
Save