workload

package
v0.0.0-...-333215a Latest Latest
Warning

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

Go to latest
Published: Jun 30, 2026 License: AGPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Package workload implements `olares-cli cluster workload ...` — read-side workload (Deployment / StatefulSet / DaemonSet) inspection for the active user's profile.

The KubeSphere paginated paths (`/kapis/resources.kubesphere.io/ v1alpha3/<kind>` cross-ns and `/kapis/.../namespaces/<ns>/<kind>` per-ns) drive list verbs; per-resource detail uses the K8s native path (`/apis/apps/v1/namespaces/<ns>/<kind>/<name>`). Server-side scoping decides what's visible — CLI never filters or gates based on the cached cluster context (see olares-cluster SKILL.md).

Index

Constants

View Source
const KindAll = "all"

KindAll is the magic value the `list` verb uses to mean "fan out to every kind in SupportedKinds". Not part of SupportedKinds itself so the get/yaml verbs can reject it cleanly.

Variables

View Source
var SupportedKinds = []string{"deployment", "statefulset", "daemonset"}

SupportedKinds lists the workload kinds the cluster tree models today. Kept in canonical singular form — list/get verbs accept either singular (deployment) or plural (deployments); the normalize helper maps both to the path-segment shape the KubeSphere / K8s native APIs expect (always plural).

Functions

func NewDeleteCommand

func NewDeleteCommand(f *cmdutil.Factory) *cobra.Command

NewDeleteCommand: `olares-cli cluster workload delete <ns/name | name> --kind X [-n NS] [--yes] [--propagation P]`.

