Documentation
¶
Overview ¶
Package admission is the control-plane admission framework (ADR-0063): a two-phase pipeline (mutate-all → validate-all) of single-purpose Admissions run on every resource write, after authz and before the store. It generalizes the former inline obj.Validate() admit step (ADR-0018) and opens the cross-resource/Delete extension point (ADR-0064 links consume it).
It is a near-leaf: it imports api/types, internal/auth, api/fault only — it nests under internal/controlplane but must NOT import its parent package (no cycle).
Index ¶
- func FindCycle(start string, adj map[string][]string) string
- func Members(ctx context.Context, r StoreReader, ns v1.NamespaceName, ...) ([]v1.Object, error)
- type Admission
- func NewBackupScheduleAdmission(storeURL string) Admission
- func NewBackupSpecImmutableAdmission() Admission
- func NewBackupTTLAdmission(r StoreReader) Admission
- func NewBindingDeclaredAdmission(r StoreReader) Admission
- func NewBucketDeletionProtectionAdmission(r StoreReader, p BlobProber) Admission
- func NewBucketQuotaAdmission(r StoreReader, maxPerNamespace int) Admission
- func NewCatalogStoreOwnerAdmission() Admission
- func NewFunctionStoreOwnerAdmission() Admission
- func NewKVStoreDeletionProtectionAdmission(r StoreReader, p KVProber) Admission
- func NewKVStoreQuotaAdmission(r StoreReader, maxPerNamespace int) Admission
- func NewLinkDeletionProtectionAdmission(r StoreReader) Admission
- func NewLinkValidityAdmission(r StoreReader) Admission
- func NewPolicyValidityAdmission() Admission
- func NewResourceGroupDeletionProtectionAdmission(r StoreReader) Admission
- func NewRestoreInPlaceAdmission(authz auth.Authorizer, r StoreReader, h *hold.Hold) Admission
- func NewSQLDatabaseDeletionProtectionAdmission(r StoreReader, p SQLProber) Admission
- func NewSQLDatabaseQuotaAdmission(r StoreReader, maxPerNamespace int) Admission
- func NewSitePrefixImmutableAdmission() Admission
- func NewValidateAdmission() Admission
- func NewWorkflowRunContractAdmission(r workflowGetter) Admission
- func NewWorkflowRunPayloadAdmission(limit int64) Admission
- func NewWorkflowRunSpecImmutableAdmission() Admission
- type BlobProber
- type Declared
- type KVProber
- type NamespaceReading
- type Operation
- type Phase
- type Pipeline
- type Request
- type SQLProber
- type StoreReader
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FindCycle ¶ added in v0.10.0
FindCycle runs a coloured DFS from start over adj and returns the cycle path (or "" if none reachable). A self-edge (start → start) is detected as a degenerate cycle. link-validity and app-requires (ADR-0219) use it.
func Members ¶ added in v0.4.0
func Members(ctx context.Context, r StoreReader, ns v1.NamespaceName, group v1.ResourceGroupName) ([]v1.Object, error)
Members returns the members of ResourceGroup group in ns (ADR-0170 Decision 7): every object of a namespaced kind other than ResourceGroup, in ns, whose metadata.resourceGroup is group and that no controller owns (a controlled child goes with its owner). Platform-written records (WorkflowRuns, Invocations) count.
Types ¶
type Admission ¶
type Admission interface {
// Name identifies the admission in errors and ordering (stable, kebab-case).
Name() string
// Phase is Mutating or Validating.
Phase() Phase
// Handles reports whether this admission applies to the given GVK + operation.
Handles(gvk v1.GroupVersionKind, op Operation) bool
// Admit reviews req and returns the (possibly-mutated) object, or a fault error denying the write.
Admit(ctx context.Context, req Request) (v1.Object, error)
}
Admission reviews a write before it is persisted. Deterministic and side-effect-free. A Validating admission returns req.Object on allow, or a fault error (Invalid/Forbidden/Conflict/PayloadTooLarge) on deny. A Mutating admission returns the object to carry forward, or a fault error.
func NewBackupScheduleAdmission ¶ added in v0.11.0
NewBackupScheduleAdmission returns the Validating admission of a BackupSchedule's recipients and target: the recipients follow ADR-0204 Decision 2's rules (envelope.Parse), and a target inside the blob store, storeURL (blob.target or the file:// URL of blob.dir), is refused naming spec.target.url. A target on the store's provider is stored; the schedule's Ready reason says SameProvider.
func NewBackupSpecImmutableAdmission ¶ added in v0.11.0
func NewBackupSpecImmutableAdmission() Admission
NewBackupSpecImmutableAdmission returns the Validating admission that refuses a change to a Backup's or a Restore's spec: a run record and a request are fixed at creation, as a Site's prefix is.
func NewBackupTTLAdmission ¶ added in v0.11.0
func NewBackupTTLAdmission(r StoreReader) Admission
NewBackupTTLAdmission returns the Validating admission that refuses a Backup whose spec.ttl exceeds its schedule's ttl. Without the schedule it admits: the run fails ScheduleNotFound (no link-validity admission, ADR-0121).
func NewBindingDeclaredAdmission ¶ added in v0.15.0
func NewBindingDeclaredAdmission(r StoreReader) Admission
NewBindingDeclaredAdmission returns the Validating admission "binding-declared" (ADR-0248 Decision 2): every store, catalog, ConfigMap and Secret a Function binds, its catalog entries' bindings included, is declared at its root, and every binding of an image step is declared at its Workflow's (ADR-0250 Decision 2). A part of an App binds what the App declares too: Request.Declared under app-parts, else read from r for an object an App controls, so a direct write of a part passes as the App's own did. A step Function binds what its Workflow declares. A Site's one bucket is Site.Validate's. A standalone CatalogService's blob, config and secret bindings are declared at its root (ADR-0251 Decision 2); an App's catalog binds buckets the App declares. It replaces ADR-0229's workflow-step-stores.
func NewBucketDeletionProtectionAdmission ¶
func NewBucketDeletionProtectionAdmission(r StoreReader, p BlobProber) Admission
NewBucketDeletionProtectionAdmission returns the Validating admission that protects Bucket data (ADR-0080). On Delete: Conflict if any Function.spec.bindings.blob names the bucket OR any prefix still holds objects. On Update: Conflict if a prefix removed from spec.prefixes[] is still named by some Function.spec.bindings.blob OR still holds objects. (Clone of kvstore-deletion-protection, scanning spec.bindings.blob.) The prober is optional — a nil prober skips the data-emptiness check (binding-protection still applies).
func NewBucketQuotaAdmission ¶
func NewBucketQuotaAdmission(r StoreReader, maxPerNamespace int) Admission
NewBucketQuotaAdmission returns the Validating admission that rejects creating a Bucket when its namespace already holds maxPerNamespace buckets (ADR-0080 bucket-count quota). maxPerNamespace ≤ 0 disables the quota.
func NewCatalogStoreOwnerAdmission ¶ added in v0.15.0
func NewCatalogStoreOwnerAdmission() Admission
NewCatalogStoreOwnerAdmission returns the Mutating admission "catalog-store-owner" (ADR-0251 Decisions 1 and 4), the twin of function-store-owner: an omitted owner of a prefix a standalone CatalogService defines at its root becomes the CatalogService, and a bindings.config entry naming a ConfigMap it defines becomes that ConfigMap's stored name.
func NewFunctionStoreOwnerAdmission ¶ added in v0.15.0
func NewFunctionStoreOwnerAdmission() Admission
NewFunctionStoreOwnerAdmission returns the Mutating admission "function-store-owner": an omitted owner of a table, a prefix or a database the Function defines at its root becomes the Function (Decision 4), and a bindings.config entry naming a ConfigMap it defines becomes that ConfigMap's stored name (Decision 5), also when it names an earlier stored name of it, so the environment, the pool key and the GC read the name that holds the data.
func NewKVStoreDeletionProtectionAdmission ¶
func NewKVStoreDeletionProtectionAdmission(r StoreReader, p KVProber) Admission
NewKVStoreDeletionProtectionAdmission returns the Validating admission that protects KVStore data (ADR-0073). On Delete: Conflict if any Function.spec.bindings.kv names the store OR it still holds keys. On Update: Conflict if a table removed from spec.tables[] is still named by some Function.spec.bindings.kv, or if an added table still holds the data of its removed namesake (not yet reclaimed by the reconciler, which only diffs the current spec against the live data). (Clone of link-deletion-protection, scanning spec.bindings.kv.)
func NewKVStoreQuotaAdmission ¶
func NewKVStoreQuotaAdmission(r StoreReader, maxPerNamespace int) Admission
NewKVStoreQuotaAdmission returns the Validating admission that rejects creating a KVStore when its namespace already holds maxPerNamespace stores (ADR-0072 store-count quota). maxPerNamespace ≤ 0 disables the quota.
func NewLinkDeletionProtectionAdmission ¶
func NewLinkDeletionProtectionAdmission(r StoreReader) Admission
NewLinkDeletionProtectionAdmission returns the Validating admission that rejects deleting a Function that is another Function's link target (ADR-0064). It reads Request.Old.
func NewLinkValidityAdmission ¶
func NewLinkValidityAdmission(r StoreReader) Admission
NewLinkValidityAdmission returns the Validating admission that enforces ADR-0064's cross-resource link rules on Create/Update: every link target exists in the namespace, and the namespace link graph stays acyclic with the applied function (a self-link is a degenerate cycle).
func NewPolicyValidityAdmission ¶
func NewPolicyValidityAdmission() Admission
NewPolicyValidityAdmission returns the Validating admission that enforces ADR-0074's Policy rules on a Policy Create/Update: spec.cedar PARSES as Cedar and references only the curated actions + entity types (kv::read/kv::write; Function/KVStore/KVTable), and its scopes name no entity of another namespace (ADR-0177). An un-parseable, off-schema or foreign-namespace Policy is rejected (fault.Invalid) before it reaches the metastore — so the cedar driver can rely on every stored Policy compiling. (Shape cloned from the link/KV validity admissions.)
func NewResourceGroupDeletionProtectionAdmission ¶ added in v0.4.0
func NewResourceGroupDeletionProtectionAdmission(r StoreReader) Admission
NewResourceGroupDeletionProtectionAdmission returns the Validating admission that refuses deleting a ResourceGroup while it has a member (ADR-0170 Decision 7), naming up to five members and the count.
func NewRestoreInPlaceAdmission ¶ added in v0.11.0
func NewRestoreInPlaceAdmission(authz auth.Authorizer, r StoreReader, h *hold.Hold) Admission
NewRestoreInPlaceAdmission returns the Validating admission of a Restore with an inPlace member: its create needs update on the Namespace (the built-in RBAC gives it to an admin only) and is refused while another in-place Restore of the namespace has not ended, since they would share the namespace's restore hold; its delete is refused until it has ended, so the hold keeps the Restore that names it. A create is also refused while the namespace carries a restore marker, which only hold release --namespace lifts once its load did not complete; h nil holds nothing. It reads Request.Old on a delete.
func NewSQLDatabaseDeletionProtectionAdmission ¶ added in v0.13.0
func NewSQLDatabaseDeletionProtectionAdmission(r StoreReader, p SQLProber) Admission
NewSQLDatabaseDeletionProtectionAdmission returns the Validating admission that refuses deleting a SQLDatabase that a Function's spec.bindings.sql binds (ADR-0233 Decision 7), or whose engine holds a user table, or whose data cannot be checked (fail closed). A controller's delete through the store is not checked.
func NewSQLDatabaseQuotaAdmission ¶ added in v0.13.0
func NewSQLDatabaseQuotaAdmission(r StoreReader, maxPerNamespace int) Admission
NewSQLDatabaseQuotaAdmission returns the Validating admission that rejects creating a SQLDatabase when its namespace already holds maxPerNamespace databases. maxPerNamespace ≤ 0 disables the quota.
func NewSitePrefixImmutableAdmission ¶
func NewSitePrefixImmutableAdmission() Admission
NewSitePrefixImmutableAdmission returns the Validating admission that rejects any change to spec.bindings.blob[0].prefix on Update. The reconciler only ever adds prefixes to the Bucket, so a changed prefix would orphan the old one with its objects (ADR-0139 Decision §7). It needs no dependencies — Old and Object are both on the Request — and it never consults Old.Status, which an apply wipes.
func NewValidateAdmission ¶
func NewValidateAdmission() Admission
NewValidateAdmission returns the built-in Validating admission that runs obj.Validate() for every kind on Create and Update.
func NewWorkflowRunContractAdmission ¶
func NewWorkflowRunContractAdmission(r workflowGetter) Admission
NewWorkflowRunContractAdmission returns the Validating admission that checks a WorkflowRun's spec.input against its parent Workflow's CACHED status.contract.input (ADR-0098) — zero registry I/O. A parent that is absent or not-yet-Ready (no cached contract) is allowed: the engine's run-start gate is the backstop, and a dangling spec.workflow is the run reconciler's concern.
func NewWorkflowRunPayloadAdmission ¶
NewWorkflowRunPayloadAdmission returns the Validating admission that rejects a WorkflowRun whose spec.input exceeds the payload cap (ADR-0094: run payloads are size-bounded control-plane metadata; larger data travels by reference on the blob substrate). limit ≤ 0 disables the cap.
func NewWorkflowRunSpecImmutableAdmission ¶ added in v0.2.1
func NewWorkflowRunSpecImmutableAdmission() Admission
NewWorkflowRunSpecImmutableAdmission returns the Validating admission that rejects an Update changing a WorkflowRun's spec.workflow, spec.input or spec.replay. The engine runs a run's spec once, so a second run applied under an existing name is rejected (ADR-0094 duplicate-run-name-rejected) instead of replacing the record of what ran; spec.paused and spec.cancel stay mutable.
type BlobProber ¶
type BlobProber interface {
// HasAny reports whether any object exists under the prefix of the namespace's bucket.
HasAny(ctx context.Context, ns v1.NamespaceName, bucket v1.ObjectName, prefix string) (bool, error)
}
BlobProber probes whether a Bucket prefix holds any objects (ADR-0080): the deletion-protection admission uses it to block deleting a bucket (or removing a prefix) that still holds data. Declared HERE (like KVProber/StoreReader) so the admission package stays a near-leaf; the wiring resolves the Bucket to the substrate view the s3gateway writes, so the key layout has one owner. Optional — a nil prober skips the data-emptiness check (binding-protection still applies).
type Declared ¶ added in v0.15.0
type Declared struct {
// contains filtered or unexported fields
}
Declared is what a resource's root declares, by kind and name (ADR-0248 Decision 2): its name and ref entries, a defined ConfigMap under its name and its stored name, and its Secret declarations.
func RootDeclared ¶ added in v0.15.0
func RootDeclared(kv []v1.KVStoreEntry, buckets []v1.BucketEntry, sql []v1.SQLDatabaseEntry, catalogs []v1.CatalogEntry, configMaps []v1.ConfigMapEntry, secrets []v1.SecretDeclaration) *Declared
RootDeclared is what these root entries declare.
type KVProber ¶
type KVProber interface {
// HasAny reports whether any key exists under prefix.
HasAny(ctx context.Context, prefix string) (bool, error)
}
KVProber probes whether a KVStore holds any keys (ADR-0072): the deletion-protection admission uses it to block deleting a store that still holds data. Declared HERE (like StoreReader) so the admission package stays a near-leaf; the wiring adapts the kvstore driver's List to it.
type NamespaceReading ¶ added in v0.4.0
type NamespaceReading interface {
ReadsNamespace() bool
}
NamespaceReading marks an admission that needs the namespace's admission lock (ADR-0147): two concurrent writes it admits could store a state no sequential order of them allows. The control plane holds the lock from the Old fetch through the store write.
type Phase ¶
type Phase int
Phase orders an admission: all Mutating run (threading the object), then all Validating.
type Pipeline ¶
type Pipeline struct {
// contains filtered or unexported fields
}
Pipeline runs the registered admissions for a write: all Mutating (threading the object), then all Validating. Construct once at server start with NewPipeline; it is read-only thereafter.
func NewPipeline ¶
NewPipeline registers admissions, partitioning by Phase; registration order within a phase is preserved (it is the deterministic tie-break).
func (*Pipeline) Admit ¶
Admit runs all Mutating admissions (threading req.Object — each may transform it), then all Validating ones (each sees the final object), skipping any whose Handles is false. The first fault error short-circuits. Returns the final (possibly-mutated) object.
func (*Pipeline) Handles ¶
func (p *Pipeline) Handles(gvk v1.GroupVersionKind, op Operation) bool
Handles reports whether any registered admission applies to (gvk, op) — lets a caller skip an Old-object fetch on Delete when nothing admits deletes.
func (*Pipeline) ReadsNamespace ¶ added in v0.4.0
func (p *Pipeline) ReadsNamespace(gvk v1.GroupVersionKind, op Operation) bool
ReadsNamespace reports whether any admission handling (gvk, op) implements NamespaceReading and returns true: the write must hold its namespace's admission lock (ADR-0147).
type Request ¶
type Request struct {
Operation Operation
GVK v1.GroupVersionKind
Object v1.Object
Old v1.Object
Identity auth.Identity
Declared *Declared
}
Request is one admission review. Object is the incoming desired object (nil on Delete); Old is the stored object (nil on Create; set on Update/Delete). GVK is the route's kind (authoritative, not body-derived). Identity is the authenticated caller (authz already passed). Declared is set when app-parts reviews an App's part: what the App's root declares, which the part binds without a root entry of its own (ADR-0248 Decision 2).
type SQLProber ¶ added in v0.13.0
type SQLProber interface {
HasTables(ctx context.Context, ns v1.NamespaceName, name v1.ObjectName) (bool, error)
}
SQLProber reports whether a SQLDatabase's engine holds a user table (ADR-0232 Decision 7). It fails Unavailable when the engine cannot answer but the database has data on disk.
type StoreReader ¶
type StoreReader interface {
List(ctx context.Context, gvk v1.GroupVersionKind, ns v1.NamespaceName) ([]v1.Object, error)
}
StoreReader is the read-only store view a cross-resource admission needs. It is a subset of store.Store declared here so the admission package stays a near-leaf (the wiring adapts the real store.Store to this interface).