Skip to content

Commit

Permalink
Merge branch 'main' into swang392/refactor-api-const
Browse files Browse the repository at this point in the history
  • Loading branch information
swang392 authored Jan 23, 2025
2 parents 990ef16 + 98ae1c6 commit 1d636f6
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@ func (r *Reconciler) reconcileV2Agent(logger logr.Logger, requiredComponents fea
return r.createOrUpdateDaemonset(daemonsetLogger, dda, daemonset, newStatus, updateDSStatusV2WithAgent, profile)
}

func updateDSStatusV2WithAgent(ds *appsv1.DaemonSet, newStatus *datadoghqv2alpha1.DatadogAgentStatus, updateTime metav1.Time, status metav1.ConditionStatus, reason, message string) {
newStatus.AgentList = condition.UpdateDaemonSetStatus(ds, newStatus.AgentList, &updateTime)
func updateDSStatusV2WithAgent(dsName string, ds *appsv1.DaemonSet, newStatus *datadoghqv2alpha1.DatadogAgentStatus, updateTime metav1.Time, status metav1.ConditionStatus, reason, message string) {
newStatus.AgentList = condition.UpdateDaemonSetStatus(dsName, ds, newStatus.AgentList, &updateTime)
condition.UpdateDatadogAgentStatusConditions(newStatus, updateTime, common.AgentReconcileConditionType, status, reason, message, true)
newStatus.Agent = condition.UpdateCombinedDaemonSetStatus(newStatus.AgentList)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const (
)

type updateDepStatusComponentFunc func(deployment *appsv1.Deployment, newStatus *datadoghqv2alpha1.DatadogAgentStatus, updateTime metav1.Time, status metav1.ConditionStatus, reason, message string)
type updateDSStatusComponentFunc func(daemonset *appsv1.DaemonSet, newStatus *datadoghqv2alpha1.DatadogAgentStatus, updateTime metav1.Time, status metav1.ConditionStatus, reason, message string)
type updateDSStatusComponentFunc func(daemonsetName string, daemonset *appsv1.DaemonSet, newStatus *datadoghqv2alpha1.DatadogAgentStatus, updateTime metav1.Time, status metav1.ConditionStatus, reason, message string)
type updateEDSStatusComponentFunc func(eds *edsv1alpha1.ExtendedDaemonSet, newStatus *datadoghqv2alpha1.DatadogAgentStatus, updateTime metav1.Time, status metav1.ConditionStatus, reason, message string)

func (r *Reconciler) createOrUpdateDeployment(parentLogger logr.Logger, dda *datadoghqv2alpha1.DatadogAgent, deployment *appsv1.Deployment, newStatus *datadoghqv2alpha1.DatadogAgentStatus, updateStatusFunc updateDepStatusComponentFunc) (reconcile.Result, error) {
Expand Down Expand Up @@ -219,7 +219,7 @@ func (r *Reconciler) createOrUpdateDaemonset(parentLogger logr.Logger, dda *data
// Even if the DaemonSet is still the same, its status might have
// changed (for example, the number of pods ready). This call is
// needed to keep the agent status updated.
newStatus.AgentList = condition.UpdateDaemonSetStatus(currentDaemonset, newStatus.AgentList, &now)
newStatus.AgentList = condition.UpdateDaemonSetStatus(currentDaemonset.Name, currentDaemonset, newStatus.AgentList, &now)
newStatus.Agent = condition.UpdateCombinedDaemonSetStatus(newStatus.AgentList)

// Stop reconcile loop since DaemonSet hasn't changed
Expand All @@ -243,12 +243,12 @@ func (r *Reconciler) createOrUpdateDaemonset(parentLogger logr.Logger, dda *data

err = kubernetes.UpdateFromObject(context.TODO(), r.client, updateDaemonset, currentDaemonset.ObjectMeta)
if err != nil {
updateStatusFunc(updateDaemonset, newStatus, now, metav1.ConditionFalse, updateSucceeded, "Unable to update Daemonset")
updateStatusFunc(updateDaemonset.Name, updateDaemonset, newStatus, now, metav1.ConditionFalse, updateSucceeded, "Unable to update Daemonset")
return reconcile.Result{}, err
}
event := buildEventInfo(updateDaemonset.Name, updateDaemonset.Namespace, kubernetes.DaemonSetKind, datadog.UpdateEvent)
r.recordEvent(dda, event)
updateStatusFunc(updateDaemonset, newStatus, now, metav1.ConditionTrue, updateSucceeded, "Daemonset updated")
updateStatusFunc(updateDaemonset.Name, updateDaemonset, newStatus, now, metav1.ConditionTrue, updateSucceeded, "Daemonset updated")
} else {
// From here the PodTemplateSpec should be ready, we can generate the hash that will be added to this daemonset.
_, err = comparison.SetMD5DatadogAgentGenerationAnnotation(&daemonset.ObjectMeta, daemonset.Spec)
Expand All @@ -260,12 +260,12 @@ func (r *Reconciler) createOrUpdateDaemonset(parentLogger logr.Logger, dda *data

err = r.client.Create(context.TODO(), daemonset)
if err != nil {
updateStatusFunc(nil, newStatus, now, metav1.ConditionFalse, createSucceeded, "Unable to create Daemonset")
updateStatusFunc(daemonset.Name, nil, newStatus, now, metav1.ConditionFalse, createSucceeded, "Unable to create Daemonset")
return reconcile.Result{}, err
}
event := buildEventInfo(daemonset.Name, daemonset.Namespace, kubernetes.DaemonSetKind, datadog.CreationEvent)
r.recordEvent(dda, event)
updateStatusFunc(daemonset, newStatus, now, metav1.ConditionTrue, createSucceeded, "Daemonset created")
updateStatusFunc(daemonset.Name, daemonset, newStatus, now, metav1.ConditionTrue, createSucceeded, "Daemonset created")
}

logger.Info("Creating Daemonset")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
53 changes: 45 additions & 8 deletions internal/controller/datadogagent/feature/otelcollector/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ import (
"github.com/DataDog/datadog-operator/internal/controller/datadogagent/common"
"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"
)
Expand All @@ -26,7 +30,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 {
Expand All @@ -35,6 +45,11 @@ type otelCollectorFeature struct {
configMapName string
ports []*corev1.ContainerPort
coreAgentConfig coreAgentConfig

customConfigAnnotationKey string
customConfigAnnotationValue string

logger logr.Logger
}

type coreAgentConfig struct {
Expand All @@ -43,7 +58,7 @@ type coreAgentConfig struct {
enabled *bool
}

func (o otelCollectorFeature) ID() feature.IDType {
func (o *otelCollectorFeature) ID() feature.IDType {
return feature.OtelAgentIDType
}

Expand Down Expand Up @@ -97,12 +112,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{}
Expand Down Expand Up @@ -134,11 +166,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
Expand All @@ -161,6 +193,11 @@ func (o otelCollectorFeature) ManageNodeAgent(managers feature.PodTemplateManage
volMount := volume.GetVolumeMountWithSubPath(otelAgentVolumeName, common.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.
Expand Down Expand Up @@ -200,10 +237,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
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ var (
}
)

var defaultAnnotations = map[string]string{"checksum/otel_agent-custom-config": "07f4530ba2b36a9279f070daa769454e"}

func Test_otelCollectorFeature_Configure(t *testing.T) {
tests := test.FeatureTestSuite{
// disabled
Expand Down Expand Up @@ -80,7 +82,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",
Expand All @@ -90,7 +92,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",
Expand All @@ -99,7 +101,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",
Expand All @@ -115,6 +117,7 @@ func Test_otelCollectorFeature_Configure(t *testing.T) {
},
defaultLocalObjectReferenceName,
defaultExpectedEnvVars,
map[string]string{"checksum/otel_agent-custom-config": "8aeb28718c1afdd92cd7d48d24950727"},
),
},
// coreconfig
Expand All @@ -126,7 +129,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",
Expand All @@ -136,7 +139,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",
Expand All @@ -152,7 +155,8 @@ func Test_otelCollectorFeature_Configure(t *testing.T) {
present: true,
value: "13",
},
}),
},
defaultAnnotations),
},
{
Name: "otel agent coreconfig extensionURL",
Expand All @@ -168,7 +172,8 @@ func Test_otelCollectorFeature_Configure(t *testing.T) {
present: true,
value: "https://localhost:1234",
},
}),
},
defaultAnnotations),
},
{
Name: "otel agent coreconfig all env vars",
Expand All @@ -193,13 +198,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)
Expand Down Expand Up @@ -283,6 +289,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)
},
)
}
Expand Down
67 changes: 34 additions & 33 deletions pkg/condition/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,47 +149,48 @@ func UpdateDeploymentStatus(dep *appsv1.Deployment, depStatus *v2alpha1.Deployme
}

