lifecycle

package
v0.7.2 Latest Latest
Warning

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

Go to latest
Published: Jun 13, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package lifecycle holds the scaffolding shared by the `kuke daemon` lifecycle verbs (start, stop, kill, restart, reset, logs). Each verb used to maintain its own near-identical copy of these helpers; centralising them prevents silent drift of the "running" definition, the SIGTERM → SIGKILL grace period, and the test-injection key.

Index

Constants

View Source
const DefaultReachableTimeout = 500 * time.Millisecond

DefaultReachableTimeout is the dial budget the lifecycle verbs use when probing the kukeond socket. Short on purpose: the only acceptable failure mode here is "the socket is dead" — a healthy daemon answers in <1ms over the local unix socket, so 500ms is generous and a hung accept still surfaces fast enough that the operator notices.

View Source
const DefaultTimeout = 10 * time.Second

DefaultTimeout is the SIGTERM grace period before SIGKILL escalation, shared by `kuke daemon stop`/`restart`/`reset`. Centralised so the three verbs cannot drift on what "graceful" means.

View Source
const KukeondReadyTick = 200 * time.Millisecond

KukeondReadyTick is the poll interval between Ping attempts inside WaitForKukeondReady, and the per-attempt dial/ping budget. 200ms keeps the spin rate low (~150 attempts over the 30s window) while staying short enough that a healthy daemon answers on the first or second tick.

View Source
const KukeondReadyTimeout = 30 * time.Second

KukeondReadyTimeout is the bootstrap budget callers grant kukeond to bind its listener and start serving after the cell-creation path returns. Shared by `kuke init` and `kuke daemon recreate` so the two bring-up paths cannot drift on how long they wait before declaring failure.

Variables

This section is empty.

Functions

func EnsureSocketDir

func EnsureSocketDir(socketPath string) error

EnsureSocketDir recreates the kukeond socket's parent directory — the /run/kukeon bind-mount source the kukeond cell spec requires — and re-asserts the root:kukeon SGID 0750 ownership `kuke init` applies.

`kuke init` creates this directory once via the controller bootstrap, but /run is a tmpfs that is wiped on every reboot, so the bind source is gone when `kuke daemon start`/`restart` later launch the cell — runc then fails the mount with "open /run/kukeon: no such file or directory". Calling this before the start path makes the daemon recoverable after a reboot without a manual `mkdir` or a full re-`init`. Idempotent: on a healthy host the MkdirAll is a no-op and the ownership/mode are simply re-applied.

socketPath is the resolved kukeond socket; its parent directory is the bind-mount source, so passing the configured socket (which honours a nested-mode KUKEOND_SOCKET override) recreates the directory the persisted cell spec actually binds.

func IsCellRunning

func IsCellRunning(cell v1beta1.CellDoc) bool

IsCellRunning treats the cell as live if any container reports Ready, or if the persisted cell state is Ready. Every `kuke daemon` lifecycle verb uses this to agree on what "running" means; the controller's StartCell path uses the same definition so the in-process and stateful views stay aligned even when external crashes leave the persisted state stale.

func IsDaemonReachable

func IsDaemonReachable(ctx context.Context, socketPath string, timeout time.Duration) bool

IsDaemonReachable is the production reachability probe: a bounded net.Dialer-backed dial of the kukeond unix socket. Empty socketPath is treated as unreachable so a missing config does not masquerade as "up". The dial errors are intentionally not surfaced to the caller — the only question this answers is "did the socket accept a connection within the budget?", and any error (ENOENT, ECONNREFUSED, ETIMEDOUT) maps to no.

func PingKukeond

func PingKukeond(ctx context.Context, socketPath string) error

PingKukeond performs a single bring-up readiness check on socketPath: a bounded raw unix dial followed by a kukeonv1 Ping. The dial guards against the window where the socket file has appeared but the gRPC handler is not yet installed; the Ping confirms the handler answers. Errors are wrapped with a "dial:" or "ping:" prefix so callers can disambiguate which gate failed.

