Skip to content

feat(helm-prereqs): automate DPF (DOCA Platform Framework) install in setup.sh#3578

Open
shayan1995 wants to merge 1 commit into
NVIDIA:mainfrom
shayan1995:feat/setup-dpf-install
Open

feat(helm-prereqs): automate DPF (DOCA Platform Framework) install in setup.sh#3578
shayan1995 wants to merge 1 commit into
NVIDIA:mainfrom
shayan1995:feat/setup-dpf-install

Conversation

@shayan1995

Copy link
Copy Markdown
Contributor

Related issues

Closes #2897 — docs: Document standalone NICo control plane setup with DPF provisioning.

Type of Change

  • Add - New feature or capability
  • Change - Changes in existing functionality
  • Fix - Bug fixes
  • Remove - Removed features or deprecated functionality
  • Internal - Internal changes (refactoring, tests, docs, etc.)

Breaking Changes

  • This PR contains breaking changes

DPF now installs by default, so existing setup.sh runs will fail preflight unless they either set the DPF env vars (NICO_DPF_DPU_INTERFACE, NICO_DPF_DPU_CLUSTER_VIP, NICO_DPF_BMC_ROOT_PASSWORD) or add --skip-dpf to keep the previous behavior.

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • No testing required (docs, internal refactor, etc.)

Clean teardown + full reinstall on a dev cluster (DPF default-on): all pods healthy, dpucluster: Ready=True, kamaji HA 2/2, [dpf] enabled = true.

Additional Notes

