fix: remove Helm charts and standardize on operator-based deployment#448
Conversation
❌ Deploy Preview for jumpstarter-docs failed. Why did it fail? →
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughRemoves Helm-based deployment artifacts and logic across the repo, consolidating installs and tests to operator-only flows by deleting Helm charts, helpers, CLI/install APIs, CI Helm jobs/linting, and updating tests/workflows to use operator-managed CRDs and installer YAMLs. Changes
Sequence Diagram(s)sequenceDiagram
participant CLI as CLI / Make
participant CI as CI Workflows
participant Operator as Jumpstarter Operator (installer YAML)
participant K8s as Kubernetes API (CRDs)
CLI->>Operator: apply installer YAML / make deploy
CI->>Operator: run e2e/compat jobs (apply installer / deploy)
Operator->>K8s: create CRDs & controller Deployment
K8s-->>Operator: CRDs ready / controller available
Operator-->>CI: report ready (tests proceed)
Operator-->>CLI: deployment success
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
6884226 to
fa102b3
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py (1)
220-228: Cover the non-zerokubectlfailure path too.
run_command()failures are often reported via a non-zero return code, not only by raising. This test only exercises the exception path, so the current regression incheck_jumpstarter_installation()can slip through unnoticed.💡 Suggested test addition
`@pytest.mark.asyncio` `@patch`("jumpstarter_kubernetes.cluster.kubectl.run_command") async def test_check_jumpstarter_installation_command_failure(self, mock_run_command): mock_run_command.side_effect = RuntimeError("kubectl not found") result = await check_jumpstarter_installation("test-context") assert result.installed is False assert result.has_crds is False assert result.error is not None assert "kubectl not found" in result.error + + `@pytest.mark.asyncio` + `@patch`("jumpstarter_kubernetes.cluster.kubectl.run_command") + async def test_check_jumpstarter_installation_nonzero_exit(self, mock_run_command): + mock_run_command.return_value = (1, "", "forbidden") + + result = await check_jumpstarter_installation("test-context") + + assert result.installed is False + assert result.has_crds is False + assert result.error is not None + assert "forbidden" in result.error🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py` around lines 220 - 228, The test test_check_jumpstarter_installation_command_failure only simulates run_command raising an exception, but check_jumpstarter_installation must also handle non-zero exit codes; add a test case that makes mock_run_command return a completed-result with a non-zero return code (and stderr containing "kubectl not found") instead of raising, then call check_jumpstarter_installation("test-context") and assert result.installed is False, result.has_crds is False, and the error message contains the stderr text; reference the same test function name and mock_run_command to locate where to add this non-exception path test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@controller/Makefile`:
- Around line 67-68: The Makefile's manifests target now emits CRDs/RBAC to
deploy/operator/config/... (see output:crd:artifacts and output:rbac:artifacts),
but the consuming targets install, uninstall and build-installer still reference
config/crd and config/default; update the consuming targets to read from
deploy/operator/config/... (or revert manifests to write to the canonical
config/... tree) so generated artifacts and consumers are aligned. Specifically,
modify the install and uninstall targets (currently building config/crd) and the
build-installer target (currently building config/default) to point to
deploy/operator/config/crd and deploy/operator/config/default respectively, or
change the manifests output back to the original config/... paths so nothing
else needs changing.
In `@e2e/setup-e2e.sh`:
- Around line 296-299: The script currently hardcodes ports when building
ENDPOINT and LOGIN_ENDPOINT; instead query the Jumpstarter CR for the actual
endpoints/ports and use those values. Replace the kubectl JSONPath that sets
BASEDOMAIN/ENDPOINT/LOGIN_ENDPOINT with commands that read the controller and
login endpoint values from the CR spec (e.g., fields like
.spec.controllerEndpoint or .spec.endpoints.controller and .spec.loginEndpoint
or .spec.endpoints.login) and assign them to ENDPOINT and LOGIN_ENDPOINT (fall
back to the previous host:port construction only if those spec fields are
empty); update any references to BASEDOMAIN if you must derive host/port
separately so ENDPOINT and LOGIN_ENDPOINT reflect the CR configuration rather
than hardcoded ports.
In `@e2e/tests.bats`:
- Around line 65-69: The teardown log dump redirection is wrong: the kubectl log
commands using `kubectl -n "${JS_NAMESPACE}" logs -l component=controller
--tail=250 2>&1 >&2` and the similar router line send both streams to stdout
instead of stderr; update those two commands (`kubectl -n "${JS_NAMESPACE}" logs
-l component=controller --tail=250 ...` and `kubectl -n "${JS_NAMESPACE}" logs
-l component=router --tail=250 ...`) to redirect their output directly to stderr
(use `>&2`) so kubectl errors are shown in Bats failure output.
In
`@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.py`:
- Around line 92-117: The current logic calls run_command(crd_cmd) and if
returncode != 0 it silently leaves result_data without an error and reports
installed=False; change this so non-zero return codes set result_data["error"]
(include the returncode and stdout/stderr text) and do not flip "installed" to
True/False based on absent output; specifically update the code around
run_command/crd_cmd and the handling of returncode to populate
result_data["error"] on failures (and avoid treating lack of jumpstarter_crds as
a clean "not installed" success), using the existing result_data and
jumpstarter_crds variables so callers can distinguish real errors from a genuine
"no CRDs" state.
---
Nitpick comments:
In
`@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py`:
- Around line 220-228: The test
test_check_jumpstarter_installation_command_failure only simulates run_command
raising an exception, but check_jumpstarter_installation must also handle
non-zero exit codes; add a test case that makes mock_run_command return a
completed-result with a non-zero return code (and stderr containing "kubectl not
found") instead of raising, then call
check_jumpstarter_installation("test-context") and assert result.installed is
False, result.has_crds is False, and the error message contains the stderr text;
reference the same test function name and mock_run_command to locate where to
add this non-exception path test.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1c194525-ebff-4562-9606-789010160bb2
📒 Files selected for processing (86)
.cursor/rules/working-with-operator.mdc.github/workflows/build-images.yaml.github/workflows/controller-kind.yaml.github/workflows/e2e.yaml.github/workflows/lint.yamlMakefilecontroller/Makefilecontroller/deploy/helm/jumpstarter/.helmignorecontroller/deploy/helm/jumpstarter/Chart.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/Chart.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/model.pycontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/_endpoints.tplcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-deployment.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-ingress.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-route.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-ingress.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-route.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_clients.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporteraccesspolicies.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporters.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_leases.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-ingress.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-route.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/metrics_service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/monitor.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_editor_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_viewer_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_editor_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_viewer_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role_binding.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role_binding.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/service_account.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-ingress.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-route.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/secrets-job.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.schema.jsoncontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.yamlcontroller/deploy/helm/jumpstarter/model.pycontroller/deploy/helm/jumpstarter/values.kind.yamlcontroller/deploy/helm/jumpstarter/values.schema.jsoncontroller/deploy/helm/jumpstarter/values.yamlcontroller/deploy/operator/README.mdcontroller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.gocontroller/deploy/operator/test/e2e/e2e_test.gocontroller/hack/deploy_with_helm.shcontroller/hack/deploy_with_operator.shcontroller/hack/install_helm.shcontroller/hack/utilscontroller/internal/controller/suite_test.gocontroller/internal/service/suite_test.goe2e/compat/run.she2e/compat/setup.she2e/compat/tests-old-client.batse2e/compat/tests-old-controller.batse2e/setup-e2e.she2e/test/compat_old_controller_test.goe2e/tests.batspython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/__init__.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create_test.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install_test.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/__init__.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/__init__.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/common.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm_test.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations_test.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clusters.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/controller.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exceptions.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install_test.py
💤 Files with no reviewable changes (64)
- .cursor/rules/working-with-operator.mdc
- controller/deploy/helm/jumpstarter/.helmignore
- controller/deploy/helm/jumpstarter/values.kind.yaml
- .github/workflows/lint.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_editor_role.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role_binding.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/monitor.yaml
- controller/deploy/helm/jumpstarter/Chart.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/Chart.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_viewer_role.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role_binding.yaml
- controller/deploy/helm/jumpstarter/values.schema.json
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/common.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/service_account.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-service.yaml
- .github/workflows/build-images.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-ingress.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/_endpoints.tpl
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-route.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-service.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_clients.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_editor_role.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role.yaml
- controller/deploy/helm/jumpstarter/values.yaml
- controller/deploy/operator/README.md
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.schema.json
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clusters.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-route.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-ingress.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/secrets-job.yaml
- controller/hack/install_helm.sh
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_viewer_role.yaml
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create_test.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-route.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/init.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-ingress.yaml
- controller/deploy/helm/jumpstarter/model.py
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/init.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-deployment.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-service.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-route.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporters.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporteraccesspolicies.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-service.yaml
- controller/hack/deploy_with_helm.sh
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install_test.py
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install_test.py
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/init.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-ingress.yaml
- e2e/test/compat_old_controller_test.go
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/model.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/metrics_service.yaml
- e2e/compat/tests-old-controller.bats
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm_test.py
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_leases.yaml
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.py
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@e2e/compat/setup.sh`:
- Around line 205-208: After applying the released operator-installer.yaml via
kubectl apply -f "${INSTALLER_URL}", create a Jumpstarter custom resource
instance so setup_test_environment() can read .spec.baseDomain; mirror the CR
creation from controller/hack/deploy_with_operator.sh (lines ~173-208) by
applying a Jumpstarter manifest (name as in deploy_with_operator.sh) with
spec.baseDomain set to the computed BASEDOMAIN (use the same namespace used by
the operator), ensuring this step runs immediately after the kubectl apply and
before calling setup_test_environment().
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: fdb9e59c-c82e-4d79-ab26-f37ea140c28b
📒 Files selected for processing (3)
.github/workflows/e2e.yamlMakefilee2e/compat/setup.sh
🚧 Files skipped from review as they are similar to previous changes (2)
- .github/workflows/e2e.yaml
- Makefile
0630037 to
e15a5cc
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.py (1)
93-113:⚠️ Potential issue | 🟠 MajorHandle non-zero CRD command exits explicitly.
Line 95 only handles success. If
run_commandreturns non-zero, this currently looks like a clean “not installed” result instead of an execution failure (e.g., RBAC/context errors).Proposed fix
- returncode, stdout, _ = await run_command(crd_cmd) - - if returncode == 0: - json_start = stdout.find("{") - if json_start >= 0: - json_output = stdout[json_start:] - crds = json.loads(json_output) - else: - crds = json.loads(stdout) - jumpstarter_crds = [] - for item in crds.get("items", []): - name = item.get("metadata", {}).get("name", "") - if "jumpstarter.dev" in name: - jumpstarter_crds.append(name) - - if jumpstarter_crds: - result_data["has_crds"] = True - result_data["installed"] = True - result_data["namespace"] = namespace or "unknown" - result_data["status"] = "installed" + returncode, stdout, stderr = await run_command(crd_cmd) + if returncode != 0: + result_data["error"] = f"Failed to query CRDs (exit {returncode}): {stderr or stdout}" + return V1Alpha1JumpstarterInstance(**result_data) + + json_start = stdout.find("{") + if json_start >= 0: + json_output = stdout[json_start:] + crds = json.loads(json_output) + else: + crds = json.loads(stdout) + jumpstarter_crds = [] + for item in crds.get("items", []): + name = item.get("metadata", {}).get("name", "") + if "jumpstarter.dev" in name: + jumpstarter_crds.append(name) + + if jumpstarter_crds: + result_data["has_crds"] = True + result_data["installed"] = True + result_data["namespace"] = namespace or "unknown" + result_data["status"] = "installed"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.py` around lines 93 - 113, The code currently treats any non-zero return from run_command(crd_cmd) as a benign "not installed" path; change the logic in the block that calls run_command so that when returncode != 0 you explicitly handle the execution failure: read the captured stderr (the third value returned by run_command), set result_data["status"] = "error" (or raise an informative exception), include returncode and stderr (and namespace/context) in the error information, and avoid marking result_data["installed"] = True — update the branch around run_command/crd_cmd and the result_data assignments to reflect this explicit error handling.e2e/compat/setup.sh (1)
106-109:⚠️ Potential issue | 🔴 CriticalApply a
Jumpstarterresource after the released installer.The released
operator-installer.yamlinstalls the operator/CRDs, but not thejumpstartercustom resource the operator reconciles. In theold-controllerpath that leaves nothing for the operator to deploy, so the gRPC wait loop below times out and the later.spec.baseDomainlookup also fails.Please verify against the tagged release asset. Expected result: the installer contains no
kind: Jumpstarter, which confirms this script must create one itself immediately after thekubectl apply.#!/bin/bash set -euo pipefail tag="${COMPAT_CONTROLLER_TAG:-v0.8.1}" tmp="$(mktemp)" trap 'rm -f "$tmp"' EXIT curl -LsSf \ "https://github.com/jumpstarter-dev/jumpstarter/releases/download/${tag}/operator-installer.yaml" \ -o "$tmp" echo "== resource kinds in ${tag}/operator-installer.yaml ==" rg -n '^kind:\s*' "$tmp" echo echo "== Jumpstarter CRs in installer ==" rg -n '^kind:\s*Jumpstarter$' "$tmp" || true🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@e2e/compat/setup.sh` around lines 106 - 109, After applying the released operator-installer.yaml (the INSTALLER_URL built from COMPAT_CONTROLLER_TAG), immediately create and apply a minimal Jumpstarter custom resource so the old operator has something to reconcile; construct a Jumpstarter manifest (apiVersion jumpstarter.dev/v1alpha1, kind Jumpstarter, metadata name e.g. "jumpstarter") with the required spec (at least spec.baseDomain set from your cluster/base domain variable) and kubectl apply it right after the kubectl apply -f "${INSTALLER_URL}" line to avoid the gRPC wait loop timing out and the later .spec.baseDomain lookup failing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@e2e/setup-e2e.sh`:
- Around line 282-288: The script assigns BASEDOMAIN from kubectl get
jumpstarter but doesn't validate it; if empty it exports invalid
ENDPOINT/LOGIN_ENDPOINT. After BASEDOMAIN=$(kubectl get jumpstarter ...), check
if BASEDOMAIN is empty/blank and if so print an error (including the
JS_NAMESPACE and the kubectl command context) and exit non‑zero to fail fast;
otherwise export ENDPOINT="grpc.${BASEDOMAIN}:8082" and
LOGIN_ENDPOINT="login.${BASEDOMAIN}:8086". Ensure this validation runs under the
existing set -e behavior so failures propagate.
---
Duplicate comments:
In `@e2e/compat/setup.sh`:
- Around line 106-109: After applying the released operator-installer.yaml (the
INSTALLER_URL built from COMPAT_CONTROLLER_TAG), immediately create and apply a
minimal Jumpstarter custom resource so the old operator has something to
reconcile; construct a Jumpstarter manifest (apiVersion
jumpstarter.dev/v1alpha1, kind Jumpstarter, metadata name e.g. "jumpstarter")
with the required spec (at least spec.baseDomain set from your cluster/base
domain variable) and kubectl apply it right after the kubectl apply -f
"${INSTALLER_URL}" line to avoid the gRPC wait loop timing out and the later
.spec.baseDomain lookup failing.
In
`@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.py`:
- Around line 93-113: The code currently treats any non-zero return from
run_command(crd_cmd) as a benign "not installed" path; change the logic in the
block that calls run_command so that when returncode != 0 you explicitly handle
the execution failure: read the captured stderr (the third value returned by
run_command), set result_data["status"] = "error" (or raise an informative
exception), include returncode and stderr (and namespace/context) in the error
information, and avoid marking result_data["installed"] = True — update the
branch around run_command/crd_cmd and the result_data assignments to reflect
this explicit error handling.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 43ff7ac7-0567-4906-a8b0-f68d4d33eba5
📒 Files selected for processing (80)
.cursor/rules/working-with-operator.mdc.github/workflows/build-images.yaml.github/workflows/controller-kind.yaml.github/workflows/e2e.yaml.github/workflows/lint.yamlMakefilecontroller/Makefilecontroller/deploy/helm/jumpstarter/.helmignorecontroller/deploy/helm/jumpstarter/Chart.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/Chart.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/model.pycontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/_endpoints.tplcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-deployment.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-ingress.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-route.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-ingress.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-route.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_clients.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporteraccesspolicies.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporters.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_leases.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-ingress.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-route.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/metrics_service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/monitor.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_editor_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_viewer_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_editor_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_viewer_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role_binding.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role_binding.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/service_account.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-ingress.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-route.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/secrets-job.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.schema.jsoncontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.yamlcontroller/deploy/helm/jumpstarter/model.pycontroller/deploy/helm/jumpstarter/values.kind.yamlcontroller/deploy/helm/jumpstarter/values.schema.jsoncontroller/deploy/helm/jumpstarter/values.yamlcontroller/deploy/operator/README.mdcontroller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.gocontroller/hack/deploy_with_helm.shcontroller/hack/deploy_with_operator.shcontroller/hack/install_helm.shcontroller/hack/utilscontroller/internal/controller/suite_test.gocontroller/internal/service/suite_test.goe2e/compat/setup.she2e/setup-e2e.shpython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/__init__.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create_test.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install_test.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/__init__.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/__init__.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/common.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm_test.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations_test.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clusters.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/controller.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exceptions.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install_test.py
💤 Files with no reviewable changes (62)
- .cursor/rules/working-with-operator.mdc
- controller/deploy/helm/jumpstarter/.helmignore
- controller/deploy/helm/jumpstarter/Chart.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clusters.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/Chart.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/common.py
- controller/deploy/operator/README.md
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_editor_role.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role_binding.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_editor_role.yaml
- controller/deploy/helm/jumpstarter/values.schema.json
- .github/workflows/lint.yaml
- controller/deploy/helm/jumpstarter/values.kind.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role_binding.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/init.py
- controller/deploy/helm/jumpstarter/values.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/service_account.yaml
- controller/hack/install_helm.sh
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_viewer_role.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/monitor.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-route.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/_endpoints.tpl
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-service.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_clients.yaml
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create_test.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-service.yaml
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/init.py
- controller/deploy/helm/jumpstarter/model.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-service.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-ingress.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/init.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_viewer_role.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-route.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.yaml
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install_test.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-route.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-ingress.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/secrets-job.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporters.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-ingress.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-route.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install_test.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporteraccesspolicies.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.schema.json
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-service.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm_test.py
- controller/hack/deploy_with_helm.sh
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_leases.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-deployment.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-ingress.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/model.py
- .github/workflows/build-images.yaml
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/metrics_service.yaml
✅ Files skipped from review due to trivial changes (4)
- controller/internal/controller/suite_test.go
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/controller.py
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exceptions.py
- controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go
🚧 Files skipped from review as they are similar to previous changes (8)
- .github/workflows/controller-kind.yaml
- controller/internal/service/suite_test.go
- controller/hack/utils
- .github/workflows/e2e.yaml
- Makefile
- controller/Makefile
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations_test.py
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations.py
There was a problem hiding this comment.
🧹 Nitpick comments (1)
python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py (1)
371-376: This doesn't actually exercise the customminikubepath.Because Line 372 returns no contexts,
list_clusters()exits before any downstream call can observeminikube="custom-minikube". Consider returning one context and asserting the follow-up cluster-info call receives the custom binary path too.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py` around lines 371 - 376, The test test_list_clusters_custom_parameters currently returns no contexts so list_clusters exits early; change the mock_get_contexts return to include a context (e.g., ["some-context"]) so the code proceeds, then assert that the subsequent call that invokes cluster info (the mock for whichever helper is used to run minikube/cluster-info in list_clusters) was called with minikube="custom-minikube" (and keep asserting mock_get_contexts.assert_called_once_with("custom-kubectl")); update references to the mocks used in this test (mock_get_contexts and the mock for cluster-info/runner used by list_clusters) to validate both custom kubectl and custom minikube are passed through.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py`:
- Around line 371-376: The test test_list_clusters_custom_parameters currently
returns no contexts so list_clusters exits early; change the mock_get_contexts
return to include a context (e.g., ["some-context"]) so the code proceeds, then
assert that the subsequent call that invokes cluster info (the mock for
whichever helper is used to run minikube/cluster-info in list_clusters) was
called with minikube="custom-minikube" (and keep asserting
mock_get_contexts.assert_called_once_with("custom-kubectl")); update references
to the mocks used in this test (mock_get_contexts and the mock for
cluster-info/runner used by list_clusters) to validate both custom kubectl and
custom minikube are passed through.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 4b6a2325-119d-4569-a0dc-4bde621153da
📒 Files selected for processing (5)
controller/Makefilee2e/compat/setup.she2e/setup-e2e.shpython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py
🚧 Files skipped from review as they are similar to previous changes (1)
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.py
|
@mangelajo ptal again. i have applied your suggestion but i think branch protection rules stop CI from passing. |
635f4f7 to
bbfa5e8
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
e2e/setup-e2e.sh (1)
282-292:⚠️ Potential issue | 🟠 MajorResolve endpoints from the Jumpstarter CR instead of rebuilding them with
:8082/:8086.This still only matches the default kind/nodeport path. Operator deployments can publish different addresses, so the setup script can point tests at the wrong endpoint even when the CR already contains the correct values.
Suggested fix
- local BASEDOMAIN - BASEDOMAIN=$(kubectl get jumpstarter -n "${JS_NAMESPACE}" jumpstarter -o jsonpath='{.spec.baseDomain}') - if [ -z "${BASEDOMAIN}" ]; then - log_error "Failed to get baseDomain from Jumpstarter CR in namespace ${JS_NAMESPACE}" - exit 1 - fi - export ENDPOINT="grpc.${BASEDOMAIN}:8082" - export LOGIN_ENDPOINT="login.${BASEDOMAIN}:8086" + local ENDPOINT_VALUE LOGIN_ENDPOINT_VALUE + ENDPOINT_VALUE=$(kubectl get jumpstarter -n "${JS_NAMESPACE}" jumpstarter -o jsonpath='{.spec.controller.grpc.endpoints[0].address}') + LOGIN_ENDPOINT_VALUE=$(kubectl get jumpstarter -n "${JS_NAMESPACE}" jumpstarter -o jsonpath='{.spec.login.endpoints[0].address}') + if [ -z "${ENDPOINT_VALUE}" ] || [ -z "${LOGIN_ENDPOINT_VALUE}" ]; then + log_error "Failed to resolve endpoints from Jumpstarter CR in namespace ${JS_NAMESPACE}" + exit 1 + fi + export ENDPOINT="${ENDPOINT_VALUE}" + export LOGIN_ENDPOINT="${LOGIN_ENDPOINT_VALUE}"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@e2e/setup-e2e.sh` around lines 282 - 292, The script currently reconstructs endpoints using BASEDOMAIN and hardcoded ports (export ENDPOINT and LOGIN_ENDPOINT); instead, read the actual endpoint addresses from the Jumpstarter CR and use those values if present. Change the kubectl jsonpath query (currently BASEDOMAIN=$(kubectl get jumpstarter ... .spec.baseDomain)) to fetch the CR fields that contain published endpoints (e.g., .status.endpoint, .status.endpoints.grpc, .status.endpoints.login or a corresponding .spec.* field used by the operator) and set ENDPOINT and LOGIN_ENDPOINT from those fields; keep a fallback to the existing BASEDOMAIN+port construction only if the CR does not contain explicit endpoint values. Ensure you update the references to BASEDOMAIN, ENDPOINT, and LOGIN_ENDPOINT accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@controller/Makefile`:
- Around line 159-162: The build-installer target is patching the wrong image
key — the kustomize edit uses "controller=${IMG}" but the kustomization defines
the image name as "quay.io/jumpstarter-dev/jumpstarter-operator", so the edit
silently fails; update the command in the build-installer recipe to set the
image using the exact name from kustomization (replace the "controller"
identifier with "quay.io/jumpstarter-dev/jumpstarter-operator" or use a variable
that matches that name) so $(KUSTOMIZE) edit set image <exact-image-name>=${IMG}
will correctly update the operator image before $(KUSTOMIZE) build writes
dist/install.yaml.
In
`@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.py`:
- Around line 111-115: The current code sets result_data["installed"] and
status/namespace as soon as any jumpstarter CRD exists (jumpstarter_crds), which
misclassifies operator-only installs; keep result_data["has_crds"]=True but
instead query for actual Jumpstarter resources (kind "Jumpstarter", plural e.g.
"jumpstarters" in group "jumpstarter.dev") before setting
result_data["installed"], result_data["status"], and result_data["namespace"];
if at least one Jumpstarter resource is found, set installed=True,
status="installed" and namespace to that resource's namespace, otherwise leave
installed False (or unset) and status as not-installed. Locate and update the
logic around the jumpstarter_crds check and result_data assignments (symbols:
jumpstarter_crds, result_data["has_crds"], result_data["installed"],
result_data["status"], result_data["namespace"]) to perform this additional API
call and conditional assignment.
---
Duplicate comments:
In `@e2e/setup-e2e.sh`:
- Around line 282-292: The script currently reconstructs endpoints using
BASEDOMAIN and hardcoded ports (export ENDPOINT and LOGIN_ENDPOINT); instead,
read the actual endpoint addresses from the Jumpstarter CR and use those values
if present. Change the kubectl jsonpath query (currently BASEDOMAIN=$(kubectl
get jumpstarter ... .spec.baseDomain)) to fetch the CR fields that contain
published endpoints (e.g., .status.endpoint, .status.endpoints.grpc,
.status.endpoints.login or a corresponding .spec.* field used by the operator)
and set ENDPOINT and LOGIN_ENDPOINT from those fields; keep a fallback to the
existing BASEDOMAIN+port construction only if the CR does not contain explicit
endpoint values. Ensure you update the references to BASEDOMAIN, ENDPOINT, and
LOGIN_ENDPOINT accordingly.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 600ec8b0-305e-4d82-9308-f6cbff5d5d0f
📒 Files selected for processing (80)
.cursor/rules/working-with-operator.mdc.github/workflows/build-images.yaml.github/workflows/controller-kind.yaml.github/workflows/e2e.yaml.github/workflows/lint.yamlMakefilecontroller/Makefilecontroller/deploy/helm/jumpstarter/.helmignorecontroller/deploy/helm/jumpstarter/Chart.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/Chart.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/model.pycontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/_endpoints.tplcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-deployment.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-ingress.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-route.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-ingress.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-route.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_clients.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporteraccesspolicies.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporters.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_leases.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-ingress.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-route.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/metrics_service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/monitor.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_editor_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_viewer_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_editor_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_viewer_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role_binding.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role_binding.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/service_account.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-ingress.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-route.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-service.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/secrets-job.yamlcontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.schema.jsoncontroller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.yamlcontroller/deploy/helm/jumpstarter/model.pycontroller/deploy/helm/jumpstarter/values.kind.yamlcontroller/deploy/helm/jumpstarter/values.schema.jsoncontroller/deploy/helm/jumpstarter/values.yamlcontroller/deploy/operator/README.mdcontroller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.gocontroller/hack/deploy_with_helm.shcontroller/hack/deploy_with_operator.shcontroller/hack/install_helm.shcontroller/hack/utilscontroller/internal/controller/suite_test.gocontroller/internal/service/suite_test.goe2e/compat/setup.she2e/setup-e2e.shpython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/__init__.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create_test.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.pypython/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install_test.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/__init__.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/__init__.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/common.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm_test.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations_test.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clusters.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/controller.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exceptions.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install.pypython/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install_test.py
💤 Files with no reviewable changes (62)
- .cursor/rules/working-with-operator.mdc
- controller/deploy/helm/jumpstarter/.helmignore
- controller/deploy/helm/jumpstarter/values.kind.yaml
- controller/deploy/operator/README.md
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/Chart.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/common.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/service_account.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_viewer_role.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role.yaml
- controller/hack/install_helm.sh
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role_binding.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/metrics_service.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/init.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role_binding.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clusters.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-service.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_editor_role.yaml
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/init.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/_endpoints.tpl
- controller/deploy/helm/jumpstarter/values.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/monitor.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-service.yaml
- .github/workflows/build-images.yaml
- controller/deploy/helm/jumpstarter/values.schema.json
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_viewer_role.yaml
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create_test.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_editor_role.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/init.py
- .github/workflows/lint.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_clients.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.schema.json
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/secrets-job.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-route.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-ingress.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm_test.py
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install_test.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-route.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-ingress.yaml
- controller/deploy/helm/jumpstarter/model.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-route.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yaml
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-ingress.yaml
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install_test.py
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_leases.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporters.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-ingress.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporteraccesspolicies.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-deployment.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/model.py
- controller/deploy/helm/jumpstarter/Chart.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-service.yaml
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-service.yaml
- controller/hack/deploy_with_helm.sh
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.py
- controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-route.yaml
✅ Files skipped from review due to trivial changes (4)
- controller/internal/service/suite_test.go
- controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exceptions.py
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/controller.py
🚧 Files skipped from review as they are similar to previous changes (8)
- .github/workflows/controller-kind.yaml
- controller/internal/controller/suite_test.go
- controller/hack/utils
- python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations_test.py
- Makefile
- .github/workflows/e2e.yaml
- python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.py
- e2e/compat/setup.sh
df4f7ab to
ff0a9d8
Compare
5b9e472 to
7ef1b71
Compare
Remove all Helm-related code, configuration, CI steps, and documentation from the repository. The project has transitioned to OLM operator-based deployment, making Helm artifacts dead code. Changes: - Delete controller/deploy/helm/ directory (43 files) - Delete controller/hack/deploy_with_helm.sh and install_helm.sh - Update controller Makefile to generate CRDs/RBAC directly to operator config paths and remove Helm targets - Update Go test CRD paths to use operator config/crd/bases - Remove jumpstarter_kubernetes install.py, cluster/helm.py and their test files - Remove jumpstarter_cli_admin install.py and its test file - Update all __init__.py exports to remove Helm symbols - Update cluster/operations.py to always use operator install - Update cluster/kubectl.py to use CRD-only detection - Update CLI create.py and get.py to remove Helm options - Remove publish-helm-charts job from build-images.yaml - Remove lint-helm job from lint.yaml - Remove Helm from controller-kind.yaml CI matrix - Update e2e scripts to use operator-only deployment - Update documentation and rule files Closes jumpstarter-dev#445 Generated-By: Forge/20260409_114748_239149_5e586097 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… of swallowing Flatten nested try/except in check_jumpstarter_installation so that RuntimeError from run_command (e.g. kubectl not found, permission errors) propagates to the outer handler that properly reports the error. Previously the inner `except RuntimeError: pass` silently swallowed the error, making it impossible for callers to distinguish "not installed" from "failed to check". Generated-By: Forge/20260409_114748_239149_5e586097 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rter_installation After removing the nested Helm detection logic, the function complexity is well under the C901 threshold. The suppression comment is no longer needed. Generated-By: Forge/20260409_114748_239149_5e586097 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Helm deployment method has been removed. Update the Makefile comment and help text to no longer advertise helm as a valid option. Generated-By: Forge/20260409_114748_239149_5e586097 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The chart_name/chartName field was only populated by the Helm detection code path which has been removed. The field was permanently None, making it dead structure in the API model. Generated-By: Forge/20260409_114748_239149_5e586097 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The comment said COMPAT_CONTROLLER_TAG defaults to v0.7.1 but the actual default on line 31 is v0.7.0. Generated-By: Forge/20260409_114748_239149_5e586097 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… Helm chart repo The Helm chart publishing CI job is being removed, so the function querying quay.io/jumpstarter-dev/helm/jumpstarter for version tags will return stale results. Switch to querying the operator image repository (jumpstarter-dev/jumpstarter-operator) which continues to receive new version tags with each release. Generated-By: Forge/20260409_114748_239149_5e586097 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…setup Instead of silently falling back to a default domain when the Jumpstarter CR cannot be found, fail immediately with an actionable error message. This prevents misleading test failures caused by connecting to the wrong endpoint. Generated-By: Forge/20260409_114748_239149_5e586097 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…r paths
All return paths from _check_cr_instances now consistently include the
"installed" key. The error path previously returned only {"error": ...},
relying on the caller's pre-initialized default. The tautological elif
is replaced with else. A CrInstanceResult TypedDict documents the
contract.
Generated-By: Forge/20260512_145216_1337542_9a078ae2
…type Replace the weakened Dict[str, Any] return annotation with a TypedDict that captures the known shape (name, cluster, server, user, namespace as str; current as bool). This strengthens the implicit contract for callers that access these keys by string literal. Generated-By: Forge/20260512_145216_1337542_9a078ae2
The function queries CRs across all namespaces (-A) but previously returned the caller-supplied namespace parameter, which was often None (yielding "unknown"). Now extracts the namespace from the first CR item's metadata, falling back to the parameter and then to "unknown". Generated-By: Forge/20260512_145216_1337542_9a078ae2
In get_cluster_info and list_clusters, json.JSONDecodeError is caught locally within inner try blocks or wrapped as KubeconfigError by get_kubectl_contexts, so it never reaches the outer except clauses. Remove the dead exception type to avoid misleading readers. Generated-By: Forge/20260512_145216_1337542_9a078ae2
The kind parameter was accepted but never referenced in the function body. Remove it from the function signature and update callers in the CLI admin package to stop passing it. Generated-By: Forge/20260512_145216_1337542_9a078ae2
The test_create_cluster_and_install_success test previously only asserted assert_called_once() without verifying the arguments passed to install_jumpstarter_operator. Add full keyword argument assertions matching the pattern used in test_create_cluster_and_install_calls_operator_installer. Generated-By: Forge/20260512_145216_1337542_9a078ae2
The comment claimed the default was 0.8.1 but the actual default on line 30 is 0.7.4. Update the comment to match the code. Generated-By: Forge/20260512_145216_1337542_9a078ae2
…t_kubectl_contexts Add "status": "no-cr-instance" to the empty-items return path in _check_cr_instances to distinguish from error states. Narrow the outer except clause in get_kubectl_contexts from broad Exception to (RuntimeError, JumpstarterKubernetesError) for consistency with get_cluster_info and list_clusters. Generated-By: Forge/20260512_145216_1337542_9a078ae2
Replace single CrInstanceResult TypedDict(total=False) with three distinct types (CrInstanceSuccess, CrInstanceError, CrInstanceNotFound) using Literal discriminants for static type narrowing. Replace dict.update() in check_jumpstarter_installation with explicit conditional field assignment. Make the no-instance return path explicit with an else clause. Add test for missing items key in JSON response. Generated-By: Forge/20260512_170224_1547662_b3e5aa08
Replace .get() calls with direct key access on CrInstanceResult Union to enable static type narrowing via the Literal discriminant. This ensures type checkers can verify field access is valid for each variant and that malformed dicts with installed=True but missing required fields raise KeyError rather than silently returning None. Add direct unit tests for _apply_cr_result covering all three CrInstanceResult variants plus malformed input rejection. Generated-By: Forge/20260512_170224_1547662_b3e5aa08
Break long function signature in delete_cluster_by_name to stay within 120-char line limit and remove unused json import from controller_test. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
d9a10b4 to
f71d16d
Compare
The inline waitForCompatExporter only ran kubectl wait, which can return before both conditions are fully propagated. The shared WaitForExporter also polls until exporterStatus reaches Available, preventing the race that caused flaky CI failures. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The kind parameter was removed from list_clusters and get_cluster_info but the --kind click option was left behind as dead code. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Annotate context_info in get_cluster_info and export KubectlContext from the cluster package so external consumers can reference the type. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Refactor build-installer, install, uninstall, and undeploy targets in the controller Makefile to delegate to the operator Makefile via $(MAKE) -C deploy/operator instead of directly referencing deploy/operator/config/* paths. This addresses the reviewer's concern that the controller Makefile should not directly manipulate operator config paths, and follows the existing delegation pattern already used by build-operator and manifests targets. Generated-By: Forge/20260512_204804_1774718_7f9a01ee
This reverts commit f2b8b8f.
Revert the path changes in build-installer, install, uninstall, and undeploy targets back to the controller's own kubebuilder config/ layout (config/manager, config/default, config/crd) instead of reaching into deploy/operator/config/. The manifests target still outputs to deploy/operator/config/ since helm paths are being removed and CRDs need to go to the operator. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@mangelajo lint-helm needs to be removed as a gate |
mangelajo
left a comment
There was a problem hiding this comment.
Some comments before merging, I am looking at CI now, brb :)
| @@ -1,17 +0,0 @@ | |||
| #!/usr/bin/env bash | |||
There was a problem hiding this comment.
nit: I think we still need helm for installing dex (not jumpstarter) in E2E, so may be it's relying on system installed helm. We can add this back if necessary, no worries...
|
|
||
| kubectl config set-context --current --namespace=jumpstarter-lab | ||
| # Install old controller using operator installer from the release assets | ||
| local INSTALLER_URL="https://github.com/jumpstarter-dev/jumpstarter/releases/download/${COMPAT_CONTROLLER_TAG}/operator-installer.yaml" |
| admin.add_command(install) | ||
| admin.add_command(uninstall) | ||
| admin.add_command(ip) |
There was a problem hiding this comment.
why are we removing those admin subverbs? I see on the subverbs we remove helm support/leave operator.
There was a problem hiding this comment.
ahhh there is create cluster !
There was a problem hiding this comment.
hmmm but that doesn't cover it all. Can we add a follow-up to re-instate the install admin command but using the operator?
Then we could even hook it on the E2E tests to install the operator in kind using that command.
Kirk added that to make it easy for people to install and tryout.
There was a problem hiding this comment.
but installing an operator is ... easy - operatorhub > jumpstarter > install - otherwise just apply a subscription
Co-authored-by: Miguel Angel Ajo Pelayo <majopela@redhat.com>
Co-authored-by: Miguel Angel Ajo Pelayo <majopela@redhat.com>
Summary
Closes #445
Test plan
make pkg-test-jumpstarter_cli_adminpassesmake pkg-test-jumpstarter_kubernetespasses🤖 Generated with Claude Code