Skip to content

feat: Add kubernetes live-status command - #590

Open
egorpavlikhin wants to merge 6 commits into
mainfrom
feature/kubernetes-live-status
Open

feat: Add kubernetes live-status command#590
egorpavlikhin wants to merge 6 commits into
mainfrom
feature/kubernetes-live-status

Conversation

@egorpavlikhin

Copy link
Copy Markdown

Summary

  • Adds a new octopus kubernetes live-status command (aliased as octopus k8s live-status) to query real-time health and sync status of Kubernetes resources deployed via Octopus Deploy
  • Supports project, environment, and optional tenant targeting with --summary-only mode for quick health checks
  • Includes full table output with hierarchical indentation for nested resources (Deployments → ReplicaSets → Pods)

Example

$ octopus k8s live-status --project "K8s Smoke Test Demo" --environment Development --space Default --no-prompt

Name                                 Kind           Namespace  Health     Sync    Last Updated
smoke-test-app                       Deployment     default    Healthy    InSync  2026-04-16T04:34:36.6034688Z
  smoke-test-app-7f6d95648f          ReplicaSet     default    Healthy            2026-04-16T04:34:36.6300166Z
    smoke-test-app-7f6d95648f-22k58  Pod            default    Healthy            2026-04-16T04:34:36.6496788Z
    smoke-test-app-7f6d95648f-hfn8b  Pod            default    Healthy            2026-04-16T04:34:36.6757964Z
smoke-test-app                       Service        default    Healthy    InSync  2026-04-16T04:34:36.577708Z
  smoke-test-app-xpzhb               EndpointSlice  default    Available          2026-04-16T04:34:36.7116532Z
  smoke-test-app                     Endpoints      default    Available          2026-04-16T04:34:36.6819317Z

Files changed

  • pkg/cmd/kubernetes/kubernetes.go — New top-level kubernetes command group with k8s alias
  • pkg/cmd/kubernetes/live-status/live-status.go — Command implementation with flags, API call, and output formatting
  • pkg/cmd/kubernetes/live-status/live-status_test.go — 6 unit tests covering automation mode, JSON output, summary mode, and alias
  • pkg/cmd/root/root.go — Register new kubernetes command
  • examples.md — Add usage examples
  • README.md — Add kubernetes to code structure docs

Test plan

  • go build ./... compiles successfully
  • go test ./pkg/cmd/kubernetes/... — all 6 tests pass
  • go test ./pkg/... — full test suite passes with no regressions
  • Manual test against live Octopus Deploy instance

🤖 Generated with Claude Code

egorpavlikhin and others added 6 commits April 16, 2026 14:26
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each machine or Argo CD gateway is now always displayed as a top-level
grouping node, with its resources indented underneath. This makes it
clear which machine owns which resources when a project-environment
pair has multiple deployment targets.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
A project and environment whose deployment process cannot report live
object status returns Summary.Status "NotSupported" with no machine
statuses, which read as "No Kubernetes resources found." That sends the
user looking for a data problem, when the cause is the deployment process
using script-based Kubernetes steps, or a target whose Kubernetes monitor
is not enabled.

Reproduced against a local Octopus with a Kubernetes agent: every
script-step project reports NotSupported, a raw-YAML project reports
Healthy with its resources.

An empty result on a supported project still reports no resources found;
the two are different situations.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The grouping row printed the raw machine ID (Machines-21), where every
other command resolves machine IDs to names. Look the name up, falling
back to the ID if the lookup fails, since this is a display detail and
should not fail the command.

NewRootResource in the test fake had no Machines link, so machine lookups
failed without issuing a request and could not be asserted on; added it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The json output format was re-marshalled from the structs the table needs,
which silently dropped every other field the server reports. Against a
local Octopus with a Kubernetes monitor, that lost ArgoCDInstanceStatuses,
and per resource ResourceId, DesiredResourceId, MachineId, OrphanedAt and
the DeletionTask fields, plus Summary.TotalOrphanCount and
SyncStatusMessage -- so orphaned and pending-deletion resources were
invisible to a programmatic caller.

Print the response body instead. The structs stay as they are; they model
what the table renders, which is not the same contract as -f json.

Also drops the Json mapper from PrintArray, which was unreachable because
the json format returns earlier.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@NickJosevski

Copy link
Copy Markdown
Contributor

Question on -f json, since I've changed it in 22791b9 and want to check I haven't undone something deliberate.

It was re-marshalling LiveStatusResponse rather than emitting the server's response. Testing against a local Octopus with a Kubernetes monitor enabled, that dropped every field the structs don't model:

  • top level: ArgoCDInstanceStatuses
  • per resource: ResourceId, DesiredResourceId, MachineId, OrphanedAt, DeletionTaskId, DeletionTaskState, DeletionTaskErrorMessage
  • summary: TotalOrphanCount, SyncStatusMessage

So orphaned and pending-deletion resources were invisible to anything consuming the JSON, and Argo CD instance statuses were absent entirely. I've made it print the response body instead, which brings that to zero missing fields.

Was the narrower shape intentional — a deliberately stable CLI-owned contract, insulated from server changes — or just a side effect of reusing the structs the table needs? If it was intentional I'll happily revert that commit and instead widen the structs to cover the fields above, though then they need maintaining as the server adds more.

Worth noting either way: the struct fields you did model all match the real payload, ResourceSourceId and SourceType included, so nothing was being silently parsed into zero values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants