summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Clay <matt@mystile.com>2021-09-23 13:47:07 -0700
committerMatt Clay <matt@mystile.com>2021-09-23 15:52:34 -0700
commite3fd9b0769ec5ae85e0e698b5f9e0777d57c7c21 (patch)
treed57677abab7c6481475cef198a4c09ba9a754e09
parent28a094c5deb33cf244ff72ab47a217e3925d42c7 (diff)
downloadansible-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.
-rw-r--r--changelogs/fragments/ansible-test-prime-containers.yml2
-rw-r--r--test/lib/ansible_test/_internal/__init__.py6
-rw-r--r--test/lib/ansible_test/_internal/cli/environments.py7
-rw-r--r--test/lib/ansible_test/_internal/commands/integration/cloud/__init__.py5
-rw-r--r--test/lib/ansible_test/_internal/commands/integration/cloud/cs.py5
-rw-r--r--test/lib/ansible_test/_internal/commands/integration/cloud/galaxy.py3
-rw-r--r--test/lib/ansible_test/_internal/commands/integration/cloud/httptester.py3
-rw-r--r--test/lib/ansible_test/_internal/commands/integration/cloud/openshift.py5
-rw-r--r--test/lib/ansible_test/_internal/config.py2
-rw-r--r--test/lib/ansible_test/_internal/containers.py6
-rw-r--r--test/lib/ansible_test/_internal/host_profiles.py3
-rw-r--r--test/lib/ansible_test/_internal/provisioning.py12
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