The platform package that places servers across nodes and wires the operator, build, restore, and reaper subsystems, plus cmd/felis, the single binary that runs them.
59 lines
3.5 KiB
Go
59 lines
3.5 KiB
Go
// Package platform renders the cluster-install objects that bound what every
|
|
// Felis identity may do (spec §21, §22): the RBAC for the control-plane
|
|
// identities (felis-api and felis-operator always; felis-reaper only when the
|
|
// retention reaper is enabled, gated with its CronJob), the weak service
|
|
// accounts for the build/restore Jobs, and the minecraft-namespace
|
|
// NetworkPolicies that fence server pods. Like internal/build and
|
|
// internal/restore, the objects are pure Go-typed values so the security-critical
|
|
// shape is unit-tested here, because no cluster runs in this environment.
|
|
//
|
|
// # Why the RBAC is derived from code, not from the spec prose
|
|
//
|
|
// The allowlist is built from the actual K8s API call sites in the control
|
|
// plane, not transcribed from §21's wording, because the prose is incomplete and
|
|
// in places wrong. Concretely, the rendered Roles encode these realities the
|
|
// prose misses:
|
|
//
|
|
// - felis-api creates the restore Job in the minecraft namespace (see
|
|
// internal/restore) and the build Job in the build namespace (see
|
|
// internal/build), so it needs batch/jobs verbs in BOTH namespaces — not
|
|
// just minecraftservers + secrets.
|
|
// - The RCON port (25575) is reached by BOTH felis-api (console writes, see
|
|
// internal/api.console) AND felis-operator (the readiness prober, see
|
|
// internal/operator.prober). The RCON NetworkPolicy peer is therefore
|
|
// {api, operator}, not api alone.
|
|
// - felis-api ALSO reads pod logs for the read-side console (spec §8 读=pods/log
|
|
// follow, see internal/api.logstream): it gets pods:list (to find a server's
|
|
// running pod by label) + pods/log:get (to follow it), and deliberately NOT
|
|
// pods:get — the streamer never reads a pod's full object. This is the only
|
|
// pods grant in the bundle, and it belongs to the api, not the operator.
|
|
// - felis-operator uses the manager's CACHED client (informers), so even a
|
|
// single Get on a type requires list+watch on it; felis-api and felis-reaper
|
|
// use direct clients, so they need only the verbs they literally call.
|
|
// - The reaper is a distinct, destructive identity: it deletes
|
|
// PersistentVolumeClaims and patches minecraftservers, powers that belong to
|
|
// neither the api nor the operator. It gets its own SA and Role.
|
|
// - The operator never emits Events, sets finalizers, deletes workloads, or
|
|
// touches pods/PVCs, so none of those appear in its Role — and
|
|
// minecraftservers/status carries only `update` (it calls Status().Update),
|
|
// never get/patch.
|
|
//
|
|
// # Honesty
|
|
//
|
|
// The typed render and the §22 invariant tests are Oracle-verifiable here. What
|
|
// is NOT verifiable in this toolchain, and is therefore code-complete-but-
|
|
// unverified (the same bucket as the K8s E2E):
|
|
//
|
|
// - that the RBAC actually binds and authorizes on a live apiserver;
|
|
// - that the NetworkPolicies are enforced by the cluster CNI (a CNI without
|
|
// NetworkPolicy support silently ignores them);
|
|
// - the egress_mode=loadbalancer source-IP caveat (spec §20): with MetalLB L2,
|
|
// a per-server Service must set externalTrafficPolicy=Local or the client IP
|
|
// is SNAT'd and the 25565 ipBlock allowlist will not match the Velocity host.
|
|
//
|
|
// A Helm-chart wrapper around these objects is intentionally NOT produced: it
|
|
// could not be validated here (no helm/kubeconform), and the typed generator
|
|
// (RenderYAML, surfaced by `felis manifests`) is the verifiable source of truth a
|
|
// chart would only re-encode.
|
|
package platform
|