Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2454b86
Add DatadogCSIDriver CRD types and generated manifests
tbavelier Apr 2, 2026
3e5e846
Add DatadogCSIDriver outer controller with RBAC markers
tbavelier Apr 2, 2026
af2010c
Add DatadogCSIDriver reconciler, DaemonSet and CSIDriver builders
tbavelier Apr 2, 2026
fae3f32
Wire DatadogCSIDriver controller into operator startup
tbavelier Apr 2, 2026
a2effa1
Add CreateDatadogCSIDriver field to CSIConfig
tbavelier Apr 2, 2026
4377bf2
Add reconcileDatadogCSIDriver for creating DatadogCSIDriver from DDA
tbavelier Apr 2, 2026
bfaae4c
Wire reconcileDatadogCSIDriver into manageDDADependenciesWithDDAI
tbavelier Apr 2, 2026
f79d3ce
Add tests for reconcileDatadogCSIDriver
tbavelier Apr 2, 2026
893e5d5
Add update logic to createOrUpdateDatadogCSIDriver
tbavelier Apr 2, 2026
2034c4d
Merge branch 'main' into tbavelier/csi-driver-standalone-v2
tbavelier Apr 7, 2026
0d23610
remove unnecessary variable declaration
tbavelier Apr 7, 2026
a98d54c
fix test after merging main
tbavelier Apr 7, 2026
e81e212
Scope csidriver RBAC to Datadog driver
tbavelier Apr 7, 2026
9633847
Add comment why these were re-implemented but could be extracted for …
tbavelier Apr 7, 2026
612bdeb
Merge branch 'tbavelier/csi-driver-standalone-v2' into tbavelier/crea…
tbavelier Apr 7, 2026
08bf9c1
Move DD_APM_ENABLED to shared controller constants
tbavelier Apr 8, 2026
2b7940c
Move image tag and registries to proper package and delete defaults.g…
tbavelier Apr 8, 2026
877cf9c
Remove useless variable after constant driver name
tbavelier Apr 8, 2026
2174793
Switch to context based logging
tbavelier Apr 8, 2026
9cd13e2
Merge branch 'main' into tbavelier/csi-driver-standalone-v2
tbavelier Apr 8, 2026
e6fb3c7
Merge branch 'tbavelier/csi-driver-standalone-v2' into tbavelier/crea…
tbavelier Apr 8, 2026
27ae2fc
Merge branch 'main' into tbavelier/create-ddcsi-from-dda
tbavelier Apr 9, 2026
932c38e
Fix pointer use
tbavelier Apr 9, 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
7 changes: 7 additions & 0 deletions api/datadoghq/v2alpha1/datadogagent_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,13 @@ type CSIConfig struct {
// Default: false
// +optional
Enabled *bool `json:"enabled,omitempty"`

// CreateDatadogCSIDriver instructs the operator to create a DatadogCSIDriver custom resource
// when CSI is enabled. This requires the DatadogCSIDriver CRD to be installed and the
// DatadogCSIDriver controller to be enabled on the operator.
// Default: false
// +optional
CreateDatadogCSIDriver *bool `json:"createDatadogCSIDriver,omitempty"`
}

