Documentation
¶
Index ¶
- Variables
- func CPRunning(ctx context.Context, dc *docker.Client) (bool, error)
- func EnsureRunning(ctx context.Context, opts EnsureOpts) error
- func Stop(ctx context.Context, dc *docker.Client) error
- type CPContainerConfig
- type CPContainerOpts
- type CPHealthTimeoutError
- type EnsureOpts
- type HostDirs
- type Manager
Constants ¶
This section is empty.
Variables ¶
var ClawkerCPBinary []byte
ClawkerCPBinary is the pre-compiled static Linux binary for the clawker control plane daemon.
Built by: make cp-binary Target: GOOS=linux CGO_ENABLED=0 go build ./cmd/clawker-cp
This binary is embedded into every clawker release binary so the clawker-cp container image can be built on-demand without a registry or source tree. Like EBPFManagerBinary and the firewall CoreDNS binary, it must match the Docker host's architecture (arm64 or amd64).
At runtime the CP bootstrapper (B2 Task 3) writes this binary into an on-demand Alpine image and starts the clawker-cp container from that image. The daemon runs inside the container as PID 1.
Lives in the cpboot subpackage so cmd/clawker-cp can import internal/controlplane without dragging in this embed directive — the daemon would otherwise need to embed itself, which can't resolve during its own build.
var EBPFManagerBinary []byte
EBPFManagerBinary is the pre-compiled static Linux binary for the eBPF manager. Built by: make ebpf-binary Target: GOOS=linux CGO_ENABLED=0 go build ./internal/controlplane/firewall/ebpf/cmd
This binary is embedded into every clawker release binary so the eBPF manager container image can be built on-demand without a registry or source tree. The binary must match the Docker host's architecture (arm64 or amd64).
Functions ¶
func CPRunning ¶
CPRunning reports whether the CP container exists AND is in the running state. Used by CLI commands (`firewall status`, `firewall down`) that observe or tear down the CP without wanting to trigger EnsureRunning's creation path as a side effect. Returns (false, nil) when absent; errors only on Docker API failures.
func EnsureRunning ¶
func EnsureRunning(ctx context.Context, opts EnsureOpts) error
func Stop ¶
Stop removes the CP container. Used by `clawker controlplane down`. Docker sends SIGTERM to PID 1 (clawker-cp), whose own shutdown path drains the firewall stack (Envoy + CoreDNS) and flushes per-container eBPF state before exiting — this call does not need to tear those down separately (INV-B2-008).
Types ¶
type CPContainerConfig ¶
type CPContainerConfig struct {
// Image is the container image to use.
Image string
// Labels are the Docker labels applied to the container.
Labels map[string]string
// Mounts are the bind mounts for the container.
Mounts []mount.Mount
// PortBindings are the published port mappings.
PortBindings network.PortMap
// CapAdd are the Linux capabilities added to the container.
CapAdd []string
// Env are environment variables for the container.
Env []string
// Cmd is the command to run inside the container.
Cmd []string
// NetworkName is the Docker network to attach to.
NetworkName string
// RestartPolicy is the Docker restart policy for the container.
RestartPolicy container.RestartPolicy
// ExtraHosts adds /etc/hosts entries inside the CP container.
// Used to map host.docker.internal → host-gateway so the daemon
// can reach host-loopback-bound services (currently the OTEL
// collector OTLP HTTP receiver). Agent containers cannot reach the
// same address because the BPF firewall redirects gateway traffic
// for non-hostproxy ports to Envoy; the CP is exempt because it
// owns container_map and is never enrolled.
ExtraHosts []string
}
CPContainerConfig holds the configuration for creating the control plane container. It is a structured representation that can be inspected and tested without requiring a Docker daemon.
func BuildCPContainerConfig ¶
func BuildCPContainerConfig(cfg config.Config, opts CPContainerOpts) (*CPContainerConfig, error)
BuildCPContainerConfig constructs the CPContainerConfig for the control plane container. Reads all ports from cfg.Settings().ControlPlane — defaults come from struct tags via the storage layer.
Bind mounts:
- Config dir (read-only) → CP loads config.NewConfig() inside the container
- CLI signing JWK (public key) → for Hydra client registration (read-only)
- Server TLS cert + key → for gRPC TLS (read-only)
- /sys/fs/cgroup, /sys/fs/bpf → for eBPF programs
- /var/run/docker.sock (read-only) → Docker API access for container state verification
The CLI's private signing key NEVER enters the container.
type CPContainerOpts ¶
type CPContainerOpts struct {
HostDirs HostDirs
}
CPContainerOpts bundles the host-side inputs BuildCPContainerConfig needs that cannot be derived from config.Config alone.
type CPHealthTimeoutError ¶
type CPHealthTimeoutError struct {
Timeout time.Duration
URL string
LastStatus int
LastBody string
Err error
}
CPHealthTimeoutError is returned when /healthz does not return 200 within cpReadyTimeout. Separate from firewall.HealthTimeoutError so callers can distinguish "CP never came up" from "Envoy/CoreDNS unhealthy" via errors.As. Carries the last observed probe outcome.
func (*CPHealthTimeoutError) Error ¶
func (e *CPHealthTimeoutError) Error() string
func (*CPHealthTimeoutError) Unwrap ¶
func (e *CPHealthTimeoutError) Unwrap() error
type EnsureOpts ¶
type EnsureOpts struct {
Docker *docker.Client
Config config.Config
Logger *logger.Logger
HostDirs HostDirs
}
EnsureRunning is the host-side entry point for bringing up the control plane. Idempotent and concurrency-safe. Returns nil when the CP container is running and /healthz is green.
Steps (in order):
- Ensure CLI auth material (CA, signing key, server cert).
- Ensure CP image present (build from embedded binaries if missing).
- If an existing CP container is found, start it (if stopped) and return once /healthz is green. Mount spec is NOT inspected: CP mounts are a function of install-level XDG env vars + compile- time constants, never of clawker.yaml or settings.yaml, so legitimate in-process divergence cannot happen. A host-level attacker who can mutate the CP container spec already has privileges that trivially bypass anything a mount-inspection guard could protect. (Spec INV-B2-006 originally defended the B1→B2 RO→RW upgrade — now vestigial and retired.)
- Ensure clawker-net exists (defensive guard — CLI bootstrap is normally the primary owner).
- Discover the network to compute the CP's static IP.
- Create and start the CP container with static IP + clawker-net attachment (INV-B2-014).
- Poll /healthz on 127.0.0.1:<HealthPort> until 200 or timeout.
On partial failure (container created but /healthz timed out) the next call observes the stopped/unhealthy container and reconciles. EnsureOpts bundles the inputs EnsureRunning needs. HostDirs is required; callers resolve it host-side from consts.{ConfigDir,DataDir,StateDir, CacheDir} before invoking. The CP container reads the host paths back from the CLAWKER_HOST_*_DIR env vars injected by BuildCPContainerConfig so it can compute sibling container bind mount sources via Docker-outside-of-Docker.
type HostDirs ¶
HostDirs carries the host-FS XDG-shaped directory roots the CP needs to compute sibling container bind mount sources when it creates Envoy / CoreDNS / future containers via Docker-outside-of-Docker. All four fields are REQUIRED — host-side callers resolve them via consts.ConfigDir() / DataDir() / StateDir() / CacheDir(). Missing any field fails fast at BuildCPContainerConfig and EnsureRunning rather than silently producing a bad bind source that only surfaces when Docker rejects the container-create request.
type Manager ¶
type Manager interface {
// EnsureRunning is idempotent: it builds the CP image if missing,
// creates/starts the container on clawker-net, and blocks until the
// aggregate /healthz endpoint returns 200. Returns nil when the CP
// is running and healthy.
EnsureRunning(ctx context.Context) error
// Stop removes the CP container. SIGTERM reaches PID 1 (clawker-cp),
// which drains the firewall stack and flushes per-container eBPF
// state before exiting, so this leaves no orphans behind
// (INV-B2-008). No-op when the CP container is absent.
Stop(ctx context.Context) error
// IsRunning reports whether a managed CP container exists AND is in
// Docker's `running` state. Never triggers EnsureRunning — safe for
// status commands that must not bootstrap as a side effect.
IsRunning(ctx context.Context) (bool, error)
// ProbeHealthz performs a single short-deadline GET against the CP's
// /healthz endpoint on the configured HealthPort. Returns the HTTP
// status on any response (caller decides if 200 is required), or
// (0, err) on transport failure.
ProbeHealthz(ctx context.Context) (int, error)
}
Manager is the CLI-facing noun for the host-side clawker control plane lifecycle. CLI commands that need to bring the CP up, tear it down, or observe its health go through this interface rather than importing the package-level functions directly — that keeps the Factory the single place where Docker/Config/Logger resolution is wired and lets tests inject a fake without reaching into package-level seams.
func NewManager ¶
func NewManager( client func(context.Context) (*docker.Client, error), cfg func() (config.Config, error), log func() (*logger.Logger, error), ) Manager
NewManager constructs a Manager from lazy Factory accessors. Callers are expected to hand in the same closures that live on *cmdutil.Factory so the manager and direct `f.Client/Config/Logger` callers observe the same cached singletons.