Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
155 commits
Select commit Hold shift + click to select a range
7d42469
feat(check): re-gate cluster-validator per compute-plane targeting an…
rohithb-hub Aug 11, 2026
1ffb0c0
feat(check): detect stale NVCF namespaces and add control-plane valid…
rohithb-hub Aug 11, 2026
dfd490e
feat(check): validate registry credentials before install using gener…
rohithb-hub Aug 11, 2026
1deb005
build(check): update BUILD.bazel for new selfhosted sources and deps
rohithb-hub Aug 11, 2026
4d7c477
fix(check): address code-review findings in cluster-validator and pre…
rohithb-hub Aug 12, 2026
6fa7733
fix(check): replace parseRegistryHostPort with net.SplitHostPort and …
rohithb-hub Aug 12, 2026
b6eaac1
fix(check): sweep ClusterRole and ClusterRoleBinding after validator …
rohithb-hub Aug 12, 2026
5c4d2dc
fix(nvcf-cli): add DaemonSet create/delete RBAC for node-to-node probe
rohithb-hub Aug 17, 2026
df8ac49
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Aug 18, 2026
8193089
fix(nvcf-cli): address CodeRabbit review comments in validatortag and…
rohithb-hub Aug 19, 2026
c3c4a41
fix(nvcf-cli): restrict NGC token fallback to NGC registries and fix …
rohithb-hub Aug 19, 2026
de7999b
fix(nvcf-cli): response body close, case-insensitive params, empty sc…
rohithb-hub Aug 19, 2026
a52685f
fix(nvcf-cli): authorize realm host before forwarding credentials and…
rohithb-hub Aug 19, 2026
2218f34
fix(nvcf-cli): allow Docker Hub delegated auth realm in token exchange
rohithb-hub Aug 19, 2026
b8faf70
fix(nvcf-cli): stop preflight failing healthy clusters and destroying…
rohithb-hub Sep 15, 2026
ff14b5d
fix(nvcf-cli): scope preflight to the targeted role and stop cross-ro…
rohithb-hub Sep 15, 2026
7aba33b
fix(nvcf-cli): derive stale-namespace probe targets from the stack he…
rohithb-hub Sep 15, 2026
ce9f770
fix(nvcf-cli): make credential and RBAC outcomes consistent across pr…
rohithb-hub Sep 15, 2026
9d6fd31
fix(nvcf-cli): scope validator RBAC per role and quote operator-suppl…
rohithb-hub Sep 15, 2026
1bff24a
style(nvcf-cli): revert unrelated gofmt churn in task and self_hosted…
rohithb-hub Sep 15, 2026
0d35502
fix(nvcf-cli): scope the managed pull secret per validator role
rohithb-hub Sep 15, 2026
3fcd00d
fix(nvcf-cli): verify ownership before mutating or deleting any valid…
rohithb-hub Sep 15, 2026
5952b0f
fix(nvcf-cli): verify RBAC ownership before reuse and reject host-con…
rohithb-hub Sep 15, 2026
96d0865
fix(nvcf-cli): give validator RBAC an unguessable per-run name and re…
rohithb-hub Sep 15, 2026
cbd2c1f
fix(nvcf-cli): require the generated name before deleting any validat…
rohithb-hub Sep 15, 2026
ca3a28c
refactor(nvcf-cli): derive validator label selectors from the managed…
rohithb-hub Sep 15, 2026
46bac78
fix(nvcf-cli): run split-mode preflight only for the roles the flags …
rohithb-hub Sep 15, 2026
95e5648
fix(nvcf-cli): pin preflight remediation hints to the probed kube con…
rohithb-hub Sep 15, 2026
ef693a4
docs(nvcf-cli): document the cluster-validator check flags and regist…
rohithb-hub Sep 15, 2026
1d005b6
Merge remote-tracking branch 'origin/main' into feat/nvcf-cli-cluster…
rohithb-hub Sep 15, 2026
2630d3a
fix(nvcf-cli): pin deletes to the inspected object and always credent…
rohithb-hub Sep 15, 2026
a7475ac
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Sep 15, 2026
458b201
fix(nvcf-cli): probe the resolved kube context so stale-namespace hin…
rohithb-hub Sep 15, 2026
6c5e2d9
Merge remote-tracking branch 'origin/feat/nvcf-cli-cluster-validator'…
rohithb-hub Sep 15, 2026
8ac688a
Merge branch 'main' into feat/nvcf-cli-cluster-validator
vrv3814 Sep 16, 2026
49ef18a
Merge branch 'main' into feat/nvcf-cli-cluster-validator
vrv3814 Sep 16, 2026
13ddd00
fix(nvcf-cli): stop leaking the NGC key to mirrored registries and re…
rohithb-hub Sep 22, 2026
bb0d56b
fix(nvcf-cli): scope pull-secret adoption per role and stop the stale…
rohithb-hub Sep 22, 2026
e5ab3dd
fix(nvcf-cli): bound the validator Job and make the check command's t…
rohithb-hub Sep 22, 2026
937c88d
docs(nvcf-cli): give isBareRegistryHost and isNGCRegistry their own d…
rohithb-hub Sep 22, 2026
fe418dd
fix(nvcf-cli): scope the validator's pull secret and config to one run
rohithb-hub Sep 22, 2026
3531290
fix(nvcf-cli): preserve the validator Job under --no-cleanup like its…
rohithb-hub Sep 22, 2026
02d5ade
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Sep 28, 2026
6e32129
fix(nvcf-cli): scope validator cleanup to one run and reclaim every a…
rohithb-hub Sep 29, 2026
d642bef
fix(nvcf-cli): forward the validator's settings and probe the registr…
rohithb-hub Sep 29, 2026
af2c3c3
fix(nvcf-cli): count checks by one rule, scope stale namespaces and S…
rohithb-hub Sep 29, 2026
b375d4b
build(nvcf-cli): register the new validator tests and deps with Bazel
rohithb-hub Sep 29, 2026
ebccad8
Merge remote-tracking branch 'origin/feat/nvcf-cli-cluster-validator'…
rohithb-hub Sep 29, 2026
fbe7599
fix(nvcf-cli): report a validator image without role support as a war…
rohithb-hub Sep 29, 2026
7959067
docs(nvcf-cli): drop a comment reference to the removed prior-Job sweep
rohithb-hub Sep 29, 2026
178461e
fix(nvcf-cli): require positive evidence of a legacy validator, clean…
rohithb-hub Sep 29, 2026
047d62c
fix(nvcf-cli): trim the validator ClusterRole to the verbs its checks…
rohithb-hub Sep 29, 2026
8581a78
fix(nvcf-cli): keep the no-cleanup hint on RBAC failure, forward list…
rohithb-hub Sep 29, 2026
8807222
docs(nvcf-cli): document the validator registry set, probe image, loc…
rohithb-hub Sep 29, 2026
0d240a8
fix(nvcf-cli): fail check when the cluster validator cannot run, and …
rohithb-hub Sep 29, 2026
2672f1e
fix(nvcf-cli): bound the validator cleanup sweeps and end an interrup…
rohithb-hub Sep 29, 2026
bc370f0
fix(nvcf-cli): correct stale validator comments, use severity constan…
rohithb-hub Sep 30, 2026
ff98280
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Sep 30, 2026
37b3dbe
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Sep 30, 2026
cca7029
fix(nvcf-cli): pass the stack's NVCF Gateways and HA mode to the vali…
rohithb-hub Sep 30, 2026
3557d52
Merge remote-tracking branch 'origin/feat/nvcf-cli-cluster-validator'…
rohithb-hub Sep 30, 2026
698d4bf
fix(nvcf-cli): grade a spent check budget as a timeout, stop the vali…
rohithb-hub Sep 30, 2026
183583a
fix(nvcf-cli): skip an unresolvable validator tag, prefer the NGC key…
rohithb-hub Sep 30, 2026
ccd5908
fix(nvcf-cli): size the check budget from the validator's full run, r…
rohithb-hub Sep 30, 2026
828ce37
fix(nvcf-cli): count the deferred cleanup sweeps in the validator run…
rohithb-hub Sep 30, 2026
079eb0f
Merge branch 'main' into feat/nvcf-cli-cluster-validator
vrv3814 Oct 1, 2026
5408614
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Oct 1, 2026
e19b05b
fix(nvcf-cli): grant the validator reads on gatewayclasses and contro…
rohithb-hub Oct 1, 2026
aafc163
Merge remote-tracking branch 'origin/feat/nvcf-cli-cluster-validator'…
rohithb-hub Oct 1, 2026
f456c1e
fix(nvcf-cli): time out check only on checks the budget stopped, keep…
rohithb-hub Oct 2, 2026
915871a
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Oct 2, 2026
e780cae
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Oct 3, 2026
cbf80d8
fix(nvcf-cli): grade validator runs on the Job end state
rohithb-hub Oct 3, 2026
cfb0caa
test(nvcf-cli): make the check test harness hermetic
rohithb-hub Oct 3, 2026
6e095bb
fix(nvcf-cli): route probe images and validate tolerations up front
rohithb-hub Oct 3, 2026
87f9d88
fix(nvcf-cli): read stack values from the env file, type registry probes
rohithb-hub Oct 3, 2026
fd36d80
fix(nvcf-cli): delete only run-owned validator objects, scope role RBAC
rohithb-hub Oct 3, 2026
277e766
feat(nvcf-cli): forward NVCF_EXTERNAL_COMPONENTS to the validator
rohithb-hub Oct 3, 2026
8b7aa3c
fix(nvcf-cli): report every check as a graded row, fail closed
rohithb-hub Oct 3, 2026
cc985a1
fix(nvcf-cli): grade stale namespaces on evidence
rohithb-hub Oct 3, 2026
344c179
test(nvcf-cli): keep check tests off the developer kubeconfig
rohithb-hub Oct 3, 2026
1786e10
docs(nvcf-cli): align check help and skill docs with current behavior
rohithb-hub Oct 3, 2026
5f4ab20
fix(nvcf-cli): align validator RBAC and env, keep stuck rows visible
rohithb-hub Oct 3, 2026
00bdf25
fix(nvcf-cli): match the validator pod grace, security context and co…
rohithb-hub Oct 3, 2026
3a557b0
test(nvcf-cli): use placeholder registry hosts in test fixtures
rohithb-hub Oct 3, 2026
370eb3f
fix(nvcf-cli): give local and registry checks their own time share
rohithb-hub Oct 3, 2026
8c35d39
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Oct 4, 2026
8e6dadc
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Oct 5, 2026
6617204
Merge branch 'main' into feat/nvcf-cli-cluster-validator
vrv3814 Oct 5, 2026
0f525cb
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Oct 5, 2026
e1cea06
fix(nvcf-cli): grant the validator pods get and test its roles agains…
rohithb-hub Oct 5, 2026
3e337e0
fix(nvcf-cli): grant the control-plane validator replicasets list to …
rohithb-hub Oct 5, 2026
6237e80
fix(nvcf-cli): hold SIGPIPE from the first interrupt so a dead stderr…
rohithb-hub Oct 5, 2026
ddf173e
fix(nvcf-cli): leave credential-plugin time out of the first-call bou…
rohithb-hub Oct 5, 2026
21ba5d7
fix(nvcf-cli): call a cluster unreachable when its first API call fai…
rohithb-hub Oct 5, 2026
1ee2141
fix(nvcf-cli): send the NGC key when nvcr.io rejects the docker login…
rohithb-hub Oct 5, 2026
5e48408
fix(nvcf-cli): read registry credentials again on every --wait poll s…
rohithb-hub Oct 5, 2026
1d44b71
fix(nvcf-cli): keep the credential lookup out of tag discovery round-…
rohithb-hub Oct 5, 2026
311acc1
fix(nvcf-cli): send no token scope for a one-segment stack repository…
rohithb-hub Oct 5, 2026
94b0964
docs(nvcf-cli): bring the credential-order and post-install grading c…
rohithb-hub Oct 5, 2026
f882bdd
test(nvcf-cli): give the mirrored stack fixtures two-segment reposito…
rohithb-hub Oct 5, 2026
8843671
fix(nvcf-cli): word the rejected docker login note as advice to renew…
rohithb-hub Oct 5, 2026
f82c531
fix(nvcf-cli): poll again on nodes the inotify probe budget did not r…
rohithb-hub Oct 5, 2026
5693c88
fix(nvcf-cli): pass a succeeded validator Job whose transcript cannot…
rohithb-hub Oct 5, 2026
1a866a7
fix(nvcf-cli): keep a cut-short check at its worst severity, report c…
rohithb-hub Oct 5, 2026
125e41c
fix(nvcf-cli): read the stack environment up installs with for a plan…
rohithb-hub Oct 5, 2026
65ae895
fix(nvcf-cli): read stale-namespace gates from the stack and environm…
rohithb-hub Oct 5, 2026
ecf15d3
fix(nvcf-cli): measure how long a namespace has been deleting on the …
rohithb-hub Oct 5, 2026
b9517a5
fix(nvcf-cli): fail check on a validator config list entry that is no…
rohithb-hub Oct 5, 2026
9a9fd6b
fix(nvcf-cli): read the check env toggles as booleans so false and 0 …
rohithb-hub Oct 5, 2026
b7c9f77
fix(nvcf-cli): do not probe NVIDIA's hosted SIS from a base_http_url …
rohithb-hub Oct 5, 2026
3e06471
docs(nvcf-cli): add a compute plane with compute-plane register and i…
rohithb-hub Oct 5, 2026
e797591
test(nvcf-cli): stage the stacks as Bazel data so the stack-tie tests…
rohithb-hub Oct 5, 2026
2f487dc
fix(nvcf-cli): keep a cut-short critical registry row a warning after…
rohithb-hub Oct 5, 2026
42142e0
fix(nvcf-cli): keep SIGPIPE ignored after an interrupted check return…
rohithb-hub Oct 5, 2026
e35900e
fix(nvcf-cli): fail check on a validator config list written as a sin…
rohithb-hub Oct 5, 2026
454ce63
test(nvcf-cli): pin the rejected docker login note to advice to renew…
rohithb-hub Oct 5, 2026
4c2e407
test(nvcf-cli): say under bazel test that the helmfile render test ne…
rohithb-hub Oct 5, 2026
7bff2d3
docs(nvcf-cli): copy the exported control-plane profile from the path…
rohithb-hub Oct 5, 2026
0c29a65
fix(nvcf-cli): bound the round trips of the first cluster call inside…
rohithb-hub Oct 5, 2026
c41ac0f
fix(nvcf-cli): say a passed validator row with an unreadable transcri…
rohithb-hub Oct 5, 2026
e3fa4e7
docs(nvcf-cli): spell add-on with a hyphen in the troubleshooting table
rohithb-hub Oct 5, 2026
456276e
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Oct 5, 2026
4ce5cca
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Oct 6, 2026
1f4004e
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Oct 6, 2026
4220792
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Oct 6, 2026
30de03b
fix(nvcf-cli): leave the validator Job time past VALIDATOR_TIMEOUT fo…
rohithb-hub Oct 6, 2026
bf74f02
fix(nvcf-cli): settle the nvcr.io credential once per repository scop…
rohithb-hub Oct 7, 2026
c254c33
fix(nvcf-cli): before install, fail a critical registry row on a dock…
rohithb-hub Oct 7, 2026
d930295
fix(nvcf-cli): after install, fail a refused docker login, and call a…
rohithb-hub Oct 7, 2026
f55afba
fix(nvcf-cli): ignore SIGPIPE for the whole check run so a reader tha…
rohithb-hub Oct 7, 2026
69b618c
fix(nvcf-cli): accept yes, no, on and off in the check env toggles an…
rohithb-hub Oct 7, 2026
84c4fd1
fix(nvcf-cli): end check --wait on a warning-only row its share cut s…
rohithb-hub Oct 7, 2026
633b18f
test(nvcf-cli): grade the ignored-signal child on its final event, no…
rohithb-hub Oct 7, 2026
4013126
fix(nvcf-cli): retry a first cluster call that met a server error, an…
rohithb-hub Oct 7, 2026
cab5f54
fix(nvcf-cli): create the inotify probe pod again with small requests…
rohithb-hub Oct 7, 2026
eb9c032
fix(nvcf-cli): keep inotify results across --wait polls and mark only…
rohithb-hub Oct 7, 2026
4907ca6
fix(nvcf-cli): make compute-plane install read the --values file what…
rohithb-hub Oct 7, 2026
86e8b1c
docs(nvcf-cli): pass a per-context kubeconfig instead of switching th…
rohithb-hub Oct 7, 2026
725635d
test(nvcf-cli): report SKIP when the RBAC inventory copy could not be…
rohithb-hub Oct 7, 2026
7b26bb0
ci(nvcf-cli): run the root Bazel row when the self-managed or compute…
rohithb-hub Oct 7, 2026
244c09e
fix(nvcf-cli): keep a rejected docker login failing after install, an…
rohithb-hub Oct 7, 2026
ecdf06a
fix(nvcf-cli): send the NGC key first only before a local control-pla…
rohithb-hub Oct 7, 2026
76c3d0f
fix(nvcf-cli): end a node's inotify probe at once when its pod cannot…
rohithb-hub Oct 7, 2026
a9aa486
fix(nvcf-cli): make the retry of a first cluster call after a server …
rohithb-hub Oct 7, 2026
d13a037
fix(nvcf-cli): read each cluster's pull secrets once per poll for the…
rohithb-hub Oct 7, 2026
108face
docs(nvcf-cli): list every value the check env toggles accept
rohithb-hub Oct 7, 2026
0761b6e
fix(nvcf-cli): judge the docker login for the stack's chart scope bef…
rohithb-hub Oct 7, 2026
3eae4da
fix(nvcf-cli): give a chart source on another scope than the stack's …
rohithb-hub Oct 7, 2026
d5e2cae
fix(nvcf-cli): warn on the chart row when the docker login helm uses …
rohithb-hub Oct 7, 2026
c711f99
docs(nvcf-cli): ask for the control-plane context and env the compute…
rohithb-hub Oct 7, 2026
e90721a
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Oct 7, 2026
4f1d5b1
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Oct 7, 2026
4babf29
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Oct 7, 2026
aaab74e
Merge branch 'main' into feat/nvcf-cli-cluster-validator
rohithb-hub Oct 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .github/workflows/bazel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,10 @@ jobs:
# subtrees plus the shared Bazel scaffold). Java and stargate no longer
# ride the root row: discovered Java components and stargate have
# their own scoped rows, so src/libraries/ is narrowed to
# src/libraries/go/.
ROOT_GLOBS=(MODULE.bazel .bazelignore .bazelrc .bazelversion BUILD.bazel WORKSPACE WORKSPACE.bazel go.work go.work.bazel rules/ platforms/ tools/ ci/ src/clis/ src/libraries/go/ .github/bazel-root-test-quarantine.txt)
# src/libraries/go/. The two stacks are the data of //:nvcf-cli-stacks,
# which the nvcf-cli tests that pin the CLI to the stacks read, so a
# change to a stack runs those tests.
ROOT_GLOBS=(MODULE.bazel .bazelignore .bazelrc .bazelversion BUILD.bazel WORKSPACE WORKSPACE.bazel go.work go.work.bazel rules/ platforms/ tools/ ci/ src/clis/ src/libraries/go/ deploy/stacks/self-managed/ deploy/stacks/nvcf-compute-plane/ .github/bazel-root-test-quarantine.txt)