// InjectorConfig contains the configuration for the APM Injector.
Expand Down
5 changes: 5 additions & 0 deletions api/datadoghq/v2alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -2612,6 +2612,13 @@ spec:
csi:
description: CSI contains configuration for Datadog CSI Driver
properties:
createDatadogCSIDriver:
description: |-
CreateDatadogCSIDriver instructs the operator to create a DatadogCSIDriver custom resource
when CSI is enabled. This requires the DatadogCSIDriver CRD to be installed and the
DatadogCSIDriver controller to be enabled on the operator.
Default: false
type: boolean
enabled:
description: |-
Enables the usage of CSI driver in Datadog Agent.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2739,6 +2739,10 @@
"additionalProperties": false,
"description": "CSI contains configuration for Datadog CSI Driver",
"properties": {
"createDatadogCSIDriver": {
"description": "CreateDatadogCSIDriver instructs the operator to create a DatadogCSIDriver custom resource\nwhen CSI is enabled. This requires the DatadogCSIDriver CRD to be installed and the\nDatadogCSIDriver controller to be enabled on the operator.\nDefault: false",
"type": "boolean"
},
"enabled": {
"description": "Enables the usage of CSI driver in Datadog Agent.\nRequires installation of Datadog CSI Driver https://github.com/DataDog/helm-charts/tree/main/charts/datadog-csi-driver\nDefault: false",
"type": "boolean"
Expand Down
7 changes: 7 additions & 0 deletions config/crd/bases/v1/datadoghq.com_datadogagentprofiles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2612,6 +2612,13 @@ spec:
csi:
description: CSI contains configuration for Datadog CSI Driver
properties:
createDatadogCSIDriver:
description: |-
CreateDatadogCSIDriver instructs the operator to create a DatadogCSIDriver custom resource
when CSI is enabled. This requires the DatadogCSIDriver CRD to be installed and the
DatadogCSIDriver controller to be enabled on the operator.
Default: false
type: boolean
enabled:
description: |-
Enables the usage of CSI driver in Datadog Agent.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2743,6 +2743,10 @@
"additionalProperties": false,
"description": "CSI contains configuration for Datadog CSI Driver",
"properties": {
"createDatadogCSIDriver": {
"description": "CreateDatadogCSIDriver instructs the operator to create a DatadogCSIDriver custom resource\nwhen CSI is enabled. This requires the DatadogCSIDriver CRD to be installed and the\nDatadogCSIDriver controller to be enabled on the operator.\nDefault: false",
"type": "boolean"
},
"enabled": {
"description": "Enables the usage of CSI driver in Datadog Agent.\nRequires installation of Datadog CSI Driver https://github.com/DataDog/helm-charts/tree/main/charts/datadog-csi-driver\nDefault: false",
"type": "boolean"
Expand Down
7 changes: 7 additions & 0 deletions config/crd/bases/v1/datadoghq.com_datadogagents.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2616,6 +2616,13 @@ spec:
csi:
description: CSI contains configuration for Datadog CSI Driver
properties:
createDatadogCSIDriver:
description: |-
CreateDatadogCSIDriver instructs the operator to create a DatadogCSIDriver custom resource
when CSI is enabled. This requires the DatadogCSIDriver CRD to be installed and the
DatadogCSIDriver controller to be enabled on the operator.
Default: false
type: boolean
enabled:
description: |-
Enables the usage of CSI driver in Datadog Agent.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2739,6 +2739,10 @@
"additionalProperties": false,
"description": "CSI contains configuration for Datadog CSI Driver",
"properties": {
"createDatadogCSIDriver": {
"description": "CreateDatadogCSIDriver instructs the operator to create a DatadogCSIDriver custom resource\nwhen CSI is enabled. This requires the DatadogCSIDriver CRD to be installed and the\nDatadogCSIDriver controller to be enabled on the operator.\nDefault: false",
"type": "boolean"
},
"enabled": {
"description": "Enables the usage of CSI driver in Datadog Agent.\nRequires installation of Datadog CSI Driver https://github.com/DataDog/helm-charts/tree/main/charts/datadog-csi-driver\nDefault: false",
"type": "boolean"
Expand Down
1 change: 1 addition & 0 deletions docs/configuration.v2alpha1.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ spec:
| global.credentials.appSecret.keyName | KeyName is the key of the secret to use. |
| global.credentials.appSecret.secretName | SecretName is the name of the secret. |
| global.criSocketPath | Path to the container runtime socket (if different from Docker). |
| global.csi.createDatadogCSIDriver | CreateDatadogCSIDriver instructs the operator to create a DatadogCSIDriver custom resource when CSI is enabled. This requires the DatadogCSIDriver CRD to be installed and the DatadogCSIDriver controller to be enabled on the operator. Default: false |
| global.csi.enabled | Enables the usage of CSI driver in Datadog Agent. Requires installation of Datadog CSI Driver https://github.com/DataDog/helm-charts/tree/main/charts/datadog-csi-driver Default: false |
| global.disableNonResourceRules | Set DisableNonResourceRules to exclude NonResourceURLs from default ClusterRoles. Required 'true' for Google Cloud Marketplace. |
| global.dockerSocketPath | Path to the docker runtime socket. |
Expand Down
3 changes: 3 additions & 0 deletions docs/configuration_public.md
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,9 @@ spec:
`global.criSocketPath`
: Path to the container runtime socket (if different from Docker).

`global.csi.createDatadogCSIDriver`
: CreateDatadogCSIDriver instructs the operator to create a DatadogCSIDriver custom resource when CSI is enabled. This requires the DatadogCSIDriver CRD to be installed and the DatadogCSIDriver controller to be enabled on the operator. Default: false

`global.csi.enabled`
: Enables the usage of CSI driver in Datadog Agent. Requires installation of Datadog CSI Driver https://github.com/DataDog/helm-charts/tree/main/charts/datadog-csi-driver Default: false

Expand Down
133 changes: 133 additions & 0 deletions internal/controller/datadogagent/ddcsi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.

package datadogagent

import (
"context"
"fmt"

"github.com/go-logr/logr"
apiequality "k8s.io/apimachinery/pkg/api/equality"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

"github.com/DataDog/datadog-operator/api/datadoghq/v1alpha1"
"github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1"
apiutils "github.com/DataDog/datadog-operator/api/utils"
"github.com/DataDog/datadog-operator/pkg/kubernetes"
)

const datadogCSIDriverKind = "DatadogCSIDriver"

// reconcileDatadogCSIDriver creates or deletes a DatadogCSIDriver custom resource based on the
// DDA's spec.global.csi configuration.
//
// This uses direct create/delete via the API client rather than the dependency store because the
// store (store.Store) only supports built-in Kubernetes types via a hardcoded ObjectKind enum,
// type-specific factory functions, and type-specific equality checks. Extending it for a single
// custom resource would require changes across multiple packages (pkg/kubernetes, pkg/equality,
// store). Direct management is simpler and follows the same pattern used for DatadogAgentInternal.
func (r *Reconciler) reconcileDatadogCSIDriver(ctx context.Context, logger logr.Logger, instance *v2alpha1.DatadogAgent) error {
csiEnabled := instance.Spec.Global != nil &&
instance.Spec.Global.CSI != nil &&
apiutils.BoolValue(instance.Spec.Global.CSI.Enabled) &&
apiutils.BoolValue(instance.Spec.Global.CSI.CreateDatadogCSIDriver)

if csiEnabled {
return r.createOrUpdateDatadogCSIDriver(ctx, logger, instance)
}
return r.cleanupDatadogCSIDriver(ctx, logger, instance)
}

// buildDesiredDatadogCSIDriver builds the desired DatadogCSIDriver object from the DDA spec.
// Currently the spec is empty (the DatadogCSIDriver controller applies its own defaults).
// In a follow-up, this will construct the spec based on relevant DDA fields.
func (r *Reconciler) buildDesiredDatadogCSIDriver(instance *v2alpha1.DatadogAgent) (*v1alpha1.DatadogCSIDriver, error) {
ddcsi := &v1alpha1.DatadogCSIDriver{
ObjectMeta: metav1.ObjectMeta{
Name: instance.Name,
Namespace: instance.Namespace,
},
}
if err := controllerutil.SetControllerReference(instance, ddcsi, r.scheme); err != nil {
return nil, fmt.Errorf("failed to set owner reference on DatadogCSIDriver: %w", err)
}
return ddcsi, nil
}

// createOrUpdateDatadogCSIDriver ensures a DatadogCSIDriver resource exists with the desired spec.
// Like DatadogAgentInternal, this treats the DatadogCSIDriver as a desired-state object: if someone
// modifies it, the operator will reconcile it back to the desired state on the next loop.
func (r *Reconciler) createOrUpdateDatadogCSIDriver(ctx context.Context, logger logr.Logger, instance *v2alpha1.DatadogAgent) error {
// Guard: check that the DatadogCSIDriver CRD is installed on the cluster.
if !r.platformInfo.IsResourceSupported(datadogCSIDriverKind) {
return fmt.Errorf("DatadogCSIDriver CRD is not installed on the cluster but spec.global.csi.createDatadogCSIDriver is enabled")
}

desired, err := r.buildDesiredDatadogCSIDriver(instance)
if err != nil {
return err
}

existing := &v1alpha1.DatadogCSIDriver{}
err = r.client.Get(ctx, types.NamespacedName{Name: desired.Name, Namespace: desired.Namespace}, existing)
if err != nil {
if !apierrors.IsNotFound(err) {
return fmt.Errorf("failed to get DatadogCSIDriver %s/%s: %w", desired.Namespace, desired.Name, err)
}

// Create a new DatadogCSIDriver.
logger.Info("Creating DatadogCSIDriver", "name", desired.Name, "namespace", desired.Namespace)
if err := r.client.Create(ctx, desired); err != nil {
return fmt.Errorf("failed to create DatadogCSIDriver %s/%s: %w", desired.Namespace, desired.Name, err)
}
return nil
}

// Update if the spec has drifted from the desired state.
if !apiequality.Semantic.DeepEqual(existing.Spec, desired.Spec) {
logger.Info("Updating DatadogCSIDriver", "name", desired.Name, "namespace", desired.Namespace)
if err := kubernetes.UpdateFromObject(ctx, r.client, desired, existing.ObjectMeta); err != nil {
return fmt.Errorf("failed to update DatadogCSIDriver %s/%s: %w", desired.Namespace, desired.Name, err)
}
}

return nil
}

// cleanupDatadogCSIDriver deletes the DDA-owned DatadogCSIDriver if it exists.
func (r *Reconciler) cleanupDatadogCSIDriver(ctx context.Context, logger logr.Logger, instance *v2alpha1.DatadogAgent) error {
// If the CRD is not installed, there is nothing to clean up.
if !r.platformInfo.IsResourceSupported(datadogCSIDriverKind) {
return nil
}

ddcsiName := instance.Name
ddcsiNamespace := instance.Namespace

existing := &v1alpha1.DatadogCSIDriver{}
err := r.client.Get(ctx, types.NamespacedName{Name: ddcsiName, Namespace: ddcsiNamespace}, existing)
if apierrors.IsNotFound(err) {
return nil
}
if err != nil {
return fmt.Errorf("failed to get DatadogCSIDriver %s/%s for cleanup: %w", ddcsiNamespace, ddcsiName, err)
}

// Only delete if this DDA owns it (via controller reference).
if !metav1.IsControlledBy(existing, instance) {
logger.V(1).Info("DatadogCSIDriver exists but is not owned by this DatadogAgent, skipping cleanup", "name", ddcsiName)
return nil
}

logger.Info("Deleting DatadogCSIDriver", "name", ddcsiName, "namespace", ddcsiNamespace)
if err := r.client.Delete(ctx, existing); err != nil && !apierrors.IsNotFound(err) {
return fmt.Errorf("failed to delete DatadogCSIDriver %s/%s: %w", ddcsiNamespace, ddcsiName, err)
}
return nil
}
Loading
Loading