Help us shape the future of Go! Take the 2026 Go Developer Survey

nodejob

package
v1.36.5-stratum.0 Latest Latest
Warning

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

Go to latest
Published: Oct 26, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package nodejob runs a privileged, node-pinned Job that nsenters PID 1 and execs the on-host stratum binary, then gates on the Job result. It is the one implementation of a mechanism that internal/upgrade (rolling upgrades) and internal/certs (cluster CA rotation) both drive, so the two drivers cannot diverge. Every change to the privileged-Job runner — stale-Job guard, image pin, security-context tightening — lives here once.

The Job pod is deliberately hostPID/hostNetwork + privileged and runs a shell-free argv (nsenter execs the binary directly; no /bin/bash -c), so no interpreter ever re-parses a caller value.

Index

Constants

View Source
const NodeAnnotation = "stratum.ciq.com/node"

NodeAnnotation carries the target node's name verbatim.

The label cannot: a node name is a DNS subdomain and may be 253 characters, while a label value may be 63. Build therefore puts a hash in the label when the name does not fit, and the full name here, where there is no limit.

Variables

View Source
var ErrLogUnread = errors.New("its log could not be read")

ErrLogUnread marks a RunExitCodeLogs error whose Job did end with an exit status, returned beside it, but whose Pod's log could not be read: the apiserver reads it from the node's kubelet, which can be unreachable or untrusted while the Job's status still says how it ended.

Functions

func Build

func Build(s Spec) *batchv1.Job

Build renders the Job object for s. Pure — split out so the pod spec is unit-testable without a cluster.

func DeleteAndWait

func DeleteAndWait(ctx context.Context, cs kubernetes.Interface, namespace, name string) error

DeleteAndWait foreground-deletes a Job and waits until it is gone, so a fresh Create cannot race the old object.

func DeleteExactAndWait

func DeleteExactAndWait(ctx context.Context, cs kubernetes.Interface, j *batchv1.Job) error

DeleteExactAndWait deletes exactly the Job object it was given, with its UID and resourceVersion as preconditions, so a Job recreated or changed since it was inspected (another run's, now running) is never the one removed. Then it waits for it to be gone.

func Finished

func Finished(j *batchv1.Job) bool

Finished reports whether a Job has run to an end: it succeeded or failed, by its counters or its conditions. A Job being deleted is not finished until its Pod is: a deletion timestamp alone says nothing about the host.

func JobNode

func JobNode(j *batchv1.Job, labelKey string) string

JobNode returns the node a Job targets. Jobs written before NodeAnnotation existed carry the name in the label, which was possible only because a node whose name did not fit could not have a Job at all.

func Logs

func Logs(ctx context.Context, cs kubernetes.Interface, s Spec) (string, error)

Logs returns the log of s.Container in the Pod of the Job named s.Name, as RunExitCode reads its exit code: by the Job's UID, so an earlier Job's Pod cannot answer.

func NodeLabelValue

func NodeLabelValue(node string) string

NodeLabelValue returns node when it is a usable label value, or a stable hash of it when it is not. Selecting on LabelKey=NodeLabelValue(node) finds every Job targeting that node, whatever scheme named them.

func Ready

func Ready(n *corev1.Node) bool

Ready reports whether a node's Ready condition is True.

func Run

func Run(ctx context.Context, cs kubernetes.Interface, s Spec) error

Run creates the Job (replacing a stale one from a prior run so its stale status cannot short-circuit the poll), waits for it to complete, deletes it on success, and returns an error on failure or timeout.

func RunExitCode

func RunExitCode(ctx context.Context, cs kubernetes.Interface, s Spec) (int, error)

RunExitCode runs a Job whose answer is its exit status rather than its success, and returns the container's exit code: 0 when the Job succeeded, the code it failed with otherwise. A failed Job is left in place for inspection, and the next Run or RunExitCode on it replaces it. An error means no exit status could be established (the Job timed out, or failed without its container terminating).

func RunExitCodeLogs

func RunExitCodeLogs(ctx context.Context, cs kubernetes.Interface, s Spec) (int, string, error)

RunExitCodeLogs is RunExitCode that also returns the log of the Job's Pod, for a Job that answers in its output as well as its exit status. The log of a succeeded Job is read before the Job is deleted, since Logs finds the Pod through the Job. An error also means the log could not be read; one that wraps ErrLogUnread had an exit status all the same, and returns it.

func TruncName

func TruncName(name string) string

TruncName returns name when it fits the 63-character object-name limit. A longer name keeps its first 46 characters, less any trailing '-' or '.', and gains a hash of the whole name, so the result is a valid name and two long names sharing a prefix still differ.

func WaitReady

func WaitReady(ctx context.Context, cs kubernetes.Interface, name string, attempts int) error

WaitReady polls until the named node is Ready or attempts run out (one every pollInterval).

Types

type Spec

type Spec struct {
	// Output receives cleanup warnings. Nil preserves stdout for standalone
	// callers; operations serving MCP supply their own progress writer.
	Output         io.Writer
	Namespace      string
	Name           string   // Job name; use TruncName to respect the 63-char limit
	Node           string   // pod NodeName, and the value of the LabelKey label
	LabelKey       string   // label whose value is Node (e.g. stratum.ciq.com/upgrade)
	Container      string   // container name
	Argv           []string // full shell-free command: nsenter … -- <binary> …
	ActiveDeadline time.Duration
	PollAttempts   int    // completion polls, one every pollInterval
	Kind           string // noun for error messages, e.g. "per-node upgrade" / "carotate"
	// Critical admits the pod as system-node-critical, as the static pods are:
	// under node pressure the kubelet refuses every other new pod. It is also
	// allowed to evict workload pods to make room, past every PDB, so only a
	// Job on a node that has already been drained should set it.
	Critical bool
}

Spec describes one privileged node Job. Namespace/Name/Node/LabelKey/Container/ Argv define the pod; ActiveDeadline and PollAttempts bound it; Kind names it in the error messages so each caller keeps its own wording.

Jump to

Keyboard shortcuts

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