feature: prime cluster login and the k8s credential plugin - #808
feature: prime cluster login and the k8s credential plugin#808JannikSt wants to merge 4 commits into
Conversation
- `prime cluster login <cluster>` writes a kubeconfig with an exec block, one context per pool the researcher has been granted. No Kubernetes token is ever written to disk - `prime auth k8s-token` is the credential plugin kubectl invokes on every call. It writes only the ExecCredential to stdout, messages to stderr, and uses distinct exit codes so callers can tell a transient failure from a permanent one - Revoked access, expired platform auth, rate limits, an unreachable platform and an ambiguous pool each get their own exit code and message - Talks to the platform with httpx directly rather than the shared APIClient, which collapses status codes into one error type and would lose the contract
transfer-bulk-failures.jsonl is written by the images-transfer-bulk test and is not gitignored, so it got swept into the previous commit.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e0947ad575
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- the credential plugin now posts to /api/v1/clusters/{name}/kube-token;
Config.base_url strips the prefix, so without it every call 404'd. A test
pins the exact route string.
- prime --context X cluster login bakes --context X into the exec args, so
refreshes from kubectl (where PRIME_CONTEXT is unset) hit the same
platform the login did
|
Review findings addressed (e550d3b):
978 tests passing, ruff clean. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit e550d3b. Configure here.
Baking --context into the exec args regressed custom API URLs: with PRIME_CONTEXT=production, every kubectl refresh reloads the built-in production environment and forces base_url back to the public default, ignoring a URL set via 'prime config set-base-url'. The login-time resolved URL now rides in the exec block's env as PRIME_API_BASE_URL, which outranks context resolution in Config.base_url — so refreshes hit the same platform the login did, while --context still selects the matching API key. Tests cover the custom-base-url + production-context combination in both directions.
|
Pushed dbc59e4 fixing the custom-base-url regression from the --context change:
|

Targeting
mainbecause this repo does not use thedevelop-branch convention — it has nodevelopbranch and merges PRs straight intomain. (The platform-side PRs for this feature targetdevelopas usual.)Adds the researcher side of PrimeCluster node pools: a kubeconfig, and the credential plugin behind it.
prime cluster login <cluster>writes a kubeconfig with one context per pool the researcher has been granted, and anexecblock instead of a token. Nothing credential-shaped is ever written to diskprime auth k8s-tokenis the credential plugin kubectl invokes on every API call. It exchanges the platform API token for a short-lived ServiceAccount token scoped to the researcher's namespaceThat indirection is what makes revocation mean something: revoking a grant deletes the namespace and its ServiceAccount, so the next refresh fails and any token already issued expires within the hour.
The plugin has a stricter contract than the rest of the CLI, because kubectl is the caller rather than a human:
interactiveMode: Never; there may be no terminal at allIt talks to the platform with
httpxdirectly rather than the sharedAPIClient.APIClientcollapses every status into oneAPIError, and the entire failure contract here is a function of the status code.Two things worth flagging:
The kubeconfig needs the apiserver URL and CA, which the mint endpoint doesn't return, so this depends on a new
GET /api/v1/clusters/{name}/kubeconfig-infoendpoint added in the platform PR.prime cluster loginwill fail against a platform that predates it.A Typer app holding exactly one command promotes it to the group, which would have made
prime auth k8s-tokenfail whileprime authsilently ran the plugin — and that exact string is written into every kubeconfig we generate. Both groups now carry an explicit callback to prevent it, and the tests cover the wiring.Note
Medium Risk
New authentication path invoked on every kubectl call; mistakes in stdout/exit-code contract or URL pinning would break cluster access or send users to the wrong platform.
Overview
Adds researcher Kubernetes access for granted Prime clusters:
prime cluster loginfetches cluster metadata from the platform and writes a per-cluster kubeconfig under~/.prime/kube/with one context per pool, each using anexeccredential that callsprime auth k8s-token(no tokens on disk).prime auth k8s-tokenimplements the kubectl credential plugin contract: ExecCredential JSON only on stdout, errors on stderr, distinct exit codes for unreachable vs revoked vs rate-limited vs expired auth vs ambiguous pool, and directhttpxcalls (notAPIClient) so HTTP status drives behavior. Kubeconfig exec args/env pin--contextandPRIME_API_BASE_URLso refreshes from kubectl use the same platform and API key as login.Wires
clusterandauthinto the root CLI (with Typer group callbacks soprime auth k8s-tokenstays a real subcommand).logindepends onGET …/kubeconfig-infoon the platform; the plugin posts to…/kube-token.Tests cover kubeconfig shape, context/base-URL pinning, plugin success path, and failure exit codes.
Reviewed by Cursor Bugbot for commit dbc59e4. Bugbot is set up for automated code reviews on this repo. Configure here.