func ResolveEnsureSocketDir

func ResolveEnsureSocketDir(cmd *cobra.Command) func() error

ResolveEnsureSocketDir picks the recreate-/run/kukeon step the start and restart verbs run before launching the cell. Tests inject a stub via EnsureSocketDirKey; production recreates the parent directory of the resolved kukeond socket. The indirection lets both verbs call the same one-liner without duplicating the context-value lookup.

func ResolveSocketPath

func ResolveSocketPath() string

ResolveSocketPath returns the kukeond socket path the reachability probe should dial. Honours an explicit KUKEOND_SOCKET (env or viper) and falls back to the registered default. Centralised so every lifecycle verb agrees on which socket counts as the source of truth.

func SetRunDirOwnershipForTesting

func SetRunDirOwnershipForTesting(f func(dir string) error) func()

SetRunDirOwnershipForTesting replaces the ownership step EnsureSocketDir runs and returns a restore func. Tests use it to assert the directory the step receives without needing root or a real kukeon group.

func StopPhase

func StopPhase(
	cmd *cobra.Command,
	client kukeonv1.Client,
	doc v1beta1.CellDoc,
	timeout time.Duration,
) error

StopPhase runs the graceful StopCell → SIGKILL escalation used by `kuke daemon stop`/`restart`/`reset`. The inner StopCell call runs in a goroutine under a context derived from `cmd.Context()` via context.WithCancel; on timeout, the derived context is cancelled before KillCell is invoked so the orphan StopCell observes the cancellation instead of continuing against an unmodified parent context. KillCell uses the original `cmd.Context()` so the escalation itself is not affected by the stop cancellation.

func WaitForKukeondReady

func WaitForKukeondReady(ctx context.Context, socketPath string, timeout time.Duration) error

WaitForKukeondReady polls the kukeond socket with PingKukeond until it responds or the timeout expires. Used by `kuke init` and `kuke daemon recreate` after their cell-creation phase to gate "kukeond is ready" output on the RPC handler actually serving — the socket file appears as soon as the listener binds, which is strictly earlier than the gRPC handler being installed.

Types

type EnsureSocketDirKey

type EnsureSocketDirKey struct{}

EnsureSocketDirKey injects a socket-dir recreate func via the command context so unit tests can drive `kuke daemon start`/`restart` without root or a real /run/kukeon. Same pattern as MockClientKey / ReachableProbeKey: the key lives here so every verb's resolver agrees on a single identity.

type MockClientKey

type MockClientKey struct{}

MockClientKey injects a kukeonv1.Client (typically a fake) via the command context so unit tests can drive the daemon-lifecycle verbs without a real controller. The key lives in this package so every verb's resolveClient agrees on a single context-value identity, and the type stays off each verb's production surface.

type ReachableProbe

type ReachableProbe func(ctx context.Context, socketPath string, timeout time.Duration) bool

ReachableProbe reports whether a kukeond socket at socketPath answers a short-budget dial. The lifecycle verbs use it together with IsCellRunning to disambiguate the two staleness directions: persisted state says Ready while the daemon has been externally killed (socket=down → start must re-bring it up, stop must not silently no-op), and persisted state lags behind a live daemon (socket=up → stop/kill must not silently no-op).

func ResolveReachableProbe

func ResolveReachableProbe(cmd *cobra.Command) ReachableProbe

ResolveReachableProbe picks the probe a lifecycle verb uses. Tests inject a fake via ReachableProbeKey; production returns IsDaemonReachable. The indirection lets every verb call the same one-liner without duplicating the context-value lookup or hard-coding the default.

type ReachableProbeKey

type ReachableProbeKey struct{}

ReachableProbeKey injects a custom ReachableProbe via the command context so unit tests can drive the verbs without a real listening socket. Same pattern as MockClientKey; production verbs call ResolveReachableProbe to pick either the injected fake or the net.Dialer-backed default.

Jump to

Keyboard shortcuts

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