summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberto Contreras <alberto.contreras@canonical.com>2022-08-02 15:45:45 +0200
committerGitHub <noreply@github.com>2022-08-02 07:45:45 -0600
commitbccf9a5791d83b2cf679a9c08447f3e3bc73b541 (patch)
tree76a7d839666b0f12e4946372425339467bc4a6ec
parentd7ce6bf096d2431cbb6bc736cc561fef78170d7d (diff)
downloadcloud-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.txt2
-rw-r--r--tests/integration_tests/bugs/test_lp1835584.py11
-rw-r--r--tests/integration_tests/clouds.py33
-rw-r--r--tests/integration_tests/conftest.py83
-rw-r--r--tox.ini1
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
diff --git a/tox.ini b/tox.ini
index 1fcd26bc..78e370eb 100644
--- a/tox.ini
+++ b/tox.ini
@@ -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