Skip to content

Implement 'roxie shell' command for (re-)connecting to central deployment#201

Open
mclasmeier wants to merge 15 commits into
mainfrom
mc/resume
Open

Implement 'roxie shell' command for (re-)connecting to central deployment#201
mclasmeier wants to merge 15 commits into
mainfrom
mc/resume

Conversation

@mclasmeier
Copy link
Copy Markdown
Collaborator

@mclasmeier mclasmeier commented Jun 1, 2026

This addresses #197 but in a more general way.

Adds a roxie shell command that opens a subshell (or runs a command) against an existing ACS deployment without re-deploying.

How it works: roxie deploy now persists a manifest secret (roxie-manifest) in a dedicated roxie namespace on the cluster. roxie shell reads that secret, re-fetches the CA certificate, and spawns a subshell with the same environment variables (ROX_ENDPOINT, ROX_ADMIN_PASSWORD, etc.) that roxie deploy sets up.

roxie shell                              # interactive subshell
roxie shell -- roxctl central whoami     # run a single command

Changes:

  • New roxie shell command (cmd/shell.go)
  • New manifest package — stores/loads/deletes a RoxieManifest secret on-cluster, including deploy config for reproducibility
  • New roxieenv package — single source of truth for assembling the ACS environment variables (used by deploy, envrc, and shell)
  • CentralDeploymentInfo and RoxieEnvironment types extracted to internal/types
  • RoxieEnvironment custom YAML marshaler excludes local-only fields (ROX_CA_CERT_FILE)
  • Teardown cleans up the manifest secret and roxie namespace
  • Manifest creation respects --dry-run

Summary by CodeRabbit

  • New Features

    • Added a shell command to open an interactive subshell or run commands against an existing deployment
    • Persist deployment state as a cluster manifest secret for later retrieval
  • Improvements

    • Deploy now writes manifest secrets and sets up runtime environment for subshells (including HAProxy when available)
    • Teardown now cleans manifest secrets and optionally removes the deployment namespace
    • Environment assembly/export improved for clearer ROXIE configuration
  • Tests

    • Added unit and integration tests for manifest and environment handling

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

Warning

Review limit reached

@mclasmeier, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 56 minutes and 6 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Enterprise

Run ID: 8f814aa0-de52-435f-bc53-273272122f80

📥 Commits

Reviewing files that changed from the base of the PR and between a9a3a6f and 1560e3e.

📒 Files selected for processing (1)
  • cmd/shell.go
📝 Walkthrough

Walkthrough

Adds persistent ROXIE manifest storage in a Kubernetes Secret, new types and helpers for assembling a ROXIE environment from central deployment info, CLI integration to create/load/delete the manifest (deploy/teardown), and a new shell command/subshell refactor that uses the assembled environment.

Changes

ROXIE Manifest Persistence and Environment Management Feature