DPF v26.4.0 via setup.sh; --skip-dpf opts out. Known upstream (kamaji cold-start deadlock, BYO-ArgoCD, clone-unusable operator chart) and NICo-internal (BMC two-phase, SDK doesn't create its CRs, no config-checksum restart) items are worked around here and catalogued for separate issues — none block this PR.

@shayan1995 shayan1995 requested review from a team and polarweasel as code owners July 15, 2026 20:34
@copy-pr-bot

copy-pr-bot Bot commented Jul 15, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Summary by CodeRabbit

  • New Features
    • Enabled DPF as the default provisioning/enablement path in the setup workflow, with new DPF env vars, flags, and phases (including optional prereqs and MetalLB VIP support).
    • Added Nico API Helm-side RBAC support to manage DPF CRs when enabled via chart settings.
  • Documentation
    • Updated quick-start and DPF/Helm prerequisites docs with the new default flow, required configuration, and DPF disablement guidance.
  • Bug Fixes
    • Improved DPF preflight validation, health checks, idempotent reruns, and cleanup for partial/failed installs.
  • Chores
    • Added Helm packaging ignore rules and updated .gitignore for DPF-related artifacts.

Walkthrough

Adds DPF as the default DPU provisioning stack, including prerequisite Helm releases, operator resources, setup orchestration, two-phase NICo Core enablement, RBAC, health checks, teardown handling, and configuration and operational documentation.

Changes

DPF provisioning integration

Layer / File(s) Summary
DPF foundation resources
helm-prereqs/helmfile.yaml, helm-prereqs/operators/..., helm/charts/nico-api/..., helm-prereqs/values/nico-core.yaml
Adds DPF prerequisite releases, operator configuration, DPU cluster and VIP resources, certificate approval RBAC, packaging exclusions, and conditional NICo API permissions.
Setup gating and installation
helm-prereqs/preflight.sh, helm-prereqs/setup.sh, docs/getting-started/quick-start.md
Makes DPF installation default, adds --skip-dpf and --install-dpf, validates required settings, installs the DPF stack, and creates its custom resources.
Core enablement and lifecycle
helm-prereqs/setup.sh, helm-prereqs/health-check.sh, helm-prereqs/clean.sh
Adds two-phase Core enablement with BMC credential injection, idempotent reruns, DPF readiness checks, and ordered teardown of DPF resources.
DPF workflow documentation
helm-prereqs/README.md, docs/manuals/dpf.md, book/src/configuration/..., crates/dpf/README.md
Documents default DPF setup, configuration variables, host behavior, repositories and images, CLI operations, setup phases, and the renamed API harness binary.

Estimated code review effort: 5 (Critical) | ~90 minutes

Sequence Diagram(s)

sequenceDiagram
  participant setup.sh
  participant preflight.sh
  participant helmfile
  participant dpf-operator
  participant carbide-api
  participant nico-api
  setup.sh->>preflight.sh: Validate DPF flags, tools, variables, and Core values
  setup.sh->>helmfile: Install DPF prerequisite releases
  setup.sh->>dpf-operator: Install operator and apply DPF resources
  setup.sh->>carbide-api: Set BMC credential and enable DPF
  setup.sh->>nico-api: Restart service for DPF SDK initialization
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed It clearly summarizes the main change: automating DPF install in setup.sh.
Description check ✅ Passed The description is directly about the DPF default-on setup.sh integration and its opt-out path.
Linked Issues check ✅ Passed The PR covers the standalone DPF docs and the optional setup.sh integration requested by the linked issue.
Out of Scope Changes check ✅ Passed The changes stay focused on DPF provisioning, docs, cleanup, and related Helm prerequisites.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@shayan1995 shayan1995 requested a review from abvarshney-nv July 15, 2026 20:34
@shayan1995 shayan1995 force-pushed the feat/setup-dpf-install branch from b4958b8 to c31fb7a Compare July 15, 2026 20:42

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 12

🧹 Nitpick comments (1)
helm-prereqs/operators/dpf/dpu-cluster-vip-service.yaml.tmpl (1)

32-42: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Prefer EndpointSlice for the selector-less Service.

v1 Endpoints is deprecated in Kubernetes 1.33+, and this relies on control-plane mirroring of a manually authored Endpoints object. Create a discovery.k8s.io/v1 EndpointSlice directly, labeled for dpu-cluster-vip-loadbalancer, and verify the repository’s minimum Kubernetes version. (kubernetes.io)

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

In `@helm-prereqs/operators/dpf/dpu-cluster-vip-service.yaml.tmpl` around lines 32
- 42, Replace the manually authored v1 Endpoints resource with a
discovery.k8s.io/v1 EndpointSlice for dpu-cluster-vip-loadbalancer, preserving
the dummy VIP address and port while labeling the slice for the selector-less
Service. Verify and honor the repository’s minimum Kubernetes version before
applying this API change.

Sources: Path instructions, MCP tools

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

Inline comments:
In `@docs/manuals/dpf.md`:
- Around line 75-78: Update the explanatory text in the DPF SDK initialization
documentation to consistently hyphenate “site-wide,” including the phrase
“site-wide BMC root credentials.”
- Around line 1027-1040: Add an explicit DPU-service mapping table at both
docs/manuals/dpf.md lines 1027-1040 and helm-prereqs/README.md lines 354-364,
mapping each configured service name (dpu_agent, dhcp_server, fmds, and otel) to
its corresponding forge-* or carbide-* image/artifact. Keep the existing build
and publish instructions, and ensure both tables use consistent mappings.

In `@helm-prereqs/clean.sh`:
- Around line 97-128: Scope the teardown commands for tenantcontrolplane,
datastores.kamaji.clastix.io, applications.argoproj.io, and
appprojects.argoproj.io to resources owned by this installation using exact
names or installation labels instead of --all -A. Update the finalizer loop over
_kind and _res to discover only owned resources and patch each resource in its
actual namespace rather than hard-coding dpf-operator-system. Apply the same
ownership restriction to the broad RBAC cleanup.

In `@helm-prereqs/health-check.sh`:
- Around line 249-253: Update the DPF health-check logic around DPF_NS discovery
and the DPU query to distinguish an explicit --skip-dpf opt-out from an
unhealthy or partial installation. Detect any existing DPF namespace or release
independently, and treat failures from kubectl observation commands as explicit
errors rather than converting them to an empty namespace or zero DPUs; reserve
the skip message only for a confirmed opt-out.

In `@helm-prereqs/helmfile.yaml`:
- Around line 156-165: Update both preSync CRD-apply hooks for Kamaji to replace
the silent “|| true” fallback with a clear failure message written to stderr,
including the chart or CRD context. Preserve the existing command pipeline and
allow the hook to continue as currently intended after reporting the failure.

In `@helm-prereqs/operators/dpf/dpucluster.yaml.tmpl`:
- Around line 30-34: Update the DPUCluster node-selection configuration around
nodeSelector so control-plane nodes are matched regardless of whether
node-role.kubernetes.io/control-plane has an empty or "true" value. Prefer an
Exists-based node affinity rule if the CRD supports affinity; otherwise expose
the selector value as a configurable template setting instead of hardcoding an
empty string.

In `@helm-prereqs/README.md`:
- Around line 315-320: Update the DPF documentation to match the per-service
defaults defined by dpf_services.rs: dts uses public DOCA NGC, doca_hbn uses
public DOCA images, and dpu_agent, dhcp_server, fmds, and otelcol use the
private carbide-dev Helm/image registries with nico-pull-secret. Apply this
matrix at helm-prereqs/README.md lines 315-320 and 368-376, and
docs/manuals/dpf.md lines 1027-1031 and 1051-1055, replacing blanket public-NGC
wording without changing unrelated setup guidance.

In `@helm-prereqs/setup.sh`:
- Around line 548-568: Track whether _kamaji_patch_failurepolicy Ignore
successfully relaxed Kamaji’s webhook policy, and add EXIT cleanup that restores
Fail whenever that state remains active, including errexit paths before the
explicit restoration. Clear the tracked state after restoring Fail so cleanup is
idempotent, while preserving the existing successful setup flow.
- Around line 587-613: Update the secret-generation commands, including
_dpf_argo_repo_secret and the corresponding BMC-password handling around the
other affected block, so credentials never appear in kubectl process arguments.
Generate manifests using stdin or permission-restricted temporary files, then
apply them through kubectl while preserving the existing secret names,
namespaces, labels, and values.
- Around line 665-670: Update the NICO_DPF_SRC_DIR cleanup logic in the
surrounding setup flow to refuse deletion of any existing path that is not an
expected Git clone, including arbitrary system or repository directories.
Validate the configured path and Git-repository state before rm -rf, and exit
with the existing safety error for invalid or non-Git directories; preserve
cleanup only for the intended clone directory.
- Around line 817-883: Update the BMC-root Job manifest before its template to
set activeDeadlineSeconds to the polling timeout, and in the failure path after
polling explicitly delete the Job and wait until it is gone before deleting
dpf-bmc-root-pw and dpf-admincli-cert or returning failure. Preserve the
existing success path and cleanup behavior.

In `@helm/charts/nico-api/values.yaml`:
- Around line 224-226: Remove the configurable dpf.operatorNamespace override
from the values configuration and keep the DPF namespace fixed consistently with
the prerequisite manifests at dpf-operator-system, ensuring NICo API RBAC
remains aligned with the operator and CR namespace.

---

Nitpick comments:
In `@helm-prereqs/operators/dpf/dpu-cluster-vip-service.yaml.tmpl`:
- Around line 32-42: Replace the manually authored v1 Endpoints resource with a
discovery.k8s.io/v1 EndpointSlice for dpu-cluster-vip-loadbalancer, preserving
the dummy VIP address and port while labeling the slice for the selector-less
Service. Verify and honor the repository’s minimum Kubernetes version before
applying this API change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: cc57ca8a-7ba9-425c-bf15-52437b2649b0

📥 Commits

Reviewing files that changed from the base of the PR and between 2d274e6 and b4958b8.

📒 Files selected for processing (23)
  • .gitignore
  • book/src/configuration/configurability.md
  • crates/dpf/README.md
  • docs/getting-started/quick-start.md
  • docs/manuals/dpf.md
  • helm-prereqs/.helmignore
  • helm-prereqs/README.md
  • helm-prereqs/clean.sh
  • helm-prereqs/health-check.sh
  • helm-prereqs/helmfile.yaml
  • helm-prereqs/operators/dpf/cert-manager-policy.yaml
  • helm-prereqs/operators/dpf/dpfoperatorconfig.yaml.tmpl
  • helm-prereqs/operators/dpf/dpu-cluster-vip-service.yaml.tmpl
  • helm-prereqs/operators/dpf/dpucluster.yaml.tmpl
  • helm-prereqs/operators/values/argo-cd.yaml
  • helm-prereqs/operators/values/kamaji.yaml
  • helm-prereqs/operators/values/maintenance-operator.yaml
  • helm-prereqs/operators/values/node-feature-discovery.yaml
  • helm-prereqs/preflight.sh
  • helm-prereqs/setup.sh
  • helm-prereqs/values/nico-core.yaml
  • helm/charts/nico-api/templates/dpf-rbac.yaml
  • helm/charts/nico-api/values.yaml

Comment thread docs/manuals/dpf.md
Comment on lines +75 to +78
carbide-api's DPF SDK init **hard-requires** the site-wide BMC root credential
(the shared BMC password DPF uses to reach the DPUs' host BMCs over Redfish). If
it is not set, carbide-api fails to start with
`Failed to initialize DPF SDK: ... Site wide BMC root credentials not set`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Hyphenate “site-wide”.

Use “site-wide BMC root credentials” in the explanatory text.

As per path instructions, documentation must be grammatically correct.

🧰 Tools
🪛 LanguageTool

[grammar] ~77-~77: Use a hyphen to join words.
Context: ...ot set, carbide-api fails to start with Failed to initialize DPF SDK: ... Site wide BMC root credentials not set. That...

(QB_NEW_EN_HYPHEN)

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

In `@docs/manuals/dpf.md` around lines 75 - 78, Update the explanatory text in the
DPF SDK initialization documentation to consistently hyphenate “site-wide,”
including the phrase “site-wide BMC root credentials.”

Sources: Path instructions, Linters/SAST tools

Comment thread docs/manuals/dpf.md
Comment thread helm-prereqs/clean.sh Outdated
Comment on lines +97 to +128
kubectl delete tenantcontrolplane --all -A --timeout=180s 2>/dev/null || true
# Kamaji `default` DataStore: carries helm.sh/resource-policy:keep (so
# helmfile destroy won't remove it) and a kamaji finalizer. Delete it here,
# while the kamaji controller is still alive to finalize it — otherwise its
# finalizer blocks the datastores CRD deletion and namespace termination.
kubectl delete datastores.kamaji.clastix.io --all -A \
--timeout=120s 2>/dev/null || true
# Argo CD Applications carry resources-finalizer.argocd.argoproj.io, which
# cascades a delete onto the (now-gone) DPU cluster and cannot complete on a
# DPU-less / VIP-unroutable cluster. Delete best-effort; stragglers get their
# finalizers stripped below before argo-cd itself is destroyed.
kubectl delete applications.argoproj.io --all -A \
--timeout=60s 2>/dev/null || true

# Best-effort finalizer strip for anything stuck after the bounded waits.
# Cover every DPF CR kind here — plus the kamaji DataStore and the Argo CD
# Applications/AppProjects — because `kubectl delete crd` (step 2) blocks
# until all instances finalize, so any kind left finalizer-stuck would hang
# the whole teardown. Applications must be stripped before argo-cd is
# destroyed (below), or nothing can ever clear their cascade finalizer.
for _kind in dpudeployments dpuservices dpuservicechains dpuserviceinterfaces \
dpuservicetemplates dpuserviceconfigurations dpuservicenads \
dpus dpudevices dpunodes dpunodemaintenances dpusets \
bfbs bluefieldsoftwares dpuflavors \
dpfoperatorconfigs dpuclusters tenantcontrolplanes \
datastores.kamaji.clastix.io \
applications.argoproj.io appprojects.argoproj.io; do
for _res in $(kubectl get "${_kind}" -A -o name 2>/dev/null); do
echo "WARNING: force-removing finalizers on stuck ${_res}"
kubectl patch "${_res}" -n dpf-operator-system --type merge \
-p '{"metadata":{"finalizers":[]}}' 2>/dev/null || true
done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🔴 Critical | 🏗️ Heavy lift

Scope teardown to resources owned by this installation.

The --all -A operations can delete unrelated Kamaji tenants and Argo CD Applications, including cascading deletion of their workloads. The broad RBAC name match has the same cross-installation risk. Additionally, the finalizer loop discovers resources cluster-wide but patches all of them in dpf-operator-system, so out-of-namespace results are not actually repaired.

Use exact resource names, installation labels, or namespace-aware iteration rather than cluster-wide deletion.

Also applies to: 234-236

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

In `@helm-prereqs/clean.sh` around lines 97 - 128, Scope the teardown commands for
tenantcontrolplane, datastores.kamaji.clastix.io, applications.argoproj.io, and
appprojects.argoproj.io to resources owned by this installation using exact
names or installation labels instead of --all -A. Update the finalizer loop over
_kind and _res to discover only owned resources and patch each resource in its
actual namespace rather than hard-coding dpf-operator-system. Apply the same
ownership restriction to the broad RBAC cleanup.

Comment thread helm-prereqs/health-check.sh
Comment thread helm-prereqs/helmfile.yaml Outdated
Comment thread helm-prereqs/setup.sh
Comment thread helm-prereqs/setup.sh Outdated
Comment thread helm-prereqs/setup.sh Outdated
Comment thread helm-prereqs/setup.sh
Comment thread helm/charts/nico-api/values.yaml
@shayan1995 shayan1995 force-pushed the feat/setup-dpf-install branch from c31fb7a to f364b80 Compare July 15, 2026 20:48
@shayan1995

Copy link
Copy Markdown
Contributor Author

Thanks @coderabbitai — triaged all 12 comments against the current code. Summary of what was addressed (commit 301b8261c) vs. skipped:

Fixed (9):

  • setup.sh — secrets in kubectl argv (Major/Security): NGC keys + BMC password no longer passed as --docker-password/--from-literal; fed off-argv via a builtin printf + process substitution (docker-registry secrets built as dockerconfigjson). Verified the rendered secrets are byte-identical to before.
  • setup.sh — Kamaji webhook left fail-open (Major): track the relaxed state and restore failurePolicy: Fail from the EXIT trap, so an abort between relax→restore (or a re-run that skips the block) can't leave vdatastore.kb.io on Ignore.
  • setup.sh — BMC-root Job (Major): added activeDeadlineSeconds: 180 and delete+wait the Job on the failure path before removing its Secrets, so no pod lingers holding the password.
  • setup.shrm -rf $NICO_DPF_SRC_DIR (Critical): now refuses and exits on any existing non-Git path instead of deleting it.
  • clean.sh — finalizer strip (Critical, the one real sub-claim): the loop discovered resources -A but patched with a hard-coded -n dpf-operator-system; now namespace-aware (cluster-scoped resources patched without -n).
  • helmfile.yaml — preSync CRD hooks (Minor): || true → a stderr WARNING, preserving continue-on-failure but surfacing real failures.
  • health-check.sh (Major): a lingering dpf-operator-system namespace with no operator now fails (partial install) instead of being reported as a --skip-dpf opt-out.
  • README.md + docs/manuals/dpf.md (Major/feat: Slack Notification when Release new version #7): the two residual "public NGC defaults" sentences now give the per-service public-vs-private matrix.
  • values.yaml (For review/fix build on gha #12): documented that dpf.operatorNamespace must match where the DPF stack runs (footgun note).

Skipped as false positives (3):

  • dpf.md:78 hyphenate "site-wide": that string is a verbatim quote of carbide-api's runtime error (crates/machine-controller/src/dpf.rs); editing it would desync the doc from real output. The prose already hyphenates it.
  • clean.sh:128 --all -A scope: by design — clean.sh is a full teardown of a single-tenant cluster it owns.
  • dpucluster.yaml.tmpl:34 control-plane selector: node-role.kubernetes.io/control-plane: "" is the canonical kubeadm value (already documented in-file); the keepalived block exposes only a nodeSelector, not affinity.

Also not changed (optional polish): the dpf.md:1040 naming-scheme mapping table — the mapping is already present in parallel order in that appendix section.

@shayan1995 shayan1995 force-pushed the feat/setup-dpf-install branch from f364b80 to 301b826 Compare July 15, 2026 21:15
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
cd /tmp
gh pr view 3578 --repo NVIDIA/infra-controller --json commits --jq '.commits[-5:] | .[].oid' 2>&1 || true
git log --oneline -10 2>&1 | head -20
git show 301b8261c --stat 2>&1 | head -50

Length of output: 523


🏁 Script executed:

#!/bin/bash
set -e
gh repo clone NVIDIA/infra-controller /tmp/repo -- --quiet 2>&1 | tail -5
cd /tmp/repo
git fetch origin 301b8261c8e172fc3060c276362d438c47e0b1c3 --depth=2 2>&1 | tail -20
git show 301b8261c8e172fc3060c276362d438c47e0b1c3 --stat 2>&1 | head -60

Length of output: 4083


🏁 Script executed:

#!/bin/bash
cd /tmp/repo
git checkout 301b8261c8e172fc3060c276362d438c47e0b1c3 -- helm-prereqs/setup.sh helm-prereqs/clean.sh helm-prereqs/helmfile.yaml helm-prereqs/health-check.sh 2>&1

echo "=== secrets off-argv ==="
grep -n "docker-password\|from-literal\|dockerconfigjson\|process substitution\|printf.*|" helm-prereqs/setup.sh | head -40

echo "=== trap / failurePolicy ==="
grep -n "trap\|failurePolicy" helm-prereqs/setup.sh | head -40

echo "=== activeDeadlineSeconds / Job delete wait ==="
grep -n "activeDeadlineSeconds\|kubectl delete job\|wait.*job" helm-prereqs/setup.sh -i | head -40

echo "=== rm -rf NICO_DPF_SRC_DIR ==="
grep -n "NICO_DPF_SRC_DIR" helm-prereqs/setup.sh -i | head -40

echo "=== clean.sh namespace-aware patch ==="
grep -n "kubectl patch\|dpf-operator-system\| -A \|finalize" helm-prereqs/clean.sh | head -60

echo "=== helmfile preSync WARNING ==="
grep -n "preSync\|WARNING\|true$" helm-prereqs/helmfile.yaml | head -40

echo "=== health-check dpf-operator-system ==="
grep -n "dpf-operator-system\|skip-dpf\|fail" helm-prereqs/health-check.sh | head -40

Length of output: 12198


🏁 Script executed:

#!/bin/bash
cd /tmp/repo
sed -n '900,940p' helm-prereqs/setup.sh

Length of output: 2329


@shayan1995 Thanks for the detailed triage — I pulled commit 301b8261c and independently verified each of the nine fixes against the actual diff:

  • Secrets off-argv (Lines 599–657 of helm-prereqs/setup.sh): confirmed the NGC token/BMC password are now piped via printf + process substitution into --from-file=.dockerconfigjson=<(...), no plaintext in kubectl argv or ps.
  • Kamaji webhook fail-open: confirmed trap '_on_failure' EXIT (Line 264) with the failurePolicy relax/restore bracketing (Lines 538–575) so the trap restores Fail on any abort path.
  • BMC-root Job hardening: activeDeadlineSeconds: 180 (Line 843) plus kubectl delete job ... --wait=true on the failure branch (Lines 903–906) before the Secrets are removed.
  • NICO_DPF_SRC_DIR guard: confirmed the refusal logic (Lines 683–696) — it now errors out on any pre-existing non-Git path instead of rm -rf.
  • clean.sh namespace-aware finalizer strip: confirmed the loop now conditionally appends -n "${_ns}" only for namespaced kinds (Lines 116–141), leaving cluster-scoped resources unnamespaced.
  • helmfile.yaml preSync hooks: confirmed both kamaji and maintenance-operator hooks now emit echo "WARNING: CRD apply for ... failed; continuing" >&2 instead of a silent || true.
  • health-check.sh: confirmed the elif kc get namespace dpf-operator-system branch now fails a partial install rather than reporting it as --skip-dpf opt-out (Lines 292–297).

Everything checks out as described — nice work closing these out cleanly, especially the Kamaji trap and the finalizer-strip namespace bug, which were the two I'd have flagged as highest-risk if left unaddressed.

On the three skipped items, your reasoning holds up:

  • The dpf.md:78 string is indeed a verbatim runtime error quote — editing it would desync docs from actual output, so leaving it is correct.
  • clean.sh's --all -A scope is consistent with its documented single-tenant full-teardown design.
  • The kubeadm node-role.kubernetes.io/control-plane: "" selector is the canonical label; no change needed there.

This is a solid, well-scoped remediation pass. Marking the addressed comments as resolved.

[resolve]


✏️ Learnings added
Learnt from: shayan1995
URL: https://github.com/NVIDIA/infra-controller/pull/3578

Timestamp: 2026-07-15T21:17:19.816Z
Learning: In NVIDIA/infra-controller `helm-prereqs/setup.sh`, secrets (NGC API keys, BMC root password) that must not appear in `kubectl` argv/process listings are fed off-argv via `printf '%s' ... | base64` combined with process substitution (`--from-file=.dockerconfigjson=<(printf ...)`), building `kubernetes.io/dockerconfigjson` secrets rather than using `--docker-password`/`--from-literal` directly on the command line.

Learnt from: shayan1995
URL: https://github.com/NVIDIA/infra-controller/pull/3578

Timestamp: 2026-07-15T21:17:19.816Z
Learning: In NVIDIA/infra-controller `helm-prereqs/setup.sh`, the Kamaji cold-start webhook deadlock workaround temporarily relaxes the `vdatastore.kb.io` webhook's `failurePolicy` from `Fail` to `Ignore`; the restoration back to `Fail` is guaranteed via the script's `EXIT` trap (`_on_failure`), not just inline code, so any abort mid-sequence or a skipped re-run still restores fail-closed behavior.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

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

Inline comments:
In `@docs/getting-started/quick-start.md`:
- Around line 92-96: Update the DPF provisioning examples in the quick-start
instructions to use shell-valid quoted placeholder values for
NICO_DPF_DPU_INTERFACE and NICO_DPF_DPU_CLUSTER_VIP, and replace the password
export with a silent read prompt that assigns NICO_DPF_BMC_ROOT_PASSWORD without
exposing it in shell history.

In `@docs/manuals/dpf.md`:
- Around line 373-383: Update both manual dpf-operator Helm commands in the
documentation to remove the unconditional
imagePullSecrets[0].name=dpf-pull-secret setting. Add concise guidance that
imagePullSecrets should be supplied only when using a private registry or
mirror, while keeping the anonymous public-image workflow as the default.

In `@helm-prereqs/setup.sh`:
- Around line 1023-1025: Update the idempotent rerun branches guarded by
_dpf_already_on to apply the supplied NICO_DPF_BMC_ROOT_PASSWORD instead of
skipping BMC credential handling. Ensure both occurrences reconcile the current
password while preserving the existing skip behavior for the DPF-off down-cycle.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 396af73f-a07b-4c78-a3c2-083512530764

📥 Commits

Reviewing files that changed from the base of the PR and between f364b80 and 301b826.

📒 Files selected for processing (23)
  • .gitignore
  • book/src/configuration/configurability.md
  • crates/dpf/README.md
  • docs/getting-started/quick-start.md
  • docs/manuals/dpf.md
  • helm-prereqs/.helmignore
  • helm-prereqs/README.md
  • helm-prereqs/clean.sh
  • helm-prereqs/health-check.sh
  • helm-prereqs/helmfile.yaml
  • helm-prereqs/operators/dpf/cert-manager-policy.yaml
  • helm-prereqs/operators/dpf/dpfoperatorconfig.yaml.tmpl
  • helm-prereqs/operators/dpf/dpu-cluster-vip-service.yaml.tmpl
  • helm-prereqs/operators/dpf/dpucluster.yaml.tmpl
  • helm-prereqs/operators/values/argo-cd.yaml
  • helm-prereqs/operators/values/kamaji.yaml
  • helm-prereqs/operators/values/maintenance-operator.yaml
  • helm-prereqs/operators/values/node-feature-discovery.yaml
  • helm-prereqs/preflight.sh
  • helm-prereqs/setup.sh
  • helm-prereqs/values/nico-core.yaml
  • helm/charts/nico-api/templates/dpf-rbac.yaml
  • helm/charts/nico-api/values.yaml
🚧 Files skipped from review as they are similar to previous changes (17)
  • helm-prereqs/.helmignore
  • helm-prereqs/operators/values/maintenance-operator.yaml
  • helm-prereqs/operators/values/node-feature-discovery.yaml
  • helm-prereqs/operators/dpf/dpucluster.yaml.tmpl
  • helm-prereqs/operators/dpf/dpfoperatorconfig.yaml.tmpl
  • helm-prereqs/values/nico-core.yaml
  • .gitignore
  • helm/charts/nico-api/values.yaml
  • book/src/configuration/configurability.md
  • helm-prereqs/operators/dpf/cert-manager-policy.yaml
  • helm-prereqs/operators/values/kamaji.yaml
  • helm-prereqs/operators/dpf/dpu-cluster-vip-service.yaml.tmpl
  • helm-prereqs/health-check.sh
  • crates/dpf/README.md
  • helm-prereqs/helmfile.yaml
  • helm-prereqs/README.md
  • helm-prereqs/clean.sh

Comment thread docs/getting-started/quick-start.md Outdated
Comment on lines +92 to +96
# DPF DPU provisioning is installed by default. Set these three, or pass
# --skip-dpf to setup.sh (sites with no DPUs / still on iPXE):
export NICO_DPF_DPU_INTERFACE=<control-plane-nic> # NIC facing the DPUs
export NICO_DPF_DPU_CLUSTER_VIP=<free-routable-ip> # DPU cluster control-plane VIP
export NICO_DPF_BMC_ROOT_PASSWORD=<bmc-root-password> # site-wide BMC root password

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Use shell-valid, history-safe DPF variable examples.

The angle-bracket placeholders make these Bash assignments invalid when copied, and entering NICO_DPF_BMC_ROOT_PASSWORD directly in an export command records the secret in shell history. Use quoted example values for non-secrets and a silent read prompt for the password.

As per path instructions, Markdown commands/examples must be realistic and safe.

Suggested revision
-export NICO_DPF_DPU_INTERFACE=<control-plane-nic>     # NIC facing the DPUs
-export NICO_DPF_DPU_CLUSTER_VIP=<free-routable-ip>    # DPU cluster control-plane VIP
-export NICO_DPF_BMC_ROOT_PASSWORD=<bmc-root-password> # site-wide BMC root password
+export NICO_DPF_DPU_INTERFACE="enoX"       # replace with the NIC facing the DPUs
+export NICO_DPF_DPU_CLUSTER_VIP="192.0.2.10" # replace with a free DPU-routable VIP
+read -r -s -p "DPF BMC root password: " NICO_DPF_BMC_ROOT_PASSWORD
+printf '\n'
+export NICO_DPF_BMC_ROOT_PASSWORD
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# DPF DPU provisioning is installed by default. Set these three, or pass
# --skip-dpf to setup.sh (sites with no DPUs / still on iPXE):
export NICO_DPF_DPU_INTERFACE=<control-plane-nic> # NIC facing the DPUs
export NICO_DPF_DPU_CLUSTER_VIP=<free-routable-ip> # DPU cluster control-plane VIP
export NICO_DPF_BMC_ROOT_PASSWORD=<bmc-root-password> # site-wide BMC root password
# DPF DPU provisioning is installed by default. Set these three, or pass
# --skip-dpf to setup.sh (sites with no DPUs / still on iPXE):
export NICO_DPF_DPU_INTERFACE="enoX" # replace with the NIC facing the DPUs
export NICO_DPF_DPU_CLUSTER_VIP="192.0.2.10" # replace with a free DPU-routable VIP
read -r -s -p "DPF BMC root password: " NICO_DPF_BMC_ROOT_PASSWORD
printf '\n'
export NICO_DPF_BMC_ROOT_PASSWORD
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/getting-started/quick-start.md` around lines 92 - 96, Update the DPF
provisioning examples in the quick-start instructions to use shell-valid quoted
placeholder values for NICO_DPF_DPU_INTERFACE and NICO_DPF_DPU_CLUSTER_VIP, and
replace the password export with a silent read prompt that assigns
NICO_DPF_BMC_ROOT_PASSWORD without exposing it in shell history.

Source: Path instructions

Comment thread docs/manuals/dpf.md
Comment thread helm-prereqs/setup.sh Outdated
… setup.sh

Automates deploying NVIDIA DOCA Platform Framework (DPF v26.4.0) as part of
helm-prereqs/setup.sh so DPF-based DPU provisioning is enable-able this release.
DPF installs by default; --skip-dpf opts out.

- Prereqs: argo-cd, kamaji, maintenance-operator, node-feature-discovery as
  pinned helmfile releases (mirrors doca-platform prereqs.yaml), with preSync
  CRD-apply hooks and static values under operators/values/.
- Kamaji cold-start deadlock recovery: breaks the DataStore/webhook
  chicken-and-egg on first install (out-of-band Issuer/Certificate/DataStore +
  failurePolicy toggle), plus kamaji controller HA via replicaCount.
- DPF operator + CRs: clones doca-platform, installs the operator, applies
  DPFOperatorConfig / DPUCluster / DPU-cluster VIP Service (envsubst templates).
- Two-phase Core: deploys DPF-off, sets the site-wide BMC root via an in-cluster
  nico-admin-cli Job (Vault-issued mTLS client cert, root token fed via stdin),
  then re-deploys DPF-on and restarts carbide-api, with idempotent re-run
  detection so a rerun never down-cycles an already-enabled site.
- Build-and-push registry support (custom/self-built DPF image + version) with
  anonymous NGC pulls as the default; split public/private image handling.
- clean.sh DPF teardown (ordered CR deletion + finalizer strip), preflight.sh
  and health-check.sh DPF coverage, and nico-api dpf-rbac chart template.
- Docs: docs/manuals/dpf.md automated-install section, quick-start, README.

Validated end-to-end on a dev cluster: clean teardown followed by a fresh
reinstall brought all pods healthy with dpucluster Ready and DPF enabled.

Signed-off-by: Shayan Namaghi <snamaghi@nvidia.com>
@shayan1995

Copy link
Copy Markdown
Contributor Author

Second CodeRabbit pass (on the fix commit) — all 3 addressed:

  • setup.sh idempotent rerun / BMC credential (Major): the already-DPF-on rerun path now (re-)runs _dpf_set_bmc_root after waiting for nico-api, so a rerun with a rotated/corrected NICO_DPF_BMC_ROOT_PASSWORD is actually reconciled (it was required by preflight but silently ignored). Still skips the destructive DPF-off down-cycle.
  • dpf.md manual operator install (Minor): dropped the unconditional --set imagePullSecrets[0].name=dpf-pull-secret from both manual helm upgrade commands to match the automated anonymous-pull default, and documented adding it only for a private registry/mirror (avoids the 403-on-public-image footgun).
  • quick-start.md DPF env (Minor): the BMC password is now read via read -r -s instead of an inline export, so it isn't recorded in shell history.

All scripts pass bash -n. The docs changes are no-op at runtime; the setup.sh change reuses the already-validated _dpf_set_bmc_root path (verified end-to-end on a real cluster).

@shayan1995 shayan1995 force-pushed the feat/setup-dpf-install branch from 301b826 to 01a7d54 Compare July 15, 2026 22:46

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
docs/manuals/dpf.md (1)

1029-1058: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add the explicit service-to-artifact mapping requested previously.

The separate lists still leave carbide-otelcol’s two-image mapping ambiguous. Add a Service | Chart | Image(s) table covering all four services.

Proposed mapping
+| Service | Chart | Image(s) |
+| --- | --- | --- |
+| `carbide-dpu-agent` | `nico-dpu-agent` | `forge-dpu-agent` |
+| `carbide-dhcp-server` | `nico-dhcp-server` | `forge-dhcp-server` |
+| `carbide-fmds` | `nico-fmds` | `carbide-fmds` |
+| `carbide-otelcol` | `nico-otelcol` | `forge-dpu-otel-agent`, `otelcol-contrib` |

As per path instructions, documentation must be technically correct and operationally usable.

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

In `@docs/manuals/dpf.md` around lines 1029 - 1058, Add a Service | Chart |
Image(s) table in the DPF deployment documentation covering all four mandatory
services: carbide-api’s carbide-dpu-agent, carbide-dhcp-server, carbide-fmds,
and carbide-otelcol. Map each service to its corresponding chart under
bluefield/charts and list every image it deploys, explicitly showing
carbide-otelcol’s two-image mapping; keep the artifact names consistent with the
build commands and configuration blocks.

Source: Path instructions

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

Inline comments:
In `@helm-prereqs/setup.sh`:
- Around line 654-658: Update the hbn-user-password creation block to avoid
passing the generated password via the kubectl command-line arguments. Reuse the
existing secret-safe off-argv pattern in setup.sh, while preserving the current
namespace, secret name, and generated password behavior.
- Around line 211-217: Update the EXIT cleanup block in setup.sh to terminate
the dpf-set-bmc-root credential Job before deleting dpf-bmc-root-pw and
dpf-admincli-cert. Keep the cleanup scoped to INSTALL_DPF=true, make the Job
termination best-effort so cleanup continues, and preserve deletion of both
Secrets afterward.

---

Duplicate comments:
In `@docs/manuals/dpf.md`:
- Around line 1029-1058: Add a Service | Chart | Image(s) table in the DPF
deployment documentation covering all four mandatory services: carbide-api’s
carbide-dpu-agent, carbide-dhcp-server, carbide-fmds, and carbide-otelcol. Map
each service to its corresponding chart under bluefield/charts and list every
image it deploys, explicitly showing carbide-otelcol’s two-image mapping; keep
the artifact names consistent with the build commands and configuration blocks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b28f6ead-dae6-4252-bd37-c656c0e45868

📥 Commits

Reviewing files that changed from the base of the PR and between 301b826 and 01a7d54.

📒 Files selected for processing (23)
  • .gitignore
  • book/src/configuration/configurability.md
  • crates/dpf/README.md
  • docs/getting-started/quick-start.md
  • docs/manuals/dpf.md
  • helm-prereqs/.helmignore
  • helm-prereqs/README.md
  • helm-prereqs/clean.sh
  • helm-prereqs/health-check.sh
  • helm-prereqs/helmfile.yaml
  • helm-prereqs/operators/dpf/cert-manager-policy.yaml
  • helm-prereqs/operators/dpf/dpfoperatorconfig.yaml.tmpl
  • helm-prereqs/operators/dpf/dpu-cluster-vip-service.yaml.tmpl
  • helm-prereqs/operators/dpf/dpucluster.yaml.tmpl
  • helm-prereqs/operators/values/argo-cd.yaml
  • helm-prereqs/operators/values/kamaji.yaml
  • helm-prereqs/operators/values/maintenance-operator.yaml
  • helm-prereqs/operators/values/node-feature-discovery.yaml
  • helm-prereqs/preflight.sh
  • helm-prereqs/setup.sh
  • helm-prereqs/values/nico-core.yaml
  • helm/charts/nico-api/templates/dpf-rbac.yaml
  • helm/charts/nico-api/values.yaml
🚧 Files skipped from review as they are similar to previous changes (16)
  • helm-prereqs/operators/dpf/dpucluster.yaml.tmpl
  • .gitignore
  • helm-prereqs/.helmignore
  • helm-prereqs/operators/values/argo-cd.yaml
  • helm-prereqs/operators/values/node-feature-discovery.yaml
  • helm-prereqs/operators/dpf/dpu-cluster-vip-service.yaml.tmpl
  • helm-prereqs/operators/dpf/dpfoperatorconfig.yaml.tmpl
  • crates/dpf/README.md
  • helm-prereqs/operators/dpf/cert-manager-policy.yaml
  • helm-prereqs/operators/values/kamaji.yaml
  • helm-prereqs/values/nico-core.yaml
  • book/src/configuration/configurability.md
  • helm-prereqs/helmfile.yaml
  • helm-prereqs/README.md
  • docs/getting-started/quick-start.md
  • helm-prereqs/clean.sh

Comment thread helm-prereqs/setup.sh
Comment on lines +211 to +217
# Drop the ephemeral BMC-root + admin-cert Secrets if a mid-run errexit
# skipped _dpf_set_bmc_root's own cleanup — the plaintext site-wide BMC
# password must never linger in the cluster after setup exits.
if [[ "${INSTALL_DPF:-false}" == "true" ]]; then
kubectl delete secret dpf-bmc-root-pw dpf-admincli-cert -n nico-system \
--ignore-not-found >/dev/null 2>&1 || true
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Terminate the credential Job from EXIT cleanup before deleting its Secrets.

An interrupt or unrelated errexit during polling leaves dpf-set-bmc-root running with the site-wide BMC password already loaded into its environment.

Proposed fix
     if [[ "${INSTALL_DPF:-false}" == "true" ]]; then
+        kubectl delete job dpf-set-bmc-root -n nico-system \
+            --ignore-not-found --wait=true --timeout=30s \
+            >/dev/null 2>&1 || true
         kubectl delete secret dpf-bmc-root-pw dpf-admincli-cert -n nico-system \
             --ignore-not-found >/dev/null 2>&1 || true
     fi

As per path instructions, shell scripts must propagate failures safely and handle secrets securely.

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

In `@helm-prereqs/setup.sh` around lines 211 - 217, Update the EXIT cleanup block
in setup.sh to terminate the dpf-set-bmc-root credential Job before deleting
dpf-bmc-root-pw and dpf-admincli-cert. Keep the cleanup scoped to
INSTALL_DPF=true, make the Job termination best-effort so cleanup continues, and
preserve deletion of both Secrets afterward.

Source: Path instructions

Comment thread helm-prereqs/setup.sh
Comment on lines +654 to +658
if ! kubectl get secret hbn-user-password -n dpf-operator-system &>/dev/null; then
kubectl create secret generic hbn-user-password \
--namespace dpf-operator-system \
--from-literal=password="$(LC_ALL=C tr -dc 'a-z0-9' < /dev/urandom | head -c 10)"
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Keep the generated HBN password out of kubectl arguments.

--from-literal=password="$(...)" exposes this credential through the local process table. Use the existing off-argv pattern.

Proposed fix
         kubectl create secret generic hbn-user-password \
             --namespace dpf-operator-system \
-            --from-literal=password="$(LC_ALL=C tr -dc 'a-z0-9' < /dev/urandom | head -c 10)"
+            --from-file=password=<(LC_ALL=C tr -dc 'a-z0-9' < /dev/urandom | head -c 10)

As per path instructions, shell scripts must use secret-safe logging and argument handling.

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

In `@helm-prereqs/setup.sh` around lines 654 - 658, Update the hbn-user-password
creation block to avoid passing the generated password via the kubectl
command-line arguments. Reuse the existing secret-safe off-argv pattern in
setup.sh, while preserving the current namespace, secret name, and generated
password behavior.

Source: Path instructions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: Document standalone NICo control plane setup with DPF provisioning

1 participant