diff --git a/internal/controller/datadogagent/controller_reconcile_agent.go b/internal/controller/datadogagent/controller_reconcile_agent.go index 54fcdb42d..c2bd34fcd 100644 --- a/internal/controller/datadogagent/controller_reconcile_agent.go +++ b/internal/controller/datadogagent/controller_reconcile_agent.go @@ -378,7 +378,7 @@ func (r *Reconciler) cleanupPodsForProfilesThatNoLongerApply(ctx context.Context Name: agentPod.Name, }, } - if err = r.client.Delete(ctx, &toDelete); err != nil { + if err = r.client.Delete(ctx, &toDelete); err != nil && !errors.IsNotFound(err) { return err } } diff --git a/internal/controller/datadogagent/controller_reconcile_agent_test.go b/internal/controller/datadogagent/controller_reconcile_agent_test.go index 4cc45bdd4..307aaebc9 100644 --- a/internal/controller/datadogagent/controller_reconcile_agent_test.go +++ b/internal/controller/datadogagent/controller_reconcile_agent_test.go @@ -1841,3 +1841,226 @@ func Test_labelNodesWithProfiles(t *testing.T) { }) } } + +func Test_cleanupPodsForProfilesThatNoLongerApply(t *testing.T) { + sch := runtime.NewScheme() + _ = scheme.AddToScheme(sch) + ctx := context.Background() + + testCases := []struct { + name string + description string + profilesByNode map[string]types.NamespacedName + ddaNamespace string + existingPods []client.Object + wantPods []corev1.Pod + }{ + { + name: "delete agent pod that shouldn't be running", + description: "pod-2 should be deleted", + profilesByNode: map[string]types.NamespacedName{ + "node-1": { + Namespace: "foo", + Name: "profile-1", + }, + "node-2": { + Namespace: "foo", + Name: "profile-2", + }, + "node-default": { + Namespace: "", + Name: "default", + }, + }, + ddaNamespace: "foo", + existingPods: []client.Object{ + &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-1", + Namespace: "foo", + Labels: map[string]string{ + apicommon.AgentDeploymentComponentLabelKey: constants.DefaultAgentResourceSuffix, + agentprofile.ProfileLabelKey: "profile-1", + }, + }, + Spec: corev1.PodSpec{ + NodeName: "node-1", + }, + }, + &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-2", + Namespace: "foo", + Labels: map[string]string{ + apicommon.AgentDeploymentComponentLabelKey: constants.DefaultAgentResourceSuffix, + agentprofile.ProfileLabelKey: "profile-1", + }, + }, + Spec: corev1.PodSpec{ + NodeName: "node-2", + }, + }, + }, + wantPods: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-1", + Namespace: "foo", + Labels: map[string]string{ + apicommon.AgentDeploymentComponentLabelKey: constants.DefaultAgentResourceSuffix, + agentprofile.ProfileLabelKey: "profile-1", + }, + ResourceVersion: "999", + }, + Spec: corev1.PodSpec{ + NodeName: "node-1", + }, + }, + }, + }, + { + name: "delete default agent on profile node", + description: "pod-2 should be deleted", + profilesByNode: map[string]types.NamespacedName{ + "node-1": { + Namespace: "foo", + Name: "profile-1", + }, + "node-2": { + Namespace: "foo", + Name: "profile-2", + }, + "node-default": { + Namespace: "", + Name: "default", + }, + }, + ddaNamespace: "foo", + existingPods: []client.Object{ + &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-1", + Namespace: "foo", + Labels: map[string]string{ + apicommon.AgentDeploymentComponentLabelKey: constants.DefaultAgentResourceSuffix, + agentprofile.ProfileLabelKey: "profile-1", + }, + }, + Spec: corev1.PodSpec{ + NodeName: "node-1", + }, + }, + &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-default", + Namespace: "foo", + Labels: map[string]string{ + apicommon.AgentDeploymentComponentLabelKey: constants.DefaultAgentResourceSuffix, + }, + }, + Spec: corev1.PodSpec{ + NodeName: "node-2", + }, + }, + }, + wantPods: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-1", + Namespace: "foo", + Labels: map[string]string{ + apicommon.AgentDeploymentComponentLabelKey: constants.DefaultAgentResourceSuffix, + agentprofile.ProfileLabelKey: "profile-1", + }, + ResourceVersion: "999", + }, + Spec: corev1.PodSpec{ + NodeName: "node-1", + }, + }, + }, + }, + { + name: "delete profile agent on default node", + description: "pod-2 should be deleted", + profilesByNode: map[string]types.NamespacedName{ + "node-1": { + Namespace: "foo", + Name: "profile-1", + }, + "node-2": { + Namespace: "foo", + Name: "profile-2", + }, + "node-default": { + Namespace: "", + Name: "default", + }, + }, + ddaNamespace: "foo", + existingPods: []client.Object{ + &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-1", + Namespace: "foo", + Labels: map[string]string{ + apicommon.AgentDeploymentComponentLabelKey: constants.DefaultAgentResourceSuffix, + agentprofile.ProfileLabelKey: "profile-1", + }, + }, + Spec: corev1.PodSpec{ + NodeName: "node-1", + }, + }, + &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-2", + Namespace: "foo", + Labels: map[string]string{ + apicommon.AgentDeploymentComponentLabelKey: constants.DefaultAgentResourceSuffix, + agentprofile.ProfileLabelKey: "profile-2", + }, + }, + Spec: corev1.PodSpec{ + NodeName: "node-default", + }, + }, + }, + wantPods: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-1", + Namespace: "foo", + Labels: map[string]string{ + apicommon.AgentDeploymentComponentLabelKey: constants.DefaultAgentResourceSuffix, + agentprofile.ProfileLabelKey: "profile-1", + }, + ResourceVersion: "999", + }, + Spec: corev1.PodSpec{ + NodeName: "node-1", + }, + }, + }, + }, + } + + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + fakeClient := fake.NewClientBuilder().WithScheme(sch).WithObjects(tt.existingPods...).Build() + + r := &Reconciler{ + client: fakeClient, + } + + err := r.cleanupPodsForProfilesThatNoLongerApply(ctx, tt.profilesByNode, tt.ddaNamespace) + assert.NoError(t, err) + + podList := &corev1.PodList{} + err = fakeClient.List(ctx, podList) + assert.NoError(t, err) + assert.Len(t, podList.Items, len(tt.wantPods)) + assert.Equal(t, tt.wantPods, podList.Items) + }) + } +}