diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py new file mode 100644 index 0000000000..37df4e6327 --- /dev/null +++ b/tests/integration/conftest.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +import pytest + + +@pytest.fixture +def charm(): + # Return str instead of pathlib.Path since python-libjuju's model.deploy(), juju deploy, and + # juju bundle files expect local charms to begin with `./` or `/` to distinguish them from + # Charmhub charms. + return "./opensearch_ubuntu@22.04-amd64.charm" diff --git a/tests/integration/ha/conftest.py b/tests/integration/ha/conftest.py index 40ad315786..0e45df4e14 100644 --- a/tests/integration/ha/conftest.py +++ b/tests/integration/ha/conftest.py @@ -14,14 +14,6 @@ logger = logging.getLogger(__name__) -@pytest.fixture -def charm(): - # Return str instead of pathlib.Path since python-libjuju's model.deploy(), juju deploy, and - # juju bundle files expect local charms to begin with `./` or `/` to distinguish them from - # Charmhub charms. - return "./opensearch_ubuntu@22.04-amd64.charm" - - @pytest.fixture(scope="function") async def reset_restart_delay(ops_test: OpsTest): """Resets service file delay on all units.""" diff --git a/tests/integration/ha/test_backups.py b/tests/integration/ha/test_backups.py index 39a54f6a3a..b48a535971 100644 --- a/tests/integration/ha/test_backups.py +++ b/tests/integration/ha/test_backups.py @@ -17,6 +17,7 @@ import asyncio import logging +import os import random import string import subprocess @@ -328,10 +329,28 @@ async def test_small_deployment_build_and_deploy( await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), - ops_test.model.deploy(backup_integrator, channel=backup_integrator_channel), - ops_test.model.deploy(charm, num_units=3, series=SERIES, config=CONFIG_OPTS), + ops_test.model.deploy( + backup_integrator, + channel=backup_integrator_channel, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), + ops_test.model.deploy( + charm, + num_units=3, + series=SERIES, + config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), + ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, ) # Relate it to OpenSearch to set up TLS. @@ -386,15 +405,23 @@ async def test_large_deployment_build_and_deploy( await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=tls_config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=tls_config, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), + ops_test.model.deploy( + backup_integrator, + channel=backup_integrator_channel, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), - ops_test.model.deploy(backup_integrator, channel=backup_integrator_channel), ops_test.model.deploy( charm, application_name="main", num_units=1, series=SERIES, config=main_orchestrator_conf | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( charm, @@ -402,6 +429,7 @@ async def test_large_deployment_build_and_deploy( num_units=2, series=SERIES, config=failover_orchestrator_conf | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( charm, @@ -409,9 +437,23 @@ async def test_large_deployment_build_and_deploy( num_units=1, series=SERIES, config=data_hot_conf | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} main", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} failover", + shell=True, + ) + # Large deployment setup await ops_test.model.integrate("main:peer-cluster-orchestrator", "failover:peer-cluster") await ops_test.model.integrate("main:peer-cluster-orchestrator", f"{APP_NAME}:peer-cluster") @@ -694,10 +736,28 @@ async def test_restore_to_new_cluster( await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), + ops_test.model.deploy( + backup_integrator, + channel=backup_integrator_channel, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), + ops_test.model.deploy( + charm, + num_units=3, + series=SERIES, + config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), - ops_test.model.deploy(backup_integrator, channel=backup_integrator_channel), - ops_test.model.deploy(charm, num_units=3, series=SERIES, config=CONFIG_OPTS), + ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, ) # Relate it to OpenSearch to set up TLS. @@ -800,10 +860,28 @@ async def test_build_deploy_and_test_status(ops_test: OpsTest, charm) -> None: config = {"ca-common-name": "CN_CA"} await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), - ops_test.model.deploy(S3_INTEGRATOR, channel=S3_INTEGRATOR_CHANNEL), - ops_test.model.deploy(charm, num_units=3, series=SERIES, config=CONFIG_OPTS), + ops_test.model.deploy( + S3_INTEGRATOR, + channel=S3_INTEGRATOR_CHANNEL, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), + ops_test.model.deploy( + charm, + num_units=3, + series=SERIES, + config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), + ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, ) # Relate it to OpenSearch to set up TLS. diff --git a/tests/integration/ha/test_ha.py b/tests/integration/ha/test_ha.py index 5b22fcfad6..2317c9eb0f 100644 --- a/tests/integration/ha/test_ha.py +++ b/tests/integration/ha/test_ha.py @@ -4,6 +4,8 @@ import asyncio import logging +import os +import subprocess import time import pytest @@ -51,22 +53,36 @@ @pytest.mark.group(1) @pytest.mark.abort_on_fail @pytest.mark.skip_if_deployed -async def test_build_and_deploy(ops_test: OpsTest) -> None: +async def test_build_and_deploy(ops_test: OpsTest, charm) -> None: """Build and deploy one unit of OpenSearch.""" # it is possible for users to provide their own cluster for HA testing. # Hence, check if there is a pre-existing cluster. if await app_name(ops_test): return - my_charm = await ops_test.build_charm(".") await ops_test.model.set_config(MODEL_CONFIG) # Deploy TLS Certificates operator. config = {"ca-common-name": "CN_CA"} await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), - ops_test.model.deploy(my_charm, num_units=NUM_HA_UNITS, series=SERIES, config=CONFIG_OPTS), + ops_test.model.deploy( + charm, + application_name="opensearch", + num_units=NUM_HA_UNITS, + series=SERIES, + config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), + ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} opensearch", + shell=True, ) # Relate it to OpenSearch to set up TLS. diff --git a/tests/integration/ha/test_ha_multi_clusters.py b/tests/integration/ha/test_ha_multi_clusters.py index 12a3a94c3e..4b938d5263 100644 --- a/tests/integration/ha/test_ha_multi_clusters.py +++ b/tests/integration/ha/test_ha_multi_clusters.py @@ -4,6 +4,8 @@ import asyncio import logging +import os +import subprocess import pytest from pytest_operator.plugin import OpsTest @@ -43,9 +45,23 @@ async def test_build_and_deploy(ops_test: OpsTest, charm) -> None: config = {"ca-common-name": "CN_CA"} await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), - ops_test.model.deploy(charm, num_units=2, series=SERIES, config=CONFIG_OPTS), + ops_test.model.deploy( + charm, + num_units=2, + series=SERIES, + config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), + ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, ) # Relate it to OpenSearch to set up TLS. @@ -75,7 +91,11 @@ async def test_multi_clusters_db_isolation( # deploy new cluster await ops_test.model.deploy( - charm, num_units=1, application_name=SECOND_APP_NAME, config=CONFIG_OPTS + charm, + num_units=1, + application_name=SECOND_APP_NAME, + config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ) await ops_test.model.integrate(SECOND_APP_NAME, TLS_CERTIFICATES_APP_NAME) diff --git a/tests/integration/ha/test_ha_networking.py b/tests/integration/ha/test_ha_networking.py index 21abaa96e2..791ddb41e7 100644 --- a/tests/integration/ha/test_ha_networking.py +++ b/tests/integration/ha/test_ha_networking.py @@ -4,6 +4,8 @@ import asyncio import logging +import os +import subprocess import pytest from pytest_operator.plugin import OpsTest @@ -27,6 +29,7 @@ SERIES, app_name, check_cluster_formation_successful, + filter_cloud, get_application_unit_ids_hostnames, get_application_unit_ids_ips, get_application_unit_names, @@ -42,6 +45,7 @@ logger = logging.getLogger(__name__) +@filter_cloud(["lxd"]) @pytest.mark.runner(["self-hosted", "linux", "X64", "jammy"]) @pytest.mark.group(1) @pytest.mark.abort_on_fail @@ -58,9 +62,23 @@ async def test_build_and_deploy(ops_test: OpsTest, charm) -> None: config = {"ca-common-name": "CN_CA"} await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), - ops_test.model.deploy(charm, num_units=3, series=SERIES, config=CONFIG_OPTS), + ops_test.model.deploy( + charm, + num_units=3, + series=SERIES, + config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), + ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, ) # Relate it to OpenSearch to set up TLS. @@ -74,6 +92,7 @@ async def test_build_and_deploy(ops_test: OpsTest, charm) -> None: assert len(ops_test.model.applications[APP_NAME].units) == 3 +@filter_cloud(["lxd"]) @pytest.mark.runner(["self-hosted", "linux", "X64", "jammy"]) @pytest.mark.group(1) @pytest.mark.abort_on_fail @@ -177,6 +196,7 @@ async def test_full_network_cut_with_ip_change_node_with_elected_cm( await assert_continuous_writes_consistency(ops_test, c_writes, [app]) +@filter_cloud(["lxd"]) @pytest.mark.runner(["self-hosted", "linux", "X64", "jammy"]) @pytest.mark.group(1) @pytest.mark.abort_on_fail @@ -296,6 +316,7 @@ async def test_full_network_cut_with_ip_change_node_with_primary_shard( await assert_continuous_writes_consistency(ops_test, c_writes, [app]) +@filter_cloud(["lxd"]) @pytest.mark.runner(["self-hosted", "linux", "X64", "jammy"]) @pytest.mark.group(1) @pytest.mark.abort_on_fail @@ -385,6 +406,7 @@ async def test_full_network_cut_without_ip_change_node_with_elected_cm( await assert_continuous_writes_consistency(ops_test, c_writes, [app]) +@filter_cloud(["lxd"]) @pytest.mark.runner(["self-hosted", "linux", "X64", "jammy"]) @pytest.mark.group(1) @pytest.mark.abort_on_fail diff --git a/tests/integration/ha/test_horizontal_scaling.py b/tests/integration/ha/test_horizontal_scaling.py index dd5bd11fb7..00e640fd11 100644 --- a/tests/integration/ha/test_horizontal_scaling.py +++ b/tests/integration/ha/test_horizontal_scaling.py @@ -4,6 +4,8 @@ import asyncio import logging +import os +import subprocess import time import pytest @@ -45,22 +47,35 @@ @pytest.mark.group(1) @pytest.mark.abort_on_fail @pytest.mark.skip_if_deployed -async def test_build_and_deploy(ops_test: OpsTest) -> None: +async def test_build_and_deploy(ops_test: OpsTest, charm) -> None: """Build and deploy one unit of OpenSearch.""" # it is possible for users to provide their own cluster for HA testing. # Hence, check if there is a pre-existing cluster. if await app_name(ops_test): return - my_charm = await ops_test.build_charm(".") await ops_test.model.set_config(MODEL_CONFIG) # Deploy TLS Certificates operator. config = {"ca-common-name": "CN_CA"} await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), - ops_test.model.deploy(my_charm, num_units=1, series=SERIES, config=CONFIG_OPTS), + ops_test.model.deploy( + charm, + num_units=1, + series=SERIES, + config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), + ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, ) # Relate it to OpenSearch to set up TLS. diff --git a/tests/integration/ha/test_large_deployments_cluster_manager_only_nodes.py b/tests/integration/ha/test_large_deployments_cluster_manager_only_nodes.py index 05f435663a..5c8184cce3 100644 --- a/tests/integration/ha/test_large_deployments_cluster_manager_only_nodes.py +++ b/tests/integration/ha/test_large_deployments_cluster_manager_only_nodes.py @@ -4,6 +4,8 @@ import asyncio import logging +import os +import subprocess import time import pytest @@ -35,44 +37,62 @@ @pytest.mark.group(1) @pytest.mark.abort_on_fail @pytest.mark.skip_if_deployed -async def test_build_and_deploy(ops_test: OpsTest) -> None: +async def test_build_and_deploy(ops_test: OpsTest, charm) -> None: """Build and deploy one unit of OpenSearch.""" # it is possible for users to provide their own cluster for HA testing. # Hence, check if there is a pre-existing cluster. - my_charm = await ops_test.build_charm(".") await ops_test.model.set_config(MODEL_CONFIG) # Deploy TLS Certificates operator. config = {"ca-common-name": "CN_CA"} await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=MAIN_APP, num_units=1, series=SERIES, config={"cluster_name": CLUSTER_NAME, "roles": "cluster_manager"} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=FAILOVER_APP, num_units=1, series=SERIES, config={"cluster_name": CLUSTER_NAME, "init_hold": True, "roles": "cluster_manager"} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=DATA_APP, num_units=2, series=SERIES, config={"cluster_name": CLUSTER_NAME, "init_hold": True, "roles": "data"} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {MAIN_APP}", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {FAILOVER_APP}", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {DATA_APP}", + shell=True, + ) + # wait until the TLS operator is ready await wait_until( ops_test, diff --git a/tests/integration/ha/test_large_deployments_inherit_cluster_name.py b/tests/integration/ha/test_large_deployments_inherit_cluster_name.py index 0e8fcd3ea1..7701637ced 100644 --- a/tests/integration/ha/test_large_deployments_inherit_cluster_name.py +++ b/tests/integration/ha/test_large_deployments_inherit_cluster_name.py @@ -4,6 +4,8 @@ import asyncio import logging +import os +import subprocess import time import pytest @@ -47,35 +49,46 @@ @pytest.mark.group("Cluster name not autogenerated") @pytest.mark.abort_on_fail @pytest.mark.skip_if_deployed -async def test_build_and_deploy_not_autogen(ops_test: OpsTest) -> None: +async def test_build_and_deploy_not_autogen(ops_test: OpsTest, charm) -> None: """Build and deploy one unit of OpenSearch without autogenerated cluster name.""" - # it is possible for users to provide their own cluster for HA testing. - # Hence, check if there is a pre-existing cluster. - my_charm = await ops_test.build_charm(".") await ops_test.model.set_config(MODEL_CONFIG) # Deploy TLS Certificates operator. config = {"ca-common-name": "CN_CA"} await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=MAIN_APP_NOT_AUTOGEN, num_units=1, series=SERIES, config={"cluster_name": CLUSTER_NAME} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=INVALID_FAILOVER_APP, num_units=1, series=SERIES, config={"init_hold": True, "roles": "cluster_manager"} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {MAIN_APP_NOT_AUTOGEN}", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {INVALID_FAILOVER_APP}", + shell=True, + ) + # wait until the TLS operator is ready await wait_until( ops_test, @@ -115,42 +128,58 @@ async def test_build_and_deploy_not_autogen(ops_test: OpsTest) -> None: @pytest.mark.group("Cluster name autogenerated") @pytest.mark.abort_on_fail @pytest.mark.skip_if_deployed -async def test_build_and_deploy_autogen(ops_test: OpsTest) -> None: +async def test_build_and_deploy_autogen(ops_test: OpsTest, charm) -> None: """Build and deploy one unit of OpenSearch with autogenerated cluster name.""" - # it is possible for users to provide their own cluster for HA testing. - # Hence, check if there is a pre-existing cluster. - my_charm = await ops_test.build_charm(".") await ops_test.model.set_config(MODEL_CONFIG) # Deploy TLS Certificates operator. config = {"ca-common-name": "CN_CA"} await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=MAIN_APP_AUTOGEN, num_units=1, series=SERIES, config={"roles": "cluster_manager"} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=FAILOVER_APP_AUTOGEN, num_units=1, series=SERIES, config={"init_hold": True, "roles": "cluster_manager"} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=DATA_APP_AUTOGEN, num_units=2, series=SERIES, config={"init_hold": True, "roles": "data"} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {MAIN_APP_AUTOGEN}", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {FAILOVER_APP_AUTOGEN}", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {DATA_APP_AUTOGEN}", + shell=True, + ) + # wait until the TLS operator is ready await wait_until( ops_test, diff --git a/tests/integration/ha/test_large_deployments_relations.py b/tests/integration/ha/test_large_deployments_relations.py index d80c220f3f..3063e67801 100644 --- a/tests/integration/ha/test_large_deployments_relations.py +++ b/tests/integration/ha/test_large_deployments_relations.py @@ -4,6 +4,8 @@ import asyncio import logging +import os +import subprocess import time import pytest @@ -37,51 +39,74 @@ @pytest.mark.group(1) @pytest.mark.abort_on_fail @pytest.mark.skip_if_deployed -async def test_build_and_deploy(ops_test: OpsTest) -> None: +async def test_build_and_deploy(ops_test: OpsTest, charm) -> None: """Build and deploy one unit of OpenSearch.""" # it is possible for users to provide their own cluster for HA testing. # Hence, check if there is a pre-existing cluster. - my_charm = await ops_test.build_charm(".") await ops_test.model.set_config(MODEL_CONFIG) # Deploy TLS Certificates operator. config = {"ca-common-name": "CN_CA"} await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=MAIN_APP, num_units=3, series=SERIES, config={"cluster_name": CLUSTER_NAME} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=FAILOVER_APP, num_units=3, series=SERIES, config={"cluster_name": CLUSTER_NAME, "init_hold": True} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=DATA_APP, num_units=2, series=SERIES, config={"cluster_name": CLUSTER_NAME, "init_hold": True, "roles": "data.hot,ml"} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=INVALID_APP, num_units=1, series=SERIES, config={"cluster_name": INVALID_CLUSTER_NAME, "init_hold": True, "roles": "data.cold"} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {MAIN_APP}", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {FAILOVER_APP}", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {DATA_APP}", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {INVALID_APP}", + shell=True, + ) + # wait until the TLS operator is ready await wait_until( ops_test, diff --git a/tests/integration/ha/test_roles_managements.py b/tests/integration/ha/test_roles_managements.py index 616ee78fc9..9683ad6111 100644 --- a/tests/integration/ha/test_roles_managements.py +++ b/tests/integration/ha/test_roles_managements.py @@ -4,6 +4,8 @@ import asyncio import logging +import os +import subprocess import pytest from charms.opensearch.v0.constants_charm import PClusterWrongNodesCountForQuorum @@ -33,22 +35,35 @@ @pytest.mark.group(1) @pytest.mark.abort_on_fail @pytest.mark.skip_if_deployed -async def test_build_and_deploy(ops_test: OpsTest) -> None: +async def test_build_and_deploy(ops_test: OpsTest, charm) -> None: """Build and deploy one unit of OpenSearch.""" # it is possible for users to provide their own cluster for HA testing. # Hence, check if there is a pre-existing cluster. if await app_name(ops_test): return - my_charm = await ops_test.build_charm(".") await ops_test.model.set_config(MODEL_CONFIG) # Deploy TLS Certificates operator. config = {"ca-common-name": "CN_CA"} await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), - ops_test.model.deploy(my_charm, num_units=3, series=SERIES, config=CONFIG_OPTS), + ops_test.model.deploy( + charm, + num_units=3, + series=SERIES, + config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), + ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, ) # Relate it to OpenSearch to set up TLS. diff --git a/tests/integration/ha/test_scale_to_one_and_back.py b/tests/integration/ha/test_scale_to_one_and_back.py index 17302b9b7b..b90dc8f1ee 100644 --- a/tests/integration/ha/test_scale_to_one_and_back.py +++ b/tests/integration/ha/test_scale_to_one_and_back.py @@ -4,6 +4,8 @@ import asyncio import logging +import os +import subprocess import pytest from pytest_operator.plugin import OpsTest @@ -37,14 +39,13 @@ @pytest.mark.group(1) @pytest.mark.abort_on_fail @pytest.mark.skip_if_deployed -async def test_build_and_deploy(ops_test: OpsTest) -> None: +async def test_build_and_deploy(ops_test: OpsTest, charm) -> None: """Build and deploy one unit of OpenSearch.""" # it is possible for users to provide their own cluster for HA testing. # Hence, check if there is a pre-existing cluster. if await app_name(ops_test): return - my_charm = await ops_test.build_charm(".") # This test will manually issue update-status hooks, as we want to see the change in behavior # when applying `settle_voting` during start/stop and during update-status. MODEL_CONFIG["update-status-hook-interval"] = "360m" @@ -55,9 +56,23 @@ async def test_build_and_deploy(ops_test: OpsTest) -> None: config = {"ca-common-name": "CN_CA"} await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), - ops_test.model.deploy(my_charm, num_units=3, series=SERIES, config=CONFIG_OPTS), + ops_test.model.deploy( + charm, + num_units=3, + series=SERIES, + config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), + ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, ) # Relate it to OpenSearch to set up TLS. diff --git a/tests/integration/ha/test_storage.py b/tests/integration/ha/test_storage.py index 645035fe35..8b4dc33c34 100644 --- a/tests/integration/ha/test_storage.py +++ b/tests/integration/ha/test_storage.py @@ -4,6 +4,7 @@ import asyncio import logging +import os import subprocess import time @@ -34,14 +35,13 @@ @pytest.mark.runner(["self-hosted", "linux", "X64", "jammy", "xlarge"]) @pytest.mark.group(1) @pytest.mark.abort_on_fail -async def test_build_and_deploy(ops_test: OpsTest) -> None: +async def test_build_and_deploy(ops_test: OpsTest, charm) -> None: """Build and deploy one unit of OpenSearch.""" # it is possible for users to provide their own cluster for HA testing. # Hence, check if there is a pre-existing cluster. if await app_name(ops_test): return - my_charm = await ops_test.build_charm(".") await ops_test.model.set_config(MODEL_CONFIG) # this assumes the test is run on a lxd cloud await ops_test.model.create_storage_pool("opensearch-pool", "lxd") @@ -50,13 +50,26 @@ async def test_build_and_deploy(ops_test: OpsTest) -> None: config = {"ca-common-name": "CN_CA"} await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, num_units=1, series=SERIES, storage=storage, config=CONFIG_OPTS + charm, + num_units=1, + series=SERIES, + storage=storage, + config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, + ) + # Relate it to OpenSearch to set up TLS. await ops_test.model.integrate(APP_NAME, TLS_CERTIFICATES_APP_NAME) await wait_until( @@ -68,7 +81,7 @@ async def test_build_and_deploy(ops_test: OpsTest) -> None: idle_period=IDLE_PERIOD, wait_for_exact_units={ TLS_CERTIFICATES_APP_NAME: 1, - my_charm: 1, + charm: 1, }, ) assert len(ops_test.model.applications[APP_NAME].units) == 1 @@ -227,7 +240,7 @@ async def test_storage_reuse_after_scale_to_zero( @pytest.mark.group(1) @pytest.mark.abort_on_fail async def test_storage_reuse_in_new_cluster_after_app_removal( - ops_test: OpsTest, c_writes: ContinuousWrites, c_balanced_writes_runner + ops_test: OpsTest, charm, c_writes: ContinuousWrites, c_balanced_writes_runner ): """Check storage is reused and data accessible after removing app and deploying new cluster.""" app = (await app_name(ops_test)) or APP_NAME @@ -290,9 +303,8 @@ async def test_storage_reuse_in_new_cluster_after_app_removal( await ops_test.model.remove_application(app, block_until_done=True) # deploy new cluster, attaching the storage from the previous leader to the new leader - my_charm = await ops_test.build_charm(".") deploy_cluster_with_storage_cmd = ( - f"deploy {my_charm} --model={ops_test.model.info.name} --attach-storage={storage_ids[0]}" + f"deploy {charm} --model={ops_test.model.info.name} --attach-storage={storage_ids[0]}" " --config profile=testing" ) return_code, _, _ = await ops_test.juju(*deploy_cluster_with_storage_cmd.split()) diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index 0ec7c862af..a726e90a6e 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -1,8 +1,10 @@ #!/usr/bin/env python3 # Copyright 2024 Canonical Ltd. # See LICENSE file for licensing details. + import json import logging +import os import random import shlex import subprocess @@ -12,6 +14,7 @@ from types import SimpleNamespace from typing import Dict, List, Optional, Union +import pytest import requests import yaml from charms.opensearch.v0.helper_networking import is_reachable @@ -638,3 +641,20 @@ async def is_each_unit_restarted( return True except RetryError: return False + + +def filter_cloud(allowed_clouds: List[str]) -> "pytest.mark.skipif": + if not (chosen_cloud := os.environ.get("SUBSTRATE", "").lower()): + # Assume we are running in LXD if not specified + chosen_cloud = "lxd" + + if not allowed_clouds: + allowed_clouds = ["aws", "azure", "maas", "manual"] + + if chosen_cloud not in allowed_clouds: + logger.info(f"Skipping test as substrate:{chosen_cloud} not in {allowed_clouds}") + + return pytest.mark.skipif( + chosen_cloud not in allowed_clouds, + reason=f"Skipping test as substrate:{chosen_cloud} not in {allowed_clouds}", + ) diff --git a/tests/integration/plugins/test_plugins.py b/tests/integration/plugins/test_plugins.py index 9924c6e95b..7b1e209f8a 100644 --- a/tests/integration/plugins/test_plugins.py +++ b/tests/integration/plugins/test_plugins.py @@ -5,6 +5,7 @@ import asyncio import json import logging +import os import subprocess import pytest @@ -166,13 +167,13 @@ async def _wait_for_units( @pytest.mark.parametrize("deploy_type", SMALL_DEPLOYMENTS) @pytest.mark.abort_on_fail @pytest.mark.skip_if_deployed -async def test_build_and_deploy_small_deployment(ops_test: OpsTest, deploy_type: str) -> None: +async def test_build_and_deploy_small_deployment( + ops_test: OpsTest, charm, deploy_type: str +) -> None: """Build and deploy an OpenSearch cluster.""" if await app_name(ops_test): return - my_charm = await ops_test.build_charm(".") - model_conf = MODEL_CONFIG.copy() # Make it more regular as COS relation-broken really happens on the # next hook call in each opensearch unit. @@ -185,16 +186,25 @@ async def test_build_and_deploy_small_deployment(ops_test: OpsTest, deploy_type: config = {"ca-common-name": "CN_CA"} await asyncio.gather( ops_test.model.deploy( - my_charm, + charm, num_units=3, series=SERIES, config={"plugin_opensearch_knn": False} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, + ) + await wait_until( ops_test, apps=[APP_NAME], @@ -249,7 +259,12 @@ async def test_prometheus_exporter_enabled_by_default(ops_test, deploy_type: str @pytest.mark.parametrize("deploy_type", SMALL_DEPLOYMENTS) @pytest.mark.abort_on_fail async def test_small_deployments_prometheus_exporter_cos_relation(ops_test, deploy_type: str): - await ops_test.model.deploy(COS_APP_NAME, channel="edge", series=SERIES), + await ops_test.model.deploy( + COS_APP_NAME, + channel="edge", + series=SERIES, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), await ops_test.model.integrate(APP_NAME, COS_APP_NAME) await _wait_for_units(ops_test, deploy_type, wait_for_cos=True) @@ -277,14 +292,14 @@ async def test_small_deployments_prometheus_exporter_cos_relation(ops_test, depl @pytest.mark.parametrize("deploy_type", LARGE_DEPLOYMENTS) @pytest.mark.abort_on_fail @pytest.mark.skip_if_deployed -async def test_large_deployment_build_and_deploy(ops_test: OpsTest, deploy_type: str) -> None: +async def test_large_deployment_build_and_deploy( + ops_test: OpsTest, charm, deploy_type: str +) -> None: """Build and deploy a large deployment for OpenSearch.""" await ops_test.model.set_config(MODEL_CONFIG) # Deploy TLS Certificates operator. tls_config = {"ca-common-name": "CN_CA"} - my_charm = await ops_test.build_charm(".") - main_orchestrator_conf = { "cluster_name": "plugins-test", "init_hold": False, @@ -299,31 +314,50 @@ async def test_large_deployment_build_and_deploy(ops_test: OpsTest, deploy_type: await asyncio.gather( ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=tls_config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=tls_config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=MAIN_ORCHESTRATOR_NAME, num_units=1, series=SERIES, config=main_orchestrator_conf | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=FAILOVER_ORCHESTRATOR_NAME, num_units=2, series=SERIES, config=failover_orchestrator_conf | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=APP_NAME, num_units=1, series=SERIES, config=data_hot_conf | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {MAIN_ORCHESTRATOR_NAME}", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {FAILOVER_ORCHESTRATOR_NAME}", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, + ) + # Large deployment setup await ops_test.model.integrate("main:peer-cluster-orchestrator", "failover:peer-cluster") await ops_test.model.integrate("main:peer-cluster-orchestrator", f"{APP_NAME}:peer-cluster") @@ -344,7 +378,12 @@ async def test_large_deployment_build_and_deploy(ops_test: OpsTest, deploy_type: @pytest.mark.abort_on_fail async def test_large_deployment_prometheus_exporter_cos_relation(ops_test, deploy_type: str): # Check that the correct settings were successfully communicated to grafana-agent - await ops_test.model.deploy(COS_APP_NAME, channel="edge", series=SERIES), + await ops_test.model.deploy( + COS_APP_NAME, + channel="edge", + series=SERIES, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ), await ops_test.model.integrate(FAILOVER_ORCHESTRATOR_NAME, COS_APP_NAME) await ops_test.model.integrate(MAIN_ORCHESTRATOR_NAME, COS_APP_NAME) await ops_test.model.integrate(APP_NAME, COS_APP_NAME) diff --git a/tests/integration/relations/test_opensearch_provider.py b/tests/integration/relations/test_opensearch_provider.py index d9a7eefb24..b937ddfd36 100644 --- a/tests/integration/relations/test_opensearch_provider.py +++ b/tests/integration/relations/test_opensearch_provider.py @@ -4,7 +4,9 @@ import asyncio import json import logging +import os import re +import subprocess import time import pytest @@ -68,7 +70,10 @@ async def test_create_relation(ops_test: OpsTest, application_charm, opensearch_ config = {"ca-common-name": "CN_CA"} await ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ) await ops_test.model.set_config(new_model_conf) @@ -76,12 +81,14 @@ async def test_create_relation(ops_test: OpsTest, application_charm, opensearch_ ops_test.model.deploy( application_charm, application_name=CLIENT_APP_NAME, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( DASHBOARDS_APP_NAME, application_name=DASHBOARDS_APP_NAME, channel="2/edge", series=SERIES, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( opensearch_charm, @@ -89,8 +96,19 @@ async def test_create_relation(ops_test: OpsTest, application_charm, opensearch_ num_units=NUM_UNITS, series=SERIES, config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {DASHBOARDS_APP_NAME}", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {OPENSEARCH_APP_NAME}", + shell=True, + ) + await ops_test.model.integrate(OPENSEARCH_APP_NAME, TLS_CERTIFICATES_APP_NAME) await ops_test.model.wait_for_idle( apps=[TLS_CERTIFICATES_APP_NAME, OPENSEARCH_APP_NAME], status="active", timeout=1600 @@ -379,6 +397,7 @@ async def test_multiple_relations(ops_test: OpsTest, application_charm): application_charm, num_units=1, application_name=SECONDARY_CLIENT_APP_NAME, + constraints=os.environ.get("TEST_CONSTRAINTS"), ) # Relate the new application and wait for them to exchange connection data. diff --git a/tests/integration/test_charm.py b/tests/integration/test_charm.py index 88c3b0ba2a..d11d8b5c85 100644 --- a/tests/integration/test_charm.py +++ b/tests/integration/test_charm.py @@ -4,6 +4,7 @@ import asyncio import logging +import os import shlex import subprocess @@ -46,21 +47,30 @@ @pytest.mark.runner(["self-hosted", "linux", "X64", "jammy", "large"]) @pytest.mark.group(1) @pytest.mark.abort_on_fail -async def test_deploy_and_remove_single_unit(ops_test: OpsTest) -> None: +async def test_deploy_and_remove_single_unit(ops_test: OpsTest, charm) -> None: """Build and deploy OpenSearch with a single unit and remove it.""" - my_charm = await ops_test.build_charm(".") await ops_test.model.set_config(MODEL_CONFIG) await ops_test.model.deploy( - my_charm, + charm, num_units=1, series=SERIES, config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, + ) + # Deploy TLS Certificates operator. config = {"ca-common-name": "CN_CA"} await ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ) # Relate it to OpenSearch to set up TLS. await ops_test.model.integrate(APP_NAME, TLS_CERTIFICATES_APP_NAME) @@ -86,20 +96,26 @@ async def test_deploy_and_remove_single_unit(ops_test: OpsTest) -> None: @pytest.mark.runner(["self-hosted", "linux", "X64", "jammy", "large"]) @pytest.mark.group(1) @pytest.mark.abort_on_fail -async def test_build_and_deploy(ops_test: OpsTest) -> None: +async def test_build_and_deploy(ops_test: OpsTest, charm) -> None: """Build and deploy a couple of OpenSearch units.""" - my_charm = await ops_test.build_charm(".") model_config = MODEL_CONFIG model_config["update-status-hook-interval"] = "1m" await ops_test.model.set_config(MODEL_CONFIG) await ops_test.model.deploy( - my_charm, + charm, num_units=DEFAULT_NUM_UNITS, series=SERIES, config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, + ) + await wait_until( ops_test, apps=[APP_NAME], @@ -123,7 +139,10 @@ async def test_actions_get_admin_password(ops_test: OpsTest) -> None: # Deploy TLS Certificates operator. config = {"ca-common-name": "CN_CA"} await ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ) # Relate it to OpenSearch to set up TLS. await ops_test.model.integrate(APP_NAME, TLS_CERTIFICATES_APP_NAME) diff --git a/tests/integration/tls/test_ca_rotation.py b/tests/integration/tls/test_ca_rotation.py index 0869892441..c29e88a852 100644 --- a/tests/integration/tls/test_ca_rotation.py +++ b/tests/integration/tls/test_ca_rotation.py @@ -4,6 +4,8 @@ import asyncio import logging +import os +import subprocess import pytest import requests @@ -65,22 +67,30 @@ @pytest.mark.group(SMALL_DEPLOYMENT) @pytest.mark.abort_on_fail @pytest.mark.skip_if_deployed -async def test_build_and_deploy_active(ops_test: OpsTest) -> None: +async def test_build_and_deploy_active(ops_test: OpsTest, charm) -> None: """Build and deploy one unit of OpenSearch.""" - my_charm = await ops_test.build_charm(".") await ops_test.model.set_config(MODEL_CONFIG) await ops_test.model.deploy( - my_charm, + charm, num_units=len(UNIT_IDS), series=SERIES, config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, ) # Deploy TLS Certificates operator. config = {"ca-common-name": "CN_CA"} await ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ) await wait_until(ops_test, apps=[TLS_CERTIFICATES_APP_NAME], apps_statuses=["active"]) @@ -99,20 +109,20 @@ async def test_build_and_deploy_active(ops_test: OpsTest) -> None: @pytest.mark.runner(["self-hosted", "linux", "X64", "jammy", "xlarge"]) @pytest.mark.group(LARGE_DEPLOYMENT) @pytest.mark.abort_on_fail -async def test_build_large_deployment(ops_test: OpsTest) -> None: +async def test_build_large_deployment(ops_test: OpsTest, charm) -> None: """Setup a large deployments cluster.""" # deploy new cluster - my_charm = await ops_test.build_charm(".") await asyncio.gather( ops_test.model.deploy( - my_charm, + charm, application_name=MAIN_APP, num_units=3, series=SERIES, config={"cluster_name": CLUSTER_NAME, "roles": "cluster_manager,data"} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=FAILOVER_APP, num_units=1, series=SERIES, @@ -122,22 +132,38 @@ async def test_build_large_deployment(ops_test: OpsTest) -> None: "roles": "cluster_manager,data", } | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( - my_charm, + charm, application_name=DATA_APP, num_units=1, series=SERIES, config={"cluster_name": CLUSTER_NAME, "init_hold": True, "roles": "data"} | CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ops_test.model.deploy( TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config={"ca-common-name": "CN_CA"}, + constraints=os.environ.get("TEST_CONSTRAINTS"), ), ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {MAIN_APP}", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {FAILOVER_APP}", + shell=True, + ) + subprocess.call( + f"juju expose -m {ops_test.model.name} {DATA_APP}", + shell=True, + ) + # integrate TLS to all applications for app in [MAIN_APP, FAILOVER_APP, DATA_APP]: await ops_test.model.integrate(app, TLS_CERTIFICATES_APP_NAME) diff --git a/tests/integration/tls/test_manual_tls.py b/tests/integration/tls/test_manual_tls.py index a510cab815..b1d9aa7e93 100644 --- a/tests/integration/tls/test_manual_tls.py +++ b/tests/integration/tls/test_manual_tls.py @@ -3,6 +3,8 @@ # See LICENSE file for licensing details. import logging +import os +import subprocess import pytest from juju.application import Application @@ -19,23 +21,29 @@ @pytest.mark.group(1) @pytest.mark.abort_on_fail @pytest.mark.skip_if_deployed -async def test_build_and_deploy_with_manual_tls(ops_test: OpsTest) -> None: +async def test_build_and_deploy_with_manual_tls(ops_test: OpsTest, charm) -> None: """Build and deploy prod cluster of OpenSearch with Manual TLS Operator integration.""" - my_charm = await ops_test.build_charm(".") await ops_test.model.set_config(MODEL_CONFIG) os_app: Application = await ops_test.model.deploy( - my_charm, + charm, num_units=len(UNIT_IDS), series=SERIES, application_name=APP_NAME, config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, ) # Deploy TLS Certificates operator. tls_app: Application = await ops_test.model.deploy( MANUAL_TLS_CERTIFICATES_APP_NAME, channel="stable", + constraints=os.environ.get("TEST_CONSTRAINTS"), ) await wait_until( ops_test, diff --git a/tests/integration/tls/test_tls.py b/tests/integration/tls/test_tls.py index 7f38983447..89fb246a14 100644 --- a/tests/integration/tls/test_tls.py +++ b/tests/integration/tls/test_tls.py @@ -3,6 +3,7 @@ # See LICENSE file for licensing details. import logging +import os import subprocess import time @@ -47,22 +48,30 @@ @pytest.mark.group(1) @pytest.mark.abort_on_fail @pytest.mark.skip_if_deployed -async def test_build_and_deploy_active(ops_test: OpsTest) -> None: +async def test_build_and_deploy_active(ops_test: OpsTest, charm) -> None: """Build and deploy one unit of OpenSearch.""" - my_charm = await ops_test.build_charm(".") await ops_test.model.set_config(MODEL_CONFIG) await ops_test.model.deploy( - my_charm, + charm, num_units=len(UNIT_IDS), series=SERIES, config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, ) # Deploy TLS Certificates operator. config = {"ca-common-name": "CN_CA"} await ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ) await wait_until(ops_test, apps=[TLS_CERTIFICATES_APP_NAME], apps_statuses=["active"]) @@ -171,7 +180,7 @@ async def test_tls_renewal(ops_test: OpsTest) -> None: @pytest.mark.runner(["self-hosted", "linux", "X64", "jammy", "large"]) @pytest.mark.group(1) @pytest.mark.abort_on_fail -async def test_tls_expiration(ops_test: OpsTest) -> None: +async def test_tls_expiration(ops_test: OpsTest, charm) -> None: """Test that expiring TLS certificates are renewed.""" # before we can run this test, need to clean up and deploy with different config if APP_NAME in ops_test.model.applications: @@ -185,20 +194,28 @@ async def test_tls_expiration(ops_test: OpsTest) -> None: logger.info("Deploying TLS Certificates operator") config = {"ca-common-name": "CN_CA", "certificate-validity": "1"} await ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ) await wait_until(ops_test, apps=[TLS_CERTIFICATES_APP_NAME], apps_statuses=["active"]) # Deploy Opensearch operator await ops_test.model.set_config(MODEL_CONFIG) - my_charm = await ops_test.build_charm(".") logger.info("Deploying OpenSearch") await ops_test.model.deploy( - my_charm, + charm, num_units=1, series=SERIES, config=CONFIG_OPTS, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} {APP_NAME}", + shell=True, ) await wait_until( diff --git a/tests/integration/upgrades/test_small_deployment_upgrades.py b/tests/integration/upgrades/test_small_deployment_upgrades.py index d210a319e8..9f00f5ba3a 100644 --- a/tests/integration/upgrades/test_small_deployment_upgrades.py +++ b/tests/integration/upgrades/test_small_deployment_upgrades.py @@ -3,6 +3,8 @@ # See LICENSE file for licensing details. import logging +import os +import subprocess import pytest from pytest_operator.plugin import OpsTest @@ -73,12 +75,21 @@ async def _build_env(ops_test: OpsTest, version: str) -> None: channel=OPENSEARCH_CHANNEL, revision=VERSION_TO_REVISION[version], series=SERIES, + constraints=os.environ.get("TEST_CONSTRAINTS"), + ) + + subprocess.call( + f"juju expose -m {ops_test.model.name} opensearch", + shell=True, ) # Deploy TLS Certificates operator. config = {"ca-common-name": "CN_CA"} await ops_test.model.deploy( - TLS_CERTIFICATES_APP_NAME, channel=TLS_STABLE_CHANNEL, config=config + TLS_CERTIFICATES_APP_NAME, + channel=TLS_STABLE_CHANNEL, + config=config, + constraints=os.environ.get("TEST_CONSTRAINTS"), ) # Relate it to OpenSearch to set up TLS. @@ -107,6 +118,8 @@ async def _build_env(ops_test: OpsTest, version: str) -> None: @pytest.mark.skip_if_deployed async def test_deploy_latest_from_channel(ops_test: OpsTest) -> None: """Deploy OpenSearch.""" + if await app_name(ops_test): + return await _build_env(ops_test, STARTING_VERSION) @@ -180,11 +193,10 @@ async def test_upgrade_between_versions( @pytest.mark.group("happy_path_upgrade") @pytest.mark.abort_on_fail async def test_upgrade_to_local( - ops_test: OpsTest, c_writes: ContinuousWrites, c_writes_runner + ops_test: OpsTest, charm, c_writes: ContinuousWrites, c_writes_runner ) -> None: """Test upgrade from usptream to currently locally built version.""" logger.info("Build charm locally") - charm = await ops_test.build_charm(".") await assert_upgrade_to_local(ops_test, c_writes, charm) @@ -204,6 +216,8 @@ async def test_upgrade_to_local( @pytest.mark.skip_if_deployed async def test_deploy_from_version(ops_test: OpsTest, version) -> None: """Deploy OpenSearch.""" + if await app_name(ops_test): + return await _build_env(ops_test, version) @@ -211,7 +225,7 @@ async def test_deploy_from_version(ops_test: OpsTest, version) -> None: @pytest.mark.parametrize("version", UPGRADE_INITIAL_VERSION) @pytest.mark.abort_on_fail async def test_upgrade_rollback_from_local( - ops_test: OpsTest, c_writes: ContinuousWrites, c_writes_runner, version + ops_test: OpsTest, charm, c_writes: ContinuousWrites, c_writes_runner, version ) -> None: """Test upgrade and rollback to each version available.""" app = (await app_name(ops_test)) or APP_NAME @@ -226,11 +240,6 @@ async def test_upgrade_rollback_from_local( ) assert action.status == "completed" - logger.info("Build charm locally") - global charm - if not charm: - charm = await ops_test.build_charm(".") - async with ops_test.fast_forward(): logger.info("Refresh the charm") await refresh(ops_test, app, path=charm, config={"profile": "testing"}) @@ -293,11 +302,7 @@ async def test_upgrade_rollback_from_local( @pytest.mark.parametrize("version", UPGRADE_INITIAL_VERSION) @pytest.mark.abort_on_fail async def test_upgrade_from_version_to_local( - ops_test: OpsTest, c_writes: ContinuousWrites, c_writes_runner, version + ops_test: OpsTest, charm, c_writes: ContinuousWrites, c_writes_runner, version ) -> None: """Test upgrade from usptream to currently locally built version.""" - logger.info("Build charm locally") - global charm - if not charm: - charm = await ops_test.build_charm(".") await assert_upgrade_to_local(ops_test, c_writes, charm) diff --git a/tox.ini b/tox.ini index a89ce1cb53..058e30529a 100644 --- a/tox.ini +++ b/tox.ini @@ -64,6 +64,8 @@ pass_env = GITHUB_OUTPUT S3_INTEGRATOR_CHARMPATH SECRETS_FROM_GITHUB + TEST_CONSTRAINTS + SUBSTRATE allowlist_externals = {[testenv]allowlist_externals} # Set the testing host before starting the lxd cloud