From 332cdb61fdc87e804a7a134f90fdbd938cc7712b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinclert=20P=C3=A9rez?= Date: Mon, 16 Dec 2024 10:47:37 +0100 Subject: [PATCH] [DPE-5588] Check against invalid arch (#563) --- src/charm.py | 7 +++- tests/integration/helpers.py | 17 ++++++++- tests/integration/test_architecture.py | 53 ++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 tests/integration/test_architecture.py diff --git a/src/charm.py b/src/charm.py index 810e22f8b..362dc9b30 100755 --- a/src/charm.py +++ b/src/charm.py @@ -4,6 +4,12 @@ """Charmed Machine Operator for MySQL.""" +from charms.mysql.v0.architecture import WrongArchitectureWarningCharm, is_wrong_architecture +from ops.main import main + +if is_wrong_architecture() and __name__ == "__main__": + main(WrongArchitectureWarningCharm) + import logging import random import socket @@ -55,7 +61,6 @@ Unit, WaitingStatus, ) -from ops.main import main from tenacity import ( RetryError, Retrying, diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index 4d239c655..1dac0cf15 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -8,7 +8,8 @@ import string import subprocess import tempfile -from typing import Dict, List, Optional, Set +from pathlib import Path +from typing import Dict, List, Optional, Set, Union import juju.unit import yaml @@ -979,3 +980,17 @@ def get_unit_by_index(app_name: str, units: list, index: int): for unit in units: if unit.name == f"{app_name}/{index}": return unit + + +async def get_charm(charm_path: Union[str, Path], architecture: str, bases_index: int) -> Path: + """Fetches packed charm from CI runner without checking for architecture.""" + charm_path = Path(charm_path) + charmcraft_yaml = yaml.safe_load((charm_path / "charmcraft.yaml").read_text()) + assert charmcraft_yaml["type"] == "charm" + + base = charmcraft_yaml["bases"][bases_index] + build_on = base.get("build-on", [base])[0] + version = build_on["channel"] + packed_charms = list(charm_path.glob(f"*{version}-{architecture}.charm")) + + return packed_charms[0].resolve(strict=True) diff --git a/tests/integration/test_architecture.py b/tests/integration/test_architecture.py new file mode 100644 index 000000000..abadeb0fc --- /dev/null +++ b/tests/integration/test_architecture.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# Copyright 2024 Canonical Ltd. +# See LICENSE file for licensing details. + +import pytest +from pytest_operator.plugin import OpsTest + +from . import markers +from .helpers import get_charm + +MYSQL_APP_NAME = "mysql" + + +@pytest.mark.group(1) +@markers.amd64_only +async def test_arm_charm_on_amd_host(ops_test: OpsTest) -> None: + """Tries deploying an arm64 charm on amd64 host.""" + charm = await get_charm(".", "arm64", 1) + + await ops_test.model.deploy( + charm, + application_name=MYSQL_APP_NAME, + num_units=1, + config={"profile": "testing"}, + base="ubuntu@22.04", + ) + + await ops_test.model.wait_for_idle( + apps=[MYSQL_APP_NAME], + status="error", + raise_on_error=False, + ) + + +@pytest.mark.group(1) +@markers.arm64_only +async def test_amd_charm_on_arm_host(ops_test: OpsTest) -> None: + """Tries deploying an amd64 charm on arm64 host.""" + charm = await get_charm(".", "amd64", 0) + + await ops_test.model.deploy( + charm, + application_name=MYSQL_APP_NAME, + num_units=1, + config={"profile": "testing"}, + base="ubuntu@22.04", + ) + + await ops_test.model.wait_for_idle( + apps=[MYSQL_APP_NAME], + status="error", + raise_on_error=False, + )