Documentation
¶
Overview ¶
Package cli builds the stratum command tree as a *cobra.Command. It is stratum's one deliberate public API surface: an importer (e.g. a downstream build) can call NewRootCommand, then AddCommand additional subcommands onto the returned root before calling Execute, without reimplementing any of the base commands. tools/check-cli-api-boundary.sh enforces that this package's exported surface never leaks an internal/* type back out, which is what makes that safe to import from outside this module.
Index ¶
- Variables
- func AddDestructiveNodeTool[In any](r *Registrar, t *mcp.Tool, op NodeOperation[In])
- func AddTool[In, Out any](r *Registrar, tier Tier, t *mcp.Tool, h mcp.ToolHandlerFor[In, Out])
- func DestructiveTool(name, description string) *mcp.Tool
- func EngineAPIServerArgs() []string
- func ExitCode(err error, stderr io.Writer) int
- func NewRootCommand(opts ...Option) *cobra.Command
- func NodeAdminClientset() (kubernetes.Interface, error)
- func PKIRotationCopies(name string) []string
- func ProfileAPIServerArgs(p Profile) ([]string, error)
- func ReadTool(name, description string) *mcp.Tool
- func TLSCipherSuites() []string
- func WriteTool(name, description string) *mcp.Tool
- type AuditResult
- type AuditVerdict
- type ComponentVersions
- type ErrExitCode
- type ErrUsage
- type NodeEnv
- type NodeLayout
- type NodeOperation
- type NodeResult
- type Option
- type Profile
- type ProfileContext
- type ProfileFile
- type ProfileFileKind
- type ProfileFlag
- type ProfileSecret
- type ProfileSetting
- type ProfileSource
- type Registrar
- type StackContext
- type StackFunc
- type Tier
- type ToolSet
Constants ¶
This section is empty.
Variables ¶
var ErrCheckFailed = errors.New("the check found failures")
ErrCheckFailed is returned by a check command whose report found a failure, such as an importer's audit command, so main can exit 1 (a bare lint-style nonzero exit — the full report has already been printed, so no additional "stratum: ..." line is wanted) without an os.Exit call inside pkg/cli itself. pkg/cli is a public, importable package, so an os.Exit from inside a RunE would terminate the importing process outright — a host binary couldn't observe the failure, run its own cleanup, or apply its own exit policy, because the process would already be gone.
var ErrNoCommand = errors.New("no command given")
ErrNoCommand is returned when stratum is invoked with no subcommand, so main can exit 2 (usage error) instead of 1 without printing a redundant "stratum: <err>" line on top of the usage cmd.Help() already printed — a bare `stratum` invocation is a usage error, not a run failure.
Functions ¶
func AddDestructiveNodeTool ¶
func AddDestructiveNodeTool[In any](r *Registrar, t *mcp.Tool, op NodeOperation[In])
AddDestructiveNodeTool registers op at the destructive tier, run like the engine's destructive tools: on a Stratum node only, one at a time with them.
func AddTool ¶
AddTool registers a typed tool at the given tier, or does nothing at all when the operator has not enabled that tier. On a server built by the internal MCP package's NewServer, the text of every result and error the tool returns reaches the client fenced as untrusted data.
func DestructiveTool ¶
DestructiveTool builds the annotations for a tool that can take a cluster down or lose data.
func EngineAPIServerArgs ¶
func EngineAPIServerArgs() []string
EngineAPIServerArgs returns the apiserver argv entries every control plane renders whatever its profile.
func ExitCode ¶
ExitCode maps err — the error Execute returned on the root command — to the process exit code the caller must end with, writing any error report it owes the operator to stderr. It is the single mapping every binary that embeds pkg/cli shares: an embedding binary imports pkg/cli, so a new sentinel is mapped once where every embedding binary can adopt it, and TestExitCodeCoversEveryExportedSentinel fails until it is.
The mapping is an observable exit-code contract:
- ErrNoCommand and *ErrUsage exit 2 (usage error). Both have already printed everything the operator needs — help, or the flag error plus usage — so nothing more is written.
- ErrCheckFailed exits 1 (lint-style failure). The full report has already printed, so nothing more is written.
- *ErrExitCode propagates its Code exactly. Whoever returned it has already told the operator what it needed to (the passthrough's child inherits stdout/stderr; `upgrade --check` prints its answer), so nothing is written.
- any other error exits 1, and because no sentinel has reported it, this is the one place a failing command's error prints, as a "stratum: <message>" line on stderr.
A nil err is success: exit 0, nothing written. Callers can therefore hand Execute's return value straight over and end with the returned code:
if code := cli.ExitCode(root.Execute(), os.Stderr); code != 0 {
os.Exit(code)
}
func NewRootCommand ¶
NewRootCommand builds the full stratum command tree. An importer adds its own commands with root.AddCommand(...) before calling root.Execute().
func NodeAdminClientset ¶
func NodeAdminClientset() (kubernetes.Interface, error)
NodeAdminClientset returns a clientset on this node's internal admin kubeconfig: super-admin.conf, else admin.conf.
func PKIRotationCopies ¶
PKIRotationCopies returns the staged and pre-rotation names a CA rotation keeps beside the PKI file name, or nil when it keeps none.
func ProfileAPIServerArgs ¶
ProfileAPIServerArgs returns the apiserver argv entries p contributes, as a control plane renders them.
func TLSCipherSuites ¶
func TLSCipherSuites() []string
TLSCipherSuites returns the strong TLS cipher suites the apiserver and kubelet are rendered with.
Types ¶
type AuditResult ¶
type AuditResult int
AuditResult is the outcome of one engine audit.
const ( // AuditPass means the audit verified the property. AuditPass AuditResult = iota + 1 // AuditFail means the audit found the property violated, or could not read what it must. AuditFail // AuditException means the audit could not verify the property and reports it unverified. AuditException )
func (AuditResult) String ¶
func (r AuditResult) String() string
type AuditVerdict ¶
type AuditVerdict struct {
Result AuditResult
Detail string
}
AuditVerdict is an audit's result and the detail an operator reads.
func AuditEtcdTrust ¶
func AuditEtcdTrust(ctx context.Context) AuditVerdict
AuditEtcdTrust reports whether this node's running etcd refuses a client certificate the cluster root signs.
func AuditKubeletClientTrust ¶
func AuditKubeletClientTrust() AuditVerdict
AuditKubeletClientTrust reports whether this node's kubelet trusts a client CA distinct from the cluster root.
func AuditKubeletsRefuseRoot ¶
func AuditKubeletsRefuseRoot(ctx context.Context, cs kubernetes.Interface) AuditVerdict
AuditKubeletsRefuseRoot reports whether every kubelet cs lists refuses a root-signed client certificate and accepts apiserver-kubelet-client.
type ComponentVersions ¶
type ComponentVersions struct {
Containerd string
Runc string
KubeVip string
Cilium string
CoreDNS string
// Deprecated: konnectivity is not shipped, so nothing reads this. The
// field stays only because released importers compile against it.
Konnectivity string
}
ComponentVersions carries the five component versions `stratum version --components` reports. The stamped values live in internal/version (ContainerdVersion, RuncVersion, ...) and the command reads them as its defaults, so this struct is only the per-field override an importer can still supply through WithComponentVersions.
func StampedVersions ¶
func StampedVersions() ComponentVersions
StampedVersions returns the engine's link-time-stamped component versions (internal/version) as a value: the same stamps `version --components` reports as its defaults. ComponentVersions is a plain struct of strings, so the caller receives a copy and cannot reach the package state behind it — read-only, because the stamps are this binary's build identity, not configuration. It exists because the stamps live in an internal package an importer cannot see: a downstream build reporting its own components would otherwise have to re-parse `version --components` output. Every field reads "unknown" in a build linked without the engine's -X stamp list.
type ErrExitCode ¶
type ErrExitCode struct{ Code int }
ErrExitCode is returned when a command's answer is its exit status: the kubectl/etcdctl passthrough when the child exits non-zero, and `upgrade --check` when the node needs the upgrade. It carries the exact code so main can propagate it precisely, without pkg/cli itself calling os.Exit — for the same importability reason as ErrCheckFailed above. Whoever returns it has already told the operator what it needed to (the passthrough's child inherits stdout/stderr; --check prints its answer), so main prints nothing additional for this error.
func (*ErrExitCode) Error ¶
func (e *ErrExitCode) Error() string
type ErrUsage ¶
type ErrUsage struct {
// contains filtered or unexported fields
}
ErrUsage wraps a flag-parsing failure so main can exit 2 (usage error) instead of 1, without printing a redundant "stratum: <err>" line on top of the error + usage text root's FlagErrorFunc already printed — a bad flag is a usage error, not a run failure.
type NodeEnv ¶
type NodeEnv struct {
Out io.Writer
Clientset kubernetes.Interface
}
NodeEnv is what a NodeOperation runs with: Out collects the progress the operator reads, and Clientset is on the node connector.
type NodeLayout ¶
type NodeLayout struct {
ConfDir string
DataDir string
PKIDir string
KubeconfigDir string
K8sConfigDir string
StaticPodDir string
KubeletConfig string
AdminConf string
SuperAdminConf string
BinDir string
ContainerdConfig string
ContainerdConfinedSinceStamp string
SELinuxLabelStamp string
EtcdDataDir string
}
NodeLayout is where this node's Stratum files live.
func Layout ¶
func Layout() NodeLayout
Layout returns this node's file layout as the engine resolves it.
type NodeOperation ¶
NodeOperation is a destructive operation on this node, run on the node connector's client.
type NodeResult ¶
NodeResult is what a NodeOperation reports; Next and Warnings reach the operator whether or not the operation fails.
type Option ¶
type Option func(*rootConfig)
Option configures the root command returned by NewRootCommand.
func WithComponentVersions
deprecated
func WithComponentVersions(v ComponentVersions) Option
WithComponentVersions supplies per-field overrides for the component versions `stratum version --components` reports: a non-empty field replaces the stamped default internal/version carries, an empty field leaves the stamp.
Deprecated: the engine stamps its component versions into internal/version, which `version --components` reads as its defaults, so an importer no longer needs to stamp main-package vars and hand them here. The option is not a no-op — it still overrides — and it goes away only through a deliberate breaking-release adoption.
func WithProfiles ¶
WithProfiles registers node profiles a node may select by name. A profile that is not declared completely, or a name registered twice, fails the node commands that read profiles.
func WithStacks ¶
WithStacks adds an importer's manifest stacks to every control-plane start.
func WithToolSets ¶
WithToolSets contributes tool sets to `stratum mcp`. The engine's own tools are always present; these are added after them.
func WithVersionOverride ¶
WithVersionOverride replaces the top-line version string `stratum version` reports, letting an importer report its own product version while reusing every base command unchanged. Empty (the default) leaves internal/version.StratumVersion, the OSS ldflags-stamped version.
type Profile ¶
type Profile struct {
// Name selects the profile: a DNS-1123 label, unique in the binary.
Name string
// APIServerFlags are spliced into the apiserver's argv on control planes,
// in order.
APIServerFlags []ProfileFlag
// KubeletSettings are rendered into kubelet.conf on every node, in order.
KubeletSettings []ProfileSetting
// ConfigFiles are written under the engine's config directory on control
// planes before the apiserver renders, backed up across an upgrade and
// restored first on a rollback.
ConfigFiles []ProfileFile
// carried to every later control plane in the join bundle, written 0600
// and never regenerated.
SharedSecrets []ProfileSecret
// Sysctls are key=value lines written as a sysctl drop-in on every node.
// A node that cannot apply them does not start.
Sysctls []string
// RequiresOperator refuses a control plane with spec.operator: false.
RequiresOperator bool
// RequiresSELinux refuses spec.selinux: false and treats a missing
// SELinux policy as fatal.
RequiresSELinux bool
// KubeletServerTLSBootstrap makes every node, control planes included,
// bootstrap its kubelet serving certificate through the CSR flow.
KubeletServerTLSBootstrap bool
// DisableNodeShell turns the dashboard's privileged node shell off by
// default.
DisableNodeShell bool
}
Profile is a named node profile an importer registers with WithProfiles. Registering validates the declaration and makes the profile selectable by name; the engine release's notes say which of its fields the node start reads and renders, as the engine's own profile moves onto this seam. Once selection is in place, a node selects a profile with `stratum up --profile <name>` or `spec.profile`, records the name in its state, and hands it to every worker's join line; a node whose state names a profile the running binary did not register refuses to start, so every node of a cluster must run a binary that carries its profile. An importer must not take a registered profile for an applied one on a release whose notes do not say the start reads it.
type ProfileContext ¶
type ProfileContext struct {
// KubernetesVersion is the version the binary runs, as vMAJOR.MINOR.PATCH
// with any pre-release suffix the stamp carries.
KubernetesVersion string
}
ProfileContext is what a profile may read when it renders a file.
type ProfileFile ¶
type ProfileFile struct {
// Name is the file name; no directory, and not the name of a file the
// engine keeps in its config directory, such as kubelet.conf.
Name string
Kind ProfileFileKind
// Render returns the file's bytes.
Render func(ProfileContext) ([]byte, error)
}
ProfileFile is a config file the engine writes for the profile.
type ProfileFileKind ¶
type ProfileFileKind int
ProfileFileKind says how the engine treats a config file beyond writing it.
const ( // ProfilePlainFile is written, and may be named by a ProfileConfigFile // flag. ProfilePlainFile ProfileFileKind = ProfileFileKind(profile.PlainFile) // ProfileAdmissionConfiguration is an apiserver AdmissionConfiguration // the engine merges its own admission plugins into. The engine names the // merged file on the apiserver's argv itself. ProfileAdmissionConfiguration ProfileFileKind = ProfileFileKind(profile.AdmissionConfiguration) )
type ProfileFlag ¶
type ProfileFlag struct {
// Name is the flag with its leading --; the value goes in Value.
Name string
Value string
From ProfileSource
}
ProfileFlag is one apiserver flag.
type ProfileSecret ¶
type ProfileSecret struct {
// Name is the file name; no directory.
Name string
// Mint returns the bytes a new cluster starts with.
Mint func() ([]byte, error)
}
ProfileSecret is a file the engine mints once and shares between control planes.
type ProfileSetting ¶
type ProfileSetting struct {
// Key is the kubelet.conf key.
Key string
// Value is the setting's value, on one line.
Value string
From ProfileSource
}
ProfileSetting is one kubelet.conf line.
type ProfileSource ¶
type ProfileSource int
ProfileSource says where a flag's or a setting's value comes from.
const ( // ProfileLiteral uses Value as written. ProfileLiteral ProfileSource = ProfileSource(profile.Literal) // ProfileConfigFile resolves Value, the name of one of the profile's // ConfigFiles or SharedSecrets, to the path the engine wrote it at. ProfileConfigFile ProfileSource = ProfileSource(profile.ConfigFile) // ProfileLogFile resolves Value, a file name, to a path under the // engine's log directory. ProfileLogFile ProfileSource = ProfileSource(profile.LogFile) // ProfilePKIFile resolves Value, a file name, to a path under the // engine's PKI directory. ProfilePKIFile ProfileSource = ProfileSource(profile.PKIFile) )
type Registrar ¶
type Registrar struct {
// contains filtered or unexported fields
}
Registrar admits tools by tier.
func (*Registrar) Registered ¶
Registered returns the names of every admitted tool, in registration order.
type StackContext ¶
StackContext is the cluster an importer's stacks are rendered for.
type StackFunc ¶
type StackFunc func(StackContext) (map[string][]byte, error)
A StackFunc returns manifest stacks keyed "<stack>/<file>.yaml" (or .yml): one directory level, a stack name that is a DNS-1123 label and not a bundled one, and no file name starting with a dot. On every control-plane `stratum up` they are staged beside the bundled add-ons, which the operator applies and prunes; a file no longer returned is removed, and its objects pruned. Only the operator leader's copy is applied, so return the same bytes on every control plane. An error, or a key that breaks these rules, fails the start.