CLI-original verb (the SPA has no equivalent helper — workload deletion goes through the SPA's app-uninstall path which is a different abstraction). Here we issue the canonical `DELETE /apis/apps/v1/namespaces/<ns>/<kind>/<name>` directly so operators have a sharp tool when they really need to remove a workload object.

--propagation maps to the apiserver's propagationPolicy query parameter:

  • foreground (default): blocks until the cascade completes — pods, replicaSets, etc. all gone before the call returns.
  • background: returns immediately; cascade happens out of band.
  • orphan: leaves the dependents alone (rarely what you want; provided for parity).

Wrapped in ConfirmDestructive — workload deletion is permanent.

func NewDoctorImagesCommand

func NewDoctorImagesCommand(f *cmdutil.Factory) *cobra.Command

NewDoctorImagesCommand backs `olares-cli doctor images` — a local containerd image inventory annotated with how many workload container references point at each image. `--unused` narrows the view to images nothing references (orphans / prune candidates).

func NewGetCommand

func NewGetCommand(f *cmdutil.Factory) *cobra.Command

NewGetCommand: `olares-cli cluster workload get <ns/name | name> [-n NS] --kind <kind> [-o table|json]`.

Calls SPA's getWorkloadsControler (apps/packages/app/src/apps/controlPanelCommon/network/index.ts:384): `/apis/apps/v1/namespaces/<ns>/<kind>/<name>` — K8s native.

--kind is REQUIRED here (cannot be "all"); identity is fully qualified by namespace + kind + name. Accept the same input shapes as `cluster pod get`: positional "<ns>/<name>" or "-n <ns>" + bare "<name>".

func NewImagesCommand

func NewImagesCommand(f *cmdutil.Factory) *cobra.Command

func NewListCommand

func NewListCommand(f *cmdutil.Factory) *cobra.Command

NewListCommand: `olares-cli cluster workload list [-n NS] [--kind all|deployment|statefulset|daemonset] [-l SEL] [--limit N] [--page N] [--all] [-o table|json] [--no-headers] [--quiet]`.

Default --kind is "all" — the verb fans out one KubeSphere request per kind in SupportedKinds and merges the results into a single table with a KIND column. --kind <single> issues one request and drops the KIND column from the output.

Pagination is per-kind. In --all mode each kind drains independently (so a deployment-heavy ns doesn't starve statefulsets). In --page mode the same page index is requested from every kind — useful for "give me page 2 across the board" symmetry.

Calls SPA's getWorkloadList (apps/packages/app/src/apps/controlPanelCommon/network/index.ts:297): `/kapis/resources.kubesphere.io/v1alpha3/<kind>` cross-ns or `/kapis/.../namespaces/<ns>/<kind>` per-ns.

func NewRestartCommand

func NewRestartCommand(f *cmdutil.Factory) *cobra.Command

NewRestartCommand: `olares-cli cluster workload restart <ns/name | name> --kind X [-n NS] [--yes] [--concurrency N]`.

SPA-aligned restart (matches confirmHandler2 in apps/.../controlHub/pages/ApplicationSpaces/Workloads/Detail.vue):

  1. GET the workload to read spec.selector.matchLabels (the authoritative source — we don't reconstruct it from convention).
  2. List pods server-side via labelSelector=<rebuilt selector> (`/api/v1/namespaces/<ns>/pods`).
  3. ConfirmDestructive showing the count and pod names so the user sees exactly which pods are about to be deleted.
  4. Parallel `DELETE /api/v1/namespaces/<ns>/pods/<name>` with bounded concurrency (default 5).

The controller then recreates each pod from the workload's template. We deliberately do NOT use the kubectl-style `restartedAt` annotation trick — that would diverge from the SPA's behavior the user already knows, and it requires PATCHing the template (which some user-facing constraints disallow).

func NewRolloutStatusCommand

func NewRolloutStatusCommand(f *cmdutil.Factory) *cobra.Command

NewRolloutStatusCommand: `olares-cli cluster workload rollout-status <ns/name | name> --kind X [-n NS] [--watch] [--interval D] [--timeout D]`.

Polls the same K8s native endpoint `cluster workload get` uses (`/apis/apps/v1/namespaces/<ns>/<kind>/<name>`) and applies a kind-aware convergence rule that mirrors `kubectl rollout status`:

  • Deployment / StatefulSet: observedGeneration == metadata.generation AND updatedReplicas == spec.replicas AND readyReplicas == spec.replicas
  • DaemonSet: observedGeneration == metadata.generation AND updatedNumberScheduled == desiredNumberScheduled AND numberReady == desiredNumberScheduled

Without --watch: one GET, prints a one-line status, exits 0 if converged or 2 if not — handy for shell scripts that just want a yes/no answer.

With --watch: re-poll on --interval (default 2s) until converged, --timeout elapses (default 10m), or Ctrl-C. Same signal + 5-error tolerance plumbing as `cluster pod logs --follow`. Each state change emits one line (table mode) or one JSON object (JSONL mode); steady ticks are silent so users only see real progress.

func NewScaleCommand

func NewScaleCommand(f *cmdutil.Factory) *cobra.Command

NewScaleCommand: `olares-cli cluster workload scale <ns/name | name> --kind X --replicas N [-n NS] [--watch] [--interval D] [--timeout D] [--yes]`.

PATCHes the workload with `{"spec":{"replicas":N}}` using Content-Type `application/merge-patch+json`. Same plumbing the SPA's patchWorkloadsControler uses (apps/.../controlPanelCommon/network/index.ts:372).

Confirmation:

  • --replicas=0 (scale-to-zero / "stop") triggers ConfirmDestructive because it pauses traffic the same way `workload stop` does. Other replica counts are reversible and silent.

--watch chains into the rollout-status convergence loop so users get "scaled and waited for ready" in one command. Skipped for DaemonSets (which can't be scaled — server would reject the PATCH with 422 anyway, but we surface a clearer error before the wire).

func NewStartCommand

func NewStartCommand(f *cmdutil.Factory) *cobra.Command

NewStartCommand: `olares-cli cluster workload start <ns/name | name> --kind X --replicas N [-n NS] [--watch]`.

Thin alias for `cluster workload scale --replicas=N`. Justified for the same reason as `stop` — the SPA pairs them ("STOP" / "START") and CLI users will look for the verb by name.

--replicas is REQUIRED here (we don't have a "previous replicas count" cached anywhere; the SPA infers it from spec but for the CLI it's safer to make the operator name the target). No ConfirmDestructive — starting a stopped workload is non-destructive.

DaemonSets are rejected the same way `workload scale` rejects them.

func NewStopCommand

func NewStopCommand(f *cmdutil.Factory) *cobra.Command

NewStopCommand: `olares-cli cluster workload stop <ns/name | name> --kind X [-n NS] [--watch] [--yes]`.

Thin alias for `cluster workload scale --replicas=0 --yes`. Justified because the SPA exposes a labeled "STOP" button on the workload detail page (apps/.../Workloads/Detail.vue:208-209) — CLI users will look for the verb by name, not infer "scale to 0".

DaemonSets are rejected the same way `workload scale` rejects them (no replicas concept). To "stop" a DaemonSet you'd delete the workload entirely (`cluster workload delete`) since DaemonSet has no scale-to-zero idiom.

func NewWorkloadCommand

func NewWorkloadCommand(f *cmdutil.Factory) *cobra.Command

NewWorkloadCommand assembles `olares-cli cluster workload`. Verbs are added incrementally; today's set is the read-only Phase 1b slice (list / get / yaml). Phase 4 will bring scale + restart using the same merge-patch+json plumbing the SPA's patchWorkloadsControler uses (see apps/packages/app/src/apps/controlPanelCommon/network/index.ts:372).

func NewYAMLCommand

func NewYAMLCommand(f *cmdutil.Factory) *cobra.Command

NewYAMLCommand: `olares-cli cluster workload yaml <ns/name | name> [-n NS] --kind <kind>`. Same K8s native endpoint as `get`, but bytes are forwarded through sigs.k8s.io/yaml so unknown fields stay in the output (the typed Workload struct only models the fields verbs render).

func NormalizeKind

func NormalizeKind(s string) (string, error)

NormalizeKind converts user-facing kind input to the canonical plural lowercase form expected by both KubeSphere and K8s APIs.

Accepts: deployment / deployments / Deployment / DEPLOYMENT (and the same for statefulset / daemonset). Returns ("deployments", nil) etc. on success, ("", error) on unknown.

Special case: KindAll is preserved verbatim so list.go can branch on it without re-checking case.

func RunList

func RunList(
	ctx context.Context,
	o *clusteropts.ClusterOptions,
	p *clusteropts.PaginationOptions,
	namespace, kindRaw, labelSelector string,
) error

RunList is the exported entry point so sibling packages (cluster/application) can share the same fetch + render path.

func RunScale

func RunScale(ctx context.Context, o *clusteropts.ClusterOptions, namespace, name, kindPlural string, replicas int, watch bool, interval, timeout time.Duration, assumeYes bool) error

RunScale is the exported scale entry point used by `workload stop` and `workload start` (which are thin aliases over scale-with-known- replicas). Keeps the PATCH plumbing in one place.

func SingularKind

func SingularKind(plural string) string

SingularKind returns the user-facing singular form of a normalized plural kind (used to populate the KIND column when the wire item didn't carry kind). plural must be a value from NormalizeKind's success branch.

Types

type Workload

type Workload struct {
	APIVersion string           `json:"apiVersion,omitempty"`
	Kind       string           `json:"kind,omitempty"`
	Metadata   WorkloadMetadata `json:"metadata"`
	Spec       WorkloadSpec     `json:"spec"`
	Status     WorkloadStatus   `json:"status"`
}

Workload is the minimal typed view we decode from both the KubeSphere paginated list envelope and the K8s native single- resource GET. Spans Deployment / StatefulSet / DaemonSet — fields not relevant to a particular kind stay zero-valued.

As with cmd/ctl/cluster/pod/types.go::Pod, the goal is to model only the fields actually rendered or summarized by verbs in this package. Verbs that need richer detail can decode the same body into their own typed view; for `yaml` we use the raw response bytes to avoid dropping unknown fields entirely.

func (Workload) Age

func (w Workload) Age(now time.Time) string

Age returns the AGE column string.

func (Workload) Available

func (w Workload) Available(plural string) string

Available returns a coarse boolean sentence for the get summary: "all replicas available" / "X of Y available" / "rolling out". Used in the vertical key/value layout, NOT in the list table (the READY column there already conveys availability).

func (Workload) Ready

func (w Workload) Ready(plural string) string

Ready returns the "x/y" READY column for a workload, picking the right counts based on kind. Falls back to "-/-" when neither shape applies (shouldn't happen in practice).

func (Workload) RolloutInProgress

func (w Workload) RolloutInProgress() bool

RolloutInProgress reports whether the controller hasn't caught up with the spec yet. Used by the get summary to flag in-flight rollouts ("rollout in progress" suffix). Compared against metadata.generation rather than status.replicas so the verdict matches kubectl rollout status semantics.

func (Workload) UpdateStrategyLabel

func (w Workload) UpdateStrategyLabel(plural string) string

updateStrategyLabel returns the kind-appropriate update-strategy string for the get summary. Exposed so get.go can render it without re-implementing the per-kind branching.

type WorkloadContainer

type WorkloadContainer struct {
	Name  string `json:"name,omitempty"`
	Image string `json:"image,omitempty"`
}

type WorkloadMetadata

type WorkloadMetadata struct {
	Name              string            `json:"name"`
	Namespace         string            `json:"namespace,omitempty"`
	UID               string            `json:"uid,omitempty"`
	CreationTimestamp string            `json:"creationTimestamp,omitempty"`
	Labels            map[string]string `json:"labels,omitempty"`
	Annotations       map[string]string `json:"annotations,omitempty"`
	Generation        int64             `json:"generation,omitempty"`
}

type WorkloadPodSpec

type WorkloadPodSpec struct {
	InitContainers []WorkloadContainer `json:"initContainers,omitempty"`
	Containers     []WorkloadContainer `json:"containers,omitempty"`
}

type WorkloadSelector

type WorkloadSelector struct {
	MatchLabels map[string]string `json:"matchLabels,omitempty"`
}

type WorkloadSpec

type WorkloadSpec struct {
	// Replicas is the desired count for Deployment / StatefulSet.
	// Pointer so we can distinguish "missing" (DaemonSet) from
	// "explicit zero" (scaled-to-zero Deployment).
	Replicas *int             `json:"replicas,omitempty"`
	Selector WorkloadSelector `json:"selector,omitempty"`
	// Strategy carries Deployment.spec.strategy.type
	// (RollingUpdate / Recreate); we surface it in get -o table.
	Strategy struct {
		Type string `json:"type,omitempty"`
	} `json:"strategy,omitempty"`
	// UpdateStrategy carries StatefulSet/DaemonSet update strategy
	// (OnDelete / RollingUpdate). One of Strategy or UpdateStrategy
	// is populated depending on the kind.
	UpdateStrategy struct {
		Type string `json:"type,omitempty"`
	} `json:"updateStrategy,omitempty"`
	ServiceName string            `json:"serviceName,omitempty"` // StatefulSet only
	Template    *WorkloadTemplate `json:"template,omitempty"`
}

type WorkloadStatus

type WorkloadStatus struct {
	// Deployment + StatefulSet fields.
	Replicas          int `json:"replicas,omitempty"`
	ReadyReplicas     int `json:"readyReplicas,omitempty"`
	AvailableReplicas int `json:"availableReplicas,omitempty"`
	UpdatedReplicas   int `json:"updatedReplicas,omitempty"`
	// DaemonSet fields.
	CurrentNumberScheduled int `json:"currentNumberScheduled,omitempty"`
	NumberReady            int `json:"numberReady,omitempty"`
	DesiredNumberScheduled int `json:"desiredNumberScheduled,omitempty"`
	NumberMisscheduled     int `json:"numberMisscheduled,omitempty"`
	NumberAvailable        int `json:"numberAvailable,omitempty"`
	// UpdatedNumberScheduled is the DaemonSet equivalent of
	// updatedReplicas — number of nodes whose pod is on the latest
	// template version. Used by `cluster workload rollout-status` to
	// decide whether a DaemonSet rollout has converged.
	UpdatedNumberScheduled int `json:"updatedNumberScheduled,omitempty"`
	// Generation observed by the controller; if it lags
	// metadata.generation the rollout is still in progress.
	ObservedGeneration int64 `json:"observedGeneration,omitempty"`
}

type WorkloadTemplate

type WorkloadTemplate struct {
	Spec WorkloadPodSpec `json:"spec,omitempty"`
}

Jump to

Keyboard shortcuts

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