feat: handle charm and model type mismatch at deploy#22773
Open
sinanawad wants to merge 6 commits into
Open
Conversation
Juju does not stop a Kubernetes charm being deployed to a machine model,
or a machine charm to a Kubernetes model. Unless the charm declares
"assumes: k8s-api", both directions deploy silently and then break, or
fail later on an incidental check (e.g. block storage) whose message
never mentions the real problem.
Add the classification to charm metadata, the only signal available at
deploy time on both the client and the apiserver (the charm is resolved
but not yet persisted, so state-backed checks cannot be used):
- Meta.IsSidecar reports whether the charm declares workload containers.
It intentionally matches the row-counting semantics of the model's
SupportsContainers check, so an empty "containers: {}" block does not
classify as a sidecar charm.
- Meta.ModelMismatchWarning returns a user-facing warning for the two
mismatch directions. Subordinate charms declare no containers but are
machine charms by nature, so they are never flagged on a Kubernetes
model. The check is advisory only and never blocks a deploy.
MetaFormat now uses IsSidecar in place of its inline containers check.
refers to JUJU-10101
Charmhub deploys are resolved server side via DeployFromRepository, so a charm/model type mismatch can only be detected on the apiserver, and the result carried no channel to tell the deploying user anything short of an error. Add a Warnings field to DeployFromRepositoryInfo. The validator computes mismatch warnings from the resolved charm metadata, logs them on the controller for clients that do not render results, and threads them into the returned info on both the success and the validation-error paths, so the user sees the context alongside a rejection. Before this commit, the facade only set a result's Info on the success path, silently dropping the payload for rejected deploys; it is now set unconditionally. refers to JUJU-10101
Surface the charm/model type mismatch warnings on the deploying user's terminal, in both deploy paths: - Local charm deploys hold the charm metadata client side, so the deployer checks it directly before calling the API. - Charmhub deploys print the warnings returned by DeployFromRepository, ahead of any errors, so the context is visible even when the deploy is rejected (e.g. by the block storage precheck, whose message otherwise never mentions the charm type). The warning is advisory only; deploys proceed exactly as before. refers to JUJU-10101
manadart
reviewed
Jul 2, 2026
manadart
left a comment
Member
There was a problem hiding this comment.
Just some minor ordering/semantic changes.
Return the already-built result info from every post-validation error path in DeployFromRepository, so accumulated warnings are no longer hidden from the user when the deploy is rejected after validation. Also from review: emit the client-side mismatch warning before the charm format check; drop the IAAS/CAAS jargon from the user-facing messages in favour of "Kubernetes model" and "machine model"; return a plain string from Meta.ModelMismatchWarning and test for empty at the callers; name the parameter isK8s in line with the caas-to-k8s direction. refers to JUJU-10101
From review: a charm that declares workload containers can never run them on a machine model, so this direction is now rejected with a not-supported error instead of a warning; --force downgrades the rejection to a warning, mirroring the assumes handling. The inverse direction cannot be classified with certainty (charm metadata has no positive machine charm marker), so it remains an advisory warning. Meta.ModelMismatchWarning becomes Meta.ModelMismatch, returning the warning and/or the rejection; both deploy seams honour --force. refers to JUJU-10101
| Revision int `json:"revision"` | ||
| // Warnings holds advisory, non-blocking messages about the deployment | ||
| // (e.g. a charm/model-type mismatch) for the client to surface to the user. | ||
| Warnings []string `json:"warnings,omitempty"` |
Member
There was a problem hiding this comment.
We won't need to bump the facade as this is optional, though older facade versions (19 for example) will emit the warnings, though it should be harmless.
SimonRichardson
approved these changes
Jul 2, 2026
The Warnings field added to DeployFromRepositoryInfo changed the client facade wire shape; regenerate the schema to satisfy the static-analysis schema check. refers to JUJU-10101
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Deploying a Kubernetes (sidecar) charm to a machine model, or a machine charm
to a Kubernetes model, is not something Juju guards against. Unless the charm
declares
assumes: k8s-api, both directions deploy cleanly and then breaksilently: the unit starts but the workload never runs. When the deploy does
fail, it fails on an incidental check — typically
block storage "..." is not supported for container charms— which never mentions the actual problem.At deploy time the charm is resolved but not yet persisted, so state-backed
checks are unusable on both the client and the apiserver. Charm metadata is
the only available signal, and it has no positive "machine charm" marker; what
it does have is containers:
Meta.IsSidecarandMeta.ModelMismatchclassify the charm and build therejection or warning.
IsSidecarmatches the row-counting semantics of themodel's
SupportsContainerscheck, so an emptycontainers: {}block isnot a sidecar charm, and subordinates — machine charms with no containers
by nature — are never flagged.
DeployFromRepositoryresult gains an additiveWarningsfield:charmhub deploys resolve server side, and the result previously carried
nothing short of an error back to the user. Warnings are also logged on the
controller for API clients that do not render results. The major change
is in eaa13ac.
returned
Warnings— ahead of any errors — for charmhub deploys.Before this change a mismatched deploy produced silence or a misleading
error. After it, both paths print, for example:
Per review, the two directions are treated differently. A Kubernetes charm
on a machine model is unambiguous — the declared containers can never run —
so it is now rejected with a not-supported error (
--forcedowngrades therejection to a warning, mirroring the existing
assumesbehaviour). Themachine-charm-on-Kubernetes direction is inferential (charm metadata has no
positive machine-charm marker), so it remains an advisory warning.
APIBase.DeployFromRepositorypreviously set a result'sInfoonly onsuccess, which would have dropped the warnings for rejected deploys; it is
now set unconditionally.
Bundle deploys are not instrumented — a mismatched charm inside a bundle
does not warn. The bundle seam is deliberate follow-up scope.
Checklist
Integration tests, with comments saying what you're testing(advisory output only; unit tests cover all three layers, manual QA below)doc.go added or updated in changed packages(no new packages)QA steps
Machine charm on a Kubernetes model (charmhub deploy):
Kubernetes charm on a machine model (local charm deploy):
Correct placements emit no warning:
The controller log carries the same warning for non-CLI clients:
Facade change (additive
Warningsresult field), so model migration wasverified:
The model migrated, the added unit came up active, and the only ERROR-level
log lines are the standard migration-cutover watcher shutdowns and the
fresh machine's "container types not yet available" transient; nothing
references the new field or the application facade.
The 4.0 to 4.0 leg cannot currently be exercised: it is broken on the 4.0
branch itself, independent of this change. The source side of the
password-to-macaroon exchange landed on 4.0 in #22675 and requires
MigrationTarget v8 on the target (internal/migration/auth.go:42), but the
target-side v8 facade landed on main only (#22655, #22674) and has not been
backported, so any password-authenticated 4.0 to 4.0 migration fails at
precheck with "target controller is too old...". This PR touches no
migration, auth or facade-registration files; the leg will be re-run once
v8 reaches 4.0.
Documentation changes
None — advisory warning only; theWarningsresult field is additive and noCLI flags or command shapes change.
Links
Jira card: JUJU-10101