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
- Variables
- func NewDeleteCommand(f *cmdutil.Factory) *cobra.Command
- func NewDoctorImagesCommand(f *cmdutil.Factory) *cobra.Command
- func NewGetCommand(f *cmdutil.Factory) *cobra.Command
- func NewImagesCommand(f *cmdutil.Factory) *cobra.Command
- func NewListCommand(f *cmdutil.Factory) *cobra.Command
- func NewRestartCommand(f *cmdutil.Factory) *cobra.Command
- func NewRolloutStatusCommand(f *cmdutil.Factory) *cobra.Command
- func NewScaleCommand(f *cmdutil.Factory) *cobra.Command
- func NewStartCommand(f *cmdutil.Factory) *cobra.Command
- func NewStopCommand(f *cmdutil.Factory) *cobra.Command
- func NewWorkloadCommand(f *cmdutil.Factory) *cobra.Command
- func NewYAMLCommand(f *cmdutil.Factory) *cobra.Command
- func NormalizeKind(s string) (string, error)
- func RunList(ctx context.Context, o *clusteropts.ClusterOptions, ...) error
- func RunScale(ctx context.Context, o *clusteropts.ClusterOptions, ...) error
- func SingularKind(plural string) string
- type Workload
- type WorkloadContainer
- type WorkloadMetadata
- type WorkloadPodSpec
- type WorkloadSelector
- type WorkloadSpec
- type WorkloadStatus
- type WorkloadTemplate
Constants ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 NewListCommand ¶
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 ¶
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):
- GET the workload to read spec.selector.matchLabels (the authoritative source — we don't reconstruct it from convention).
- List pods server-side via labelSelector=<rebuilt selector> (`/api/v1/namespaces/<ns>/pods`).
- ConfirmDestructive showing the count and pod names so the user sees exactly which pods are about to be deleted.
- 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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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) Available ¶
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 ¶
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 ¶
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 ¶
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 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 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"`
}