Layer / File(s) Summary
Type Contracts for Deployment and Environment Info
internal/types/central_deployment_info.go, internal/types/roxie_environment.go
CentralDeploymentInfo captures central connection, exposure, CA path, and HAProxy state. RoxieEnvironment holds ROXIE config fields, implements MarshalYAML() to exclude local-only CA cert from persisted YAML, and provides Export() to yield non-empty YAML-tagged fields as env key/value pairs.
Environment Assembly from Deployment Info
internal/roxieenv/env.go, internal/roxieenv/env_test.go
AssembleRoxieEnvironment builds a RoxieEnvironment from CentralDeploymentInfo (derives RoxBaseURL from endpoint). Unit tests verify the exported environment keys/values and omission of keys when inputs are empty.
Manifest Persistence: Creation, Loading, and Deletion
internal/manifest/manifest.go, internal/manifest/manifest_integration_test.go
Defines RoxieManifest (contains RoxieEnvironment and deployer.Config). Implements conversion to/from a Kubernetes Secret, CreateManifestSecretOnCluster (ensures namespace), LoadManifestSecret (base64 decode + YAML unmarshal), DeleteManifestSecret/DeleteRoxieNamespace (ignore-not-found), and ManifestToCentralDeploymentInfo which attempts to fetch Central CA PEM into a temp file. Integration tests cover lifecycle and not-found/error cases.
Deployer: New Type and Dynamic Environment Generation
internal/deployer/deployer.go
GetCentralDeploymentInfo() returns types.CentralDeploymentInfo (populates Endpoint and Username). writeEnvrcFile now iterates roxieenv.AssembleRoxieEnvironment(...).Export() to write export lines instead of hardcoded exports.
CLI Integration: Manifest Persistence and Subshell Refactoring
cmd/main.go, cmd/deploy.go, cmd/teardown.go, cmd/subshell.go, cmd/shell.go
Deploy assembles RoxieManifest and calls CreateManifestSecretOnCluster when Central is included (non-dry-run), logging warnings on failures. Teardown deletes manifest Secret (when Central included) and deletes Roxie namespace (when tearing down all), downgrading errors to warnings. Registers a new shell command. Subshell refactored to runCommandOrSubshell which builds environment from AssembleRoxieEnvironment(...).Export(), optionally starts HAProxy, and runs either an interactive shell (resolved path, prints banner, uses -i) or a provided command; printBanner now accepts types.CentralDeploymentInfo.

Sequence Diagram

sequenceDiagram
  participant user as User
  participant deployCmd as Deploy Command
  participant deployer as Deployer
  participant manifest as manifest package
  participant kubectl as kubectl
  participant shellCmd as Shell Command
  participant subshell as Subshell

  user->>deployCmd: roxie deploy
  deployCmd->>deployer: WaitForCentral()
  deployer-->>deployCmd: CentralDeploymentInfo
  deployCmd->>manifest: CreateManifestSecretOnCluster(RoxieManifest)
  manifest->>kubectl: apply namespace & apply Secret (stdin)
  kubectl->>manifest: cluster applies Secret
  deployCmd-->>user: continue (warnings logged if failure)

  user->>shellCmd: roxie shell
  shellCmd->>manifest: LoadManifestSecret()
  manifest->>kubectl: get Secret data
  kubectl->>manifest: return Secret data
  manifest-->>shellCmd: RoxieManifest -> CentralDeploymentInfo (attempt CA fetch)
  shellCmd->>subshell: runCommandOrSubshell(info, args)
  subshell->>subshell: Assemble env via AssembleRoxieEnvironment(...).Export()
  subshell->>subshell: optionally start HAProxy
  subshell-->>user: launch interactive shell or run command
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

"🐰 A manifest appears, with secrets in hand,
The deployer dances across the land,
Environment whispers through export loops,
HAProxy hums guard beside our groups,
A shell pops open — persistence at last!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Implement roxie shell command for (re-)connecting to central deployment' accurately summarizes the primary change—adding a new shell command that enables users to reconnect to existing Central deployments.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch mc/resume

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
cmd/deploy.go (1)

342-351: ⚡ Quick win

Confirm manifest API matches the cmd/deploy.go call site; drop the type/signature mismatch concern.
internal/manifest/manifest.go defines RoxieManifest with RoxieEnvironment types.RoxieEnvironment and Config deployer.Config, and CreateManifestSecretOnCluster(ctx, log, m RoxieManifest) error, matching the constructed m and call signature in cmd/deploy.go. If CI still typechecks-fails, the issue is elsewhere.

  • If dryRun already returns earlier in cmd/deploy.go, the && !dryRun guard around this block can be removed.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/deploy.go` around lines 342 - 351, The call site constructs a
manifest.RoxieManifest using
roxieenv.AssembleRoxieEnvironment(d.GetCentralDeploymentInfo()) and
deploySettings and passes it to manifest.CreateManifestSecretOnCluster(ctx, log,
m); confirm the manifest.RoxieManifest type and
CreateManifestSecretOnCluster(ctx, log, m RoxieManifest) signature in
internal/manifest/manifest.go match exactly (field names/types for
RoxieEnvironment and Config) and fix any mismatched imports or type aliases;
also, if cmd/deploy.go already returns early on dryRun, remove the redundant "&&
!dryRun" guard around the block guarded by components.IncludesCentral() to avoid
dead/duplicate checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/subshell.go`:
- Around line 54-89: The command mode currently wraps any child non-zero exit
into a generic error instead of propagating the child's exit code; change the
error handling after cmd.Run() so that when err is an *exec.ExitError you
extract the exit status (use exitErr.ExitCode()) and call os.Exit(exitCode) (or
otherwise return a sentinel that the caller converts into that exit code),
rather than returning fmt.Errorf("failed to execute command: %w", err); keep the
existing behavior for non-start failures. Locate this logic around the cmd.Run()
call and the error handling for both the subshell branch and the non-subshell
branch (referencing subShellMode, cmd.Run, and exec.ExitError) and implement the
exit-code propagation for the non-subshell command path.

