Documentation
¶
Index ¶
- Constants
- func ComputeContainerSpecHash(spec intmodel.ContainerSpec) string
- type ContainerObservation
- type Exec
- func (r *Exec) BootstrapCNI(cfgDir, cacheDir, binDir string) (cni.BootstrapReport, error)
- func (r *Exec) Close() error
- func (r *Exec) ContainerRootChainID(namespace, containerID string) (string, error)
- func (r *Exec) CreateCell(cell intmodel.Cell) (intmodel.Cell, error)
- func (r *Exec) CreateContainer(cell intmodel.Cell, container intmodel.ContainerSpec) (intmodel.Cell, error)
- func (r *Exec) CreateRealm(realm intmodel.Realm) (intmodel.Realm, error)
- func (r *Exec) CreateSpace(space intmodel.Space) (intmodel.Space, error)
- func (r *Exec) CreateStack(stack intmodel.Stack) (intmodel.Stack, error)
- func (r *Exec) DeleteBlueprint(blueprint intmodel.CellBlueprint) error
- func (r *Exec) DeleteCell(cell intmodel.Cell) error
- func (r *Exec) DeleteConfig(config intmodel.CellConfig) error
- func (r *Exec) DeleteContainer(cell intmodel.Cell, containerID string) error
- func (r *Exec) DeleteImage(namespace, ref string) error
- func (r *Exec) DeleteRealm(realm intmodel.Realm) error
- func (r *Exec) DeleteSecret(secret intmodel.Secret) error
- func (r *Exec) DeleteSpace(space intmodel.Space) error
- func (r *Exec) DeleteStack(stack intmodel.Stack) error
- func (r *Exec) DeleteVolume(volume intmodel.Volume) error
- func (r *Exec) EnsureCell(cell intmodel.Cell) (intmodel.Cell, error)
- func (r *Exec) EnsureContainer(cell intmodel.Cell, container intmodel.ContainerSpec) (intmodel.Cell, error)
- func (r *Exec) EnsureKukeonRootCgroup() (bool, bool, error)
- func (r *Exec) EnsureRealm(realm intmodel.Realm) (intmodel.Realm, error)
- func (r *Exec) EnsureSpace(space intmodel.Space) (intmodel.Space, error)
- func (r *Exec) EnsureStack(stack intmodel.Stack) (intmodel.Stack, error)
- func (r *Exec) ExistsCellRootContainer(cell intmodel.Cell) (bool, error)
- func (r *Exec) ExistsCgroup(doc any) (bool, error)
- func (r *Exec) ExistsContainer(namespace, containerdID string) (bool, error)
- func (r *Exec) ExistsRealmContainerdNamespace(namespace string) (bool, error)
- func (r *Exec) ExistsSpaceCNIConfig(space intmodel.Space) (bool, error)
- func (r *Exec) ExtractContainersFromCells(cells []intmodel.Cell) []intmodel.ContainerSpec
- func (r *Exec) GetBlueprint(blueprint intmodel.CellBlueprint) (intmodel.CellBlueprint, error)
- func (r *Exec) GetCell(cell intmodel.Cell) (intmodel.Cell, error)
- func (r *Exec) GetConfig(config intmodel.CellConfig) (intmodel.CellConfig, error)
- func (r *Exec) GetContainerObservation(cell intmodel.Cell, containerID string) (ContainerObservation, error)
- func (r *Exec) GetContainerState(cell intmodel.Cell, containerID string) (intmodel.ContainerState, error)
- func (r *Exec) GetImage(namespace, ref string) (ctr.ImageInfo, error)
- func (r *Exec) GetRealm(realm intmodel.Realm) (intmodel.Realm, error)
- func (r *Exec) GetSecret(secret intmodel.Secret) (intmodel.Secret, error)
- func (r *Exec) GetSpace(space intmodel.Space) (intmodel.Space, error)
- func (r *Exec) GetStack(stack intmodel.Stack) (intmodel.Stack, error)
- func (r *Exec) GetVolume(volume intmodel.Volume) (intmodel.Volume, error)
- func (r *Exec) ImageChainID(namespace, ref string) (string, error)
- func (r *Exec) KillCell(cell intmodel.Cell) (intmodel.Cell, error)
- func (r *Exec) KillContainer(cell intmodel.Cell, containerID string) error
- func (r *Exec) ListBlueprints(realmName, spaceName, stackName string) ([]intmodel.CellBlueprint, error)
- func (r *Exec) ListCells(realmName, spaceName, stackName string) ([]intmodel.Cell, error)
- func (r *Exec) ListConfigs(realmName, spaceName, stackName string) ([]intmodel.CellConfig, error)
- func (r *Exec) ListContainerdNamespaces() ([]string, error)
- func (r *Exec) ListContainers(realmName, spaceName, stackName, cellName string) ([]intmodel.ContainerSpec, error)
- func (r *Exec) ListImages(namespace string) ([]ctr.ImageInfo, error)
- func (r *Exec) ListRealms() ([]intmodel.Realm, error)
- func (r *Exec) ListSecrets(realmName, spaceName, stackName, cellName string) ([]intmodel.Secret, error)
- func (r *Exec) ListSpaces(realmName string) ([]intmodel.Space, error)
- func (r *Exec) ListStacks(realmName, spaceName string) ([]intmodel.Stack, error)
- func (r *Exec) ListVolumes(realmName, spaceName, stackName string) ([]intmodel.Volume, error)
- func (r *Exec) LoadImage(namespace string, reader io.Reader) ([]string, error)
- func (r *Exec) PopulateAndPersistCellContainerStatuses(cell *intmodel.Cell) error
- func (r *Exec) PruneImages(namespace string) (ctr.PruneResult, error)
- func (r *Exec) PurgeCell(cell intmodel.Cell) error
- func (r *Exec) PurgeContainer(realm intmodel.Realm, containerID string) error
- func (r *Exec) PurgeRealm(realm intmodel.Realm) (bool, error)
- func (r *Exec) PurgeSpace(space intmodel.Space) error
- func (r *Exec) PurgeStack(stack intmodel.Stack) error
- func (r *Exec) ReapplyAttachableSocketPerms(spec intmodel.ContainerSpec)
- func (r *Exec) ReconcileCell(cell intmodel.Cell) (intmodel.Cell, ReconcileOutcome, error)
- func (r *Exec) RecreateCell(desired intmodel.Cell) (_ intmodel.Cell, retErr error)
- func (r *Exec) RefreshCell(cell intmodel.Cell) (intmodel.Cell, int, error)
- func (r *Exec) RefreshRealm(realm intmodel.Realm) (intmodel.Realm, bool, error)
- func (r *Exec) RefreshSpace(space intmodel.Space) (intmodel.Space, bool, error)
- func (r *Exec) RefreshStack(stack intmodel.Stack) (intmodel.Stack, bool, error)
- func (r *Exec) ResolveSpaceCNIConfigPath(realmID, spaceID string) (string, error)
- func (r *Exec) StartCell(cell intmodel.Cell) (intmodel.Cell, error)
- func (r *Exec) StartContainer(cell intmodel.Cell, containerID string) (_ intmodel.Cell, retErr error)
- func (r *Exec) StopCell(cell intmodel.Cell) (intmodel.Cell, error)
- func (r *Exec) StopContainer(cell intmodel.Cell, containerID string) error
- func (r *Exec) UpdateCell(desired intmodel.Cell) (intmodel.Cell, error)
- func (r *Exec) UpdateCellMetadata(cell intmodel.Cell) error
- func (r *Exec) UpdateContainer(cell intmodel.Cell, desiredContainer intmodel.ContainerSpec) (intmodel.Cell, error)
- func (r *Exec) UpdateRealm(desired intmodel.Realm) (intmodel.Realm, error)
- func (r *Exec) UpdateRealmMetadata(realm intmodel.Realm) error
- func (r *Exec) UpdateSpace(desired intmodel.Space) (intmodel.Space, error)
- func (r *Exec) UpdateSpaceMetadata(space intmodel.Space) error
- func (r *Exec) UpdateStack(desired intmodel.Stack) (intmodel.Stack, error)
- func (r *Exec) UpdateStackMetadata(stack intmodel.Stack) error
- func (r *Exec) VolumeMountedByLiveCell(volume intmodel.Volume) (string, bool, error)
- func (r *Exec) WriteBlueprint(blueprint intmodel.CellBlueprint) (bool, error)
- func (r *Exec) WriteConfig(config intmodel.CellConfig) (bool, error)
- func (r *Exec) WriteConfigIfAbsent(config intmodel.CellConfig) error
- func (r *Exec) WriteSecret(secret intmodel.Secret) (bool, error)
- func (r *Exec) WriteVolume(volume intmodel.Volume) (bool, error)
- type Options
- type ReconcileOutcome
- type Runner
Constants ¶
const ContainerIDMinimumParts = 2
ContainerIDMinimumParts is the minimum number of parts needed in a container ID to extract the network name. Container ID format: realm-space-cell-container We need at least realm and space to form the network name: realm-space.
const SpecHashDomainVersion = "4"
SpecHashDomainVersion is the current hash-domain version. Bump it whenever containerSpecHashPayload's field set changes — the TestSpecHashDomainVersionPinsToPayload regression guard forces the bump in the same edit by pinning the version to the payload's reflected field set. History: "1" (issue #867, original domain) → "2" (#1001, widened the root-container diff to all spec fields) → "3" (#1155, added Volumes, Secrets, WorkingDir, SecurityOpts) → "4" (#1252, added Devices). A cell stamped under an older version is re-stamped from its authoritative on-disk spec on the next start rather than refused. Issue #1171.
const SpecHashLabelKey = "kukeon.io/spec-hash"
SpecHashLabelKey is the containerd container label that pins the OCI spec to the CellSpec it was created from. StartCell's existing-container branch reads the label, recomputes the hash from the on-disk CellSpec, and refuses to resume a record whose hash diverges — the operator is told to reconcile via `kuke apply -f`. The supported `kuke apply -f` flow re-stamps the label inside the same RecreateCell / UpdateCell transaction that rewrites containerd state, so steady-state restarts always match. Issue #867.
const SpecHashVersionLabelKey = "kukeon.io/spec-hash-version"
SpecHashVersionLabelKey pins the *domain version* the SpecHashLabelKey value was computed under — the field set in containerSpecHashPayload. A bare hash cannot distinguish "the spec drifted" (genuine out-of-band tampering, which must refuse) from "the hashing algorithm changed" (a daemon upgrade widened the payload, which must NOT refuse). Without this label, any change to the hash domain made every pre-existing cell look tampered and stranded the whole fleet on the next start with no migration path. The guard now keys its refuse-vs-re-stamp decision on whether this version matches the running daemon's SpecHashDomainVersion. Issue #1171.
Variables ¶
This section is empty.
Functions ¶
func ComputeContainerSpecHash ¶ added in v0.6.0
func ComputeContainerSpecHash(spec intmodel.ContainerSpec) string
ComputeContainerSpecHash returns a hex-encoded SHA-256 over the containerSpecHashPayload projection of spec. Pure function; no containerd access. Same hash for root and non-root containers — the domain is identical (see containerSpecHashPayload).
Types ¶
type ContainerObservation ¶ added in v0.6.0
type ContainerObservation struct {
State intmodel.ContainerState
ExitCode int
// ExitTime is the wall-clock time containerd recorded the task's death,
// surfaced as ContainerStatus.FinishTime. Zero until the task is Stopped.
ExitTime time.Time
}
ContainerObservation bundles the slice of containerd task state the runner needs to surface in ContainerStatus and drive lifecycle decisions: the internal-state mapping plus the exit code and exit time reported by the task. ExitCode and ExitTime are only meaningful on the TaskStatus-success branch — on every other branch (NotCreated, ErrTaskNotFound, transient error, fallback Unknown) they stay zero. containerd's task status carries no start time, so StartTime is stamped by observe-and-preserve in populateCellContainerStatuses rather than read here (issue #1137).
type Exec ¶
type Exec struct {
// contains filtered or unexported fields
}
func (*Exec) BootstrapCNI ¶
func (r *Exec) BootstrapCNI(cfgDir, cacheDir, binDir string) (cni.BootstrapReport, error)
func (*Exec) ContainerRootChainID ¶ added in v0.6.0
ContainerRootChainID returns the chainID the container's root snapshot is anchored on at the moment of the call, paired with ImageChainID by bootstrapCell to detect image digest drift (issue #915 defect 2).
errdefs.ErrContainerNotFound is propagated unchanged so callers can use errors.Is for not-found detection.
func (*Exec) CreateContainer ¶
func (r *Exec) CreateContainer(cell intmodel.Cell, container intmodel.ContainerSpec) (intmodel.Cell, error)
CreateContainer creates a container in an existing cell by merging the container spec into the cell's containers list. The cell must already exist.
Inheritance of spec.defaults.container from the parent Space happens in ensureCellContainers, which is the single choke point every creation and update path traverses — so the post-merge (effective) configuration is what gets persisted and what `kuke get container -o yaml` displays.
func (*Exec) DeleteBlueprint ¶ added in v0.6.0
func (r *Exec) DeleteBlueprint(blueprint intmodel.CellBlueprint) error
DeleteBlueprint removes the daemon-stored document file for a single named, scoped CellBlueprint (issue #643). Returns errdefs.ErrBlueprintNotFound when the file is absent so the caller can report a clear "not found" instead of a silent success. Unlike DeleteSecret there is no live-reference gate: a cell materialized by `kuke run -b` is a fresh, independent copy (#620), so removing the blueprint never breaks a running cell.
func (*Exec) DeleteConfig ¶ added in v0.6.0
func (r *Exec) DeleteConfig(config intmodel.CellConfig) error
DeleteConfig removes the daemon-stored document file for a single named, scoped CellConfig (issue #644). Returns errdefs.ErrConfigNotFound when the file is absent so the caller can report a clear "not found" instead of a silent success. Deleting a Config never touches the cell it materialized — that is `kuke delete cell` — so there is no live-reference gate here; the back-reference notice is computed and surfaced by the controller layer.
func (*Exec) DeleteContainer ¶
DeleteContainer stops and deletes a specific container in a cell from containerd.
func (*Exec) DeleteImage ¶ added in v0.3.0
DeleteImage removes the named image ref from the given containerd namespace. errdefs.ErrImageNotFound is propagated unchanged so callers can use errors.Is for not-found detection.
func (*Exec) DeleteSecret ¶ added in v0.6.0
DeleteSecret removes the daemon-stored bytes file for a single named, scoped Secret (issue #622). Returns errdefs.ErrSecretNotFound when the file is absent so the caller can report a clear "not found" instead of a silent success. The bytes are never read before removal.
func (*Exec) DeleteVolume ¶ added in v0.8.0
DeleteVolume removes the daemon-provisioned directory for a single named, scoped Volume (issue #1018). Returns errdefs.ErrVolumeNotFound when the directory is absent so the caller can report a clear "not found" instead of a silent success. Uses RemoveAll (the volume is a directory that may hold container-written contents), gated on a prior stat so a missing volume still surfaces NotFound rather than RemoveAll's silent nil.
func (*Exec) EnsureCell ¶
EnsureCell ensures that all required resources for a cell exist. It ensures the cgroup exists, ensures cell containers exist, and updates metadata.
func (*Exec) EnsureContainer ¶
func (r *Exec) EnsureContainer(cell intmodel.Cell, container intmodel.ContainerSpec) (intmodel.Cell, error)
EnsureContainer ensures that a container spec is merged into an existing cell. It merges the container into the cell's Spec.Containers list (avoiding duplicates by ID), ensures containers exist, and updates metadata.
func (*Exec) EnsureKukeonRootCgroup ¶
EnsureKukeonRootCgroup ensures the kukeon root cgroup (/kukeon) exists at the cgroup hierarchy root. This is the base under which all realms are created. It bypasses buildCgroupPath (which would otherwise nest /kukeon under itself) and creates the cgroup directly at the discovered mountpoint. Returns (existsPre, created, err).
func (*Exec) EnsureRealm ¶
EnsureRealm ensures that all required resources for a realm exist and reconciles its state. It ensures the containerd namespace and cgroup exist, and transitions the realm from "Creating" to "Ready" state if all resources are present.
func (*Exec) EnsureSpace ¶
EnsureSpace ensures that all required resources for a space exist. It ensures the CNI config and cgroup exist.
func (*Exec) EnsureStack ¶
EnsureStack ensures that all required resources for a stack exist. It ensures the cgroup exists.
func (*Exec) ExistsCellRootContainer ¶
func (*Exec) ExistsContainer ¶
ExistsContainer checks if a container exists in containerd by its containerd ID. It ensures the client is connected before making the call.
func (*Exec) ExistsRealmContainerdNamespace ¶
func (*Exec) ExistsSpaceCNIConfig ¶
ExistsSpaceCNIConfig checks if the CNI config for a space exists. It returns a bool and an error. The bool is true if the CNI config exists, false otherwise. The error is returned if the space name is required, the realm name is required, the CNI config does not exist, or the CNI config creation fails.
func (*Exec) ExtractContainersFromCells ¶
func (r *Exec) ExtractContainersFromCells(cells []intmodel.Cell) []intmodel.ContainerSpec
ExtractContainersFromCells extracts all containers from a list of cells. It returns both root containers and regular containers as internal ContainerSpec types.
func (*Exec) GetBlueprint ¶ added in v0.6.0
func (r *Exec) GetBlueprint(blueprint intmodel.CellBlueprint) (intmodel.CellBlueprint, error)
GetBlueprint reads a single named, scoped CellBlueprint's document off disk (issue #620). Unlike GetSecret — which is metadata-only because secret bytes must never round-trip — a blueprint carries only template references, so the full document is read back and returned for `kuke run -b` to materialize. Returns errdefs.ErrBlueprintNotFound when the file is absent.
func (*Exec) GetConfig ¶ added in v0.6.0
func (r *Exec) GetConfig(config intmodel.CellConfig) (intmodel.CellConfig, error)
GetConfig reads a single named, scoped CellConfig's document off disk (issue #644). Like GetBlueprint — and unlike GetSecret — the full document is read back and returned: a Config carries only a blueprint reference, scalar values, and slot fills (no credential bytes), so the whole document is safe to surface for `kuke get config`. Returns errdefs.ErrConfigNotFound when the file is absent.
func (*Exec) GetContainerObservation ¶ added in v0.6.0
func (r *Exec) GetContainerObservation(cell intmodel.Cell, containerID string) (ContainerObservation, error)
GetContainerObservation is GetContainerState plus the task's exit code. Behaves identically on the existence/namespace/task-not-found edges so callers can swap from GetContainerState without observability gaps; the ExitCode field is only populated on the TaskStatus-success branch (every other return path leaves it zero).
func (*Exec) GetContainerState ¶
func (r *Exec) GetContainerState(cell intmodel.Cell, containerID string) (intmodel.ContainerState, error)
GetContainerState queries containerd for the actual task status of a container and converts it to the internal ContainerState. Thin wrapper around GetContainerObservation for callers that only need the state column.
func (*Exec) GetImage ¶ added in v0.3.0
GetImage returns metadata for the named image ref in the given containerd namespace. errdefs.ErrImageNotFound is propagated unchanged so callers can use errors.Is for not-found detection.
func (*Exec) GetSecret ¶ added in v0.6.0
GetSecret reports whether a single named, scoped Secret exists on disk and returns its metadata-only view (issue #622). The bytes are never read: a stat is sufficient to confirm existence, and echoing the material would violate the never-round-tripped contract from #619. Returns errdefs.ErrSecretNotFound when the file is absent.
func (*Exec) GetVolume ¶ added in v0.8.0
GetVolume reports whether a single named, scoped Volume exists on disk and returns its metadata-only view (issue #1018). Like GetSecret the scope and name come from the path, not from any stored document — a Volume carries no body. Returns errdefs.ErrVolumeNotFound when the directory is absent, or when a non-directory occupies the path (which is not a volume).
func (*Exec) ImageChainID ¶ added in v0.6.0
ImageChainID returns the chainID the image at ref would unpack to today in the given containerd namespace. Issue #915 defect 2: bootstrapCell uses this to detect that an image tag has been re-pointed since the kukeond cell was created (so the persisted ContainerSpec.Image ref matches the desired one but the underlying content has changed) and route through RecreateCell instead of EnsureCell+StartCell, which would otherwise re-start the stale image.
errdefs.ErrImageNotFound is propagated unchanged so callers can use errors.Is for not-found detection.
func (*Exec) KillCell ¶
KillCell immediately force-kills all containers in a cell (workload containers first, then root container). It detaches the root container from the CNI network before killing it.
func (*Exec) KillContainer ¶
KillContainer immediately force-kills a specific container in a cell.
func (*Exec) ListBlueprints ¶ added in v0.6.0
func (r *Exec) ListBlueprints(realmName, spaceName, stackName string) ([]intmodel.CellBlueprint, error)
ListBlueprints enumerates the metadata of every CellBlueprint bound to the scope identified by the filter coordinates, plus every Blueprint bound to a deeper scope nested within it (issue #643). The filter is a prefix: an empty realmName lists across all realms; a set realmName with an empty spaceName lists realm-scoped blueprints and everything under that realm; and so on. This mirrors the subtree-filter semantics of ListSecrets, but bounded at stack depth — a Blueprint is never cell-scoped (#620). The returned carriers are metadata-only (Document nil): the scope coordinates come from the path and the name from the file basename, so a list never parses every document.
func (*Exec) ListConfigs ¶ added in v0.6.0
func (r *Exec) ListConfigs(realmName, spaceName, stackName string) ([]intmodel.CellConfig, error)
ListConfigs enumerates the metadata of every CellConfig bound to the scope identified by the filter coordinates, plus every Config bound to a deeper scope nested within it (issue #644). The filter is a prefix: an empty realmName lists across all realms; a set realmName with an empty spaceName lists realm-scoped configs and everything under that realm; and so on. This mirrors the subtree-filter semantics of ListBlueprints, bounded at stack depth — a Config is never cell-scoped (#624). The returned carriers are metadata-only (Document nil): the scope coordinates come from the path and the name from the file basename, so a list never parses every document.
func (*Exec) ListContainerdNamespaces ¶ added in v0.3.0
ListContainerdNamespaces returns every containerd namespace visible to the runner's client. A missing containerd socket returns an empty list rather than an error so the uninstall path can degrade gracefully on hosts where containerd was never running (or has already been torn down).
func (*Exec) ListContainers ¶
func (r *Exec) ListContainers(realmName, spaceName, stackName, cellName string) ([]intmodel.ContainerSpec, error)
func (*Exec) ListImages ¶ added in v0.3.0
ListImages enumerates images in the given containerd namespace. The caller (controller) is responsible for resolving the realm to a namespace and ensuring the realm exists; this method only routes the call onto a connected containerd client.
func (*Exec) ListSecrets ¶ added in v0.6.0
func (r *Exec) ListSecrets(realmName, spaceName, stackName, cellName string) ([]intmodel.Secret, error)
ListSecrets enumerates the metadata of every Secret bound to the scope identified by the filter coordinates, plus every Secret bound to a deeper scope nested within it (issue #622). The filter is a prefix: an empty realmName lists across all realms; a set realmName with an empty spaceName lists realm-scoped secrets and everything under that realm; and so on. This mirrors the subtree-filter semantics of `kuke get cells --realm <r>`. The bytes are never read — only the scope coordinates (from the path) and the secret name (the file basename) are returned.
func (*Exec) ListStacks ¶
func (*Exec) ListVolumes ¶ added in v0.8.0
ListVolumes enumerates the metadata of every Volume bound to the scope identified by the filter coordinates, plus every Volume bound to a deeper scope nested within it (issue #1018). The filter is a prefix: an empty realmName lists across all realms; a set realmName with an empty spaceName lists realm-scoped volumes and everything under that realm; and so on. This mirrors ListBlueprints's subtree-filter semantics, bounded at stack depth — a Volume is never cell-scoped. Each entry under a volumes/ dir is itself a directory (the volume), so the walk collects directories and the metadata is the scope coordinates (from the path) plus the directory name.
func (*Exec) LoadImage ¶ added in v0.3.0
LoadImage imports an OCI/docker image tarball into the given containerd namespace and returns the names of the imported images. The caller is responsible for ensuring the namespace exists; the controller layer validates the realm before invoking this method.
func (*Exec) PopulateAndPersistCellContainerStatuses ¶
PopulateAndPersistCellContainerStatuses populates container statuses from containerd and persists them by updating cell metadata. This should be used when the cell status changes need to be persisted to disk.
func (*Exec) PruneImages ¶ added in v0.6.0
func (r *Exec) PruneImages(namespace string) (ctr.PruneResult, error)
PruneImages reclaims dangling image layers and the orphaned leases pinning them in the given containerd namespace. The caller (controller) resolves the realm to a namespace and ensures the realm exists; this method only routes the call onto a connected containerd client.
func (*Exec) PurgeCell ¶
PurgeCell performs comprehensive cleanup of a cell, including CNI resources and orphaned containers.
func (*Exec) PurgeContainer ¶
PurgeContainer performs comprehensive cleanup of a container, including CNI resources.
func (*Exec) PurgeRealm ¶
PurgeRealm performs comprehensive cleanup of a realm, including all child resources, CNI resources, and orphaned containers.
Returns (namespaceRemoved, err). namespaceRemoved is true iff the containerd namespace was actually removed (or was already gone). err is non-nil only for fatal precondition failures (missing name, GetRealm error, containerd connect error) or when DeleteNamespace itself failed — it is the load-bearing piece of "purge". Best-effort cleanups (cgroup removal, CNI teardown, orphaned-container drain) log warnings and do not surface as err so a fully-cleaned namespace is never reported as a failed purge.
func (*Exec) PurgeSpace ¶
PurgeSpace performs comprehensive cleanup of a space, including CNI resources and orphaned containers.
func (*Exec) PurgeStack ¶
PurgeStack performs comprehensive cleanup of a stack, including CNI resources and orphaned containers.
func (*Exec) ReapplyAttachableSocketPerms ¶ added in v0.6.0
func (r *Exec) ReapplyAttachableSocketPerms(spec intmodel.ContainerSpec)
ReapplyAttachableSocketPerms re-asserts the mode and group of a single live attachable container's tty socket inode on the attach path (#1169).
`kuke run` against an already-Ready cell short-circuits straight to attach without re-entering StartCell — that Ready branch exists to dodge the #630 CNI duplicate-allocation re-entry — so the #935 heal wired into StartCell's idempotent no-op path never runs on the path `run`/`attach` actually take. A socket an old kuketty bound 0o640 (group-read only, the pre-sbsh#361 mode) is therefore undialable forever on `kuke run`, while `kuke restart` heals it because its stop+start rebinds the socket fresh at 0o660. Healing the live inode in place at attach time — a root-owned chmod+chown, no workload bounce — closes that asymmetry without reintroducing the #630 start-on-running hazard.
A non-Attachable spec is a no-op (only sbsh-wrapped containers bind a tty control socket). Best-effort, mirroring the StartCell-skip heal: a per-socket failure is logged and swallowed rather than surfaced to the caller, because the attach path must not regress when the socket is already healthy. A socket kuketty has not bound yet (ENOENT) is a benign no-op — the normal startup chown sets the mode when the listener appears.
func (*Exec) ReconcileCell ¶ added in v0.4.0
ReconcileCell is the daemon-side counterpart to RefreshCell. Where RefreshCell derives cell.Status.State from cgroup existence alone (so `kuke refresh` keeps its current shape), ReconcileCell additionally considers container task state — which is what flips a Ready cell to Stopped when an operator runs `ctr task kill` outside of kukeon, or when the cell's non-root workloads have all exited.
State derivation (see deriveCellState):
- cgroup check error or cgroup absent → Unknown
- cgroup present, no non-root container in spec (kukeond-style or cgroup-only cell) → derived from the root container's task state (the legacy behavior; root *is* the workload here)
- cgroup present, at least one non-root container in spec → derived from the union of non-root container task states (Ready if any non-root is active; Exited if every non-root exited cleanly; Error if any non-root exited non-zero; Unknown if any non-root reads back Unknown — the defensive read-side check that pairs with #301). The derivation never yields Stopped: that label is reserved for the operator stop/kill verbs (#1267).
Container statuses are populated up front so the derivation reads them straight from the snapshot instead of re-querying containerd (and so `kuke get cell` sees the same per-container view the reconciler decided on).
Wind-down side-effects: when the derivation flips to Exited and the cell has at least one non-root container in spec and the root container task is still running, the reconciler kills the cell so the root container shell stops too (a crash → Error is sticky and left for the operator, so it does not wind down). Two flavors:
- AutoDelete=true: autoDeleteCell runs (KillCell + DeleteCell) and the cell metadata is removed. Subsumes the per-cell `kuke run --rm` watcher.
- AutoDelete=false: windDownCell runs (KillCell only). The cell metadata is preserved in Exited state for the operator to `kuke delete` explicitly — a long-lived `sleep infinity` root does not get to hold the cell open after every workload has exited.
Both flavors are gated by the ReadyObserved latch so an in-flight CreateCell (cgroup created, non-root containers not yet registered → derivation reads Exited from "container does not exist") is not reaped before it ever reached Ready.
Errors during kill/delete are returned to the caller so the loop's per-pass `Errors` slice records them and the cell is preserved for retry on the next tick (best-effort, like the watcher it replaces).
Post-reboot cgroup healing (#855): when the cgroup check returns absent and the cell's persisted ReadyObserved latch is true (the cell was ever Ready), the reconciler re-runs ensureCellCgroup to re-create the cgroup directory and re-assert subtree controllers. Cells that never reached Ready (a half-CreateCell that crashed mid-way, gated by the same latch the wind-down path uses) are not promoted by the re-ensure.
func (*Exec) RecreateCell ¶
RecreateCell stops all containers in the cell, deletes them, and recreates the cell with the new root container spec. This is used when the root container spec changes (image, command, or args).
func (*Exec) RefreshCell ¶
RefreshCell refreshes the status of a cell and its containers. Returns the updated cell, number of containers updated, and any error.
Mirrors the container-aware derivation ReconcileCell does (#543): the post-reboot scenario (cgroup wiped, container records survive, tasks gone) must transition cells out of Unknown so `kuke refresh` surfaces the same Cells / Containers updates the reconcile loop does. Pure "cgroup-only" cell-state derivation would re-park them at Unknown.
func (*Exec) RefreshRealm ¶
RefreshRealm refreshes the status of a realm by checking cgroup and containerd namespace. Returns the updated realm, whether it was updated, and any error.
func (*Exec) RefreshSpace ¶
RefreshSpace refreshes the status of a space by checking CNI config. Returns the updated space, whether it was updated, and any error.
func (*Exec) RefreshStack ¶
RefreshStack refreshes the status of a stack by checking cgroup. Returns the updated stack, whether it was updated, and any error.
func (*Exec) ResolveSpaceCNIConfigPath ¶ added in v0.6.0
ResolveSpaceCNIConfigPath resolves the CNI conflist path the runner bakes onto every container spec it provisions in the given realm/space: the space's explicit spec.cniConfigPath when set, otherwise the conventional per-space default under the run path. Exported so the OutOfSync detector's re-materialization (reconcile_outofsync.go) can reproduce the same runner-injected value and avoid a spurious drift (#1136).
func (*Exec) StartCell ¶
StartCell starts the root container and all containers defined in the CellDoc. The root container is started first, then all containers in doc.Spec.Containers are started.
If a containerd-touching step fails (CreateContainer, StartContainer, CNI attach, attachable chown), the cell is transitioned to CellStateFailed and any containers that did start are killed — issue #407. Errors raised before the provisioning phase (input validation, realm lookup, idempotent-skip path) leave the cell's persisted state alone.
func (*Exec) StartContainer ¶
func (r *Exec) StartContainer(cell intmodel.Cell, containerID string) (_ intmodel.Cell, retErr error)
StartContainer starts a specific container in a cell. Mirrors StartCell's issue-#407 behavior: a containerd-touching failure (CreateContainer, StartContainer, attachable chown) marks the cell as CellStateFailed and kills any siblings the cell still holds, so a single non-root container that cannot be brought up no longer leaves the cell wedged in Unknown.
func (*Exec) StopCell ¶
StopCell stops all containers in the cell (workload containers first, then root container). It detaches the root container from the CNI network before stopping it, ensuring the network namespace is still valid. If detachment fails or the container is already stopped, fallback cleanup removes IPAM allocations directly.
func (*Exec) StopContainer ¶
StopContainer stops a specific container in a cell.
func (*Exec) UpdateCell ¶
UpdateCell updates an existing cell with new metadata and container changes. It handles: - Metadata updates (labels) - Container additions (containers in desired but not in actual) - Container updates (containers in both, with spec changes) - Container removals (orphans: containers in actual but not in desired)
Breaking changes (root container spec changes, parent associations) should be rejected before calling this method.
func (*Exec) UpdateContainer ¶
func (r *Exec) UpdateContainer(cell intmodel.Cell, desiredContainer intmodel.ContainerSpec) (intmodel.Cell, error)
UpdateContainer updates an existing container within a cell. If the container spec has breaking changes (image, command, args), it will stop, delete, and recreate the container. Otherwise, it updates the container spec in metadata.
func (*Exec) UpdateRealm ¶
UpdateRealm updates an existing realm with new metadata and compatible spec fields. It only updates fields that are backward-compatible (labels, registry credentials). Breaking changes (name, namespace) should be rejected before calling this method.
func (*Exec) UpdateSpace ¶
UpdateSpace updates an existing space with new metadata and compatible spec fields. It only updates fields that are backward-compatible (labels). Breaking changes (name, realm association, CNI config path) should be rejected before calling this method.
func (*Exec) UpdateStack ¶
UpdateStack updates an existing stack with new metadata and compatible spec fields. It only updates fields that are backward-compatible (labels, ID). Breaking changes (name, realm/space association) should be rejected before calling this method.
func (*Exec) VolumeMountedByLiveCell ¶ added in v0.8.0
VolumeMountedByLiveCell scans every cell across all realms for a running cell that mounts the given Volume through a kind: volume mount, the live-reference gate `kuke delete volume` consults (issue #1016). A cell counts as a live mounter when its last-reconciled state is Ready and one of its container specs declares a kind: volume mount that resolves — via the same scope walk the create path uses — to this Volume's exact scope + name. The first match short-circuits and returns the cell's scoped reference (realm/space/stack/ cell); a mount that fails to resolve is skipped rather than failing the gate (it cannot be referencing the still-present target). Returns ("", false, nil) when no running cell mounts the Volume.
func (*Exec) WriteBlueprint ¶ added in v0.6.0
func (r *Exec) WriteBlueprint(blueprint intmodel.CellBlueprint) (bool, error)
WriteBlueprint persists a CellBlueprint's serialized document to <RunPath>/data/<scope>/blueprints/<name>, root-owned and world-readable (issue #620). The document is written atomically via a temp file + rename so a reader never observes a partially-written blueprint. Returns whether the file was newly created (vs. overwritten). The caller (ReconcileBlueprint) is responsible for having verified the scope exists.
func (*Exec) WriteConfig ¶ added in v0.6.0
func (r *Exec) WriteConfig(config intmodel.CellConfig) (bool, error)
WriteConfig persists a CellConfig's serialized document to <RunPath>/data/<scope>/configs/<name>, root-owned and world-readable (issue #624). The document is written atomically via a temp file + rename so a reader never observes a partially-written config. Returns whether the file was newly created (vs. overwritten). The caller (ReconcileConfig) is responsible for having verified the scope exists and the referenced blueprint resolves.
func (*Exec) WriteConfigIfAbsent ¶ added in v0.6.0
func (r *Exec) WriteConfigIfAbsent(config intmodel.CellConfig) error
WriteConfigIfAbsent atomically persists a CellConfig document only when no file at the target path exists yet (issue #839). Used by the daemon's create-only CreateConfig path (caller: `kuke create config`): returns errdefs.ErrConfigExists when the target path is already taken, so two concurrent invocations cannot race onto the same slot. The implementation writes to a same-directory temp file, then uses `os.Link` to claim the destination — link is the portable atomic "create-or-fail" primitive on POSIX, returning EEXIST when the target already exists. On any failure the temp file is best-effort removed.
func (*Exec) WriteSecret ¶ added in v0.6.0
WriteSecret persists a Secret's bytes to <RunPath>/data/<scope>/secrets/<name>, root-owned and 0o600 (issue #619). The bytes are written atomically via a temp file + rename so a reader never observes a partially-written secret, and the data is never logged. Returns whether the file was newly created.
The daemon runs as root, so files it creates are root-owned by default; WriteSecret additionally chmods the directory and file to strip any umask bits, so the 0o700/0o600 contract holds regardless of the daemon's umask.
func (*Exec) WriteVolume ¶ added in v0.8.0
WriteVolume provisions a Volume's directory at <RunPath>/data/<scope>/volumes/<name>, root-owned and container-writable (issue #1018). The per-scope volumes/ container dir is created world- traversable; the volume dir itself is created setgid root:kukeon (group- writable) when the kukeon GID is configured, root:root 0o770 otherwise. MkdirAll is idempotent, so re-applying an existing volume re-asserts the mode/owner and reports created=false. The caller (ReconcileVolume) is responsible for having verified the scope exists.
Cross-uid sharing contract. At container create the mounting container's resolved process uid is granted *owner* write on the resolved directory by volumePostCreateChown, so a non-root workload can write into the Volume even without kukeon-group membership. Only the owner is reset — the setgid root:kukeon group is preserved — so two cells that mount the same Volume as different non-root uids each re-own it at their own create and the last writer wins the owner bit. Cross-uid *shared* write therefore relies on the kukeon group (setgid group-write), not the owner chown. Two consequences of the WriteVolume re-apply make this durable rather than racy: when the kukeon group is configured a reconcile re-apply chowns the owner back to root, but group-write persists; in the no-group fallback WriteVolume issues no chown at all, so the mount-time owner grant survives reconcile. Per-cell volume identity (step 5, #1294 — ${CELL_NAME} claims) gives each cell its own Volume directory and is the supported pattern when distinct uids each need exclusive owner-write. Step 4 follow-up (#1291).
type Options ¶
type Options struct {
ContainerdSocket string
RunPath string
CniConf cni.Conf
// ForceRegenerateCNI forces ensureSpaceCNIConfig to rewrite an existing conflist
// even when one is present and its bridge name matches SafeBridgeName. Set by
// `kuke init --force-regenerate-cni` as an operator escape hatch.
ForceRegenerateCNI bool
// KukeonGroupGID, when non-zero, is the numeric GID of the kukeon system
// group. The runner uses it to chown the host-side per-container tty
// directory created for Attachable containers, so that members of the
// kukeon group can reach the per-container sbsh socket via the same
// group-traversal path that `kuke init` sets up on /opt/kukeon.
KukeonGroupGID int
// DefaultMemoryLimitBytes, when > 0, is forwarded to ctr.BuildContainerSpec
// / ctr.BuildRootContainerSpec via ctr.WithDefaultMemoryLimit so the
// kernel-level memory.max is written for any admitted container whose
// ContainerSpec does not already declare a positive
// Resources.MemoryLimitBytes. Plumbed from controller.Options of the
// same name. Zero preserves the prior behavior. Issue #531.
DefaultMemoryLimitBytes int64
// KukettyLogLevel is the daemon-wide default verbosity of the kuketty
// wrapper's slog output, threaded down from controller.Options into the
// renderer's resolveTtyLogLevel helper. Empty falls through to the
// hardcoded "info" inside that helper (preserves the behavior of test
// fixtures that build the runner directly with zero-value Options).
// Issue #599.
KukettyLogLevel string
// DiskPressureBlockPercent, when > 0, is the data-volume usage percentage
// at or above which CreateCell refuses to provision a new cell — failing
// fast with errdefs.ErrDiskPressure instead of creating a snapshot that
// pushes the volume toward 100%. A cell whose Spec.IgnoreDiskPressure is
// set bypasses the guard. Zero (the default) disables it. Plumbed from
// controller.Options of the same name. Issue #1035.
DiskPressureBlockPercent int
}
type ReconcileOutcome ¶ added in v0.4.0
type ReconcileOutcome struct {
// Updated is true if the cell's status (state or container statuses)
// was written back to disk during the pass.
Updated bool
// Deleted is true if the reconciler killed and removed the cell as
// part of honoring Spec.AutoDelete. When true the input cell no
// longer exists in metadata.
Deleted bool
// Vanished is true if the reconciler found the cell's metadata already
// gone after acquiring the per-cell lock — an operator `kuke delete
// cell` (or a stack/space teardown) completed while this tick was
// blocked on the lock holding a pre-delete snapshot (#1251). Unlike
// Deleted, the reconciler did not perform the removal, so it must not
// count toward the auto-delete metric; the flag exists purely to make
// the loop short-circuit the cell as a no-op (no status write, no
// OutOfSync re-derivation) instead of healing it back into existence
// from the stale snapshot.
Vanished bool
}
ReconcileOutcome describes the per-cell effect of a single reconcile pass. At most one of Updated / Deleted is true: an AutoDelete cell whose root task has exited skips the persisted state-update path and runs the kill+delete sequence instead, so callers see Deleted, not Updated.
type Runner ¶
type Runner interface {
BootstrapCNI(cfgDir, cacheDir, binDir string) (cni.BootstrapReport, error)
EnsureKukeonRootCgroup() (existsPre bool, created bool, err error)
GetRealm(realm intmodel.Realm) (intmodel.Realm, error)
ListRealms() ([]intmodel.Realm, error)
CreateRealm(realm intmodel.Realm) (intmodel.Realm, error)
EnsureRealm(realm intmodel.Realm) (intmodel.Realm, error)
UpdateRealm(realm intmodel.Realm) (intmodel.Realm, error)
ExistsRealmContainerdNamespace(namespace string) (bool, error)
// ListContainerdNamespaces returns every containerd namespace the
// runner's client can see. Surfaced for the uninstall path so it can
// enumerate kukeon namespaces by `.kukeon.io` suffix and clean up
// user-created realms whose on-disk metadata was already wiped.
ListContainerdNamespaces() ([]string, error)
DeleteRealm(realm intmodel.Realm) error
GetSpace(space intmodel.Space) (intmodel.Space, error)
ListSpaces(realmName string) ([]intmodel.Space, error)
CreateSpace(space intmodel.Space) (intmodel.Space, error)
EnsureSpace(space intmodel.Space) (intmodel.Space, error)
UpdateSpace(space intmodel.Space) (intmodel.Space, error)
ExistsSpaceCNIConfig(space intmodel.Space) (bool, error)
// ResolveSpaceCNIConfigPath resolves the CNI conflist path the runner
// bakes onto every container spec it provisions in the given realm/space
// (space spec.cniConfigPath when set, else the per-space default under the
// run path). Exported for the OutOfSync detector so its re-materialization
// reproduces the same runner-injected value rather than flagging it as
// spurious drift (#1136).
ResolveSpaceCNIConfigPath(realmName, spaceName string) (string, error)
DeleteSpace(space intmodel.Space) error
GetCell(cell intmodel.Cell) (intmodel.Cell, error)
ListCells(realmName, spaceName, stackName string) ([]intmodel.Cell, error)
ListContainers(realmName, spaceName, stackName, cellName string) ([]intmodel.ContainerSpec, error)
CreateCell(cell intmodel.Cell) (intmodel.Cell, error)
EnsureCell(cell intmodel.Cell) (intmodel.Cell, error)
StartCell(cell intmodel.Cell) (intmodel.Cell, error)
StopCell(cell intmodel.Cell) (intmodel.Cell, error)
StartContainer(cell intmodel.Cell, containerID string) (intmodel.Cell, error)
StopContainer(cell intmodel.Cell, containerID string) error
KillCell(cell intmodel.Cell) (intmodel.Cell, error)
KillContainer(cell intmodel.Cell, containerID string) error
DeleteContainer(cell intmodel.Cell, containerID string) error
CreateContainer(cell intmodel.Cell, container intmodel.ContainerSpec) (intmodel.Cell, error)
EnsureContainer(cell intmodel.Cell, container intmodel.ContainerSpec) (intmodel.Cell, error)
UpdateCell(cell intmodel.Cell) (intmodel.Cell, error)
RecreateCell(cell intmodel.Cell) (intmodel.Cell, error)
UpdateContainer(cell intmodel.Cell, container intmodel.ContainerSpec) (intmodel.Cell, error)
UpdateCellMetadata(cell intmodel.Cell) error
ExistsCellRootContainer(cell intmodel.Cell) (bool, error)
DeleteCell(cell intmodel.Cell) error
// ReapplyAttachableSocketPerms re-asserts the mode and group of a single
// live attachable container's tty control socket inode on the attach
// path (#1169). `kuke run` against an already-Ready cell short-circuits
// to attach without re-entering StartCell, so the #935 heal wired into
// StartCell's idempotent no-op path never runs on the path run/attach
// take; calling this from the daemon's AttachContainer RPC heals a
// wrong-mode (pre-sbsh#361 0o640) live socket in place. Non-Attachable
// specs are a no-op; best-effort (failures logged, never returned).
ReapplyAttachableSocketPerms(spec intmodel.ContainerSpec)
GetStack(stack intmodel.Stack) (intmodel.Stack, error)
ListStacks(realmName, spaceName string) ([]intmodel.Stack, error)
CreateStack(stack intmodel.Stack) (intmodel.Stack, error)
EnsureStack(stack intmodel.Stack) (intmodel.Stack, error)
UpdateStack(stack intmodel.Stack) (intmodel.Stack, error)
DeleteStack(stack intmodel.Stack) error
// WriteSecret persists a `kind: Secret`'s bytes to the daemon-managed,
// root-owned, 0o600 file under the scope's metadata tree (issue #619).
// It returns whether the file was newly created (vs. overwritten). The
// caller (ReconcileSecret) is responsible for having verified the scope
// exists; WriteSecret only creates the secrets/ subdir and the file, not
// the scope itself.
WriteSecret(secret intmodel.Secret) (created bool, err error)
// GetSecret reports the metadata-only view of a single named, scoped
// `kind: Secret` and whether it exists on disk (issue #622). The bytes
// are never read — a stat confirms existence. Returns
// errdefs.ErrSecretNotFound when absent.
GetSecret(secret intmodel.Secret) (intmodel.Secret, error)
// ListSecrets enumerates the metadata of every Secret bound to the
// filter scope or any scope nested within it (issue #622). An empty
// realmName lists across all realms; the filter is a subtree prefix.
ListSecrets(realmName, spaceName, stackName, cellName string) ([]intmodel.Secret, error)
// DeleteSecret removes the daemon-stored bytes file for a single named,
// scoped Secret (issue #622). Returns errdefs.ErrSecretNotFound when
// the file is absent.
DeleteSecret(secret intmodel.Secret) error
// WriteBlueprint persists a `kind: CellBlueprint`'s serialized document to
// the daemon-managed, root-owned, world-readable file under the scope's
// metadata tree (issue #620). Returns whether the file was newly created
// (vs. overwritten). The caller (ReconcileBlueprint) is responsible for
// having verified the scope exists.
WriteBlueprint(blueprint intmodel.CellBlueprint) (created bool, err error)
// GetBlueprint reads a single named, scoped CellBlueprint's document off
// disk (issue #620). Unlike GetSecret the full document is returned — a
// blueprint carries only template references, no credential bytes — so
// `kuke run -b` can materialize it. Returns errdefs.ErrBlueprintNotFound
// when the file is absent.
GetBlueprint(blueprint intmodel.CellBlueprint) (intmodel.CellBlueprint, error)
// ListBlueprints enumerates the metadata of every CellBlueprint bound to
// the filter scope or any scope nested within it (issue #643). An empty
// realmName lists across all realms; the filter is a subtree prefix
// bounded at stack depth (a Blueprint is never cell-scoped). The returned
// carriers are metadata-only — the document is not read.
ListBlueprints(realmName, spaceName, stackName string) ([]intmodel.CellBlueprint, error)
// DeleteBlueprint removes the daemon-stored document file for a single
// named, scoped CellBlueprint (issue #643). Returns
// errdefs.ErrBlueprintNotFound when the file is absent.
DeleteBlueprint(blueprint intmodel.CellBlueprint) error
// WriteVolume provisions a `kind: Volume`'s directory under the scope's
// metadata tree, root-owned and container-writable (issue #1018). Unlike the
// blueprint/secret writers — which write a single file — the resource is the
// directory itself, so MkdirAll is idempotent: re-applying re-asserts the
// mode/owner and reports created=false. The caller (ReconcileVolume) is
// responsible for having verified the scope exists.
WriteVolume(volume intmodel.Volume) (created bool, err error)
// GetVolume reports the metadata-only view of a single named, scoped
// `kind: Volume` and whether its directory exists on disk (issue #1018). A
// Volume carries no body, so the scope and name come from the path. Returns
// errdefs.ErrVolumeNotFound when the directory is absent.
GetVolume(volume intmodel.Volume) (intmodel.Volume, error)
// ListVolumes enumerates the metadata of every Volume bound to the filter
// scope or any scope nested within it (issue #1018). An empty realmName
// lists across all realms; the filter is a subtree prefix bounded at stack
// depth (a Volume is never cell-scoped). The returned carriers are
// metadata-only.
ListVolumes(realmName, spaceName, stackName string) ([]intmodel.Volume, error)
// DeleteVolume removes the daemon-provisioned directory for a single named,
// scoped Volume (issue #1018). Returns errdefs.ErrVolumeNotFound when the
// directory is absent.
DeleteVolume(volume intmodel.Volume) error
// VolumeMountedByLiveCell reports the scoped reference of the first running
// cell that mounts the given Volume via a kind: volume mount, gating
// `kuke delete volume` against a live mount (issue #1016). Returns
// (ref, true, nil) naming the mounting cell when one is found, ("", false,
// nil) when no running cell mounts it.
VolumeMountedByLiveCell(volume intmodel.Volume) (cellRef string, mounted bool, err error)
// WriteConfig persists a `kind: CellConfig`'s serialized document to the
// daemon-managed, root-owned, world-readable file under the scope's metadata
// tree (issue #624). Returns whether the file was newly created (vs.
// overwritten). The caller (ReconcileConfig) is responsible for having
// verified the config's scope exists and the referenced blueprint resolves.
WriteConfig(config intmodel.CellConfig) (created bool, err error)
// WriteConfigIfAbsent atomically persists a CellConfig document only when
// no file at the target path exists yet (issue #839). It is the
// create-only sibling of WriteConfig used by the daemon's create-only
// CreateConfig path (caller: `kuke create config`); returns
// errdefs.ErrConfigExists when the path is already taken. The
// implementation writes to a same-directory temp file, then uses
// `os.Link` to atomically claim the destination — link returns EEXIST
// when the path is taken, so two concurrent invocations never silently
// overwrite each other.
WriteConfigIfAbsent(config intmodel.CellConfig) error
// GetConfig reads a single named, scoped CellConfig's document off disk
// (issue #644). Like GetBlueprint the full document is returned — a Config
// carries only a blueprint ref, scalar values, and slot fills, no credential
// bytes. Returns errdefs.ErrConfigNotFound when the file is absent.
GetConfig(config intmodel.CellConfig) (intmodel.CellConfig, error)
// ListConfigs enumerates the metadata of every CellConfig bound to the
// filter scope or any scope nested within it (issue #644). An empty
// realmName lists across all realms; the filter is a subtree prefix bounded
// at stack depth (a Config is never cell-scoped). The returned carriers are
// metadata-only — the document is not read.
ListConfigs(realmName, spaceName, stackName string) ([]intmodel.CellConfig, error)
// DeleteConfig removes the daemon-stored document file for a single named,
// scoped CellConfig (issue #644). Returns errdefs.ErrConfigNotFound when the
// file is absent. Deleting a Config never touches the cell it materialized.
DeleteConfig(config intmodel.CellConfig) error
ExistsCgroup(doc any) (bool, error)
PurgeRealm(realm intmodel.Realm) (namespaceRemoved bool, err error)
PurgeSpace(space intmodel.Space) error
PurgeStack(stack intmodel.Stack) error
PurgeCell(cell intmodel.Cell) error
PurgeContainer(realm intmodel.Realm, containerID string) error
RefreshRealm(realm intmodel.Realm) (intmodel.Realm, bool, error)
RefreshSpace(space intmodel.Space) (intmodel.Space, bool, error)
RefreshStack(stack intmodel.Stack) (intmodel.Stack, bool, error)
RefreshCell(cell intmodel.Cell) (intmodel.Cell, int, error)
// ReconcileCell is the daemon-side counterpart to RefreshCell: it
// re-derives the cell's status from cgroup + root-container task state
// (so a Ready cell whose root task exits externally flips to Stopped),
// and — when Spec.AutoDelete is set on a cell that has reached
// Stopped/Failed — best-effort kills and deletes the cell instead of
// persisting the new status. Subsumes the per-cell `kuke run --rm`
// watcher: the trigger (cell stopped) is exactly what the loop already
// computes, and a single-instance, restart-resilient ticker means a
// cell whose Spec.AutoDelete=true survives a daemon restart without
// needing the daemon to re-install per-cell goroutines on startup.
ReconcileCell(cell intmodel.Cell) (intmodel.Cell, ReconcileOutcome, error)
GetContainerState(cell intmodel.Cell, containerID string) (intmodel.ContainerState, error)
// LoadImage imports an OCI/docker image tarball into the given
// containerd namespace and returns the names of the imported images.
LoadImage(namespace string, reader io.Reader) ([]string, error)
// ListImages enumerates images in the given containerd namespace.
ListImages(namespace string) ([]ctr.ImageInfo, error)
// GetImage returns metadata for the named image ref in the given
// containerd namespace. Returns errdefs.ErrImageNotFound when the
// ref is absent.
GetImage(namespace, ref string) (ctr.ImageInfo, error)
// ImageChainID returns the chainID the image at ref would unpack to
// today in the given containerd namespace. bootstrapCell pairs it
// with ContainerRootChainID to catch the case where the
// persisted ContainerSpec.Image ref matches the desired image but
// the underlying content has been re-pointed (issue #915 defect 2).
ImageChainID(namespace, ref string) (string, error)
// ContainerRootChainID returns the chainID the container's root
// snapshot is anchored on, regardless of what the image ref by the
// same name resolves to today (issue #915 defect 2).
ContainerRootChainID(namespace, containerID string) (string, error)
// DeleteImage removes the named image ref from the given containerd
// namespace. Returns errdefs.ErrImageNotFound when the ref is absent.
DeleteImage(namespace, ref string) error
// PruneImages reclaims dangling image layers and the orphaned leases
// pinning them in the given containerd namespace, leaving tagged
// images and snapshots backing live containers untouched.
PruneImages(namespace string) (ctr.PruneResult, error)
Close() error
}
Source Files
¶
- attachable.go
- blueprint.go
- cell_cgroup_path.go
- cell_etc_files.go
- cell_lock.go
- cell_runtime_env.go
- config.go
- container_state.go
- create_cell.go
- create_container.go
- create_realm.go
- create_space.go
- create_stack.go
- delete_cell.go
- delete_container.go
- delete_realm.go
- delete_space.go
- delete_stack.go
- egress.go
- exists.go
- get.go
- helpers.go
- image.go
- kill.go
- kukepause.go
- labels.go
- lifecycle.go
- load_image.go
- metadata.go
- provision.go
- purge_cell.go
- purge_container.go
- purge_realm.go
- purge_space.go
- purge_stack.go
- read.go
- reclaim_scope.go
- recreate_cell.go
- refresh.go
- runner.go
- scope_children.go
- secret.go
- setup_status_client.go
- spec_hash.go
- stage_status.go
- start.go
- stop.go
- update_cell.go
- update_container.go
- update_realm.go
- update_space.go
- update_stack.go
- volume.go
- volume_meta.go