Skip to content

[Backport v1.26] [CONTP-1504] Manage DatadogCSIDriver from DatadogAgent#2938

Merged
tbavelier merged 1 commit into
v1.26from
backport-2857-to-v1.26
Apr 27, 2026
Merged

[Backport v1.26] [CONTP-1504] Manage DatadogCSIDriver from DatadogAgent#2938
tbavelier merged 1 commit into
v1.26from
backport-2857-to-v1.26

Conversation

@dd-octo-sts

@dd-octo-sts dd-octo-sts Bot commented Apr 27, 2026

Copy link
Copy Markdown

Backport e3f69bf from #2857.


What does this PR do?

When spec.global.csi.enabled=true, the DatadogAgent controller can now create and manage a DatadogCSIDriver custom resource on behalf of the DDA. The DatadogCSIDriver controller then reconciles it into the CSI DaemonSet and the cluster-scoped k8s.csi.datadoghq.com CSIDriver.

Controller-level opt-in. Management is gated on the existing operator flag --datadogCSIDriverEnabled (default false). With the flag off, csi.enabled=true keeps its long-standing semantics — the Agent uses a CSI driver that's installed by some other means (Helm chart, manual apply, GitOps) — and the operator doesn't touch anything. This preserves backward compatibility for existing clusters.

Defer to external installs. On the first-time create path (no DDA-owned CR yet), if a cluster-scoped k8s.csi.datadoghq.com CSIDriver is already present, the operator defers and skips creation. Avoids collisions with Helm/manual installs. Once the operator owns a CR, subsequent reconciles stay on the update path regardless of external CSIDriver presence.

Per-DDA opt-out for migrations. New field spec.global.csi.autoManage (*bool, default true). Flipping to false triggers cleanup of the operator-owned CR so users can hand ownership over to a DatadogCSIDriver they maintain themselves (useful when they need customizations not exposed via DDA spec) without having to toggle csi.enabled off/on.

Spec propagation from DDA. The created DatadogCSIDriver is built from:

  • Spec.APMSocketPathdda.Spec.Features.APM.UnixDomainSocketConfig.Path
  • Spec.DSDSocketPathdda.Spec.Features.Dogstatsd.UnixDomainSocketConfig.Path
  • Spec.Override.Tolerationsdda.Spec.Global.CSI.Tolerations
  • Spec.Override.NodeSelectordda.Spec.Global.CSI.NodeSelector
  • Spec.Override.Affinity.NodeAffinitydda.Spec.Global.CSI.NodeAffinity
  • Default operator-managed labels/annotations (app.kubernetes.io/managed-by=datadog-operator, etc.)
  • controllerutil.SetControllerReference → ownerRef for cascade delete

Scheduling fields (tolerations, nodeSelector, nodeAffinity) are set explicitly on spec.global.csi rather than being implicitly inherited from the node-agent component override. The Spec.Override struct is only populated when at least one scheduling field is set.

Update semantics. Spec-drift updates use a client.MergeFrom JSON merge patch (instead of UpdateFromObject), so only the fields we own (.spec, labels, annotations) appear in the wire payload. Finalizers added by the sibling DatadogCSIDriver controller (finalizer.datadoghq.com/csi-driver) and .status are not touched — prevents a class of bug where a spec-drift update would wipe the finalizer and a subsequent delete would leak the cluster-scoped CSIDriver.

Event-driven reconciles. The DDA controller now declares Owns(&v1alpha1.DatadogCSIDriver{}) (gated on DatadogCSIDriverEnabled to avoid startup crashes when the CRD is absent, matching the DatadogAgentInternal/ExtendedDaemonSet pattern). Drift on the operator-owned CR now self-heals within milliseconds via watch events rather than waiting for the 15s periodic requeue.

Motivation

Simplify CSI driver setup. Users can configure CSI on their DatadogAgent (and for cluster admins that want the operator to install the driver, flip --datadogCSIDriverEnabled at deployment time) without maintaining a separate DatadogCSIDriver by hand. For advanced users who need finer-grained control, autoManage=false offers a seamless migration path off "automatic" operator management based on DDA spec.

