Skip to content

feat: add kubernetes-agent solution (CX-41) - #241

Merged
jeff-schnitter merged 44 commits into
mainfrom
worktree-kubernetes-agent-solution
Sep 7, 2026
Merged

jeff-schnitter merged 44 commits into
mainfrom
worktree-kubernetes-agent-solution

Conversation

@jeff-schnitter

Copy link
Copy Markdown
Collaborator

Summary

  • Adds the kubernetes-agent Cortex solution bundle, which deploys the Cortex k8s-agent to a Kubernetes cluster and creates demo workloads to demonstrate the integration
  • Supports two deployment paths: GitHub Codespace (spins up a kind cluster automatically) and existing cluster
  • Includes a devcontainer for the Codespace path with kubectl/helm/kind installed via onCreate.sh

What's included

  • cortexapps_cli/solutions/kubernetes-agent/setup.py — post-install setup script
  • cortexapps_cli/solutions/kubernetes-agent/helm-chart/ — bundled k8s-agent Helm chart
  • cortexapps_cli/solutions/kubernetes-agent/manifests/ — demo workloads (Deployment, StatefulSet, CronJob, Argo Rollout)
  • cortexapps_cli/solutions/kubernetes-agent/catalog/ — demo-kubernetes Cortex entity
  • cortexapps_cli/solutions/kubernetes-agent/README.md — with ASCII art data model and After Installing next steps
  • .devcontainer/kubernetes-agent/ — devcontainer config and onCreate.sh

Test plan

  • End-to-end tested: Codespace path (create Codespace → kind cluster → k8s-agent → demo workloads → entity creation)
  • Agent syncs every 5 minutes and data appears in Cortex K8s tab
  • Re-run idempotency: completed steps are skipped on re-run
  • Saved Codespace name reused across re-runs; auto-recreates if deleted
  • What next? menu: Data Model (ASCII art) and Next Steps (After Installing) both render correctly

🤖 Generated with Claude Code

jeff-schnitter and others added 30 commits August 25, 2026 09:31
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…aths

setup.py now prompts the user to choose between:
- Spinning up a GitHub Codespace with a kind cluster automatically
  (via gh codespace create + gh codespace ssh for all k8s/helm commands)
- Deploying to any existing Kubernetes cluster configured in kubectl context
  (runs kubectl/helm locally as before)

Idempotent: Codespace name is persisted in state so re-runs reconnect
rather than creating a new Codespace.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously the existing-Codespace path returned immediately after
verifying the Codespace exists, without waiting for kubectl/kind to
be ready. Now both the new and reuse paths converge on the same
kubectl readiness poll.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Tee all onCreate.sh output to /tmp/onCreate.log for diagnosability
- Use python3 -m pip instead of pip (more reliable on Ubuntu 24.04)
- Timeout error now shows the SSH + log command to diagnose failures

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- onCreate.sh writes /tmp/onCreate.failed on non-zero exit (EXIT trap)
- Poll loop checks failure sentinel on each iteration via a single SSH
  call, failing fast instead of waiting out the full 15-min timeout
- Combined kubectl check + sentinel check into one SSH round-trip
- Corrected wait message to "may take 15-20 min" (was "~5-10 min")

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The CLI runs locally; installing it in the Codespace is unnecessary
and was causing onCreate.sh to fail (Ubuntu 24.04 base has no python3
in PATH by default), which triggered Alpine recovery mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both the FAILED sentinel and timeout error paths now SSH in and fetch
/tmp/onCreate.log automatically, printing it inline so the user sees
the failure reason immediately without manual steps.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jeff-schnitter and others added 14 commits September 2, 2026 16:41
…cess

- Phase 1 (Codespace Available) and Phase 2 (kubectl ready) now each
  get their own full CODESPACE_READY_TIMEOUT budget instead of sharing
  one — Phase 1 taking 5+ min was consuming kubectl polling time
- Add sshd devcontainer feature so SSH is available immediately when
  the Codespace starts, before onCreateCommand completes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…emote

Non-interactive SSH sessions don't load .bashrc, so kubectl doesn't find
~/.kube/config via KUBECONFIG. The readiness poll now uses the explicit
binary path and kubeconfig. _run_remote uses bash -lc (login shell) so
PATH and env are set correctly for kubectl/helm calls.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
gh codespace ssh joins post-'--' args with spaces before the remote
shell sees them, so shell metacharacters (;, >, |) in our bash -c
script were interpreted by the remote shell, not bash. Replace with
two simple SSH calls: 'test -f /tmp/onCreate.failed' for the sentinel
and direct kubectl invocation for readiness — no shell metacharacters.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
gh codespace ssh joins post-'--' args with spaces before the remote
shell sees them, making it impossible to safely pass scripts with
shell metacharacters (|, >, ;). bash -lc also sources profile scripts
that can corrupt stdout of piped commands (e.g. kubectl apply -f -).

_run_remote now writes the script to a local temp file, copies it to
the Codespace via gh codespace cp, then executes it with a clean env.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
gh codespace cp wraps remote paths in single quotes (scp behavior),
making the destination filename include literal quote characters.
Instead, pipe the script to 'tee /home/vscode/cortex-run.sh' via
SSH stdin — no file path quoting issues, no shell metacharacters.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The helm install script installs with -rwxr-xr-- (750), which the
vscode user (non-root, not in root group) cannot execute.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Client-side kubectl apply stores the full manifest in a
last-applied-configuration annotation, which exceeds the 262144-byte
limit for the large Argo Rollouts CRD. Server-side apply avoids this.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When metadata labels are configured, Cortex bypasses cortex.io/tag
annotation lookup entirely — the two strategies are mutually exclusive.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Data Model: ASCII art renders in the CLI 'What next?' menu
- Architecture -> Data Model (matches _extract_first_codeblock path)
- Next steps -> After Installing (matches _extract_section lookup)
- Updated After Installing content per product guidance

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@jeff-schnitter
jeff-schnitter merged commit 7d26660 into main Sep 7, 2026
1 of 2 checks passed
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.

1 participant