canonical / canonical/charm-integration-testing

bundle_builder_x: cross_model_mesh is wired as a standalone interface, but it is a companion-only metadata channel

Open
#980 1 comment 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Python
Stars
6
Forks
1
Avg merge
1d 20h
Merged PRs (30d)
98

Description

> Filed by an AI agent on behalf of @canonical/solutions-qa during test failure triage. Please verify details before acting.

### Problem statement

`cross_model_mesh` (`provide-cmr-mesh` / `require-cmr-mesh`) is currently treated by both the test-plan generator and `bundle_builder_x` as an ordinary pairable interface, like `grafana_dashboard` or `metrics-endpoint`. It is not: per the interface's own documentation (`canonical/service-mesh`, `docs/explanation/cross-model-mesh.md`) and `validators/cross_model_mesh/validator.py`, `cross_model_mesh` carries no application traffic. It exists solely as a metadata side-channel so `istio-beacon-k8s` can build correct `AuthorizationPolicy` source identities for an **already-existing, genuinely cross-model** relation between the same two applications, riding the *same* Juju offer. It has no meaning as a standalone integration and no meaning at all in a single-model deployment.

Querying Test Observer's test plans (`get_test_plans(q="cross_model_mesh")`) currently returns **303 distinct test plans** that pair `provide-cmr-mesh`/`require-cmr-mesh` directly between arbitrary charm pairs across the observability/kubeflow ecosystem, e.g.:

- `admission-webhook:provide-cmr-mesh/cross_model_mesh/alertmanager-k8s:require-cmr-mesh`
- `alertmanager-k8s:provide-cmr-mesh/cross_model_mesh/kfp-ui:require-cmr-mesh`

None of these charm pairs have any other relationship to each other; there is no real cross-model relation for the mesh metadata to describe.

A concrete instance of the resulting bad bundle: test execution 919485 (mongodb-k8s revision 231/edge, test plan `mongodb-k8s:grafana-dashboard/grafana_dashboard/opentelemetry-collector-k8s:grafana-dashboards-consumer`) deploys a **single-model** environment (no Juju offers/SAAS present), yet `bundle_builder_x` wires two `cross_model_mesh` relations into the same bundle:
- `opentelemetry-collector-k8s:provide-cmr-mesh <-> grafana-k8s:require-cmr-mesh`
- `parca-k8s:provide-cmr-mesh <-> opentelemetry-collector-k8s:require-cmr-mesh` (with **no other relation at all** between `parca-k8s` and `opentelemetry-collector-k8s`)

Test Observer link: https://test-observer.canonical.com/#/charms/411048?testExecutionId=919485&testResultId=13470140

This is a variant of the invalid-test-plan class already described in #887, but specific to `cross_model_mesh`'s companion-only semantics.

### Enhancement Proposal

Two complementary mechanisms, both scoped to `bundle_builder_x`:

1. **Reject invalid standalone pairings.** Tag `provide-cmr-mesh`/`require-cmr-mesh` endpoints (via the existing per-endpoint `features` override mechanism) and extend the constraint solver so that a `cross_model_mesh` integration is only satisfiable when it accompanies a genuine, already cross-model relation between the same two applications (on the same offer). A standalone/local-only `cross_model_mesh` pairing should make the bundle build fail cleanly (`UncompletableBundleError` or equivalent) rather than silently producing an invalid bundle that fails at runtime. Once this is in place, the ~303 test plans that only ever request a standalone `cross_model_mesh` pairing will fail deterministically at bundle-build time; a filtered Test Observer **attachment rule** can then auto-attach a single explanatory issue to these, instead of requiring manual per-execution triage.

2. **Add a constraint primitive for the mandatory direction.** `bundle_builder_x`'s internal domain model already has `Domain.is_cross_model(integration)`, used today inside `_reachable_set`'s Z3 lowering (`dsl_lowering.py`). Expose an equivalent primitive in the public constraint DSL (`constraints_dsl.py`), e.g. `cross_model(endpoint[x])`, so per-charm override YAML can express the converse rule: whenever a real interface *is* actually integrated across models, `provide-cmr-mesh`/`require-cmr-mesh` becomes **required**, not merely optional — e.g.:

```
cross_model(endpoint[grafana-dashboard]) => bool(endpoint[provide-cmr-mesh])
```

This replaces today's per-charm, per-track "mark it optional and hope the solver only wires it opportunistically when needed" pattern (see `static/charm-overrides/grafana-k8s.yaml`, `static/charm-overrides/opentelemetry-collector-k8s.yaml`) with a rule that is both stricter (rejects invalid local wiring) and more complete (mandates it when genuinely needed).

### What needs to get done?

- [ ] Add a `features`/constraint-based rejection rule to `bundle_builder_x` so `cross_model_mesh` integrations are unsatisfiable unless they accompany a genuine cross-model relation between the same two apps on the same offer.
- [ ] Add a `cross_model(endpoint[x])` primitive to the constraint DSL (parser in `constraints_dsl.py`, lowering in `dsl_lowering.py`), backed by the existing `Domain.is_cross_model()`.
- [ ] Update `static/charm-overrides/*.yaml` for charms with `cross_model_mesh` endpoints (e.g. `grafana-k8s`, `opentelemetry-collector-k8s`, `parca-k8s`, `alertmanager-k8s`, `istio-beacon-k8s`) to use the new mandatory-when-CMR constraint instead of a bare `optional: true`.
- [ ] Once bundle-build failures for invalid standalone `cross_model_mesh` pairings are deterministic, create a filtered Test Observer attachment rule to auto-triage the affected test plans.

Contributor guide

Open the contributing guide

Research direction

Start with constraints_dsl.py and dsl_lowering.py, then inspect Domain.is_cross_model() and the existing bundle_builder_x constraint handling. Review the cross_model_mesh overrides in static/charm-overrides/*.yaml, especially the named charm files. Done means invalid standalone pairings are rejected, the DSL exposes the mandatory cross-model constraint, affected overrides are updated, and the Test Observer attachment rule is defined.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
testing, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.