run_all=false
changed=""
Expand Down Expand Up @@ -255,7 +257,7 @@ jobs:
# subtrees a change actually touches (path prefix), plus the
# reverse-dependency edges below (shared Java config -> every Java row;
# a Java framework -> every Java service) and ROOT_GLOBS -> root row. A
# docs-only or helm-only change touches no subtree and runs nothing.
# docs-only or chart-only change touches no subtree and runs nothing.
# The full-matrix fallbacks stay in the case above (workflow_dispatch,
# an unreadable or rewritten diff, a new branch) so an untrustworthy
# changeset is never under-tested.
Expand Down Expand Up @@ -416,7 +418,7 @@ jobs:
hit=true
elif [ "$path" = "." ]; then
# Root is glob-gated on PRs and merges alike: it runs only when a
# ROOT_GLOB file changed (a docs- or helm-only change never triggers
# ROOT_GLOB file changed (a docs- or chart-only change never triggers
# it). When it does run on a main push it uploads (CACHE_UPLOAD),
# warming the cache; the rings do not evict, so a later root PR reads
# that warm closure.
Expand Down
20 changes: 20 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ filegroup(
visibility = ["//visibility:public"],
)

# The self-managed and compute-plane stacks, also outside gazelle, for the
# nvcf-cli tests that pin the CLI's view of the stacks to their source.
# ROOT_GLOBS in .github/workflows/bazel.yml lists the same directories, so a
# change to them runs those tests.
filegroup(
name = "nvcf-cli-stacks",
srcs = glob(
[
"deploy/stacks/nvcf-compute-plane/**",
"deploy/stacks/self-managed/**",
],
exclude = [
"deploy/stacks/*/out/**",
"deploy/stacks/*/testdata/**",
"deploy/stacks/*/tests/**",
],
),
visibility = ["//src/clis/nvcf-cli:__subpackages__"],
)