---

Nitpick comments:
In `@cmd/deploy.go`:
- Around line 342-351: The call site constructs a manifest.RoxieManifest using
roxieenv.AssembleRoxieEnvironment(d.GetCentralDeploymentInfo()) and
deploySettings and passes it to manifest.CreateManifestSecretOnCluster(ctx, log,
m); confirm the manifest.RoxieManifest type and
CreateManifestSecretOnCluster(ctx, log, m RoxieManifest) signature in
internal/manifest/manifest.go match exactly (field names/types for
RoxieEnvironment and Config) and fix any mismatched imports or type aliases;
also, if cmd/deploy.go already returns early on dryRun, remove the redundant "&&
!dryRun" guard around the block guarded by components.IncludesCentral() to avoid
dead/duplicate checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Enterprise

Run ID: c33d0da6-23cf-44f4-b552-8bfff8724aa8

📥 Commits

Reviewing files that changed from the base of the PR and between befa352 and 53703cc.

📒 Files selected for processing (11)
  • cmd/deploy.go
  • cmd/main.go
  • cmd/subshell.go
  • cmd/teardown.go
  • internal/deployer/deployer.go
  • internal/manifest/manifest.go
  • internal/manifest/manifest_integration_test.go
  • internal/roxieenv/env.go
  • internal/roxieenv/env_test.go
  • internal/types/central_deployment_info.go
  • internal/types/roxie_environment.go

Comment thread cmd/subshell.go
…ironment

Provide separate function for spawning subshell given a deployer.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/shell.go`:
- Around line 31-34: Fix the typo in the examples block by replacing the
incorrect "roxie shel" string with the correct "roxie shell" so the advertised
primary usage matches the actual command; locate the Examples/usage string where
"roxie shel" appears and update that literal to "roxie shell".
- Around line 35-42: The Run function currently exits with os.Exit(1) for
non-*exec.ExitError errors without logging; update the Run closure (the
anonymous func calling runShell) so that when err != nil and it is not an
*exec.ExitError you first print the error (e.g., fmt.Fprintln(os.Stderr, err) or
use a logger) before calling os.Exit(1). Locate the error handling block that
uses errors.AsType[*exec.ExitError] and add a branch to output the error to
stderr, preserving the existing exit behavior for child process exit errors
returned by runShell.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Enterprise

Run ID: f54999d9-3ae8-480f-937f-2f05a70bb3b2

📥 Commits

Reviewing files that changed from the base of the PR and between 53703cc and a9a3a6f.

📒 Files selected for processing (2)
  • cmd/shell.go
  • cmd/subshell.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/subshell.go

Comment thread cmd/shell.go
Comment thread cmd/shell.go
type roxieEnvironmentStd RoxieEnvironment

// MarshalYAML skips local-only fields (ROX_CA_CERT_FILE).
func (r RoxieEnvironment) MarshalYAML() (any, error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick - it might be nice to add a quick unit test that marshals a RoxieEnvironment with RoxCaCertFile set and asserts the output YAML doesn't contain ROX_CA_CERT_FILE.

@AlexVulaj
Copy link
Copy Markdown
Contributor

Approved with one minor comment, great work!

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