From 48a1daa8ec04df47d2d3c522dc0225f85f567b43 Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Thu, 20 Nov 2025 10:04:00 -0500 Subject: [PATCH 01/19] fix/grafana's self-dashboard when ingressed --- terraform/cos-lite/integrations.tf | 14 ++++++++++++++ terraform/cos/integrations.tf | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/terraform/cos-lite/integrations.tf b/terraform/cos-lite/integrations.tf index 99a2bb0e..33f110b1 100644 --- a/terraform/cos-lite/integrations.tf +++ b/terraform/cos-lite/integrations.tf @@ -411,3 +411,17 @@ resource "juju_integration" "external_grafana_ca_cert" { endpoint = module.grafana.endpoints.receive_ca_cert } } + +resource "juju_integration" "external_prom_ca_cert" { + count = local.tls_termination ? 1 : 0 + model_uuid = var.model_uuid + + application { + offer_url = var.external_ca_cert_offer_url + } + + application { + name = module.prometheus.app_name + endpoint = module.prometheus.endpoints.receive_ca_cert + } +} diff --git a/terraform/cos/integrations.tf b/terraform/cos/integrations.tf index 3cd93be5..375b5fc2 100644 --- a/terraform/cos/integrations.tf +++ b/terraform/cos/integrations.tf @@ -438,6 +438,20 @@ resource "juju_integration" "external_grafana_ca_cert" { } } +resource "juju_integration" "external_otelcol_ca_cert" { + count = local.tls_termination ? 1 : 0 + model_uuid = var.model_uuid + + application { + offer_url = var.external_ca_cert_offer_url + } + + application { + name = module.opentelemetry_collector.app_name + endpoint = module.opentelemetry_collector.endpoints.receive_ca_cert + } +} + # -------------- # Telemetry correlations --------------------- resource "juju_integration" "traces_and_logs_correlation" { From d50d394b3d8b49226a322c1052c4276b1efd078d Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Fri, 21 Nov 2025 14:19:55 -0500 Subject: [PATCH 02/19] fix: Cleanup TF docs and tests after cutting track/2 --- docs/how-to/cos-tls.tf | 4 +- .../cos-canonical-k8s-sandbox.conf | 4 +- .../installation/cos-lite-microk8s-sandbox.tf | 4 +- .../test_upgrade_cos_tls_external.py | 18 +++++ tests/integration/cos/tls_external/track-2.tf | 4 +- .../integration/cos/tls_external/track-dev.tf | 65 +++++++++++++++++++ .../cos/tls_full/test_upgrade_cos_tls_full.py | 18 +++++ tests/integration/cos/tls_full/track-2.tf | 4 +- tests/integration/cos/tls_full/track-dev.tf | 65 +++++++++++++++++++ .../test_upgrade_cos_tls_internal.py | 15 +++++ tests/integration/cos/tls_internal/track-2.tf | 4 +- .../integration/cos/tls_internal/track-dev.tf | 49 ++++++++++++++ .../cos/tls_none/test_upgrade_cos_tls_none.py | 15 +++++ tests/integration/cos/tls_none/track-2.tf | 4 +- tests/integration/cos/tls_none/track-dev.tf | 49 ++++++++++++++ .../test_upgrade_cos_lite_tls_external.py | 11 ++-- .../cos_lite/tls_external/track-2.tf | 4 +- .../tls_external/{track-1.tf => track-dev.tf} | 2 +- .../test_upgrade_cos_lite_tls_full.py | 11 ++-- .../integration/cos_lite/tls_full/track-2.tf | 4 +- .../tls_full/{track-1.tf => track-dev.tf} | 3 +- .../test_upgrade_cos_lite_tls_internal.py | 11 ++-- .../cos_lite/tls_internal/track-2.tf | 4 +- .../tls_internal/{track-1.tf => track-dev.tf} | 2 +- .../test_upgrade_cos_lite_tls_none.py | 11 ++-- .../integration/cos_lite/tls_none/track-2.tf | 4 +- .../tls_none/{track-1.tf => track-dev.tf} | 2 +- 27 files changed, 345 insertions(+), 46 deletions(-) create mode 100644 tests/integration/cos/tls_external/track-dev.tf create mode 100644 tests/integration/cos/tls_full/track-dev.tf create mode 100644 tests/integration/cos/tls_internal/track-dev.tf create mode 100644 tests/integration/cos/tls_none/track-dev.tf rename tests/integration/cos_lite/tls_external/{track-1.tf => track-dev.tf} (95%) rename tests/integration/cos_lite/tls_full/{track-1.tf => track-dev.tf} (95%) rename tests/integration/cos_lite/tls_internal/{track-1.tf => track-dev.tf} (95%) rename tests/integration/cos_lite/tls_none/{track-1.tf => track-dev.tf} (95%) diff --git a/docs/how-to/cos-tls.tf b/docs/how-to/cos-tls.tf index b6330546..5b8d99b1 100644 --- a/docs/how-to/cos-tls.tf +++ b/docs/how-to/cos-tls.tf @@ -4,9 +4,9 @@ resource "juju_model" "cos" { module "cos" { # Use the right source value depending on whether you are using cos or cos-lite - source = "git::https://github.com/canonical/observability-stack//terraform/cos" + source = "git::https://github.com/canonical/observability-stack//terraform/cos?ref=track/2" model_uuid = juju_model.cos.uuid - channel = "1/stable" + channel = "2/stable" internal_tls = true # TLS between in-model applications # Update the _offer_url inputs with the offered endpoints of the external CA's model diff --git a/docs/tutorial/installation/cos-canonical-k8s-sandbox.conf b/docs/tutorial/installation/cos-canonical-k8s-sandbox.conf index 37d1343c..5ef0d901 100644 --- a/docs/tutorial/installation/cos-canonical-k8s-sandbox.conf +++ b/docs/tutorial/installation/cos-canonical-k8s-sandbox.conf @@ -74,9 +74,9 @@ runcmd: } module "cos" { - source = "git::https://github.com/canonical/observability-stack//terraform/cos" + source = "git::https://github.com/canonical/observability-stack//terraform/cos?ref=track/2" model_uuid = juju_model.cos.uuid - channel = "2/edge" + channel = "2/stable" anti_affinity = false internal_tls = false external_certificates_offer_url = null diff --git a/docs/tutorial/installation/cos-lite-microk8s-sandbox.tf b/docs/tutorial/installation/cos-lite-microk8s-sandbox.tf index f75c07ff..c3d1a1b0 100644 --- a/docs/tutorial/installation/cos-lite-microk8s-sandbox.tf +++ b/docs/tutorial/installation/cos-lite-microk8s-sandbox.tf @@ -14,9 +14,9 @@ resource "juju_model" "cos" { } module "cos-lite" { - source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite" + source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite?ref=track/2" model_uuid = juju_model.cos.uuid - channel = "1/stable" + channel = "2/stable" ssc = { channel = "1/stable" } traefik = { channel = "latest/edge" } } diff --git a/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py b/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py index 4db63bad..6d7d72ef 100644 --- a/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py +++ b/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py @@ -10,12 +10,14 @@ from helpers import ( catalogue_apps_are_reachable, get_tls_context, + refresh_o11y_apps, wait_for_active_idle_without_error, ) import jubilant TRACK_2_TF_FILE = Path(__file__).parent.resolve() / "track-2.tf" +TRACK_DEV_TF_FILE = Path(__file__).parent.resolve() / "track-dev.tf" S3_ENDPOINT = { "s3_endpoint": os.getenv("S3_ENDPOINT"), "s3_secret_key": os.getenv("S3_SECRET_KEY"), @@ -38,3 +40,19 @@ def test_deploy_from_track( wait_for_active_idle_without_error([cos_model], timeout=5400) tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") catalogue_apps_are_reachable(cos_model, tls_ctx) + + +def test_deploy_to_track( + tmp_path, tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju +): + # WHEN upgraded to track n + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) + + # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 + refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") + + # THEN the model is upgraded and is active/idle + wait_for_active_idle_without_error([ca_model, cos_model]) + tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") + catalogue_apps_are_reachable(cos_model, tls_ctx) diff --git a/tests/integration/cos/tls_external/track-2.tf b/tests/integration/cos/tls_external/track-2.tf index 5c940b27..9766172c 100644 --- a/tests/integration/cos/tls_external/track-2.tf +++ b/tests/integration/cos/tls_external/track-2.tf @@ -44,9 +44,9 @@ module "ssc" { } module "cos" { - source = "git::https://github.com/canonical/observability-stack//terraform/cos" + source = "git::https://github.com/canonical/observability-stack//terraform/cos?ref=track/2" model_uuid = data.juju_model.cos-model.uuid - channel = "2/edge" + channel = "2/stable" internal_tls = "false" external_certificates_offer_url = "admin/${var.ca_model}.certificates" external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert" diff --git a/tests/integration/cos/tls_external/track-dev.tf b/tests/integration/cos/tls_external/track-dev.tf new file mode 100644 index 00000000..b55c8a24 --- /dev/null +++ b/tests/integration/cos/tls_external/track-dev.tf @@ -0,0 +1,65 @@ +terraform { + required_version = ">= 1.5" + required_providers { + juju = { + source = "juju/juju" + version = "~> 1.0" + } + } +} + +variable "cos_model" { + type = string +} + +variable "ca_model" { + type = string +} + +data "juju_model" "ca-model" { + name = var.ca_model + owner = "admin" +} + +data "juju_model" "cos-model" { + name = var.cos_model + owner = "admin" +} + +variable "s3_endpoint" { + type = string +} + +variable "s3_secret_key" { + type = string +} + +variable "s3_access_key" { + type = string +} + +module "ssc" { + source = "git::https://github.com/canonical/self-signed-certificates-operator//terraform" + model_uuid = data.juju_model.ca-model.uuid +} + +module "cos" { + source = "git::https://github.com/canonical/observability-stack//terraform/cos" + model_uuid = data.juju_model.cos-model.uuid + channel = "dev/edge" + internal_tls = "false" + external_certificates_offer_url = "admin/${var.ca_model}.certificates" + external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert" + + s3_endpoint = var.s3_endpoint + s3_secret_key = var.s3_secret_key + s3_access_key = var.s3_access_key + + traefik = { channel = "latest/edge" } # TODO: Switch to latest/stable when rev257 hits stable + loki_coordinator = { units = 1 } + loki_worker = { backend_units = 1, read_units = 1, write_units = 1 } + mimir_coordinator = { units = 1 } + mimir_worker = { backend_units = 1, read_units = 1, write_units = 1 } + tempo_coordinator = { units = 1 } + tempo_worker = { compactor_units = 1, distributor_units = 1, ingester_units = 1, metrics_generator_units = 1, querier_units = 1, query_frontend_units = 1 } +} diff --git a/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py b/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py index 8a5a651c..05247e73 100644 --- a/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py +++ b/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py @@ -10,12 +10,14 @@ from helpers import ( catalogue_apps_are_reachable, get_tls_context, + refresh_o11y_apps, wait_for_active_idle_without_error, ) import jubilant TRACK_2_TF_FILE = Path(__file__).parent.resolve() / "track-2.tf" +TRACK_DEV_TF_FILE = Path(__file__).parent.resolve() / "track-dev.tf" S3_ENDPOINT = { "s3_endpoint": os.getenv("S3_ENDPOINT"), "s3_secret_key": os.getenv("S3_SECRET_KEY"), @@ -38,3 +40,19 @@ def test_deploy_from_track( wait_for_active_idle_without_error([cos_model], timeout=5400) tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") catalogue_apps_are_reachable(cos_model, tls_ctx) + + +def test_deploy_to_track( + tmp_path, tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju +): + # WHEN upgraded to track n + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) + + # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 + refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") + + # THEN the model is upgraded and is active/idle + wait_for_active_idle_without_error([ca_model, cos_model]) + tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") + catalogue_apps_are_reachable(cos_model, tls_ctx) diff --git a/tests/integration/cos/tls_full/track-2.tf b/tests/integration/cos/tls_full/track-2.tf index 6151f22a..ce4b36bd 100644 --- a/tests/integration/cos/tls_full/track-2.tf +++ b/tests/integration/cos/tls_full/track-2.tf @@ -44,9 +44,9 @@ module "ssc" { } module "cos" { - source = "git::https://github.com/canonical/observability-stack//terraform/cos" + source = "git::https://github.com/canonical/observability-stack//terraform/cos?ref=track/2" model_uuid = data.juju_model.cos-model.uuid - channel = "2/edge" + channel = "2/stable" internal_tls = "true" external_certificates_offer_url = "admin/${var.ca_model}.certificates" external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert" diff --git a/tests/integration/cos/tls_full/track-dev.tf b/tests/integration/cos/tls_full/track-dev.tf new file mode 100644 index 00000000..e0ad2d26 --- /dev/null +++ b/tests/integration/cos/tls_full/track-dev.tf @@ -0,0 +1,65 @@ +terraform { + required_version = ">= 1.5" + required_providers { + juju = { + source = "juju/juju" + version = "~> 1.0" + } + } +} + +variable "cos_model" { + type = string +} + +variable "ca_model" { + type = string +} + +data "juju_model" "ca-model" { + name = var.ca_model + owner = "admin" +} + +data "juju_model" "cos-model" { + name = var.cos_model + owner = "admin" +} + +variable "s3_endpoint" { + type = string +} + +variable "s3_secret_key" { + type = string +} + +variable "s3_access_key" { + type = string +} + +module "ssc" { + source = "git::https://github.com/canonical/self-signed-certificates-operator//terraform" + model_uuid = data.juju_model.ca-model.uuid +} + +module "cos" { + source = "git::https://github.com/canonical/observability-stack//terraform/cos" + model_uuid = data.juju_model.cos-model.uuid + channel = "dev/edge" + internal_tls = "true" + external_certificates_offer_url = "admin/${var.ca_model}.certificates" + external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert" + + s3_endpoint = var.s3_endpoint + s3_secret_key = var.s3_secret_key + s3_access_key = var.s3_access_key + + traefik = { channel = "latest/edge" } # TODO: Switch to latest/stable when rev257 hits stable + loki_coordinator = { units = 1 } + loki_worker = { backend_units = 1, read_units = 1, write_units = 1 } + mimir_coordinator = { units = 1 } + mimir_worker = { backend_units = 1, read_units = 1, write_units = 1 } + tempo_coordinator = { units = 1 } + tempo_worker = { compactor_units = 1, distributor_units = 1, ingester_units = 1, metrics_generator_units = 1, querier_units = 1, query_frontend_units = 1 } +} diff --git a/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py b/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py index 84bef0ea..974764ae 100644 --- a/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py +++ b/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py @@ -9,12 +9,14 @@ from helpers import ( catalogue_apps_are_reachable, + refresh_o11y_apps, wait_for_active_idle_without_error, ) import jubilant TRACK_2_TF_FILE = Path(__file__).parent.resolve() / "track-2.tf" +TRACK_DEV_TF_FILE = Path(__file__).parent.resolve() / "track-dev.tf" S3_ENDPOINT = { "s3_endpoint": os.getenv("S3_ENDPOINT"), "s3_secret_key": os.getenv("S3_SECRET_KEY"), @@ -34,3 +36,16 @@ def test_deploy_from_track(tmp_path, tf_manager, cos_model: jubilant.Juju): tf_manager.apply(model=cos_model.model, **S3_ENDPOINT) wait_for_active_idle_without_error([cos_model], timeout=5400) catalogue_apps_are_reachable(cos_model) + + +def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): + # WHEN upgraded to track n + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(model=cos_model.model) + + # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 + refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") + + # THEN the model is upgraded and is active/idle + wait_for_active_idle_without_error([cos_model]) + catalogue_apps_are_reachable(cos_model) diff --git a/tests/integration/cos/tls_internal/track-2.tf b/tests/integration/cos/tls_internal/track-2.tf index fc47b30b..15e31d5a 100644 --- a/tests/integration/cos/tls_internal/track-2.tf +++ b/tests/integration/cos/tls_internal/track-2.tf @@ -30,9 +30,9 @@ variable "s3_access_key" { } module "cos" { - source = "git::https://github.com/canonical/observability-stack//terraform/cos" + source = "git::https://github.com/canonical/observability-stack//terraform/cos?ref=track/2" model_uuid = data.juju_model.model.uuid - channel = "2/edge" + channel = "2/stable" internal_tls = "true" s3_endpoint = var.s3_endpoint diff --git a/tests/integration/cos/tls_internal/track-dev.tf b/tests/integration/cos/tls_internal/track-dev.tf new file mode 100644 index 00000000..c0f76b45 --- /dev/null +++ b/tests/integration/cos/tls_internal/track-dev.tf @@ -0,0 +1,49 @@ +terraform { + required_version = ">= 1.5" + required_providers { + juju = { + source = "juju/juju" + version = "~> 1.0" + } + } +} + +variable "model" { + type = string +} + +data "juju_model" "model" { + name = var.model + owner = "admin" +} + +variable "s3_endpoint" { + type = string +} + +variable "s3_secret_key" { + type = string +} + +variable "s3_access_key" { + type = string +} + +module "cos" { + source = "git::https://github.com/canonical/observability-stack//terraform/cos" + model_uuid = data.juju_model.model.uuid + channel = "dev/edge" + internal_tls = "true" + + s3_endpoint = var.s3_endpoint + s3_secret_key = var.s3_secret_key + s3_access_key = var.s3_access_key + + traefik = { channel = "latest/edge" } # TODO: Switch to latest/stable when rev257 hits stable + loki_coordinator = { units = 1 } + loki_worker = { backend_units = 1, read_units = 1, write_units = 1 } + mimir_coordinator = { units = 1 } + mimir_worker = { backend_units = 1, read_units = 1, write_units = 1 } + tempo_coordinator = { units = 1 } + tempo_worker = { compactor_units = 1, distributor_units = 1, ingester_units = 1, metrics_generator_units = 1, querier_units = 1, query_frontend_units = 1 } +} diff --git a/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py b/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py index bf4a3dff..bcfdc846 100644 --- a/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py +++ b/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py @@ -9,12 +9,14 @@ from helpers import ( catalogue_apps_are_reachable, + refresh_o11y_apps, wait_for_active_idle_without_error, ) import jubilant TRACK_2_TF_FILE = Path(__file__).parent.resolve() / "track-2.tf" +TRACK_DEV_TF_FILE = Path(__file__).parent.resolve() / "track-dev.tf" S3_ENDPOINT = { "s3_endpoint": os.getenv("S3_ENDPOINT"), "s3_secret_key": os.getenv("S3_SECRET_KEY"), @@ -34,3 +36,16 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): tf_manager.apply(model=cos_model.model, **S3_ENDPOINT) wait_for_active_idle_without_error([cos_model], timeout=5400) catalogue_apps_are_reachable(cos_model) + + +def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): + # WHEN upgraded to track n + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(model=cos_model.model) + + # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 + refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") + + # THEN the model is upgraded and is active/idle + wait_for_active_idle_without_error([cos_model]) + catalogue_apps_are_reachable(cos_model) diff --git a/tests/integration/cos/tls_none/track-2.tf b/tests/integration/cos/tls_none/track-2.tf index af3dbfe5..479becba 100644 --- a/tests/integration/cos/tls_none/track-2.tf +++ b/tests/integration/cos/tls_none/track-2.tf @@ -30,9 +30,9 @@ variable "s3_access_key" { } module "cos" { - source = "git::https://github.com/canonical/observability-stack//terraform/cos" + source = "git::https://github.com/canonical/observability-stack//terraform/cos?ref=track/2" model_uuid = data.juju_model.model.uuid - channel = "2/edge" + channel = "2/stable" internal_tls = "false" s3_endpoint = var.s3_endpoint diff --git a/tests/integration/cos/tls_none/track-dev.tf b/tests/integration/cos/tls_none/track-dev.tf new file mode 100644 index 00000000..5707bea3 --- /dev/null +++ b/tests/integration/cos/tls_none/track-dev.tf @@ -0,0 +1,49 @@ +terraform { + required_version = ">= 1.5" + required_providers { + juju = { + source = "juju/juju" + version = "~> 1.0" + } + } +} + +variable "model" { + type = string +} + +data "juju_model" "model" { + name = var.model + owner = "admin" +} + +variable "s3_endpoint" { + type = string +} + +variable "s3_secret_key" { + type = string +} + +variable "s3_access_key" { + type = string +} + +module "cos" { + source = "git::https://github.com/canonical/observability-stack//terraform/cos" + model_uuid = data.juju_model.model.uuid + channel = "dev/edge" + internal_tls = "false" + + s3_endpoint = var.s3_endpoint + s3_secret_key = var.s3_secret_key + s3_access_key = var.s3_access_key + + traefik = { channel = "latest/edge" } # TODO: Switch to latest/stable when rev257 hits stable + loki_coordinator = { units = 1 } + loki_worker = { backend_units = 1, read_units = 1, write_units = 1 } + mimir_coordinator = { units = 1 } + mimir_worker = { backend_units = 1, read_units = 1, write_units = 1 } + tempo_coordinator = { units = 1 } + tempo_worker = { compactor_units = 1, distributor_units = 1, ingester_units = 1, metrics_generator_units = 1, querier_units = 1, query_frontend_units = 1 } +} diff --git a/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py b/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py index e8996217..57565abc 100644 --- a/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py +++ b/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py @@ -15,15 +15,15 @@ import jubilant -TRACK_1_TF_FILE = Path(__file__).parent.resolve() / "track-1.tf" TRACK_2_TF_FILE = Path(__file__).parent.resolve() / "track-2.tf" +TRACK_DEV_TF_FILE = Path(__file__).parent.resolve() / "track-dev.tf" def test_deploy_from_track( tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju ): # GIVEN a module deployed from track n-1 - tf_manager.init(TRACK_1_TF_FILE) + tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) wait_for_active_idle_without_error([ca_model, cos_model]) @@ -32,10 +32,11 @@ def test_deploy_to_track( tmp_path, tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju ): # WHEN upgraded to track n + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) + # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 - # tf_manager.init(TRACK_2_TF_FILE) - # tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - refresh_o11y_apps(cos_model, channel="2/edge", base="ubuntu@24.04") + refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") # THEN the model is upgraded and is active/idle wait_for_active_idle_without_error([ca_model, cos_model]) diff --git a/tests/integration/cos_lite/tls_external/track-2.tf b/tests/integration/cos_lite/tls_external/track-2.tf index 6f819d90..fb11292a 100644 --- a/tests/integration/cos_lite/tls_external/track-2.tf +++ b/tests/integration/cos_lite/tls_external/track-2.tf @@ -32,9 +32,9 @@ module "ssc" { } module "cos-lite" { - source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite" + source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite?ref=track/2" model_uuid = data.juju_model.cos-model.uuid - channel = "2/edge" + channel = "2/stable" internal_tls = "false" external_certificates_offer_url = "admin/${var.ca_model}.certificates" external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert" diff --git a/tests/integration/cos_lite/tls_external/track-1.tf b/tests/integration/cos_lite/tls_external/track-dev.tf similarity index 95% rename from tests/integration/cos_lite/tls_external/track-1.tf rename to tests/integration/cos_lite/tls_external/track-dev.tf index 2a2f183f..8cd3de8f 100644 --- a/tests/integration/cos_lite/tls_external/track-1.tf +++ b/tests/integration/cos_lite/tls_external/track-dev.tf @@ -34,7 +34,7 @@ module "ssc" { module "cos-lite" { source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite" model_uuid = data.juju_model.cos-model.uuid - channel = "1/stable" + channel = "dev/edge" internal_tls = "false" external_certificates_offer_url = "admin/${var.ca_model}.certificates" external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert" diff --git a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py index 41ccc176..18c27b27 100644 --- a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py +++ b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py @@ -15,15 +15,15 @@ import jubilant -TRACK_1_TF_FILE = Path(__file__).parent.resolve() / "track-1.tf" TRACK_2_TF_FILE = Path(__file__).parent.resolve() / "track-2.tf" +TRACK_DEV_TF_FILE = Path(__file__).parent.resolve() / "track-dev.tf" def test_deploy_from_track( tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju ): # GIVEN a module deployed from track n-1 - tf_manager.init(TRACK_1_TF_FILE) + tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) wait_for_active_idle_without_error([ca_model, cos_model]) @@ -32,10 +32,11 @@ def test_deploy_to_track( tmp_path, tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju ): # WHEN upgraded to track n + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) + # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 - # tf_manager.init(TRACK_2_TF_FILE) - # tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - refresh_o11y_apps(cos_model, channel="2/edge", base="ubuntu@24.04") + refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") # THEN the model is upgraded and is active/idle wait_for_active_idle_without_error([ca_model, cos_model]) diff --git a/tests/integration/cos_lite/tls_full/track-2.tf b/tests/integration/cos_lite/tls_full/track-2.tf index d6089644..12dbff49 100644 --- a/tests/integration/cos_lite/tls_full/track-2.tf +++ b/tests/integration/cos_lite/tls_full/track-2.tf @@ -32,9 +32,9 @@ module "ssc" { } module "cos-lite" { - source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite" + source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite?ref=track/2" model_uuid = data.juju_model.cos-model.uuid - channel = "2/edge" + channel = "2/stable" internal_tls = "true" external_certificates_offer_url = "admin/${var.ca_model}.certificates" external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert" diff --git a/tests/integration/cos_lite/tls_full/track-1.tf b/tests/integration/cos_lite/tls_full/track-dev.tf similarity index 95% rename from tests/integration/cos_lite/tls_full/track-1.tf rename to tests/integration/cos_lite/tls_full/track-dev.tf index fa75e106..bb4e48a5 100644 --- a/tests/integration/cos_lite/tls_full/track-1.tf +++ b/tests/integration/cos_lite/tls_full/track-dev.tf @@ -34,10 +34,11 @@ module "ssc" { module "cos-lite" { source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite" model_uuid = data.juju_model.cos-model.uuid - channel = "1/stable" + channel = "dev/edge" internal_tls = "true" external_certificates_offer_url = "admin/${var.ca_model}.certificates" external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert" traefik = { channel = "latest/edge" } # TODO: Switch to latest/stable when rev257 hits stable } + diff --git a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py index 33a4e94c..97ac2e2c 100644 --- a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py +++ b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py @@ -14,23 +14,24 @@ import jubilant -TRACK_1_TF_FILE = Path(__file__).parent.resolve() / "track-1.tf" TRACK_2_TF_FILE = Path(__file__).parent.resolve() / "track-2.tf" +TRACK_DEV_TF_FILE = Path(__file__).parent.resolve() / "track-dev.tf" def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): # GIVEN a module deployed from track n-1 - tf_manager.init(TRACK_1_TF_FILE) + tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(model=cos_model.model) wait_for_active_idle_without_error([cos_model]) def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(model=cos_model.model) + # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 - # tf_manager.init(TRACK_2_TF_FILE) - # tf_manager.apply(model=cos_model.model) - refresh_o11y_apps(cos_model, channel="2/edge", base="ubuntu@24.04") + refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") # THEN the model is upgraded and is active/idle wait_for_active_idle_without_error([cos_model]) diff --git a/tests/integration/cos_lite/tls_internal/track-2.tf b/tests/integration/cos_lite/tls_internal/track-2.tf index 051f8c60..fbcbdaa3 100644 --- a/tests/integration/cos_lite/tls_internal/track-2.tf +++ b/tests/integration/cos_lite/tls_internal/track-2.tf @@ -18,9 +18,9 @@ data "juju_model" "model" { } module "cos-lite" { - source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite" + source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite?ref=track/2" model_uuid = data.juju_model.model.uuid - channel = "2/edge" + channel = "2/stable" internal_tls = "true" traefik = { channel = "latest/edge" } # TODO: Switch to latest/stable when rev257 hits stable diff --git a/tests/integration/cos_lite/tls_internal/track-1.tf b/tests/integration/cos_lite/tls_internal/track-dev.tf similarity index 95% rename from tests/integration/cos_lite/tls_internal/track-1.tf rename to tests/integration/cos_lite/tls_internal/track-dev.tf index b0b66db5..266cb6aa 100644 --- a/tests/integration/cos_lite/tls_internal/track-1.tf +++ b/tests/integration/cos_lite/tls_internal/track-dev.tf @@ -20,7 +20,7 @@ data "juju_model" "model" { module "cos-lite" { source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite" model_uuid = data.juju_model.model.uuid - channel = "1/stable" + channel = "dev/edge" internal_tls = "true" traefik = { channel = "latest/edge" } # TODO: Switch to latest/stable when rev257 hits stable diff --git a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py index f346fddf..f830976b 100644 --- a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py +++ b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py @@ -14,23 +14,24 @@ import jubilant -TRACK_1_TF_FILE = Path(__file__).parent.resolve() / "track-1.tf" TRACK_2_TF_FILE = Path(__file__).parent.resolve() / "track-2.tf" +TRACK_DEV_TF_FILE = Path(__file__).parent.resolve() / "track-dev.tf" def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): # GIVEN a module deployed from track n-1 - tf_manager.init(TRACK_1_TF_FILE) + tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(model=cos_model.model) wait_for_active_idle_without_error([cos_model]) def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(model=cos_model.model) + # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 - # tf_manager.init(TRACK_2_TF_FILE) - # tf_manager.apply(model=cos_model.model) - refresh_o11y_apps(cos_model, channel="2/edge", base="ubuntu@24.04") + refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") # THEN the model is upgraded and is active/idle wait_for_active_idle_without_error([cos_model]) diff --git a/tests/integration/cos_lite/tls_none/track-2.tf b/tests/integration/cos_lite/tls_none/track-2.tf index a9beb974..e94708d5 100644 --- a/tests/integration/cos_lite/tls_none/track-2.tf +++ b/tests/integration/cos_lite/tls_none/track-2.tf @@ -18,9 +18,9 @@ data "juju_model" "model" { } module "cos-lite" { - source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite" + source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite?ref=track/2" model_uuid = data.juju_model.model.uuid - channel = "2/edge" + channel = "2/stable" internal_tls = "false" traefik = { channel = "latest/edge" } # TODO: Switch to latest/stable when rev257 hits stable diff --git a/tests/integration/cos_lite/tls_none/track-1.tf b/tests/integration/cos_lite/tls_none/track-dev.tf similarity index 95% rename from tests/integration/cos_lite/tls_none/track-1.tf rename to tests/integration/cos_lite/tls_none/track-dev.tf index 0728a4b1..3cbe40ef 100644 --- a/tests/integration/cos_lite/tls_none/track-1.tf +++ b/tests/integration/cos_lite/tls_none/track-dev.tf @@ -20,7 +20,7 @@ data "juju_model" "model" { module "cos-lite" { source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite" model_uuid = data.juju_model.model.uuid - channel = "1/stable" + channel = "dev/edge" internal_tls = "false" traefik = { channel = "latest/edge" } # TODO: Switch to latest/stable when rev257 hits stable From 94d3b2fd5831e48114306520a08e7d43e90f65c6 Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Fri, 21 Nov 2025 15:59:42 -0500 Subject: [PATCH 03/19] chore: remove branch PR CI rule --- .github/workflows/terraform.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/terraform.yml b/.github/workflows/terraform.yml index 128a8707..d52feee4 100644 --- a/.github/workflows/terraform.yml +++ b/.github/workflows/terraform.yml @@ -2,8 +2,6 @@ name: Terraform on: pull_request: - branches: - - main paths: - "**/*.tf" From 18eb23e992f5a3886b0d8060fbf4820c7f62606c Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Mon, 24 Nov 2025 10:50:26 -0500 Subject: [PATCH 04/19] chore --- .../cos/tls_external/test_upgrade_cos_tls_external.py | 8 ++++---- .../cos/tls_full/test_upgrade_cos_tls_full.py | 8 ++++---- .../cos/tls_internal/test_upgrade_cos_tls_internal.py | 8 ++++---- .../cos/tls_none/test_upgrade_cos_tls_none.py | 8 ++++---- .../tls_external/test_upgrade_cos_lite_tls_external.py | 10 +++++----- .../tls_full/test_upgrade_cos_lite_tls_full.py | 8 ++++---- .../tls_internal/test_upgrade_cos_lite_tls_internal.py | 8 ++++---- .../tls_none/test_upgrade_cos_lite_tls_none.py | 8 ++++---- 8 files changed, 33 insertions(+), 33 deletions(-) diff --git a/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py b/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py index 6d7d72ef..94fa01ec 100644 --- a/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py +++ b/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py @@ -46,13 +46,13 @@ def test_deploy_to_track( tmp_path, tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju ): # WHEN upgraded to track n - tf_manager.init(TRACK_DEV_TF_FILE) - tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - + cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - # THEN the model is upgraded and is active/idle + # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") catalogue_apps_are_reachable(cos_model, tls_ctx) diff --git a/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py b/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py index 05247e73..18852f84 100644 --- a/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py +++ b/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py @@ -46,13 +46,13 @@ def test_deploy_to_track( tmp_path, tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju ): # WHEN upgraded to track n - tf_manager.init(TRACK_DEV_TF_FILE) - tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - + cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - # THEN the model is upgraded and is active/idle + # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") catalogue_apps_are_reachable(cos_model, tls_ctx) diff --git a/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py b/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py index 974764ae..5daab262 100644 --- a/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py +++ b/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py @@ -40,12 +40,12 @@ def test_deploy_from_track(tmp_path, tf_manager, cos_model: jubilant.Juju): def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n - tf_manager.init(TRACK_DEV_TF_FILE) - tf_manager.apply(model=cos_model.model) - + cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(cos_model=cos_model.model) - # THEN the model is upgraded and is active/idle + # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) catalogue_apps_are_reachable(cos_model) diff --git a/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py b/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py index bcfdc846..a3ff4e32 100644 --- a/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py +++ b/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py @@ -40,12 +40,12 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n - tf_manager.init(TRACK_DEV_TF_FILE) - tf_manager.apply(model=cos_model.model) - + cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(cos_model=cos_model.model) - # THEN the model is upgraded and is active/idle + # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) catalogue_apps_are_reachable(cos_model) diff --git a/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py b/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py index 57565abc..84ff919b 100644 --- a/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py +++ b/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py @@ -32,13 +32,13 @@ def test_deploy_to_track( tmp_path, tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju ): # WHEN upgraded to track n - tf_manager.init(TRACK_DEV_TF_FILE) - tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - + cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") - - # THEN the model is upgraded and is active/idle + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) + + # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") catalogue_apps_are_reachable(cos_model, tls_ctx) diff --git a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py index 18c27b27..da304503 100644 --- a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py +++ b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py @@ -32,13 +32,13 @@ def test_deploy_to_track( tmp_path, tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju ): # WHEN upgraded to track n - tf_manager.init(TRACK_DEV_TF_FILE) - tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - + cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - # THEN the model is upgraded and is active/idle + # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") catalogue_apps_are_reachable(cos_model, tls_ctx) diff --git a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py index 97ac2e2c..61d63104 100644 --- a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py +++ b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py @@ -27,12 +27,12 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n - tf_manager.init(TRACK_DEV_TF_FILE) - tf_manager.apply(model=cos_model.model) - + cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(cos_model=cos_model.model) - # THEN the model is upgraded and is active/idle + # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) catalogue_apps_are_reachable(cos_model) diff --git a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py index f830976b..c61af2d7 100644 --- a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py +++ b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py @@ -27,12 +27,12 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n - tf_manager.init(TRACK_DEV_TF_FILE) - tf_manager.apply(model=cos_model.model) - + cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") + tf_manager.init(TRACK_DEV_TF_FILE) + tf_manager.apply(cos_model=cos_model.model) - # THEN the model is upgraded and is active/idle + # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) catalogue_apps_are_reachable(cos_model) From ecf86f5340147e91d068506510ec30253b3e7478 Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Mon, 24 Nov 2025 12:15:44 -0500 Subject: [PATCH 05/19] chore: bump the default timeout for model settling --- tests/integration/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index 45b4ff89..eee395af 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -54,7 +54,7 @@ def destroy(self, **kwargs): def wait_for_active_idle_without_error( - jujus: List[jubilant.Juju], timeout: int = 60 * 20 + jujus: List[jubilant.Juju], timeout: int = 60 * 30 ): for juju in jujus: print(f"\nwaiting for the model ({juju.model}) to settle ...\n") From 2b96da540e0940be6dc39000becaae1ccfd09172 Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Mon, 24 Nov 2025 22:00:00 -0500 Subject: [PATCH 06/19] fix: CI --- .../cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py | 2 ++ .../cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py | 1 + 2 files changed, 3 insertions(+) diff --git a/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py b/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py index 84ff919b..b7feb70f 100644 --- a/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py +++ b/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py @@ -33,6 +33,7 @@ def test_deploy_to_track( ): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") + wait_for_active_idle_without_error([ca_model, cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) @@ -41,4 +42,5 @@ def test_deploy_to_track( # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") + breakpoint() catalogue_apps_are_reachable(cos_model, tls_ctx) diff --git a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py index da304503..e7016bd9 100644 --- a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py +++ b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py @@ -33,6 +33,7 @@ def test_deploy_to_track( ): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") + wait_for_active_idle_without_error([ca_model, cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) From 88e4d2b5ed93fe75f2b585e15b4d87b394b58bc8 Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Tue, 25 Nov 2025 11:14:03 -0500 Subject: [PATCH 07/19] chore: remove breakpoint --- .../cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py b/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py index b7feb70f..e4f838aa 100644 --- a/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py +++ b/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py @@ -42,5 +42,4 @@ def test_deploy_to_track( # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") - breakpoint() catalogue_apps_are_reachable(cos_model, tls_ctx) From db1b722fa4fde3333b936a7bbe65561ae5e9a0c8 Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Tue, 25 Nov 2025 11:49:09 -0500 Subject: [PATCH 08/19] chore: wait after removal of grafana ingress relation --- .../cos/tls_external/test_upgrade_cos_tls_external.py | 1 + tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py | 1 + .../cos/tls_internal/test_upgrade_cos_tls_internal.py | 1 + tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py | 1 + .../cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py | 2 +- .../cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py | 2 +- .../cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py | 1 + .../cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py | 1 + 8 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py b/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py index 94fa01ec..5e678739 100644 --- a/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py +++ b/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py @@ -47,6 +47,7 @@ def test_deploy_to_track( ): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") + wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) diff --git a/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py b/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py index 18852f84..0c657bec 100644 --- a/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py +++ b/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py @@ -47,6 +47,7 @@ def test_deploy_to_track( ): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") + wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) diff --git a/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py b/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py index 5daab262..00cd7418 100644 --- a/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py +++ b/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py @@ -41,6 +41,7 @@ def test_deploy_from_track(tmp_path, tf_manager, cos_model: jubilant.Juju): def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") + wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) diff --git a/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py b/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py index a3ff4e32..57310b10 100644 --- a/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py +++ b/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py @@ -41,6 +41,7 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") + wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) diff --git a/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py b/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py index e4f838aa..96b64b43 100644 --- a/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py +++ b/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py @@ -33,7 +33,7 @@ def test_deploy_to_track( ): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") - wait_for_active_idle_without_error([ca_model, cos_model]) + wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) diff --git a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py index e7016bd9..7cb258ec 100644 --- a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py +++ b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py @@ -33,7 +33,7 @@ def test_deploy_to_track( ): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") - wait_for_active_idle_without_error([ca_model, cos_model]) + wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) diff --git a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py index 61d63104..c2ec2104 100644 --- a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py +++ b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py @@ -28,6 +28,7 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") + wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) diff --git a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py index c61af2d7..3b27055c 100644 --- a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py +++ b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py @@ -28,6 +28,7 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") + wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) From c1990b46586485e2bd983fc74e051e3db424683a Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Tue, 25 Nov 2025 12:17:34 -0500 Subject: [PATCH 09/19] chore --- .../cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py | 2 +- .../cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py index c2ec2104..152d37d3 100644 --- a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py +++ b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py @@ -32,7 +32,7 @@ def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) - tf_manager.apply(cos_model=cos_model.model) + tf_manager.apply(model=cos_model.model) # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) diff --git a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py index 3b27055c..66c8908f 100644 --- a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py +++ b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py @@ -32,7 +32,7 @@ def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) - tf_manager.apply(cos_model=cos_model.model) + tf_manager.apply(model=cos_model.model) # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) From 42a270631d7a45073c23eb217c40cefb0cfa8f4f Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Tue, 25 Nov 2025 12:19:17 -0500 Subject: [PATCH 10/19] chore --- .../cos/tls_external/test_upgrade_cos_tls_external.py | 2 +- tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py | 2 +- .../cos/tls_internal/test_upgrade_cos_tls_internal.py | 2 +- tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py b/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py index 5e678739..931fb5e2 100644 --- a/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py +++ b/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py @@ -51,7 +51,7 @@ def test_deploy_to_track( # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) - tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) + tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model, **S3_ENDPOINT) # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) diff --git a/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py b/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py index 0c657bec..7ffb87e5 100644 --- a/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py +++ b/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py @@ -51,7 +51,7 @@ def test_deploy_to_track( # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) - tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) + tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model, **S3_ENDPOINT) # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) diff --git a/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py b/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py index 00cd7418..d08e745d 100644 --- a/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py +++ b/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py @@ -45,7 +45,7 @@ def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) - tf_manager.apply(cos_model=cos_model.model) + tf_manager.apply(model=cos_model.model, **S3_ENDPOINT) # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) diff --git a/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py b/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py index 57310b10..419dfaf1 100644 --- a/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py +++ b/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py @@ -45,7 +45,7 @@ def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) - tf_manager.apply(cos_model=cos_model.model) + tf_manager.apply(model=cos_model.model, **S3_ENDPOINT) # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) From 427ca5e163377665ac1ce57c6362b9db3b6d5933 Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Wed, 26 Nov 2025 09:50:07 -0500 Subject: [PATCH 11/19] test: CPU usage --- .../test_upgrade_cos_lite_tls_full.py | 19 +++++++++++++++++++ .../test_upgrade_cos_lite_tls_internal.py | 19 +++++++++++++++++++ .../test_upgrade_cos_lite_tls_none.py | 19 +++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py index 7cb258ec..2dc5f0d6 100644 --- a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py +++ b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py @@ -4,6 +4,7 @@ For more further TLS configuration details, refer to our documentation: https://documentation.ubuntu.com/observability/latest/how-to/configure-tls-encryption/""" +import os from pathlib import Path from helpers import ( @@ -25,20 +26,38 @@ def test_deploy_from_track( # GIVEN a module deployed from track n-1 tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) + + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + wait_for_active_idle_without_error([ca_model, cos_model]) + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + def test_deploy_to_track( tmp_path, tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju ): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") + + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") + + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") diff --git a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py index 152d37d3..5fe984d1 100644 --- a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py +++ b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py @@ -4,6 +4,7 @@ For more further TLS configuration details, refer to our documentation: https://documentation.ubuntu.com/observability/latest/how-to/configure-tls-encryption/""" +import os from pathlib import Path from helpers import ( @@ -22,18 +23,36 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): # GIVEN a module deployed from track n-1 tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(model=cos_model.model) + + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + wait_for_active_idle_without_error([cos_model]) + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") + + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") + + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(model=cos_model.model) + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) catalogue_apps_are_reachable(cos_model) diff --git a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py index 66c8908f..32c3fa9f 100644 --- a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py +++ b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py @@ -4,6 +4,7 @@ For more further TLS configuration details, refer to our documentation: https://documentation.ubuntu.com/observability/latest/how-to/configure-tls-encryption/""" +import os from pathlib import Path from helpers import ( @@ -22,18 +23,36 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): # GIVEN a module deployed from track n-1 tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(model=cos_model.model) + + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + wait_for_active_idle_without_error([cos_model]) + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") + + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") + + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(model=cos_model.model) + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) catalogue_apps_are_reachable(cos_model) From 97bd1733b594685432fb2608c26f056cd31420ee Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Wed, 26 Nov 2025 10:44:09 -0500 Subject: [PATCH 12/19] test: CPU and MEM usage --- .../test_upgrade_cos_lite_tls_full.py | 21 +++++++++---------- .../test_upgrade_cos_lite_tls_internal.py | 19 ++++++++--------- .../test_upgrade_cos_lite_tls_none.py | 19 +++++++---------- tests/integration/helpers.py | 18 ++++++++++++++++ 4 files changed, 44 insertions(+), 33 deletions(-) diff --git a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py index 2dc5f0d6..9a0c81d6 100644 --- a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py +++ b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py @@ -10,6 +10,7 @@ from helpers import ( catalogue_apps_are_reachable, get_tls_context, + print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -27,13 +28,11 @@ def test_deploy_from_track( tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + print_resource_usage() wait_for_active_idle_without_error([ca_model, cos_model]) - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + print_resource_usage() def test_deploy_to_track( @@ -42,21 +41,21 @@ def test_deploy_to_track( # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + print_resource_usage() wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") - - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + + print_resource_usage() tf_manager.init(TRACK_DEV_TF_FILE) + + print_resource_usage() + tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) diff --git a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py index 5fe984d1..1d10ae36 100644 --- a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py +++ b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py @@ -9,6 +9,7 @@ from helpers import ( catalogue_apps_are_reachable, + print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -24,34 +25,32 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(model=cos_model.model) - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + print_resource_usage() wait_for_active_idle_without_error([cos_model]) - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + print_resource_usage() def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + print_resource_usage() wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + print_resource_usage() tf_manager.init(TRACK_DEV_TF_FILE) + + print_resource_usage() + tf_manager.apply(model=cos_model.model) - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) diff --git a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py index 32c3fa9f..d3b46ab1 100644 --- a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py +++ b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py @@ -4,11 +4,11 @@ For more further TLS configuration details, refer to our documentation: https://documentation.ubuntu.com/observability/latest/how-to/configure-tls-encryption/""" -import os from pathlib import Path from helpers import ( catalogue_apps_are_reachable, + print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -24,34 +24,29 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(model=cos_model.model) - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + print_resource_usage() wait_for_active_idle_without_error([cos_model]) - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + print_resource_usage() def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + print_resource_usage() wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") - - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + + print_resource_usage() tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(model=cos_model.model) - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index eee395af..cc804410 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -8,6 +8,8 @@ from typing import List, Optional from urllib.request import urlopen +import psutil + import jubilant @@ -19,6 +21,8 @@ def refresh_o11y_apps(juju: jubilant.Juju, channel: str, base: Optional[str] = N for app in juju.status().apps: if app in {"traefik", "ca"}: continue + if "s3-integrator" in app: + continue juju.refresh(app, channel=channel, base=base) @@ -101,3 +105,17 @@ def catalogue_apps_are_reachable( continue response = urlopen(url, data=None, timeout=2.0, context=tls_context) assert response.code == 200, f"{app} was not reachable" + + +def print_resource_usage(): + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + + vm = psutil.virtual_memory() + available = vm.available + total = vm.total + percent_used = vm.percent + + print( + f"system memory: total={total:,} bytes, available={available:,} bytes, used_percent={percent_used}%" + ) From 7f37075e5878f8292642321ecc2103b3b240a00d Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Wed, 26 Nov 2025 11:30:47 -0500 Subject: [PATCH 13/19] chore --- justfile | 7 ++- pyproject.toml | 2 +- uv.lock | 151 +++++++++++++------------------------------------ 3 files changed, 47 insertions(+), 113 deletions(-) diff --git a/justfile b/justfile index cda744be..066c6794 100644 --- a/justfile +++ b/justfile @@ -2,11 +2,16 @@ set quiet # Recipes are silent by default set export # Just variables are exported to the environment terraform := `which terraform || which tofu || echo ""` # require 'terraform' or 'opentofu' +uv_flags := "--frozen --isolated" [private] default: just --list +# Update uv.lock with the latest deps +lock: + uv lock --upgrade --no-cache + # Lint everything [group("Lint")] lint: lint-workflows lint-terraform lint-terraform-docs @@ -53,4 +58,4 @@ validate-terraform: # Run integration tests [working-directory("./tests/integration")] integration *args='': - uv run pytest -vv --capture=no --exitfirst "${args}" + uv run ${uv_flags} pytest -vv --capture=no --exitfirst "${args}" diff --git a/pyproject.toml b/pyproject.toml index 26bb1691..02ef2d20 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,5 +8,5 @@ version = "0.0.0" dependencies = [ "jubilant", "pytest", - "jinja2", + "psutil", ] diff --git a/uv.lock b/uv.lock index 4c73b574..bc9c09ae 100644 --- a/uv.lock +++ b/uv.lock @@ -13,132 +13,35 @@ wheels = [ [[package]] name = "exceptiongroup" -version = "1.3.0" +version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, ] [[package]] name = "iniconfig" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, -] - -[[package]] -name = "jinja2" -version = "3.1.6" +version = "2.3.0" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markupsafe" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, ] [[package]] name = "jubilant" -version = "1.4.0" +version = "1.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4d/1a/ba5838825ac99db4ceec68fa146b594c97b682cf3ccf670b1ecf1261209d/jubilant-1.4.0.tar.gz", hash = "sha256:aa377699a8811fea29bfe0febb6b552d4593c02e666f5ba8c3fba24258700199", size = 27502, upload-time = "2025-08-27T00:11:46.295Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/06/4965ed70d4b9d405c8bdefc4926d94cae202014b4488a25aa8c1fe9fb462/jubilant-1.4.0-py3-none-any.whl", hash = "sha256:1df7eaf125fad8d0d3d35e6d83eca43bfbb7884debcd6c7f4b0822600e2a485c", size = 27185, upload-time = "2025-08-27T00:11:44.851Z" }, -] - -[[package]] -name = "markupsafe" -version = "3.0.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d1/af/2c7d2a677389eb4de3bb841f399b749ca2fd4c6c1b70313e21249536e6be/jubilant-1.5.0.tar.gz", hash = "sha256:055c65a662586191939a1a3d3e2b6d08b71ecf0c7f403a1c7ba0cde6ecaf3bbd", size = 28433, upload-time = "2025-10-10T01:08:06.58Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559", size = 11631, upload-time = "2025-09-27T18:36:05.558Z" }, - { url = "https://files.pythonhosted.org/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419", size = 12057, upload-time = "2025-09-27T18:36:07.165Z" }, - { url = "https://files.pythonhosted.org/packages/40/01/e560d658dc0bb8ab762670ece35281dec7b6c1b33f5fbc09ebb57a185519/markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695", size = 22050, upload-time = "2025-09-27T18:36:08.005Z" }, - { url = "https://files.pythonhosted.org/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591", size = 20681, upload-time = "2025-09-27T18:36:08.881Z" }, - { url = "https://files.pythonhosted.org/packages/c9/2a/b5c12c809f1c3045c4d580b035a743d12fcde53cf685dbc44660826308da/markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c", size = 20705, upload-time = "2025-09-27T18:36:10.131Z" }, - { url = "https://files.pythonhosted.org/packages/cf/e3/9427a68c82728d0a88c50f890d0fc072a1484de2f3ac1ad0bfc1a7214fd5/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f", size = 21524, upload-time = "2025-09-27T18:36:11.324Z" }, - { url = "https://files.pythonhosted.org/packages/bc/36/23578f29e9e582a4d0278e009b38081dbe363c5e7165113fad546918a232/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6", size = 20282, upload-time = "2025-09-27T18:36:12.573Z" }, - { url = "https://files.pythonhosted.org/packages/56/21/dca11354e756ebd03e036bd8ad58d6d7168c80ce1fe5e75218e4945cbab7/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1", size = 20745, upload-time = "2025-09-27T18:36:13.504Z" }, - { url = "https://files.pythonhosted.org/packages/87/99/faba9369a7ad6e4d10b6a5fbf71fa2a188fe4a593b15f0963b73859a1bbd/markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa", size = 14571, upload-time = "2025-09-27T18:36:14.779Z" }, - { url = "https://files.pythonhosted.org/packages/d6/25/55dc3ab959917602c96985cb1253efaa4ff42f71194bddeb61eb7278b8be/markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8", size = 15056, upload-time = "2025-09-27T18:36:16.125Z" }, - { url = "https://files.pythonhosted.org/packages/d0/9e/0a02226640c255d1da0b8d12e24ac2aa6734da68bff14c05dd53b94a0fc3/markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1", size = 13932, upload-time = "2025-09-27T18:36:17.311Z" }, - { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, - { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, - { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, - { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" }, - { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" }, - { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" }, - { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" }, - { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" }, - { url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" }, - { url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" }, - { url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" }, - { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, - { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, - { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, - { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, - { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, - { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, - { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, - { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, - { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, - { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, - { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, - { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, - { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, - { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, - { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, - { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, - { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, - { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, - { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, - { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, - { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, - { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, - { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, - { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, - { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, - { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, - { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, - { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, - { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, - { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, - { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, - { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, - { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, - { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, - { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, - { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, - { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, - { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, - { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, - { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, - { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, - { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, - { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, - { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, - { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, - { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, - { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, - { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, - { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, - { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, - { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, - { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, - { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, - { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, - { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, + { url = "https://files.pythonhosted.org/packages/f6/c9/05e5aa65baa7b71b17c1314b8f25744f36fd9aad60ef9fb46fd84347885a/jubilant-1.5.0-py3-none-any.whl", hash = "sha256:eec58340b9d3d478f31e18e33281638fdf0d9b84608c8935368f7a1bb1972255", size = 28275, upload-time = "2025-10-10T01:08:04.963Z" }, ] [[package]] @@ -146,15 +49,15 @@ name = "observability-stack" version = "0.0.0" source = { virtual = "." } dependencies = [ - { name = "jinja2" }, { name = "jubilant" }, + { name = "psutil" }, { name = "pytest" }, ] [package.metadata] requires-dist = [ - { name = "jinja2" }, { name = "jubilant" }, + { name = "psutil" }, { name = "pytest" }, ] @@ -176,6 +79,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] +[[package]] +name = "psutil" +version = "7.1.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/88/bdd0a41e5857d5d703287598cbf08dad90aed56774ea52ae071bae9071b6/psutil-7.1.3.tar.gz", hash = "sha256:6c86281738d77335af7aec228328e944b30930899ea760ecf33a4dba66be5e74", size = 489059, upload-time = "2025-11-02T12:25:54.619Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/93/0c49e776b8734fef56ec9c5c57f923922f2cf0497d62e0f419465f28f3d0/psutil-7.1.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0005da714eee687b4b8decd3d6cc7c6db36215c9e74e5ad2264b90c3df7d92dc", size = 239751, upload-time = "2025-11-02T12:25:58.161Z" }, + { url = "https://files.pythonhosted.org/packages/6f/8d/b31e39c769e70780f007969815195a55c81a63efebdd4dbe9e7a113adb2f/psutil-7.1.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:19644c85dcb987e35eeeaefdc3915d059dac7bd1167cdcdbf27e0ce2df0c08c0", size = 240368, upload-time = "2025-11-02T12:26:00.491Z" }, + { url = "https://files.pythonhosted.org/packages/62/61/23fd4acc3c9eebbf6b6c78bcd89e5d020cfde4acf0a9233e9d4e3fa698b4/psutil-7.1.3-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95ef04cf2e5ba0ab9eaafc4a11eaae91b44f4ef5541acd2ee91d9108d00d59a7", size = 287134, upload-time = "2025-11-02T12:26:02.613Z" }, + { url = "https://files.pythonhosted.org/packages/30/1c/f921a009ea9ceb51aa355cb0cc118f68d354db36eae18174bab63affb3e6/psutil-7.1.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1068c303be3a72f8e18e412c5b2a8f6d31750fb152f9cb106b54090296c9d251", size = 289904, upload-time = "2025-11-02T12:26:05.207Z" }, + { url = "https://files.pythonhosted.org/packages/a6/82/62d68066e13e46a5116df187d319d1724b3f437ddd0f958756fc052677f4/psutil-7.1.3-cp313-cp313t-win_amd64.whl", hash = "sha256:18349c5c24b06ac5612c0428ec2a0331c26443d259e2a0144a9b24b4395b58fa", size = 249642, upload-time = "2025-11-02T12:26:07.447Z" }, + { url = "https://files.pythonhosted.org/packages/df/ad/c1cd5fe965c14a0392112f68362cfceb5230819dbb5b1888950d18a11d9f/psutil-7.1.3-cp313-cp313t-win_arm64.whl", hash = "sha256:c525ffa774fe4496282fb0b1187725793de3e7c6b29e41562733cae9ada151ee", size = 245518, upload-time = "2025-11-02T12:26:09.719Z" }, + { url = "https://files.pythonhosted.org/packages/2e/bb/6670bded3e3236eb4287c7bcdc167e9fae6e1e9286e437f7111caed2f909/psutil-7.1.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b403da1df4d6d43973dc004d19cee3b848e998ae3154cc8097d139b77156c353", size = 239843, upload-time = "2025-11-02T12:26:11.968Z" }, + { url = "https://files.pythonhosted.org/packages/b8/66/853d50e75a38c9a7370ddbeefabdd3d3116b9c31ef94dc92c6729bc36bec/psutil-7.1.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ad81425efc5e75da3f39b3e636293360ad8d0b49bed7df824c79764fb4ba9b8b", size = 240369, upload-time = "2025-11-02T12:26:14.358Z" }, + { url = "https://files.pythonhosted.org/packages/41/bd/313aba97cb5bfb26916dc29cf0646cbe4dd6a89ca69e8c6edce654876d39/psutil-7.1.3-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f33a3702e167783a9213db10ad29650ebf383946e91bc77f28a5eb083496bc9", size = 288210, upload-time = "2025-11-02T12:26:16.699Z" }, + { url = "https://files.pythonhosted.org/packages/c2/fa/76e3c06e760927a0cfb5705eb38164254de34e9bd86db656d4dbaa228b04/psutil-7.1.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fac9cd332c67f4422504297889da5ab7e05fd11e3c4392140f7370f4208ded1f", size = 291182, upload-time = "2025-11-02T12:26:18.848Z" }, + { url = "https://files.pythonhosted.org/packages/0f/1d/5774a91607035ee5078b8fd747686ebec28a962f178712de100d00b78a32/psutil-7.1.3-cp314-cp314t-win_amd64.whl", hash = "sha256:3792983e23b69843aea49c8f5b8f115572c5ab64c153bada5270086a2123c7e7", size = 250466, upload-time = "2025-11-02T12:26:21.183Z" }, + { url = "https://files.pythonhosted.org/packages/00/ca/e426584bacb43a5cb1ac91fae1937f478cd8fbe5e4ff96574e698a2c77cd/psutil-7.1.3-cp314-cp314t-win_arm64.whl", hash = "sha256:31d77fcedb7529f27bb3a0472bea9334349f9a04160e8e6e5020f22c59893264", size = 245756, upload-time = "2025-11-02T12:26:23.148Z" }, + { url = "https://files.pythonhosted.org/packages/ef/94/46b9154a800253e7ecff5aaacdf8ebf43db99de4a2dfa18575b02548654e/psutil-7.1.3-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2bdbcd0e58ca14996a42adf3621a6244f1bb2e2e528886959c72cf1e326677ab", size = 238359, upload-time = "2025-11-02T12:26:25.284Z" }, + { url = "https://files.pythonhosted.org/packages/68/3a/9f93cff5c025029a36d9a92fef47220ab4692ee7f2be0fba9f92813d0cb8/psutil-7.1.3-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:bc31fa00f1fbc3c3802141eede66f3a2d51d89716a194bf2cd6fc68310a19880", size = 239171, upload-time = "2025-11-02T12:26:27.23Z" }, + { url = "https://files.pythonhosted.org/packages/ce/b1/5f49af514f76431ba4eea935b8ad3725cdeb397e9245ab919dbc1d1dc20f/psutil-7.1.3-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3bb428f9f05c1225a558f53e30ccbad9930b11c3fc206836242de1091d3e7dd3", size = 263261, upload-time = "2025-11-02T12:26:29.48Z" }, + { url = "https://files.pythonhosted.org/packages/e0/95/992c8816a74016eb095e73585d747e0a8ea21a061ed3689474fabb29a395/psutil-7.1.3-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56d974e02ca2c8eb4812c3f76c30e28836fffc311d55d979f1465c1feeb2b68b", size = 264635, upload-time = "2025-11-02T12:26:31.74Z" }, + { url = "https://files.pythonhosted.org/packages/55/4c/c3ed1a622b6ae2fd3c945a366e64eb35247a31e4db16cf5095e269e8eb3c/psutil-7.1.3-cp37-abi3-win_amd64.whl", hash = "sha256:f39c2c19fe824b47484b96f9692932248a54c43799a84282cfe58d05a6449efd", size = 247633, upload-time = "2025-11-02T12:26:33.887Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ad/33b2ccec09bf96c2b2ef3f9a6f66baac8253d7565d8839e024a6b905d45d/psutil-7.1.3-cp37-abi3-win_arm64.whl", hash = "sha256:bd0d69cee829226a761e92f28140bec9a5ee9d5b4fb4b0cc589068dbfff559b1", size = 244608, upload-time = "2025-11-02T12:26:36.136Z" }, +] + [[package]] name = "pygments" version = "2.19.2" @@ -187,7 +116,7 @@ wheels = [ [[package]] name = "pytest" -version = "8.4.2" +version = "9.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -198,9 +127,9 @@ dependencies = [ { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" } +sdist = { url = "https://files.pythonhosted.org/packages/07/56/f013048ac4bc4c1d9be45afd4ab209ea62822fb1598f40687e6bf45dcea4/pytest-9.0.1.tar.gz", hash = "sha256:3e9c069ea73583e255c3b21cf46b8d3c56f6e3a1a8f6da94ccb0fcf57b9d73c8", size = 1564125, upload-time = "2025-11-12T13:05:09.333Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, + { url = "https://files.pythonhosted.org/packages/0b/8b/6300fb80f858cda1c51ffa17075df5d846757081d11ab4aa35cef9e6258b/pytest-9.0.1-py3-none-any.whl", hash = "sha256:67be0030d194df2dfa7b556f2e56fb3c3315bd5c8822c6951162b92b32ce7dad", size = 373668, upload-time = "2025-11-12T13:05:07.379Z" }, ] [[package]] From 809c08c67b317b85082768fde45c71106321a596 Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Wed, 26 Nov 2025 12:13:16 -0500 Subject: [PATCH 14/19] chore --- .../test_upgrade_cos_tls_external.py | 3 + .../cos/tls_full/test_upgrade_cos_tls_full.py | 3 + .../test_upgrade_cos_tls_internal.py | 3 + .../cos/tls_none/test_upgrade_cos_tls_none.py | 3 + .../test_upgrade_cos_lite_tls_external.py | 3 + .../test_upgrade_cos_lite_tls_full.py | 15 ---- .../test_upgrade_cos_lite_tls_internal.py | 15 ---- .../test_upgrade_cos_lite_tls_none.py | 11 --- tests/integration/helpers.py | 69 +++++++++---------- 9 files changed, 49 insertions(+), 76 deletions(-) diff --git a/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py b/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py index 931fb5e2..ba3089fa 100644 --- a/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py +++ b/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py @@ -10,6 +10,7 @@ from helpers import ( catalogue_apps_are_reachable, get_tls_context, + print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -37,6 +38,7 @@ def test_deploy_from_track( # GIVEN a module deployed from track n tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model, **S3_ENDPOINT) + print_resource_usage() wait_for_active_idle_without_error([cos_model], timeout=5400) tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") catalogue_apps_are_reachable(cos_model, tls_ctx) @@ -52,6 +54,7 @@ def test_deploy_to_track( refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model, **S3_ENDPOINT) + print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) diff --git a/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py b/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py index 7ffb87e5..3a9637be 100644 --- a/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py +++ b/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py @@ -10,6 +10,7 @@ from helpers import ( catalogue_apps_are_reachable, get_tls_context, + print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -37,6 +38,7 @@ def test_deploy_from_track( # GIVEN a module deployed from track n tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model, **S3_ENDPOINT) + print_resource_usage() wait_for_active_idle_without_error([cos_model], timeout=5400) tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") catalogue_apps_are_reachable(cos_model, tls_ctx) @@ -52,6 +54,7 @@ def test_deploy_to_track( refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model, **S3_ENDPOINT) + print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) diff --git a/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py b/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py index d08e745d..c31cd67e 100644 --- a/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py +++ b/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py @@ -9,6 +9,7 @@ from helpers import ( catalogue_apps_are_reachable, + print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -34,6 +35,7 @@ def test_deploy_from_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # GIVEN a module deployed from track n tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(model=cos_model.model, **S3_ENDPOINT) + print_resource_usage() wait_for_active_idle_without_error([cos_model], timeout=5400) catalogue_apps_are_reachable(cos_model) @@ -46,6 +48,7 @@ def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(model=cos_model.model, **S3_ENDPOINT) + print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) diff --git a/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py b/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py index 419dfaf1..82a8600c 100644 --- a/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py +++ b/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py @@ -9,6 +9,7 @@ from helpers import ( catalogue_apps_are_reachable, + print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -34,6 +35,7 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): # GIVEN a module deployed from track n tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(model=cos_model.model, **S3_ENDPOINT) + print_resource_usage() wait_for_active_idle_without_error([cos_model], timeout=5400) catalogue_apps_are_reachable(cos_model) @@ -46,6 +48,7 @@ def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(model=cos_model.model, **S3_ENDPOINT) + print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) diff --git a/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py b/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py index 96b64b43..22ee6a23 100644 --- a/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py +++ b/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py @@ -9,6 +9,7 @@ from helpers import ( catalogue_apps_are_reachable, get_tls_context, + print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -25,6 +26,7 @@ def test_deploy_from_track( # GIVEN a module deployed from track n-1 tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) + print_resource_usage() wait_for_active_idle_without_error([ca_model, cos_model]) @@ -38,6 +40,7 @@ def test_deploy_to_track( refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) + print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) diff --git a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py index 9a0c81d6..55d9acd7 100644 --- a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py +++ b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py @@ -4,7 +4,6 @@ For more further TLS configuration details, refer to our documentation: https://documentation.ubuntu.com/observability/latest/how-to/configure-tls-encryption/""" -import os from pathlib import Path from helpers import ( @@ -27,34 +26,20 @@ def test_deploy_from_track( # GIVEN a module deployed from track n-1 tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - print_resource_usage() - wait_for_active_idle_without_error([ca_model, cos_model]) - print_resource_usage() - def test_deploy_to_track( tmp_path, tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju ): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") - - print_resource_usage() - wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") - - print_resource_usage() - tf_manager.init(TRACK_DEV_TF_FILE) - - print_resource_usage() - tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - print_resource_usage() # THEN the model is upgraded and is healthy diff --git a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py index 1d10ae36..581dba9f 100644 --- a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py +++ b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py @@ -4,7 +4,6 @@ For more further TLS configuration details, refer to our documentation: https://documentation.ubuntu.com/observability/latest/how-to/configure-tls-encryption/""" -import os from pathlib import Path from helpers import ( @@ -24,32 +23,18 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): # GIVEN a module deployed from track n-1 tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(model=cos_model.model) - print_resource_usage() - wait_for_active_idle_without_error([cos_model]) - print_resource_usage() - def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") - - print_resource_usage() - wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") - - print_resource_usage() - tf_manager.init(TRACK_DEV_TF_FILE) - - print_resource_usage() - tf_manager.apply(model=cos_model.model) - print_resource_usage() # THEN the model is upgraded and is healthy diff --git a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py index d3b46ab1..513807d4 100644 --- a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py +++ b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py @@ -23,29 +23,18 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): # GIVEN a module deployed from track n-1 tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(model=cos_model.model) - print_resource_usage() - wait_for_active_idle_without_error([cos_model]) - print_resource_usage() - def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # WHEN upgraded to track n cos_model.remove_relation("traefik:traefik-route", "grafana:ingress") - - print_resource_usage() - wait_for_active_idle_without_error([cos_model]) # FIXME: https://github.com/juju/terraform-provider-juju/issues/967 refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") - - print_resource_usage() - tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(model=cos_model.model) - print_resource_usage() # THEN the model is upgraded and is healthy diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index cc804410..ec904052 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -13,19 +13,6 @@ import jubilant -def refresh_o11y_apps(juju: jubilant.Juju, channel: str, base: Optional[str] = None): - """Temporary workaround for the issue: - - FIXME: https://github.com/juju/terraform-provider-juju/issues/967 - """ - for app in juju.status().apps: - if app in {"traefik", "ca"}: - continue - if "s3-integrator" in app: - continue - juju.refresh(app, channel=channel, base=base) - - class TfDirManager: def __init__(self, base_tmpdir): self.base: str = str(base_tmpdir) @@ -57,21 +44,47 @@ def destroy(self, **kwargs): subprocess.run(shlex.split(cmd_str), check=True) +def print_resource_usage(): + print("\n---RESOURCE USAGE---") + + one, five, fifteen = os.getloadavg() + print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") + + vm = psutil.virtual_memory() + available = vm.available + total = vm.total + percent_used = vm.percent + print( + f"system memory: total={total:,} bytes, available={available:,} bytes, used_percent={percent_used}%" + ) + + print("---RESOURCE USAGE---\n") + + +def refresh_o11y_apps(juju: jubilant.Juju, channel: str, base: Optional[str] = None): + """Temporary workaround for the issue: + + FIXME: https://github.com/juju/terraform-provider-juju/issues/967 + """ + for app in juju.status().apps: + if app in {"traefik", "ca"}: + continue + if "s3-integrator" in app: + continue + juju.refresh(app, channel=channel, base=base) + + def wait_for_active_idle_without_error( - jujus: List[jubilant.Juju], timeout: int = 60 * 30 + jujus: List[jubilant.Juju], timeout: int = 60 * 45 ): for juju in jujus: print(f"\nwaiting for the model ({juju.model}) to settle ...\n") - juju.wait(jubilant.all_active, delay=5, timeout=timeout) - print("\nwaiting for no errors ...\n") - juju.wait( - jubilant.all_active, delay=5, timeout=60 * 5, error=jubilant.any_error - ) + juju.wait(jubilant.all_active, delay=10, timeout=timeout) print("\nwaiting for agents idle ...\n") juju.wait( jubilant.all_agents_idle, - delay=5, - timeout=60 * 10, + delay=10, + timeout=60 * 30, error=jubilant.any_error, ) @@ -105,17 +118,3 @@ def catalogue_apps_are_reachable( continue response = urlopen(url, data=None, timeout=2.0, context=tls_context) assert response.code == 200, f"{app} was not reachable" - - -def print_resource_usage(): - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") - - vm = psutil.virtual_memory() - available = vm.available - total = vm.total - percent_used = vm.percent - - print( - f"system memory: total={total:,} bytes, available={available:,} bytes, used_percent={percent_used}%" - ) From ac450ce4cd64d3f79e653c4d93b3e10a2d1b7e2a Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Wed, 26 Nov 2025 12:59:49 -0500 Subject: [PATCH 15/19] test --- pyproject.toml | 1 + tests/integration/helpers.py | 15 +++++++++++---- uv.lock | 11 +++++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 02ef2d20..95be84ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,4 +9,5 @@ dependencies = [ "jubilant", "pytest", "psutil", + "sh", ] diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index ec904052..9941d547 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -4,11 +4,13 @@ import shutil import ssl import subprocess +import sys from pathlib import Path from typing import List, Optional from urllib.request import urlopen import psutil +import sh import jubilant @@ -20,14 +22,18 @@ def __init__(self, base_tmpdir): @property def tf_cmd(self): - return f"terraform -chdir={self.dir}" + return f"-chdir={self.dir}" def init(self, tf_file: str): """Initialize a Terraform module in a subdirectory.""" self.dir = os.path.join(self.base, "terraform") os.makedirs(self.dir, exist_ok=True) shutil.copy(tf_file, os.path.join(self.dir, "main.tf")) - subprocess.run(shlex.split(f"{self.tf_cmd} init -upgrade"), check=True) + sh.terraform( + shlex.split(f"{self.tf_cmd} init -upgrade"), + _out=sys.stdout, + _err=sys.stderr, + ) @staticmethod def _args_str(target: Optional[str] = None, **kwargs) -> str: @@ -37,11 +43,12 @@ def _args_str(target: Optional[str] = None, **kwargs) -> str: def apply(self, target: Optional[str] = None, **kwargs): cmd_str = f"{self.tf_cmd} apply " + self._args_str(target, **kwargs) - subprocess.run(shlex.split(cmd_str), check=True) + breakpoint() + sh.terraform(shlex.split(cmd_str), _out=sys.stdout, _err=sys.stderr) def destroy(self, **kwargs): cmd_str = f"{self.tf_cmd} destroy " + self._args_str(None, **kwargs) - subprocess.run(shlex.split(cmd_str), check=True) + sh.terraform(shlex.split(cmd_str), _out=sys.stdout, _err=sys.stderr) def print_resource_usage(): diff --git a/uv.lock b/uv.lock index bc9c09ae..603f6bdd 100644 --- a/uv.lock +++ b/uv.lock @@ -52,6 +52,7 @@ dependencies = [ { name = "jubilant" }, { name = "psutil" }, { name = "pytest" }, + { name = "sh" }, ] [package.metadata] @@ -59,6 +60,7 @@ requires-dist = [ { name = "jubilant" }, { name = "psutil" }, { name = "pytest" }, + { name = "sh" }, ] [[package]] @@ -196,6 +198,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, ] +[[package]] +name = "sh" +version = "2.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/59/52/f43920223c93e31874677c681b8603d36a40d3d8502d3a37f80d3995d43e/sh-2.2.2.tar.gz", hash = "sha256:653227a7c41a284ec5302173fbc044ee817c7bad5e6e4d8d55741b9aeb9eb65b", size = 345866, upload-time = "2025-02-24T07:16:25.363Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/98/d82f14ac7ffedbd38dfa2383f142b26d18d23ca6cf35a40f4af60df666bd/sh-2.2.2-py3-none-any.whl", hash = "sha256:e0b15b4ae8ffcd399bc8ffddcbd770a43c7a70a24b16773fbb34c001ad5d52af", size = 38295, upload-time = "2025-02-24T07:16:23.782Z" }, +] + [[package]] name = "tomli" version = "2.3.0" From c1ef383d0baa391a95b6bbb39d911d6a00cc58c3 Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Wed, 26 Nov 2025 13:17:05 -0500 Subject: [PATCH 16/19] chore --- tests/integration/helpers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index 9941d547..81e6d822 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -43,7 +43,6 @@ def _args_str(target: Optional[str] = None, **kwargs) -> str: def apply(self, target: Optional[str] = None, **kwargs): cmd_str = f"{self.tf_cmd} apply " + self._args_str(target, **kwargs) - breakpoint() sh.terraform(shlex.split(cmd_str), _out=sys.stdout, _err=sys.stderr) def destroy(self, **kwargs): From 8a1721a1277703f579957b13c7b11200dec43136 Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Wed, 26 Nov 2025 16:19:31 -0500 Subject: [PATCH 17/19] test --- .github/workflows/_integration.yml | 2 + tests/integration/helpers.py | 68 ++++++++++++++---------------- 2 files changed, 33 insertions(+), 37 deletions(-) diff --git a/.github/workflows/_integration.yml b/.github/workflows/_integration.yml index 051ff930..550e3148 100644 --- a/.github/workflows/_integration.yml +++ b/.github/workflows/_integration.yml @@ -26,6 +26,8 @@ jobs: run: | sudo snap install concierge --classic sudo concierge prepare --juju-channel 3.6/stable -p microk8s --extra-snaps just,astral-uv,terraform + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 - name: Test deployment run: | just integration ${{ inputs.product }}/${{ matrix.scenario }} diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index 81e6d822..494e966f 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -4,52 +4,15 @@ import shutil import ssl import subprocess -import sys from pathlib import Path from typing import List, Optional from urllib.request import urlopen import psutil -import sh import jubilant -class TfDirManager: - def __init__(self, base_tmpdir): - self.base: str = str(base_tmpdir) - self.dir: str = "" - - @property - def tf_cmd(self): - return f"-chdir={self.dir}" - - def init(self, tf_file: str): - """Initialize a Terraform module in a subdirectory.""" - self.dir = os.path.join(self.base, "terraform") - os.makedirs(self.dir, exist_ok=True) - shutil.copy(tf_file, os.path.join(self.dir, "main.tf")) - sh.terraform( - shlex.split(f"{self.tf_cmd} init -upgrade"), - _out=sys.stdout, - _err=sys.stderr, - ) - - @staticmethod - def _args_str(target: Optional[str] = None, **kwargs) -> str: - target_arg = f"-target module.{target}" if target else "" - var_args = " ".join(f"-var {k}={v}" for k, v in kwargs.items()) - return "-auto-approve " + f"{target_arg} " + var_args - - def apply(self, target: Optional[str] = None, **kwargs): - cmd_str = f"{self.tf_cmd} apply " + self._args_str(target, **kwargs) - sh.terraform(shlex.split(cmd_str), _out=sys.stdout, _err=sys.stderr) - - def destroy(self, **kwargs): - cmd_str = f"{self.tf_cmd} destroy " + self._args_str(None, **kwargs) - sh.terraform(shlex.split(cmd_str), _out=sys.stdout, _err=sys.stderr) - - def print_resource_usage(): print("\n---RESOURCE USAGE---") @@ -80,6 +43,37 @@ def refresh_o11y_apps(juju: jubilant.Juju, channel: str, base: Optional[str] = N juju.refresh(app, channel=channel, base=base) +class TfDirManager: + def __init__(self, base_tmpdir): + self.base: str = str(base_tmpdir) + self.dir: str = "" + + @property + def tf_cmd(self): + return f"terraform -chdir={self.dir}" + + def init(self, tf_file: str): + """Initialize a Terraform module in a subdirectory.""" + self.dir = os.path.join(self.base, "terraform") + os.makedirs(self.dir, exist_ok=True) + shutil.copy(tf_file, os.path.join(self.dir, "main.tf")) + subprocess.run(shlex.split(f"{self.tf_cmd} init -upgrade"), check=True) + + @staticmethod + def _args_str(target: Optional[str] = None, **kwargs) -> str: + target_arg = f"-target module.{target}" if target else "" + var_args = " ".join(f"-var {k}={v}" for k, v in kwargs.items()) + return "-auto-approve " + f"{target_arg} " + var_args + + def apply(self, target: Optional[str] = None, **kwargs): + cmd_str = f"{self.tf_cmd} apply " + self._args_str(target, **kwargs) + subprocess.run(shlex.split(cmd_str), check=True) + + def destroy(self, **kwargs): + cmd_str = f"{self.tf_cmd} destroy " + self._args_str(None, **kwargs) + subprocess.run(shlex.split(cmd_str), check=True) + + def wait_for_active_idle_without_error( jujus: List[jubilant.Juju], timeout: int = 60 * 45 ): From 6a44f0e27b6fa75777cd6fb5405c014a7ac8a0e9 Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Wed, 26 Nov 2025 16:36:48 -0500 Subject: [PATCH 18/19] test --- .github/workflows/terraform.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/terraform.yml b/.github/workflows/terraform.yml index d52feee4..e9f5dd50 100644 --- a/.github/workflows/terraform.yml +++ b/.github/workflows/terraform.yml @@ -45,7 +45,7 @@ jobs: run: just validate-terraform test-integration-cos-lite: name: COS Lite Terraform integration - uses: canonical/observability-stack/.github/workflows/_integration.yml@main + uses: canonical/observability-stack/.github/workflows/_integration.yml@feat/external-ca-prom-rel with: product: cos_lite runner: ubuntu-latest From 2874d2c978b56a1f31c4073cc10c47d5fbfc62af Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Thu, 27 Nov 2025 09:38:48 -0500 Subject: [PATCH 19/19] chore: cleanup --- .github/workflows/_integration.yml | 2 - .github/workflows/terraform.yml | 2 +- pyproject.toml | 2 - .../test_upgrade_cos_tls_external.py | 3 -- .../cos/tls_full/test_upgrade_cos_tls_full.py | 3 -- .../test_upgrade_cos_tls_internal.py | 3 -- .../cos/tls_none/test_upgrade_cos_tls_none.py | 3 -- .../test_upgrade_cos_lite_tls_external.py | 7 ++- .../test_upgrade_cos_lite_tls_full.py | 7 ++- .../test_upgrade_cos_lite_tls_internal.py | 4 +- .../test_upgrade_cos_lite_tls_none.py | 4 +- tests/integration/helpers.py | 47 ++++++------------- uv.lock | 45 ++---------------- 13 files changed, 26 insertions(+), 106 deletions(-) diff --git a/.github/workflows/_integration.yml b/.github/workflows/_integration.yml index 550e3148..051ff930 100644 --- a/.github/workflows/_integration.yml +++ b/.github/workflows/_integration.yml @@ -26,8 +26,6 @@ jobs: run: | sudo snap install concierge --classic sudo concierge prepare --juju-channel 3.6/stable -p microk8s --extra-snaps just,astral-uv,terraform - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - name: Test deployment run: | just integration ${{ inputs.product }}/${{ matrix.scenario }} diff --git a/.github/workflows/terraform.yml b/.github/workflows/terraform.yml index e9f5dd50..d52feee4 100644 --- a/.github/workflows/terraform.yml +++ b/.github/workflows/terraform.yml @@ -45,7 +45,7 @@ jobs: run: just validate-terraform test-integration-cos-lite: name: COS Lite Terraform integration - uses: canonical/observability-stack/.github/workflows/_integration.yml@feat/external-ca-prom-rel + uses: canonical/observability-stack/.github/workflows/_integration.yml@main with: product: cos_lite runner: ubuntu-latest diff --git a/pyproject.toml b/pyproject.toml index 95be84ad..5d68be1e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,6 +8,4 @@ version = "0.0.0" dependencies = [ "jubilant", "pytest", - "psutil", - "sh", ] diff --git a/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py b/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py index ba3089fa..931fb5e2 100644 --- a/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py +++ b/tests/integration/cos/tls_external/test_upgrade_cos_tls_external.py @@ -10,7 +10,6 @@ from helpers import ( catalogue_apps_are_reachable, get_tls_context, - print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -38,7 +37,6 @@ def test_deploy_from_track( # GIVEN a module deployed from track n tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model, **S3_ENDPOINT) - print_resource_usage() wait_for_active_idle_without_error([cos_model], timeout=5400) tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") catalogue_apps_are_reachable(cos_model, tls_ctx) @@ -54,7 +52,6 @@ def test_deploy_to_track( refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model, **S3_ENDPOINT) - print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) diff --git a/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py b/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py index 3a9637be..7ffb87e5 100644 --- a/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py +++ b/tests/integration/cos/tls_full/test_upgrade_cos_tls_full.py @@ -10,7 +10,6 @@ from helpers import ( catalogue_apps_are_reachable, get_tls_context, - print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -38,7 +37,6 @@ def test_deploy_from_track( # GIVEN a module deployed from track n tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model, **S3_ENDPOINT) - print_resource_usage() wait_for_active_idle_without_error([cos_model], timeout=5400) tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") catalogue_apps_are_reachable(cos_model, tls_ctx) @@ -54,7 +52,6 @@ def test_deploy_to_track( refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model, **S3_ENDPOINT) - print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) diff --git a/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py b/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py index c31cd67e..d08e745d 100644 --- a/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py +++ b/tests/integration/cos/tls_internal/test_upgrade_cos_tls_internal.py @@ -9,7 +9,6 @@ from helpers import ( catalogue_apps_are_reachable, - print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -35,7 +34,6 @@ def test_deploy_from_track(tmp_path, tf_manager, cos_model: jubilant.Juju): # GIVEN a module deployed from track n tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(model=cos_model.model, **S3_ENDPOINT) - print_resource_usage() wait_for_active_idle_without_error([cos_model], timeout=5400) catalogue_apps_are_reachable(cos_model) @@ -48,7 +46,6 @@ def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(model=cos_model.model, **S3_ENDPOINT) - print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) diff --git a/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py b/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py index 82a8600c..419dfaf1 100644 --- a/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py +++ b/tests/integration/cos/tls_none/test_upgrade_cos_tls_none.py @@ -9,7 +9,6 @@ from helpers import ( catalogue_apps_are_reachable, - print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -35,7 +34,6 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): # GIVEN a module deployed from track n tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(model=cos_model.model, **S3_ENDPOINT) - print_resource_usage() wait_for_active_idle_without_error([cos_model], timeout=5400) catalogue_apps_are_reachable(cos_model) @@ -48,7 +46,6 @@ def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(model=cos_model.model, **S3_ENDPOINT) - print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) diff --git a/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py b/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py index 22ee6a23..9e028b0e 100644 --- a/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py +++ b/tests/integration/cos_lite/tls_external/test_upgrade_cos_lite_tls_external.py @@ -9,7 +9,6 @@ from helpers import ( catalogue_apps_are_reachable, get_tls_context, - print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -21,13 +20,14 @@ def test_deploy_from_track( - tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju + tmp_path, tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju ): # GIVEN a module deployed from track n-1 tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - print_resource_usage() wait_for_active_idle_without_error([ca_model, cos_model]) + tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") + catalogue_apps_are_reachable(cos_model, tls_ctx) def test_deploy_to_track( @@ -40,7 +40,6 @@ def test_deploy_to_track( refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) diff --git a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py index 55d9acd7..340d81b5 100644 --- a/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py +++ b/tests/integration/cos_lite/tls_full/test_upgrade_cos_lite_tls_full.py @@ -9,7 +9,6 @@ from helpers import ( catalogue_apps_are_reachable, get_tls_context, - print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -21,13 +20,14 @@ def test_deploy_from_track( - tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju + tmp_path, tf_manager, ca_model: jubilant.Juju, cos_model: jubilant.Juju ): # GIVEN a module deployed from track n-1 tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - print_resource_usage() wait_for_active_idle_without_error([ca_model, cos_model]) + tls_ctx = get_tls_context(tmp_path, ca_model, "self-signed-certificates") + catalogue_apps_are_reachable(cos_model, tls_ctx) def test_deploy_to_track( @@ -40,7 +40,6 @@ def test_deploy_to_track( refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(ca_model=ca_model.model, cos_model=cos_model.model) - print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([ca_model, cos_model]) diff --git a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py index 581dba9f..76a132ec 100644 --- a/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py +++ b/tests/integration/cos_lite/tls_internal/test_upgrade_cos_lite_tls_internal.py @@ -8,7 +8,6 @@ from helpers import ( catalogue_apps_are_reachable, - print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -23,8 +22,8 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): # GIVEN a module deployed from track n-1 tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(model=cos_model.model) - print_resource_usage() wait_for_active_idle_without_error([cos_model]) + catalogue_apps_are_reachable(cos_model) def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): @@ -35,7 +34,6 @@ def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(model=cos_model.model) - print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) diff --git a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py index 513807d4..1a8352c5 100644 --- a/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py +++ b/tests/integration/cos_lite/tls_none/test_upgrade_cos_lite_tls_none.py @@ -8,7 +8,6 @@ from helpers import ( catalogue_apps_are_reachable, - print_resource_usage, refresh_o11y_apps, wait_for_active_idle_without_error, ) @@ -23,8 +22,8 @@ def test_deploy_from_track(tf_manager, cos_model: jubilant.Juju): # GIVEN a module deployed from track n-1 tf_manager.init(TRACK_2_TF_FILE) tf_manager.apply(model=cos_model.model) - print_resource_usage() wait_for_active_idle_without_error([cos_model]) + catalogue_apps_are_reachable(cos_model) def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): @@ -35,7 +34,6 @@ def test_deploy_to_track(tmp_path, tf_manager, cos_model: jubilant.Juju): refresh_o11y_apps(cos_model, channel="dev/edge", base="ubuntu@24.04") tf_manager.init(TRACK_DEV_TF_FILE) tf_manager.apply(model=cos_model.model) - print_resource_usage() # THEN the model is upgraded and is healthy wait_for_active_idle_without_error([cos_model]) diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index 494e966f..84f5a6e5 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -8,41 +8,9 @@ from typing import List, Optional from urllib.request import urlopen -import psutil - import jubilant -def print_resource_usage(): - print("\n---RESOURCE USAGE---") - - one, five, fifteen = os.getloadavg() - print(f"loadavg: 1m={one:.2f}, 5m={five:.2f}, 15m={fifteen:.2f}") - - vm = psutil.virtual_memory() - available = vm.available - total = vm.total - percent_used = vm.percent - print( - f"system memory: total={total:,} bytes, available={available:,} bytes, used_percent={percent_used}%" - ) - - print("---RESOURCE USAGE---\n") - - -def refresh_o11y_apps(juju: jubilant.Juju, channel: str, base: Optional[str] = None): - """Temporary workaround for the issue: - - FIXME: https://github.com/juju/terraform-provider-juju/issues/967 - """ - for app in juju.status().apps: - if app in {"traefik", "ca"}: - continue - if "s3-integrator" in app: - continue - juju.refresh(app, channel=channel, base=base) - - class TfDirManager: def __init__(self, base_tmpdir): self.base: str = str(base_tmpdir) @@ -74,6 +42,19 @@ def destroy(self, **kwargs): subprocess.run(shlex.split(cmd_str), check=True) +def refresh_o11y_apps(juju: jubilant.Juju, channel: str, base: Optional[str] = None): + """Temporary workaround for the issue: + + FIXME: https://github.com/juju/terraform-provider-juju/issues/967 + """ + for app in juju.status().apps: + if app in {"traefik", "ca"}: + continue + if "s3-integrator" in app: + continue + juju.refresh(app, channel=channel, base=base) + + def wait_for_active_idle_without_error( jujus: List[jubilant.Juju], timeout: int = 60 * 45 ): @@ -84,7 +65,7 @@ def wait_for_active_idle_without_error( juju.wait( jubilant.all_agents_idle, delay=10, - timeout=60 * 30, + timeout=timeout, error=jubilant.any_error, ) diff --git a/uv.lock b/uv.lock index 603f6bdd..79c8b71d 100644 --- a/uv.lock +++ b/uv.lock @@ -34,14 +34,14 @@ wheels = [ [[package]] name = "jubilant" -version = "1.5.0" +version = "1.6.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d1/af/2c7d2a677389eb4de3bb841f399b749ca2fd4c6c1b70313e21249536e6be/jubilant-1.5.0.tar.gz", hash = "sha256:055c65a662586191939a1a3d3e2b6d08b71ecf0c7f403a1c7ba0cde6ecaf3bbd", size = 28433, upload-time = "2025-10-10T01:08:06.58Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b3/13/c38036a0b2d44bae765216f5f85d4feed8f1a254110b0d1df7158b7a35f0/jubilant-1.6.1.tar.gz", hash = "sha256:bb57dc215b1960d31716ef071ba6be121331991bbbbe3449257471f5e7795d06", size = 31998, upload-time = "2025-11-26T20:58:40.867Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f6/c9/05e5aa65baa7b71b17c1314b8f25744f36fd9aad60ef9fb46fd84347885a/jubilant-1.5.0-py3-none-any.whl", hash = "sha256:eec58340b9d3d478f31e18e33281638fdf0d9b84608c8935368f7a1bb1972255", size = 28275, upload-time = "2025-10-10T01:08:04.963Z" }, + { url = "https://files.pythonhosted.org/packages/e2/38/c054fa0b9de01d0b108f91f892c288bf99e68abd6593b55c2a8964de40f2/jubilant-1.6.1-py3-none-any.whl", hash = "sha256:a74ea1184eea43b9e8921dcad22ffeb14a238e91c9024f5d41fe2e210fd05be2", size = 33005, upload-time = "2025-11-26T20:58:39.566Z" }, ] [[package]] @@ -50,17 +50,13 @@ version = "0.0.0" source = { virtual = "." } dependencies = [ { name = "jubilant" }, - { name = "psutil" }, { name = "pytest" }, - { name = "sh" }, ] [package.metadata] requires-dist = [ { name = "jubilant" }, - { name = "psutil" }, { name = "pytest" }, - { name = "sh" }, ] [[package]] @@ -81,32 +77,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] -[[package]] -name = "psutil" -version = "7.1.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e1/88/bdd0a41e5857d5d703287598cbf08dad90aed56774ea52ae071bae9071b6/psutil-7.1.3.tar.gz", hash = "sha256:6c86281738d77335af7aec228328e944b30930899ea760ecf33a4dba66be5e74", size = 489059, upload-time = "2025-11-02T12:25:54.619Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/93/0c49e776b8734fef56ec9c5c57f923922f2cf0497d62e0f419465f28f3d0/psutil-7.1.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0005da714eee687b4b8decd3d6cc7c6db36215c9e74e5ad2264b90c3df7d92dc", size = 239751, upload-time = "2025-11-02T12:25:58.161Z" }, - { url = "https://files.pythonhosted.org/packages/6f/8d/b31e39c769e70780f007969815195a55c81a63efebdd4dbe9e7a113adb2f/psutil-7.1.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:19644c85dcb987e35eeeaefdc3915d059dac7bd1167cdcdbf27e0ce2df0c08c0", size = 240368, upload-time = "2025-11-02T12:26:00.491Z" }, - { url = "https://files.pythonhosted.org/packages/62/61/23fd4acc3c9eebbf6b6c78bcd89e5d020cfde4acf0a9233e9d4e3fa698b4/psutil-7.1.3-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95ef04cf2e5ba0ab9eaafc4a11eaae91b44f4ef5541acd2ee91d9108d00d59a7", size = 287134, upload-time = "2025-11-02T12:26:02.613Z" }, - { url = "https://files.pythonhosted.org/packages/30/1c/f921a009ea9ceb51aa355cb0cc118f68d354db36eae18174bab63affb3e6/psutil-7.1.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1068c303be3a72f8e18e412c5b2a8f6d31750fb152f9cb106b54090296c9d251", size = 289904, upload-time = "2025-11-02T12:26:05.207Z" }, - { url = "https://files.pythonhosted.org/packages/a6/82/62d68066e13e46a5116df187d319d1724b3f437ddd0f958756fc052677f4/psutil-7.1.3-cp313-cp313t-win_amd64.whl", hash = "sha256:18349c5c24b06ac5612c0428ec2a0331c26443d259e2a0144a9b24b4395b58fa", size = 249642, upload-time = "2025-11-02T12:26:07.447Z" }, - { url = "https://files.pythonhosted.org/packages/df/ad/c1cd5fe965c14a0392112f68362cfceb5230819dbb5b1888950d18a11d9f/psutil-7.1.3-cp313-cp313t-win_arm64.whl", hash = "sha256:c525ffa774fe4496282fb0b1187725793de3e7c6b29e41562733cae9ada151ee", size = 245518, upload-time = "2025-11-02T12:26:09.719Z" }, - { url = "https://files.pythonhosted.org/packages/2e/bb/6670bded3e3236eb4287c7bcdc167e9fae6e1e9286e437f7111caed2f909/psutil-7.1.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b403da1df4d6d43973dc004d19cee3b848e998ae3154cc8097d139b77156c353", size = 239843, upload-time = "2025-11-02T12:26:11.968Z" }, - { url = "https://files.pythonhosted.org/packages/b8/66/853d50e75a38c9a7370ddbeefabdd3d3116b9c31ef94dc92c6729bc36bec/psutil-7.1.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ad81425efc5e75da3f39b3e636293360ad8d0b49bed7df824c79764fb4ba9b8b", size = 240369, upload-time = "2025-11-02T12:26:14.358Z" }, - { url = "https://files.pythonhosted.org/packages/41/bd/313aba97cb5bfb26916dc29cf0646cbe4dd6a89ca69e8c6edce654876d39/psutil-7.1.3-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f33a3702e167783a9213db10ad29650ebf383946e91bc77f28a5eb083496bc9", size = 288210, upload-time = "2025-11-02T12:26:16.699Z" }, - { url = "https://files.pythonhosted.org/packages/c2/fa/76e3c06e760927a0cfb5705eb38164254de34e9bd86db656d4dbaa228b04/psutil-7.1.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fac9cd332c67f4422504297889da5ab7e05fd11e3c4392140f7370f4208ded1f", size = 291182, upload-time = "2025-11-02T12:26:18.848Z" }, - { url = "https://files.pythonhosted.org/packages/0f/1d/5774a91607035ee5078b8fd747686ebec28a962f178712de100d00b78a32/psutil-7.1.3-cp314-cp314t-win_amd64.whl", hash = "sha256:3792983e23b69843aea49c8f5b8f115572c5ab64c153bada5270086a2123c7e7", size = 250466, upload-time = "2025-11-02T12:26:21.183Z" }, - { url = "https://files.pythonhosted.org/packages/00/ca/e426584bacb43a5cb1ac91fae1937f478cd8fbe5e4ff96574e698a2c77cd/psutil-7.1.3-cp314-cp314t-win_arm64.whl", hash = "sha256:31d77fcedb7529f27bb3a0472bea9334349f9a04160e8e6e5020f22c59893264", size = 245756, upload-time = "2025-11-02T12:26:23.148Z" }, - { url = "https://files.pythonhosted.org/packages/ef/94/46b9154a800253e7ecff5aaacdf8ebf43db99de4a2dfa18575b02548654e/psutil-7.1.3-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2bdbcd0e58ca14996a42adf3621a6244f1bb2e2e528886959c72cf1e326677ab", size = 238359, upload-time = "2025-11-02T12:26:25.284Z" }, - { url = "https://files.pythonhosted.org/packages/68/3a/9f93cff5c025029a36d9a92fef47220ab4692ee7f2be0fba9f92813d0cb8/psutil-7.1.3-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:bc31fa00f1fbc3c3802141eede66f3a2d51d89716a194bf2cd6fc68310a19880", size = 239171, upload-time = "2025-11-02T12:26:27.23Z" }, - { url = "https://files.pythonhosted.org/packages/ce/b1/5f49af514f76431ba4eea935b8ad3725cdeb397e9245ab919dbc1d1dc20f/psutil-7.1.3-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3bb428f9f05c1225a558f53e30ccbad9930b11c3fc206836242de1091d3e7dd3", size = 263261, upload-time = "2025-11-02T12:26:29.48Z" }, - { url = "https://files.pythonhosted.org/packages/e0/95/992c8816a74016eb095e73585d747e0a8ea21a061ed3689474fabb29a395/psutil-7.1.3-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56d974e02ca2c8eb4812c3f76c30e28836fffc311d55d979f1465c1feeb2b68b", size = 264635, upload-time = "2025-11-02T12:26:31.74Z" }, - { url = "https://files.pythonhosted.org/packages/55/4c/c3ed1a622b6ae2fd3c945a366e64eb35247a31e4db16cf5095e269e8eb3c/psutil-7.1.3-cp37-abi3-win_amd64.whl", hash = "sha256:f39c2c19fe824b47484b96f9692932248a54c43799a84282cfe58d05a6449efd", size = 247633, upload-time = "2025-11-02T12:26:33.887Z" }, - { url = "https://files.pythonhosted.org/packages/c9/ad/33b2ccec09bf96c2b2ef3f9a6f66baac8253d7565d8839e024a6b905d45d/psutil-7.1.3-cp37-abi3-win_arm64.whl", hash = "sha256:bd0d69cee829226a761e92f28140bec9a5ee9d5b4fb4b0cc589068dbfff559b1", size = 244608, upload-time = "2025-11-02T12:26:36.136Z" }, -] - [[package]] name = "pygments" version = "2.19.2" @@ -198,15 +168,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, ] -[[package]] -name = "sh" -version = "2.2.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/59/52/f43920223c93e31874677c681b8603d36a40d3d8502d3a37f80d3995d43e/sh-2.2.2.tar.gz", hash = "sha256:653227a7c41a284ec5302173fbc044ee817c7bad5e6e4d8d55741b9aeb9eb65b", size = 345866, upload-time = "2025-02-24T07:16:25.363Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/70/98/d82f14ac7ffedbd38dfa2383f142b26d18d23ca6cf35a40f4af60df666bd/sh-2.2.2-py3-none-any.whl", hash = "sha256:e0b15b4ae8ffcd399bc8ffddcbd770a43c7a70a24b16773fbb34c001ad5d52af", size = 38295, upload-time = "2025-02-24T07:16:23.782Z" }, -] - [[package]] name = "tomli" version = "2.3.0"