diff --git a/lib/ansible/cli/galaxy.py b/lib/ansible/cli/galaxy.py index 0680fab2410..ba2a1a129e6 100644 --- a/lib/ansible/cli/galaxy.py +++ b/lib/ansible/cli/galaxy.py @@ -426,7 +426,7 @@ class GalaxyCLI(CLI): 'required': required, } server_def = [('url', True), ('username', False), ('password', False), ('token', False), - ('auth_url', False)] + ('auth_url', False), ('v3', False)] validate_certs = not context.CLIARGS['ignore_certs'] @@ -447,6 +447,14 @@ class GalaxyCLI(CLI): auth_url = server_options.pop('auth_url', None) token_val = server_options['token'] or NoTokenSentinel username = server_options['username'] + available_api_versions = None + v3 = server_options.pop('v3', None) + if v3: + # This allows a user to explicitly indicate the server uses the /v3 API + # 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 + server_options['available_api_versions'] = {'v3': '/v3'} # default case if no auth info is provided. server_options['token'] = None diff --git a/lib/ansible/galaxy/api.py b/lib/ansible/galaxy/api.py index cf5290b7dad..3335c5f0f6a 100644 --- a/lib/ansible/galaxy/api.py +++ b/lib/ansible/galaxy/api.py @@ -168,7 +168,8 @@ class CollectionVersionMetadata: class GalaxyAPI: """ This class is meant to be used as a API client for an Ansible Galaxy server """ - def __init__(self, galaxy, name, url, username=None, password=None, token=None, validate_certs=True): + def __init__(self, galaxy, name, url, username=None, password=None, token=None, validate_certs=True, + available_api_versions=None): self.galaxy = galaxy self.name = name self.username = username @@ -176,7 +177,7 @@ class GalaxyAPI: self.token = token self.api_server = url self.validate_certs = validate_certs - self._available_api_versions = {} + self._available_api_versions = available_api_versions or {} display.debug('Validate TLS certificates for %s: %s' % (self.api_server, self.validate_certs)) @@ -478,8 +479,16 @@ class GalaxyAPI: wait = 2 while timeout == 0 or (time.time() - start) < timeout: - data = self._call_galaxy(full_url, method='GET', auth_required=True, - error_context_msg='Error when getting import task results at %s' % full_url) + 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) + except GalaxyError as e: + if e.http_code != 404: + raise + # The import job may not have started, and as such, the task url may not yet exist + display.vvv('Galaxy import process has not started, wait %s seconds before trying again' % wait) + time.sleep(wait) + continue state = data.get('state', 'waiting') @@ -545,12 +554,10 @@ class GalaxyAPI: relative_link = False if 'v3' in self.available_api_versions: api_path = self.available_api_versions['v3'] - results_key = 'data' 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'] - results_key = 'results' pagination_path = ['next'] n_url = _urljoin(self.api_server, api_path, 'collections', namespace, name, 'versions', '/') @@ -559,6 +566,14 @@ class GalaxyAPI: % (namespace, name, self.name, self.api_server) data = self._call_galaxy(n_url, error_context_msg=error_context_msg) + if 'data' in data: + # v3 automation-hub is the only known API that uses `data` + # since v3 pulp_ansible does not, we cannot rely on version + # to indicate which key to use + results_key = 'data' + else: + results_key = 'results' + versions = [] while True: versions += [v['version'] for v in data[results_key]] diff --git a/shippable.yml b/shippable.yml index 701e83c84f9..d70d894437b 100644 --- a/shippable.yml +++ b/shippable.yml @@ -102,8 +102,8 @@ matrix: - env: T=linux/ubuntu1604/5 - env: T=linux/ubuntu1804/5 - - env: T=fallaxy/2.7/1 - - env: T=fallaxy/3.6/1 + - env: T=galaxy/2.7/1 + - env: T=galaxy/3.6/1 - env: T=generic/2.7/1 - env: T=generic/3.6/1 diff --git a/test/integration/targets/ansible-galaxy-collection/aliases b/test/integration/targets/ansible-galaxy-collection/aliases index 4b3ebea36a8..e501bce5886 100644 --- a/test/integration/targets/ansible-galaxy-collection/aliases +++ b/test/integration/targets/ansible-galaxy-collection/aliases @@ -1,3 +1,3 @@ -shippable/fallaxy/group1 -shippable/fallaxy/smoketest -cloud/fallaxy +shippable/galaxy/group1 +shippable/galaxy/smoketest +cloud/galaxy diff --git a/test/integration/targets/ansible-galaxy-collection/library/setup_collections.py b/test/integration/targets/ansible-galaxy-collection/library/setup_collections.py index b876a65f4ee..9f4d71e1942 100644 --- a/test/integration/targets/ansible-galaxy-collection/library/setup_collections.py +++ b/test/integration/targets/ansible-galaxy-collection/library/setup_collections.py @@ -88,7 +88,7 @@ from ansible.module_utils._text import to_bytes def run_module(): module_args = dict( server=dict(type='str', required=True), - token=dict(type='str', required=True), + token=dict(type='str'), collections=dict( type='list', elements='dict', @@ -108,7 +108,7 @@ def run_module(): supports_check_mode=False ) - result = dict(changed=True) + result = dict(changed=True, results=[]) for idx, collection in enumerate(module.params['collections']): collection_dir = os.path.join(module.tmpdir, "%s-%s-%s" % (collection['namespace'], collection['name'], @@ -126,6 +126,7 @@ def run_module(): 'readme': 'README.md', 'authors': ['Collection author 0 + block: + - name: delete pulp distributions + uri: + url: '{{ pulp_api }}{{ distribution.pulp_href }}' + method: DELETE + status_code: + - 202 + user: '{{ pulp_user }}' + password: '{{ pulp_password }}' + force_basic_auth: true + register: pulp_distribution_delete_tasks + loop: '{{ pulp_distributions.json.results }}' + loop_control: + loop_var: distribution + label: '{{ distribution.name }}' + + - name: wait for distribution delete + uri: + url: '{{ pulp_api }}{{ task.json.task }}' + method: GET + status_code: + - 200 + user: '{{ pulp_user }}' + password: '{{ pulp_password }}' + force_basic_auth: true + register: pulp_distribution_delete + until: pulp_distribution_delete is successful and pulp_distribution_delete.json.state|default("MISSING") == "completed" + delay: 1 + retries: 25 + loop: '{{ pulp_distribution_delete_tasks.results }}' + loop_control: + loop_var: task + label: '{{ task.json.task }}' + + - name: delete pulp repository + uri: + url: '{{ pulp_api }}{{ distribution.repository }}' + method: DELETE + status_code: + - 202 + user: '{{ pulp_user }}' + password: '{{ pulp_password }}' + force_basic_auth: true + register: pulp_repository_delete_tasks + loop: '{{ pulp_distributions.json.results }}' + loop_control: + loop_var: distribution + label: '{{ distribution.name }}' + + - name: wait for repository delete + uri: + url: '{{ pulp_api }}{{ task.json.task }}' + method: GET + status_code: + - 200 + user: '{{ pulp_user }}' + password: '{{ pulp_password }}' + force_basic_auth: true + register: pulp_repository_delete + until: pulp_repository_delete is successful and pulp_repository_delete.json.state|default("MISSING") == "completed" + delay: 1 + retries: 25 + loop: '{{ pulp_repository_delete_tasks.results }}' + loop_control: + loop_var: task + label: '{{ task.json.task }}' + + - name: delete pulp orphans + uri: + url: '{{ pulp_api }}/pulp/api/v3/orphans/' + method: DELETE + status_code: + - 202 + user: '{{ pulp_user }}' + password: '{{ pulp_password }}' + force_basic_auth: true + register: pulp_orphans_delete_task + + - name: wait for orphan delete + uri: + url: '{{ pulp_api }}{{ pulp_orphans_delete_task.json.task }}' + method: GET + status_code: + - 200 + user: '{{ pulp_user }}' + password: '{{ pulp_password }}' + force_basic_auth: true + register: pulp_orphans_delete + until: pulp_orphans_delete is successful and pulp_orphans_delete.json.state|default("MISSING") == "completed" + delay: 1 + retries: 25 + +- name: create pulp repo + uri: + url: '{{ pulp_api }}/pulp/api/v3/repositories/ansible/ansible/' + method: POST + body_format: json + body: + name: ansible_ci + status_code: + - 201 + user: '{{ pulp_user }}' + password: '{{ pulp_password }}' + force_basic_auth: true + register: pulp_repo + +- name: create pulp distribution + uri: + url: '{{ pulp_api }}/pulp/api/v3/distributions/ansible/ansible/' + method: POST + body_format: json + body: + name: ansible_ci + base_path: ansible_ci + repository: '{{ pulp_api }}{{ pulp_repo.json.pulp_href }}' + status_code: + - 202 + user: '{{ pulp_user }}' + password: '{{ pulp_password }}' + force_basic_auth: true + register: pulp_distribution_task + +- name: wait for distribution creation + uri: + url: '{{ pulp_api }}{{ pulp_distribution_task.json.task }}' + method: GET + status_code: + - 200 + user: '{{ pulp_user }}' + password: '{{ pulp_password }}' + force_basic_auth: true + until: pulp_distribution is successful and pulp_distribution.json.state|default("MISSING") == "completed" + delay: 1 + retries: 25 + register: pulp_distribution diff --git a/test/integration/targets/ansible-galaxy-collection/templates/ansible.cfg.j2 b/test/integration/targets/ansible-galaxy-collection/templates/ansible.cfg.j2 index 74d36aacfbd..6e043f3450a 100644 --- a/test/integration/targets/ansible-galaxy-collection/templates/ansible.cfg.j2 +++ b/test/integration/targets/ansible-galaxy-collection/templates/ansible.cfg.j2 @@ -1,5 +1,5 @@ [galaxy] -server_list=galaxy,automation_hub +server_list=galaxy,automation_hub,pulp_v2,pulp_v3 [galaxy_server.galaxy] url={{ fallaxy_galaxy_server }} @@ -8,3 +8,14 @@ token={{ fallaxy_token }} [galaxy_server.automation_hub] url={{ fallaxy_ah_server }} token={{ fallaxy_token }} + +[galaxy_server.pulp_v2] +url={{ pulp_v2_server }} +username={{ pulp_user }} +password={{ pulp_password }} + +[galaxy_server.pulp_v3] +url={{ pulp_v3_server }} +v3=true +username={{ pulp_user }} +password={{ pulp_password }} diff --git a/test/lib/ansible_test/_internal/cloud/fallaxy.py b/test/lib/ansible_test/_internal/cloud/fallaxy.py deleted file mode 100644 index 504094bd1d7..00000000000 --- a/test/lib/ansible_test/_internal/cloud/fallaxy.py +++ /dev/null @@ -1,177 +0,0 @@ -"""Fallaxy (ansible-galaxy) plugin for integration tests.""" -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import uuid - -from . import ( - CloudProvider, - CloudEnvironment, - CloudEnvironmentConfig, -) - -from ..util import ( - find_executable, - display, -) - -from ..docker_util import ( - docker_run, - docker_rm, - docker_inspect, - docker_pull, - get_docker_container_id, -) - - -class FallaxyProvider(CloudProvider): - """Fallaxy plugin. - - Sets up Fallaxy (ansible-galaxy) stub server for tests. - - It's source source itself resides at: https://github.com/ansible/fallaxy-test-container - """ - - DOCKER_SIMULATOR_NAME = 'fallaxy-stub' - - def __init__(self, args): - """ - :type args: TestConfig - """ - super(FallaxyProvider, self).__init__(args) - - if os.environ.get('ANSIBLE_FALLAXY_CONTAINER'): - self.image = os.environ.get('ANSIBLE_FALLAXY_CONTAINER') - else: - self.image = 'quay.io/ansible/fallaxy-test-container:2.0.1' - self.container_name = '' - - def filter(self, targets, exclude): - """Filter out the tests with the necessary config and res unavailable. - - :type targets: tuple[TestTarget] - :type exclude: list[str] - """ - docker_cmd = 'docker' - docker = find_executable(docker_cmd, required=False) - - if docker: - return - - skip = 'cloud/%s/' % self.platform - skipped = [target.name for target in targets if skip in target.aliases] - - if skipped: - exclude.append(skip) - display.warning('Excluding tests marked "%s" which require the "%s" command: %s' - % (skip.rstrip('/'), docker_cmd, ', '.join(skipped))) - - def setup(self): - """Setup cloud resource before delegation and reg cleanup callback.""" - super(FallaxyProvider, self).setup() - - if self._use_static_config(): - self._setup_static() - else: - self._setup_dynamic() - - def get_docker_run_options(self): - """Get additional options needed when delegating tests to a container. - - :rtype: list[str] - """ - return ['--link', self.DOCKER_SIMULATOR_NAME] if self.managed else [] - - def cleanup(self): - """Clean up the resource and temporary configs files after tests.""" - if self.container_name: - docker_rm(self.args, self.container_name) - - super(FallaxyProvider, self).cleanup() - - def _setup_dynamic(self): - container_id = get_docker_container_id() - - if container_id: - display.info('Running in docker container: %s' % container_id, verbosity=1) - - self.container_name = self.DOCKER_SIMULATOR_NAME - - results = docker_inspect(self.args, self.container_name) - - if results and not results[0].get('State', {}).get('Running'): - docker_rm(self.args, self.container_name) - results = [] - - display.info('%s Fallaxy simulator docker container.' - % ('Using the existing' if results else 'Starting a new'), - verbosity=1) - - fallaxy_port = 8080 - fallaxy_token = str(uuid.uuid4()).replace('-', '') - - if not results: - if self.args.docker or container_id: - publish_ports = [] - else: - # publish the simulator ports when not running inside docker - publish_ports = [ - '-p', ':'.join((str(fallaxy_port),) * 2), - ] - - if not os.environ.get('ANSIBLE_FALLAXY_CONTAINER'): - docker_pull(self.args, self.image) - - docker_run( - self.args, - self.image, - ['-d', '--name', self.container_name, '-e', 'FALLAXY_TOKEN=%s' % fallaxy_token] + publish_ports, - ) - - if self.args.docker: - fallaxy_host = self.DOCKER_SIMULATOR_NAME - elif container_id: - fallaxy_host = self._get_simulator_address() - display.info('Found Fallaxy simulator container address: %s' % fallaxy_host, verbosity=1) - else: - fallaxy_host = 'localhost' - - self._set_cloud_config('FALLAXY_HOST', fallaxy_host) - self._set_cloud_config('FALLAXY_PORT', str(fallaxy_port)) - self._set_cloud_config('FALLAXY_TOKEN', fallaxy_token) - - def _get_simulator_address(self): - results = docker_inspect(self.args, self.container_name) - ipaddress = results[0]['NetworkSettings']['IPAddress'] - return ipaddress - - def _setup_static(self): - raise NotImplementedError() - - -class FallaxyEnvironment(CloudEnvironment): - """Fallaxy environment plugin. - - Updates integration test environment after delegation. - """ - def get_environment_config(self): - """ - :rtype: CloudEnvironmentConfig - """ - fallaxy_token = self._get_cloud_config('FALLAXY_TOKEN') - fallaxy_host = self._get_cloud_config('FALLAXY_HOST') - fallaxy_port = self._get_cloud_config('FALLAXY_PORT') - - return CloudEnvironmentConfig( - ansible_vars=dict( - fallaxy_token=fallaxy_token, - fallaxy_galaxy_server='http://%s:%s/api/' % (fallaxy_host, fallaxy_port), - fallaxy_ah_server='http://%s:%s/api/automation-hub/' % (fallaxy_host, fallaxy_port), - ), - env_vars=dict( - FALLAXY_TOKEN=fallaxy_token, - FALLAXY_GALAXY_SERVER='http://%s:%s/api/' % (fallaxy_host, fallaxy_port), - FALLAXY_AH_SERVER='http://%s:%s/api/automation-hub/' % (fallaxy_host, fallaxy_port), - ), - ) diff --git a/test/lib/ansible_test/_internal/cloud/galaxy.py b/test/lib/ansible_test/_internal/cloud/galaxy.py new file mode 100644 index 00000000000..95db6f4966a --- /dev/null +++ b/test/lib/ansible_test/_internal/cloud/galaxy.py @@ -0,0 +1,271 @@ +"""Galaxy (ansible-galaxy) plugin for integration tests.""" +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import tempfile +import uuid + +from . import ( + CloudProvider, + CloudEnvironment, + CloudEnvironmentConfig, +) + +from ..util import ( + find_executable, + display, +) + +from ..docker_util import ( + docker_command, + docker_run, + docker_start, + docker_rm, + docker_inspect, + docker_pull, + get_docker_container_id, +) + + +SETTINGS = b''' +CONTENT_ORIGIN='pulp:80' +ANSIBLE_API_HOSTNAME='http://pulp:80' +ANSIBLE_CONTENT_HOSTNAME='http://pulp:80/pulp/content' +TOKEN_AUTH_DISABLED=True +''' + +SET_ADMIN_PASSWORD = b'''#!/usr/bin/execlineb -S0 +foreground { + redirfd -w 1 /dev/null + redirfd -w 2 /dev/null + export DJANGO_SETTINGS_MODULE pulpcore.app.settings + export PULP_CONTENT_ORIGIN localhost + s6-setuidgid postgres + /usr/local/bin/django-admin reset-admin-password --password password +} +''' + + +class GalaxyProvider(CloudProvider): + """Galaxy plugin. + + Sets up fallaxy and pulp (ansible-galaxy) servers for tests. + + The fallaxy source itself resides at: https://github.com/ansible/fallaxy-test-container + The pulp source itself resides at: https://github.com/pulp/pulp-oci-images + """ + + def __init__(self, args): + """ + :type args: TestConfig + """ + super(GalaxyProvider, self).__init__(args) + + self.fallaxy = os.environ.get( + 'ANSIBLE_FALLAXY_CONTAINER', + 'quay.io/ansible/fallaxy-test-container:2.0.1' + ) + self.pulp = os.environ.get( + 'ANSIBLE_PULP_CONTAINER', + 'docker.io/pulp/pulp-fedora31@sha256:71054f92fc9c986ba823d86b68631bafc84ae61b7832ce0be1f8e74423e56f64' + ) + + self.containers = [] + + def filter(self, targets, exclude): + """Filter out the tests with the necessary config and res unavailable. + + :type targets: tuple[TestTarget] + :type exclude: list[str] + """ + docker_cmd = 'docker' + docker = find_executable(docker_cmd, required=False) + + if docker: + return + + skip = 'cloud/%s/' % self.platform + skipped = [target.name for target in targets if skip in target.aliases] + + if skipped: + exclude.append(skip) + display.warning('Excluding tests marked "%s" which require the "%s" command: %s' + % (skip.rstrip('/'), docker_cmd, ', '.join(skipped))) + + def setup(self): + """Setup cloud resource before delegation and reg cleanup callback.""" + super(GalaxyProvider, self).setup() + + container_id = get_docker_container_id() + + if container_id: + display.info('Running in docker container: %s' % container_id, verbosity=1) + + f_results = docker_inspect(self.args, 'fallaxy-stub') + p_results = docker_inspect(self.args, 'pulp') + + if f_results and not f_results[0].get('State', {}).get('Running'): + docker_rm(self.args, 'fallaxy-stub') + f_results = [] + + if p_results and not p_results[0].get('State', {}).get('Running'): + docker_rm(self.args, 'pulp') + p_results = [] + + display.info('%s fallaxy-stub docker container.' + % ('Using the existing' if f_results else 'Starting a new'), + verbosity=1) + + fallaxy_port = 8080 + fallaxy_token = str(uuid.uuid4()).replace('-', '') + + if not f_results: + if self.args.docker or container_id: + publish_ports = [] + else: + # publish the simulator ports when not running inside docker + publish_ports = [ + '-p', ':'.join((str(fallaxy_port),) * 2), + ] + + docker_pull(self.args, self.fallaxy) + + docker_run( + self.args, + self.fallaxy, + ['-d', '--name', 'fallaxy-stub', '-e', 'FALLAXY_TOKEN=%s' % fallaxy_token] + publish_ports, + ) + self.containers.append('fallaxy-stub') + + if self.args.docker: + fallaxy_host = 'fallaxy-stub' + elif container_id: + fallaxy_host = self._get_simulator_address('fallaxy-stub') + display.info('Found Galaxy simulator container address: %s' % fallaxy_host, verbosity=1) + else: + fallaxy_host = 'localhost' + + self._set_cloud_config('FALLAXY_HOST', fallaxy_host) + self._set_cloud_config('FALLAXY_PORT', str(fallaxy_port)) + self._set_cloud_config('FALLAXY_TOKEN', fallaxy_token) + + display.info('%s pulp docker container.' + % ('Using the existing' if p_results else 'Starting a new'), + verbosity=1) + + pulp_port = 80 + + if not p_results: + if self.args.docker or container_id: + publish_ports = [] + else: + # publish the simulator ports when not running inside docker + publish_ports = [ + '-p', ':'.join((str(fallaxy_port),) * 2), + ] + + docker_pull(self.args, self.pulp) + + # Create the container, don't run it, we need to inject configs before it starts + stdout, _dummy = docker_run( + self.args, + self.pulp, + ['--name', 'pulp'] + publish_ports, + create_only=True + ) + + pulp_id = stdout.strip() + + try: + # Inject our settings.py file + with tempfile.NamedTemporaryFile(delete=False) as settings: + settings.write(SETTINGS) + docker_command(self.args, ['cp', settings.name, '%s:/etc/pulp/settings.py' % pulp_id]) + finally: + os.unlink(settings.name) + + try: + # Inject our settings.py file + with tempfile.NamedTemporaryFile(delete=False) as admin_pass: + admin_pass.write(SET_ADMIN_PASSWORD) + docker_command(self.args, ['cp', admin_pass.name, '%s:/etc/cont-init.d/111-postgres' % pulp_id]) + finally: + os.unlink(admin_pass.name) + + # Start the container + docker_start(self.args, 'pulp', []) + + self.containers.append('pulp') + + if self.args.docker: + pulp_host = 'pulp' + elif container_id: + pulp_host = self._get_simulator_address('pulp') + display.info('Found Galaxy simulator container address: %s' % pulp_host, verbosity=1) + else: + pulp_host = 'localhost' + + self._set_cloud_config('PULP_HOST', pulp_host) + self._set_cloud_config('PULP_PORT', str(pulp_port)) + self._set_cloud_config('PULP_USER', 'admin') + self._set_cloud_config('PULP_PASSWORD', 'password') + + def get_docker_run_options(self): + """Get additional options needed when delegating tests to a container. + + :rtype: list[str] + """ + return ['--link', 'fallaxy-stub', '--link', 'pulp'] # if self.managed else [] + + def cleanup(self): + """Clean up the resource and temporary configs files after tests.""" + for container_name in self.containers: + docker_rm(self.args, container_name) + + super(GalaxyProvider, self).cleanup() + + def _get_simulator_address(self, container_name): + results = docker_inspect(self.args, container_name) + ipaddress = results[0]['NetworkSettings']['IPAddress'] + return ipaddress + + +class GalaxyEnvironment(CloudEnvironment): + """Galaxy environment plugin. + + Updates integration test environment after delegation. + """ + def get_environment_config(self): + """ + :rtype: CloudEnvironmentConfig + """ + fallaxy_token = self._get_cloud_config('FALLAXY_TOKEN') + fallaxy_host = self._get_cloud_config('FALLAXY_HOST') + fallaxy_port = self._get_cloud_config('FALLAXY_PORT') + pulp_user = self._get_cloud_config('PULP_USER') + pulp_password = self._get_cloud_config('PULP_PASSWORD') + pulp_host = self._get_cloud_config('PULP_HOST') + pulp_port = self._get_cloud_config('PULP_PORT') + + return CloudEnvironmentConfig( + ansible_vars=dict( + fallaxy_token=fallaxy_token, + fallaxy_galaxy_server='http://%s:%s/api/' % (fallaxy_host, fallaxy_port), + fallaxy_ah_server='http://%s:%s/api/automation-hub/' % (fallaxy_host, fallaxy_port), + pulp_user=pulp_user, + pulp_password=pulp_password, + pulp_v2_server='http://%s:%s/pulp_ansible/galaxy/ansible_ci/api/' % (pulp_host, pulp_port), + pulp_v3_server='http://%s:%s/pulp_ansible/galaxy/ansible_ci/api/' % (pulp_host, pulp_port), + pulp_api='http://%s:%s' % (pulp_host, pulp_port), + ), + env_vars=dict( + FALLAXY_TOKEN=fallaxy_token, + FALLAXY_GALAXY_SERVER='http://%s:%s/api/' % (fallaxy_host, fallaxy_port), + FALLAXY_AH_SERVER='http://%s:%s/api/automation-hub/' % (fallaxy_host, fallaxy_port), + PULP_USER=pulp_user, + PULP_PASSWORD=pulp_password, + PULP_V2_SERVER='http://%s:%s/pulp_ansible/galaxy/ansible_ci/api/' % (pulp_host, pulp_port), + PULP_V3_SERVER='http://%s:%s/pulp_ansible/galaxy/ansible_ci/api/' % (pulp_host, pulp_port), + ), + ) diff --git a/test/lib/ansible_test/_internal/docker_util.py b/test/lib/ansible_test/_internal/docker_util.py index 0ce2ffb328e..1807d063f67 100644 --- a/test/lib/ansible_test/_internal/docker_util.py +++ b/test/lib/ansible_test/_internal/docker_util.py @@ -135,12 +135,13 @@ def docker_get(args, container_id, src, dst): options=['-i'], stdout=dst_fd, capture=True) -def docker_run(args, image, options, cmd=None): +def docker_run(args, image, options, cmd=None, create_only=False): """ :type args: EnvironmentConfig :type image: str :type options: list[str] | None :type cmd: list[str] | None + :type create_only[bool] | False :rtype: str | None, str | None """ if not options: @@ -149,9 +150,14 @@ def docker_run(args, image, options, cmd=None): if not cmd: cmd = [] + if create_only: + command = 'create' + else: + command = 'run' + for _iteration in range(1, 3): try: - return docker_command(args, ['run'] + options + [image] + cmd, capture=True) + return docker_command(args, [command] + options + [image] + cmd, capture=True) except SubprocessError as ex: display.error(ex) display.warning('Failed to run docker image "%s". Waiting a few seconds before trying again.' % image) @@ -160,6 +166,24 @@ def docker_run(args, image, options, cmd=None): raise ApplicationError('Failed to run docker image "%s".' % image) +def docker_start(args, container_id, options): # type: (EnvironmentConfig, str, t.List[str]) -> (t.Optional[str], t.Optional[str]) + """ + Start a docker container by name or ID + """ + if not options: + options = [] + + for _iteration in range(1, 3): + try: + return docker_command(args, ['start'] + options + [container_id], capture=True) + except SubprocessError as ex: + display.error(ex) + display.warning('Failed to start docker container "%s". Waiting a few seconds before trying again.' % container_id) + time.sleep(3) + + raise ApplicationError('Failed to run docker container "%s".' % container_id) + + def docker_images(args, image): """ :param args: CommonConfig @@ -275,7 +299,7 @@ def docker_version(args): return json.loads(stdout) -def docker_command(args, cmd, capture=False, stdin=None, stdout=None, always=False): +def docker_command(args, cmd, capture=False, stdin=None, stdout=None, always=False, data=None): """ :type args: CommonConfig :type cmd: list[str] @@ -283,10 +307,11 @@ def docker_command(args, cmd, capture=False, stdin=None, stdout=None, always=Fal :type stdin: file | None :type stdout: file | None :type always: bool + :type data: str | None :rtype: str | None, str | None """ env = docker_environment() - return run_command(args, ['docker'] + cmd, env=env, capture=capture, stdin=stdin, stdout=stdout, always=always) + return run_command(args, ['docker'] + cmd, env=env, capture=capture, stdin=stdin, stdout=stdout, always=always, data=data) def docker_environment(): diff --git a/test/utils/shippable/fallaxy.sh b/test/utils/shippable/galaxy.sh similarity index 100% rename from test/utils/shippable/fallaxy.sh rename to test/utils/shippable/galaxy.sh