# Gazelle manages only the native Go subtrees listed in go.work.bazel.
# nv-boot-parent and Cloud Tasks are also owned by the root Bazel module, but
# their checked-in Java BUILD files are maintained manually and remain outside
Expand Down
39 changes: 26 additions & 13 deletions ai-tooling/user/skills/nvcf-self-managed-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,21 @@ KUBECONFIG=cp.yaml:gpu1.yaml nvcf-cli self-hosted up \
--compute-plane-context=admin@gpu1 \
--icms-url=https://icms.nvcf.example.com

# Add a new compute plane to an existing control plane (no kubectl access to CP needed;
# Add a new compute plane to an existing control plane, from the profile
# `self-hosted control-plane profile export` wrote to the path it printed,
# copied here as control-plane-profile.yaml (no kubectl access to CP needed;
# reaches the control plane via the public ICMS HTTPRoute):
nvcf-cli self-hosted add-compute-plane \
nvcf-cli self-hosted compute-plane register \
--control-plane-profile=control-plane-profile.yaml \
--cluster-name=ncp-local-2 \
--compute-plane-context=admin@gpu2 \
--kube-context=admin@gpu2 \
--icms-url=https://icms.nvcf.example.com \
--token=$ADMIN_JWT
--token=$ADMIN_JWT \
--output=ncp-local-2-register-values.yaml
nvcf-cli self-hosted compute-plane install \
--values=ncp-local-2-register-values.yaml \
--kube-context=admin@gpu2 \
--cluster-name=ncp-local-2

