diff options
author | Alberto Contreras <alberto.contreras@canonical.com> | 2022-08-02 15:45:45 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-02 07:45:45 -0600 |
commit | bccf9a5791d83b2cf679a9c08447f3e3bc73b541 (patch) | |
tree | 76a7d839666b0f12e4946372425339467bc4a6ec | |
parent | d7ce6bf096d2431cbb6bc736cc561fef78170d7d (diff) | |
download | cloud-init-git-bccf9a5791d83b2cf679a9c08447f3e3bc73b541.tar.gz |
testing: add support for pycloudlib's pro images (#1604)
Added new pytest marker to define IntegrationCloud customizations.
Migrate test_lp1835584 to use this functionality.
Bump pycloudlib version.
-rw-r--r-- | integration-requirements.txt | 2 | ||||
-rw-r--r-- | tests/integration_tests/bugs/test_lp1835584.py | 11 | ||||
-rw-r--r-- | tests/integration_tests/clouds.py | 33 | ||||
-rw-r--r-- | tests/integration_tests/conftest.py | 83 | ||||
-rw-r--r-- | tox.ini | 1 |
5 files changed, 102 insertions, 28 deletions
diff --git a/integration-requirements.txt b/integration-requirements.txt index cd10c540..681456a6 100644 --- a/integration-requirements.txt +++ b/integration-requirements.txt @@ -1,5 +1,5 @@ # PyPI requirements for cloud-init integration testing # https://cloudinit.readthedocs.io/en/latest/topics/integration_tests.html # -pycloudlib @ git+https://github.com/canonical/pycloudlib.git@6eee33c9c4f630bc9c13b6e48f9ab36e7fb79ca6 +pycloudlib @ git+https://github.com/canonical/pycloudlib.git@f9293647e44dff6e98996e6ca83376477139eb5e pytest diff --git a/tests/integration_tests/bugs/test_lp1835584.py b/tests/integration_tests/bugs/test_lp1835584.py index 8ecb1246..4d669ee2 100644 --- a/tests/integration_tests/bugs/test_lp1835584.py +++ b/tests/integration_tests/bugs/test_lp1835584.py @@ -28,15 +28,12 @@ https://bugs.launchpad.net/cloud-init/+bug/1835584 import re import pytest +from pycloudlib.cloud import ImageType from tests.integration_tests.clouds import ImageSpecification, IntegrationCloud from tests.integration_tests.conftest import get_validated_source from tests.integration_tests.instances import IntegrationInstance -IMG_AZURE_UBUNTU_PRO_FIPS_BIONIC = ( - "Canonical:0001-com-ubuntu-pro-bionic-fips:pro-fips-18_04:18.04.202010201" -) - def _check_iid_insensitive_across_kernel_upgrade( instance: IntegrationInstance, @@ -71,6 +68,7 @@ def _check_iid_insensitive_across_kernel_upgrade( @pytest.mark.azure +@pytest.mark.integration_cloud_args(image_type=ImageType.PRO_FIPS) def test_azure_kernel_upgrade_case_insensitive_uuid( session_cloud: IntegrationCloud, ): @@ -86,10 +84,7 @@ def test_azure_kernel_upgrade_case_insensitive_uuid( pytest.skip( "Provide CLOUD_INIT_SOURCE to install expected working cloud-init" ) - image_id = IMG_AZURE_UBUNTU_PRO_FIPS_BIONIC - with session_cloud.launch( - launch_kwargs={"image_id": image_id} - ) as instance: + with session_cloud.launch() as instance: # We can't use setup_image fixture here because we want to avoid # taking a snapshot or cleaning the booted machine after cloud-init # upgrade. diff --git a/tests/integration_tests/clouds.py b/tests/integration_tests/clouds.py index eb9bd9cc..6b959ade 100644 --- a/tests/integration_tests/clouds.py +++ b/tests/integration_tests/clouds.py @@ -18,7 +18,7 @@ from pycloudlib import ( LXDVirtualMachine, Openstack, ) -from pycloudlib.cloud import BaseCloud +from pycloudlib.cloud import BaseCloud, ImageType from pycloudlib.lxd.cloud import _BaseLXD from pycloudlib.lxd.instance import BaseInstance, LXDInstance @@ -94,7 +94,12 @@ class IntegrationCloud(ABC): datasource: str cloud_instance: BaseCloud - def __init__(self, settings=integration_settings): + def __init__( + self, + image_type: ImageType = ImageType.GENERIC, + settings=integration_settings, + ): + self._image_type = image_type self.settings = settings self.cloud_instance: BaseCloud = self._get_cloud_instance() self.initial_image_id = self._get_initial_image() @@ -119,11 +124,12 @@ class IntegrationCloud(ABC): def _get_cloud_instance(self): raise NotImplementedError - def _get_initial_image(self): + def _get_initial_image(self, **kwargs) -> str: image = ImageSpecification.from_os_image() try: - return self.cloud_instance.daily_image(image.image_id) - except (ValueError, IndexError): + return self.cloud_instance.daily_image(image.image_id, **kwargs) + except (ValueError, IndexError) as ex: + log.debug("Exception while executing `daily_image`: %s", ex) return image.image_id def _perform_launch(self, launch_kwargs, **kwargs) -> BaseInstance: @@ -208,6 +214,11 @@ class Ec2Cloud(IntegrationCloud): def _get_cloud_instance(self): return EC2(tag="ec2-integration-test") + def _get_initial_image(self, **kwargs) -> str: + return super()._get_initial_image( + image_type=self._image_type, **kwargs + ) + def _perform_launch(self, launch_kwargs, **kwargs): """Use a dual-stack VPC for cloud-init integration testing.""" if "vpc" not in launch_kwargs: @@ -234,6 +245,11 @@ class GceCloud(IntegrationCloud): tag="gce-integration-test", ) + def _get_initial_image(self, **kwargs) -> str: + return super()._get_initial_image( + image_type=self._image_type, **kwargs + ) + class AzureCloud(IntegrationCloud): datasource = "azure" @@ -242,6 +258,11 @@ class AzureCloud(IntegrationCloud): def _get_cloud_instance(self): return Azure(tag="azure-integration-test") + def _get_initial_image(self, **kwargs) -> str: + return super()._get_initial_image( + image_type=self._image_type, **kwargs + ) + def destroy(self): if self.settings.KEEP_INSTANCE: log.info( @@ -366,7 +387,7 @@ class OpenstackCloud(IntegrationCloud): tag="openstack-integration-test", ) - def _get_initial_image(self): + def _get_initial_image(self, **kwargs): image = ImageSpecification.from_os_image() try: UUID(image.image_id) diff --git a/tests/integration_tests/conftest.py b/tests/integration_tests/conftest.py index a90a5d49..580fd6ad 100644 --- a/tests/integration_tests/conftest.py +++ b/tests/integration_tests/conftest.py @@ -7,7 +7,7 @@ import sys from contextlib import contextmanager from pathlib import Path from tarfile import TarFile -from typing import Dict, Type +from typing import Dict, Iterator, Type import pytest from pycloudlib.lxd.instance import LXDInstance @@ -92,8 +92,10 @@ def disable_subp_usage(request): pass -@pytest.fixture(scope="session") -def session_cloud(): +@contextmanager +def _session_cloud( + request: pytest.FixtureRequest, +) -> Iterator[IntegrationCloud]: if integration_settings.PLATFORM not in platforms.keys(): raise ValueError( "{} is an invalid PLATFORM specified in settings. " @@ -102,7 +104,17 @@ def session_cloud(): ) ) - cloud = platforms[integration_settings.PLATFORM]() + integration_cloud_marker = request.node.get_closest_marker( + "integration_cloud_args" + ) + cloud_args = [] + cloud_kwargs = {} + if integration_cloud_marker: + cloud_args = integration_cloud_marker.args + cloud_kwargs = integration_cloud_marker.kwargs + cloud = platforms[integration_settings.PLATFORM]( + *cloud_args, **cloud_kwargs + ) cloud.emit_settings_to_log() yield cloud @@ -110,6 +122,30 @@ def session_cloud(): cloud.destroy() +@pytest.fixture +def session_cloud( + request: pytest.FixtureRequest, +) -> Iterator[IntegrationCloud]: + with _session_cloud(request) as cloud: + yield cloud + + +@pytest.fixture(scope="module") +def module_session_cloud( + request: pytest.FixtureRequest, +) -> Iterator[IntegrationCloud]: + with _session_cloud(request) as cloud: + yield cloud + + +@pytest.fixture(scope="class") +def class_session_cloud( + request: pytest.FixtureRequest, +) -> Iterator[IntegrationCloud]: + with _session_cloud(request) as cloud: + yield cloud + + def get_validated_source( session_cloud: IntegrationCloud, source=integration_settings.CLOUD_INIT_SOURCE, @@ -135,13 +171,11 @@ def get_validated_source( ) -@pytest.fixture(scope="session") -def setup_image(session_cloud: IntegrationCloud, request): +def _setup_image(session_cloud: IntegrationCloud, request): """Setup the target environment with the correct version of cloud-init. So we can launch instances / run tests with the correct image """ - source = get_validated_source(session_cloud) if not source.installs_new_version(): return @@ -159,6 +193,21 @@ def setup_image(session_cloud: IntegrationCloud, request): request.addfinalizer(session_cloud.delete_snapshot) +@pytest.fixture +def setup_image(session_cloud: IntegrationCloud, request): + _setup_image(session_cloud, request) + + +@pytest.fixture(scope="module") +def module_setup_image(module_session_cloud: IntegrationCloud, request): + _setup_image(module_session_cloud, request) + + +@pytest.fixture(scope="class") +def class_setup_image(class_session_cloud: IntegrationCloud, request): + _setup_image(class_session_cloud, request) + + def _collect_logs( instance: IntegrationInstance, node_id: str, test_failed: bool ): @@ -218,7 +267,9 @@ def _collect_logs( @contextmanager -def _client(request, fixture_utils, session_cloud: IntegrationCloud): +def _client( + request, fixture_utils, session_cloud: IntegrationCloud +) -> Iterator[IntegrationInstance]: """Fixture implementation for the client fixtures. Launch the dynamic IntegrationClient instance using any provided @@ -268,23 +319,29 @@ def _client(request, fixture_utils, session_cloud: IntegrationCloud): @pytest.fixture -def client(request, fixture_utils, session_cloud, setup_image): +def client( + request, fixture_utils, session_cloud, setup_image +) -> Iterator[IntegrationInstance]: """Provide a client that runs for every test.""" with _client(request, fixture_utils, session_cloud) as client: yield client @pytest.fixture(scope="module") -def module_client(request, fixture_utils, session_cloud, setup_image): +def module_client( + request, fixture_utils, module_session_cloud, module_setup_image +) -> Iterator[IntegrationInstance]: """Provide a client that runs once per module.""" - with _client(request, fixture_utils, session_cloud) as client: + with _client(request, fixture_utils, module_session_cloud) as client: yield client @pytest.fixture(scope="class") -def class_client(request, fixture_utils, session_cloud, setup_image): +def class_client( + request, fixture_utils, class_session_cloud, class_setup_image +) -> Iterator[IntegrationInstance]: """Provide a client that runs once per class.""" - with _client(request, fixture_utils, session_cloud) as client: + with _client(request, fixture_utils, class_session_cloud) as client: yield client @@ -308,6 +308,7 @@ markers = gce: test will only run on GCE platform hypothesis_slow: hypothesis test too slow to run as unit test instance_name: the name to be used for the test instance + integration_cloud_args: args for IntegrationCloud customization is_iscsi: whether is an instance has iscsi net cfg or not lxd_config_dict: set the config_dict passed on LXD instance creation lxd_container: test will only run in LXD container |