Additional Notes

  • The DatadogCSIDriver lifecycle is managed via direct API calls (get/patch/delete) rather than the dependency store, because the store only supports built-in Kubernetes types. Documented in code comments on reconcileDatadogCSIDriver.
  • RBAC is unchanged — the existing csidrivers rules (list/watch/create cluster-wide, get/update/patch/delete scoped to k8s.csi.datadoghq.com) cover the new external-check Get.

Minimum Agent Versions

N/A — this is an operator-level feature.

Describe your test plan

Unit tests in ddcsi_test.go cover:

  • Disabled — csi.enabled=false, no CR created
  • EnabledAndCreated — csi.enabled=true, flag on, CR created with owner ref and operator-managed labels
  • SpecFromDDA — APMSocketPath, DSDSocketPath, and tolerations (via spec.global.csi.tolerations) propagated from DDA
  • NodeSelectorPropagatedspec.global.csi.nodeSelector forwarded to Spec.Override.NodeSelector
  • NodeAffinityPropagatedspec.global.csi.nodeAffinity forwarded to Spec.Override.Affinity.NodeAffinity
  • NoOverrideWhenNoTolerations — override not set when no scheduling fields are configured
  • AutoManageDisabledCleansUpAndDoesNotRecreate — opt-out deletes the CR and stays out of the way
  • AutoManageDisabledSkipsForeignCR — opt-out honors IsControlledBy guard
  • ControllerDisabled — flag off is a no-op (no error, no CR)
  • DefersToExternalCSIDriver — pre-existing cluster-scoped CSIDriver blocks first-time create
  • ExternalAppearsAfterCRCreated — once owning a CR, external appearance doesn't abandon it
  • Idempotent — repeat reconciles are no-ops
  • CleanupOnDisable — owned resource deleted on toggle
  • CleanupSkipsNotOwned — manually-created CRs left alone
  • UpdateOnSpecDrift — drift reconciled back via merge patch
  • UpdatePreservesFinalizers — spec-drift update preserves externally-added finalizers (finalizer-wipe bug regression test)
  • CleanupCRDNotAvailable — no error when CRD isn't present

Checklist

  • PR has at least one valid label: bug, enhancement, refactoring, documentation, tooling, and/or dependencies
  • PR has a milestone or the qa/skip-qa label
  • All commits are signed (see: signing commits)

* Add DatadogCSIDriver CRD types and generated manifests

Define the DatadogCSIDriver, DatadogCSIDriverSpec, DatadogCSIDriverOverride,
and DatadogCSIDriverStatus types in api/datadoghq/v1alpha1. The CRD enables
declarative management of the Datadog CSI Driver via the operator, replacing
the standalone Helm chart deployment.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Add DatadogCSIDriver outer controller with RBAC markers

Controller-runtime wiring for the DatadogCSIDriver reconciler. Watches the
primary CR with GenerationChangedPredicate, owned DaemonSets for all changes
(including status), and CSIDriver objects via label-based enqueue for drift
detection on the cluster-scoped resource.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Add DatadogCSIDriver reconciler, DaemonSet and CSIDriver builders

Implements the reconciliation logic for the DatadogCSIDriver controller:
- Deferred SSA status patch with ObservedGeneration tracking
- CSIDriver object management with Get+DeepEqual+Update for full drift reversion
- DaemonSet management with the same pattern, including label enforcement
- Override system with merge-by-name semantics (env vars, volumes, mounts)
- Image resolution via pkg/images (supports tag-only overrides)
- Finalizer-based cleanup of the cluster-scoped CSIDriver on deletion
- Comprehensive unit tests covering creation, updates, drift, deletion, overrides

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Wire DatadogCSIDriver controller into operator startup