# Tear down (always plan-only first):
nvcf-cli self-hosted down --plan-only --cluster-name=ncp-local --json | jq
Expand All @@ -75,7 +83,7 @@ nvcf-cli self-hosted down --cluster-name=ncp-local
nvcf-cli self-hosted uninstall --no-apply --compute-plane --cluster-name=ncp-local | kubectl delete -f -
```

> **`up` vs `add-compute-plane`.** `up` always installs both planes — use it for the *first* install. `add-compute-plane` is the right subcommand any time the control plane is already running and you want to attach an Nth compute cluster.
> `up` vs `compute-plane register` and `install`. `up` always installs both planes; use it for the first install. To attach an Nth compute cluster to a running control plane, register it with `compute-plane register` and install it with `compute-plane install`.
>
> **`down` always with `--plan-only` first.** Show the user the `willUninstall.commands[]` array before running for real.

Expand Down Expand Up @@ -135,12 +143,12 @@ After `init`, the credentials live in `~/.nvcf-cli.state`, so later commands wor

| Subcommand | What it does | When to use |
|---|---|---|
| `nvcf-cli self-hosted check --pre [--local-only \| --control-plane-context=X \| --compute-plane-context=Y]` | Pre-flight: local-host tools + cluster-side prerequisites | Always run first on a new environment |
| `nvcf-cli self-hosted check --pre [--local-only \| --control-plane-context=X --compute-plane-context=Y]` | Pre-flight: local-host tools, registry credentials, and cluster-side prerequisites for both planes. Pass both context flags or neither | Always run first on a new environment |
| `nvcf-cli self-hosted install --control-plane \| kubectl apply -f -` | Render + apply the control plane | When you want manual control over apply (GitOps-friendly) |
| `nvcf-cli self-hosted install --compute-plane --cluster-name=X \| kubectl apply -f -` | Register cluster + render compute plane | Same — manual apply path |
| `nvcf-cli self-hosted up --cluster-name=X` | One-shot first install: pre-flight → control plane → register → compute plane | Standard install path (both planes from scratch) |
| `nvcf-cli self-hosted up --plan-only --cluster-name=X` | Dry-run: emit phase-by-phase plan + ETA without changing state | Agent / CI preview before commit |
| `nvcf-cli self-hosted add-compute-plane --cluster-name=X --compute-plane-context=Y --icms-url=… --token=$JWT` | Add a new compute plane to an *existing* control plane (no CP install) | Adding the 2nd, 3rd, … GPU cluster after the initial `up` |
| `nvcf-cli self-hosted compute-plane register --control-plane-profile=P --cluster-name=X --kube-context=Y --output=V`, then `nvcf-cli self-hosted compute-plane install --values=V --kube-context=Y` | Add a new compute plane to an existing control plane (no CP install) | Adding the 2nd, 3rd, ... GPU cluster after the initial `up` |
| `nvcf-cli self-hosted uninstall --control-plane` | Per-plane primitive: `helmfile destroy` on the control plane (refuses if compute planes still registered) | Final teardown after all compute planes are gone, or scripted pipelines |
| `nvcf-cli self-hosted uninstall --compute-plane --cluster-name=X` | Per-plane primitive: `helmfile destroy` on a compute plane (no ICMS unregister, no drain) | Just remove the helm releases without the ICMS-side cleanup |
| `nvcf-cli self-hosted uninstall --no-apply <plane>` | Render delete YAML via `helm get manifest` | GitOps; `\| kubectl delete -f -` or commit + Argo applies |
Expand Down Expand Up @@ -195,7 +203,7 @@ Session stickiness uses `x-multi-turn-session-id` for chat completions and Respo
For step-by-step playbooks, load the prompt that matches the user's intent:

- **Install from scratch.** [prompts/install-from-scratch.md](prompts/install-from-scratch.md) — k3d cluster → preflight → up → deploy a smoke function.
- **Add a new compute plane.** [prompts/add-compute-plane.md](prompts/add-compute-plane.md) — split-cluster `up` against an existing control plane.
- **Add a new compute plane.** [prompts/add-compute-plane.md](prompts/add-compute-plane.md): register and install a compute plane against an existing control plane.
- **Deploy and invoke a function.** [prompts/deploy-and-invoke.md](prompts/deploy-and-invoke.md) — create → deploy → API key → invoke, including the LLM create/invoke variant.
- **Diagnose a failed install.** [prompts/diagnose-failed-install.md](prompts/diagnose-failed-install.md) — `status --json` → identify failed component → kubectl describe → remediation.
- **Rotate JWKS.** [prompts/rotate-cluster-jwks.md](prompts/rotate-cluster-jwks.md) — when PSAT auth starts failing.
Expand Down Expand Up @@ -250,16 +258,21 @@ For step-by-step playbooks, load the prompt that matches the user's intent:

`nvcf-cli` subcommands that long-run (`up`, `status`, `check`) accept four output modes:

- **`--json`** — JSONL events on stderr; one event per line; stable schema (`schemaVersion: 2`). **Use this when running under an agent.** Parse line-by-line with `jq -c .` or `json.loads()`.
- **`--plain`** — Plain timestamped lines, RFC3339 UTC, `[NN/8]` phase prefix; grep-friendly. Default in non-TTY.
- **`--accessible`** — Plain output without spinners, with verbose state markers (`[completed]`, `[running]`, `[pending]`, `[failed]`). For screen readers and constrained terminals.
- **(no flag)** — Bubbletea TTY dashboard. Default in TTY ≥100×30. Don't use under an agent (cursor-up sequences are noisy).
- `--json`: JSONL events on stderr, one event per line, stable schema (`schemaVersion: 1`). Use this when running under an agent. Redirect stderr to the parser (`2>&1 >/dev/null`), keep only lines that start with `{`, and parse line-by-line with `jq -c .` or `json.loads()`.
- `--plain`: plain timestamped lines, RFC3339 UTC, `[NN/8]` phase prefix; grep-friendly. Default in non-TTY.
- `--accessible`: plain output without spinners, with verbose state markers (`[completed]`, `[running]`, `[pending]`, `[failed]`). For screen readers and constrained terminals.
- (no flag): Bubbletea TTY dashboard. Default in a TTY of at least 100x30. Don't use under an agent (cursor-up sequences are noisy).

Auto-detect picks the right mode for whatever stdout/stderr is. The CLI also honors `NO_COLOR` (any value → forces plain), `TERM=dumb` (forces plain), and `CI=truthy` (forces plain even on a fake TTY). When the terminal is smaller than 100×30, the bubbletea renderer falls back to a compact layout. Explicit `--json` is the right call for agent piping.

## On failure

`nvcf-cli` failures emit structured `phase_failed` events in JSON:
`check` never emits `phase_failed`. It ends with one `final` event: gate on
`success`, and treat a missing `final` event as a failure. See
[examples/ci-pipelines.md](examples/ci-pipelines.md) and
[reference/exit-codes.md](reference/exit-codes.md).

Other `nvcf-cli` failures emit structured `phase_failed` events in JSON:

```json
{"event":"phase_failed","phaseNum":4,"phase":"apply-cp",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,25 @@ deploy_nvcf:
variables:
KUBECONFIG: $KUBECONFIG_FILE
script:
- nvcf-cli self-hosted check --pre --json | jq -e '.event != "phase_failed"' || exit 2
- nvcf-cli self-hosted check --pre --json 2>&1 >/dev/null | grep '^{' | jq -se 'any(.[]; .event == "final" and .success)' || exit 2
- nvcf-cli self-hosted up --cluster-name=$CLUSTER_NAME --token=$NVCF_ADMIN_JWT --non-interactive --json
- nvcf-cli self-hosted status --json | jq -e '.verdict == "healthy"'
- nvcf-cli self-hosted status --json 2>&1 >/dev/null | grep '^{' | jq -se 'any(.[]; .verdict == "healthy")'
```

Notes:

- `--non-interactive --token=$JWT` is required in CI; never use interactive `init`.
- Always `--json` for machine-parsing.
- `--json` writes JSONL to stderr, not stdout, so redirect with `2>&1 >/dev/null` before a parser.
- `check` reports its verdict in one `final` event, with `success: false` when any check failed at error severity or the run timed out (exit `5`, `verdict: "timeout"`). Gate on that event: `check` never emits `phase_failed`, so a condition on it always passes. Requiring the `final` event also fails the step when the command dies before emitting it.
- Slurp with `jq -s` before testing a condition. Without it `jq -e` takes its exit status from the last event alone.
- stderr also carries plain-text notices, so filter to JSON lines. Do not add `--show-logs` here: it appends a non-JSON transcript to the same stream.
- The plain-text notice that says how to remove objects a validator run left in the cluster is filtered out with the rest. Read the same commands from the `final` event instead, for example `jq -r '.[] | select(.event == "final") | .cleanup[]?'` on the slurped stream.
- Final status check gates downstream stages on `verdict == "healthy"`.

## GitOps (Argo / Flux) pattern

CI doesn't `kubectl apply` — instead, render manifests, commit them, let the controller apply.
CI doesn't `kubectl apply`. Instead, render manifests, commit them, let the controller apply.

```yaml
render:
Expand Down Expand Up @@ -62,16 +67,20 @@ deploy_compute_planes:
- CLUSTER: ncp-eu-1
CONTEXT: admin@gpu-eu-1
script:
- nvcf-cli self-hosted up
- nvcf-cli self-hosted compute-plane register
--control-plane-profile=control-plane-profile.yaml
--cluster-name=$CLUSTER
--compute-plane-context=$CONTEXT
--kube-context=$CONTEXT
--icms-url=$ICMS_PUBLIC_URL
--token=$NVCF_ADMIN_JWT
--non-interactive
--json
--output=$CLUSTER-register-values.yaml
- nvcf-cli self-hosted compute-plane install
--values=$CLUSTER-register-values.yaml
--kube-context=$CONTEXT
--cluster-name=$CLUSTER
```

Each parallel job registers + installs one compute plane against the shared control plane. Failures are isolated.
Each parallel job registers + installs one compute plane against the shared control plane. Failures are isolated. The control-plane profile comes from `nvcf-cli self-hosted control-plane profile export`, run once against the control plane. It writes the profile to the stack's `out/` directory and prints that path; hand the file to each job as `control-plane-profile.yaml`, for example as an artifact.

## Plan-only preview in PRs

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,30 @@ The canonical multi-cluster topology. Each compute plane is registered separatel
KUBECONFIG=cp.yaml nvcf-cli self-hosted install --control-plane | kubectl apply -f -
nvcf-cli self-hosted check --control-plane --wait 5m

# 2. Register + install each compute plane:
# 2. Export the control-plane profile every compute plane registers from.
# It is written to the stack's out/ directory, and the command prints
# that path. Copy the file here:
KUBECONFIG=cp.yaml nvcf-cli self-hosted control-plane profile export --cluster-name=ncp-cp
cp <path it printed> control-plane-profile.yaml

# 3. Register + install each compute plane. Both commands name the GPU
# cluster's context with --kube-context:
for CTX in admin@gpu-east-1 admin@gpu-west-1 admin@gpu-eu-1; do
NAME=$(echo "$CTX" | cut -d@ -f2)
nvcf-cli self-hosted up \
nvcf-cli self-hosted compute-plane register \
--control-plane-profile=control-plane-profile.yaml \
--cluster-name=$NAME \
--compute-plane-context=$CTX \
--kube-context=$CTX \
--icms-url=https://icms.nvcf.example.com \
--token=$NVCF_ADMIN_JWT \
--non-interactive \
--json
--output=$NAME-register-values.yaml
nvcf-cli self-hosted compute-plane install \
--values=$NAME-register-values.yaml \
--kube-context=$CTX \
--cluster-name=$NAME
done

# 3. Verify all compute planes registered:
# 4. Verify all compute planes registered:
nvcf-cli cluster list-registered --nca-id=$NCA_ID --icms-url=$ICMS --json \
| jq '.clusters[] | {name: .clusterName, status, nvcaVersion}'
```
Expand All @@ -37,24 +48,45 @@ The operator has kubectl access to ONE compute plane only — the control plane
# service is reachable via api.nvcf.example.com — no kubectl access needed):
nvcf-cli init --api-url=https://api.nvcf.example.com

# Run pre-flight scoped to the compute plane only:
nvcf-cli self-hosted check --pre \
--compute-plane-context=admin@gpu1 \
# Run pre-flight scoped to the compute plane only. check takes both context
# flags or neither and has no --kubeconfig flag, so give it, through
# KUBECONFIG for this command only, a kubeconfig holding just the compute
# cluster's context. The current context of your kubeconfig stays as it was.
# --compute-plane checks the compute plane as installed, so a docker login
# with no access to the org of the compute-plane charts passes where
# NGC_API_KEY reaches it: treat a registry-credentials row that says the
# docker login has no access as blocking, since compute-plane install pulls
# its charts with that login. A docker login nvcr.io rejects fails either way.
# With a control-plane context, check --pre --control-plane checks the new
# compute plane as not yet installed instead; see prompts/add-compute-plane.md.
KC=$(mktemp)
kubectl config view --minify --flatten --context=admin@gpu1 > "$KC"
KUBECONFIG="$KC" nvcf-cli self-hosted check --compute-plane \
--icms-url=https://icms.nvcf.example.com \
--json

# Bring up just the compute plane:
nvcf-cli self-hosted up \
# Register and install just the compute plane, from the profile the
# control-plane operator exported with `self-hosted control-plane profile export`,
# saved here as control-plane-profile.yaml:
nvcf-cli self-hosted compute-plane register \
--control-plane-profile=control-plane-profile.yaml \
--cluster-name=my-compute-1 \
--compute-plane-context=admin@gpu1 \
--kube-context=admin@gpu1 \
--icms-url=https://icms.nvcf.example.com \
--token=$ADMIN_JWT \
--non-interactive

# Status (compute-only — operator can't see control-plane component health):
nvcf-cli self-hosted status \
--compute-plane-context=admin@gpu1 \
--output=my-compute-1-register-values.yaml
nvcf-cli self-hosted compute-plane install \
--values=my-compute-1-register-values.yaml \
--kube-context=admin@gpu1 \
--cluster-name=my-compute-1

# Status of admin@gpu1, from the same kubeconfig (compute-only: the operator
# can't see control-plane component health). Then remove the file, which
# holds the context's credentials:
KUBECONFIG="$KC" nvcf-cli self-hosted status \
--cluster-name=my-compute-1 \
--icms-url=https://icms.nvcf.example.com
rm -f "$KC"
```

## Functions targeting specific compute planes
Expand Down Expand Up @@ -84,13 +116,17 @@ The `clusters` array (using cluster names, not IDs) limits scheduling to those c
nvcf-cli cluster list-registered --nca-id=$NCA_ID --icms-url=$ICMS --json \
| jq -r '.clusters[].clusterName' > clusters.txt

# Status snapshot per compute plane (assuming each context name matches):
# Status snapshot per compute plane (assuming each context name matches).
# Each run reads a temporary kubeconfig holding only that cluster's context,
# so the loop leaves the current context of your kubeconfig alone:
while read NAME; do
echo "=== $NAME ==="
nvcf-cli self-hosted status \
--cluster-name=$NAME \
--compute-plane-context=admin@$NAME \
--json | jq -c '{cluster:.cluster, verdict:.verdict, reconcile:.reconcileAgeSec}'
KC=$(mktemp)
kubectl config view --minify --flatten --context="admin@$NAME" > "$KC" &&
KUBECONFIG="$KC" nvcf-cli self-hosted status \
--cluster-name=$NAME \
--json | jq -c '{cluster:.cluster, verdict:.verdict, reconcile:.reconcileAgeSec}'
rm -f "$KC"
done < clusters.txt
```

Expand Down
Loading
Loading