controller

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 7, 2026 License: Apache-2.0 Imports: 31 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ClusterProjectionReconciler added in v0.3.0

type ClusterProjectionReconciler struct {
	*ControllerDeps

	// SourceMode is the cluster-admin-configured policy for which source
	// objects are projectable. Empty string defaults to SourceModeAllowlist.
	// Mirrors the namespaced reconciler's flag — both honor the same
	// projectable-annotation veto and the same allowlist/permissive modes.
	SourceMode SourceMode

	// RequeueInterval controls how long the reconciler sleeps before
	// retrying after a failed reconcile. Defaults to 30 seconds when unset
	// (filled by SetupWithManager).
	RequeueInterval time.Duration

	// SelectorWriteConcurrency caps the number of in-flight destination
	// writes during selector-based fan-out. Bounded so a CR matching
	// thousands of namespaces doesn't burst the apiserver. Defaults to
	// 16 when SetupWithManager runs against a zero value.
	SelectorWriteConcurrency int

	// Controller and Cache are captured by SetupWithManager so Reconcile
	// can lazily register source / destination watches as new GVKs appear.
	// Both are nil in unit-test paths that call Reconcile directly without
	// SetupWithManager — the watch helpers no-op in that mode.
	Controller controller.Controller
	Cache      cache.Cache
	// contains filtered or unexported fields
}

ClusterProjectionReconciler reconciles cluster-scoped ClusterProjection objects: a single source object is fanned out to many destination namespaces selected either by an explicit list or a label selector.

State separated from ProjectionReconciler because the two reconcilers must not contend on the same source-watch and dest-watch maps — distinct ownership tiers, distinct enqueue paths, distinct cleanup semantics. Apiserver-facing dependencies are shared via *ControllerDeps.

func (*ClusterProjectionReconciler) Reconcile added in v0.3.0

func (*ClusterProjectionReconciler) SetupWithManager added in v0.3.0

func (r *ClusterProjectionReconciler) SetupWithManager(mgr ctrl.Manager) error

SetupWithManager wires the cluster reconciler to the manager.

Three things happen here that Reconcile relies on:

  1. A field indexer on ClusterProjection.spec indexes each CR by the canonical sourceKey of its source ref (mapSource resolves source events through this).
  2. A field indexer on ClusterProjection.metadata.uid indexes each CR by UID (ensureClusterDestWatch resolves dest events through this in O(1)).
  3. A namespace watch is registered on the builder so a namespace gaining or losing a selector label re-enqueues every affected ClusterProjection — without this, the only catch-up path would be the periodic resync.

We use .Build(r) (not .Complete(r)) to capture the controller.Controller so Reconcile can lazily register source / destination watches.

type ControllerDeps added in v0.3.0

type ControllerDeps struct {
	client.Client
	Scheme        *runtime.Scheme
	DynamicClient dynamic.Interface
	RESTMapper    apimeta.RESTMapper
	Recorder      events.EventRecorder
}

ControllerDeps bundles dependencies shared by every projection reconciler (namespaced and cluster-scoped). Each reconciler embeds one. Reconciler- specific state (the watched-sources map, the controller handle, requeue interval, source mode, …) lives on the reconciler itself, not here.

Exported so cmd/main.go can construct it. Field names match the historical ProjectionReconciler shape so existing callers (cmd/main.go, tests) keep compiling with only the construction-shape change of wrapping the apiserver dependencies in `ControllerDeps: &ControllerDeps{...}`.

type ProjectionReconciler

type ProjectionReconciler struct {
	// ControllerDeps bundles the apiserver-facing dependencies shared with
	// ClusterProjectionReconciler (Client, Scheme, DynamicClient,
	// RESTMapper, Recorder). Embedded so `r.Client`, `r.Scheme`, etc. continue
	// to resolve via promotion and existing callsites read unchanged. Pointer
	// embedding lets cmd/main.go and tests build the reconciler with a single
	// composite literal where the apiserver dependencies live behind one field.
	*ControllerDeps

	// SourceMode is the cluster-admin-configured policy for which source
	// objects are projectable. Empty string defaults to SourceModeAllowlist.
	SourceMode SourceMode

	// RequeueInterval controls how long the reconciler sleeps before
	// retrying after a successful or failed reconcile. Configured via the
	// --requeue-interval CLI flag. Defaults to 30 seconds when unset
	// (SetupWithManager fills the zero value so unit-test constructions
	// don't need to set it explicitly).
	RequeueInterval time.Duration

	// Controller is the underlying controller.Controller we built in
	// SetupWithManager. We need it so Reconcile can register new source
	// watches lazily as previously-unseen source GVKs show up. It is nil
	// in unit tests that call Reconcile directly without SetupWithManager.
	Controller controller.Controller
	// Cache is the manager's cache, used as the source for dynamic watches.
	// Also nil in direct-reconcile unit tests.
	Cache cache.Cache
	// contains filtered or unexported fields
}

ProjectionReconciler reconciles a (namespaced) Projection object. The Projection mirrors a single source object into the Projection's own namespace; cross-namespace fan-out lives on the cluster-scoped sibling (ClusterProjection) and its dedicated reconciler.

func (*ProjectionReconciler) Reconcile

func (r *ProjectionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)

func (*ProjectionReconciler) SetupWithManager

func (r *ProjectionReconciler) SetupWithManager(mgr ctrl.Manager) error

SetupWithManager sets up the controller with the Manager.

Three things happen here that Reconcile relies on:

  1. A field indexer on Projection.spec indexes each CR by the canonical sourceKey of its source ref, so mapSource can list all projections referencing a changed source via a single cached List.
  2. A field indexer on Projection.metadata.uid lets ensureDestWatch's handler resolve a destination's UID-label value back to its owner in O(1) (single cached List, no full-cluster scan).
  3. We use .Build(r) (not .Complete(r)) to capture the controller.Controller so Reconcile can lazily register source / destination watches as previously-unseen GVKs appear. No up-front watches — Reconcile adds them on demand.

type SourceMode

type SourceMode string

SourceMode controls which source objects the operator is willing to project. Configured once per controller via the --source-mode flag.

const (
	// SourceModePermissive allows any source object to be projected. Source
	// owners can still veto individual objects with the
	// projection.sh/projectable="false" annotation.
	SourceModePermissive SourceMode = "permissive"

	// SourceModeAllowlist requires every source object to carry the
	// projection.sh/projectable="true" annotation before it can be
	// mirrored. This is the default — Kubernetes convention favors
	// opt-in for cluster-scoped operators with broad read RBAC.
	SourceModeAllowlist SourceMode = "allowlist"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL