From 2798ece0cf263954dcf266f7a6728047b091c832 Mon Sep 17 00:00:00 2001 From: khewonc <39867936+khewonc@users.noreply.github.com> Date: Thu, 16 Jan 2025 10:32:26 -0500 Subject: [PATCH] Add otel collector configdata annotations --- .../feature/otelcollector/configmap_test.go | 3 ++ .../feature/otelcollector/feature.go | 53 ++++++++++++++++--- .../feature/otelcollector/feature_test.go | 27 ++++++---- 3 files changed, 66 insertions(+), 17 deletions(-) diff --git a/internal/controller/datadogagent/feature/otelcollector/configmap_test.go b/internal/controller/datadogagent/feature/otelcollector/configmap_test.go index 2a5c46aad..0fa9a8c6f 100644 --- a/internal/controller/datadogagent/feature/otelcollector/configmap_test.go +++ b/internal/controller/datadogagent/feature/otelcollector/configmap_test.go @@ -21,6 +21,9 @@ func Test_buildOtelCollectorConfigMap(t *testing.T) { configMapWant := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "-otel-agent-config", + Annotations: map[string]string{ + "checksum/otel_agent-custom-config": "07f4530ba2b36a9279f070daa769454e", + }, }, Data: map[string]string{ "otel-config.yaml": defaultconfig.DefaultOtelCollectorConfig, diff --git a/internal/controller/datadogagent/feature/otelcollector/feature.go b/internal/controller/datadogagent/feature/otelcollector/feature.go index 69083073d..c888ee932 100644 --- a/internal/controller/datadogagent/feature/otelcollector/feature.go +++ b/internal/controller/datadogagent/feature/otelcollector/feature.go @@ -9,10 +9,14 @@ 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/otelcollector/defaultconfig" + "github.com/DataDog/datadog-operator/internal/controller/datadogagent/object" "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/constants" + "github.com/DataDog/datadog-operator/pkg/controller/utils/comparison" "github.com/DataDog/datadog-operator/pkg/kubernetes" + + "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -30,7 +34,13 @@ func init() { } func buildOtelCollectorFeature(options *feature.Options) feature.Feature { - return &otelCollectorFeature{} + otelCollectorFeat := &otelCollectorFeature{} + + if options != nil { + otelCollectorFeat.logger = options.Logger + } + + return otelCollectorFeat } type otelCollectorFeature struct { @@ -39,6 +49,11 @@ type otelCollectorFeature struct { configMapName string ports []*corev1.ContainerPort coreAgentConfig coreAgentConfig + + customConfigAnnotationKey string + customConfigAnnotationValue string + + logger logr.Logger } type coreAgentConfig struct { @@ -47,7 +62,7 @@ type coreAgentConfig struct { enabled *bool } -func (o otelCollectorFeature) ID() feature.IDType { +func (o *otelCollectorFeature) ID() feature.IDType { return feature.OtelAgentIDType } @@ -101,12 +116,29 @@ func (o *otelCollectorFeature) Configure(dda *v2alpha1.DatadogAgent) feature.Req 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) + cm, err := configmap.BuildConfigMapConfigData(o.owner.GetNamespace(), o.customConfig.ConfigData, o.configMapName, otelConfigFileName) + if err != nil { + return nil, err + } + + // Add md5 hash annotation for configMap + o.customConfigAnnotationKey = object.GetChecksumAnnotationKey(feature.OtelAgentIDType) + o.customConfigAnnotationValue, err = comparison.GenerateMD5ForSpec(o.customConfig.ConfigData) + if err != nil { + return cm, err + } + + if o.customConfigAnnotationKey != "" && o.customConfigAnnotationValue != "" { + annotations := object.MergeAnnotationsLabels(o.logger, cm.Annotations, map[string]string{o.customConfigAnnotationKey: o.customConfigAnnotationValue}, "*") + cm.SetAnnotations(annotations) + } + + return cm, nil } return nil, nil } -func (o otelCollectorFeature) 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{} @@ -138,11 +170,11 @@ func (o otelCollectorFeature) ManageDependencies(managers feature.ResourceManage return nil } -func (o otelCollectorFeature) ManageClusterAgent(managers feature.PodTemplateManagers) error { +func (o *otelCollectorFeature) ManageClusterAgent(managers feature.PodTemplateManagers) error { return nil } -func (o otelCollectorFeature) 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 @@ -165,6 +197,11 @@ func (o otelCollectorFeature) ManageNodeAgent(managers feature.PodTemplateManage volMount := volume.GetVolumeMountWithSubPath(otelAgentVolumeName, v2alpha1.ConfigVolumePath+"/"+otelConfigFileName, otelConfigFileName) managers.VolumeMount().AddVolumeMountToContainer(&volMount, apicommon.OtelAgent) + // Add md5 hash annotation for configMap + if o.customConfigAnnotationKey != "" && o.customConfigAnnotationValue != "" { + managers.Annotation().AddAnnotation(o.customConfigAnnotationKey, o.customConfigAnnotationValue) + } + // add ports for _, port := range o.ports { // bind container port to host port. @@ -204,10 +241,10 @@ func (o otelCollectorFeature) ManageNodeAgent(managers feature.PodTemplateManage return nil } -func (o otelCollectorFeature) ManageSingleContainerNodeAgent(managers feature.PodTemplateManagers, provider string) error { +func (o *otelCollectorFeature) ManageSingleContainerNodeAgent(managers feature.PodTemplateManagers, provider string) error { return nil } -func (o otelCollectorFeature) ManageClusterChecksRunner(managers feature.PodTemplateManagers) error { +func (o *otelCollectorFeature) ManageClusterChecksRunner(managers feature.PodTemplateManagers) error { return nil } diff --git a/internal/controller/datadogagent/feature/otelcollector/feature_test.go b/internal/controller/datadogagent/feature/otelcollector/feature_test.go index 5f8c39d62..f2591c13a 100644 --- a/internal/controller/datadogagent/feature/otelcollector/feature_test.go +++ b/internal/controller/datadogagent/feature/otelcollector/feature_test.go @@ -52,6 +52,8 @@ var ( } ) +var defaultAnnotations = map[string]string{"checksum/otel_agent-custom-config": "07f4530ba2b36a9279f070daa769454e"} + func Test_otelCollectorFeature_Configure(t *testing.T) { tests := test.FeatureTestSuite{ // disabled @@ -79,7 +81,7 @@ func Test_otelCollectorFeature_Configure(t *testing.T) { Build(), WantConfigure: true, WantDependenciesFunc: testExpectedDepsCreatedCM, - Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, defaultExpectedEnvVars), + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, defaultExpectedEnvVars, defaultAnnotations), }, { Name: "otel agent enabled with configMap", @@ -89,7 +91,7 @@ func Test_otelCollectorFeature_Configure(t *testing.T) { Build(), WantConfigure: true, WantDependenciesFunc: testExpectedDepsCreatedCM, - Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, "user-provided-config-map", defaultExpectedEnvVars), + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, "user-provided-config-map", defaultExpectedEnvVars, map[string]string{}), }, { Name: "otel agent enabled without config", @@ -98,7 +100,7 @@ func Test_otelCollectorFeature_Configure(t *testing.T) { Build(), WantConfigure: true, WantDependenciesFunc: testExpectedDepsCreatedCM, - Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, defaultExpectedEnvVars), + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, defaultExpectedEnvVars, defaultAnnotations), }, { Name: "otel agent enabled without config non default ports", @@ -114,6 +116,7 @@ func Test_otelCollectorFeature_Configure(t *testing.T) { }, defaultLocalObjectReferenceName, defaultExpectedEnvVars, + map[string]string{"checksum/otel_agent-custom-config": "8aeb28718c1afdd92cd7d48d24950727"}, ), }, // coreconfig @@ -125,7 +128,7 @@ func Test_otelCollectorFeature_Configure(t *testing.T) { Build(), WantConfigure: true, WantDependenciesFunc: testExpectedDepsCreatedCM, - Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, defaultExpectedEnvVars), + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, defaultExpectedEnvVars, defaultAnnotations), }, { Name: "otel agent coreconfig disabled", @@ -135,7 +138,7 @@ func Test_otelCollectorFeature_Configure(t *testing.T) { Build(), WantConfigure: true, WantDependenciesFunc: testExpectedDepsCreatedCM, - Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, expectedEnvVars{}), + Agent: testExpectedAgent(apicommon.OtelAgent, defaultExpectedPorts, defaultLocalObjectReferenceName, expectedEnvVars{}, defaultAnnotations), }, { Name: "otel agent coreconfig extensionTimeout", @@ -151,7 +154,8 @@ func Test_otelCollectorFeature_Configure(t *testing.T) { present: true, value: "13", }, - }), + }, + defaultAnnotations), }, { Name: "otel agent coreconfig extensionURL", @@ -167,7 +171,8 @@ func Test_otelCollectorFeature_Configure(t *testing.T) { present: true, value: "https://localhost:1234", }, - }), + }, + defaultAnnotations), }, { Name: "otel agent coreconfig all env vars", @@ -192,13 +197,14 @@ func Test_otelCollectorFeature_Configure(t *testing.T) { present: true, value: "true", }, - }), + }, + defaultAnnotations), }, } tests.Run(t, buildOtelCollectorFeature) } -func testExpectedAgent(agentContainerName apicommon.AgentContainerName, expectedPorts expectedPorts, localObjectReferenceName string, expectedEnvVars expectedEnvVars) *test.ComponentTest { +func testExpectedAgent(agentContainerName apicommon.AgentContainerName, expectedPorts expectedPorts, localObjectReferenceName string, expectedEnvVars expectedEnvVars, expectedAnnotations map[string]string) *test.ComponentTest { return test.NewDefaultComponentTest().WithWantFunc( func(t testing.TB, mgrInterface feature.PodTemplateManagers) { mgr := mgrInterface.(*fake.PodTemplateManagers) @@ -282,6 +288,9 @@ func testExpectedAgent(agentContainerName apicommon.AgentContainerName, expected agentEnvVars := mgr.EnvVarMgr.EnvVarsByC[apicommon.CoreAgentContainerName] assert.True(t, apiutils.IsEqualStruct(agentEnvVars, wantEnvVars), "Agent envvars \ndiff = %s", cmp.Diff(agentEnvVars, wantEnvVars)) + // annotations + agentAnnotations := mgr.AnnotationMgr.Annotations + assert.Equal(t, expectedAnnotations, agentAnnotations) }, ) }