// UpdateDaemonSetStatus updates a daemonset's DaemonSetStatus
func UpdateDaemonSetStatus(ds *appsv1.DaemonSet, dsStatus []*v2alpha1.DaemonSetStatus, updateTime *metav1.Time) []*v2alpha1.DaemonSetStatus {
func UpdateDaemonSetStatus(dsName string, ds *appsv1.DaemonSet, dsStatus []*v2alpha1.DaemonSetStatus, updateTime *metav1.Time) []*v2alpha1.DaemonSetStatus {
if dsStatus == nil {
dsStatus = []*v2alpha1.DaemonSetStatus{}
}
if ds == nil {
dsStatus = append(dsStatus, &v2alpha1.DaemonSetStatus{
State: string(DatadogAgentStateFailed),
Status: string(DatadogAgentStateFailed),
})
return dsStatus
}

newStatus := v2alpha1.DaemonSetStatus{
Desired: ds.Status.DesiredNumberScheduled,
Current: ds.Status.CurrentNumberScheduled,
Ready: ds.Status.NumberReady,
Available: ds.Status.NumberAvailable,
UpToDate: ds.Status.UpdatedNumberScheduled,
DaemonsetName: ds.ObjectMeta.Name,
}
var newStatus v2alpha1.DaemonSetStatus
if ds == nil {
newStatus = v2alpha1.DaemonSetStatus{
State: string(DatadogAgentStateFailed),
Status: string(DatadogAgentStateFailed),
DaemonsetName: dsName,
}
} else {
newStatus = v2alpha1.DaemonSetStatus{
Desired: ds.Status.DesiredNumberScheduled,
Current: ds.Status.CurrentNumberScheduled,
Ready: ds.Status.NumberReady,
Available: ds.Status.NumberAvailable,
UpToDate: ds.Status.UpdatedNumberScheduled,
DaemonsetName: ds.ObjectMeta.Name,
}
if updateTime != nil {
newStatus.LastUpdate = updateTime
}
if hash, ok := ds.Annotations[v2alpha1.MD5AgentDeploymentAnnotationKey]; ok {

Check failure on line 176 in pkg/condition/condition.go

View workflow job for this annotation

GitHub Actions / build

undefined: v2alpha1.MD5AgentDeploymentAnnotationKey

Check failure on line 176 in pkg/condition/condition.go

View workflow job for this annotation

GitHub Actions / build

undefined: v2alpha1.MD5AgentDeploymentAnnotationKey

Check failure on line 176 in pkg/condition/condition.go

View workflow job for this annotation

GitHub Actions / build

undefined: v2alpha1.MD5AgentDeploymentAnnotationKey

Check failure on line 176 in pkg/condition/condition.go

View workflow job for this annotation

GitHub Actions / build

undefined: v2alpha1.MD5AgentDeploymentAnnotationKey
newStatus.CurrentHash = hash
}

if updateTime != nil {
newStatus.LastUpdate = updateTime
}
if hash, ok := ds.Annotations[constants.MD5AgentDeploymentAnnotationKey]; ok {
newStatus.CurrentHash = hash
}
var deploymentState DatadogAgentState
switch {
case newStatus.UpToDate != newStatus.Desired:
deploymentState = DatadogAgentStateUpdating
case newStatus.Ready == 0 && newStatus.Desired != 0:
deploymentState = DatadogAgentStateProgressing
default:
deploymentState = DatadogAgentStateRunning
}

var deploymentState DatadogAgentState
switch {
case newStatus.UpToDate != newStatus.Desired:
deploymentState = DatadogAgentStateUpdating
case newStatus.Ready == 0 && newStatus.Desired != 0:
deploymentState = DatadogAgentStateProgressing
default:
deploymentState = DatadogAgentStateRunning
newStatus.State = fmt.Sprintf("%v", deploymentState)
newStatus.Status = fmt.Sprintf("%v (%d/%d/%d)", deploymentState, newStatus.Desired, newStatus.Ready, newStatus.UpToDate)
}

newStatus.State = fmt.Sprintf("%v", deploymentState)
newStatus.Status = fmt.Sprintf("%v (%d/%d/%d)", deploymentState, newStatus.Desired, newStatus.Ready, newStatus.UpToDate)

// match ds name to ds status
found := false
for id := range dsStatus {
Expand Down
Loading

0 comments on commit 1d636f6

Please sign in to comment.