Description
Raised as GitHub issue #39, the full-vend half of a two-part request from a Kubernetes-platform operator team. Their tenancy model creates a project CR per environment, and they want a new project appearing to produce a whole Grafana Cloud stack, from a template, with no human writing a request. The narrower request for content into an already-existing stack is tracked separately as GCV-0079.
WHAT IS ALREADY THERE, and what is not. The stack itself is the oldest and most exercised surface in this platform: GrafanaCloudStackRequest vends a stack, its administrator and telemetry credential chains, its per-stack ProviderConfig and its baseline content, and GCV-0032 settled multi-organization vending. So this issue adds almost nothing to the composition function. What it adds is a TRIGGER and a TEMPLATE, and both sit outside the composition layer.
THE TRIGGER. Nothing in this repository reads a third-party CR, from any cluster. The ApplicationSet watches exactly top-level enabled/* and scripts/validate.sh asserts that equality, precisely so inert examples cannot become live requests. Widening that glob is the wrong answer and the gate will refuse it. The right answer is a separate component that observes project CRs and writes a claim - a controller, a generator, or an ApplicationSet generator pointed at the project CRs - and the choice of which, and whether it lives in this repository at all, is the first decision. GCV-0079 needs the same component, so whichever is built first owns that decision and the other consumes it.
THE TEMPLATE. A claim generated from a CR has to get its values from somewhere: which fields come from the project CR, which are fixed by the platform, and what happens to a project whose CR carries a value the request schema refuses. The usage classification is a constrained enum, the organization field is required and immutable, and the output identity is derived from both, so a generated claim can be refused on rules a hand-written one would never hit. The generated claim must be reviewable before it reconciles, or an operator cannot tell a templating mistake from a vendor refusal.
TWO CONSEQUENCES worth naming now. Automatic vending removes the human step that today bounds how many stacks exist, so the template needs a cap or an approval seam, not just a mapping. And stack decommission is non-destructive by design here, so a project CR disappearing must not be wired to stack deletion without the owner-authorised decommission path.
The requesting team’s own identifiers, cluster names and stack slugs are deliberately absent: write the shape, never the instance.
Acceptance Criteria
- #1 The mechanism that turns an external project CR into a stack request is chosen and recorded, with the alternatives considered, and it does not widen the ApplicationSet watch path beyond enabled/*
- #2 The mapping from project CR to request fields is explicit, states which values the platform fixes, and states what happens to a project whose CR value the request schema refuses
- #3 A generated request is reviewable before it reconciles, and a templating error is distinguishable from a vendor refusal without reading provider logs
- #4 The blast radius of automatic vending is bounded by an explicit cap or approval seam, not only by the rate projects are created
- #5 A project CR disappearing does not delete a vended stack except through the existing owner-authorised decommission path
- #6 Whether this component belongs in this repository or in the consuming platform is recorded as a decision, given the public-reference constraint
Definition of Done
- #1 just check passes locally
- #2 hosted Validate workflow passes on the completing commit