Register the controller in setup.go with a feature flag and add the
-datadogCSIDriverEnabled flag (default: false) to cmd/main.go. Also
registers the storagev1 scheme required for CSIDriver object management.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Add CreateDatadogCSIDriver field to CSIConfig

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Add reconcileDatadogCSIDriver for creating DatadogCSIDriver from DDA

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Wire reconcileDatadogCSIDriver into manageDDADependenciesWithDDAI

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Add tests for reconcileDatadogCSIDriver

* Add update logic to createOrUpdateDatadogCSIDriver

Treat the DatadogCSIDriver as a desired-state object like DDAI: if
someone modifies it externally, reconcile it back to the operator's
desired state on the next loop. Uses apiequality.Semantic.DeepEqual
to compare specs and kubernetes.UpdateFromObject to update.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* remove unnecessary variable declaration

* fix test after merging main

* Scope csidriver RBAC to Datadog driver

* Add comment why these were re-implemented but could be extracted for future work

* Move DD_APM_ENABLED to shared controller constants

* Move image tag and registries to proper package and delete defaults.go to consolide with const.go

* Remove useless variable after constant driver name

* Switch to context based logging

* Fix pointer use

* Always create DDCSIDriver unless existing CSIDriver with name and managed by Helm, remove CRD option

* Add labels on created DatadogCSIDriver

* Add tolerations + customize socket paths based on config on DatadogAgent

* Use JSON patch instead of UpdateFromObject to keep finalizer added by DatadogCSIDriver controller

* Do not create DatadogCSIDriver if controller not enabled and share info to DDA

* Do not crash existing CSIDrivers users, simply skip

* add debug logs

* add DDCSI to informer to reconcile instantly

* Add manageDatadogCSIDriver flag to allow smooth transitions to user-managed DDCSIs

* guard update on controllerref to avoid managing same namespace/name DDCSI

* Add tolerations, affinity, nodeselector to CRD field + remove automatic tolerations from DDA

* rename to autoManage

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
(cherry picked from commit e3f69bf)
@dd-octo-sts dd-octo-sts Bot added enhancement New feature or request do-not-merge backport label added by backport action bot label added by backport bot team/container-platform team/container-autoscaling team/documentation labels Apr 27, 2026
@dd-octo-sts
dd-octo-sts Bot requested review from a team as code owners April 27, 2026 06:52
@dd-octo-sts dd-octo-sts Bot added this to the v1.26.0 milestone Apr 27, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b22199de0d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread internal/controller/datadogagent/dependencies.go
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 79.24528% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 40.67%. Comparing base (554029b) to head (b22199d).

Files with missing lines Patch % Lines
internal/controller/datadogagent/ddcsi.go 82.17% 9 Missing and 9 partials ⚠️
internal/controller/datadogagent/dependencies.go 0.00% 1 Missing and 1 partial ⚠️
internal/controller/datadogagent_controller.go 0.00% 1 Missing and 1 partial ⚠️

❌ Your patch status has failed because the patch coverage (79.24%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##            v1.26    #2938      +/-   ##
==========================================
+ Coverage   40.52%   40.67%   +0.14%     
==========================================
  Files         320      321       +1     
  Lines       28376    28482     +106     
==========================================
+ Hits        11500    11584      +84     
- Misses      16032    16043      +11     
- Partials      844      855      +11     
Flag Coverage Δ
unittests 40.67% <79.24%> (+0.14%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
internal/controller/datadogagent/controller.go 92.85% <ø> (ø)
internal/controller/setup.go 36.64% <100.00%> (+0.33%) ⬆️
internal/controller/datadogagent/dependencies.go 60.86% <0.00%> (-2.77%) ⬇️
internal/controller/datadogagent_controller.go 58.64% <0.00%> (-0.90%) ⬇️
internal/controller/datadogagent/ddcsi.go 82.17% <82.17%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 554029b...b22199d. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tbavelier
tbavelier merged commit e5cf461 into v1.26 Apr 27, 2026
72 checks passed
@tbavelier
tbavelier deleted the backport-2857-to-v1.26 branch April 27, 2026 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants