diff options
author | Matt Clay <matt@mystile.com> | 2021-09-23 13:47:07 -0700 |
---|---|---|
committer | Matt Clay <matt@mystile.com> | 2021-09-23 15:52:34 -0700 |
commit | e3fd9b0769ec5ae85e0e698b5f9e0777d57c7c21 (patch) | |
tree | d57677abab7c6481475cef198a4c09ba9a754e09 | |
parent | 28a094c5deb33cf244ff72ab47a217e3925d42c7 (diff) | |
download | ansible-e3fd9b0769ec5ae85e0e698b5f9e0777d57c7c21.tar.gz |
ansible-test - Add `--prime-containers` option.
Resolves https://github.com/ansible/ansible/issues/75320
The option `--prime-containers` was chosen over `--docker-pull-only` to match the recently added `--prime-venvs` option for sanity tests.
It would also fit well with a future `--prime-requirements` option for pre-installing requirements for unit and integration tests.
12 files changed, 55 insertions, 4 deletions
diff --git a/changelogs/fragments/ansible-test-prime-containers.yml b/changelogs/fragments/ansible-test-prime-containers.yml new file mode 100644 index 0000000000..0c2d46a44a --- /dev/null +++ b/changelogs/fragments/ansible-test-prime-containers.yml @@ -0,0 +1,2 @@ +minor_changes: + - ansible-test - Added a ``--prime-containers`` option to support downloading containers without running tests. diff --git a/test/lib/ansible_test/_internal/__init__.py b/test/lib/ansible_test/_internal/__init__.py index b9d0e98e5d..e604a2b35a 100644 --- a/test/lib/ansible_test/_internal/__init__.py +++ b/test/lib/ansible_test/_internal/__init__.py @@ -42,6 +42,10 @@ from .cli import ( parse_args, ) +from .provisioning import ( + PrimeContainers, +) + def main(): """Main program function.""" @@ -64,6 +68,8 @@ def main(): try: args.func(config) + except PrimeContainers: + pass except ListTargets as ex: # save target_names for use once we exit the exception handler target_names = ex.target_names diff --git a/test/lib/ansible_test/_internal/cli/environments.py b/test/lib/ansible_test/_internal/cli/environments.py index b041ece7dc..640ff56bd4 100644 --- a/test/lib/ansible_test/_internal/cli/environments.py +++ b/test/lib/ansible_test/_internal/cli/environments.py @@ -385,6 +385,7 @@ def add_global_docker( docker_no_pull=False, docker_network=None, docker_terminate=None, + prime_containers=False, ) return @@ -410,6 +411,12 @@ def add_global_docker( help='terminate the container: %(choices)s (default: %(default)s)', ) + parser.add_argument( + '--prime-containers', + action='store_true', + help='download containers without running tests', + ) + def add_environment_docker( exclusive_parser, # type: argparse.ArgumentParser diff --git a/test/lib/ansible_test/_internal/commands/integration/cloud/__init__.py b/test/lib/ansible_test/_internal/commands/integration/cloud/__init__.py index 040fbc5004..70f8afafe6 100644 --- a/test/lib/ansible_test/_internal/commands/integration/cloud/__init__.py +++ b/test/lib/ansible_test/_internal/commands/integration/cloud/__init__.py @@ -151,7 +151,10 @@ def cloud_init(args, targets): # type: (IntegrationConfig, t.Tuple[IntegrationT results = {} - for provider in get_cloud_providers(args, targets): + for provider in get_cloud_providers(args, targets): # type: CloudProvider + if args.prime_containers and not provider.uses_docker: + continue + args.metadata.cloud_config[provider.platform] = {} start_time = time.time() diff --git a/test/lib/ansible_test/_internal/commands/integration/cloud/cs.py b/test/lib/ansible_test/_internal/commands/integration/cloud/cs.py index 1dc07abb98..f20a7d887e 100644 --- a/test/lib/ansible_test/_internal/commands/integration/cloud/cs.py +++ b/test/lib/ansible_test/_internal/commands/integration/cloud/cs.py @@ -91,7 +91,7 @@ class CsCloudProvider(CloudProvider): self.port, ] - run_support_container( + descriptor = run_support_container( self.args, self.platform, self.image, @@ -101,6 +101,9 @@ class CsCloudProvider(CloudProvider): cleanup=CleanupMode.YES, ) + if not descriptor: + return + # apply work-around for OverlayFS issue # https://github.com/docker/for-linux/issues/72#issuecomment-319904698 docker_exec(self.args, self.DOCKER_SIMULATOR_NAME, ['find', '/var/lib/mysql', '-type', 'f', '-exec', 'touch', '{}', ';']) diff --git a/test/lib/ansible_test/_internal/commands/integration/cloud/galaxy.py b/test/lib/ansible_test/_internal/commands/integration/cloud/galaxy.py index 066d2b0a0b..9c9000715d 100644 --- a/test/lib/ansible_test/_internal/commands/integration/cloud/galaxy.py +++ b/test/lib/ansible_test/_internal/commands/integration/cloud/galaxy.py @@ -115,6 +115,9 @@ class GalaxyProvider(CloudProvider): allow_existing=True, ) + if not descriptor: + return + if not descriptor.running: pulp_id = descriptor.container_id diff --git a/test/lib/ansible_test/_internal/commands/integration/cloud/httptester.py b/test/lib/ansible_test/_internal/commands/integration/cloud/httptester.py index 2899aeff62..2d8217e99c 100644 --- a/test/lib/ansible_test/_internal/commands/integration/cloud/httptester.py +++ b/test/lib/ansible_test/_internal/commands/integration/cloud/httptester.py @@ -68,6 +68,9 @@ class HttptesterProvider(CloudProvider): }, ) + if not descriptor: + return + # Read the password from the container environment. # This allows the tests to work when re-using an existing container. # The password is marked as sensitive, since it may differ from the one we generated. diff --git a/test/lib/ansible_test/_internal/commands/integration/cloud/openshift.py b/test/lib/ansible_test/_internal/commands/integration/cloud/openshift.py index 2acf96282d..c30785afaf 100644 --- a/test/lib/ansible_test/_internal/commands/integration/cloud/openshift.py +++ b/test/lib/ansible_test/_internal/commands/integration/cloud/openshift.py @@ -69,7 +69,7 @@ class OpenShiftCloudProvider(CloudProvider): cmd = ['start', 'master', '--listen', 'https://0.0.0.0:%d' % port] - run_support_container( + descriptor = run_support_container( self.args, self.platform, self.image, @@ -80,6 +80,9 @@ class OpenShiftCloudProvider(CloudProvider): cmd=cmd, ) + if not descriptor: + return + if self.args.explain: config = '# Unknown' else: diff --git a/test/lib/ansible_test/_internal/config.py b/test/lib/ansible_test/_internal/config.py index 9c79e33b3a..be9ef2ffc7 100644 --- a/test/lib/ansible_test/_internal/config.py +++ b/test/lib/ansible_test/_internal/config.py @@ -106,6 +106,8 @@ class EnvironmentConfig(CommonConfig): self.remote_stage = args.remote_stage # type: t.Optional[str] self.remote_terminate = args.remote_terminate # type: t.Optional[TerminateMode] + self.prime_containers = args.prime_containers # type: bool + self.requirements = args.requirements # type: bool self.delegate_args = [] # type: t.List[str] diff --git a/test/lib/ansible_test/_internal/containers.py b/test/lib/ansible_test/_internal/containers.py index 64c1d9ec76..97e84880e9 100644 --- a/test/lib/ansible_test/_internal/containers.py +++ b/test/lib/ansible_test/_internal/containers.py @@ -113,11 +113,15 @@ def run_support_container( env=None, # type: t.Optional[t.Dict[str, str]] options=None, # type: t.Optional[t.List[str]] publish_ports=True, # type: bool -): # type: (...) -> ContainerDescriptor +): # type: (...) -> t.Optional[ContainerDescriptor] """ Start a container used to support tests, but not run them. Containers created this way will be accessible from tests. """ + if args.prime_containers: + docker_pull(args, image) + return None + # SSH is required for publishing ports, as well as modifying the hosts file. # Initializing the SSH key here makes sure it is available for use after delegation. SshKey(args) diff --git a/test/lib/ansible_test/_internal/host_profiles.py b/test/lib/ansible_test/_internal/host_profiles.py index 30b4f8570c..ae33eb0749 100644 --- a/test/lib/ansible_test/_internal/host_profiles.py +++ b/test/lib/ansible_test/_internal/host_profiles.py @@ -349,6 +349,9 @@ class DockerProfile(ControllerHostProfile[DockerConfig], SshTargetHostProfile[Do cleanup=CleanupMode.NO, ) + if not container: + return + self.container_name = container.name def setup(self): # type: () -> None diff --git a/test/lib/ansible_test/_internal/provisioning.py b/test/lib/ansible_test/_internal/provisioning.py index 6f81c40b86..a95360360b 100644 --- a/test/lib/ansible_test/_internal/provisioning.py +++ b/test/lib/ansible_test/_internal/provisioning.py @@ -30,6 +30,7 @@ from .thread import ( from .host_profiles import ( ControllerHostProfile, + DockerProfile, HostProfile, SshConnection, SshTargetHostProfile, @@ -44,6 +45,10 @@ THostProfile = t.TypeVar('THostProfile', bound=HostProfile) TEnvironmentConfig = t.TypeVar('TEnvironmentConfig', bound=EnvironmentConfig) +class PrimeContainers(ApplicationError): + """Exception raised to end execution early after priming containers.""" + + @dataclasses.dataclass(frozen=True) class HostState: """State of hosts and profiles to be passed to ansible-test during delegation.""" @@ -109,6 +114,13 @@ def prepare_profiles( target_profiles=[create_host_profile(args, target, False) for target in args.targets], ) + if args.prime_containers: + for host_profile in host_state.profiles: + if isinstance(host_profile, DockerProfile): + host_profile.provision() + + raise PrimeContainers() + atexit.register(functools.partial(cleanup_profiles, host_state)) def provision(profile): # type: (HostProfile) -> None |