From 75940d46a487b549f408ac28de1684a94e8bf47e Mon Sep 17 00:00:00 2001 From: Adam Dyess Date: Fri, 8 Dec 2023 16:48:47 -0600 Subject: [PATCH] test integration tests with multiple charm builds --- .github/workflows/integration_test.yaml | 2 +- tests/integration/conftest.py | 59 ++++++++++++++++--------- tox.ini | 2 +- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/.github/workflows/integration_test.yaml b/.github/workflows/integration_test.yaml index 8a549cc4..ec74a014 100644 --- a/.github/workflows/integration_test.yaml +++ b/.github/workflows/integration_test.yaml @@ -5,7 +5,7 @@ on: jobs: integration-tests: - uses: canonical/operator-workflows/.github/workflows/integration_test.yaml@main + uses: addyess/operator-workflows/.github/workflows/integration_test.yaml@main secrets: inherit with: provider: lxd diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 6da43819..e7022244 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -4,24 +4,30 @@ """Fixtures for charm tests.""" import asyncio import contextlib +import logging from dataclasses import asdict, dataclass from itertools import chain from pathlib import Path -from typing import Optional +from typing import List, Optional import pytest import pytest_asyncio import yaml from pytest_operator.plugin import OpsTest +log = logging.getLogger(__name__) + def pytest_addoption(parser: pytest.Parser): """Parse additional pytest options. + --charm-file can be called multiple times for each + supplied charm + Args: parser: Pytest parser. """ - parser.addoption("--charm-file", action="store") + parser.addoption("--charm-file", dest="charm_files", action="append") @dataclass @@ -90,8 +96,8 @@ def _craft_resource(self, _name: str, resource: dict) -> Optional[str]: return oci_image return None - async def resolve(self) -> Path: - """Build the charm with ops_test. + async def resolve(self, charm_files: List[str]) -> Path: + """Build or find the charm with ops_test. Return: path to charm file @@ -101,13 +107,21 @@ async def resolve(self) -> Path: """ if self._charmfile is None: try: - charm_name = f"{self.app_name}*.charm" - potentials = chain(*(path.glob(charm_name) for path in (Path(), self.path))) - self._charmfile, *_ = filter(None, potentials) + header = f"{self.app_name}_" + charm_name = header + "*.charm" + print(charm_files) + potentials = chain( + map(Path, charm_files), # Look in pytest arguments + Path().glob(charm_name), # Look in top-level path + self.path.glob(charm_name), # Look in charm-level path + ) + self._charmfile, *_ = filter(lambda s: s.name.startswith(header), potentials) + log.info("For %s found charmfile %s", self.app_name, self._charmfile) except ValueError: + log.info("For %s build charmfile", self.app_name) self._charmfile = await self.ops_test.build_charm(self.path) if self._charmfile is None: - raise FileNotFoundError(f"{self.app_name}*.charm not found") + raise FileNotFoundError(f"{self.app_name}_*.charm not found") return self._charmfile.resolve() @@ -141,19 +155,20 @@ async def deploy_model( config=config, ) with ops_test.model_context(model_name) as the_model: - await asyncio.gather( - *( - the_model.deploy(**asdict(charm)) - for charm in deploy_args - if charm.application_name not in the_model.applications - ), - the_model.wait_for_idle( - apps=[n.application_name for n in deploy_args], - status="active", - raise_on_blocked=True, - timeout=15 * 60, - ), - ) + async with ops_test.fast_forward(): + await asyncio.gather( + *( + the_model.deploy(**asdict(charm)) + for charm in deploy_args + if charm.application_name not in the_model.applications + ), + the_model.wait_for_idle( + apps=[n.application_name for n in deploy_args], + status="active", + raise_on_blocked=True, + timeout=15 * 60, + ), + ) yield the_model @@ -163,7 +178,7 @@ async def kubernetes_cluster(request: pytest.FixtureRequest, ops_test: OpsTest): model = "main" charm_names = ("k8s", "k8s-worker") charms = [Charm(ops_test, Path("charms") / p) for p in charm_names] - charm_files = await asyncio.gather(*[charm.resolve() for charm in charms]) + charm_files = await asyncio.gather(*[charm.resolve(request.config.option.charm_files) for charm in charms]) deployments = [ CharmDeploymentArgs( entity_url=str(path), diff --git a/tox.ini b/tox.ini index a2e9e58b..8a1738e2 100644 --- a/tox.ini +++ b/tox.ini @@ -90,7 +90,7 @@ deps = pytest-asyncio pytest-operator commands = - pytest -v --tb native --ignore={toxinidir}/charms --log-cli-level=INFO -s {posargs} + pytest -v --tb native --log-cli-level=INFO -s {toxinidir}/tests/integration {posargs} [testenv:src-docs] allowlist_externals=sh