From 94b0882f4972afb95b4bde51041895ed7b6d0cad Mon Sep 17 00:00:00 2001 From: mackjmr Date: Wed, 11 Dec 2024 17:53:48 +0100 Subject: [PATCH 01/28] OTel Agent Feature Support --- Makefile | 2 +- api/datadoghq/v2alpha1/const.go | 2 + .../v2alpha1/datadogagent_default.go | 7 + api/datadoghq/v2alpha1/datadogagent_types.go | 21 ++ api/datadoghq/v2alpha1/test/builder.go | 48 +++++ .../v2alpha1/zz_generated.deepcopy.go | 41 ++++ .../v2alpha1/zz_generated.openapi.go | 50 ++++- .../bases/v1/datadoghq.com_datadogagents.yaml | 196 +++++++++++++++++ .../datadoghq.com_datadogagents_v2alpha1.json | 204 ++++++++++++++++++ config/manager/kustomization.yaml | 2 +- configmap.yaml | 35 +++ docs/configuration.v2alpha1.md | 5 + .../datadogagent/datadog-agent-minimum.yaml | 52 ++++- .../datadogagent/component/agent/default.go | 62 +++--- .../controller/datadogagent/controller.go | 1 + .../controller/datadogagent/feature/ids.go | 2 + .../feature/otelagent/configmap_test.go | 43 ++++ .../otelagent/defaultconfig/defaultconfig.go | 49 +++++ .../datadogagent/feature/otelagent/feature.go | 164 ++++++++++++++ .../feature/otelagent/feature_test.go | 201 +++++++++++++++++ 20 files changed, 1146 insertions(+), 41 deletions(-) create mode 100644 configmap.yaml create mode 100644 internal/controller/datadogagent/feature/otelagent/configmap_test.go create mode 100644 internal/controller/datadogagent/feature/otelagent/defaultconfig/defaultconfig.go create mode 100644 internal/controller/datadogagent/feature/otelagent/feature.go create mode 100644 internal/controller/datadogagent/feature/otelagent/feature_test.go diff --git a/Makefile b/Makefile index d36506393..7fc761a9d 100644 --- a/Makefile +++ b/Makefile @@ -132,7 +132,7 @@ uninstall: manifests $(KUSTOMIZE) ## Uninstall CRDs from a cluster .PHONY: deploy deploy: manifests $(KUSTOMIZE) ## Deploy controller in the configured Kubernetes cluster in ~/.kube/config - cd config/manager && $(ROOT)/$(KUSTOMIZE) edit set image controller=$(subst operator:v,operator:,$(IMG)) + cd config/manager && $(ROOT)/$(KUSTOMIZE) edit set image controller=$(IMG) $(KUSTOMIZE) build $(KUSTOMIZE_CONFIG) | kubectl apply --force-conflicts --server-side -f - .PHONY: undeploy diff --git a/api/datadoghq/v2alpha1/const.go b/api/datadoghq/v2alpha1/const.go index 3c26823cb..27378c62a 100644 --- a/api/datadoghq/v2alpha1/const.go +++ b/api/datadoghq/v2alpha1/const.go @@ -104,6 +104,8 @@ const ( DefaultDogstatsdPort = 8125 // DefaultDogstatsdPortName default dogstatsd port name DefaultDogstatsdPortName = "dogstatsdport" + // DefaultOTelAgentConf default otel agent ConfigMap name + DefaultOTelAgentConf string = "otel-agent-config" // DefaultKubeStateMetricsCoreConf default ksm core ConfigMap name DefaultKubeStateMetricsCoreConf string = "kube-state-metrics-core-config" // DefaultOrchestratorExplorerConf default orchestrator explorer ConfigMap name diff --git a/api/datadoghq/v2alpha1/datadogagent_default.go b/api/datadoghq/v2alpha1/datadogagent_default.go index ccaf1602d..3240a8b92 100644 --- a/api/datadoghq/v2alpha1/datadogagent_default.go +++ b/api/datadoghq/v2alpha1/datadogagent_default.go @@ -26,6 +26,7 @@ const ( defaultLogPodLogsPath string = "/var/log/pods" defaultLogContainerSymlinksPath string = "/var/log/containers" + defaultOtelAgentEnabled bool = false defaultLiveProcessCollectionEnabled bool = false defaultLiveContainerCollectionEnabled bool = true defaultProcessDiscoveryEnabled bool = true @@ -220,6 +221,12 @@ func defaultFeaturesConfig(ddaSpec *DatadogAgentSpec) { } apiutils.DefaultBooleanIfUnset(&ddaSpec.Features.LiveContainerCollection.Enabled, defaultLiveContainerCollectionEnabled) + // OTelAgent Feature + if ddaSpec.Features.OTelAgent == nil { + ddaSpec.Features.OTelAgent = &OTelAgentFeatureConfig{} + } + apiutils.DefaultBooleanIfUnset(&ddaSpec.Features.OTelAgent.Enabled, defaultOtelAgentEnabled) + // LiveProcessCollection Feature if ddaSpec.Features.LiveProcessCollection == nil { ddaSpec.Features.LiveProcessCollection = &LiveProcessCollectionFeatureConfig{} diff --git a/api/datadoghq/v2alpha1/datadogagent_types.go b/api/datadoghq/v2alpha1/datadogagent_types.go index 1c1187105..b6436e90c 100644 --- a/api/datadoghq/v2alpha1/datadogagent_types.go +++ b/api/datadoghq/v2alpha1/datadogagent_types.go @@ -44,6 +44,8 @@ type DatadogAgentSpec struct { type DatadogFeatures struct { // Application-level features + // OTelAgent configuration. + OTelAgent *OTelAgentFeatureConfig `json:"otelAgent,omitempty"` // LogCollection configuration. LogCollection *LogCollectionFeatureConfig `json:"logCollection,omitempty"` // LiveProcessCollection configuration. @@ -682,6 +684,25 @@ type KubeStateMetricsCoreFeatureConfig struct { Conf *CustomConfig `json:"conf,omitempty"` } +// OTelAgentFeatureConfig contains the configuration for the otel-agent. +// +k8s:openapi-gen=true +type OTelAgentFeatureConfig struct { + // Enabled enables the OTel Agent. + // Default: true + // +optional + Enabled *bool `json:"enabled,omitempty"` + + // Conf overrides the configuration for the default Kubernetes State Metrics Core check. + // This must point to a ConfigMap containing a valid cluster check configuration. + // +optional + Conf *CustomConfig `json:"conf,omitempty"` + + // Ports contains the ports for the otel-agent. + // Default: 4317/4318 + // +optional + Ports []*corev1.ContainerPort `json:"ports,omitempty"` +} + // AdmissionControllerFeatureConfig contains the Admission Controller feature configuration. // The Admission Controller runs in the Cluster Agent. type AdmissionControllerFeatureConfig struct { diff --git a/api/datadoghq/v2alpha1/test/builder.go b/api/datadoghq/v2alpha1/test/builder.go index 260919894..febd7cf06 100644 --- a/api/datadoghq/v2alpha1/test/builder.go +++ b/api/datadoghq/v2alpha1/test/builder.go @@ -9,6 +9,7 @@ import ( "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1" "github.com/DataDog/datadog-operator/api/utils" apiutils "github.com/DataDog/datadog-operator/api/utils" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelagent/defaultconfig" defaulting "github.com/DataDog/datadog-operator/pkg/defaulting" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -374,6 +375,53 @@ func (builder *DatadogAgentBuilder) WithProcessDiscoveryEnabled(enabled bool) *D return builder } +// OTel Agent +func (builder *DatadogAgentBuilder) initOtelAgent() { + if builder.datadogAgent.Spec.Features.OTelAgent == nil { + builder.datadogAgent.Spec.Features.OTelAgent = &v2alpha1.OTelAgentFeatureConfig{} + } +} + +func (builder *DatadogAgentBuilder) WithOTelAgentEnabled(enabled bool) *DatadogAgentBuilder { + builder.initOtelAgent() + builder.datadogAgent.Spec.Features.OTelAgent.Enabled = apiutils.NewBoolPointer(enabled) + return builder +} + +func (builder *DatadogAgentBuilder) WithOTelAgentConfig() *DatadogAgentBuilder { + builder.datadogAgent.Spec.Features.OTelAgent.Conf = &v2alpha1.CustomConfig{} + builder.datadogAgent.Spec.Features.OTelAgent.Conf.ConfigData = + apiutils.NewStringPointer(defaultconfig.DefaultOtelCollectorConfig) + return builder +} + +func (builder *DatadogAgentBuilder) WithOTelAgentConfigMap() *DatadogAgentBuilder { + builder.datadogAgent.Spec.Features.OTelAgent.Conf = &v2alpha1.CustomConfig{} + builder.datadogAgent.Spec.Features.OTelAgent.Conf.ConfigMap = &v2alpha1.ConfigMapConfig{ + Name: "user-provided-config-map", + Items: []corev1.KeyToPath{ + { + Key: "otel-config.yaml", + }, + }, + } + return builder +} + +func (builder *DatadogAgentBuilder) WithOTelAgentPorts(grpcPort int32, httpPort int32) *DatadogAgentBuilder { + builder.datadogAgent.Spec.Features.OTelAgent.Ports = []*corev1.ContainerPort{ + { + Name: "otel-http", + ContainerPort: httpPort, + }, + { + Name: "otel-grpc", + ContainerPort: grpcPort, + }, + } + return builder +} + // Log Collection func (builder *DatadogAgentBuilder) initLogCollection() { if builder.datadogAgent.Spec.Features.LogCollection == nil { diff --git a/api/datadoghq/v2alpha1/zz_generated.deepcopy.go b/api/datadoghq/v2alpha1/zz_generated.deepcopy.go index 2e038d625..9fb9bced0 100644 --- a/api/datadoghq/v2alpha1/zz_generated.deepcopy.go +++ b/api/datadoghq/v2alpha1/zz_generated.deepcopy.go @@ -1097,6 +1097,11 @@ func (in *DatadogCredentials) DeepCopy() *DatadogCredentials { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DatadogFeatures) DeepCopyInto(out *DatadogFeatures) { *out = *in + if in.OTelAgent != nil { + in, out := &in.OTelAgent, &out.OTelAgent + *out = new(OTelAgentFeatureConfig) + (*in).DeepCopyInto(*out) + } if in.LogCollection != nil { in, out := &in.LogCollection, &out.LogCollection *out = new(LogCollectionFeatureConfig) @@ -2176,6 +2181,42 @@ func (in *OTLPReceiverConfig) DeepCopy() *OTLPReceiverConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OTelAgentFeatureConfig) DeepCopyInto(out *OTelAgentFeatureConfig) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.Conf != nil { + in, out := &in.Conf, &out.Conf + *out = new(CustomConfig) + (*in).DeepCopyInto(*out) + } + if in.Ports != nil { + in, out := &in.Ports, &out.Ports + *out = make([]*corev1.ContainerPort, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(corev1.ContainerPort) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OTelAgentFeatureConfig. +func (in *OTelAgentFeatureConfig) DeepCopy() *OTelAgentFeatureConfig { + if in == nil { + return nil + } + out := new(OTelAgentFeatureConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OrchestratorExplorerFeatureConfig) DeepCopyInto(out *OrchestratorExplorerFeatureConfig) { *out = *in diff --git a/api/datadoghq/v2alpha1/zz_generated.openapi.go b/api/datadoghq/v2alpha1/zz_generated.openapi.go index 813a4d3b1..a47d4a15c 100644 --- a/api/datadoghq/v2alpha1/zz_generated.openapi.go +++ b/api/datadoghq/v2alpha1/zz_generated.openapi.go @@ -39,6 +39,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTLPHTTPConfig": schema_datadog_operator_api_datadoghq_v2alpha1_OTLPHTTPConfig(ref), "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTLPProtocolsConfig": schema_datadog_operator_api_datadoghq_v2alpha1_OTLPProtocolsConfig(ref), "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTLPReceiverConfig": schema_datadog_operator_api_datadoghq_v2alpha1_OTLPReceiverConfig(ref), + "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTelAgentFeatureConfig": schema_datadog_operator_api_datadoghq_v2alpha1_OTelAgentFeatureConfig(ref), "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OrchestratorExplorerFeatureConfig": schema_datadog_operator_api_datadoghq_v2alpha1_OrchestratorExplorerFeatureConfig(ref), "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.PrometheusScrapeFeatureConfig": schema_datadog_operator_api_datadoghq_v2alpha1_PrometheusScrapeFeatureConfig(ref), "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.RemoteConfigConfiguration": schema_datadog_operator_api_datadoghq_v2alpha1_RemoteConfigConfiguration(ref), @@ -525,6 +526,12 @@ func schema_datadog_operator_api_datadoghq_v2alpha1_DatadogFeatures(ref common.R Description: "DatadogFeatures are features running on the Agent and Cluster Agent.", Type: []string{"object"}, Properties: map[string]spec.Schema{ + "otelAgent": { + SchemaProps: spec.SchemaProps{ + Description: "OTelAgent configuration.", + Ref: ref("github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTelAgentFeatureConfig"), + }, + }, "logCollection": { SchemaProps: spec.SchemaProps{ Description: "LogCollection configuration.", @@ -691,7 +698,7 @@ func schema_datadog_operator_api_datadoghq_v2alpha1_DatadogFeatures(ref common.R }, }, Dependencies: []string{ - "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.APMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ASMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.AdmissionControllerFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.AutoscalingFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CSPMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CWSFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ClusterChecksFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.DogstatsdFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.EBPFCheckFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.EventCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ExternalMetricsServerFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.HelmCheckFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.KubeStateMetricsCoreFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.LiveContainerCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.LiveProcessCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.LogCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.NPMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OOMKillFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTLPFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OrchestratorExplorerFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ProcessDiscoveryFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.PrometheusScrapeFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.RemoteConfigurationFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.SBOMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ServiceDiscoveryFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.TCPQueueLengthFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.USMFeatureConfig"}, + "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.APMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ASMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.AdmissionControllerFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.AutoscalingFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CSPMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CWSFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ClusterChecksFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.DogstatsdFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.EBPFCheckFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.EventCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ExternalMetricsServerFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.HelmCheckFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.KubeStateMetricsCoreFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.LiveContainerCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.LiveProcessCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.LogCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.NPMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OOMKillFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTLPFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTelAgentFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OrchestratorExplorerFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ProcessDiscoveryFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.PrometheusScrapeFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.RemoteConfigurationFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.SBOMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ServiceDiscoveryFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.TCPQueueLengthFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.USMFeatureConfig"}, } } @@ -1273,6 +1280,47 @@ func schema_datadog_operator_api_datadoghq_v2alpha1_OTLPReceiverConfig(ref commo } } +func schema_datadog_operator_api_datadoghq_v2alpha1_OTelAgentFeatureConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "OTelAgentFeatureConfig contains the configuration for the otel-agent.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "enabled": { + SchemaProps: spec.SchemaProps{ + Description: "Enabled enables the OTel Agent. Default: true", + Type: []string{"boolean"}, + Format: "", + }, + }, + "conf": { + SchemaProps: spec.SchemaProps{ + Description: "Conf overrides the configuration for the default Kubernetes State Metrics Core check. This must point to a ConfigMap containing a valid cluster check configuration.", + Ref: ref("github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CustomConfig"), + }, + }, + "ports": { + SchemaProps: spec.SchemaProps{ + Description: "Ports contains the ports for the otel-agent. Default: 4317/4318", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.ContainerPort"), + }, + }, + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CustomConfig", "k8s.io/api/core/v1.ContainerPort"}, + } +} + func schema_datadog_operator_api_datadoghq_v2alpha1_OrchestratorExplorerFeatureConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/config/crd/bases/v1/datadoghq.com_datadogagents.yaml b/config/crd/bases/v1/datadoghq.com_datadogagents.yaml index 01c9cc545..6c433ef29 100644 --- a/config/crd/bases/v1/datadoghq.com_datadogagents.yaml +++ b/config/crd/bases/v1/datadoghq.com_datadogagents.yaml @@ -1284,6 +1284,104 @@ spec: Default: true type: boolean type: object + otelAgent: + description: OTelAgent configuration. + properties: + conf: + description: |- + Conf overrides the configuration for the default Kubernetes State Metrics Core check. + This must point to a ConfigMap containing a valid cluster check configuration. + properties: + configData: + description: ConfigData corresponds to the configuration file content. + type: string + configMap: + description: ConfigMap references an existing ConfigMap with the configuration file content. + properties: + items: + description: Items maps a ConfigMap data `key` to a file `path` mount. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: |- + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + If not specified, the volume defaultMode will be used. + This might be in conflict with other options that affect the file + mode, like fsGroup, and the result can be other mode bits set. + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map + name: + description: Name is the name of the ConfigMap. + type: string + type: object + type: object + enabled: + description: |- + Enabled enables the OTel Agent. + Default: true + type: boolean + ports: + description: |- + Ports contains the ports for the otel-agent. + Default: 4317/4318 + items: + description: ContainerPort represents a network port in a single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + type: object otlp: description: OTLP ingest configuration properties: @@ -8013,6 +8111,104 @@ spec: Default: true type: boolean type: object + otelAgent: + description: OTelAgent configuration. + properties: + conf: + description: |- + Conf overrides the configuration for the default Kubernetes State Metrics Core check. + This must point to a ConfigMap containing a valid cluster check configuration. + properties: + configData: + description: ConfigData corresponds to the configuration file content. + type: string + configMap: + description: ConfigMap references an existing ConfigMap with the configuration file content. + properties: + items: + description: Items maps a ConfigMap data `key` to a file `path` mount. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: |- + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + If not specified, the volume defaultMode will be used. + This might be in conflict with other options that affect the file + mode, like fsGroup, and the result can be other mode bits set. + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map + name: + description: Name is the name of the ConfigMap. + type: string + type: object + type: object + enabled: + description: |- + Enabled enables the OTel Agent. + Default: true + type: boolean + ports: + description: |- + Ports contains the ports for the otel-agent. + Default: 4317/4318 + items: + description: ContainerPort represents a network port in a single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + type: object otlp: description: OTLP ingest configuration properties: diff --git a/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json b/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json index a89741b9d..60ee384e3 100644 --- a/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json +++ b/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json @@ -1330,6 +1330,108 @@ }, "type": "object" }, + "otelAgent": { + "additionalProperties": false, + "description": "OTelAgent configuration.", + "properties": { + "conf": { + "additionalProperties": false, + "description": "Conf overrides the configuration for the default Kubernetes State Metrics Core check.\nThis must point to a ConfigMap containing a valid cluster check configuration.", + "properties": { + "configData": { + "description": "ConfigData corresponds to the configuration file content.", + "type": "string" + }, + "configMap": { + "additionalProperties": false, + "description": "ConfigMap references an existing ConfigMap with the configuration file content.", + "properties": { + "items": { + "description": "Items maps a ConfigMap data `key` to a file `path` mount.", + "items": { + "additionalProperties": false, + "description": "Maps a string key to a path within a volume.", + "properties": { + "key": { + "description": "key is the key to project.", + "type": "string" + }, + "mode": { + "description": "mode is Optional: mode bits used to set permissions on this file.\nMust be an octal value between 0000 and 0777 or a decimal value between 0 and 511.\nYAML accepts both octal and decimal values, JSON requires decimal values for mode bits.\nIf not specified, the volume defaultMode will be used.\nThis might be in conflict with other options that affect the file\nmode, like fsGroup, and the result can be other mode bits set.", + "format": "int32", + "type": "integer" + }, + "path": { + "description": "path is the relative path of the file to map the key to.\nMay not be an absolute path.\nMay not contain the path element '..'.\nMay not start with the string '..'.", + "type": "string" + } + }, + "required": [ + "key", + "path" + ], + "type": "object" + }, + "type": "array", + "x-kubernetes-list-map-keys": [ + "key" + ], + "x-kubernetes-list-type": "map" + }, + "name": { + "description": "Name is the name of the ConfigMap.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "enabled": { + "description": "Enabled enables the OTel Agent.\nDefault: true", + "type": "boolean" + }, + "ports": { + "description": "Ports contains the ports for the otel-agent.\nDefault: 4317/4318", + "items": { + "additionalProperties": false, + "description": "ContainerPort represents a network port in a single container.", + "properties": { + "containerPort": { + "description": "Number of port to expose on the pod's IP address.\nThis must be a valid port number, 0 \u003c x \u003c 65536.", + "format": "int32", + "type": "integer" + }, + "hostIP": { + "description": "What host IP to bind the external port to.", + "type": "string" + }, + "hostPort": { + "description": "Number of port to expose on the host.\nIf specified, this must be a valid port number, 0 \u003c x \u003c 65536.\nIf HostNetwork is specified, this must match ContainerPort.\nMost containers do not need this.", + "format": "int32", + "type": "integer" + }, + "name": { + "description": "If specified, this must be an IANA_SVC_NAME and unique within the pod. Each\nnamed port in a pod must have a unique name. Name for the port that can be\nreferred to by services.", + "type": "string" + }, + "protocol": { + "default": "TCP", + "description": "Protocol for port. Must be UDP, TCP, or SCTP.\nDefaults to \"TCP\".", + "type": "string" + } + }, + "required": [ + "containerPort" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, "otlp": { "additionalProperties": false, "description": "OTLP ingest configuration", @@ -7999,6 +8101,108 @@ }, "type": "object" }, + "otelAgent": { + "additionalProperties": false, + "description": "OTelAgent configuration.", + "properties": { + "conf": { + "additionalProperties": false, + "description": "Conf overrides the configuration for the default Kubernetes State Metrics Core check.\nThis must point to a ConfigMap containing a valid cluster check configuration.", + "properties": { + "configData": { + "description": "ConfigData corresponds to the configuration file content.", + "type": "string" + }, + "configMap": { + "additionalProperties": false, + "description": "ConfigMap references an existing ConfigMap with the configuration file content.", + "properties": { + "items": { + "description": "Items maps a ConfigMap data `key` to a file `path` mount.", + "items": { + "additionalProperties": false, + "description": "Maps a string key to a path within a volume.", + "properties": { + "key": { + "description": "key is the key to project.", + "type": "string" + }, + "mode": { + "description": "mode is Optional: mode bits used to set permissions on this file.\nMust be an octal value between 0000 and 0777 or a decimal value between 0 and 511.\nYAML accepts both octal and decimal values, JSON requires decimal values for mode bits.\nIf not specified, the volume defaultMode will be used.\nThis might be in conflict with other options that affect the file\nmode, like fsGroup, and the result can be other mode bits set.", + "format": "int32", + "type": "integer" + }, + "path": { + "description": "path is the relative path of the file to map the key to.\nMay not be an absolute path.\nMay not contain the path element '..'.\nMay not start with the string '..'.", + "type": "string" + } + }, + "required": [ + "key", + "path" + ], + "type": "object" + }, + "type": "array", + "x-kubernetes-list-map-keys": [ + "key" + ], + "x-kubernetes-list-type": "map" + }, + "name": { + "description": "Name is the name of the ConfigMap.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "enabled": { + "description": "Enabled enables the OTel Agent.\nDefault: true", + "type": "boolean" + }, + "ports": { + "description": "Ports contains the ports for the otel-agent.\nDefault: 4317/4318", + "items": { + "additionalProperties": false, + "description": "ContainerPort represents a network port in a single container.", + "properties": { + "containerPort": { + "description": "Number of port to expose on the pod's IP address.\nThis must be a valid port number, 0 \u003c x \u003c 65536.", + "format": "int32", + "type": "integer" + }, + "hostIP": { + "description": "What host IP to bind the external port to.", + "type": "string" + }, + "hostPort": { + "description": "Number of port to expose on the host.\nIf specified, this must be a valid port number, 0 \u003c x \u003c 65536.\nIf HostNetwork is specified, this must match ContainerPort.\nMost containers do not need this.", + "format": "int32", + "type": "integer" + }, + "name": { + "description": "If specified, this must be an IANA_SVC_NAME and unique within the pod. Each\nnamed port in a pod must have a unique name. Name for the port that can be\nreferred to by services.", + "type": "string" + }, + "protocol": { + "default": "TCP", + "description": "Protocol for port. Must be UDP, TCP, or SCTP.\nDefaults to \"TCP\".", + "type": "string" + } + }, + "required": [ + "containerPort" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, "otlp": { "additionalProperties": false, "description": "OTLP ingest configuration", diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 962660140..dab091ee7 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -3,6 +3,6 @@ resources: images: - name: controller newName: gcr.io/datadoghq/operator - newTag: 1.10.0 + newTag: v1.9.0-rc.3_6ff015ce apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization diff --git a/configmap.yaml b/configmap.yaml new file mode 100644 index 000000000..95f660fb5 --- /dev/null +++ b/configmap.yaml @@ -0,0 +1,35 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: user-provided-config-map + namespace: system +data: + otel-config.yaml: |- + receivers: + otlp: + protocols: + grpc: + http: + exporters: + debug: + verbosity: detailed + datadog: + api: + key: "" + processors: + batch: + connectors: + service: + pipelines: + traces: + receivers: [otlp] + processors: [batch] + exporters: [datadog] + metrics: + receivers: [otlp] + processors: [batch] + exporters: [datadog] + logs: + receivers: [otlp] + processors: [batch] + exporters: [datadog] diff --git a/docs/configuration.v2alpha1.md b/docs/configuration.v2alpha1.md index c99072725..07dc29548 100644 --- a/docs/configuration.v2alpha1.md +++ b/docs/configuration.v2alpha1.md @@ -141,6 +141,11 @@ spec: | features.orchestratorExplorer.enabled | Enables the Orchestrator Explorer. Default: true | | features.orchestratorExplorer.extraTags | Additional tags to associate with the collected data in the form of `a b c`. This is a Cluster Agent option distinct from DD_TAGS that is used in the Orchestrator Explorer. | | features.orchestratorExplorer.scrubContainers | ScrubContainers enables scrubbing of sensitive container data (passwords, tokens, etc. ). Default: true | +| features.otelAgent.conf.configData | ConfigData corresponds to the configuration file content. | +| features.otelAgent.conf.configMap.items | Maps a ConfigMap data `key` to a file `path` mount. | +| features.otelAgent.conf.configMap.name | Is the name of the ConfigMap. | +| features.otelAgent.enabled | Enables the OTel Agent. Default: true | +| features.otelAgent.ports | Contains the ports for the otel-agent. Default: 4317/4318 | | features.otlp.receiver.protocols.grpc.enabled | Enable the OTLP/gRPC endpoint. Host port is enabled by default and can be disabled. | | features.otlp.receiver.protocols.grpc.endpoint | For OTLP/gRPC. gRPC supports several naming schemes: https://github.com/grpc/grpc/blob/master/doc/naming.md The Datadog Operator supports only 'host:port' (usually `0.0.0.0:port`). Default: `0.0.0.0:4317`. | | features.otlp.receiver.protocols.grpc.hostPortConfig.enabled | Enables host port configuration | diff --git a/examples/datadogagent/datadog-agent-minimum.yaml b/examples/datadogagent/datadog-agent-minimum.yaml index ad9603a82..73b54daa9 100644 --- a/examples/datadogagent/datadog-agent-minimum.yaml +++ b/examples/datadogagent/datadog-agent-minimum.yaml @@ -3,7 +3,57 @@ kind: DatadogAgent metadata: name: datadog spec: + override: + nodeAgent: + containers: + agent: + env: + - name: DD_HOSTNAME + value: "mack.test.node.name" global: + kubelet: + tlsVerify: false clusterName: my-example-cluster credentials: - apiKey: + apiKey: XXX + features: + otelAgent: + enabled: true + ports: + - containerPort: 4444 + name: otel-grpc + - containerPort: 3333 + name: otel-http + # conf: + # configMap: + # name: user-provided-config-map + # configData: |- + # receivers: + # otlp: + # protocols: + # grpc: + # http: + # exporters: + # debug: + # verbosity: detailed + # datadog: + # api: + # key: "" + # processors: + # batch: + # connectors: + # service: + # pipelines: + # traces: + # receivers: [otlp] + # processors: [batch] + # exporters: [datadog] + # metrics: + # receivers: [otlp] + # processors: [batch] + # exporters: [datadog] + # logs: + # receivers: [otlp] + # processors: [batch] + # exporters: [datadog] + diff --git a/internal/controller/datadogagent/component/agent/default.go b/internal/controller/datadogagent/component/agent/default.go index e16a9bb01..e1cce5596 100644 --- a/internal/controller/datadogagent/component/agent/default.go +++ b/internal/controller/datadogagent/component/agent/default.go @@ -104,6 +104,11 @@ func agentImage() string { return fmt.Sprintf("%s/%s:%s", v2alpha1.DefaultImageRegistry, v2alpha1.DefaultAgentImageName, defaulting.AgentLatestVersion) } +func otelAgentImage() string { + // todo(mackjmr): make this dynamic once we have a non-dev image. + return "datadog/agent-dev:nightly-ot-beta-main" +} + func initContainers(dda metav1.Object, requiredContainers []apicommon.AgentContainerName) []corev1.Container { initContainers := []corev1.Container{ initVolumeContainer(), @@ -201,29 +206,32 @@ func processAgentContainer(dda metav1.Object) corev1.Container { } } -func otelAgentContainer(dda metav1.Object) corev1.Container { +func otelAgentContainer(_ metav1.Object) corev1.Container { return corev1.Container{ Name: string(apicommon.OtelAgent), - Image: agentImage(), + Image: otelAgentImage(), Command: []string{ - "/otel-agent", - fmt.Sprintf("--config=%s", apicommon.OtelCustomConfigVolumePath), + "otel-agent", + "--config=" + apicommon.OtelCustomConfigVolumePath, + "--core-config=" + apicommon.AgentCustomConfigVolumePath, + "--sync-delay=10s", }, - Env: envVarsForOtelAgent(dda), + Env: []corev1.EnvVar{}, VolumeMounts: volumeMountsForOtelAgent(), Ports: []corev1.ContainerPort{ - { - Name: "grpc", - ContainerPort: 4317, - HostPort: 4317, - Protocol: corev1.ProtocolTCP, - }, - { - Name: "http", - ContainerPort: 4318, - HostPort: 4318, - Protocol: corev1.ProtocolTCP, - }, + // mackjmr(todo): this will break the annotations and flag + // { + // Name: "grpc", + // ContainerPort: 4317, + // HostPort: 4317, + // Protocol: corev1.ProtocolTCP, + // }, + // { + // Name: "http", + // ContainerPort: 4318, + // HostPort: 4318, + // Protocol: corev1.ProtocolTCP, + // }, }, } } @@ -397,23 +405,9 @@ func envVarsForSecurityAgent(dda metav1.Object) []corev1.EnvVar { return append(envs, commonEnvVars(dda)...) } -func envVarsForOtelAgent(dda metav1.Object) []corev1.EnvVar { - envs := []corev1.EnvVar{ - // TODO: add additional env vars here - } - - return append(envs, commonEnvVars(dda)...) -} - func volumeMountsForInitConfig() []corev1.VolumeMount { return []corev1.VolumeMount{ - common.GetVolumeMountForLogs(), - common.GetVolumeMountForChecksd(), - common.GetVolumeMountForAuth(false), - common.GetVolumeMountForConfd(), common.GetVolumeMountForConfig(), - common.GetVolumeMountForProc(), - common.GetVolumeMountForRuntimeSocket(true), } } @@ -507,13 +501,7 @@ func volumeMountsForSeccompSetup() []corev1.VolumeMount { func volumeMountsForOtelAgent() []corev1.VolumeMount { return []corev1.VolumeMount{ - // TODO: add/remove volume mounts - common.GetVolumeMountForLogs(), - common.GetVolumeMountForAuth(true), common.GetVolumeMountForConfig(), - common.GetVolumeMountForDogstatsdSocket(false), - common.GetVolumeMountForRuntimeSocket(true), - common.GetVolumeMountForProc(), } } diff --git a/internal/controller/datadogagent/controller.go b/internal/controller/datadogagent/controller.go index d498e6bef..e463aebd4 100644 --- a/internal/controller/datadogagent/controller.go +++ b/internal/controller/datadogagent/controller.go @@ -42,6 +42,7 @@ import ( _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/npm" _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/oomkill" _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/orchestratorexplorer" + _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelagent" _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otlp" _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/processdiscovery" _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/prometheusscrape" diff --git a/internal/controller/datadogagent/feature/ids.go b/internal/controller/datadogagent/feature/ids.go index 812a00a7b..b395d720d 100644 --- a/internal/controller/datadogagent/feature/ids.go +++ b/internal/controller/datadogagent/feature/ids.go @@ -25,6 +25,8 @@ const ( LiveContainerIDType = "live_container" // LiveProcessIDType Live Process feature. LiveProcessIDType = "live_process" + // OtelAgentIDType Otel Agent feature. + OtelAgentIDType = "otel_agent" // ProcessDiscoveryIDType Process Discovery feature. ProcessDiscoveryIDType = "process_discovery" // KubernetesAPIServerIDType Kube APIServer feature. diff --git a/internal/controller/datadogagent/feature/otelagent/configmap_test.go b/internal/controller/datadogagent/feature/otelagent/configmap_test.go new file mode 100644 index 000000000..0dedd0c9a --- /dev/null +++ b/internal/controller/datadogagent/feature/otelagent/configmap_test.go @@ -0,0 +1,43 @@ +// 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 otelagent + +import ( + "testing" + + "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelagent/defaultconfig" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func Test_otelAgent_buildOtelAgentConfigMap(t *testing.T) { + // check config map + configMapWant := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "-otel-agent-config", + }, + Data: map[string]string{ + "otel-config.yaml": defaultconfig.DefaultOtelCollectorConfig, + }, + } + + otelAgentFeature, ok := buildOtelAgentFeature(&feature.Options{}).(*otelAgentFeature) + assert.True(t, ok) + + otelAgentFeature.owner = &metav1.ObjectMeta{ + Name: "-otel-agent-config", + } + otelAgentFeature.configMapName = "-otel-agent-config" + otelAgentFeature.customConfig = &v2alpha1.CustomConfig{} + otelAgentFeature.customConfig.ConfigData = &defaultconfig.DefaultOtelCollectorConfig + + configMap, err := otelAgentFeature.buildOTelAgentCoreConfigMap() + assert.NoError(t, err) + assert.Equal(t, configMapWant, configMap) +} diff --git a/internal/controller/datadogagent/feature/otelagent/defaultconfig/defaultconfig.go b/internal/controller/datadogagent/feature/otelagent/defaultconfig/defaultconfig.go new file mode 100644 index 000000000..5ec9362ee --- /dev/null +++ b/internal/controller/datadogagent/feature/otelagent/defaultconfig/defaultconfig.go @@ -0,0 +1,49 @@ +// package defaultconfig exposes the otel-agent default config +package defaultconfig + +var DefaultOtelCollectorConfig = ` +receivers: + prometheus: + config: + scrape_configs: + - job_name: "otelcol" + scrape_interval: 10s + static_configs: + - targets: ["0.0.0.0:8888"] + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 +exporters: + debug: + verbosity: detailed + datadog: + api: + key: "" +processors: + infraattributes: + cardinality: 2 + batch: + timeout: 10s +connectors: + datadog/connector: + traces: + compute_top_level_by_span_kind: true + peer_tags_aggregation: true + compute_stats_by_span_kind: true +service: + pipelines: + traces: + receivers: [otlp] + processors: [infraattributes, batch] + exporters: [datadog, datadog/connector] + metrics: + receivers: [otlp, datadog/connector, prometheus] + processors: [infraattributes, batch] + exporters: [datadog] + logs: + receivers: [otlp] + processors: [infraattributes, batch] + exporters: [datadog]` diff --git a/internal/controller/datadogagent/feature/otelagent/feature.go b/internal/controller/datadogagent/feature/otelagent/feature.go new file mode 100644 index 000000000..a9253b67b --- /dev/null +++ b/internal/controller/datadogagent/feature/otelagent/feature.go @@ -0,0 +1,164 @@ +package otelagent + +import ( + "strconv" + "strings" + + apicommon "github.com/DataDog/datadog-operator/api/datadoghq/common" + "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1" + apiutils "github.com/DataDog/datadog-operator/api/utils" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelagent/defaultconfig" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/object/configmap" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/object/volume" + "github.com/DataDog/datadog-operator/pkg/kubernetes" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + otelAgentVolumeName = "otel-agent-config-volume" + otelConfigFileName = "otel-config.yaml" +) + +func init() { + err := feature.Register(feature.OtelAgentIDType, buildOtelAgentFeature) + if err != nil { + panic(err) + } +} + +func buildOtelAgentFeature(options *feature.Options) feature.Feature { + return &otelAgentFeature{} +} + +type otelAgentFeature struct { + customConfig *v2alpha1.CustomConfig + owner metav1.Object + configMapName string + ports []*corev1.ContainerPort +} + +func (o otelAgentFeature) ID() feature.IDType { + return feature.OtelAgentIDType +} + +func (o *otelAgentFeature) Configure(dda *v2alpha1.DatadogAgent) feature.RequiredComponents { + o.owner = dda + if dda.Spec.Features.OTelAgent.Conf != nil { + o.customConfig = dda.Spec.Features.OTelAgent.Conf + } + o.configMapName = v2alpha1.GetConfName(dda, o.customConfig, v2alpha1.DefaultOTelAgentConf) + + if len(dda.Spec.Features.OTelAgent.Ports) == 0 { + dda.Spec.Features.OTelAgent.Ports = []*corev1.ContainerPort{ + { + Name: "otel-http", + ContainerPort: 4318, + }, + { + Name: "otel-grpc", + ContainerPort: 4317, + }, + } + } + o.ports = dda.Spec.Features.OTelAgent.Ports + + var reqComp feature.RequiredComponents + if apiutils.BoolValue(dda.Spec.Features.OTelAgent.Enabled) { + reqComp = feature.RequiredComponents{ + Agent: feature.RequiredComponent{ + IsRequired: apiutils.NewBoolPointer(true), + Containers: []apicommon.AgentContainerName{ + apicommon.CoreAgentContainerName, + apicommon.OtelAgent, + }, + }, + } + + } + return reqComp +} + +func (o *otelAgentFeature) buildOTelAgentCoreConfigMap() (*corev1.ConfigMap, error) { + if o.customConfig != nil && o.customConfig.ConfigData != nil { + return configmap.BuildConfigMapConfigData(o.owner.GetNamespace(), o.customConfig.ConfigData, o.configMapName, otelConfigFileName) + } + return nil, nil +} + +func (o otelAgentFeature) ManageDependencies(managers feature.ResourceManagers, components feature.RequiredComponents) error { + // check if an otel collector config was provided. If not, use default. + if o.customConfig == nil { + o.customConfig = &v2alpha1.CustomConfig{} + } + if o.customConfig.ConfigData == nil && o.customConfig.ConfigMap == nil { + var defaultConfig = defaultconfig.DefaultOtelCollectorConfig + for _, port := range o.ports { + if port.Name == "otel-grpc" { + defaultConfig = strings.ReplaceAll(defaultConfig, "4317", strconv.Itoa(int(port.ContainerPort))) + } + if port.Name == "otel-http" { + defaultConfig = strings.ReplaceAll(defaultConfig, "4318", strconv.Itoa(int(port.ContainerPort))) + } + } + o.customConfig.ConfigData = &defaultConfig + } + + // create configMap if customConfig is provided + configMap, err := o.buildOTelAgentCoreConfigMap() + if err != nil { + return err + } + + if configMap != nil { + if err := managers.Store().AddOrUpdate(kubernetes.ConfigMapKind, configMap); err != nil { + return err + } + } + return nil +} + +func (o otelAgentFeature) ManageClusterAgent(managers feature.PodTemplateManagers) error { + return nil +} + +func (o otelAgentFeature) ManageNodeAgent(managers feature.PodTemplateManagers, provider string) error { + var vol corev1.Volume + if o.customConfig != nil && o.customConfig.ConfigMap != nil { + // Custom config is referenced via ConfigMap + vol = volume.GetVolumeFromConfigMap( + o.customConfig.ConfigMap, + o.configMapName, + otelAgentVolumeName, + ) + } else { + // Otherwise, configMap was created in ManageDependencies (whether from CustomConfig.ConfigData or using defaults, so mount default volume) + vol = volume.GetBasicVolume(o.configMapName, otelAgentVolumeName) + } + + // create volume + managers.Volume().AddVolume(&vol) + + // [investigation needed]: When the user provides a custom config map, the file name *must be* otel-config.yaml. If we choose to allow + // any file name, we would need to update both the volume mount here, as well as the otel-agent container command. I haven't seen this + // done for other containers, which is why I think it's acceptable to force users to use the `otel-config.yaml` name. + volMount := volume.GetVolumeMountWithSubPath(otelAgentVolumeName, apicommon.ConfigVolumePath+"/"+otelConfigFileName, otelConfigFileName) + managers.VolumeMount().AddVolumeMountToContainer(&volMount, apicommon.OtelAgent) + + // add ports + for _, port := range o.ports { + port.HostPort = port.ContainerPort + managers.Port().AddPortToContainer(apicommon.OtelAgent, port) + } + + return nil +} + +func (o otelAgentFeature) ManageSingleContainerNodeAgent(managers feature.PodTemplateManagers, provider string) error { + return nil +} + +func (o otelAgentFeature) ManageClusterChecksRunner(managers feature.PodTemplateManagers) error { + return nil +} diff --git a/internal/controller/datadogagent/feature/otelagent/feature_test.go b/internal/controller/datadogagent/feature/otelagent/feature_test.go new file mode 100644 index 000000000..cfc35bfea --- /dev/null +++ b/internal/controller/datadogagent/feature/otelagent/feature_test.go @@ -0,0 +1,201 @@ +package otelagent + +import ( + "strings" + "testing" + + apicommon "github.com/DataDog/datadog-operator/api/datadoghq/common" + v2alpha1test "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1/test" + apiutils "github.com/DataDog/datadog-operator/api/utils" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/fake" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelagent/defaultconfig" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/test" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/store" + "github.com/DataDog/datadog-operator/pkg/kubernetes" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" +) + +type expectedPorts struct { + httpPort int32 + grpcPort int32 +} + +var ( + defaultExpectedPorts = expectedPorts{ + httpPort: 4318, + grpcPort: 4317, + } + defaultLocalObjectReferenceName = "-otel-agent-config" +) + +func Test_otelAgentFeature_Configure(t *testing.T) { + tests := test.FeatureTestSuite{ + // disabled + { + Name: "otel agent disabled without config", + DDA: v2alpha1test.NewDatadogAgentBuilder(). + WithOTelAgentEnabled(false). + Build(), + WantConfigure: false, + }, + { + Name: "otel agent disabled with config", + DDA: v2alpha1test.NewDatadogAgentBuilder(). + WithOTelAgentEnabled(false). + WithOTelAgentConfig(). + Build(), + WantConfigure: false, + }, + // enabled + { + Name: "otel agent enabled with config", + DDA: v2alpha1test.NewDatadogAgentBuilder(). + WithOTelAgentEnabled(true). + WithOTelAgentConfig(). + Build(), + WantConfigure: true, + WantDependenciesFunc: testExpectedDepsCreatedCM, + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName), + }, + { + Name: "otel agent enabled with configMap", + DDA: v2alpha1test.NewDatadogAgentBuilder(). + WithOTelAgentEnabled(true). + WithOTelAgentConfigMap(). + Build(), + WantConfigure: true, + WantDependenciesFunc: testExpectedDepsCreatedCM, + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, "user-provided-config-map"), + }, + { + Name: "otel agent enabled without config", + DDA: v2alpha1test.NewDatadogAgentBuilder(). + WithOTelAgentEnabled(true). + Build(), + WantConfigure: true, + WantDependenciesFunc: testExpectedDepsCreatedCM, + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName), + }, + { + Name: "otel agent enabled without config non default ports", + DDA: v2alpha1test.NewDatadogAgentBuilder(). + WithOTelAgentEnabled(true). + WithOTelAgentPorts(4444, 5555). + Build(), + WantConfigure: true, + WantDependenciesFunc: testExpectedDepsCreatedCM, + Agent: testExpectedAgent(apicommon.OtelAgent, expectedPorts{ + grpcPort: 4444, + httpPort: 5555, + }, + defaultLocalObjectReferenceName, + ), + }, + } + + tests.Run(t, buildOtelAgentFeature) +} + +func testExpectedAgent(agentContainerName apicommon.AgentContainerName, expectedPorts expectedPorts, localObjectReferenceName string) *test.ComponentTest { + return test.NewDefaultComponentTest().WithWantFunc( + func(t testing.TB, mgrInterface feature.PodTemplateManagers) { + mgr := mgrInterface.(*fake.PodTemplateManagers) + // check volume mounts + wantVolumeMounts := []corev1.VolumeMount{ + { + Name: otelAgentVolumeName, + MountPath: apicommon.ConfigVolumePath + "/" + otelConfigFileName, + SubPath: otelConfigFileName, + ReadOnly: true, + }, + } + + agentMounts := mgr.VolumeMountMgr.VolumeMountsByC[agentContainerName] + assert.True(t, apiutils.IsEqualStruct(agentMounts, wantVolumeMounts), "%s volume mounts \ndiff = %s", agentContainerName, cmp.Diff(agentMounts, wantVolumeMounts)) + + var keyToPathSlice []corev1.KeyToPath + if localObjectReferenceName == "user-provided-config-map" { + keyToPathSlice = []corev1.KeyToPath{ + { + Key: "otel-config.yaml", + }, + } + } + // check volumes "otel-agent-config" + wantVolumes := []corev1.Volume{ + { + Name: otelAgentVolumeName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + // [investigation needed]: seems strange that + // the string is prefixed by `-`. + Name: localObjectReferenceName, + }, + Items: keyToPathSlice, + }, + }, + }, + } + + volumes := mgr.VolumeMgr.Volumes + assert.True(t, apiutils.IsEqualStruct(volumes, wantVolumes), "Volumes \ndiff = %s", cmp.Diff(volumes, wantVolumes)) + + // check ports + wantPorts := []*corev1.ContainerPort{ + { + Name: "otel-http", + ContainerPort: expectedPorts.httpPort, + HostPort: expectedPorts.httpPort, + }, + { + Name: "otel-grpc", + ContainerPort: expectedPorts.grpcPort, + HostPort: expectedPorts.grpcPort, + }, + } + + ports := mgr.PortMgr.PortsByC[agentContainerName] + assert.Equal(t, wantPorts, ports) + }, + ) +} + +func testExpectedDepsCreatedCM(t testing.TB, store store.StoreClient) { + // hacky to need to hardcode test name but unaware of a better approach that doesn't require + // modifying WantDependenciesFunc definition. + if t.Name() == "Test_otelAgentFeature_Configure/otel_agent_enabled_with_configMap" { + // configMap is provided by user, no need to create it. + _, found := store.Get(kubernetes.ConfigMapKind, "", "-otel-agent-config") + assert.False(t, found) + return + } + configMapObject, found := store.Get(kubernetes.ConfigMapKind, "", "-otel-agent-config") + assert.True(t, found) + + configMap := configMapObject.(*corev1.ConfigMap) + expectedCM := map[string]string{ + "otel-config.yaml": defaultconfig.DefaultOtelCollectorConfig} + + // validate that default ports were overriden by user provided ports in default config. hacky to need to + // hardcode test name but unaware of a better approach that doesn't require modifying WantDependenciesFunc definition. + if t.Name() == "Test_otelAgentFeature_Configure/otel_agent_enabled_without_config_non_default_ports" { + expectedCM["otel-config.yaml"] = strings.ReplaceAll(expectedCM["otel-config.yaml"], "4317", "4444") + expectedCM["otel-config.yaml"] = strings.ReplaceAll(expectedCM["otel-config.yaml"], "4318", "5555") + assert.True( + t, + apiutils.IsEqualStruct(configMap.Data, expectedCM), + "ConfigMap \ndiff = %s", cmp.Diff(configMap.Data, expectedCM), + ) + return + } + assert.True( + t, + apiutils.IsEqualStruct(configMap.Data, expectedCM), + "ConfigMap \ndiff = %s", cmp.Diff(configMap.Data, expectedCM), + ) +} From c20dc8c93efd0c36536f07c110afcac52766e91b Mon Sep 17 00:00:00 2001 From: mackjmr Date: Thu, 12 Dec 2024 10:32:08 +0100 Subject: [PATCH 02/28] update test --- api/datadoghq/v2alpha1/test/builder.go | 5 ----- .../datadogagent/feature/otelagent/feature_test.go | 11 ----------- 2 files changed, 16 deletions(-) diff --git a/api/datadoghq/v2alpha1/test/builder.go b/api/datadoghq/v2alpha1/test/builder.go index febd7cf06..97318fa74 100644 --- a/api/datadoghq/v2alpha1/test/builder.go +++ b/api/datadoghq/v2alpha1/test/builder.go @@ -399,11 +399,6 @@ func (builder *DatadogAgentBuilder) WithOTelAgentConfigMap() *DatadogAgentBuilde builder.datadogAgent.Spec.Features.OTelAgent.Conf = &v2alpha1.CustomConfig{} builder.datadogAgent.Spec.Features.OTelAgent.Conf.ConfigMap = &v2alpha1.ConfigMapConfig{ Name: "user-provided-config-map", - Items: []corev1.KeyToPath{ - { - Key: "otel-config.yaml", - }, - }, } return builder } diff --git a/internal/controller/datadogagent/feature/otelagent/feature_test.go b/internal/controller/datadogagent/feature/otelagent/feature_test.go index cfc35bfea..345e23be6 100644 --- a/internal/controller/datadogagent/feature/otelagent/feature_test.go +++ b/internal/controller/datadogagent/feature/otelagent/feature_test.go @@ -117,14 +117,6 @@ func testExpectedAgent(agentContainerName apicommon.AgentContainerName, expected agentMounts := mgr.VolumeMountMgr.VolumeMountsByC[agentContainerName] assert.True(t, apiutils.IsEqualStruct(agentMounts, wantVolumeMounts), "%s volume mounts \ndiff = %s", agentContainerName, cmp.Diff(agentMounts, wantVolumeMounts)) - var keyToPathSlice []corev1.KeyToPath - if localObjectReferenceName == "user-provided-config-map" { - keyToPathSlice = []corev1.KeyToPath{ - { - Key: "otel-config.yaml", - }, - } - } // check volumes "otel-agent-config" wantVolumes := []corev1.Volume{ { @@ -132,11 +124,8 @@ func testExpectedAgent(agentContainerName apicommon.AgentContainerName, expected VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ - // [investigation needed]: seems strange that - // the string is prefixed by `-`. Name: localObjectReferenceName, }, - Items: keyToPathSlice, }, }, }, From cb51682fccf6f8b827b99628fd884e5bcc6f88bd Mon Sep 17 00:00:00 2001 From: mackjmr Date: Thu, 12 Dec 2024 14:47:59 +0100 Subject: [PATCH 03/28] add port documentation --- api/datadoghq/v2alpha1/datadogagent_types.go | 6 ++++- .../v2alpha1/zz_generated.openapi.go | 4 +-- .../bases/v1/datadoghq.com_datadogagents.yaml | 12 +++++++-- .../datadoghq.com_datadogagents_v2alpha1.json | 8 +++--- config/manager/kustomization.yaml | 2 +- docs/configuration.v2alpha1.md | 2 +- .../datadogagent/datadog-agent-minimum.yaml | 8 +++--- .../datadogagent/component/agent/default.go | 25 +++++++++---------- .../datadogagent/feature/otelagent/feature.go | 4 +++ 9 files changed, 43 insertions(+), 28 deletions(-) diff --git a/api/datadoghq/v2alpha1/datadogagent_types.go b/api/datadoghq/v2alpha1/datadogagent_types.go index b6436e90c..c91b94cb0 100644 --- a/api/datadoghq/v2alpha1/datadogagent_types.go +++ b/api/datadoghq/v2alpha1/datadogagent_types.go @@ -694,11 +694,15 @@ type OTelAgentFeatureConfig struct { // Conf overrides the configuration for the default Kubernetes State Metrics Core check. // This must point to a ConfigMap containing a valid cluster check configuration. + // When passing a configmap, file name *must* be otel-config.yaml. // +optional Conf *CustomConfig `json:"conf,omitempty"` // Ports contains the ports for the otel-agent. - // Default: 4317/4318 + // Defaults: otel-grpc:4317 / otel-http:4318. Note: setting 4317 + // or 4318 manually is *only* supported if name match default names (otel-grpc, otel-http). + // If not, this will lead to a port conflict. + // This limitation will be lifted once annotations support is removed. // +optional Ports []*corev1.ContainerPort `json:"ports,omitempty"` } diff --git a/api/datadoghq/v2alpha1/zz_generated.openapi.go b/api/datadoghq/v2alpha1/zz_generated.openapi.go index a47d4a15c..defd0e386 100644 --- a/api/datadoghq/v2alpha1/zz_generated.openapi.go +++ b/api/datadoghq/v2alpha1/zz_generated.openapi.go @@ -1296,13 +1296,13 @@ func schema_datadog_operator_api_datadoghq_v2alpha1_OTelAgentFeatureConfig(ref c }, "conf": { SchemaProps: spec.SchemaProps{ - Description: "Conf overrides the configuration for the default Kubernetes State Metrics Core check. This must point to a ConfigMap containing a valid cluster check configuration.", + Description: "Conf overrides the configuration for the default Kubernetes State Metrics Core check. This must point to a ConfigMap containing a valid cluster check configuration. When passing a configmap, file name *must* be otel-config.yaml.", Ref: ref("github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CustomConfig"), }, }, "ports": { SchemaProps: spec.SchemaProps{ - Description: "Ports contains the ports for the otel-agent. Default: 4317/4318", + Description: "Ports contains the ports for the otel-agent. Defaults: otel-grpc:4317 / otel-http:4318. Note: setting 4317 or 4318 manually is *only* supported if name match default names (otel-grpc, otel-http). If not, this will lead to a port conflict. This limitation will be lifted once annotations support is removed.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ diff --git a/config/crd/bases/v1/datadoghq.com_datadogagents.yaml b/config/crd/bases/v1/datadoghq.com_datadogagents.yaml index 6c433ef29..e7684e7f0 100644 --- a/config/crd/bases/v1/datadoghq.com_datadogagents.yaml +++ b/config/crd/bases/v1/datadoghq.com_datadogagents.yaml @@ -1291,6 +1291,7 @@ spec: description: |- Conf overrides the configuration for the default Kubernetes State Metrics Core check. This must point to a ConfigMap containing a valid cluster check configuration. + When passing a configmap, file name *must* be otel-config.yaml. properties: configData: description: ConfigData corresponds to the configuration file content. @@ -1344,7 +1345,10 @@ spec: ports: description: |- Ports contains the ports for the otel-agent. - Default: 4317/4318 + Defaults: otel-grpc:4317 / otel-http:4318. Note: setting 4317 + or 4318 manually is *only* supported if name match default names (otel-grpc, otel-http). + If not, this will lead to a port conflict. + This limitation will be lifted once annotations support is removed. items: description: ContainerPort represents a network port in a single container. properties: @@ -8118,6 +8122,7 @@ spec: description: |- Conf overrides the configuration for the default Kubernetes State Metrics Core check. This must point to a ConfigMap containing a valid cluster check configuration. + When passing a configmap, file name *must* be otel-config.yaml. properties: configData: description: ConfigData corresponds to the configuration file content. @@ -8171,7 +8176,10 @@ spec: ports: description: |- Ports contains the ports for the otel-agent. - Default: 4317/4318 + Defaults: otel-grpc:4317 / otel-http:4318. Note: setting 4317 + or 4318 manually is *only* supported if name match default names (otel-grpc, otel-http). + If not, this will lead to a port conflict. + This limitation will be lifted once annotations support is removed. items: description: ContainerPort represents a network port in a single container. properties: diff --git a/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json b/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json index 60ee384e3..b51df6f14 100644 --- a/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json +++ b/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json @@ -1336,7 +1336,7 @@ "properties": { "conf": { "additionalProperties": false, - "description": "Conf overrides the configuration for the default Kubernetes State Metrics Core check.\nThis must point to a ConfigMap containing a valid cluster check configuration.", + "description": "Conf overrides the configuration for the default Kubernetes State Metrics Core check.\nThis must point to a ConfigMap containing a valid cluster check configuration.\nWhen passing a configmap, file name *must* be otel-config.yaml.", "properties": { "configData": { "description": "ConfigData corresponds to the configuration file content.", @@ -1393,7 +1393,7 @@ "type": "boolean" }, "ports": { - "description": "Ports contains the ports for the otel-agent.\nDefault: 4317/4318", + "description": "Ports contains the ports for the otel-agent.\nDefaults: otel-grpc:4317 / otel-http:4318. Note: setting 4317\nor 4318 manually is *only* supported if name match default names (otel-grpc, otel-http).\nIf not, this will lead to a port conflict.\nThis limitation will be lifted once annotations support is removed.", "items": { "additionalProperties": false, "description": "ContainerPort represents a network port in a single container.", @@ -8107,7 +8107,7 @@ "properties": { "conf": { "additionalProperties": false, - "description": "Conf overrides the configuration for the default Kubernetes State Metrics Core check.\nThis must point to a ConfigMap containing a valid cluster check configuration.", + "description": "Conf overrides the configuration for the default Kubernetes State Metrics Core check.\nThis must point to a ConfigMap containing a valid cluster check configuration.\nWhen passing a configmap, file name *must* be otel-config.yaml.", "properties": { "configData": { "description": "ConfigData corresponds to the configuration file content.", @@ -8164,7 +8164,7 @@ "type": "boolean" }, "ports": { - "description": "Ports contains the ports for the otel-agent.\nDefault: 4317/4318", + "description": "Ports contains the ports for the otel-agent.\nDefaults: otel-grpc:4317 / otel-http:4318. Note: setting 4317\nor 4318 manually is *only* supported if name match default names (otel-grpc, otel-http).\nIf not, this will lead to a port conflict.\nThis limitation will be lifted once annotations support is removed.", "items": { "additionalProperties": false, "description": "ContainerPort represents a network port in a single container.", diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index dab091ee7..24f10b283 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -3,6 +3,6 @@ resources: images: - name: controller newName: gcr.io/datadoghq/operator - newTag: v1.9.0-rc.3_6ff015ce + newTag: v1.9.0-rc.3_c20dc8c9 apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization diff --git a/docs/configuration.v2alpha1.md b/docs/configuration.v2alpha1.md index 07dc29548..463de5fa6 100644 --- a/docs/configuration.v2alpha1.md +++ b/docs/configuration.v2alpha1.md @@ -145,7 +145,7 @@ spec: | features.otelAgent.conf.configMap.items | Maps a ConfigMap data `key` to a file `path` mount. | | features.otelAgent.conf.configMap.name | Is the name of the ConfigMap. | | features.otelAgent.enabled | Enables the OTel Agent. Default: true | -| features.otelAgent.ports | Contains the ports for the otel-agent. Default: 4317/4318 | +| features.otelAgent.ports | Contains the ports for the otel-agent. Defaults: otel-grpc:4317 / otel-http:4318. Note: setting 4317 or 4318 manually is *only* supported if name match default names (otel-grpc, otel-http). If not, this will lead to a port conflict. This limitation will be lifted once annotations support is removed. | | features.otlp.receiver.protocols.grpc.enabled | Enable the OTLP/gRPC endpoint. Host port is enabled by default and can be disabled. | | features.otlp.receiver.protocols.grpc.endpoint | For OTLP/gRPC. gRPC supports several naming schemes: https://github.com/grpc/grpc/blob/master/doc/naming.md The Datadog Operator supports only 'host:port' (usually `0.0.0.0:port`). Default: `0.0.0.0:4317`. | | features.otlp.receiver.protocols.grpc.hostPortConfig.enabled | Enables host port configuration | diff --git a/examples/datadogagent/datadog-agent-minimum.yaml b/examples/datadogagent/datadog-agent-minimum.yaml index 73b54daa9..4657f3c82 100644 --- a/examples/datadogagent/datadog-agent-minimum.yaml +++ b/examples/datadogagent/datadog-agent-minimum.yaml @@ -20,10 +20,10 @@ spec: otelAgent: enabled: true ports: - - containerPort: 4444 - name: otel-grpc - - containerPort: 3333 - name: otel-http + # - containerPort: 4317 + # name: grpc + # - containerPort: 4318 + # name: http # conf: # configMap: # name: user-provided-config-map diff --git a/internal/controller/datadogagent/component/agent/default.go b/internal/controller/datadogagent/component/agent/default.go index e1cce5596..1578fb65c 100644 --- a/internal/controller/datadogagent/component/agent/default.go +++ b/internal/controller/datadogagent/component/agent/default.go @@ -219,19 +219,18 @@ func otelAgentContainer(_ metav1.Object) corev1.Container { Env: []corev1.EnvVar{}, VolumeMounts: volumeMountsForOtelAgent(), Ports: []corev1.ContainerPort{ - // mackjmr(todo): this will break the annotations and flag - // { - // Name: "grpc", - // ContainerPort: 4317, - // HostPort: 4317, - // Protocol: corev1.ProtocolTCP, - // }, - // { - // Name: "http", - // ContainerPort: 4318, - // HostPort: 4318, - // Protocol: corev1.ProtocolTCP, - // }, + { + Name: "otel-grpc", + ContainerPort: 4317, + HostPort: 4317, + Protocol: corev1.ProtocolTCP, + }, + { + Name: "otel-http", + ContainerPort: 4318, + HostPort: 4318, + Protocol: corev1.ProtocolTCP, + }, }, } } diff --git a/internal/controller/datadogagent/feature/otelagent/feature.go b/internal/controller/datadogagent/feature/otelagent/feature.go index a9253b67b..880d08eac 100644 --- a/internal/controller/datadogagent/feature/otelagent/feature.go +++ b/internal/controller/datadogagent/feature/otelagent/feature.go @@ -55,10 +55,14 @@ func (o *otelAgentFeature) Configure(dda *v2alpha1.DatadogAgent) feature.Require { Name: "otel-http", ContainerPort: 4318, + HostPort: 4318, + Protocol: corev1.ProtocolTCP, }, { Name: "otel-grpc", ContainerPort: 4317, + HostPort: 4317, + Protocol: corev1.ProtocolTCP, }, } } From b546ad5a285f5a711bb95bd8003b0db1208062c7 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Thu, 12 Dec 2024 16:16:43 +0100 Subject: [PATCH 04/28] remove flag support --- cmd/main.go | 3 --- config/manager/kustomization.yaml | 2 +- examples/datadogagent/datadog-agent-minimum.yaml | 10 ++++++---- .../controller/datadogagent/component/agent/default.go | 3 +++ internal/controller/datadogagent/controller.go | 2 -- .../datadogagent/feature/enabledefault/feature.go | 8 +------- .../datadogagent/feature/test/factory_test.go | 3 --- internal/controller/datadogagent/feature/types.go | 2 -- internal/controller/setup.go | 2 -- 9 files changed, 11 insertions(+), 24 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 5fe587c12..82201d7ad 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -123,7 +123,6 @@ type options struct { introspectionEnabled bool datadogAgentProfileEnabled bool remoteConfigEnabled bool - otelAgentEnabled bool datadogDashboardEnabled bool // Secret Backend options @@ -157,7 +156,6 @@ func (opts *options) Parse() { flag.BoolVar(&opts.introspectionEnabled, "introspectionEnabled", false, "Enable introspection (beta)") flag.BoolVar(&opts.datadogAgentProfileEnabled, "datadogAgentProfileEnabled", false, "Enable DatadogAgentProfile controller (beta)") flag.BoolVar(&opts.remoteConfigEnabled, "remoteConfigEnabled", false, "Enable RemoteConfig capabilities in the Operator (beta)") - flag.BoolVar(&opts.otelAgentEnabled, "otelAgentEnabled", false, "Enable the OTel agent container (beta)") flag.BoolVar(&opts.datadogDashboardEnabled, "datadogDashboardEnabled", false, "Enable the DatadogDashboard controller") // ExtendedDaemonset configuration @@ -301,7 +299,6 @@ func run(opts *options) error { V2APIEnabled: true, IntrospectionEnabled: opts.introspectionEnabled, DatadogAgentProfileEnabled: opts.datadogAgentProfileEnabled, - OtelAgentEnabled: opts.otelAgentEnabled, DatadogDashboardEnabled: opts.datadogDashboardEnabled, } diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 24f10b283..7163ba39a 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -3,6 +3,6 @@ resources: images: - name: controller newName: gcr.io/datadoghq/operator - newTag: v1.9.0-rc.3_c20dc8c9 + newTag: v1.9.0-rc.3_cb51682f apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization diff --git a/examples/datadogagent/datadog-agent-minimum.yaml b/examples/datadogagent/datadog-agent-minimum.yaml index 4657f3c82..a69b08222 100644 --- a/examples/datadogagent/datadog-agent-minimum.yaml +++ b/examples/datadogagent/datadog-agent-minimum.yaml @@ -2,6 +2,8 @@ apiVersion: datadoghq.com/v2alpha1 kind: DatadogAgent metadata: name: datadog + annotations: + agent.datadoghq.com/otel-agent-enabled: "true" spec: override: nodeAgent: @@ -16,10 +18,10 @@ spec: clusterName: my-example-cluster credentials: apiKey: XXX - features: - otelAgent: - enabled: true - ports: + # features: + # otelAgent: + # enabled: true + # ports: # - containerPort: 4317 # name: grpc # - containerPort: 4318 diff --git a/internal/controller/datadogagent/component/agent/default.go b/internal/controller/datadogagent/component/agent/default.go index 1578fb65c..5fbcc007a 100644 --- a/internal/controller/datadogagent/component/agent/default.go +++ b/internal/controller/datadogagent/component/agent/default.go @@ -218,6 +218,9 @@ func otelAgentContainer(_ metav1.Object) corev1.Container { }, Env: []corev1.EnvVar{}, VolumeMounts: volumeMountsForOtelAgent(), + // todo(mackjmr): remove once support for annotations is removed. + // the otel-agent feature adds these ports if none are supplied by + // the user. Ports: []corev1.ContainerPort{ { Name: "otel-grpc", diff --git a/internal/controller/datadogagent/controller.go b/internal/controller/datadogagent/controller.go index e463aebd4..79fd0623c 100644 --- a/internal/controller/datadogagent/controller.go +++ b/internal/controller/datadogagent/controller.go @@ -64,7 +64,6 @@ type ReconcilerOptions struct { OperatorMetricsEnabled bool IntrospectionEnabled bool DatadogAgentProfileEnabled bool - OtelAgentEnabled bool } // Reconciler is the internal reconciler for Datadog Agent @@ -108,7 +107,6 @@ func reconcilerOptionsToFeatureOptions(opts *ReconcilerOptions, logger logr.Logg return &feature.Options{ SupportExtendedDaemonset: opts.ExtendedDaemonsetOptions.Enabled, Logger: logger, - OtelAgentEnabled: opts.OtelAgentEnabled, } } diff --git a/internal/controller/datadogagent/feature/enabledefault/feature.go b/internal/controller/datadogagent/feature/enabledefault/feature.go index 762decf48..e8b6f4e5d 100644 --- a/internal/controller/datadogagent/feature/enabledefault/feature.go +++ b/internal/controller/datadogagent/feature/enabledefault/feature.go @@ -52,7 +52,6 @@ func buildDefaultFeature(options *feature.Options) feature.Feature { if options != nil { dF.logger = options.Logger - dF.otelAgentEnabled = options.OtelAgentEnabled } return dF @@ -68,7 +67,6 @@ type defaultFeature struct { clusterChecksRunner clusterChecksRunnerConfig logger logr.Logger disableNonResourceRules bool - otelAgentEnabled bool adpEnabled bool customConfigAnnotationKey string @@ -134,10 +132,6 @@ func (f *defaultFeature) Configure(dda *v2alpha1.DatadogAgent) feature.RequiredC f.agent.serviceAccountAnnotations = v2alpha1.GetAgentServiceAccountAnnotations(dda) f.clusterChecksRunner.serviceAccountAnnotations = v2alpha1.GetClusterChecksRunnerServiceAccountAnnotations(dda) - if dda.ObjectMeta.Annotations != nil { - f.otelAgentEnabled = f.otelAgentEnabled || featureutils.HasOtelAgentAnnotation(dda) - } - if dda.ObjectMeta.Annotations != nil { f.adpEnabled = featureutils.HasAgentDataPlaneAnnotation(dda) } @@ -216,7 +210,7 @@ func (f *defaultFeature) Configure(dda *v2alpha1.DatadogAgent) feature.RequiredC // feature. // // NOTE: This is a temporary solution until the OTel Agent is fully integrated into the Operator via a dedicated feature. - if f.otelAgentEnabled { + if dda.ObjectMeta.Annotations != nil && featureutils.HasOtelAgentAnnotation(dda) { agentContainers = append(agentContainers, apicommon.OtelAgent) } diff --git a/internal/controller/datadogagent/feature/test/factory_test.go b/internal/controller/datadogagent/feature/test/factory_test.go index 0ef867e9d..d0e387987 100644 --- a/internal/controller/datadogagent/feature/test/factory_test.go +++ b/internal/controller/datadogagent/feature/test/factory_test.go @@ -200,9 +200,6 @@ func TestBuilder(t *testing.T) { dda: v2alpha1test.NewDatadogAgentBuilder(). WithAnnotations(map[string]string{"agent.datadoghq.com/otel-agent-enabled": "false"}). BuildWithDefaults(), - featureOptions: feature.Options{ - OtelAgentEnabled: true, - }, wantAgentContainer: map[common.AgentContainerName]bool{ common.UnprivilegedSingleAgentContainerName: false, common.CoreAgentContainerName: true, diff --git a/internal/controller/datadogagent/feature/types.go b/internal/controller/datadogagent/feature/types.go index 04767246d..c0d34f177 100644 --- a/internal/controller/datadogagent/feature/types.go +++ b/internal/controller/datadogagent/feature/types.go @@ -150,8 +150,6 @@ type Options struct { SupportExtendedDaemonset bool Logger logr.Logger - - OtelAgentEnabled bool } // BuildFunc function type used by each Feature during its factory registration. diff --git a/internal/controller/setup.go b/internal/controller/setup.go index b7e580fc9..7f3eef8af 100644 --- a/internal/controller/setup.go +++ b/internal/controller/setup.go @@ -47,7 +47,6 @@ type SetupOptions struct { V2APIEnabled bool IntrospectionEnabled bool DatadogAgentProfileEnabled bool - OtelAgentEnabled bool DatadogDashboardEnabled bool } @@ -160,7 +159,6 @@ func startDatadogAgent(logger logr.Logger, mgr manager.Manager, pInfo kubernetes OperatorMetricsEnabled: options.OperatorMetricsEnabled, IntrospectionEnabled: options.IntrospectionEnabled, DatadogAgentProfileEnabled: options.DatadogAgentProfileEnabled, - OtelAgentEnabled: options.OtelAgentEnabled, }, }).SetupWithManager(mgr, metricForwardersMgr) } From d5a8cdf3f0fbb62dec9dcaa1f080746d5dd411cf Mon Sep 17 00:00:00 2001 From: mackjmr Date: Thu, 12 Dec 2024 16:24:16 +0100 Subject: [PATCH 05/28] add examples --- .../datadogagent/datadog-agent-minimum.yaml | 54 +------------------ ...tadog-agent-with-otel-agent-configmap.yaml | 26 ++++++++- .../datadog-agent-with-otel-agent.yaml | 48 +++++++++++++++++ .../datadogagent/feature/otelagent/feature.go | 1 + 4 files changed, 74 insertions(+), 55 deletions(-) rename configmap.yaml => examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml (54%) create mode 100644 examples/datadogagent/datadog-agent-with-otel-agent.yaml diff --git a/examples/datadogagent/datadog-agent-minimum.yaml b/examples/datadogagent/datadog-agent-minimum.yaml index a69b08222..26b81b9f4 100644 --- a/examples/datadogagent/datadog-agent-minimum.yaml +++ b/examples/datadogagent/datadog-agent-minimum.yaml @@ -2,60 +2,8 @@ apiVersion: datadoghq.com/v2alpha1 kind: DatadogAgent metadata: name: datadog - annotations: - agent.datadoghq.com/otel-agent-enabled: "true" spec: - override: - nodeAgent: - containers: - agent: - env: - - name: DD_HOSTNAME - value: "mack.test.node.name" global: - kubelet: - tlsVerify: false clusterName: my-example-cluster credentials: - apiKey: XXX - # features: - # otelAgent: - # enabled: true - # ports: - # - containerPort: 4317 - # name: grpc - # - containerPort: 4318 - # name: http - # conf: - # configMap: - # name: user-provided-config-map - # configData: |- - # receivers: - # otlp: - # protocols: - # grpc: - # http: - # exporters: - # debug: - # verbosity: detailed - # datadog: - # api: - # key: "" - # processors: - # batch: - # connectors: - # service: - # pipelines: - # traces: - # receivers: [otlp] - # processors: [batch] - # exporters: [datadog] - # metrics: - # receivers: [otlp] - # processors: [batch] - # exporters: [datadog] - # logs: - # receivers: [otlp] - # processors: [batch] - # exporters: [datadog] - + apiKey: \ No newline at end of file diff --git a/configmap.yaml b/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml similarity index 54% rename from configmap.yaml rename to examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml index 95f660fb5..8f5deee7c 100644 --- a/configmap.yaml +++ b/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml @@ -1,9 +1,31 @@ +apiVersion: datadoghq.com/v2alpha1 +kind: DatadogAgent +metadata: + name: datadog + annotations: + agent.datadoghq.com/otel-agent-enabled: "true" +spec: + credentials: + apiKey: + features: + otelAgent: + enabled: true + ports: + - containerPort: 4317 + name: otel-grpc + - containerPort: 4318 + name: otel-http + conf: + configMap: + name: custom-config-map +--- apiVersion: v1 kind: ConfigMap metadata: - name: user-provided-config-map + name: custom-config-map namespace: system data: + # must be named otel-config.yaml. otel-config.yaml: |- receivers: otlp: @@ -15,7 +37,7 @@ data: verbosity: detailed datadog: api: - key: "" + key: processors: batch: connectors: diff --git a/examples/datadogagent/datadog-agent-with-otel-agent.yaml b/examples/datadogagent/datadog-agent-with-otel-agent.yaml new file mode 100644 index 000000000..a727294cc --- /dev/null +++ b/examples/datadogagent/datadog-agent-with-otel-agent.yaml @@ -0,0 +1,48 @@ +apiVersion: datadoghq.com/v2alpha1 +kind: DatadogAgent +metadata: + name: datadog + annotations: + agent.datadoghq.com/otel-agent-enabled: "true" +spec: + credentials: + apiKey: + features: + otelAgent: + enabled: true + ports: + - containerPort: 4317 + name: otel-grpc + - containerPort: 4318 + name: otel-http + conf: + configData: |- + receivers: + otlp: + protocols: + grpc: + http: + exporters: + debug: + verbosity: detailed + datadog: + api: + key: "" + processors: + batch: + connectors: + service: + pipelines: + traces: + receivers: [otlp] + processors: [batch] + exporters: [datadog] + metrics: + receivers: [otlp] + processors: [batch] + exporters: [datadog] + logs: + receivers: [otlp] + processors: [batch] + exporters: [datadog] + diff --git a/internal/controller/datadogagent/feature/otelagent/feature.go b/internal/controller/datadogagent/feature/otelagent/feature.go index 880d08eac..79107bd00 100644 --- a/internal/controller/datadogagent/feature/otelagent/feature.go +++ b/internal/controller/datadogagent/feature/otelagent/feature.go @@ -152,6 +152,7 @@ func (o otelAgentFeature) ManageNodeAgent(managers feature.PodTemplateManagers, // add ports for _, port := range o.ports { + // bind container port to host port. port.HostPort = port.ContainerPort managers.Port().AddPortToContainer(apicommon.OtelAgent, port) } From cc036f71106426361b1960b14bd64010724a6562 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Thu, 12 Dec 2024 16:38:40 +0100 Subject: [PATCH 06/28] fix --- Makefile | 2 +- internal/controller/datadogagent/feature/otelagent/feature.go | 2 +- .../controller/datadogagent/feature/otelagent/feature_test.go | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 7fc761a9d..d36506393 100644 --- a/Makefile +++ b/Makefile @@ -132,7 +132,7 @@ uninstall: manifests $(KUSTOMIZE) ## Uninstall CRDs from a cluster .PHONY: deploy deploy: manifests $(KUSTOMIZE) ## Deploy controller in the configured Kubernetes cluster in ~/.kube/config - cd config/manager && $(ROOT)/$(KUSTOMIZE) edit set image controller=$(IMG) + cd config/manager && $(ROOT)/$(KUSTOMIZE) edit set image controller=$(subst operator:v,operator:,$(IMG)) $(KUSTOMIZE) build $(KUSTOMIZE_CONFIG) | kubectl apply --force-conflicts --server-side -f - .PHONY: undeploy diff --git a/internal/controller/datadogagent/feature/otelagent/feature.go b/internal/controller/datadogagent/feature/otelagent/feature.go index 79107bd00..45a599600 100644 --- a/internal/controller/datadogagent/feature/otelagent/feature.go +++ b/internal/controller/datadogagent/feature/otelagent/feature.go @@ -147,7 +147,7 @@ func (o otelAgentFeature) ManageNodeAgent(managers feature.PodTemplateManagers, // [investigation needed]: When the user provides a custom config map, the file name *must be* otel-config.yaml. If we choose to allow // any file name, we would need to update both the volume mount here, as well as the otel-agent container command. I haven't seen this // done for other containers, which is why I think it's acceptable to force users to use the `otel-config.yaml` name. - volMount := volume.GetVolumeMountWithSubPath(otelAgentVolumeName, apicommon.ConfigVolumePath+"/"+otelConfigFileName, otelConfigFileName) + volMount := volume.GetVolumeMountWithSubPath(otelAgentVolumeName, v2alpha1.ConfigVolumePath+"/"+otelConfigFileName, otelConfigFileName) managers.VolumeMount().AddVolumeMountToContainer(&volMount, apicommon.OtelAgent) // add ports diff --git a/internal/controller/datadogagent/feature/otelagent/feature_test.go b/internal/controller/datadogagent/feature/otelagent/feature_test.go index 345e23be6..3102b96e7 100644 --- a/internal/controller/datadogagent/feature/otelagent/feature_test.go +++ b/internal/controller/datadogagent/feature/otelagent/feature_test.go @@ -5,6 +5,7 @@ import ( "testing" apicommon "github.com/DataDog/datadog-operator/api/datadoghq/common" + "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1" v2alpha1test "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1/test" apiutils "github.com/DataDog/datadog-operator/api/utils" "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature" @@ -108,7 +109,7 @@ func testExpectedAgent(agentContainerName apicommon.AgentContainerName, expected wantVolumeMounts := []corev1.VolumeMount{ { Name: otelAgentVolumeName, - MountPath: apicommon.ConfigVolumePath + "/" + otelConfigFileName, + MountPath: v2alpha1.ConfigVolumePath + "/" + otelConfigFileName, SubPath: otelConfigFileName, ReadOnly: true, }, From 7a522c536cf7119920a329e2c174fe9044f6c576 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Thu, 12 Dec 2024 16:41:23 +0100 Subject: [PATCH 07/28] fix examples --- .../datadogagent/datadog-agent-with-otel-agent-configmap.yaml | 2 -- examples/datadogagent/datadog-agent-with-otel-agent.yaml | 2 -- 2 files changed, 4 deletions(-) diff --git a/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml b/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml index 8f5deee7c..b2f26d0cf 100644 --- a/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml +++ b/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml @@ -2,8 +2,6 @@ apiVersion: datadoghq.com/v2alpha1 kind: DatadogAgent metadata: name: datadog - annotations: - agent.datadoghq.com/otel-agent-enabled: "true" spec: credentials: apiKey: diff --git a/examples/datadogagent/datadog-agent-with-otel-agent.yaml b/examples/datadogagent/datadog-agent-with-otel-agent.yaml index a727294cc..53d5d7c2a 100644 --- a/examples/datadogagent/datadog-agent-with-otel-agent.yaml +++ b/examples/datadogagent/datadog-agent-with-otel-agent.yaml @@ -2,8 +2,6 @@ apiVersion: datadoghq.com/v2alpha1 kind: DatadogAgent metadata: name: datadog - annotations: - agent.datadoghq.com/otel-agent-enabled: "true" spec: credentials: apiKey: From fe61d962509acf14efa07a73d1993b3252f61fc6 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Thu, 12 Dec 2024 17:13:08 +0100 Subject: [PATCH 08/28] fix --- internal/controller/datadogagent/component/agent/default.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/controller/datadogagent/component/agent/default.go b/internal/controller/datadogagent/component/agent/default.go index 4465bdd9b..cb2502a3c 100644 --- a/internal/controller/datadogagent/component/agent/default.go +++ b/internal/controller/datadogagent/component/agent/default.go @@ -212,8 +212,8 @@ func otelAgentContainer(_ metav1.Object) corev1.Container { Image: otelAgentImage(), Command: []string{ "otel-agent", - "--config=" + apicommon.OtelCustomConfigVolumePath, - "--core-config=" + apicommon.AgentCustomConfigVolumePath, + "--config=" + v2alpha1.OtelCustomConfigVolumePath, + "--core-config=" + v2alpha1.AgentCustomConfigVolumePath, "--sync-delay=10s", }, Env: []corev1.EnvVar{}, From cf17884f6cfe978f858db959fce8f5993efdbb93 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Thu, 12 Dec 2024 17:25:19 +0100 Subject: [PATCH 09/28] fix test --- api/datadoghq/v2alpha1/test/builder.go | 2 ++ .../controller/datadogagent/feature/otelagent/feature_test.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/api/datadoghq/v2alpha1/test/builder.go b/api/datadoghq/v2alpha1/test/builder.go index 97318fa74..f600aeeb3 100644 --- a/api/datadoghq/v2alpha1/test/builder.go +++ b/api/datadoghq/v2alpha1/test/builder.go @@ -408,10 +408,12 @@ func (builder *DatadogAgentBuilder) WithOTelAgentPorts(grpcPort int32, httpPort { Name: "otel-http", ContainerPort: httpPort, + Protocol: corev1.ProtocolTCP, }, { Name: "otel-grpc", ContainerPort: grpcPort, + Protocol: corev1.ProtocolTCP, }, } return builder diff --git a/internal/controller/datadogagent/feature/otelagent/feature_test.go b/internal/controller/datadogagent/feature/otelagent/feature_test.go index 3102b96e7..3de971e21 100644 --- a/internal/controller/datadogagent/feature/otelagent/feature_test.go +++ b/internal/controller/datadogagent/feature/otelagent/feature_test.go @@ -141,11 +141,13 @@ func testExpectedAgent(agentContainerName apicommon.AgentContainerName, expected Name: "otel-http", ContainerPort: expectedPorts.httpPort, HostPort: expectedPorts.httpPort, + Protocol: corev1.ProtocolTCP, }, { Name: "otel-grpc", ContainerPort: expectedPorts.grpcPort, HostPort: expectedPorts.grpcPort, + Protocol: corev1.ProtocolTCP, }, } From 2a962e8a13e51d34aba219de75ff9b3a6d29df1b Mon Sep 17 00:00:00 2001 From: mackjmr Date: Fri, 13 Dec 2024 10:59:22 +0100 Subject: [PATCH 10/28] rename feature from otelAgent to otelCollector --- api/datadoghq/v2alpha1/datadogagent_types.go | 2 +- api/datadoghq/v2alpha1/zz_generated.openapi.go | 2 +- config/crd/bases/v1/datadoghq.com_datadogagents.yaml | 4 ++-- .../bases/v1/datadoghq.com_datadogagents_v2alpha1.json | 4 ++-- docs/configuration.v2alpha1.md | 10 +++++----- .../datadog-agent-with-otel-agent-configmap.yaml | 2 +- .../datadogagent/datadog-agent-with-otel-agent.yaml | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/api/datadoghq/v2alpha1/datadogagent_types.go b/api/datadoghq/v2alpha1/datadogagent_types.go index f13f1f679..0c5de536b 100644 --- a/api/datadoghq/v2alpha1/datadogagent_types.go +++ b/api/datadoghq/v2alpha1/datadogagent_types.go @@ -45,7 +45,7 @@ type DatadogFeatures struct { // Application-level features // OTelAgent configuration. - OTelAgent *OTelAgentFeatureConfig `json:"otelAgent,omitempty"` + OTelAgent *OTelAgentFeatureConfig `json:"otelCollector,omitempty"` // LogCollection configuration. LogCollection *LogCollectionFeatureConfig `json:"logCollection,omitempty"` // LiveProcessCollection configuration. diff --git a/api/datadoghq/v2alpha1/zz_generated.openapi.go b/api/datadoghq/v2alpha1/zz_generated.openapi.go index defd0e386..1a520789e 100644 --- a/api/datadoghq/v2alpha1/zz_generated.openapi.go +++ b/api/datadoghq/v2alpha1/zz_generated.openapi.go @@ -526,7 +526,7 @@ func schema_datadog_operator_api_datadoghq_v2alpha1_DatadogFeatures(ref common.R Description: "DatadogFeatures are features running on the Agent and Cluster Agent.", Type: []string{"object"}, Properties: map[string]spec.Schema{ - "otelAgent": { + "otelCollector": { SchemaProps: spec.SchemaProps{ Description: "OTelAgent configuration.", Ref: ref("github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTelAgentFeatureConfig"), diff --git a/config/crd/bases/v1/datadoghq.com_datadogagents.yaml b/config/crd/bases/v1/datadoghq.com_datadogagents.yaml index 511526bc4..da9e55e3a 100644 --- a/config/crd/bases/v1/datadoghq.com_datadogagents.yaml +++ b/config/crd/bases/v1/datadoghq.com_datadogagents.yaml @@ -1284,7 +1284,7 @@ spec: Default: true type: boolean type: object - otelAgent: + otelCollector: description: OTelAgent configuration. properties: conf: @@ -8121,7 +8121,7 @@ spec: Default: true type: boolean type: object - otelAgent: + otelCollector: description: OTelAgent configuration. properties: conf: diff --git a/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json b/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json index 692d831ff..864bcc562 100644 --- a/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json +++ b/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json @@ -1330,7 +1330,7 @@ }, "type": "object" }, - "otelAgent": { + "otelCollector": { "additionalProperties": false, "description": "OTelAgent configuration.", "properties": { @@ -8105,7 +8105,7 @@ }, "type": "object" }, - "otelAgent": { + "otelCollector": { "additionalProperties": false, "description": "OTelAgent configuration.", "properties": { diff --git a/docs/configuration.v2alpha1.md b/docs/configuration.v2alpha1.md index ccb382181..15ce49c51 100644 --- a/docs/configuration.v2alpha1.md +++ b/docs/configuration.v2alpha1.md @@ -141,11 +141,11 @@ spec: | features.orchestratorExplorer.enabled | Enables the Orchestrator Explorer. Default: true | | features.orchestratorExplorer.extraTags | Additional tags to associate with the collected data in the form of `a b c`. This is a Cluster Agent option distinct from DD_TAGS that is used in the Orchestrator Explorer. | | features.orchestratorExplorer.scrubContainers | ScrubContainers enables scrubbing of sensitive container data (passwords, tokens, etc. ). Default: true | -| features.otelAgent.conf.configData | ConfigData corresponds to the configuration file content. | -| features.otelAgent.conf.configMap.items | Maps a ConfigMap data `key` to a file `path` mount. | -| features.otelAgent.conf.configMap.name | Is the name of the ConfigMap. | -| features.otelAgent.enabled | Enables the OTel Agent. Default: true | -| features.otelAgent.ports | Contains the ports for the otel-agent. Defaults: otel-grpc:4317 / otel-http:4318. Note: setting 4317 or 4318 manually is *only* supported if name match default names (otel-grpc, otel-http). If not, this will lead to a port conflict. This limitation will be lifted once annotations support is removed. | +| features.otelCollector.conf.configData | ConfigData corresponds to the configuration file content. | +| features.otelCollector.conf.configMap.items | Maps a ConfigMap data `key` to a file `path` mount. | +| features.otelCollector.conf.configMap.name | Is the name of the ConfigMap. | +| features.otelCollector.enabled | Enables the OTel Agent. Default: true | +| features.otelCollector.ports | Contains the ports for the otel-agent. Defaults: otel-grpc:4317 / otel-http:4318. Note: setting 4317 or 4318 manually is *only* supported if name match default names (otel-grpc, otel-http). If not, this will lead to a port conflict. This limitation will be lifted once annotations support is removed. | | features.otlp.receiver.protocols.grpc.enabled | Enable the OTLP/gRPC endpoint. Host port is enabled by default and can be disabled. | | features.otlp.receiver.protocols.grpc.endpoint | For OTLP/gRPC. gRPC supports several naming schemes: https://github.com/grpc/grpc/blob/master/doc/naming.md The Datadog Operator supports only 'host:port' (usually `0.0.0.0:port`). Default: `0.0.0.0:4317`. | | features.otlp.receiver.protocols.grpc.hostPortConfig.enabled | Enables host port configuration | diff --git a/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml b/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml index b2f26d0cf..1b737f2f7 100644 --- a/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml +++ b/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml @@ -6,7 +6,7 @@ spec: credentials: apiKey: features: - otelAgent: + otelCollector: enabled: true ports: - containerPort: 4317 diff --git a/examples/datadogagent/datadog-agent-with-otel-agent.yaml b/examples/datadogagent/datadog-agent-with-otel-agent.yaml index 53d5d7c2a..d7fbf426e 100644 --- a/examples/datadogagent/datadog-agent-with-otel-agent.yaml +++ b/examples/datadogagent/datadog-agent-with-otel-agent.yaml @@ -6,7 +6,7 @@ spec: credentials: apiKey: features: - otelAgent: + otelCollector: enabled: true ports: - containerPort: 4317 From 06a9f7d888c1f86a61cca7255ff0316be7d32e5e Mon Sep 17 00:00:00 2001 From: mackjmr Date: Fri, 13 Dec 2024 11:11:35 +0100 Subject: [PATCH 11/28] rename --- .../v2alpha1/datadogagent_default.go | 10 +-- api/datadoghq/v2alpha1/datadogagent_types.go | 8 +- api/datadoghq/v2alpha1/test/builder.go | 28 +++--- .../v2alpha1/zz_generated.deepcopy.go | 78 ++++++++-------- .../v2alpha1/zz_generated.openapi.go | 90 +++++++++---------- .../bases/v1/datadoghq.com_datadogagents.yaml | 4 +- .../datadoghq.com_datadogagents_v2alpha1.json | 4 +- .../feature/otelagent/configmap_test.go | 14 +-- .../datadogagent/feature/otelagent/feature.go | 36 ++++---- .../feature/otelagent/feature_test.go | 22 ++--- 10 files changed, 147 insertions(+), 147 deletions(-) diff --git a/api/datadoghq/v2alpha1/datadogagent_default.go b/api/datadoghq/v2alpha1/datadogagent_default.go index c20c34a2c..3505d5afa 100644 --- a/api/datadoghq/v2alpha1/datadogagent_default.go +++ b/api/datadoghq/v2alpha1/datadogagent_default.go @@ -25,7 +25,7 @@ const ( defaultLogPodLogsPath string = "/var/log/pods" defaultLogContainerSymlinksPath string = "/var/log/containers" - defaultOtelAgentEnabled bool = false + defaultOtelCollectorEnabled bool = false defaultLiveProcessCollectionEnabled bool = false defaultLiveContainerCollectionEnabled bool = true defaultProcessDiscoveryEnabled bool = true @@ -220,11 +220,11 @@ func defaultFeaturesConfig(ddaSpec *DatadogAgentSpec) { } apiutils.DefaultBooleanIfUnset(&ddaSpec.Features.LiveContainerCollection.Enabled, defaultLiveContainerCollectionEnabled) - // OTelAgent Feature - if ddaSpec.Features.OTelAgent == nil { - ddaSpec.Features.OTelAgent = &OTelAgentFeatureConfig{} + // OTelCollector Feature + if ddaSpec.Features.OtelCollector == nil { + ddaSpec.Features.OtelCollector = &OtelCollectorFeatureConfig{} } - apiutils.DefaultBooleanIfUnset(&ddaSpec.Features.OTelAgent.Enabled, defaultOtelAgentEnabled) + apiutils.DefaultBooleanIfUnset(&ddaSpec.Features.OtelCollector.Enabled, defaultOtelCollectorEnabled) // LiveProcessCollection Feature if ddaSpec.Features.LiveProcessCollection == nil { diff --git a/api/datadoghq/v2alpha1/datadogagent_types.go b/api/datadoghq/v2alpha1/datadogagent_types.go index 0c5de536b..6ec5ca481 100644 --- a/api/datadoghq/v2alpha1/datadogagent_types.go +++ b/api/datadoghq/v2alpha1/datadogagent_types.go @@ -44,8 +44,8 @@ type DatadogAgentSpec struct { type DatadogFeatures struct { // Application-level features - // OTelAgent configuration. - OTelAgent *OTelAgentFeatureConfig `json:"otelCollector,omitempty"` + // OtelCollector configuration. + OtelCollector *OtelCollectorFeatureConfig `json:"otelCollector,omitempty"` // LogCollection configuration. LogCollection *LogCollectionFeatureConfig `json:"logCollection,omitempty"` // LiveProcessCollection configuration. @@ -684,9 +684,9 @@ type KubeStateMetricsCoreFeatureConfig struct { Conf *CustomConfig `json:"conf,omitempty"` } -// OTelAgentFeatureConfig contains the configuration for the otel-agent. +// OtelCollectorFeatureConfig contains the configuration for the otel-agent. // +k8s:openapi-gen=true -type OTelAgentFeatureConfig struct { +type OtelCollectorFeatureConfig struct { // Enabled enables the OTel Agent. // Default: true // +optional diff --git a/api/datadoghq/v2alpha1/test/builder.go b/api/datadoghq/v2alpha1/test/builder.go index f600aeeb3..94a6d4957 100644 --- a/api/datadoghq/v2alpha1/test/builder.go +++ b/api/datadoghq/v2alpha1/test/builder.go @@ -376,35 +376,35 @@ func (builder *DatadogAgentBuilder) WithProcessDiscoveryEnabled(enabled bool) *D } // OTel Agent -func (builder *DatadogAgentBuilder) initOtelAgent() { - if builder.datadogAgent.Spec.Features.OTelAgent == nil { - builder.datadogAgent.Spec.Features.OTelAgent = &v2alpha1.OTelAgentFeatureConfig{} +func (builder *DatadogAgentBuilder) initOtelCollector() { + if builder.datadogAgent.Spec.Features.OtelCollector == nil { + builder.datadogAgent.Spec.Features.OtelCollector = &v2alpha1.OtelCollectorFeatureConfig{} } } -func (builder *DatadogAgentBuilder) WithOTelAgentEnabled(enabled bool) *DatadogAgentBuilder { - builder.initOtelAgent() - builder.datadogAgent.Spec.Features.OTelAgent.Enabled = apiutils.NewBoolPointer(enabled) +func (builder *DatadogAgentBuilder) WithOTelCollectorEnabled(enabled bool) *DatadogAgentBuilder { + builder.initOtelCollector() + builder.datadogAgent.Spec.Features.OtelCollector.Enabled = apiutils.NewBoolPointer(enabled) return builder } -func (builder *DatadogAgentBuilder) WithOTelAgentConfig() *DatadogAgentBuilder { - builder.datadogAgent.Spec.Features.OTelAgent.Conf = &v2alpha1.CustomConfig{} - builder.datadogAgent.Spec.Features.OTelAgent.Conf.ConfigData = +func (builder *DatadogAgentBuilder) WithOTelCollectorConfig() *DatadogAgentBuilder { + builder.datadogAgent.Spec.Features.OtelCollector.Conf = &v2alpha1.CustomConfig{} + builder.datadogAgent.Spec.Features.OtelCollector.Conf.ConfigData = apiutils.NewStringPointer(defaultconfig.DefaultOtelCollectorConfig) return builder } -func (builder *DatadogAgentBuilder) WithOTelAgentConfigMap() *DatadogAgentBuilder { - builder.datadogAgent.Spec.Features.OTelAgent.Conf = &v2alpha1.CustomConfig{} - builder.datadogAgent.Spec.Features.OTelAgent.Conf.ConfigMap = &v2alpha1.ConfigMapConfig{ +func (builder *DatadogAgentBuilder) WithOTelCollectorConfigMap() *DatadogAgentBuilder { + builder.datadogAgent.Spec.Features.OtelCollector.Conf = &v2alpha1.CustomConfig{} + builder.datadogAgent.Spec.Features.OtelCollector.Conf.ConfigMap = &v2alpha1.ConfigMapConfig{ Name: "user-provided-config-map", } return builder } -func (builder *DatadogAgentBuilder) WithOTelAgentPorts(grpcPort int32, httpPort int32) *DatadogAgentBuilder { - builder.datadogAgent.Spec.Features.OTelAgent.Ports = []*corev1.ContainerPort{ +func (builder *DatadogAgentBuilder) WithOTelCollectorPorts(grpcPort int32, httpPort int32) *DatadogAgentBuilder { + builder.datadogAgent.Spec.Features.OtelCollector.Ports = []*corev1.ContainerPort{ { Name: "otel-http", ContainerPort: httpPort, diff --git a/api/datadoghq/v2alpha1/zz_generated.deepcopy.go b/api/datadoghq/v2alpha1/zz_generated.deepcopy.go index be3c3ff8d..2a545d09e 100644 --- a/api/datadoghq/v2alpha1/zz_generated.deepcopy.go +++ b/api/datadoghq/v2alpha1/zz_generated.deepcopy.go @@ -1102,9 +1102,9 @@ func (in *DatadogCredentials) DeepCopy() *DatadogCredentials { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DatadogFeatures) DeepCopyInto(out *DatadogFeatures) { *out = *in - if in.OTelAgent != nil { - in, out := &in.OTelAgent, &out.OTelAgent - *out = new(OTelAgentFeatureConfig) + if in.OtelCollector != nil { + in, out := &in.OtelCollector, &out.OtelCollector + *out = new(OtelCollectorFeatureConfig) (*in).DeepCopyInto(*out) } if in.LogCollection != nil { @@ -2186,42 +2186,6 @@ func (in *OTLPReceiverConfig) DeepCopy() *OTLPReceiverConfig { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *OTelAgentFeatureConfig) DeepCopyInto(out *OTelAgentFeatureConfig) { - *out = *in - if in.Enabled != nil { - in, out := &in.Enabled, &out.Enabled - *out = new(bool) - **out = **in - } - if in.Conf != nil { - in, out := &in.Conf, &out.Conf - *out = new(CustomConfig) - (*in).DeepCopyInto(*out) - } - if in.Ports != nil { - in, out := &in.Ports, &out.Ports - *out = make([]*corev1.ContainerPort, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(corev1.ContainerPort) - **out = **in - } - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OTelAgentFeatureConfig. -func (in *OTelAgentFeatureConfig) DeepCopy() *OTelAgentFeatureConfig { - if in == nil { - return nil - } - out := new(OTelAgentFeatureConfig) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OrchestratorExplorerFeatureConfig) DeepCopyInto(out *OrchestratorExplorerFeatureConfig) { *out = *in @@ -2287,6 +2251,42 @@ func (in *OriginDetectionUnified) DeepCopy() *OriginDetectionUnified { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OtelCollectorFeatureConfig) DeepCopyInto(out *OtelCollectorFeatureConfig) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.Conf != nil { + in, out := &in.Conf, &out.Conf + *out = new(CustomConfig) + (*in).DeepCopyInto(*out) + } + if in.Ports != nil { + in, out := &in.Ports, &out.Ports + *out = make([]*corev1.ContainerPort, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(corev1.ContainerPort) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OtelCollectorFeatureConfig. +func (in *OtelCollectorFeatureConfig) DeepCopy() *OtelCollectorFeatureConfig { + if in == nil { + return nil + } + out := new(OtelCollectorFeatureConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProcessDiscoveryFeatureConfig) DeepCopyInto(out *ProcessDiscoveryFeatureConfig) { *out = *in diff --git a/api/datadoghq/v2alpha1/zz_generated.openapi.go b/api/datadoghq/v2alpha1/zz_generated.openapi.go index 1a520789e..1da105cb3 100644 --- a/api/datadoghq/v2alpha1/zz_generated.openapi.go +++ b/api/datadoghq/v2alpha1/zz_generated.openapi.go @@ -39,8 +39,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTLPHTTPConfig": schema_datadog_operator_api_datadoghq_v2alpha1_OTLPHTTPConfig(ref), "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTLPProtocolsConfig": schema_datadog_operator_api_datadoghq_v2alpha1_OTLPProtocolsConfig(ref), "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTLPReceiverConfig": schema_datadog_operator_api_datadoghq_v2alpha1_OTLPReceiverConfig(ref), - "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTelAgentFeatureConfig": schema_datadog_operator_api_datadoghq_v2alpha1_OTelAgentFeatureConfig(ref), "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OrchestratorExplorerFeatureConfig": schema_datadog_operator_api_datadoghq_v2alpha1_OrchestratorExplorerFeatureConfig(ref), + "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OtelCollectorFeatureConfig": schema_datadog_operator_api_datadoghq_v2alpha1_OtelCollectorFeatureConfig(ref), "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.PrometheusScrapeFeatureConfig": schema_datadog_operator_api_datadoghq_v2alpha1_PrometheusScrapeFeatureConfig(ref), "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.RemoteConfigConfiguration": schema_datadog_operator_api_datadoghq_v2alpha1_RemoteConfigConfiguration(ref), "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.SeccompConfig": schema_datadog_operator_api_datadoghq_v2alpha1_SeccompConfig(ref), @@ -528,8 +528,8 @@ func schema_datadog_operator_api_datadoghq_v2alpha1_DatadogFeatures(ref common.R Properties: map[string]spec.Schema{ "otelCollector": { SchemaProps: spec.SchemaProps{ - Description: "OTelAgent configuration.", - Ref: ref("github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTelAgentFeatureConfig"), + Description: "OtelCollector configuration.", + Ref: ref("github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OtelCollectorFeatureConfig"), }, }, "logCollection": { @@ -698,7 +698,7 @@ func schema_datadog_operator_api_datadoghq_v2alpha1_DatadogFeatures(ref common.R }, }, Dependencies: []string{ - "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.APMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ASMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.AdmissionControllerFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.AutoscalingFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CSPMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CWSFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ClusterChecksFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.DogstatsdFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.EBPFCheckFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.EventCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ExternalMetricsServerFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.HelmCheckFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.KubeStateMetricsCoreFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.LiveContainerCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.LiveProcessCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.LogCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.NPMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OOMKillFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTLPFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTelAgentFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OrchestratorExplorerFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ProcessDiscoveryFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.PrometheusScrapeFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.RemoteConfigurationFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.SBOMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ServiceDiscoveryFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.TCPQueueLengthFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.USMFeatureConfig"}, + "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.APMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ASMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.AdmissionControllerFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.AutoscalingFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CSPMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CWSFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ClusterChecksFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.DogstatsdFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.EBPFCheckFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.EventCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ExternalMetricsServerFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.HelmCheckFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.KubeStateMetricsCoreFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.LiveContainerCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.LiveProcessCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.LogCollectionFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.NPMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OOMKillFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OTLPFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OrchestratorExplorerFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.OtelCollectorFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ProcessDiscoveryFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.PrometheusScrapeFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.RemoteConfigurationFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.SBOMFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.ServiceDiscoveryFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.TCPQueueLengthFeatureConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.USMFeatureConfig"}, } } @@ -1280,47 +1280,6 @@ func schema_datadog_operator_api_datadoghq_v2alpha1_OTLPReceiverConfig(ref commo } } -func schema_datadog_operator_api_datadoghq_v2alpha1_OTelAgentFeatureConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "OTelAgentFeatureConfig contains the configuration for the otel-agent.", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "enabled": { - SchemaProps: spec.SchemaProps{ - Description: "Enabled enables the OTel Agent. Default: true", - Type: []string{"boolean"}, - Format: "", - }, - }, - "conf": { - SchemaProps: spec.SchemaProps{ - Description: "Conf overrides the configuration for the default Kubernetes State Metrics Core check. This must point to a ConfigMap containing a valid cluster check configuration. When passing a configmap, file name *must* be otel-config.yaml.", - Ref: ref("github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CustomConfig"), - }, - }, - "ports": { - SchemaProps: spec.SchemaProps{ - Description: "Ports contains the ports for the otel-agent. Defaults: otel-grpc:4317 / otel-http:4318. Note: setting 4317 or 4318 manually is *only* supported if name match default names (otel-grpc, otel-http). If not, this will lead to a port conflict. This limitation will be lifted once annotations support is removed.", - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Ref: ref("k8s.io/api/core/v1.ContainerPort"), - }, - }, - }, - }, - }, - }, - }, - }, - Dependencies: []string{ - "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CustomConfig", "k8s.io/api/core/v1.ContainerPort"}, - } -} - func schema_datadog_operator_api_datadoghq_v2alpha1_OrchestratorExplorerFeatureConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -1403,6 +1362,47 @@ func schema_datadog_operator_api_datadoghq_v2alpha1_OrchestratorExplorerFeatureC } } +func schema_datadog_operator_api_datadoghq_v2alpha1_OtelCollectorFeatureConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "OtelCollectorFeatureConfig contains the configuration for the otel-agent.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "enabled": { + SchemaProps: spec.SchemaProps{ + Description: "Enabled enables the OTel Agent. Default: true", + Type: []string{"boolean"}, + Format: "", + }, + }, + "conf": { + SchemaProps: spec.SchemaProps{ + Description: "Conf overrides the configuration for the default Kubernetes State Metrics Core check. This must point to a ConfigMap containing a valid cluster check configuration. When passing a configmap, file name *must* be otel-config.yaml.", + Ref: ref("github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CustomConfig"), + }, + }, + "ports": { + SchemaProps: spec.SchemaProps{ + Description: "Ports contains the ports for the otel-agent. Defaults: otel-grpc:4317 / otel-http:4318. Note: setting 4317 or 4318 manually is *only* supported if name match default names (otel-grpc, otel-http). If not, this will lead to a port conflict. This limitation will be lifted once annotations support is removed.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/api/core/v1.ContainerPort"), + }, + }, + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CustomConfig", "k8s.io/api/core/v1.ContainerPort"}, + } +} + func schema_datadog_operator_api_datadoghq_v2alpha1_PrometheusScrapeFeatureConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/config/crd/bases/v1/datadoghq.com_datadogagents.yaml b/config/crd/bases/v1/datadoghq.com_datadogagents.yaml index da9e55e3a..4b73c23db 100644 --- a/config/crd/bases/v1/datadoghq.com_datadogagents.yaml +++ b/config/crd/bases/v1/datadoghq.com_datadogagents.yaml @@ -1285,7 +1285,7 @@ spec: type: boolean type: object otelCollector: - description: OTelAgent configuration. + description: OtelCollector configuration. properties: conf: description: |- @@ -8122,7 +8122,7 @@ spec: type: boolean type: object otelCollector: - description: OTelAgent configuration. + description: OtelCollector configuration. properties: conf: description: |- diff --git a/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json b/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json index 864bcc562..5861b32f1 100644 --- a/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json +++ b/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json @@ -1332,7 +1332,7 @@ }, "otelCollector": { "additionalProperties": false, - "description": "OTelAgent configuration.", + "description": "OtelCollector configuration.", "properties": { "conf": { "additionalProperties": false, @@ -8107,7 +8107,7 @@ }, "otelCollector": { "additionalProperties": false, - "description": "OTelAgent configuration.", + "description": "OtelCollector configuration.", "properties": { "conf": { "additionalProperties": false, diff --git a/internal/controller/datadogagent/feature/otelagent/configmap_test.go b/internal/controller/datadogagent/feature/otelagent/configmap_test.go index 0dedd0c9a..d16bd3774 100644 --- a/internal/controller/datadogagent/feature/otelagent/configmap_test.go +++ b/internal/controller/datadogagent/feature/otelagent/configmap_test.go @@ -16,7 +16,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func Test_otelAgent_buildOtelAgentConfigMap(t *testing.T) { +func Test_buildOtelCollectorConfigMap(t *testing.T) { // check config map configMapWant := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ @@ -27,17 +27,17 @@ func Test_otelAgent_buildOtelAgentConfigMap(t *testing.T) { }, } - otelAgentFeature, ok := buildOtelAgentFeature(&feature.Options{}).(*otelAgentFeature) + otelCollectorFeature, ok := buildOtelCollectorFeature(&feature.Options{}).(*otelCollectorFeature) assert.True(t, ok) - otelAgentFeature.owner = &metav1.ObjectMeta{ + otelCollectorFeature.owner = &metav1.ObjectMeta{ Name: "-otel-agent-config", } - otelAgentFeature.configMapName = "-otel-agent-config" - otelAgentFeature.customConfig = &v2alpha1.CustomConfig{} - otelAgentFeature.customConfig.ConfigData = &defaultconfig.DefaultOtelCollectorConfig + otelCollectorFeature.configMapName = "-otel-agent-config" + otelCollectorFeature.customConfig = &v2alpha1.CustomConfig{} + otelCollectorFeature.customConfig.ConfigData = &defaultconfig.DefaultOtelCollectorConfig - configMap, err := otelAgentFeature.buildOTelAgentCoreConfigMap() + configMap, err := otelCollectorFeature.buildOTelAgentCoreConfigMap() assert.NoError(t, err) assert.Equal(t, configMapWant, configMap) } diff --git a/internal/controller/datadogagent/feature/otelagent/feature.go b/internal/controller/datadogagent/feature/otelagent/feature.go index 45a599600..512d8e37b 100644 --- a/internal/controller/datadogagent/feature/otelagent/feature.go +++ b/internal/controller/datadogagent/feature/otelagent/feature.go @@ -22,36 +22,36 @@ const ( ) func init() { - err := feature.Register(feature.OtelAgentIDType, buildOtelAgentFeature) + err := feature.Register(feature.OtelAgentIDType, buildOtelCollectorFeature) if err != nil { panic(err) } } -func buildOtelAgentFeature(options *feature.Options) feature.Feature { - return &otelAgentFeature{} +func buildOtelCollectorFeature(options *feature.Options) feature.Feature { + return &otelCollectorFeature{} } -type otelAgentFeature struct { +type otelCollectorFeature struct { customConfig *v2alpha1.CustomConfig owner metav1.Object configMapName string ports []*corev1.ContainerPort } -func (o otelAgentFeature) ID() feature.IDType { +func (o otelCollectorFeature) ID() feature.IDType { return feature.OtelAgentIDType } -func (o *otelAgentFeature) Configure(dda *v2alpha1.DatadogAgent) feature.RequiredComponents { +func (o *otelCollectorFeature) Configure(dda *v2alpha1.DatadogAgent) feature.RequiredComponents { o.owner = dda - if dda.Spec.Features.OTelAgent.Conf != nil { - o.customConfig = dda.Spec.Features.OTelAgent.Conf + if dda.Spec.Features.OtelCollector.Conf != nil { + o.customConfig = dda.Spec.Features.OtelCollector.Conf } o.configMapName = v2alpha1.GetConfName(dda, o.customConfig, v2alpha1.DefaultOTelAgentConf) - if len(dda.Spec.Features.OTelAgent.Ports) == 0 { - dda.Spec.Features.OTelAgent.Ports = []*corev1.ContainerPort{ + if len(dda.Spec.Features.OtelCollector.Ports) == 0 { + dda.Spec.Features.OtelCollector.Ports = []*corev1.ContainerPort{ { Name: "otel-http", ContainerPort: 4318, @@ -66,10 +66,10 @@ func (o *otelAgentFeature) Configure(dda *v2alpha1.DatadogAgent) feature.Require }, } } - o.ports = dda.Spec.Features.OTelAgent.Ports + o.ports = dda.Spec.Features.OtelCollector.Ports var reqComp feature.RequiredComponents - if apiutils.BoolValue(dda.Spec.Features.OTelAgent.Enabled) { + if apiutils.BoolValue(dda.Spec.Features.OtelCollector.Enabled) { reqComp = feature.RequiredComponents{ Agent: feature.RequiredComponent{ IsRequired: apiutils.NewBoolPointer(true), @@ -84,14 +84,14 @@ func (o *otelAgentFeature) Configure(dda *v2alpha1.DatadogAgent) feature.Require return reqComp } -func (o *otelAgentFeature) buildOTelAgentCoreConfigMap() (*corev1.ConfigMap, error) { +func (o *otelCollectorFeature) buildOTelAgentCoreConfigMap() (*corev1.ConfigMap, error) { if o.customConfig != nil && o.customConfig.ConfigData != nil { return configmap.BuildConfigMapConfigData(o.owner.GetNamespace(), o.customConfig.ConfigData, o.configMapName, otelConfigFileName) } return nil, nil } -func (o otelAgentFeature) ManageDependencies(managers feature.ResourceManagers, components feature.RequiredComponents) error { +func (o otelCollectorFeature) ManageDependencies(managers feature.ResourceManagers, components feature.RequiredComponents) error { // check if an otel collector config was provided. If not, use default. if o.customConfig == nil { o.customConfig = &v2alpha1.CustomConfig{} @@ -123,11 +123,11 @@ func (o otelAgentFeature) ManageDependencies(managers feature.ResourceManagers, return nil } -func (o otelAgentFeature) ManageClusterAgent(managers feature.PodTemplateManagers) error { +func (o otelCollectorFeature) ManageClusterAgent(managers feature.PodTemplateManagers) error { return nil } -func (o otelAgentFeature) ManageNodeAgent(managers feature.PodTemplateManagers, provider string) error { +func (o otelCollectorFeature) ManageNodeAgent(managers feature.PodTemplateManagers, provider string) error { var vol corev1.Volume if o.customConfig != nil && o.customConfig.ConfigMap != nil { // Custom config is referenced via ConfigMap @@ -160,10 +160,10 @@ func (o otelAgentFeature) ManageNodeAgent(managers feature.PodTemplateManagers, return nil } -func (o otelAgentFeature) ManageSingleContainerNodeAgent(managers feature.PodTemplateManagers, provider string) error { +func (o otelCollectorFeature) ManageSingleContainerNodeAgent(managers feature.PodTemplateManagers, provider string) error { return nil } -func (o otelAgentFeature) ManageClusterChecksRunner(managers feature.PodTemplateManagers) error { +func (o otelCollectorFeature) ManageClusterChecksRunner(managers feature.PodTemplateManagers) error { return nil } diff --git a/internal/controller/datadogagent/feature/otelagent/feature_test.go b/internal/controller/datadogagent/feature/otelagent/feature_test.go index 3de971e21..ad4e6eb98 100644 --- a/internal/controller/datadogagent/feature/otelagent/feature_test.go +++ b/internal/controller/datadogagent/feature/otelagent/feature_test.go @@ -39,15 +39,15 @@ func Test_otelAgentFeature_Configure(t *testing.T) { { Name: "otel agent disabled without config", DDA: v2alpha1test.NewDatadogAgentBuilder(). - WithOTelAgentEnabled(false). + WithOTelCollectorEnabled(false). Build(), WantConfigure: false, }, { Name: "otel agent disabled with config", DDA: v2alpha1test.NewDatadogAgentBuilder(). - WithOTelAgentEnabled(false). - WithOTelAgentConfig(). + WithOTelCollectorEnabled(false). + WithOTelCollectorConfig(). Build(), WantConfigure: false, }, @@ -55,8 +55,8 @@ func Test_otelAgentFeature_Configure(t *testing.T) { { Name: "otel agent enabled with config", DDA: v2alpha1test.NewDatadogAgentBuilder(). - WithOTelAgentEnabled(true). - WithOTelAgentConfig(). + WithOTelCollectorEnabled(true). + WithOTelCollectorConfig(). Build(), WantConfigure: true, WantDependenciesFunc: testExpectedDepsCreatedCM, @@ -65,8 +65,8 @@ func Test_otelAgentFeature_Configure(t *testing.T) { { Name: "otel agent enabled with configMap", DDA: v2alpha1test.NewDatadogAgentBuilder(). - WithOTelAgentEnabled(true). - WithOTelAgentConfigMap(). + WithOTelCollectorEnabled(true). + WithOTelCollectorConfigMap(). Build(), WantConfigure: true, WantDependenciesFunc: testExpectedDepsCreatedCM, @@ -75,7 +75,7 @@ func Test_otelAgentFeature_Configure(t *testing.T) { { Name: "otel agent enabled without config", DDA: v2alpha1test.NewDatadogAgentBuilder(). - WithOTelAgentEnabled(true). + WithOTelCollectorEnabled(true). Build(), WantConfigure: true, WantDependenciesFunc: testExpectedDepsCreatedCM, @@ -84,8 +84,8 @@ func Test_otelAgentFeature_Configure(t *testing.T) { { Name: "otel agent enabled without config non default ports", DDA: v2alpha1test.NewDatadogAgentBuilder(). - WithOTelAgentEnabled(true). - WithOTelAgentPorts(4444, 5555). + WithOTelCollectorEnabled(true). + WithOTelCollectorPorts(4444, 5555). Build(), WantConfigure: true, WantDependenciesFunc: testExpectedDepsCreatedCM, @@ -98,7 +98,7 @@ func Test_otelAgentFeature_Configure(t *testing.T) { }, } - tests.Run(t, buildOtelAgentFeature) + tests.Run(t, buildOtelCollectorFeature) } func testExpectedAgent(agentContainerName apicommon.AgentContainerName, expectedPorts expectedPorts, localObjectReferenceName string) *test.ComponentTest { From 719a485f56d03ed608f89c8f3a265cf448fd9fee Mon Sep 17 00:00:00 2001 From: mackjmr Date: Fri, 13 Dec 2024 11:15:11 +0100 Subject: [PATCH 12/28] rename directory/ pkg --- api/datadoghq/v2alpha1/test/builder.go | 2 +- internal/controller/datadogagent/controller.go | 2 +- .../{otelagent => otelcollector}/configmap_test.go | 4 ++-- .../defaultconfig/defaultconfig.go | 0 .../feature/{otelagent => otelcollector}/feature.go | 4 ++-- .../{otelagent => otelcollector}/feature_test.go | 10 +++++----- 6 files changed, 11 insertions(+), 11 deletions(-) rename internal/controller/datadogagent/feature/{otelagent => otelcollector}/configmap_test.go (95%) rename internal/controller/datadogagent/feature/{otelagent => otelcollector}/defaultconfig/defaultconfig.go (100%) rename internal/controller/datadogagent/feature/{otelagent => otelcollector}/feature.go (98%) rename internal/controller/datadogagent/feature/{otelagent => otelcollector}/feature_test.go (95%) diff --git a/api/datadoghq/v2alpha1/test/builder.go b/api/datadoghq/v2alpha1/test/builder.go index 94a6d4957..bd08ef371 100644 --- a/api/datadoghq/v2alpha1/test/builder.go +++ b/api/datadoghq/v2alpha1/test/builder.go @@ -9,7 +9,7 @@ import ( "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1" "github.com/DataDog/datadog-operator/api/utils" apiutils "github.com/DataDog/datadog-operator/api/utils" - "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelagent/defaultconfig" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelcollector/defaultconfig" defaulting "github.com/DataDog/datadog-operator/pkg/defaulting" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" diff --git a/internal/controller/datadogagent/controller.go b/internal/controller/datadogagent/controller.go index 79fd0623c..7c29bdd31 100644 --- a/internal/controller/datadogagent/controller.go +++ b/internal/controller/datadogagent/controller.go @@ -42,7 +42,7 @@ import ( _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/npm" _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/oomkill" _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/orchestratorexplorer" - _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelagent" + _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelcollector" _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otlp" _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/processdiscovery" _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/prometheusscrape" diff --git a/internal/controller/datadogagent/feature/otelagent/configmap_test.go b/internal/controller/datadogagent/feature/otelcollector/configmap_test.go similarity index 95% rename from internal/controller/datadogagent/feature/otelagent/configmap_test.go rename to internal/controller/datadogagent/feature/otelcollector/configmap_test.go index d16bd3774..3115aadcb 100644 --- a/internal/controller/datadogagent/feature/otelagent/configmap_test.go +++ b/internal/controller/datadogagent/feature/otelcollector/configmap_test.go @@ -3,14 +3,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2016-present Datadog, Inc. -package otelagent +package otelcollector import ( "testing" "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1" "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature" - "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelagent/defaultconfig" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelcollector/defaultconfig" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/internal/controller/datadogagent/feature/otelagent/defaultconfig/defaultconfig.go b/internal/controller/datadogagent/feature/otelcollector/defaultconfig/defaultconfig.go similarity index 100% rename from internal/controller/datadogagent/feature/otelagent/defaultconfig/defaultconfig.go rename to internal/controller/datadogagent/feature/otelcollector/defaultconfig/defaultconfig.go diff --git a/internal/controller/datadogagent/feature/otelagent/feature.go b/internal/controller/datadogagent/feature/otelcollector/feature.go similarity index 98% rename from internal/controller/datadogagent/feature/otelagent/feature.go rename to internal/controller/datadogagent/feature/otelcollector/feature.go index 512d8e37b..e5794a85e 100644 --- a/internal/controller/datadogagent/feature/otelagent/feature.go +++ b/internal/controller/datadogagent/feature/otelcollector/feature.go @@ -1,4 +1,4 @@ -package otelagent +package otelcollector import ( "strconv" @@ -8,7 +8,7 @@ import ( "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1" apiutils "github.com/DataDog/datadog-operator/api/utils" "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature" - "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelagent/defaultconfig" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelcollector/defaultconfig" "github.com/DataDog/datadog-operator/internal/controller/datadogagent/object/configmap" "github.com/DataDog/datadog-operator/internal/controller/datadogagent/object/volume" "github.com/DataDog/datadog-operator/pkg/kubernetes" diff --git a/internal/controller/datadogagent/feature/otelagent/feature_test.go b/internal/controller/datadogagent/feature/otelcollector/feature_test.go similarity index 95% rename from internal/controller/datadogagent/feature/otelagent/feature_test.go rename to internal/controller/datadogagent/feature/otelcollector/feature_test.go index ad4e6eb98..09f96d2eb 100644 --- a/internal/controller/datadogagent/feature/otelagent/feature_test.go +++ b/internal/controller/datadogagent/feature/otelcollector/feature_test.go @@ -1,4 +1,4 @@ -package otelagent +package otelcollector import ( "strings" @@ -10,7 +10,7 @@ import ( apiutils "github.com/DataDog/datadog-operator/api/utils" "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature" "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/fake" - "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelagent/defaultconfig" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelcollector/defaultconfig" "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/test" "github.com/DataDog/datadog-operator/internal/controller/datadogagent/store" "github.com/DataDog/datadog-operator/pkg/kubernetes" @@ -33,7 +33,7 @@ var ( defaultLocalObjectReferenceName = "-otel-agent-config" ) -func Test_otelAgentFeature_Configure(t *testing.T) { +func Test_otelCollectorFeature_Configure(t *testing.T) { tests := test.FeatureTestSuite{ // disabled { @@ -160,7 +160,7 @@ func testExpectedAgent(agentContainerName apicommon.AgentContainerName, expected func testExpectedDepsCreatedCM(t testing.TB, store store.StoreClient) { // hacky to need to hardcode test name but unaware of a better approach that doesn't require // modifying WantDependenciesFunc definition. - if t.Name() == "Test_otelAgentFeature_Configure/otel_agent_enabled_with_configMap" { + if t.Name() == "Test_otelCollectorFeature_Configure/otel_agent_enabled_with_configMap" { // configMap is provided by user, no need to create it. _, found := store.Get(kubernetes.ConfigMapKind, "", "-otel-agent-config") assert.False(t, found) @@ -175,7 +175,7 @@ func testExpectedDepsCreatedCM(t testing.TB, store store.StoreClient) { // validate that default ports were overriden by user provided ports in default config. hacky to need to // hardcode test name but unaware of a better approach that doesn't require modifying WantDependenciesFunc definition. - if t.Name() == "Test_otelAgentFeature_Configure/otel_agent_enabled_without_config_non_default_ports" { + if t.Name() == "Test_otelCollectorFeature_Configure/otel_agent_enabled_without_config_non_default_ports" { expectedCM["otel-config.yaml"] = strings.ReplaceAll(expectedCM["otel-config.yaml"], "4317", "4444") expectedCM["otel-config.yaml"] = strings.ReplaceAll(expectedCM["otel-config.yaml"], "4318", "5555") assert.True( From 29452148345a3d48f5ca9ec90bb530918757b853 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Fri, 13 Dec 2024 11:17:22 +0100 Subject: [PATCH 13/28] undo change to InitConfig volumes --- .../controller/datadogagent/component/agent/default.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/controller/datadogagent/component/agent/default.go b/internal/controller/datadogagent/component/agent/default.go index cb2502a3c..54030b6c6 100644 --- a/internal/controller/datadogagent/component/agent/default.go +++ b/internal/controller/datadogagent/component/agent/default.go @@ -220,7 +220,7 @@ func otelAgentContainer(_ metav1.Object) corev1.Container { VolumeMounts: volumeMountsForOtelAgent(), // todo(mackjmr): remove once support for annotations is removed. // the otel-agent feature adds these ports if none are supplied by - // the user. + // the user. Ports: []corev1.ContainerPort{ { Name: "otel-grpc", @@ -409,7 +409,13 @@ func envVarsForSecurityAgent(dda metav1.Object) []corev1.EnvVar { func volumeMountsForInitConfig() []corev1.VolumeMount { return []corev1.VolumeMount{ + common.GetVolumeMountForLogs(), + common.GetVolumeMountForChecksd(), + common.GetVolumeMountForAuth(false), + common.GetVolumeMountForConfd(), common.GetVolumeMountForConfig(), + common.GetVolumeMountForProc(), + common.GetVolumeMountForRuntimeSocket(true), } } From 85e150bce25b0a61639a404dbafae8137b47a014 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Fri, 13 Dec 2024 11:51:30 +0100 Subject: [PATCH 14/28] remove unrelated changes --- config/manager/kustomization.yaml | 4 ++-- examples/datadogagent/datadog-agent-minimum.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 7163ba39a..1216dd7ca 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -3,6 +3,6 @@ resources: images: - name: controller newName: gcr.io/datadoghq/operator - newTag: v1.9.0-rc.3_cb51682f + newTag: 1.10.0 apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization +kind: Kustomization \ No newline at end of file diff --git a/examples/datadogagent/datadog-agent-minimum.yaml b/examples/datadogagent/datadog-agent-minimum.yaml index 26b81b9f4..ad9603a82 100644 --- a/examples/datadogagent/datadog-agent-minimum.yaml +++ b/examples/datadogagent/datadog-agent-minimum.yaml @@ -6,4 +6,4 @@ spec: global: clusterName: my-example-cluster credentials: - apiKey: \ No newline at end of file + apiKey: From 838d361b41daf24df382b8b4fa9669464c3ad3a1 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Fri, 13 Dec 2024 11:52:25 +0100 Subject: [PATCH 15/28] add empty line --- config/manager/kustomization.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 1216dd7ca..962660140 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -5,4 +5,4 @@ images: newName: gcr.io/datadoghq/operator newTag: 1.10.0 apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization \ No newline at end of file +kind: Kustomization From d7aaf6d8defef3f816b89ed62293c86ce4463662 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Fri, 13 Dec 2024 12:08:06 +0100 Subject: [PATCH 16/28] add otel collector feature to Test_defaultFeatures --- .../v2alpha1/datadogagent_default_test.go | 182 ++++++++++++++++++ 1 file changed, 182 insertions(+) diff --git a/api/datadoghq/v2alpha1/datadogagent_default_test.go b/api/datadoghq/v2alpha1/datadogagent_default_test.go index 143da79b4..182466618 100644 --- a/api/datadoghq/v2alpha1/datadogagent_default_test.go +++ b/api/datadoghq/v2alpha1/datadogagent_default_test.go @@ -212,6 +212,9 @@ func Test_defaultFeatures(t *testing.T) { LanguageDetection: &LanguageDetectionConfig{Enabled: apiutils.NewBoolPointer(defaultLanguageDetectionEnabled)}, }, }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOtelCollectorEnabled), + }, ASM: &ASMFeatureConfig{ Threats: &ASMThreatsConfig{ Enabled: apiutils.NewBoolPointer(defaultAdmissionASMThreatsEnabled), @@ -329,6 +332,9 @@ func Test_defaultFeatures(t *testing.T) { APM: &APMFeatureConfig{ Enabled: apiutils.NewBoolPointer(valueFalse), }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOtelCollectorEnabled), + }, ASM: &ASMFeatureConfig{ Threats: &ASMThreatsConfig{ Enabled: apiutils.NewBoolPointer(valueFalse), @@ -416,6 +422,9 @@ func Test_defaultFeatures(t *testing.T) { APM: &APMFeatureConfig{ Enabled: apiutils.NewBoolPointer(valueFalse), }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOtelCollectorEnabled), + }, ASM: &ASMFeatureConfig{ Threats: &ASMThreatsConfig{ Enabled: apiutils.NewBoolPointer(valueFalse), @@ -548,6 +557,9 @@ func Test_defaultFeatures(t *testing.T) { LanguageDetection: &LanguageDetectionConfig{Enabled: apiutils.NewBoolPointer(defaultLanguageDetectionEnabled)}, }, }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOtelCollectorEnabled), + }, ASM: &ASMFeatureConfig{ Threats: &ASMThreatsConfig{ Enabled: apiutils.NewBoolPointer(defaultAdmissionASMThreatsEnabled), @@ -689,6 +701,9 @@ func Test_defaultFeatures(t *testing.T) { LanguageDetection: &LanguageDetectionConfig{Enabled: apiutils.NewBoolPointer(defaultLanguageDetectionEnabled)}, }, }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOtelCollectorEnabled), + }, ASM: &ASMFeatureConfig{ Threats: &ASMThreatsConfig{ Enabled: apiutils.NewBoolPointer(defaultAdmissionASMThreatsEnabled), @@ -825,6 +840,9 @@ func Test_defaultFeatures(t *testing.T) { LanguageDetection: &LanguageDetectionConfig{Enabled: apiutils.NewBoolPointer(defaultLanguageDetectionEnabled)}, }, }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOtelCollectorEnabled), + }, ASM: &ASMFeatureConfig{ Threats: &ASMThreatsConfig{ Enabled: apiutils.NewBoolPointer(defaultAdmissionASMThreatsEnabled), @@ -961,6 +979,9 @@ func Test_defaultFeatures(t *testing.T) { LanguageDetection: &LanguageDetectionConfig{Enabled: apiutils.NewBoolPointer(defaultLanguageDetectionEnabled)}, }, }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOtelCollectorEnabled), + }, ASM: &ASMFeatureConfig{ Threats: &ASMThreatsConfig{ Enabled: apiutils.NewBoolPointer(defaultAdmissionASMThreatsEnabled), @@ -1106,6 +1127,9 @@ func Test_defaultFeatures(t *testing.T) { LanguageDetection: &LanguageDetectionConfig{Enabled: apiutils.NewBoolPointer(defaultLanguageDetectionEnabled)}, }, }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOtelCollectorEnabled), + }, ASM: &ASMFeatureConfig{ Threats: &ASMThreatsConfig{ Enabled: apiutils.NewBoolPointer(defaultAdmissionASMThreatsEnabled), @@ -1242,6 +1266,9 @@ func Test_defaultFeatures(t *testing.T) { LanguageDetection: &LanguageDetectionConfig{Enabled: apiutils.NewBoolPointer(defaultLanguageDetectionEnabled)}, }, }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOtelCollectorEnabled), + }, ASM: &ASMFeatureConfig{ Threats: &ASMThreatsConfig{ Enabled: apiutils.NewBoolPointer(defaultAdmissionASMThreatsEnabled), @@ -1381,6 +1408,9 @@ func Test_defaultFeatures(t *testing.T) { LanguageDetection: &LanguageDetectionConfig{Enabled: apiutils.NewBoolPointer(defaultLanguageDetectionEnabled)}, }, }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOtelCollectorEnabled), + }, ASM: &ASMFeatureConfig{ Threats: &ASMThreatsConfig{ Enabled: apiutils.NewBoolPointer(defaultAdmissionASMThreatsEnabled), @@ -1512,6 +1542,9 @@ func Test_defaultFeatures(t *testing.T) { LanguageDetection: &LanguageDetectionConfig{Enabled: apiutils.NewBoolPointer(defaultLanguageDetectionEnabled)}, }, }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOtelCollectorEnabled), + }, ASM: &ASMFeatureConfig{ Threats: &ASMThreatsConfig{ Enabled: apiutils.NewBoolPointer(defaultAdmissionASMThreatsEnabled), @@ -1665,6 +1698,9 @@ func Test_defaultFeatures(t *testing.T) { LanguageDetection: &LanguageDetectionConfig{Enabled: apiutils.NewBoolPointer(defaultLanguageDetectionEnabled)}, }, }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOtelCollectorEnabled), + }, ASM: &ASMFeatureConfig{ Threats: &ASMThreatsConfig{ Enabled: apiutils.NewBoolPointer(defaultAdmissionASMThreatsEnabled), @@ -1752,6 +1788,146 @@ func Test_defaultFeatures(t *testing.T) { }, }, }, + + { + name: "OTel Collector is enabled", + ddaSpec: &DatadogAgentSpec{ + Features: &DatadogFeatures{ + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(valueTrue), + }, + }, + }, + want: &DatadogAgentSpec{ + Features: &DatadogFeatures{ + LogCollection: &LogCollectionFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultLogCollectionEnabled), + }, + LiveProcessCollection: &LiveProcessCollectionFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultLiveProcessCollectionEnabled), + }, + LiveContainerCollection: &LiveContainerCollectionFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultLiveContainerCollectionEnabled), + }, + ProcessDiscovery: &ProcessDiscoveryFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultProcessDiscoveryEnabled), + }, + OOMKill: &OOMKillFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOOMKillEnabled), + }, + TCPQueueLength: &TCPQueueLengthFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultTCPQueueLengthEnabled), + }, + EBPFCheck: &EBPFCheckFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultEBPFCheckEnabled), + }, + ServiceDiscovery: &ServiceDiscoveryFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultServiceDiscoveryEnabled), + }, + APM: &APMFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultAPMEnabled), + HostPortConfig: &HostPortConfig{ + Port: apiutils.NewInt32Pointer(defaultAPMHostPort), + Enabled: apiutils.NewBoolPointer(defaultAPMHostPortEnabled), + }, + UnixDomainSocketConfig: &UnixDomainSocketConfig{ + Enabled: apiutils.NewBoolPointer(defaultAPMSocketEnabled), + Path: apiutils.NewStringPointer(defaultAPMSocketHostPath), + }, + SingleStepInstrumentation: &SingleStepInstrumentation{ + Enabled: apiutils.NewBoolPointer(defaultAPMSingleStepInstrEnabled), + LanguageDetection: &LanguageDetectionConfig{Enabled: apiutils.NewBoolPointer(defaultLanguageDetectionEnabled)}, + }, + }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(valueTrue), + }, + ASM: &ASMFeatureConfig{ + Threats: &ASMThreatsConfig{ + Enabled: apiutils.NewBoolPointer(defaultAdmissionASMThreatsEnabled), + }, + SCA: &ASMSCAConfig{ + Enabled: apiutils.NewBoolPointer(defaultAdmissionASMSCAEnabled), + }, + IAST: &ASMIASTConfig{ + Enabled: apiutils.NewBoolPointer(defaultAdmissionASMIASTEnabled), + }, + }, + CSPM: &CSPMFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultCSPMEnabled), + }, + CWS: &CWSFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultCWSEnabled), + }, + NPM: &NPMFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultNPMEnabled), + }, + USM: &USMFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultUSMEnabled), + }, + Dogstatsd: &DogstatsdFeatureConfig{ + OriginDetectionEnabled: apiutils.NewBoolPointer(defaultDogstatsdOriginDetectionEnabled), + HostPortConfig: &HostPortConfig{Enabled: apiutils.NewBoolPointer(defaultDogstatsdHostPortEnabled)}, + UnixDomainSocketConfig: &UnixDomainSocketConfig{ + Enabled: apiutils.NewBoolPointer(defaultDogstatsdSocketEnabled), + Path: apiutils.NewStringPointer(defaultDogstatsdHostSocketPath), + }, + }, + OTLP: &OTLPFeatureConfig{Receiver: OTLPReceiverConfig{Protocols: OTLPProtocolsConfig{ + GRPC: &OTLPGRPCConfig{ + Enabled: apiutils.NewBoolPointer(defaultOTLPGRPCEnabled), + HostPortConfig: nil, + Endpoint: apiutils.NewStringPointer(defaultOTLPGRPCEndpoint), + }, + HTTP: &OTLPHTTPConfig{ + Enabled: apiutils.NewBoolPointer(defaultOTLPHTTPEnabled), + HostPortConfig: nil, + Endpoint: apiutils.NewStringPointer(defaultOTLPHTTPEndpoint), + }, + }}}, + RemoteConfiguration: &RemoteConfigurationFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultRemoteConfigurationEnabled), + }, + EventCollection: &EventCollectionFeatureConfig{ + CollectKubernetesEvents: apiutils.NewBoolPointer(defaultCollectKubernetesEvents), + }, + OrchestratorExplorer: &OrchestratorExplorerFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOrchestratorExplorerEnabled), + ScrubContainers: apiutils.NewBoolPointer(defaultOrchestratorExplorerScrubContainers), + }, + ExternalMetricsServer: &ExternalMetricsServerFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultExternalMetricsServerEnabled), + }, + KubeStateMetricsCore: &KubeStateMetricsCoreFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultKubeStateMetricsCoreEnabled), + }, + ClusterChecks: &ClusterChecksFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultClusterChecksEnabled), + UseClusterChecksRunners: apiutils.NewBoolPointer(defaultUseClusterChecksRunners), + }, + AdmissionController: &AdmissionControllerFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultAdmissionControllerEnabled), + Validation: &AdmissionControllerValidationConfig{ + Enabled: apiutils.NewBoolPointer(defaultAdmissionControllerValidationEnabled), + }, + Mutation: &AdmissionControllerMutationConfig{ + Enabled: apiutils.NewBoolPointer(defaultAdmissionControllerMutationEnabled), + }, + MutateUnlabelled: apiutils.NewBoolPointer(defaultAdmissionControllerMutateUnlabelled), + ServiceName: apiutils.NewStringPointer(defaultAdmissionServiceName), + CWSInstrumentation: &CWSInstrumentationConfig{ + Enabled: apiutils.NewBoolPointer(DefaultAdmissionControllerCWSInstrumentationEnabled), + }, + }, + PrometheusScrape: &PrometheusScrapeFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultPrometheusScrapeEnabled), + }, + HelmCheck: &HelmCheckFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultHelmCheckEnabled), + }, + }, + }, + }, { // This test sets same defaults as the one with `Features: nil`; and leaves other configs as empty structs. name: "all feature configs are empty structs, configures defaults where applicable, leaves others empty", @@ -1824,6 +2000,9 @@ func Test_defaultFeatures(t *testing.T) { LanguageDetection: &LanguageDetectionConfig{Enabled: apiutils.NewBoolPointer(defaultLanguageDetectionEnabled)}, }, }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOtelCollectorEnabled), + }, ASM: &ASMFeatureConfig{ Threats: &ASMThreatsConfig{ Enabled: apiutils.NewBoolPointer(defaultAdmissionASMThreatsEnabled), @@ -1963,6 +2142,9 @@ func Test_defaultFeatures(t *testing.T) { LanguageDetection: &LanguageDetectionConfig{Enabled: apiutils.NewBoolPointer(defaultLanguageDetectionEnabled)}, }, }, + OtelCollector: &OtelCollectorFeatureConfig{ + Enabled: apiutils.NewBoolPointer(defaultOtelCollectorEnabled), + }, ASM: &ASMFeatureConfig{ Threats: &ASMThreatsConfig{ Enabled: apiutils.NewBoolPointer(defaultAdmissionASMThreatsEnabled), From d8f55e29d79de5b554081e7f2dfbf193b7f344b6 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Fri, 13 Dec 2024 12:36:12 +0100 Subject: [PATCH 17/28] add otel agent feature to factory test --- .../datadogagent/feature/test/factory_test.go | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/internal/controller/datadogagent/feature/test/factory_test.go b/internal/controller/datadogagent/feature/test/factory_test.go index d0e387987..7f3633466 100644 --- a/internal/controller/datadogagent/feature/test/factory_test.go +++ b/internal/controller/datadogagent/feature/test/factory_test.go @@ -14,6 +14,7 @@ import ( _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/enabledefault" _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/livecontainer" _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/npm" + _ "github.com/DataDog/datadog-operator/internal/controller/datadogagent/feature/otelcollector" ) func TestBuilder(t *testing.T) { @@ -200,6 +201,40 @@ func TestBuilder(t *testing.T) { dda: v2alpha1test.NewDatadogAgentBuilder(). WithAnnotations(map[string]string{"agent.datadoghq.com/otel-agent-enabled": "false"}). BuildWithDefaults(), + wantAgentContainer: map[common.AgentContainerName]bool{ + common.UnprivilegedSingleAgentContainerName: false, + common.CoreAgentContainerName: true, + common.ProcessAgentContainerName: true, + common.TraceAgentContainerName: true, + common.SystemProbeContainerName: false, + common.SecurityAgentContainerName: false, + common.OtelAgent: false, + common.AgentDataPlaneContainerName: false, + }, + }, + { + name: "Default DDA, otel annotation false, otel collector feature enabled", + dda: v2alpha1test.NewDatadogAgentBuilder(). + WithAnnotations(map[string]string{"agent.datadoghq.com/otel-agent-enabled": "false"}). + WithOTelCollectorEnabled(true). + BuildWithDefaults(), + wantAgentContainer: map[common.AgentContainerName]bool{ + common.UnprivilegedSingleAgentContainerName: false, + common.CoreAgentContainerName: true, + common.ProcessAgentContainerName: true, + common.TraceAgentContainerName: true, + common.SystemProbeContainerName: false, + common.SecurityAgentContainerName: false, + common.OtelAgent: true, + common.AgentDataPlaneContainerName: false, + }, + }, + { + name: "Default DDA, otel annotation true, otel collector feature enabled", + dda: v2alpha1test.NewDatadogAgentBuilder(). + WithAnnotations(map[string]string{"agent.datadoghq.com/otel-agent-enabled": "true"}). + WithOTelCollectorEnabled(true). + BuildWithDefaults(), wantAgentContainer: map[common.AgentContainerName]bool{ common.UnprivilegedSingleAgentContainerName: false, common.CoreAgentContainerName: true, From 3d59facf2bef666d7c662681cea038b566e7b1b8 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Fri, 13 Dec 2024 12:38:17 +0100 Subject: [PATCH 18/28] add annotation enabled/ feature disabled test --- .../datadogagent/feature/test/factory_test.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/internal/controller/datadogagent/feature/test/factory_test.go b/internal/controller/datadogagent/feature/test/factory_test.go index 7f3633466..0fd469644 100644 --- a/internal/controller/datadogagent/feature/test/factory_test.go +++ b/internal/controller/datadogagent/feature/test/factory_test.go @@ -229,6 +229,23 @@ func TestBuilder(t *testing.T) { common.AgentDataPlaneContainerName: false, }, }, + { + name: "Default DDA, otel annotation true, otel collector feature disabled", + dda: v2alpha1test.NewDatadogAgentBuilder(). + WithAnnotations(map[string]string{"agent.datadoghq.com/otel-agent-enabled": "true"}). + WithOTelCollectorEnabled(false). + BuildWithDefaults(), + wantAgentContainer: map[common.AgentContainerName]bool{ + common.UnprivilegedSingleAgentContainerName: false, + common.CoreAgentContainerName: true, + common.ProcessAgentContainerName: true, + common.TraceAgentContainerName: true, + common.SystemProbeContainerName: false, + common.SecurityAgentContainerName: false, + common.OtelAgent: true, + common.AgentDataPlaneContainerName: false, + }, + }, { name: "Default DDA, otel annotation true, otel collector feature enabled", dda: v2alpha1test.NewDatadogAgentBuilder(). From fc532dddcece233bba3da78af30275731880a390 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Fri, 13 Dec 2024 14:22:38 +0100 Subject: [PATCH 19/28] Use Replace with i=1 instead of ReplaceAll as we know there is only 1 instance to replace --- .../controller/datadogagent/feature/otelcollector/feature.go | 4 ++-- .../datadogagent/feature/otelcollector/feature_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/controller/datadogagent/feature/otelcollector/feature.go b/internal/controller/datadogagent/feature/otelcollector/feature.go index e5794a85e..cee0df320 100644 --- a/internal/controller/datadogagent/feature/otelcollector/feature.go +++ b/internal/controller/datadogagent/feature/otelcollector/feature.go @@ -100,10 +100,10 @@ func (o otelCollectorFeature) ManageDependencies(managers feature.ResourceManage var defaultConfig = defaultconfig.DefaultOtelCollectorConfig for _, port := range o.ports { if port.Name == "otel-grpc" { - defaultConfig = strings.ReplaceAll(defaultConfig, "4317", strconv.Itoa(int(port.ContainerPort))) + defaultConfig = strings.Replace(defaultConfig, "4317", strconv.Itoa(int(port.ContainerPort)), 1) } if port.Name == "otel-http" { - defaultConfig = strings.ReplaceAll(defaultConfig, "4318", strconv.Itoa(int(port.ContainerPort))) + defaultConfig = strings.Replace(defaultConfig, "4318", strconv.Itoa(int(port.ContainerPort)), 1) } } o.customConfig.ConfigData = &defaultConfig diff --git a/internal/controller/datadogagent/feature/otelcollector/feature_test.go b/internal/controller/datadogagent/feature/otelcollector/feature_test.go index 09f96d2eb..d4a7c6a23 100644 --- a/internal/controller/datadogagent/feature/otelcollector/feature_test.go +++ b/internal/controller/datadogagent/feature/otelcollector/feature_test.go @@ -176,8 +176,8 @@ func testExpectedDepsCreatedCM(t testing.TB, store store.StoreClient) { // validate that default ports were overriden by user provided ports in default config. hacky to need to // hardcode test name but unaware of a better approach that doesn't require modifying WantDependenciesFunc definition. if t.Name() == "Test_otelCollectorFeature_Configure/otel_agent_enabled_without_config_non_default_ports" { - expectedCM["otel-config.yaml"] = strings.ReplaceAll(expectedCM["otel-config.yaml"], "4317", "4444") - expectedCM["otel-config.yaml"] = strings.ReplaceAll(expectedCM["otel-config.yaml"], "4318", "5555") + expectedCM["otel-config.yaml"] = strings.Replace(expectedCM["otel-config.yaml"], "4317", "4444", 1) + expectedCM["otel-config.yaml"] = strings.Replace(expectedCM["otel-config.yaml"], "4318", "5555", 1) assert.True( t, apiutils.IsEqualStruct(configMap.Data, expectedCM), From 7f50ee1f007d1549c661852172a65ee3f6ace014 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Fri, 13 Dec 2024 14:36:49 +0100 Subject: [PATCH 20/28] fix examples --- .../datadogagent/datadog-agent-with-otel-agent-configmap.yaml | 1 + examples/datadogagent/datadog-agent-with-otel-agent.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml b/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml index 1b737f2f7..a71737720 100644 --- a/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml +++ b/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml @@ -3,6 +3,7 @@ kind: DatadogAgent metadata: name: datadog spec: + global: credentials: apiKey: features: diff --git a/examples/datadogagent/datadog-agent-with-otel-agent.yaml b/examples/datadogagent/datadog-agent-with-otel-agent.yaml index d7fbf426e..9a3c62e55 100644 --- a/examples/datadogagent/datadog-agent-with-otel-agent.yaml +++ b/examples/datadogagent/datadog-agent-with-otel-agent.yaml @@ -3,6 +3,7 @@ kind: DatadogAgent metadata: name: datadog spec: + global: credentials: apiKey: features: @@ -43,4 +44,3 @@ spec: receivers: [otlp] processors: [batch] exporters: [datadog] - From 1a69194e7c958641288a3f0489372acb2cecfa34 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Fri, 13 Dec 2024 15:46:34 +0100 Subject: [PATCH 21/28] update example ports to 0.0.0.0 (defaults to localhost) and add annotations example with remove note --- ...dog-agent-with-otel-agent-annotations.yaml | 89 +++++++++++++++++++ ...tadog-agent-with-otel-agent-configmap.yaml | 4 +- .../datadog-agent-with-otel-agent.yaml | 4 +- 3 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 examples/datadogagent/datadog-agent-with-otel-agent-annotations.yaml diff --git a/examples/datadogagent/datadog-agent-with-otel-agent-annotations.yaml b/examples/datadogagent/datadog-agent-with-otel-agent-annotations.yaml new file mode 100644 index 000000000..e4970e7d4 --- /dev/null +++ b/examples/datadogagent/datadog-agent-with-otel-agent-annotations.yaml @@ -0,0 +1,89 @@ +apiVersion: datadoghq.com/v2alpha1 +kind: DatadogAgent +metadata: + annotations: + # Note: annotations support is temporary and will be removed in the future. + # Please use otelCollector Feature instead. + agent.datadoghq.com/otel-agent-enabled: "true" + name: datadog +spec: + global: + credentials: + apiKey: + override: + nodeAgent: + customConfigurations: + otel-config.yaml: + configMap: + name: my-datadog-otel-config + items: + - key: otel-config.yaml + path: otel-config.yaml +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: my-datadog-otel-config + labels: + app.kubernetes.io/name: "my-datadog" + app.kubernetes.io/version: "7" +data: + otel-config.yaml: |- + receivers: + prometheus: + config: + scrape_configs: + - job_name: "otel-agent" + scrape_interval: 10s + static_configs: + - targets: ["0.0.0.0:8888"] + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 + exporters: + debug: + verbosity: detailed + datadog: + api: + key: ${env:DD_API_KEY} + processors: + infraattributes: + cardinality: 2 + probabilistic_sampler: + hash_seed: 22 + sampling_percentage: 15.3 + batch: + timeout: 10s + connectors: + datadog/connector: + traces: + compute_top_level_by_span_kind: true + peer_tags_aggregation: true + compute_stats_by_span_kind: true + extensions: + health_check: + service: + extensions: [health_check] + telemetry: + logs: + level: debug + pipelines: + traces: + receivers: [otlp] + processors: [batch] + exporters: [datadog/connector] + traces/sampled: + receivers: [otlp] + processors: [probabilistic_sampler, infraattributes, batch] + exporters: [datadog] + metrics: + receivers: [otlp, datadog/connector, prometheus] + processors: [infraattributes, batch] + exporters: [datadog] + logs: + receivers: [otlp] + processors: [infraattributes, batch] + exporters: [datadog] \ No newline at end of file diff --git a/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml b/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml index a71737720..9ac53828d 100644 --- a/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml +++ b/examples/datadogagent/datadog-agent-with-otel-agent-configmap.yaml @@ -30,13 +30,15 @@ data: otlp: protocols: grpc: + endpoint: 0.0.0.0:4317 http: + endpoint: 0.0.0.0:4318 exporters: debug: verbosity: detailed datadog: api: - key: + key: ${env:DD_API_KEY} processors: batch: connectors: diff --git a/examples/datadogagent/datadog-agent-with-otel-agent.yaml b/examples/datadogagent/datadog-agent-with-otel-agent.yaml index 9a3c62e55..6f4236e35 100644 --- a/examples/datadogagent/datadog-agent-with-otel-agent.yaml +++ b/examples/datadogagent/datadog-agent-with-otel-agent.yaml @@ -20,13 +20,15 @@ spec: otlp: protocols: grpc: + endpoint: 0.0.0.0:4317 http: + endpoint: 0.0.0.0:4318 exporters: debug: verbosity: detailed datadog: api: - key: "" + key: ${env:DD_API_KEY} processors: batch: connectors: From ff7868ebd53219d2ebb593197edf50c5f2584bbf Mon Sep 17 00:00:00 2001 From: mackjmr Date: Tue, 17 Dec 2024 12:53:09 +0100 Subject: [PATCH 22/28] update o.ports rather than DDA directly --- .../controller/datadogagent/feature/otelcollector/feature.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/controller/datadogagent/feature/otelcollector/feature.go b/internal/controller/datadogagent/feature/otelcollector/feature.go index cee0df320..6eb1fa43a 100644 --- a/internal/controller/datadogagent/feature/otelcollector/feature.go +++ b/internal/controller/datadogagent/feature/otelcollector/feature.go @@ -51,7 +51,7 @@ func (o *otelCollectorFeature) Configure(dda *v2alpha1.DatadogAgent) feature.Req o.configMapName = v2alpha1.GetConfName(dda, o.customConfig, v2alpha1.DefaultOTelAgentConf) if len(dda.Spec.Features.OtelCollector.Ports) == 0 { - dda.Spec.Features.OtelCollector.Ports = []*corev1.ContainerPort{ + o.ports = []*corev1.ContainerPort{ { Name: "otel-http", ContainerPort: 4318, @@ -65,8 +65,9 @@ func (o *otelCollectorFeature) Configure(dda *v2alpha1.DatadogAgent) feature.Req Protocol: corev1.ProtocolTCP, }, } + } else { + o.ports = dda.Spec.Features.OtelCollector.Ports } - o.ports = dda.Spec.Features.OtelCollector.Ports var reqComp feature.RequiredComponents if apiutils.BoolValue(dda.Spec.Features.OtelCollector.Enabled) { From 1175a456e4b92d9d39b551a6f0fa8d28f8abcbcd Mon Sep 17 00:00:00 2001 From: mackjmr Date: Wed, 18 Dec 2024 13:35:35 +0100 Subject: [PATCH 23/28] add support for core config --- api/datadoghq/common/envvar.go | 5 + api/datadoghq/v2alpha1/datadogagent_types.go | 22 +++ api/datadoghq/v2alpha1/test/builder.go | 24 +++ .../v2alpha1/zz_generated.deepcopy.go | 35 +++++ .../v2alpha1/zz_generated.openapi.go | 43 +++++- .../bases/v1/datadoghq.com_datadogagents.yaml | 34 +++++ .../datadoghq.com_datadogagents_v2alpha1.json | 38 +++++ docs/configuration.v2alpha1.md | 3 + .../feature/otelcollector/feature.go | 50 ++++++- .../feature/otelcollector/feature_test.go | 139 +++++++++++++++++- 10 files changed, 383 insertions(+), 10 deletions(-) diff --git a/api/datadoghq/common/envvar.go b/api/datadoghq/common/envvar.go index b25e2ff8c..71d9afb39 100644 --- a/api/datadoghq/common/envvar.go +++ b/api/datadoghq/common/envvar.go @@ -178,6 +178,11 @@ const ( DDOTLPgRPCEndpoint = "DD_OTLP_CONFIG_RECEIVER_PROTOCOLS_GRPC_ENDPOINT" DDOTLPHTTPEndpoint = "DD_OTLP_CONFIG_RECEIVER_PROTOCOLS_HTTP_ENDPOINT" + // otelcollector core agent configs + DDOtelCollectorCoreConfigEnabled = "DD_OTELCOLLECTOR_ENABLED" + DDOtelCollectorCoreConfigExtensionURL = "DD_OTELCOLLECTOR_EXTENSION_URL" + DDOtelCollectorCoreConfigExtensionTimeout = "DD_OTELCOLLECTOR_EXTENSION_TIMEOUT" + // KubernetesEnvvarName Env var used by the Datadog Agent container entrypoint // to add kubelet config provider and listener KubernetesEnvVar = "KUBERNETES" diff --git a/api/datadoghq/v2alpha1/datadogagent_types.go b/api/datadoghq/v2alpha1/datadogagent_types.go index 6ec5ca481..4b3819064 100644 --- a/api/datadoghq/v2alpha1/datadogagent_types.go +++ b/api/datadoghq/v2alpha1/datadogagent_types.go @@ -705,6 +705,28 @@ type OtelCollectorFeatureConfig struct { // This limitation will be lifted once annotations support is removed. // +optional Ports []*corev1.ContainerPort `json:"ports,omitempty"` + + // OTelCollector Config Relevant to the Core agent + // +optional + CoreConfig *CoreConfig `json:"coreConfig,omitempty"` +} + +// CoreConfig exposes the otel collector configs relevant to the core agent. +// +k8s:openapi-gen=true +type CoreConfig struct { + // Enabled marks otelcollector as enabled in core agent. + // +optional + Enabled *bool `json:"enabled,omitempty"` + + // +optional + // Extension URL provides the URL of the ddflareextension to + // the core agent. + ExtensionURL *string `json:"extension_url,omitempty"` + + // +optional + // Extension URL provides the timout of the ddflareextension to + // the core agent. + ExtensionTimeout *int `json:"extension_timeout,omitempty"` } // AdmissionControllerFeatureConfig contains the Admission Controller feature configuration. diff --git a/api/datadoghq/v2alpha1/test/builder.go b/api/datadoghq/v2alpha1/test/builder.go index bd08ef371..b8d754938 100644 --- a/api/datadoghq/v2alpha1/test/builder.go +++ b/api/datadoghq/v2alpha1/test/builder.go @@ -395,6 +395,30 @@ func (builder *DatadogAgentBuilder) WithOTelCollectorConfig() *DatadogAgentBuild return builder } +func (builder *DatadogAgentBuilder) WithOTelCollectorCoreConfigEnabled(enabled bool) *DatadogAgentBuilder { + if builder.datadogAgent.Spec.Features.OtelCollector.CoreConfig == nil { + builder.datadogAgent.Spec.Features.OtelCollector.CoreConfig = &v2alpha1.CoreConfig{} + } + builder.datadogAgent.Spec.Features.OtelCollector.CoreConfig.Enabled = apiutils.NewBoolPointer(enabled) + return builder +} + +func (builder *DatadogAgentBuilder) WithOTelCollectorCoreConfigExtensionTimeout(timeout int) *DatadogAgentBuilder { + if builder.datadogAgent.Spec.Features.OtelCollector.CoreConfig == nil { + builder.datadogAgent.Spec.Features.OtelCollector.CoreConfig = &v2alpha1.CoreConfig{} + } + builder.datadogAgent.Spec.Features.OtelCollector.CoreConfig.ExtensionTimeout = apiutils.NewIntPointer(timeout) + return builder +} + +func (builder *DatadogAgentBuilder) WithOTelCollectorCoreConfigExtensionURL(url string) *DatadogAgentBuilder { + if builder.datadogAgent.Spec.Features.OtelCollector.CoreConfig == nil { + builder.datadogAgent.Spec.Features.OtelCollector.CoreConfig = &v2alpha1.CoreConfig{} + } + builder.datadogAgent.Spec.Features.OtelCollector.CoreConfig.ExtensionURL = apiutils.NewStringPointer(url) + return builder +} + func (builder *DatadogAgentBuilder) WithOTelCollectorConfigMap() *DatadogAgentBuilder { builder.datadogAgent.Spec.Features.OtelCollector.Conf = &v2alpha1.CustomConfig{} builder.datadogAgent.Spec.Features.OtelCollector.Conf.ConfigMap = &v2alpha1.ConfigMapConfig{ diff --git a/api/datadoghq/v2alpha1/zz_generated.deepcopy.go b/api/datadoghq/v2alpha1/zz_generated.deepcopy.go index 2a545d09e..5575562ab 100644 --- a/api/datadoghq/v2alpha1/zz_generated.deepcopy.go +++ b/api/datadoghq/v2alpha1/zz_generated.deepcopy.go @@ -594,6 +594,36 @@ func (in *ConfigMapConfig) DeepCopy() *ConfigMapConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CoreConfig) DeepCopyInto(out *CoreConfig) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.ExtensionURL != nil { + in, out := &in.ExtensionURL, &out.ExtensionURL + *out = new(string) + **out = **in + } + if in.ExtensionTimeout != nil { + in, out := &in.ExtensionTimeout, &out.ExtensionTimeout + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CoreConfig. +func (in *CoreConfig) DeepCopy() *CoreConfig { + if in == nil { + return nil + } + out := new(CoreConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomConfig) DeepCopyInto(out *CustomConfig) { *out = *in @@ -2275,6 +2305,11 @@ func (in *OtelCollectorFeatureConfig) DeepCopyInto(out *OtelCollectorFeatureConf } } } + if in.CoreConfig != nil { + in, out := &in.CoreConfig, &out.CoreConfig + *out = new(CoreConfig) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OtelCollectorFeatureConfig. diff --git a/api/datadoghq/v2alpha1/zz_generated.openapi.go b/api/datadoghq/v2alpha1/zz_generated.openapi.go index 1da105cb3..0568f4e9f 100644 --- a/api/datadoghq/v2alpha1/zz_generated.openapi.go +++ b/api/datadoghq/v2alpha1/zz_generated.openapi.go @@ -18,6 +18,7 @@ import ( func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { return map[string]common.OpenAPIDefinition{ "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CSPMHostBenchmarksConfig": schema_datadog_operator_api_datadoghq_v2alpha1_CSPMHostBenchmarksConfig(ref), + "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CoreConfig": schema_datadog_operator_api_datadoghq_v2alpha1_CoreConfig(ref), "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CustomConfig": schema_datadog_operator_api_datadoghq_v2alpha1_CustomConfig(ref), "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.DaemonSetStatus": schema_datadog_operator_api_datadoghq_v2alpha1_DaemonSetStatus(ref), "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.DatadogAgent": schema_datadog_operator_api_datadoghq_v2alpha1_DatadogAgent(ref), @@ -70,6 +71,40 @@ func schema_datadog_operator_api_datadoghq_v2alpha1_CSPMHostBenchmarksConfig(ref } } +func schema_datadog_operator_api_datadoghq_v2alpha1_CoreConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "CoreConfig exposes the otel collector configs relevant to the core agent.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "enabled": { + SchemaProps: spec.SchemaProps{ + Description: "Enabled marks otelcollector as enabled in core agent.", + Type: []string{"boolean"}, + Format: "", + }, + }, + "extension_url": { + SchemaProps: spec.SchemaProps{ + Description: "Extension URL provides the URL of the ddflareextension to the core agent.", + Type: []string{"string"}, + Format: "", + }, + }, + "extension_timeout": { + SchemaProps: spec.SchemaProps{ + Description: "Extension URL provides the timout of the ddflareextension to the core agent.", + Type: []string{"integer"}, + Format: "int32", + }, + }, + }, + }, + }, + } +} + func schema_datadog_operator_api_datadoghq_v2alpha1_CustomConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -1395,11 +1430,17 @@ func schema_datadog_operator_api_datadoghq_v2alpha1_OtelCollectorFeatureConfig(r }, }, }, + "coreConfig": { + SchemaProps: spec.SchemaProps{ + Description: "OTelCollector Config Relevant to the Core agent", + Ref: ref("github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CoreConfig"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CustomConfig", "k8s.io/api/core/v1.ContainerPort"}, + "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CoreConfig", "github.com/DataDog/datadog-operator/api/datadoghq/v2alpha1.CustomConfig", "k8s.io/api/core/v1.ContainerPort"}, } } diff --git a/config/crd/bases/v1/datadoghq.com_datadogagents.yaml b/config/crd/bases/v1/datadoghq.com_datadogagents.yaml index 4b73c23db..bbc2891e5 100644 --- a/config/crd/bases/v1/datadoghq.com_datadogagents.yaml +++ b/config/crd/bases/v1/datadoghq.com_datadogagents.yaml @@ -1337,6 +1337,23 @@ spec: type: string type: object type: object + coreConfig: + description: OTelCollector Config Relevant to the Core agent + properties: + enabled: + description: Enabled marks otelcollector as enabled in core agent. + type: boolean + extension_timeout: + description: |- + Extension URL provides the timout of the ddflareextension to + the core agent. + type: integer + extension_url: + description: |- + Extension URL provides the URL of the ddflareextension to + the core agent. + type: string + type: object enabled: description: |- Enabled enables the OTel Agent. @@ -8174,6 +8191,23 @@ spec: type: string type: object type: object + coreConfig: + description: OTelCollector Config Relevant to the Core agent + properties: + enabled: + description: Enabled marks otelcollector as enabled in core agent. + type: boolean + extension_timeout: + description: |- + Extension URL provides the timout of the ddflareextension to + the core agent. + type: integer + extension_url: + description: |- + Extension URL provides the URL of the ddflareextension to + the core agent. + type: string + type: object enabled: description: |- Enabled enables the OTel Agent. diff --git a/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json b/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json index 5861b32f1..3e1fb4bff 100644 --- a/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json +++ b/config/crd/bases/v1/datadoghq.com_datadogagents_v2alpha1.json @@ -1388,6 +1388,25 @@ }, "type": "object" }, + "coreConfig": { + "additionalProperties": false, + "description": "OTelCollector Config Relevant to the Core agent", + "properties": { + "enabled": { + "description": "Enabled marks otelcollector as enabled in core agent.", + "type": "boolean" + }, + "extension_timeout": { + "description": "Extension URL provides the timout of the ddflareextension to\nthe core agent.", + "type": "integer" + }, + "extension_url": { + "description": "Extension URL provides the URL of the ddflareextension to\nthe core agent.", + "type": "string" + } + }, + "type": "object" + }, "enabled": { "description": "Enabled enables the OTel Agent.\nDefault: true", "type": "boolean" @@ -8163,6 +8182,25 @@ }, "type": "object" }, + "coreConfig": { + "additionalProperties": false, + "description": "OTelCollector Config Relevant to the Core agent", + "properties": { + "enabled": { + "description": "Enabled marks otelcollector as enabled in core agent.", + "type": "boolean" + }, + "extension_timeout": { + "description": "Extension URL provides the timout of the ddflareextension to\nthe core agent.", + "type": "integer" + }, + "extension_url": { + "description": "Extension URL provides the URL of the ddflareextension to\nthe core agent.", + "type": "string" + } + }, + "type": "object" + }, "enabled": { "description": "Enabled enables the OTel Agent.\nDefault: true", "type": "boolean" diff --git a/docs/configuration.v2alpha1.md b/docs/configuration.v2alpha1.md index 15ce49c51..59a2aabf9 100644 --- a/docs/configuration.v2alpha1.md +++ b/docs/configuration.v2alpha1.md @@ -144,6 +144,9 @@ spec: | features.otelCollector.conf.configData | ConfigData corresponds to the configuration file content. | | features.otelCollector.conf.configMap.items | Maps a ConfigMap data `key` to a file `path` mount. | | features.otelCollector.conf.configMap.name | Is the name of the ConfigMap. | +| features.otelCollector.coreConfig.enabled | Marks otelcollector as enabled in core agent. | +| features.otelCollector.coreConfig.extension_timeout | Extension URL provides the timout of the ddflareextension to the core agent. | +| features.otelCollector.coreConfig.extension_url | Extension URL provides the URL of the ddflareextension to the core agent. | | features.otelCollector.enabled | Enables the OTel Agent. Default: true | | features.otelCollector.ports | Contains the ports for the otel-agent. Defaults: otel-grpc:4317 / otel-http:4318. Note: setting 4317 or 4318 manually is *only* supported if name match default names (otel-grpc, otel-http). If not, this will lead to a port conflict. This limitation will be lifted once annotations support is removed. | | features.otlp.receiver.protocols.grpc.enabled | Enable the OTLP/gRPC endpoint. Host port is enabled by default and can be disabled. | diff --git a/internal/controller/datadogagent/feature/otelcollector/feature.go b/internal/controller/datadogagent/feature/otelcollector/feature.go index 6eb1fa43a..b6a5ff994 100644 --- a/internal/controller/datadogagent/feature/otelcollector/feature.go +++ b/internal/controller/datadogagent/feature/otelcollector/feature.go @@ -33,10 +33,17 @@ func buildOtelCollectorFeature(options *feature.Options) feature.Feature { } type otelCollectorFeature struct { - customConfig *v2alpha1.CustomConfig - owner metav1.Object - configMapName string - ports []*corev1.ContainerPort + customConfig *v2alpha1.CustomConfig + owner metav1.Object + configMapName string + ports []*corev1.ContainerPort + coreAgentConfig coreAgentConfig +} + +type coreAgentConfig struct { + extension_timeout *int + extension_url *string + enabled *bool } func (o otelCollectorFeature) ID() feature.IDType { @@ -50,6 +57,12 @@ func (o *otelCollectorFeature) Configure(dda *v2alpha1.DatadogAgent) feature.Req } o.configMapName = v2alpha1.GetConfName(dda, o.customConfig, v2alpha1.DefaultOTelAgentConf) + if dda.Spec.Features.OtelCollector.CoreConfig != nil { + o.coreAgentConfig.enabled = dda.Spec.Features.OtelCollector.CoreConfig.Enabled + o.coreAgentConfig.extension_timeout = dda.Spec.Features.OtelCollector.CoreConfig.ExtensionTimeout + o.coreAgentConfig.extension_url = dda.Spec.Features.OtelCollector.CoreConfig.ExtensionURL + } + if len(dda.Spec.Features.OtelCollector.Ports) == 0 { o.ports = []*corev1.ContainerPort{ { @@ -158,6 +171,35 @@ func (o otelCollectorFeature) ManageNodeAgent(managers feature.PodTemplateManage managers.Port().AddPortToContainer(apicommon.OtelAgent, port) } + var enableEnvVar *corev1.EnvVar + if o.coreAgentConfig.enabled != nil { + if *o.coreAgentConfig.enabled { + // only need to set env var if true, as it will default to false. + enableEnvVar = &corev1.EnvVar{ + Name: apicommon.DDOtelCollectorCoreConfigEnabled, + Value: apiutils.BoolToString(o.coreAgentConfig.enabled), + } + managers.EnvVar().AddEnvVarToContainers([]apicommon.AgentContainerName{apicommon.CoreAgentContainerName}, enableEnvVar) + } + } else { + managers.EnvVar().AddEnvVarToContainers([]apicommon.AgentContainerName{apicommon.CoreAgentContainerName}, &corev1.EnvVar{ + Name: apicommon.DDOtelCollectorCoreConfigEnabled, + Value: "true", + }) + } + + if o.coreAgentConfig.extension_timeout != nil { + managers.EnvVar().AddEnvVarToContainers([]apicommon.AgentContainerName{apicommon.CoreAgentContainerName}, &corev1.EnvVar{ + Name: apicommon.DDOtelCollectorCoreConfigExtensionTimeout, + Value: strconv.Itoa(*o.coreAgentConfig.extension_timeout), + }) + } + if o.coreAgentConfig.extension_url != nil { + managers.EnvVar().AddEnvVarToContainers([]apicommon.AgentContainerName{apicommon.CoreAgentContainerName}, &corev1.EnvVar{ + Name: apicommon.DDOtelCollectorCoreConfigExtensionURL, + Value: *o.coreAgentConfig.extension_url, + }) + } return nil } diff --git a/internal/controller/datadogagent/feature/otelcollector/feature_test.go b/internal/controller/datadogagent/feature/otelcollector/feature_test.go index d4a7c6a23..1deeea5c2 100644 --- a/internal/controller/datadogagent/feature/otelcollector/feature_test.go +++ b/internal/controller/datadogagent/feature/otelcollector/feature_test.go @@ -25,12 +25,31 @@ type expectedPorts struct { grpcPort int32 } +type expectedEnvVars struct { + enabled expectedEnvVar + extension_timeout expectedEnvVar + extension_url expectedEnvVar +} + +type expectedEnvVar struct { + present bool + value string +} + var ( defaultExpectedPorts = expectedPorts{ httpPort: 4318, grpcPort: 4317, } defaultLocalObjectReferenceName = "-otel-agent-config" + defaultExpectedEnvVars = expectedEnvVars{ + enabled: expectedEnvVar{ + present: true, + value: "true", + }, + extension_timeout: expectedEnvVar{}, + extension_url: expectedEnvVar{}, + } ) func Test_otelCollectorFeature_Configure(t *testing.T) { @@ -60,7 +79,7 @@ func Test_otelCollectorFeature_Configure(t *testing.T) { Build(), WantConfigure: true, WantDependenciesFunc: testExpectedDepsCreatedCM, - Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName), + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, defaultExpectedEnvVars), }, { Name: "otel agent enabled with configMap", @@ -70,7 +89,7 @@ func Test_otelCollectorFeature_Configure(t *testing.T) { Build(), WantConfigure: true, WantDependenciesFunc: testExpectedDepsCreatedCM, - Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, "user-provided-config-map"), + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, "user-provided-config-map", defaultExpectedEnvVars), }, { Name: "otel agent enabled without config", @@ -79,7 +98,7 @@ func Test_otelCollectorFeature_Configure(t *testing.T) { Build(), WantConfigure: true, WantDependenciesFunc: testExpectedDepsCreatedCM, - Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName), + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, defaultExpectedEnvVars), }, { Name: "otel agent enabled without config non default ports", @@ -94,14 +113,92 @@ func Test_otelCollectorFeature_Configure(t *testing.T) { httpPort: 5555, }, defaultLocalObjectReferenceName, + defaultExpectedEnvVars, ), }, + // coreconfig + { + Name: "otel agent coreconfig enabled", + DDA: v2alpha1test.NewDatadogAgentBuilder(). + WithOTelCollectorEnabled(true). + WithOTelCollectorCoreConfigEnabled(true). + Build(), + WantConfigure: true, + WantDependenciesFunc: testExpectedDepsCreatedCM, + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, defaultExpectedEnvVars), + }, + { + Name: "otel agent coreconfig disabled", + DDA: v2alpha1test.NewDatadogAgentBuilder(). + WithOTelCollectorEnabled(true). + WithOTelCollectorCoreConfigEnabled(false). + Build(), + WantConfigure: true, + WantDependenciesFunc: testExpectedDepsCreatedCM, + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, expectedEnvVars{}), + }, + { + Name: "otel agent coreconfig extensionTimeout", + DDA: v2alpha1test.NewDatadogAgentBuilder(). + WithOTelCollectorEnabled(true). + WithOTelCollectorCoreConfigEnabled(false). + WithOTelCollectorCoreConfigExtensionTimeout(13). + Build(), + WantConfigure: true, + WantDependenciesFunc: testExpectedDepsCreatedCM, + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, expectedEnvVars{ + extension_timeout: expectedEnvVar{ + present: true, + value: "13", + }, + }), + }, + { + Name: "otel agent coreconfig extensionURL", + DDA: v2alpha1test.NewDatadogAgentBuilder(). + WithOTelCollectorEnabled(true). + WithOTelCollectorCoreConfigEnabled(false). + WithOTelCollectorCoreConfigExtensionURL("https://localhost:1234"). + Build(), + WantConfigure: true, + WantDependenciesFunc: testExpectedDepsCreatedCM, + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, expectedEnvVars{ + extension_url: expectedEnvVar{ + present: true, + value: "https://localhost:1234", + }, + }), + }, + { + Name: "otel agent coreconfig all env vars", + DDA: v2alpha1test.NewDatadogAgentBuilder(). + WithOTelCollectorEnabled(true). + WithOTelCollectorCoreConfigEnabled(true). + WithOTelCollectorCoreConfigExtensionTimeout(13). + WithOTelCollectorCoreConfigExtensionURL("https://localhost:1234"). + Build(), + WantConfigure: true, + WantDependenciesFunc: testExpectedDepsCreatedCM, + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, expectedEnvVars{ + extension_url: expectedEnvVar{ + present: true, + value: "https://localhost:1234", + }, + extension_timeout: expectedEnvVar{ + present: true, + value: "13", + }, + enabled: expectedEnvVar{ + present: true, + value: "true", + }, + }), + }, } - tests.Run(t, buildOtelCollectorFeature) } -func testExpectedAgent(agentContainerName apicommon.AgentContainerName, expectedPorts expectedPorts, localObjectReferenceName string) *test.ComponentTest { +func testExpectedAgent(agentContainerName apicommon.AgentContainerName, expectedPorts expectedPorts, localObjectReferenceName string, expectedEnvVars expectedEnvVars) *test.ComponentTest { return test.NewDefaultComponentTest().WithWantFunc( func(t testing.TB, mgrInterface feature.PodTemplateManagers) { mgr := mgrInterface.(*fake.PodTemplateManagers) @@ -153,6 +250,38 @@ func testExpectedAgent(agentContainerName apicommon.AgentContainerName, expected ports := mgr.PortMgr.PortsByC[agentContainerName] assert.Equal(t, wantPorts, ports) + + // check env vars + wantEnvVars := []*corev1.EnvVar{} + + if expectedEnvVars.enabled.present { + wantEnvVars = append(wantEnvVars, &corev1.EnvVar{ + Name: apicommon.DDOtelCollectorCoreConfigEnabled, + Value: expectedEnvVars.enabled.value, + }) + } + + if expectedEnvVars.extension_timeout.present { + wantEnvVars = append(wantEnvVars, &corev1.EnvVar{ + Name: apicommon.DDOtelCollectorCoreConfigExtensionTimeout, + Value: expectedEnvVars.extension_timeout.value, + }) + } + + if expectedEnvVars.extension_url.present { + wantEnvVars = append(wantEnvVars, &corev1.EnvVar{ + Name: apicommon.DDOtelCollectorCoreConfigExtensionURL, + Value: expectedEnvVars.extension_url.value, + }) + } + + if len(wantEnvVars) == 0 { + wantEnvVars = nil + } + + agentEnvVars := mgr.EnvVarMgr.EnvVarsByC[apicommon.CoreAgentContainerName] + assert.True(t, apiutils.IsEqualStruct(agentEnvVars, wantEnvVars), "Agent envvars \ndiff = %s", cmp.Diff(agentEnvVars, wantEnvVars)) + }, ) } From d1345c2ca9a0c2983a0bc696b402478ea3edf2d6 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Thu, 19 Dec 2024 13:50:24 +0100 Subject: [PATCH 24/28] Move image to images.go per feedback --- internal/controller/datadogagent/component/agent/default.go | 5 +++-- pkg/defaulting/images.go | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/internal/controller/datadogagent/component/agent/default.go b/internal/controller/datadogagent/component/agent/default.go index 29384d6a3..b5b66f33e 100644 --- a/internal/controller/datadogagent/component/agent/default.go +++ b/internal/controller/datadogagent/component/agent/default.go @@ -105,8 +105,9 @@ func agentImage() string { } func otelAgentImage() string { - // todo(mackjmr): make this dynamic once we have a non-dev image. - return "datadog/agent-dev:nightly-ot-beta-main" + // todo(mackjmr): make this dynamic once we have otel agent image which releases with regular agent. + return fmt.Sprintf("%s:%s", defaulting.AgentDevImageName, defaulting.OTelAgentNightlyTag) + } func initContainers(dda metav1.Object, requiredContainers []apicommon.AgentContainerName) []corev1.Container { diff --git a/pkg/defaulting/images.go b/pkg/defaulting/images.go index 1e1a7b37c..70fcdebb0 100644 --- a/pkg/defaulting/images.go +++ b/pkg/defaulting/images.go @@ -30,7 +30,10 @@ const ( // DefaultImageRegistry corresponds to the datadoghq containers registry DefaultImageRegistry = GCRContainerRegistry // TODO: this is also defined elsewhere and not used; consolidate // JMXTagSuffix prefix tag for agent JMX images - JMXTagSuffix = "-jmx" + JMXTagSuffix = "-jmx" + AgentDevImageName = "datadog/agent-dev" + // Nightly dev image tag for otel agent + OTelAgentNightlyTag = "nightly-ot-beta-main" agentImageName = "agent" clusterAgentImageName = "cluster-agent" From 4a490b76eebe6af198d864293723f237f29331e5 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Thu, 19 Dec 2024 14:14:00 +0100 Subject: [PATCH 25/28] fix test after merge of main --- api/datadoghq/v2alpha1/datadogagent_default_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/datadoghq/v2alpha1/datadogagent_default_test.go b/api/datadoghq/v2alpha1/datadogagent_default_test.go index f1a3cbf33..35804fce8 100644 --- a/api/datadoghq/v2alpha1/datadogagent_default_test.go +++ b/api/datadoghq/v2alpha1/datadogagent_default_test.go @@ -1954,6 +1954,9 @@ func Test_defaultFeatures(t *testing.T) { CWSInstrumentation: &CWSInstrumentationConfig{ Enabled: apiutils.NewBoolPointer(DefaultAdmissionControllerCWSInstrumentationEnabled), }, + KubernetesAdmissionEvents: &KubernetesAdmissionEventsConfig{ + Enabled: apiutils.NewBoolPointer(defaultAdmissionControllerKubernetesAdmissionEventsEnabled), + }, }, PrometheusScrape: &PrometheusScrapeFeatureConfig{ Enabled: apiutils.NewBoolPointer(defaultPrometheusScrapeEnabled), From eb7f68ed7e19750e21340bb83f6087697aef18b1 Mon Sep 17 00:00:00 2001 From: mackjmr Date: Thu, 19 Dec 2024 18:23:15 +0100 Subject: [PATCH 26/28] add non default auth path volume mount, required for staging --- internal/controller/datadogagent/component/agent/default.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/controller/datadogagent/component/agent/default.go b/internal/controller/datadogagent/component/agent/default.go index b5b66f33e..76b2cf918 100644 --- a/internal/controller/datadogagent/component/agent/default.go +++ b/internal/controller/datadogagent/component/agent/default.go @@ -511,6 +511,7 @@ func volumeMountsForSeccompSetup() []corev1.VolumeMount { func volumeMountsForOtelAgent() []corev1.VolumeMount { return []corev1.VolumeMount{ common.GetVolumeMountForConfig(), + common.GetVolumeMountForAuth(true), } } From 7d6166080d2ba602e352d0c0e850076c094582cd Mon Sep 17 00:00:00 2001 From: mackjmr Date: Thu, 19 Dec 2024 18:30:44 +0100 Subject: [PATCH 27/28] add vm logs --- internal/controller/datadogagent/component/agent/default.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/controller/datadogagent/component/agent/default.go b/internal/controller/datadogagent/component/agent/default.go index 76b2cf918..562cbc73a 100644 --- a/internal/controller/datadogagent/component/agent/default.go +++ b/internal/controller/datadogagent/component/agent/default.go @@ -510,6 +510,7 @@ func volumeMountsForSeccompSetup() []corev1.VolumeMount { func volumeMountsForOtelAgent() []corev1.VolumeMount { return []corev1.VolumeMount{ + common.GetVolumeMountForLogs(), common.GetVolumeMountForConfig(), common.GetVolumeMountForAuth(true), } From a4f0b7c0c0b54589a9b5570e6f06f388dfe5a75d Mon Sep 17 00:00:00 2001 From: mackjmr Date: Fri, 20 Dec 2024 17:31:21 +0100 Subject: [PATCH 28/28] change sync delay to 30s --- internal/controller/datadogagent/component/agent/default.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/controller/datadogagent/component/agent/default.go b/internal/controller/datadogagent/component/agent/default.go index 562cbc73a..1461f4b4b 100644 --- a/internal/controller/datadogagent/component/agent/default.go +++ b/internal/controller/datadogagent/component/agent/default.go @@ -215,7 +215,7 @@ func otelAgentContainer(_ metav1.Object) corev1.Container { "otel-agent", "--config=" + v2alpha1.OtelCustomConfigVolumePath, "--core-config=" + v2alpha1.AgentCustomConfigVolumePath, - "--sync-delay=10s", + "--sync-delay=30s", }, Env: []corev1.EnvVar{}, VolumeMounts: volumeMountsForOtelAgent(),