Documentation
¶
Overview ¶
Package function is the Function lifecycle reconciler (ADR-0020): the one controller.Reconciler for KindFunction. It stamps immutable Revisions, schedules + provisions workers via the runtime port to the EFFECTIVE desired replica count (honoring the activator's wake Status.Phase, not blindly spec.replicas), validates the shape (materialization gate — no route to a broken function), programs the gateway with the FULL route table (gateway.ProgramRoutes is replace-all), and writes status. It also provides the production activator.Endpoints (the seam ADR-0016 deferred to P-M).
Index ¶
- type ArtifactResolver
- type CatalogProxies
- type Deps
- type EndpointMode
- type FileMaterializer
- type InvokeSocketProvider
- type Materializer
- type PlatformResolver
- type Reconciler
- func (r *Reconciler) Close() error
- func (r *Reconciler) Endpoints() activator.Endpoints
- func (r *Reconciler) MapAccess(ctx context.Context, obj v1.Object) []controller.Request
- func (r *Reconciler) MapCatalogService(ctx context.Context, obj v1.Object) []controller.Request
- func (r *Reconciler) MapPoolDisplaced(ctx context.Context, obj v1.Object) []controller.Request
- func (r *Reconciler) MapRevision(_ context.Context, obj v1.Object) []controller.Request
- func (r *Reconciler) PoolMembers(ns v1.NamespaceName, worker v1.ObjectName) (members []v1.ObjectName, isMember func(name string) bool, ok bool)
- func (r *Reconciler) Reconcile(ctx context.Context, req controller.Request) (controller.Result, error)
- type S3GatewayInjection
- type SecretResolver
- type ShapeValidator
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ArtifactResolver ¶
type ArtifactResolver interface {
Resolve(ctx context.Context, uri string) (digest string, err error)
}
ArtifactResolver resolves an OCI artifact ref (tag) to its digest (ADR-0035), so the reconciler can pin it into the immutable Revision at stamp time instead of the user typing it. The oras driver implements it; the file driver needs none (file:// has no digest). Optional in Deps: nil → no resolution (file/legacy mode).
type CatalogProxies ¶ added in v0.4.0
type CatalogProxies interface {
ProxyURL(ns v1.NamespaceName, name v1.ObjectName) (string, bool)
}
CatalogProxies reports the URL of a CatalogService's PEP proxy listener bound in this daemon run (ADR-0137, ADR-0162), false when none is bound. Satisfied by *cataloggw.Manager.
type Deps ¶
type Deps struct {
Store store.Store
Runtime runtime.Runtime
Scheduler scheduler.Scheduler
Gateway gateway.Gateway
Validator ShapeValidator
Logger *slog.Logger
// LogMaxRecordBytes is FUNCD_FUNCLOG_MAX_RECORD_BYTES for every shim and pool host (ADR-0168); 0 sets none.
LogMaxRecordBytes int
// Materializer + ShimCommand enable real function execution (ADR-0030): the
// reconciler materializes the artifact and launches the runtime shim, and gates
// readiness on the shim's /health/readiness. When Materializer is nil the reconciler
// runs the legacy long-lived placeholder (ADR-0020) — used by the runtime-port tests.
Materializer Materializer
ShimCommand []string // launch prefix for the DEFAULT shim, e.g. ["node", "/.../shim.mjs"]
// ShimCommandsByFamily maps a runtime-family prefix → its shim launch prefix (ADR-0049): a
// function whose spec.runtime starts with the key (e.g. "python") is launched with that
// command instead of ShimCommand. Empty ⇒ every runtime uses the default ShimCommand (node).
ShimCommandsByFamily map[string][]string
// Resolver (ADR-0035) resolves an OCI artifact ref → digest at Revision-stamp time, so
// the user need not pin the digest. nil → no resolution (file:// dev / legacy mode).
Resolver ArtifactResolver
// Platforms (ADR-0145) lists an artifact digest's platforms for the placement gate. nil → no gate.
Platforms PlatformResolver
// EndpointMode + ImageFor select container execution (ADR-0032). EndpointLoopback
// (default) is the process driver: ShimCommand launches the shim, loopback+portfile.
// EndpointNetnsFixedPort is the containerd driver: the shim is the curated IMAGE's
// entrypoint (Command empty), the artifact is bind-mounted, and it binds a fixed port
// on the netns IP. ImageFor maps fn.Spec.Runtime → the curated image ref.
EndpointMode EndpointMode
ImageFor func(runtime string) string
// PoolShimCommand enables worker pooling (ADR-0046): the launch prefix for the pooled
// worker_threads host (e.g. ["node", "/.../pool.mjs"]). When set, a function declaring
// spec.pooling.worker co-locates with same-key peers in one pool worker launched with
// this command + FUNCD_POOL_MANIFEST. Empty ⇒ pooling is off (every function is solo).
PoolShimCommand []string
// PoolShimsByFamily maps a runtime-family prefix → its pool-host launch prefix (ADR-0050): a
// python* function that opts in co-pools via this host (the subinterpreter pool.py) instead of
// staying solo. Empty ⇒ only PoolShimCommand (node) pools; a family with no host runs solo.
PoolShimsByFamily map[string][]string
// PoolLimit caps handlers per pool worker (ADR-0046 Decision 3); 0 ⇒ the default (16).
PoolLimit int
// PoolManifestDir holds the pool workers' manifests, which carry member credentials: a 0700 dir funcd owns,
// emptied by NewReconciler. Empty ⇒ a private temp dir NewReconciler creates and Close removes.
PoolManifestDir string
// Secrets resolves a function's bound Secret names → an env-var map injected into the
// worker (ADR-0057, F15 last mile). nil ⇒ secret injection disabled: a function declaring
// spec.secrets fails closed (SecretResolveFailed). Satisfied by *secrets.Resolver.
Secrets SecretResolver
// DeveloperFor returns the identity the PDP authorizes for a namespace's secret reads
// (ADR-0057 Decision 4). Defaulted to the namespace-scoped developer identity when Secrets
// is set and this is nil; ignored when Secrets is nil.
DeveloperFor func(ns v1.NamespaceName) auth.Identity
// InvokeSockets provisions the per-function worker-node local API (ADR-0064) and yields the
// socket path the reconciler sets as FUNCD_INVOKE_SOCKET. nil ⇒ fn-to-fn links off.
InvokeSockets InvokeSocketProvider
// S3Gateway, when Enabled, injects a per-function SigV4 keypair + endpoint into the worker
// env (ADR-0085) for a function that declares spec.blob — AWS_ACCESS_KEY_ID/
// AWS_SECRET_ACCESS_KEY (DeriveKeypair over Master), AWS_REGION, AWS_ENDPOINT_URL_S3
// (ListenAddr). A function without spec.blob, or a disabled gateway, gets nothing.
S3Gateway S3GatewayInjection
// CatalogMaster is the node master secret the per-function catalog token is derived from (ADR-0137):
// resolveCatalogEnv injects FUNCD_CATALOG_<ALIAS>_TOKEN = DeriveCatalogToken(master, ns, fn), a
// MAC-authenticated bearer the catalog PEP proxy verifies (was the shared QUACK_TOKEN). It is the
// SAME master the S3 gateway derives keypairs from (loaded once at the compose root). nil/empty ⇒ a
// still-derivable but unverifiable token (the proxy holds the real master); the master is never logged.
CatalogMaster []byte
// CatalogProxies reports the catalog listeners bound in this daemon run (ADR-0137, ADR-0162): a consumer is
// injected its catalog's bound listener URL, and waits while none is bound. nil ⇒ the catalog's status.endpoint,
// for harnesses without a Manager.
CatalogProxies CatalogProxies
// CatalogExtensionDir, when non-empty, is injected as DUCKDB_EXTENSION_DIRECTORY into a
// catalog-consumer function's worker env (a function declaring spec.catalogs) so its handler's
// `LOAD quack`/`ducklake` resolves the curated DuckDB extensions from this dir. It is the dev
// analogue of the prod bundle's duckdb-ext (ADR-0089): `funcdctl dev` extracts the embedded
// catalog engine's extensions once and points consumers at them; prod leaves it empty (the
// bundle carries duckdb-ext under FUNCD_BUNDLE_DIR instead). Empty ⇒ no injection.
CatalogExtensionDir string
// SupervisionPeriod is the requeue of a Ready function (ADR-0142); 0 ⇒ controller.SupervisionPeriod.
SupervisionPeriod time.Duration
// BootBackoffInitial and BootBackoffMax bound the wait before a replica that crashed while booting is created
// again (ADR-0160); 0 ⇒ 10 s and max(5 min, initial). Negative, or a set max below initial, is fault.Invalid.
BootBackoffInitial time.Duration
BootBackoffMax time.Duration
// Calls counts the calls made to each worker (ADR-0143): the resolver records each hand-out and the drain asks
// whether a demoted revision's worker is idle. nil ⇒ every worker is idle.
Calls *activator.CallTracker
// DrainGrace bounds how long a demoted revision's workers drain; 0 ⇒ 30 s (ADR-0143).
DrainGrace time.Duration
// HandOutSettle is how long after a hand-out, or after the switch, a worker may still receive a call; 0 ⇒ 2 s.
HandOutSettle time.Duration
// DrainPollInterval is the longest gap between drain passes (runtime.drainPollInterval, ADR-0163); 0 ⇒ 1 s.
DrainPollInterval time.Duration
// BootTimeout stops a replica not ready this long after its last successful Start (runtime.bootTimeout, ADR-0163,
// ADR-0183); 0 ⇒ 1 min.
BootTimeout time.Duration
// LivenessTimeout is how long a listening replica or pool host may stay silent on /health/liveness before it is
// restarted (runtime.livenessTimeout, ADR-0215); 0 ⇒ max(30 s, three supervision periods).
LivenessTimeout time.Duration
// ReferentPollInterval re-checks a function waiting for a referent (controller.referentPollInterval, ADR-0163),
// bounded by the supervision period (ADR-0142 Decision 9); 0 ⇒ 2 s.
ReferentPollInterval time.Duration
// Clock times the drain from drainingSince; nil ⇒ clock.System().
Clock clock.Clock
}
Deps configures the Function lifecycle reconciler (internal component, ADR-0002 §1).
type EndpointMode ¶
type EndpointMode int
EndpointMode selects how a worker is ADDRESSED (ADR-0032); it is orthogonal to the Materializer-presence gate that selects the shim path.
const ( // EndpointLoopback addresses the shim on 127.0.0.1 via the FUNCD_PORTFILE handshake // (process driver, ADR-0030). EndpointLoopback EndpointMode = iota // EndpointNetnsFixedPort addresses the shim on the netns IP at a fixed port (containerd // driver, ADR-0032). EndpointNetnsFixedPort )
type FileMaterializer ¶
type FileMaterializer struct{}
FileMaterializer resolves a "file://" (or bare-path) spec.image ref to a local path. It is the no-dependency dev/test driver; production uses the oras driver (ADR-0031).
func NewFileMaterializer ¶
func NewFileMaterializer() *FileMaterializer
NewFileMaterializer builds the local-file Materializer.
func (FileMaterializer) Materialize ¶
Materialize returns the local filesystem path of the Function's artifact, verifying it exists. It accepts "file:///abs/path", "file://abs/path", or a bare local path.
type InvokeSocketProvider ¶
type InvokeSocketProvider interface {
SocketFor(ns v1.NamespaceName, name v1.ObjectName) (string, error)
// PoolSocketFor provisions the one local API socket of pool worker `pool`, on which each call names its member;
// members is the set it serves, replaced on every call.
PoolSocketFor(ns v1.NamespaceName, pool v1.ObjectName, members []v1.ObjectName) (string, error)
// Remove stops + deletes the function's local API listener (called from teardown on delete, so
// the socket lifecycle tracks the Function resource — controller-driven, not leaked).
Remove(ns v1.NamespaceName, name v1.ObjectName)
}
InvokeSocketProvider supplies the per-function worker-node local API socket path (ADR-0064): the reconciler sets it as FUNCD_INVOKE_SOCKET in the worker env so the shim can dial context.invoke. nil ⇒ fn-to-fn links are off (the env var is unset; invoke fails closed in the shim).
type Materializer ¶
type Materializer interface {
Materialize(ctx context.Context, fn *v1.Function) (localPath string, err error)
}
Materializer resolves a Function's artifact to a local path the runtime shim reads (ADR-0030). It is a seam: the local-file driver here serves the dev/e2e process path; the OCI/oras driver (ADR-0031) is the production driver of this same interface.
type PlatformResolver ¶ added in v0.2.0
type PlatformResolver interface {
Platforms(ctx context.Context, uri, digest string) ([]v1.OCIPlatform, error)
}
PlatformResolver lists the platforms an artifact digest provides (ADR-0145): an OCI image index's, an annotated manifest's one, or nil for an artifact that runs anywhere. An artifact that runs nowhere is an error matching scheduler.ErrNoMatchingPlatform. The reconciler gates placement on it.
type Reconciler ¶
type Reconciler struct {
// contains filtered or unexported fields
}
Reconciler is the one controller.Reconciler for KindFunction.
func NewReconciler ¶
func NewReconciler(d Deps) (*Reconciler, error)
NewReconciler builds the Function lifecycle reconciler. The ports are required; Materializer/ShimCommand are optional (set together to enable execution, ADR-0030).
func (*Reconciler) Close ¶ added in v0.5.0
func (r *Reconciler) Close() error
Close removes the pool manifest dir NewReconciler created; a configured one is left in place.
func (*Reconciler) Endpoints ¶
func (r *Reconciler) Endpoints() activator.Endpoints
Endpoints returns the production activator.Endpoints (the seam ADR-0016 deferred to P-M): a function's ready worker upstream.
func (*Reconciler) MapAccess ¶ added in v0.5.0
func (r *Reconciler) MapAccess(ctx context.Context, obj v1.Object) []controller.Request
MapAccess maps a KVStore, Bucket, RolesAssignment, EgressPolicy or Policy change to every Function of its namespace that declares a pool worker, Idle included: the change can move each to another pool.
func (*Reconciler) MapCatalogService ¶ added in v0.6.0
func (r *Reconciler) MapCatalogService(ctx context.Context, obj v1.Object) []controller.Request
MapCatalogService maps a changed or deleted CatalogService to every Function of its namespace whose spec.catalogs names it, so a consumer's RevisionReady follows its catalog within one pass (ADR-0162 Decision 5). A List error logs and maps nothing.
func (*Reconciler) MapPoolDisplaced ¶ added in v0.7.1
func (r *Reconciler) MapPoolDisplaced(ctx context.Context, obj v1.Object) []controller.Request
MapPoolDisplaced maps a pooled Function whose spec no pass has seen yet (a create, or a change that can move it into a pool key) to the asleep members of its key it pushes past the first PoolLimit names and that do not show PoolFull yet. An asleep member's pass sets no requeue, so without this event it would learn it is displaced only at a call (ADR-0193 Decision 4).
func (*Reconciler) MapRevision ¶ added in v0.7.0
func (r *Reconciler) MapRevision(_ context.Context, obj v1.Object) []controller.Request
MapRevision maps a changed Revision to the Function that controls it (ADR-0190 Decision 5): the scaler's wake (Deploying) or reclaim (Idle) of a held revision is then acted on by that Function's next pass.
func (*Reconciler) PoolMembers ¶ added in v0.5.0
func (r *Reconciler) PoolMembers(ns v1.NamespaceName, worker v1.ObjectName) (members []v1.ObjectName, isMember func(name string) bool, ok bool)
PoolMembers is a snapshot of the member set last recorded for pool worker `worker` in ns: its names and a lookup over them. ok is false when none is recorded.
func (*Reconciler) Reconcile ¶
func (r *Reconciler) Reconcile(ctx context.Context, req controller.Request) (controller.Result, error)
Reconcile converges one Function to its desired state.
type S3GatewayInjection ¶
type S3GatewayInjection struct {
Enabled bool
ListenAddr string
// Endpoint is the sandbox-facing S3 URL (ADR-0085): the node address a netns'd worker can reach —
// the CNI bridge gateway IP under containerd. Empty ⇒ derived as http://<ListenAddr> (loopback dev).
Endpoint string
// Derive returns the deterministic per-(kind, ns, name) SigV4 keypair (s3gateway.DeriveKeypair,
// bound to the node master secret; ADR-0175). Required when Enabled.
Derive func(kind v1.Kind, ns, name string) (access, secret string)
}
S3GatewayInjection configures the worker-env S3 keypair injection (ADR-0085). Derive computes the per-function (access, secret) from the node master over the Ref — supplied by the wiring (pkg/funcd) so this package stays free of the versitygw dependency the gateway carries; the master secret it closes over is never logged. The zero value (Enabled false) injects nothing.
type SecretResolver ¶
type SecretResolver interface {
ResolveEnv(ctx context.Context, id auth.Identity, ns v1.NamespaceName, names []string) (map[string]string, error)
}
SecretResolver resolves a function's bound Secret names → an env-var map for worker injection, PDP-authorized for id (ADR-0022/0057). The reconciler depends on this local seam for resolution (ADR-0002 import discipline) — satisfied by *secrets.Resolver, wired in pkg/funcd; it uses internal/secrets only for the pure reserved-key guard (MergeEnvGuarded, no store dep, ADR-0092). A nil resolver on Deps disables secret injection: a function that declares spec.secrets then fails closed (SecretResolveFailed).
type ShapeValidator ¶
ShapeValidator validates a Function's artifact conforms to its runtime shape.
func NewBasicValidator ¶
func NewBasicValidator() ShapeValidator
NewBasicValidator returns the V1 spec-well-formedness ShapeValidator (the authoritative load-time materialization is the shim's, on the Linux lane, P-S).