diff --git a/.chloggen/2947-updating-ds-sf-depl-mutation.yaml b/.chloggen/2947-updating-ds-sf-depl-mutation.yaml
new file mode 100755
index 0000000000..e5b2f62a44
--- /dev/null
+++ b/.chloggen/2947-updating-ds-sf-depl-mutation.yaml
@@ -0,0 +1,16 @@
+# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
+change_type: bug_fix
+
+# The name of the component, or a single word describing the area of concern, (e.g. collector, target allocator, auto-instrumentation, opamp, github action)
+component: collector
+
+# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
+note: "Fix mutation of deployments, statefulsets, and daemonsets allowing to remove fields on update"
+
+# One or more tracking issues related to the change
+issues: [2947]
+
+# (Optional) One or more lines of additional information to render under the primary note.
+# These lines will be padded with 2 spaces and then inserted directly into the document.
+# Use pipe (|) for multiline entries.
+subtext:
diff --git a/controllers/common.go b/controllers/common.go
index 3003907913..01b254128a 100644
--- a/controllers/common.go
+++ b/controllers/common.go
@@ -155,7 +155,7 @@ func reconcileDesiredObjects(ctx context.Context, kubeClient client.Client, logg
 			op = result
 			return createOrUpdateErr
 		})
-		if crudErr != nil && errors.Is(crudErr, manifests.ImmutableChangeErr) {
+		if crudErr != nil && errors.As(crudErr, &manifests.ImmutableChangeErr) {
 			l.Error(crudErr, "detected immutable field change, trying to delete, new object will be created on next reconcile", "existing", existing.GetName())
 			delErr := kubeClient.Delete(ctx, existing)
 			if delErr != nil {
diff --git a/internal/manifests/mutate.go b/internal/manifests/mutate.go
index 27b4e31266..fb9399346c 100644
--- a/internal/manifests/mutate.go
+++ b/internal/manifests/mutate.go
@@ -15,7 +15,6 @@
 package manifests
 
 import (
-	"errors"
 	"fmt"
 	"reflect"
 
@@ -34,8 +33,16 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 )
 
+type ImmutableFieldChangeErr struct {
+	Field string
+}
+
+func (e *ImmutableFieldChangeErr) Error() string {
+	return fmt.Sprintf("Immutable field change attempted: %s", e.Field)
+}
+
 var (
-	ImmutableChangeErr = errors.New("immutable field change attempted")
+	ImmutableChangeErr *ImmutableFieldChangeErr
 )
 
 // MutateFuncFor returns a mutate function based on the
@@ -189,10 +196,6 @@ func mergeWithOverride(dst, src interface{}) error {
 	return mergo.Merge(dst, src, mergo.WithOverride)
 }
 
-func mergeWithOverwriteWithEmptyValue(dst, src interface{}) error {
-	return mergo.Merge(dst, src, mergo.WithOverwriteWithEmptyValue)
-}
-
 func mutateSecret(existing, desired *corev1.Secret) {
 	existing.Labels = desired.Labels
 	existing.Annotations = desired.Annotations
@@ -276,68 +279,82 @@ func mutateService(existing, desired *corev1.Service) {
 }
 
 func mutateDaemonset(existing, desired *appsv1.DaemonSet) error {
-	if !existing.CreationTimestamp.IsZero() && !apiequality.Semantic.DeepEqual(desired.Spec.Selector, existing.Spec.Selector) {
-		return ImmutableChangeErr
-	}
-	// Daemonset selector is immutable so we set this value only if
-	// a new object is going to be created
-	if existing.CreationTimestamp.IsZero() {
-		existing.Spec.Selector = desired.Spec.Selector
-	}
-	if err := mergeWithOverride(&existing.Spec, desired.Spec); err != nil {
-		return err
+	if !existing.CreationTimestamp.IsZero() {
+		if !apiequality.Semantic.DeepEqual(desired.Spec.Selector, existing.Spec.Selector) {
+			return &ImmutableFieldChangeErr{Field: "Spec.Selector"}
+		}
+		if err := hasImmutableLabelChange(existing.Spec.Selector.MatchLabels, desired.Spec.Template.Labels); err != nil {
+			return err
+		}
 	}
-	if err := mergeWithOverwriteWithEmptyValue(&existing.Spec.Template.Spec.NodeSelector, desired.Spec.Template.Spec.NodeSelector); err != nil {
+
+	existing.Spec.MinReadySeconds = desired.Spec.MinReadySeconds
+	existing.Spec.RevisionHistoryLimit = desired.Spec.RevisionHistoryLimit
+	existing.Spec.UpdateStrategy = desired.Spec.UpdateStrategy
+
+	if err := mutatePodTemplate(&existing.Spec.Template, &desired.Spec.Template); err != nil {
 		return err
 	}
+
 	return nil
 }
 
 func mutateDeployment(existing, desired *appsv1.Deployment) error {
-	if !existing.CreationTimestamp.IsZero() && !apiequality.Semantic.DeepEqual(desired.Spec.Selector, existing.Spec.Selector) {
-		return ImmutableChangeErr
-	}
-	// Deployment selector is immutable so we set this value only if
-	// a new object is going to be created
-	if existing.CreationTimestamp.IsZero() {
-		existing.Spec.Selector = desired.Spec.Selector
+	if !existing.CreationTimestamp.IsZero() {
+		if !apiequality.Semantic.DeepEqual(desired.Spec.Selector, existing.Spec.Selector) {
+			return &ImmutableFieldChangeErr{Field: "Spec.Selector"}
+		}
+		if err := hasImmutableLabelChange(existing.Spec.Selector.MatchLabels, desired.Spec.Template.Labels); err != nil {
+			return err
+		}
 	}
+
+	existing.Spec.MinReadySeconds = desired.Spec.MinReadySeconds
+	existing.Spec.Paused = desired.Spec.Paused
+	existing.Spec.ProgressDeadlineSeconds = desired.Spec.ProgressDeadlineSeconds
 	existing.Spec.Replicas = desired.Spec.Replicas
-	if err := mergeWithOverride(&existing.Spec.Template, desired.Spec.Template); err != nil {
-		return err
-	}
-	if err := mergeWithOverwriteWithEmptyValue(&existing.Spec.Template.Spec.NodeSelector, desired.Spec.Template.Spec.NodeSelector); err != nil {
-		return err
-	}
-	if err := mergeWithOverride(&existing.Spec.Strategy, desired.Spec.Strategy); err != nil {
+	existing.Spec.RevisionHistoryLimit = desired.Spec.RevisionHistoryLimit
+	existing.Spec.Strategy = desired.Spec.Strategy
+
+	if err := mutatePodTemplate(&existing.Spec.Template, &desired.Spec.Template); err != nil {
 		return err
 	}
+
 	return nil
 }
 
 func mutateStatefulSet(existing, desired *appsv1.StatefulSet) error {
-	if hasChange, field := hasImmutableFieldChange(existing, desired); hasChange {
-		return fmt.Errorf("%s is being changed, %w", field, ImmutableChangeErr)
-	}
-	// StatefulSet selector is immutable so we set this value only if
-	// a new object is going to be created
-	if existing.CreationTimestamp.IsZero() {
-		existing.Spec.Selector = desired.Spec.Selector
+	if !existing.CreationTimestamp.IsZero() {
+		if !apiequality.Semantic.DeepEqual(desired.Spec.Selector, existing.Spec.Selector) {
+			return &ImmutableFieldChangeErr{Field: "Spec.Selector"}
+		}
+		if err := hasImmutableLabelChange(existing.Spec.Selector.MatchLabels, desired.Spec.Template.Labels); err != nil {
+			return err
+		}
+		if hasVolumeClaimsTemplatesChanged(existing, desired) {
+			return &ImmutableFieldChangeErr{Field: "Spec.VolumeClaimTemplates"}
+		}
 	}
+
+	existing.Spec.MinReadySeconds = desired.Spec.MinReadySeconds
+	existing.Spec.Ordinals = desired.Spec.Ordinals
+	existing.Spec.PersistentVolumeClaimRetentionPolicy = desired.Spec.PersistentVolumeClaimRetentionPolicy
 	existing.Spec.PodManagementPolicy = desired.Spec.PodManagementPolicy
 	existing.Spec.Replicas = desired.Spec.Replicas
+	existing.Spec.RevisionHistoryLimit = desired.Spec.RevisionHistoryLimit
+	existing.Spec.ServiceName = desired.Spec.ServiceName
+	existing.Spec.UpdateStrategy = desired.Spec.UpdateStrategy
 
 	for i := range existing.Spec.VolumeClaimTemplates {
 		existing.Spec.VolumeClaimTemplates[i].TypeMeta = desired.Spec.VolumeClaimTemplates[i].TypeMeta
 		existing.Spec.VolumeClaimTemplates[i].ObjectMeta = desired.Spec.VolumeClaimTemplates[i].ObjectMeta
 		existing.Spec.VolumeClaimTemplates[i].Spec = desired.Spec.VolumeClaimTemplates[i].Spec
 	}
-	if err := mergeWithOverride(&existing.Spec.Template, desired.Spec.Template); err != nil {
-		return err
-	}
-	if err := mergeWithOverwriteWithEmptyValue(&existing.Spec.Template.Spec.NodeSelector, desired.Spec.Template.Spec.NodeSelector); err != nil {
+
+	if err := mutatePodTemplate(&existing.Spec.Template, &desired.Spec.Template); err != nil {
 		return err
 	}
+
 	return nil
 }
 
@@ -353,19 +370,28 @@ func mutateIssuer(existing, desired *cmv1.Issuer) {
 	existing.Spec = desired.Spec
 }
 
-func hasImmutableFieldChange(existing, desired *appsv1.StatefulSet) (bool, string) {
-	if existing.CreationTimestamp.IsZero() {
-		return false, ""
-	}
-	if !apiequality.Semantic.DeepEqual(desired.Spec.Selector, existing.Spec.Selector) {
-		return true, fmt.Sprintf("Spec.Selector: desired: %s existing: %s", desired.Spec.Selector, existing.Spec.Selector)
+func mutatePodTemplate(existing, desired *corev1.PodTemplateSpec) error {
+	if err := mergeWithOverride(&existing.Labels, desired.Labels); err != nil {
+		return err
 	}
 
-	if hasVolumeClaimsTemplatesChanged(existing, desired) {
-		return true, "Spec.VolumeClaimTemplates"
+	if err := mergeWithOverride(&existing.Annotations, desired.Annotations); err != nil {
+		return err
 	}
 
-	return false, ""
+	existing.Spec = desired.Spec
+
+	return nil
+
+}
+
+func hasImmutableLabelChange(existingSelectorLabels, desiredLabels map[string]string) error {
+	for k, v := range existingSelectorLabels {
+		if vv, ok := desiredLabels[k]; !ok || vv != v {
+			return &ImmutableFieldChangeErr{Field: "Spec.Template.Metadata.Labels"}
+		}
+	}
+	return nil
 }
 
 // hasVolumeClaimsTemplatesChanged if volume claims template change has been detected.
@@ -388,6 +414,9 @@ func hasVolumeClaimsTemplatesChanged(existing, desired *appsv1.StatefulSet) bool
 		if !apiequality.Semantic.DeepEqual(desired.Spec.VolumeClaimTemplates[i].Annotations, existing.Spec.VolumeClaimTemplates[i].Annotations) {
 			return true
 		}
+		if !apiequality.Semantic.DeepEqual(desired.Spec.VolumeClaimTemplates[i].Labels, existing.Spec.VolumeClaimTemplates[i].Labels) {
+			return true
+		}
 		if !apiequality.Semantic.DeepEqual(desired.Spec.VolumeClaimTemplates[i].Spec, existing.Spec.VolumeClaimTemplates[i].Spec) {
 			return true
 		}
diff --git a/internal/manifests/mutate_test.go b/internal/manifests/mutate_test.go
index c165c8535c..6009aa007d 100644
--- a/internal/manifests/mutate_test.go
+++ b/internal/manifests/mutate_test.go
@@ -19,6 +19,7 @@ import (
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
@@ -48,3 +49,2446 @@ func TestMutateServiceAccount(t *testing.T) {
 		},
 	}, existing)
 }
+
+func TestMutateDaemonsetAdditionalContainers(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.DaemonSet
+		desired  appsv1.DaemonSet
+	}{
+		{
+			name: "add container to daemonset",
+			existing: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+								{
+									Name:  "alpine",
+									Image: "alpine:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "remove container from daemonset",
+			existing: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+								{
+									Name:  "alpine",
+									Image: "alpine:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "modify container in daemonset",
+			existing: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+								{
+									Name:  "alpine",
+									Image: "alpine:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+								{
+									Name:  "alpine",
+									Image: "alpine:1.0",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			require.NoError(t, err)
+			assert.Equal(t, tt.existing, tt.desired)
+		})
+	}
+}
+
+func TestMutateDeploymentAdditionalContainers(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.Deployment
+		desired  appsv1.Deployment
+	}{
+		{
+			name: "add container to deployment",
+			existing: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+								{
+									Name:  "alpine",
+									Image: "alpine:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "remove container from deployment",
+			existing: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+								{
+									Name:  "alpine",
+									Image: "alpine:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "modify container in deployment",
+			existing: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+								{
+									Name:  "alpine",
+									Image: "alpine:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+								{
+									Name:  "alpine",
+									Image: "alpine:1.0",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			require.NoError(t, err)
+			assert.Equal(t, tt.existing, tt.desired)
+		})
+	}
+}
+
+func TestMutateStatefulSetAdditionalContainers(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.StatefulSet
+		desired  appsv1.StatefulSet
+	}{
+		{
+			name: "add container to statefulset",
+			existing: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+								{
+									Name:  "alpine",
+									Image: "alpine:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "remove container from statefulset",
+			existing: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+								{
+									Name:  "alpine",
+									Image: "alpine:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "modify container in statefulset",
+			existing: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+								{
+									Name:  "alpine",
+									Image: "alpine:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+								{
+									Name:  "alpine",
+									Image: "alpine:1.0",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			require.NoError(t, err)
+			assert.Equal(t, tt.existing, tt.desired)
+		})
+	}
+}
+
+func TestMutateDaemonsetAffinity(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.DaemonSet
+		desired  appsv1.DaemonSet
+	}{
+		{
+			name: "add affinity to daemonset",
+			existing: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+							Affinity: &corev1.Affinity{
+								NodeAffinity: &corev1.NodeAffinity{
+									RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
+										NodeSelectorTerms: []corev1.NodeSelectorTerm{
+											{
+												MatchFields: []corev1.NodeSelectorRequirement{
+													{
+														Key:      "kubernetes.io/os",
+														Operator: corev1.NodeSelectorOpIn,
+														Values:   []string{"linux"},
+													},
+												},
+											},
+										},
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "remove affinity from daemonset",
+			existing: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+							Affinity: &corev1.Affinity{
+								NodeAffinity: &corev1.NodeAffinity{
+									RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
+										NodeSelectorTerms: []corev1.NodeSelectorTerm{
+											{
+												MatchFields: []corev1.NodeSelectorRequirement{
+													{
+														Key:      "kubernetes.io/os",
+														Operator: corev1.NodeSelectorOpIn,
+														Values:   []string{"linux"},
+													},
+												},
+											},
+										},
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "modify affinity in daemonset",
+			existing: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+							Affinity: &corev1.Affinity{
+								NodeAffinity: &corev1.NodeAffinity{
+									RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
+										NodeSelectorTerms: []corev1.NodeSelectorTerm{
+											{
+												MatchFields: []corev1.NodeSelectorRequirement{
+													{
+														Key:      "kubernetes.io/os",
+														Operator: corev1.NodeSelectorOpIn,
+														Values:   []string{"linux"},
+													},
+												},
+											},
+										},
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+							Affinity: &corev1.Affinity{
+								NodeAffinity: &corev1.NodeAffinity{
+									RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
+										NodeSelectorTerms: []corev1.NodeSelectorTerm{
+											{
+												MatchFields: []corev1.NodeSelectorRequirement{
+													{
+														Key:      "kubernetes.io/os",
+														Operator: corev1.NodeSelectorOpIn,
+														Values:   []string{"windows"},
+													},
+												},
+											},
+										},
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			require.NoError(t, err)
+			assert.Equal(t, tt.existing, tt.desired)
+		})
+	}
+}
+
+func TestMutateDeploymentAffinity(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.Deployment
+		desired  appsv1.Deployment
+	}{
+		{
+			name: "add affinity to deployment",
+			existing: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+							Affinity: &corev1.Affinity{
+								NodeAffinity: &corev1.NodeAffinity{
+									RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
+										NodeSelectorTerms: []corev1.NodeSelectorTerm{
+											{
+												MatchFields: []corev1.NodeSelectorRequirement{
+													{
+														Key:      "kubernetes.io/os",
+														Operator: corev1.NodeSelectorOpIn,
+														Values:   []string{"linux"},
+													},
+												},
+											},
+										},
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "remove affinity from deployment",
+			existing: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+							Affinity: &corev1.Affinity{
+								NodeAffinity: &corev1.NodeAffinity{
+									RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
+										NodeSelectorTerms: []corev1.NodeSelectorTerm{
+											{
+												MatchFields: []corev1.NodeSelectorRequirement{
+													{
+														Key:      "kubernetes.io/os",
+														Operator: corev1.NodeSelectorOpIn,
+														Values:   []string{"linux"},
+													},
+												},
+											},
+										},
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "modify affinity in deployment",
+			existing: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+							Affinity: &corev1.Affinity{
+								NodeAffinity: &corev1.NodeAffinity{
+									RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
+										NodeSelectorTerms: []corev1.NodeSelectorTerm{
+											{
+												MatchFields: []corev1.NodeSelectorRequirement{
+													{
+														Key:      "kubernetes.io/os",
+														Operator: corev1.NodeSelectorOpIn,
+														Values:   []string{"linux"},
+													},
+												},
+											},
+										},
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+							Affinity: &corev1.Affinity{
+								NodeAffinity: &corev1.NodeAffinity{
+									RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
+										NodeSelectorTerms: []corev1.NodeSelectorTerm{
+											{
+												MatchFields: []corev1.NodeSelectorRequirement{
+													{
+														Key:      "kubernetes.io/os",
+														Operator: corev1.NodeSelectorOpIn,
+														Values:   []string{"windows"},
+													},
+												},
+											},
+										},
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			require.NoError(t, err)
+			assert.Equal(t, tt.existing, tt.desired)
+		})
+	}
+}
+
+func TestMutateStatefulSetAffinity(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.StatefulSet
+		desired  appsv1.StatefulSet
+	}{
+		{
+			name: "add affinity to statefulset",
+			existing: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+							Affinity: &corev1.Affinity{
+								NodeAffinity: &corev1.NodeAffinity{
+									RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
+										NodeSelectorTerms: []corev1.NodeSelectorTerm{
+											{
+												MatchFields: []corev1.NodeSelectorRequirement{
+													{
+														Key:      "kubernetes.io/os",
+														Operator: corev1.NodeSelectorOpIn,
+														Values:   []string{"linux"},
+													},
+												},
+											},
+										},
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "remove affinity from statefulset",
+			existing: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+							Affinity: &corev1.Affinity{
+								NodeAffinity: &corev1.NodeAffinity{
+									RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
+										NodeSelectorTerms: []corev1.NodeSelectorTerm{
+											{
+												MatchFields: []corev1.NodeSelectorRequirement{
+													{
+														Key:      "kubernetes.io/os",
+														Operator: corev1.NodeSelectorOpIn,
+														Values:   []string{"linux"},
+													},
+												},
+											},
+										},
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "modify affinity in statefulset",
+			existing: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+							Affinity: &corev1.Affinity{
+								NodeAffinity: &corev1.NodeAffinity{
+									RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
+										NodeSelectorTerms: []corev1.NodeSelectorTerm{
+											{
+												MatchFields: []corev1.NodeSelectorRequirement{
+													{
+														Key:      "kubernetes.io/os",
+														Operator: corev1.NodeSelectorOpIn,
+														Values:   []string{"linux"},
+													},
+												},
+											},
+										},
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+							Affinity: &corev1.Affinity{
+								NodeAffinity: &corev1.NodeAffinity{
+									RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
+										NodeSelectorTerms: []corev1.NodeSelectorTerm{
+											{
+												MatchFields: []corev1.NodeSelectorRequirement{
+													{
+														Key:      "kubernetes.io/os",
+														Operator: corev1.NodeSelectorOpIn,
+														Values:   []string{"windows"},
+													},
+												},
+											},
+										},
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			require.NoError(t, err)
+			assert.Equal(t, tt.existing, tt.desired)
+		})
+	}
+}
+
+func TestMutateDaemonsetCollectorArgs(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.DaemonSet
+		desired  appsv1.DaemonSet
+	}{
+		{
+			name: "add argument to collector container in daemonset",
+			existing: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true"},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true", "extra-arg=yes"},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "remove extra arg from collector container in daemonset",
+			existing: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true", "extra-arg=yes"},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true"},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "modify extra arg in collector container in daemonset",
+			existing: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true", "extra-arg=yes"},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true", "extra-arg=no"},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			require.NoError(t, err)
+			assert.Equal(t, tt.existing, tt.desired)
+		})
+	}
+}
+
+func TestMutateDeploymentCollectorArgs(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.Deployment
+		desired  appsv1.Deployment
+	}{
+		{
+			name: "add argument to collector container in deployment",
+			existing: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true"},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true", "extra-arg=yes"},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "remove extra arg from collector container in deployment",
+			existing: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true", "extra-arg=yes"},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true"},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "modify extra arg in collector container in deployment",
+			existing: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true", "extra-arg=yes"},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true", "extra-arg=no"},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			require.NoError(t, err)
+			assert.Equal(t, tt.existing, tt.desired)
+		})
+	}
+}
+
+func TestMutateStatefulSetCollectorArgs(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.StatefulSet
+		desired  appsv1.StatefulSet
+	}{
+		{
+			name: "add argument to collector container in statefulset",
+			existing: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true"},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true", "extra-arg=yes"},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "remove extra arg from collector container in statefulset",
+			existing: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true", "extra-arg=yes"},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true"},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "modify extra arg in collector container in statefulset",
+			existing: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true", "extra-arg=yes"},
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Template: corev1.PodTemplateSpec{
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+									Args:  []string{"--default-arg=true", "extra-arg=no"},
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			require.NoError(t, err)
+			assert.Equal(t, tt.existing, tt.desired)
+		})
+	}
+}
+
+func TestNoImmutableLabelChange(t *testing.T) {
+	existingSelectorLabels := map[string]string{
+		"app.kubernetes.io/component":  "opentelemetry-collector",
+		"app.kubernetes.io/instance":   "default.deployment",
+		"app.kubernetes.io/managed-by": "opentelemetry-operator",
+		"app.kubernetes.io/part-of":    "opentelemetry",
+	}
+	desiredLabels := map[string]string{
+		"app.kubernetes.io/component":  "opentelemetry-collector",
+		"app.kubernetes.io/instance":   "default.deployment",
+		"app.kubernetes.io/managed-by": "opentelemetry-operator",
+		"app.kubernetes.io/part-of":    "opentelemetry",
+		"extra-label":                  "true",
+	}
+	err := hasImmutableLabelChange(existingSelectorLabels, desiredLabels)
+	require.NoError(t, err)
+	assert.NoError(t, err)
+}
+
+func TestHasImmutableLabelChange(t *testing.T) {
+	existingSelectorLabels := map[string]string{
+		"app.kubernetes.io/component":  "opentelemetry-collector",
+		"app.kubernetes.io/instance":   "default.deployment",
+		"app.kubernetes.io/managed-by": "opentelemetry-operator",
+		"app.kubernetes.io/part-of":    "opentelemetry",
+	}
+	desiredLabels := map[string]string{
+		"app.kubernetes.io/component":  "opentelemetry-collector",
+		"app.kubernetes.io/instance":   "default.deployment",
+		"app.kubernetes.io/managed-by": "opentelemetry-operator",
+		"app.kubernetes.io/part-of":    "not-opentelemetry",
+	}
+	err := hasImmutableLabelChange(existingSelectorLabels, desiredLabels)
+	assert.Error(t, err)
+}
+
+func TestMissingImmutableLabelChange(t *testing.T) {
+	existingSelectorLabels := map[string]string{
+		"app.kubernetes.io/component":  "opentelemetry-collector",
+		"app.kubernetes.io/instance":   "default.deployment",
+		"app.kubernetes.io/managed-by": "opentelemetry-operator",
+		"app.kubernetes.io/part-of":    "opentelemetry",
+	}
+	desiredLabels := map[string]string{
+		"app.kubernetes.io/component":  "opentelemetry-collector",
+		"app.kubernetes.io/instance":   "default.deployment",
+		"app.kubernetes.io/managed-by": "opentelemetry-operator",
+	}
+	err := hasImmutableLabelChange(existingSelectorLabels, desiredLabels)
+	assert.Error(t, err)
+}
+
+func TestMutateDaemonsetError(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.DaemonSet
+		desired  appsv1.DaemonSet
+	}{
+		{
+			name: "modified immutable label in daemonset",
+			existing: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					CreationTimestamp: metav1.Now(),
+					Name:              "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.daemonset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.daemonset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.daemonset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.daemonset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "not-opentelemetry",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "modified immutable selector in daemonset",
+			existing: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					CreationTimestamp: metav1.Now(),
+					Name:              "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.daemonset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.daemonset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.daemonset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "not-opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.daemonset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			assert.Error(t, err)
+		})
+	}
+}
+
+func TestMutateDeploymentError(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.Deployment
+		desired  appsv1.Deployment
+	}{
+		{
+			name: "modified immutable label in deployment",
+			existing: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					CreationTimestamp: metav1.Now(),
+					Name:              "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.deployment",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.deployment",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.deployment",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.deployment",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "not-opentelemetry",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "modified immutable selector in deployment",
+			existing: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					CreationTimestamp: metav1.Now(),
+					Name:              "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.deployment",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.deployment",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.deployment",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "not-opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.deployment",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			assert.Error(t, err)
+		})
+	}
+}
+
+func TestMutateStatefulSetError(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.StatefulSet
+		desired  appsv1.StatefulSet
+	}{
+		{
+			name: "modified immutable label in statefulset",
+			existing: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					CreationTimestamp: metav1.Now(),
+					Name:              "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.statefulset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.statefulset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.statefulset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.statefulset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "not-opentelemetry",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "modified immutable selector in statefulset",
+			existing: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					CreationTimestamp: metav1.Now(),
+					Name:              "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.statefulset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.statefulset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.statefulset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "not-opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.statefulset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			assert.Error(t, err)
+		})
+	}
+}
+
+func TestMutateDaemonsetLabelChange(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.DaemonSet
+		desired  appsv1.DaemonSet
+	}{
+		{
+			name: "modified label in daemonset",
+			existing: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					CreationTimestamp: metav1.Now(),
+					Name:              "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.daemonset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.daemonset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+								"user-label":                   "existing",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.daemonset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.daemonset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+								"user-label":                   "desired",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "new label in daemonset",
+			existing: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					CreationTimestamp: metav1.Now(),
+					Name:              "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.daemonset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.daemonset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+								"user-label":                   "existing",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.DaemonSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "daemonset",
+				},
+				Spec: appsv1.DaemonSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.daemonset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.daemonset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+								"user-label":                   "existing",
+								"new-user-label":               "desired",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			require.NoError(t, err)
+			assert.Equal(t, tt.existing.Spec, tt.desired.Spec)
+		})
+	}
+}
+
+func TestMutateDeploymentLabelChange(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.Deployment
+		desired  appsv1.Deployment
+	}{
+		{
+			name: "modified label in deployment",
+			existing: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					CreationTimestamp: metav1.Now(),
+					Name:              "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.deployment",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.deployment",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+								"user-label":                   "existing",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.deployment",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.deployment",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+								"user-label":                   "desired",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "new label in deployment",
+			existing: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					CreationTimestamp: metav1.Now(),
+					Name:              "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.deployment",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.deployment",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+								"user-label":                   "existing",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.Deployment{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "deployment",
+				},
+				Spec: appsv1.DeploymentSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.deployment",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.deployment",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+								"user-label":                   "existing",
+								"new-user-label":               "desired",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			require.NoError(t, err)
+			assert.Equal(t, tt.existing.Spec, tt.desired.Spec)
+		})
+	}
+}
+
+func TestMutateStatefulSetLabelChange(t *testing.T) {
+	tests := []struct {
+		name     string
+		existing appsv1.StatefulSet
+		desired  appsv1.StatefulSet
+	}{
+		{
+			name: "modified label in statefulset",
+			existing: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					CreationTimestamp: metav1.Now(),
+					Name:              "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.statefulset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.statefulset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+								"user-label":                   "existing",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.statefulset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.statefulset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+								"user-label":                   "desired",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		{
+			name: "new label in statefulset",
+			existing: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					CreationTimestamp: metav1.Now(),
+					Name:              "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.statefulset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.statefulset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+								"user-label":                   "existing",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+			desired: appsv1.StatefulSet{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "statefulset",
+				},
+				Spec: appsv1.StatefulSetSpec{
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"app.kubernetes.io/component":  "opentelemetry-collector",
+							"app.kubernetes.io/instance":   "default.statefulset",
+							"app.kubernetes.io/managed-by": "opentelemetry-operator",
+							"app.kubernetes.io/part-of":    "opentelemetry",
+						},
+					},
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								"app.kubernetes.io/component":  "opentelemetry-collector",
+								"app.kubernetes.io/instance":   "default.statefulset",
+								"app.kubernetes.io/managed-by": "opentelemetry-operator",
+								"app.kubernetes.io/part-of":    "opentelemetry",
+								"user-label":                   "existing",
+								"new-user-label":               "desired",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "collector",
+									Image: "collector:latest",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			mutateFn := MutateFuncFor(&tt.existing, &tt.desired)
+			err := mutateFn()
+			require.NoError(t, err)
+			assert.Equal(t, tt.existing.Spec, tt.desired.Spec)
+		})
+	}
+}
diff --git a/tests/e2e/additional-containers-collector/00-assert-daemonset-without-additional-containers.yaml b/tests/e2e/additional-containers-collector/00-assert-daemonset-without-additional-containers.yaml
new file mode 100644
index 0000000000..9c9a9588a2
--- /dev/null
+++ b/tests/e2e/additional-containers-collector/00-assert-daemonset-without-additional-containers.yaml
@@ -0,0 +1,14 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: daemonset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    additional-containers: without
+spec:
+  template:
+    spec:
+      (containers[?image == 'alpine' && name == 'alpine']):
+        (length(@)): 0
diff --git a/tests/e2e/additional-containers-collector/00-assert-deployment-without-additional-containers.yaml b/tests/e2e/additional-containers-collector/00-assert-deployment-without-additional-containers.yaml
new file mode 100644
index 0000000000..8fbcd2fb4b
--- /dev/null
+++ b/tests/e2e/additional-containers-collector/00-assert-deployment-without-additional-containers.yaml
@@ -0,0 +1,14 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: deployment-collector
+    app.kubernetes.io/part-of: opentelemetry
+    additional-containers: without
+spec:
+  template:
+    spec:
+      (containers[?image == 'alpine' && name == 'alpine']):
+        (length(@)): 0
diff --git a/tests/e2e/additional-containers-collector/00-assert-statefulset-without-additional-containers.yaml b/tests/e2e/additional-containers-collector/00-assert-statefulset-without-additional-containers.yaml
new file mode 100644
index 0000000000..25896fd560
--- /dev/null
+++ b/tests/e2e/additional-containers-collector/00-assert-statefulset-without-additional-containers.yaml
@@ -0,0 +1,14 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: statefulset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    additional-containers: without
+spec:
+  template:
+    spec:
+      (containers[?image == 'alpine' && name == 'alpine']):
+        (length(@)): 0
diff --git a/tests/e2e/additional-containers-collector/00-install-collectors-without-additional-containers.yaml b/tests/e2e/additional-containers-collector/00-install-collectors-without-additional-containers.yaml
new file mode 100644
index 0000000000..392395ce4d
--- /dev/null
+++ b/tests/e2e/additional-containers-collector/00-install-collectors-without-additional-containers.yaml
@@ -0,0 +1,73 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+  labels:
+    additional-containers: without
+spec:
+  mode: deployment
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+  labels:
+    additional-containers: without
+spec:
+  mode: daemonset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+  labels:
+    additional-containers: without
+spec:
+  mode: statefulset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/additional-containers-collector/01-assert-daemonset-with-additional-containers.yaml b/tests/e2e/additional-containers-collector/01-assert-daemonset-with-additional-containers.yaml
new file mode 100644
index 0000000000..77427d8cef
--- /dev/null
+++ b/tests/e2e/additional-containers-collector/01-assert-daemonset-with-additional-containers.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: daemonset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    additional-containers: with
+spec:
+  template:
+    spec:
+      (containers[?image == 'alpine' && name == 'alpine']):
+        (length(@)): 1
+      (containers[?image == 'alpine' && name == 'alpine2']):
+        (length(@)): 1
diff --git a/tests/e2e/additional-containers-collector/01-assert-deployment-with-additional-containers.yaml b/tests/e2e/additional-containers-collector/01-assert-deployment-with-additional-containers.yaml
new file mode 100644
index 0000000000..cae1197c53
--- /dev/null
+++ b/tests/e2e/additional-containers-collector/01-assert-deployment-with-additional-containers.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: deployment-collector
+    app.kubernetes.io/part-of: opentelemetry
+    additional-containers: with
+spec:
+  template:
+    spec:
+      (containers[?image == 'alpine' && name == 'alpine']):
+        (length(@)): 1
+      (containers[?image == 'alpine' && name == 'alpine2']):
+        (length(@)): 1
diff --git a/tests/e2e/additional-containers-collector/01-assert-statefulset-with-additional-containers.yaml b/tests/e2e/additional-containers-collector/01-assert-statefulset-with-additional-containers.yaml
new file mode 100644
index 0000000000..34496ba36c
--- /dev/null
+++ b/tests/e2e/additional-containers-collector/01-assert-statefulset-with-additional-containers.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: statefulset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    additional-containers: with
+spec:
+  template:
+    spec:
+      (containers[?image == 'alpine' && name == 'alpine']):
+        (length(@)): 1
+      (containers[?image == 'alpine' && name == 'alpine2']):
+        (length(@)): 1
diff --git a/tests/e2e/additional-containers-collector/01-install-collectors-with-additional-containers.yaml b/tests/e2e/additional-containers-collector/01-install-collectors-with-additional-containers.yaml
new file mode 100644
index 0000000000..ae03e35ee1
--- /dev/null
+++ b/tests/e2e/additional-containers-collector/01-install-collectors-with-additional-containers.yaml
@@ -0,0 +1,88 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+  labels:
+    additional-containers: with
+spec:
+  mode: deployment
+  additionalContainers:
+  - image: alpine
+    name: alpine
+  - image: alpine
+    name: alpine2
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+  labels:
+    additional-containers: with
+spec:
+  mode: daemonset
+  additionalContainers:
+  - image: alpine
+    name: alpine
+  - image: alpine
+    name: alpine2
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+  labels:
+    additional-containers: with
+spec:
+  mode: statefulset
+  additionalContainers:
+  - image: alpine
+    name: alpine
+  - image: alpine
+    name: alpine2
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/additional-containers-collector/02-assert-daemonset-with-modified-additional-containers.yaml b/tests/e2e/additional-containers-collector/02-assert-daemonset-with-modified-additional-containers.yaml
new file mode 100644
index 0000000000..7d45a9bad7
--- /dev/null
+++ b/tests/e2e/additional-containers-collector/02-assert-daemonset-with-modified-additional-containers.yaml
@@ -0,0 +1,18 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: daemonset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    additional-containers: with
+spec:
+  template:
+    spec:
+      (containers[?image == 'alpine' && name == 'alpine']):
+        (length(@)): 0
+      (containers[?image == 'alpine' && name == 'alpine2']):
+        (length(@)): 0
+      (containers[?image == 'alpine' && name == 'alpine3']):
+        (length(@)): 1
diff --git a/tests/e2e/additional-containers-collector/02-assert-deployment-with-modified-additional-containers.yaml b/tests/e2e/additional-containers-collector/02-assert-deployment-with-modified-additional-containers.yaml
new file mode 100644
index 0000000000..12fc910899
--- /dev/null
+++ b/tests/e2e/additional-containers-collector/02-assert-deployment-with-modified-additional-containers.yaml
@@ -0,0 +1,18 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: deployment-collector
+    app.kubernetes.io/part-of: opentelemetry
+    additional-containers: with
+spec:
+  template:
+    spec:
+      (containers[?image == 'alpine' && name == 'alpine']):
+        (length(@)): 0
+      (containers[?image == 'alpine' && name == 'alpine2']):
+        (length(@)): 0
+      (containers[?image == 'alpine' && name == 'alpine3']):
+        (length(@)): 1
diff --git a/tests/e2e/additional-containers-collector/02-assert-statefulset-with-modified-additional-containers.yaml b/tests/e2e/additional-containers-collector/02-assert-statefulset-with-modified-additional-containers.yaml
new file mode 100644
index 0000000000..4de3a7ffcd
--- /dev/null
+++ b/tests/e2e/additional-containers-collector/02-assert-statefulset-with-modified-additional-containers.yaml
@@ -0,0 +1,18 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: statefulset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    additional-containers: with
+spec:
+  template:
+    spec:
+      (containers[?image == 'alpine' && name == 'alpine']):
+        (length(@)): 0
+      (containers[?image == 'alpine' && name == 'alpine2']):
+        (length(@)): 0
+      (containers[?image == 'alpine' && name == 'alpine3']):
+        (length(@)): 1
diff --git a/tests/e2e/additional-containers-collector/02-modify-collectors-additional-containers.yaml b/tests/e2e/additional-containers-collector/02-modify-collectors-additional-containers.yaml
new file mode 100644
index 0000000000..45397baece
--- /dev/null
+++ b/tests/e2e/additional-containers-collector/02-modify-collectors-additional-containers.yaml
@@ -0,0 +1,82 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+  labels:
+    additional-containers: with
+spec:
+  mode: deployment
+  additionalContainers:
+  - image: alpine
+    name: alpine3
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+  labels:
+    additional-containers: with
+spec:
+  mode: daemonset
+  additionalContainers:
+  - image: alpine
+    name: alpine3
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+  labels:
+    additional-containers: with
+spec:
+  mode: statefulset
+  additionalContainers:
+  - image: alpine
+    name: alpine3
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/additional-containers-collector/chainsaw-test.yaml b/tests/e2e/additional-containers-collector/chainsaw-test.yaml
new file mode 100644
index 0000000000..64b47db477
--- /dev/null
+++ b/tests/e2e/additional-containers-collector/chainsaw-test.yaml
@@ -0,0 +1,66 @@
+# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json
+apiVersion: chainsaw.kyverno.io/v1alpha1
+kind: Test
+metadata:
+  name: additional-containers-collector
+spec:
+  steps:
+    - name: step-00
+      description: collectors without additionalContainers
+      try:
+        - apply:
+            file: 00-install-collectors-without-additional-containers.yaml
+        # deployment
+        - assert:
+            file: 00-assert-deployment-without-additional-containers.yaml
+        # daemonset
+        - assert:
+            file: 00-assert-daemonset-without-additional-containers.yaml
+        # statefulset
+        - assert:
+            file: 00-assert-statefulset-without-additional-containers.yaml
+
+    - name: step-01
+      description: collectors with additionalContainers
+      try:
+        - update:
+            file: 01-install-collectors-with-additional-containers.yaml
+        # deployment
+        - assert:
+            file: 01-assert-deployment-with-additional-containers.yaml
+        # daemonset
+        - assert:
+            file: 01-assert-daemonset-with-additional-containers.yaml
+        # statefulset
+        - assert:
+            file: 01-assert-statefulset-with-additional-containers.yaml
+
+    - name: step-02
+      description: modify additionalContainers
+      try:
+        - update:
+            file: 02-modify-collectors-additional-containers.yaml
+        # deployment
+        - assert:
+            file: 02-assert-deployment-with-modified-additional-containers.yaml
+        # daemonset
+        - assert:
+            file: 02-assert-daemonset-with-modified-additional-containers.yaml
+        # statefulset
+        - assert:
+            file: 02-assert-statefulset-with-modified-additional-containers.yaml
+
+    - name: step-03
+      description: delete additionalContainers
+      try:
+        - update:
+            file: 00-install-collectors-without-additional-containers.yaml
+        # deployment
+        - assert:
+            file: 00-assert-deployment-without-additional-containers.yaml
+        # daemonset
+        - assert:
+            file: 00-assert-daemonset-without-additional-containers.yaml
+        # statefulset
+        - assert:
+            file: 00-assert-statefulset-without-additional-containers.yaml
diff --git a/tests/e2e/affinity-collector/00-assert-daemonset-without-affinity.yaml b/tests/e2e/affinity-collector/00-assert-daemonset-without-affinity.yaml
new file mode 100644
index 0000000000..5f3c249b12
--- /dev/null
+++ b/tests/e2e/affinity-collector/00-assert-daemonset-without-affinity.yaml
@@ -0,0 +1,13 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: daemonset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    affinity: without
+spec:
+  template:
+    spec:
+      (affinity == null): true
diff --git a/tests/e2e/affinity-collector/00-assert-deployment-without-affinity.yaml b/tests/e2e/affinity-collector/00-assert-deployment-without-affinity.yaml
new file mode 100644
index 0000000000..2af7d10f9f
--- /dev/null
+++ b/tests/e2e/affinity-collector/00-assert-deployment-without-affinity.yaml
@@ -0,0 +1,13 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: deployment-collector
+    app.kubernetes.io/part-of: opentelemetry
+    affinity: without
+spec:
+  template:
+    spec:
+      (affinity == null): true
diff --git a/tests/e2e/affinity-collector/00-assert-statefulset-without-affinity.yaml b/tests/e2e/affinity-collector/00-assert-statefulset-without-affinity.yaml
new file mode 100644
index 0000000000..2e267cf6a4
--- /dev/null
+++ b/tests/e2e/affinity-collector/00-assert-statefulset-without-affinity.yaml
@@ -0,0 +1,13 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: statefulset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    affinity: without
+spec:
+  template:
+    spec:
+      (affinity == null): true
diff --git a/tests/e2e/affinity-collector/00-install-collectors-without-affinity.yaml b/tests/e2e/affinity-collector/00-install-collectors-without-affinity.yaml
new file mode 100644
index 0000000000..77e50adc36
--- /dev/null
+++ b/tests/e2e/affinity-collector/00-install-collectors-without-affinity.yaml
@@ -0,0 +1,73 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+  labels:
+    affinity: without
+spec:
+  mode: deployment
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+  labels:
+    affinity: without
+spec:
+  mode: daemonset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+  labels:
+    affinity: without
+spec:
+  mode: statefulset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/affinity-collector/01-assert-daemonset-with-affinity.yaml b/tests/e2e/affinity-collector/01-assert-daemonset-with-affinity.yaml
new file mode 100644
index 0000000000..9abf98b444
--- /dev/null
+++ b/tests/e2e/affinity-collector/01-assert-daemonset-with-affinity.yaml
@@ -0,0 +1,13 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: daemonset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    affinity: with
+spec:
+  template:
+    spec:
+      (affinity != null): true
diff --git a/tests/e2e/affinity-collector/01-assert-deployment-with-affinity.yaml b/tests/e2e/affinity-collector/01-assert-deployment-with-affinity.yaml
new file mode 100644
index 0000000000..114bc50253
--- /dev/null
+++ b/tests/e2e/affinity-collector/01-assert-deployment-with-affinity.yaml
@@ -0,0 +1,13 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: deployment-collector
+    app.kubernetes.io/part-of: opentelemetry
+    affinity: with
+spec:
+  template:
+    spec:
+      (affinity != null): true
diff --git a/tests/e2e/affinity-collector/01-assert-statefulset-with-affinity.yaml b/tests/e2e/affinity-collector/01-assert-statefulset-with-affinity.yaml
new file mode 100644
index 0000000000..64e580f02a
--- /dev/null
+++ b/tests/e2e/affinity-collector/01-assert-statefulset-with-affinity.yaml
@@ -0,0 +1,13 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: statefulset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    affinity: with
+spec:
+  template:
+    spec:
+      (affinity != null): true
diff --git a/tests/e2e/affinity-collector/01-install-collectors-with-affinity.yaml b/tests/e2e/affinity-collector/01-install-collectors-with-affinity.yaml
new file mode 100644
index 0000000000..95fcac394a
--- /dev/null
+++ b/tests/e2e/affinity-collector/01-install-collectors-with-affinity.yaml
@@ -0,0 +1,100 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+  labels:
+    affinity: with
+spec:
+  mode: deployment
+  affinity:
+    nodeAffinity:
+      requiredDuringSchedulingIgnoredDuringExecution:
+        nodeSelectorTerms:
+        - matchExpressions:
+          - key: kubernetes.io/os
+            operator: In
+            values:
+            - linux
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+  labels:
+    affinity: with
+spec:
+  mode: daemonset
+  affinity:
+    nodeAffinity:
+      requiredDuringSchedulingIgnoredDuringExecution:
+        nodeSelectorTerms:
+        - matchExpressions:
+          - key: kubernetes.io/os
+            operator: In
+            values:
+            - linux
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+  labels:
+    affinity: with
+spec:
+  mode: statefulset
+  affinity:
+    nodeAffinity:
+      requiredDuringSchedulingIgnoredDuringExecution:
+        nodeSelectorTerms:
+        - matchExpressions:
+          - key: kubernetes.io/os
+            operator: In
+            values:
+            - linux
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/affinity-collector/02-assert-daemonset-with-modified-affinity.yaml b/tests/e2e/affinity-collector/02-assert-daemonset-with-modified-affinity.yaml
new file mode 100644
index 0000000000..8ec0913dad
--- /dev/null
+++ b/tests/e2e/affinity-collector/02-assert-daemonset-with-modified-affinity.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: daemonset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    affinity: with
+spec:
+  template:
+    spec:
+      affinity:
+        nodeAffinity:
+          (requiredDuringSchedulingIgnoredDuringExecution == null): true
+          (preferredDuringSchedulingIgnoredDuringExecution != null): true
diff --git a/tests/e2e/affinity-collector/02-assert-deployment-with-modified-affinity.yaml b/tests/e2e/affinity-collector/02-assert-deployment-with-modified-affinity.yaml
new file mode 100644
index 0000000000..34d594fe30
--- /dev/null
+++ b/tests/e2e/affinity-collector/02-assert-deployment-with-modified-affinity.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: deployment-collector
+    app.kubernetes.io/part-of: opentelemetry
+    affinity: with
+spec:
+  template:
+    spec:
+      affinity:
+        nodeAffinity:
+          (requiredDuringSchedulingIgnoredDuringExecution == null): true
+          (preferredDuringSchedulingIgnoredDuringExecution != null): true
diff --git a/tests/e2e/affinity-collector/02-assert-statefulset-with-modified-affinity.yaml b/tests/e2e/affinity-collector/02-assert-statefulset-with-modified-affinity.yaml
new file mode 100644
index 0000000000..530116b1fb
--- /dev/null
+++ b/tests/e2e/affinity-collector/02-assert-statefulset-with-modified-affinity.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: statefulset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    affinity: with
+spec:
+  template:
+    spec:
+      affinity:
+        nodeAffinity:
+          (requiredDuringSchedulingIgnoredDuringExecution == null): true
+          (preferredDuringSchedulingIgnoredDuringExecution != null): true
diff --git a/tests/e2e/affinity-collector/02-modify-collectors-affinity.yaml b/tests/e2e/affinity-collector/02-modify-collectors-affinity.yaml
new file mode 100644
index 0000000000..dec25b413c
--- /dev/null
+++ b/tests/e2e/affinity-collector/02-modify-collectors-affinity.yaml
@@ -0,0 +1,103 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+  labels:
+    affinity: with
+spec:
+  mode: deployment
+  affinity:
+    nodeAffinity:
+      preferredDuringSchedulingIgnoredDuringExecution:
+      - weight: 1
+        preference:
+          matchExpressions:
+          - key: kubernetes.io/os
+            operator: In
+            values:
+            - linux
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+  labels:
+    affinity: with
+spec:
+  mode: daemonset
+  affinity:
+    nodeAffinity:
+      preferredDuringSchedulingIgnoredDuringExecution:
+      - weight: 1
+        preference:
+          matchExpressions:
+          - key: kubernetes.io/os
+            operator: In
+            values:
+            - linux
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+  labels:
+    affinity: with
+spec:
+  mode: statefulset
+  affinity:
+    nodeAffinity:
+      preferredDuringSchedulingIgnoredDuringExecution:
+      - weight: 1
+        preference:
+          matchExpressions:
+          - key: kubernetes.io/os
+            operator: In
+            values:
+            - linux
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/affinity-collector/chainsaw-test.yaml b/tests/e2e/affinity-collector/chainsaw-test.yaml
new file mode 100644
index 0000000000..84d36ad7ed
--- /dev/null
+++ b/tests/e2e/affinity-collector/chainsaw-test.yaml
@@ -0,0 +1,66 @@
+# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json
+apiVersion: chainsaw.kyverno.io/v1alpha1
+kind: Test
+metadata:
+  name: affinity-collector
+spec:
+  steps:
+    - name: step-00
+      description: collectors without affinity
+      try:
+        - apply:
+            file: 00-install-collectors-without-affinity.yaml
+        # deployment
+        - assert:
+            file: 00-assert-deployment-without-affinity.yaml
+        # daemonset
+        - assert:
+            file: 00-assert-daemonset-without-affinity.yaml
+        # statefulset
+        - assert:
+            file: 00-assert-statefulset-without-affinity.yaml
+
+    - name: step-01
+      description: collectors with affinity
+      try:
+        - update:
+            file: 01-install-collectors-with-affinity.yaml
+        # deployment
+        - assert:
+            file: 01-assert-deployment-with-affinity.yaml
+        # daemonset
+        - assert:
+            file: 01-assert-daemonset-with-affinity.yaml
+        # statefulset
+        - assert:
+            file: 01-assert-statefulset-with-affinity.yaml
+
+    - name: step-02
+      description: modify affinity
+      try:
+        - update:
+            file: 02-modify-collectors-affinity.yaml
+        # deployment
+        - assert:
+            file: 02-assert-deployment-with-modified-affinity.yaml
+        # daemonset
+        - assert:
+            file: 02-assert-daemonset-with-modified-affinity.yaml
+        # statefulset
+        - assert:
+            file: 02-assert-statefulset-with-modified-affinity.yaml
+
+    - name: step-03
+      description: delete affinity
+      try:
+        - update:
+            file: 00-install-collectors-without-affinity.yaml
+        # deployment
+        - assert:
+            file: 00-assert-deployment-without-affinity.yaml
+        # daemonset
+        - assert:
+            file: 00-assert-daemonset-without-affinity.yaml
+        # statefulset
+        - assert:
+            file: 00-assert-statefulset-without-affinity.yaml
diff --git a/tests/e2e/annotation-change-collector/00-assert-daemonset-with-extra-annotation.yaml b/tests/e2e/annotation-change-collector/00-assert-daemonset-with-extra-annotation.yaml
new file mode 100644
index 0000000000..e33371e300
--- /dev/null
+++ b/tests/e2e/annotation-change-collector/00-assert-daemonset-with-extra-annotation.yaml
@@ -0,0 +1,11 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  name: daemonset-collector
+  annotations:
+    user-annotation: "existing"
+spec:
+  template:
+    metadata:
+      annotations:
+        user-annotation: "existing"
diff --git a/tests/e2e/annotation-change-collector/00-assert-deployment-with-extra-annotation.yaml b/tests/e2e/annotation-change-collector/00-assert-deployment-with-extra-annotation.yaml
new file mode 100644
index 0000000000..e02ad87341
--- /dev/null
+++ b/tests/e2e/annotation-change-collector/00-assert-deployment-with-extra-annotation.yaml
@@ -0,0 +1,11 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: deployment-collector
+  annotations:
+    user-annotation: "existing"
+spec:
+  template:
+    metadata:
+      annotations:
+        user-annotation: "existing"
diff --git a/tests/e2e/annotation-change-collector/00-assert-statefulset-with-extra-annotation.yaml b/tests/e2e/annotation-change-collector/00-assert-statefulset-with-extra-annotation.yaml
new file mode 100644
index 0000000000..b74f1945b0
--- /dev/null
+++ b/tests/e2e/annotation-change-collector/00-assert-statefulset-with-extra-annotation.yaml
@@ -0,0 +1,11 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: statefulset-collector
+  annotations:
+    user-annotation: "existing"
+spec:
+  template:
+    metadata:
+      annotations:
+        user-annotation: "existing"
diff --git a/tests/e2e/annotation-change-collector/00-install-collectors-with-extra-annotation.yaml b/tests/e2e/annotation-change-collector/00-install-collectors-with-extra-annotation.yaml
new file mode 100644
index 0000000000..5e21322a3f
--- /dev/null
+++ b/tests/e2e/annotation-change-collector/00-install-collectors-with-extra-annotation.yaml
@@ -0,0 +1,73 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+  annotations:
+    user-annotation: "existing"
+spec:
+  mode: deployment
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+  annotations:
+    user-annotation: "existing"
+spec:
+  mode: daemonset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+  annotations:
+    user-annotation: "existing"
+spec:
+  mode: statefulset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/annotation-change-collector/01-assert-daemonset-with-annotation-change.yaml b/tests/e2e/annotation-change-collector/01-assert-daemonset-with-annotation-change.yaml
new file mode 100644
index 0000000000..522e45cfba
--- /dev/null
+++ b/tests/e2e/annotation-change-collector/01-assert-daemonset-with-annotation-change.yaml
@@ -0,0 +1,13 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  name: daemonset-collector
+  annotations:
+    user-annotation: "modified"
+    new-annotation: "yes"
+spec:
+  template:
+    metadata:
+      annotations:
+        user-annotation: "modified"
+        new-annotation: "yes"
diff --git a/tests/e2e/annotation-change-collector/01-assert-deployment-with-annotation-change.yaml b/tests/e2e/annotation-change-collector/01-assert-deployment-with-annotation-change.yaml
new file mode 100644
index 0000000000..86b0ac0e6f
--- /dev/null
+++ b/tests/e2e/annotation-change-collector/01-assert-deployment-with-annotation-change.yaml
@@ -0,0 +1,13 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: deployment-collector
+  annotations:
+    user-annotation: "modified"
+    new-annotation: "yes"
+spec:
+  template:
+    metadata:
+      annotations:
+        user-annotation: "modified"
+        new-annotation: "yes"
diff --git a/tests/e2e/annotation-change-collector/01-assert-statefulset-with-annotation-change.yaml b/tests/e2e/annotation-change-collector/01-assert-statefulset-with-annotation-change.yaml
new file mode 100644
index 0000000000..c0bc38d353
--- /dev/null
+++ b/tests/e2e/annotation-change-collector/01-assert-statefulset-with-annotation-change.yaml
@@ -0,0 +1,13 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: statefulset-collector
+  annotations:
+    user-annotation: "modified"
+    new-annotation: "yes"
+spec:
+  template:
+    metadata:
+      annotations:
+        user-annotation: "modified"
+        new-annotation: "yes"
diff --git a/tests/e2e/annotation-change-collector/01-install-collectors-with-annotation-change.yaml b/tests/e2e/annotation-change-collector/01-install-collectors-with-annotation-change.yaml
new file mode 100644
index 0000000000..bd02ae5766
--- /dev/null
+++ b/tests/e2e/annotation-change-collector/01-install-collectors-with-annotation-change.yaml
@@ -0,0 +1,76 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+  annotations:
+    user-annotation: "modified"
+    new-annotation: "yes"
+spec:
+  mode: deployment
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+  annotations:
+    user-annotation: "modified"
+    new-annotation: "yes"
+spec:
+  mode: daemonset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+  annotations:
+    user-annotation: "modified"
+    new-annotation: "yes"
+spec:
+  mode: statefulset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/annotation-change-collector/02-assert-daemonset-without-extra-annotation.yaml b/tests/e2e/annotation-change-collector/02-assert-daemonset-without-extra-annotation.yaml
new file mode 100644
index 0000000000..bfe14a3638
--- /dev/null
+++ b/tests/e2e/annotation-change-collector/02-assert-daemonset-without-extra-annotation.yaml
@@ -0,0 +1,15 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  name: daemonset-collector
+  (contains(keys(annotations), 'user-annotation')): true
+  (contains(keys(annotations), 'new-annotation')): true
+  annotations:
+    manual-annotation: "true"
+spec:
+  template:
+    metadata:
+      (contains(keys(annotations), 'user-annotation')): true
+      (contains(keys(annotations), 'new-annotation')): true
+      annotations:
+        manual-annotation: "true"
diff --git a/tests/e2e/annotation-change-collector/02-assert-deployment-without-extra-annotation.yaml b/tests/e2e/annotation-change-collector/02-assert-deployment-without-extra-annotation.yaml
new file mode 100644
index 0000000000..b5c7232450
--- /dev/null
+++ b/tests/e2e/annotation-change-collector/02-assert-deployment-without-extra-annotation.yaml
@@ -0,0 +1,15 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: deployment-collector
+  (contains(keys(annotations), 'user-annotation')): true
+  (contains(keys(annotations), 'new-annotation')): true
+  annotations:
+    manual-annotation: "true"
+spec:
+  template:
+    metadata:
+      (contains(keys(annotations), 'user-annotation')): true
+      (contains(keys(annotations), 'new-annotation')): true
+      annotations:
+        manual-annotation: "true"
diff --git a/tests/e2e/annotation-change-collector/02-assert-statefulset-without-extra-annotation.yaml b/tests/e2e/annotation-change-collector/02-assert-statefulset-without-extra-annotation.yaml
new file mode 100644
index 0000000000..8117b452f9
--- /dev/null
+++ b/tests/e2e/annotation-change-collector/02-assert-statefulset-without-extra-annotation.yaml
@@ -0,0 +1,15 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: statefulset-collector
+  (contains(keys(annotations), 'user-annotation')): true
+  (contains(keys(annotations), 'new-annotation')): true
+  annotations:
+    manual-annotation: "true"
+spec:
+  template:
+    metadata:
+      (contains(keys(annotations), 'user-annotation')): true
+      (contains(keys(annotations), 'new-annotation')): true
+      annotations:
+        manual-annotation: "true"
diff --git a/tests/e2e/annotation-change-collector/02-install-collectors-without-extra-annotation.yaml b/tests/e2e/annotation-change-collector/02-install-collectors-without-extra-annotation.yaml
new file mode 100644
index 0000000000..4a50758f63
--- /dev/null
+++ b/tests/e2e/annotation-change-collector/02-install-collectors-without-extra-annotation.yaml
@@ -0,0 +1,67 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+spec:
+  mode: deployment
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+spec:
+  mode: daemonset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+spec:
+  mode: statefulset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/annotation-change-collector/02-manual-annotation-resources.yaml b/tests/e2e/annotation-change-collector/02-manual-annotation-resources.yaml
new file mode 100644
index 0000000000..e59bc43e11
--- /dev/null
+++ b/tests/e2e/annotation-change-collector/02-manual-annotation-resources.yaml
@@ -0,0 +1,35 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  name: daemonset-collector
+  annotations:
+    manual-annotation: "true"
+spec:
+  template:
+    metadata:
+      annotations:
+        manual-annotation: "true"
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: deployment-collector
+  annotations:
+    manual-annotation: "true"
+spec:
+  template:
+    metadata:
+      annotations:
+        manual-annotation: "true"
+---
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: statefulset-collector
+  annotations:
+    manual-annotation: "true"
+spec:
+  template:
+    metadata:
+      annotations:
+        manual-annotation: "true"
diff --git a/tests/e2e/annotation-change-collector/chainsaw-test.yaml b/tests/e2e/annotation-change-collector/chainsaw-test.yaml
new file mode 100644
index 0000000000..cf00491f49
--- /dev/null
+++ b/tests/e2e/annotation-change-collector/chainsaw-test.yaml
@@ -0,0 +1,53 @@
+# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json
+apiVersion: chainsaw.kyverno.io/v1alpha1
+kind: Test
+metadata:
+  name: annotation-change-collector
+spec:
+  steps:
+    - name: step-00
+      description: collectors with an extra annotation
+      try:
+        - apply:
+            file: 00-install-collectors-with-extra-annotation.yaml
+        # deployment
+        - assert:
+            file: 00-assert-deployment-with-extra-annotation.yaml
+        # daemonset
+        - assert:
+            file: 00-assert-daemonset-with-extra-annotation.yaml
+        # statefulset
+        - assert:
+            file: 00-assert-statefulset-with-extra-annotation.yaml
+
+    - name: step-01
+      description: collectors with changed extra annotations
+      try:
+        - update:
+            file: 01-install-collectors-with-annotation-change.yaml
+        # deployment
+        - assert:
+            file: 01-assert-deployment-with-annotation-change.yaml
+        # daemonset
+        - assert:
+            file: 01-assert-daemonset-with-annotation-change.yaml
+        # statefulset
+        - assert:
+            file: 01-assert-statefulset-with-annotation-change.yaml
+
+    - name: step-02
+      description: manually annotate resources and delete extra annotation from collector
+      try:
+        - apply:
+            file: 02-manual-annotation-resources.yaml
+        - update:
+            file: 02-install-collectors-without-extra-annotation.yaml
+        # deployment
+        - assert:
+            file: 02-assert-deployment-without-extra-annotation.yaml
+        # daemonset
+        - assert:
+            file: 02-assert-daemonset-without-extra-annotation.yaml
+        # statefulset
+        - assert:
+            file: 02-assert-statefulset-without-extra-annotation.yaml
diff --git a/tests/e2e/args-collector/00-assert-daemonset-without-args.yaml b/tests/e2e/args-collector/00-assert-daemonset-without-args.yaml
new file mode 100644
index 0000000000..1319f06b5f
--- /dev/null
+++ b/tests/e2e/args-collector/00-assert-daemonset-without-args.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: daemonset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    args: without
+spec:
+  template:
+    spec:
+      ~.(containers):
+        name: otc-container
+        (contains(args, '--extra-arg=yes')): false
+        (contains(args, '--different-extra-arg=yes')): false
diff --git a/tests/e2e/args-collector/00-assert-deployment-without-args.yaml b/tests/e2e/args-collector/00-assert-deployment-without-args.yaml
new file mode 100644
index 0000000000..74dd0c998b
--- /dev/null
+++ b/tests/e2e/args-collector/00-assert-deployment-without-args.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: deployment-collector
+    app.kubernetes.io/part-of: opentelemetry
+    args: without
+spec:
+  template:
+    spec:
+      ~.(containers):
+        name: otc-container
+        (contains(args, '--extra-arg=yes')): false
+        (contains(args, '--different-extra-arg=yes')): false
diff --git a/tests/e2e/args-collector/00-assert-statefulset-without-args.yaml b/tests/e2e/args-collector/00-assert-statefulset-without-args.yaml
new file mode 100644
index 0000000000..70a30e913b
--- /dev/null
+++ b/tests/e2e/args-collector/00-assert-statefulset-without-args.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: statefulset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    args: without
+spec:
+  template:
+    spec:
+      ~.(containers):
+        name: otc-container
+        (contains(args, '--extra-arg=yes')): false
+        (contains(args, '--different-extra-arg=yes')): false
diff --git a/tests/e2e/args-collector/00-install-collectors-without-args.yaml b/tests/e2e/args-collector/00-install-collectors-without-args.yaml
new file mode 100644
index 0000000000..5073aaef66
--- /dev/null
+++ b/tests/e2e/args-collector/00-install-collectors-without-args.yaml
@@ -0,0 +1,73 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+  labels:
+    args: without
+spec:
+  mode: deployment
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+  labels:
+    args: without
+spec:
+  mode: daemonset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+  labels:
+    args: without
+spec:
+  mode: statefulset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/args-collector/01-assert-daemonset-with-args.yaml b/tests/e2e/args-collector/01-assert-daemonset-with-args.yaml
new file mode 100644
index 0000000000..0177692267
--- /dev/null
+++ b/tests/e2e/args-collector/01-assert-daemonset-with-args.yaml
@@ -0,0 +1,15 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: daemonset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    args: with
+spec:
+  template:
+    spec:
+      ~.(containers):
+        name: otc-container
+        (contains(args, '--extra-arg=yes')): true
diff --git a/tests/e2e/args-collector/01-assert-deployment-with-args.yaml b/tests/e2e/args-collector/01-assert-deployment-with-args.yaml
new file mode 100644
index 0000000000..c22de26d67
--- /dev/null
+++ b/tests/e2e/args-collector/01-assert-deployment-with-args.yaml
@@ -0,0 +1,15 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: deployment-collector
+    app.kubernetes.io/part-of: opentelemetry
+    args: with
+spec:
+  template:
+    spec:
+      ~.(containers):
+        name: otc-container
+        (contains(args, '--extra-arg=yes')): true
diff --git a/tests/e2e/args-collector/01-assert-statefulset-with-args.yaml b/tests/e2e/args-collector/01-assert-statefulset-with-args.yaml
new file mode 100644
index 0000000000..3afba4be8e
--- /dev/null
+++ b/tests/e2e/args-collector/01-assert-statefulset-with-args.yaml
@@ -0,0 +1,15 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: statefulset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    args: with
+spec:
+  template:
+    spec:
+      ~.(containers):
+        name: otc-container
+        (contains(args, '--extra-arg=yes')): true
diff --git a/tests/e2e/args-collector/01-install-collectors-with-args.yaml b/tests/e2e/args-collector/01-install-collectors-with-args.yaml
new file mode 100644
index 0000000000..8c6a03ab5e
--- /dev/null
+++ b/tests/e2e/args-collector/01-install-collectors-with-args.yaml
@@ -0,0 +1,79 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+  labels:
+    args: with
+spec:
+  mode: deployment
+  args:
+    extra-arg: "yes"
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+  labels:
+    args: with
+spec:
+  mode: daemonset
+  args:
+    extra-arg: "yes"
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+  labels:
+    args: with
+spec:
+  mode: statefulset
+  args:
+    extra-arg: "yes"
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/args-collector/02-assert-daemonset-with-modified-args.yaml b/tests/e2e/args-collector/02-assert-daemonset-with-modified-args.yaml
new file mode 100644
index 0000000000..3246c130db
--- /dev/null
+++ b/tests/e2e/args-collector/02-assert-daemonset-with-modified-args.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: daemonset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    args: with
+spec:
+  template:
+    spec:
+      ~.(containers):
+        name: otc-container
+        (contains(args, '--extra-arg=yes')): false
+        (contains(args, '--different-extra-arg=yes')): true
diff --git a/tests/e2e/args-collector/02-assert-deployment-with-modified-args.yaml b/tests/e2e/args-collector/02-assert-deployment-with-modified-args.yaml
new file mode 100644
index 0000000000..4eedab6b04
--- /dev/null
+++ b/tests/e2e/args-collector/02-assert-deployment-with-modified-args.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: deployment-collector
+    app.kubernetes.io/part-of: opentelemetry
+    args: with
+spec:
+  template:
+    spec:
+      ~.(containers):
+        name: otc-container
+        (contains(args, '--extra-arg=yes')): false
+        (contains(args, '--different-extra-arg=yes')): true
diff --git a/tests/e2e/args-collector/02-assert-statefulset-with-modified-args.yaml b/tests/e2e/args-collector/02-assert-statefulset-with-modified-args.yaml
new file mode 100644
index 0000000000..6ed1dc4461
--- /dev/null
+++ b/tests/e2e/args-collector/02-assert-statefulset-with-modified-args.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: statefulset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    args: with
+spec:
+  template:
+    spec:
+      ~.(containers):
+        name: otc-container
+        (contains(args, '--extra-arg=yes')): false
+        (contains(args, '--different-extra-arg=yes')): true
diff --git a/tests/e2e/args-collector/02-modify-collectors-args.yaml b/tests/e2e/args-collector/02-modify-collectors-args.yaml
new file mode 100644
index 0000000000..2d43e6c1f9
--- /dev/null
+++ b/tests/e2e/args-collector/02-modify-collectors-args.yaml
@@ -0,0 +1,79 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+  labels:
+    args: with
+spec:
+  mode: deployment
+  args:
+    different-extra-arg: "yes"
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+  labels:
+    args: with
+spec:
+  mode: daemonset
+  args:
+    different-extra-arg: "yes"
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+  labels:
+    args: with
+spec:
+  mode: statefulset
+  args:
+    different-extra-arg: "yes"
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/args-collector/chainsaw-test.yaml b/tests/e2e/args-collector/chainsaw-test.yaml
new file mode 100644
index 0000000000..2f3d6a7311
--- /dev/null
+++ b/tests/e2e/args-collector/chainsaw-test.yaml
@@ -0,0 +1,66 @@
+# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json
+apiVersion: chainsaw.kyverno.io/v1alpha1
+kind: Test
+metadata:
+  name: args-collector
+spec:
+  steps:
+    - name: step-00
+      description: collectors without args
+      try:
+        - apply:
+            file: 00-install-collectors-without-args.yaml
+        # deployment
+        - assert:
+            file: 00-assert-deployment-without-args.yaml
+        # daemonset
+        - assert:
+            file: 00-assert-daemonset-without-args.yaml
+        # statefulset
+        - assert:
+            file: 00-assert-statefulset-without-args.yaml
+
+    - name: step-01
+      description: collectors with args
+      try:
+        - update:
+            file: 01-install-collectors-with-args.yaml
+        # deployment
+        - assert:
+            file: 01-assert-deployment-with-args.yaml
+        # daemonset
+        - assert:
+            file: 01-assert-daemonset-with-args.yaml
+        # statefulset
+        - assert:
+            file: 01-assert-statefulset-with-args.yaml
+
+    - name: step-02
+      description: modify args
+      try:
+        - update:
+            file: 02-modify-collectors-args.yaml
+        # deployment
+        - assert:
+            file: 02-assert-deployment-with-modified-args.yaml
+        # daemonset
+        - assert:
+            file: 02-assert-daemonset-with-modified-args.yaml
+        # statefulset
+        - assert:
+            file: 02-assert-statefulset-with-modified-args.yaml
+
+    - name: step-03
+      description: delete args
+      try:
+        - update:
+            file: 00-install-collectors-without-args.yaml
+        # deployment
+        - assert:
+            file: 00-assert-deployment-without-args.yaml
+        # daemonset
+        - assert:
+            file: 00-assert-daemonset-without-args.yaml
+        # statefulset
+        - assert:
+            file: 00-assert-statefulset-without-args.yaml
diff --git a/tests/e2e/label-change-collector/00-assert-daemonset-with-extra-label.yaml b/tests/e2e/label-change-collector/00-assert-daemonset-with-extra-label.yaml
new file mode 100644
index 0000000000..08e3c0661f
--- /dev/null
+++ b/tests/e2e/label-change-collector/00-assert-daemonset-with-extra-label.yaml
@@ -0,0 +1,14 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: daemonset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    user-label: "existing"
+spec:
+  template:
+    metadata:
+      labels:
+        user-label: "existing"
diff --git a/tests/e2e/label-change-collector/00-assert-deployment-with-extra-label.yaml b/tests/e2e/label-change-collector/00-assert-deployment-with-extra-label.yaml
new file mode 100644
index 0000000000..91f64baf7e
--- /dev/null
+++ b/tests/e2e/label-change-collector/00-assert-deployment-with-extra-label.yaml
@@ -0,0 +1,14 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: deployment-collector
+    app.kubernetes.io/part-of: opentelemetry
+    user-label: "existing"
+spec:
+  template:
+    metadata:
+      labels:
+        user-label: "existing"
diff --git a/tests/e2e/label-change-collector/00-assert-statefulset-with-extra-label.yaml b/tests/e2e/label-change-collector/00-assert-statefulset-with-extra-label.yaml
new file mode 100644
index 0000000000..575d27cd50
--- /dev/null
+++ b/tests/e2e/label-change-collector/00-assert-statefulset-with-extra-label.yaml
@@ -0,0 +1,14 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: statefulset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    user-label: "existing"
+spec:
+  template:
+    metadata:
+      labels:
+        user-label: "existing"
diff --git a/tests/e2e/label-change-collector/00-install-collectors-with-extra-label.yaml b/tests/e2e/label-change-collector/00-install-collectors-with-extra-label.yaml
new file mode 100644
index 0000000000..27fe143df5
--- /dev/null
+++ b/tests/e2e/label-change-collector/00-install-collectors-with-extra-label.yaml
@@ -0,0 +1,73 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+  labels:
+    user-label: "existing"
+spec:
+  mode: deployment
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+  labels:
+    user-label: "existing"
+spec:
+  mode: daemonset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+  labels:
+    user-label: "existing"
+spec:
+  mode: statefulset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/label-change-collector/01-assert-daemonset-with-label-change.yaml b/tests/e2e/label-change-collector/01-assert-daemonset-with-label-change.yaml
new file mode 100644
index 0000000000..770106939d
--- /dev/null
+++ b/tests/e2e/label-change-collector/01-assert-daemonset-with-label-change.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: daemonset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    user-label: "modified"
+    new-label: "yes"
+spec:
+  template:
+    metadata:
+      labels:
+        user-label: "modified"
+        new-label: "yes"
diff --git a/tests/e2e/label-change-collector/01-assert-deployment-with-label-change.yaml b/tests/e2e/label-change-collector/01-assert-deployment-with-label-change.yaml
new file mode 100644
index 0000000000..f694609ef1
--- /dev/null
+++ b/tests/e2e/label-change-collector/01-assert-deployment-with-label-change.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: deployment-collector
+    app.kubernetes.io/part-of: opentelemetry
+    user-label: "modified"
+    new-label: "yes"
+spec:
+  template:
+    metadata:
+      labels:
+        user-label: "modified"
+        new-label: "yes"
diff --git a/tests/e2e/label-change-collector/01-assert-statefulset-with-label-change.yaml b/tests/e2e/label-change-collector/01-assert-statefulset-with-label-change.yaml
new file mode 100644
index 0000000000..64a857d051
--- /dev/null
+++ b/tests/e2e/label-change-collector/01-assert-statefulset-with-label-change.yaml
@@ -0,0 +1,16 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: statefulset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    user-label: "modified"
+    new-label: "yes"
+spec:
+  template:
+    metadata:
+      labels:
+        user-label: "modified"
+        new-label: "yes"
diff --git a/tests/e2e/label-change-collector/01-install-collectors-with-label-change.yaml b/tests/e2e/label-change-collector/01-install-collectors-with-label-change.yaml
new file mode 100644
index 0000000000..46ca873c80
--- /dev/null
+++ b/tests/e2e/label-change-collector/01-install-collectors-with-label-change.yaml
@@ -0,0 +1,76 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+  labels:
+    user-label: "modified"
+    new-label: "yes"
+spec:
+  mode: deployment
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+  labels:
+    user-label: "modified"
+    new-label: "yes"
+spec:
+  mode: daemonset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+  labels:
+    user-label: "modified"
+    new-label: "yes"
+spec:
+  mode: statefulset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/label-change-collector/02-assert-daemonset-without-extra-label.yaml b/tests/e2e/label-change-collector/02-assert-daemonset-without-extra-label.yaml
new file mode 100644
index 0000000000..4e7086d4eb
--- /dev/null
+++ b/tests/e2e/label-change-collector/02-assert-daemonset-without-extra-label.yaml
@@ -0,0 +1,18 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  (contains(keys(labels),'user-label')): true
+  (contains(keys(labels),'new-label')): true
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: daemonset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    manual-label: "true"
+spec:
+  template:
+    metadata:
+      (contains(keys(labels),'user-label')): true
+      (contains(keys(labels),'new-label')): true
+      labels:
+        manual-label: "true"
diff --git a/tests/e2e/label-change-collector/02-assert-deployment-without-extra-label.yaml b/tests/e2e/label-change-collector/02-assert-deployment-without-extra-label.yaml
new file mode 100644
index 0000000000..cfad6a1965
--- /dev/null
+++ b/tests/e2e/label-change-collector/02-assert-deployment-without-extra-label.yaml
@@ -0,0 +1,18 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  (contains(keys(labels),'user-label')): true
+  (contains(keys(labels),'new-label')): true
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: deployment-collector
+    app.kubernetes.io/part-of: opentelemetry
+    manual-label: "true"
+spec:
+  template:
+    metadata:
+      (contains(keys(labels),'user-label')): true
+      (contains(keys(labels),'new-label')): true
+      labels:
+        manual-label: "true"
diff --git a/tests/e2e/label-change-collector/02-assert-statefulset-without-extra-label.yaml b/tests/e2e/label-change-collector/02-assert-statefulset-without-extra-label.yaml
new file mode 100644
index 0000000000..72f24ab10e
--- /dev/null
+++ b/tests/e2e/label-change-collector/02-assert-statefulset-without-extra-label.yaml
@@ -0,0 +1,18 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  (contains(keys(labels),'user-label')): true
+  (contains(keys(labels),'new-label')): true
+  labels:
+    app.kubernetes.io/component: opentelemetry-collector
+    app.kubernetes.io/managed-by: opentelemetry-operator
+    app.kubernetes.io/name: statefulset-collector
+    app.kubernetes.io/part-of: opentelemetry
+    manual-label: "true"
+spec:
+  template:
+    metadata:
+      (contains(keys(labels),'user-label')): true
+      (contains(keys(labels),'new-label')): true
+      labels:
+        manual-label: "true"
diff --git a/tests/e2e/label-change-collector/02-install-collectors-without-extra-label.yaml b/tests/e2e/label-change-collector/02-install-collectors-without-extra-label.yaml
new file mode 100644
index 0000000000..4a50758f63
--- /dev/null
+++ b/tests/e2e/label-change-collector/02-install-collectors-without-extra-label.yaml
@@ -0,0 +1,67 @@
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: deployment
+spec:
+  mode: deployment
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: daemonset
+spec:
+  mode: daemonset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
+
+---
+apiVersion: opentelemetry.io/v1beta1
+kind: OpenTelemetryCollector
+metadata:
+  name: statefulset
+spec:
+  mode: statefulset
+  config:
+    receivers:
+      otlp:
+        protocols:
+          grpc: {}
+    processors: {}
+
+    exporters:
+      debug: {}
+
+    service:
+      pipelines:
+        traces:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e/label-change-collector/02-manual-labeling-resources.yaml b/tests/e2e/label-change-collector/02-manual-labeling-resources.yaml
new file mode 100644
index 0000000000..637bd44009
--- /dev/null
+++ b/tests/e2e/label-change-collector/02-manual-labeling-resources.yaml
@@ -0,0 +1,35 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  name: daemonset-collector
+  labels:
+    manual-label: "true"
+spec:
+  template:
+    metadata:
+      labels:
+        manual-label: "true"
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: deployment-collector
+  labels:
+    manual-label: "true"
+spec:
+  template:
+    metadata:
+      labels:
+        manual-label: "true"
+---
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: statefulset-collector
+  labels:
+    manual-label: "true"
+spec:
+  template:
+    metadata:
+      labels:
+        manual-label: "true"
diff --git a/tests/e2e/label-change-collector/chainsaw-test.yaml b/tests/e2e/label-change-collector/chainsaw-test.yaml
new file mode 100644
index 0000000000..25542d4ce2
--- /dev/null
+++ b/tests/e2e/label-change-collector/chainsaw-test.yaml
@@ -0,0 +1,53 @@
+# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json
+apiVersion: chainsaw.kyverno.io/v1alpha1
+kind: Test
+metadata:
+  name: label-change-collector
+spec:
+  steps:
+    - name: step-00
+      description: collectors with an extra label
+      try:
+        - apply:
+            file: 00-install-collectors-with-extra-label.yaml
+        # deployment
+        - assert:
+            file: 00-assert-deployment-with-extra-label.yaml
+        # daemonset
+        - assert:
+            file: 00-assert-daemonset-with-extra-label.yaml
+        # statefulset
+        - assert:
+            file: 00-assert-statefulset-with-extra-label.yaml
+
+    - name: step-01
+      description: collectors with changed extra labels
+      try:
+        - update:
+            file: 01-install-collectors-with-label-change.yaml
+        # deployment
+        - assert:
+            file: 01-assert-deployment-with-label-change.yaml
+        # daemonset
+        - assert:
+            file: 01-assert-daemonset-with-label-change.yaml
+        # statefulset
+        - assert:
+            file: 01-assert-statefulset-with-label-change.yaml
+
+    - name: step-02
+      description: delete extra label from collector
+      try:
+        - apply:
+            file: 02-manual-labeling-resources.yaml
+        - update:
+            file: 02-install-collectors-without-extra-label.yaml
+        # deployment
+        - assert:
+            file: 02-assert-deployment-without-extra-label.yaml
+        # daemonset
+        - assert:
+            file: 02-assert-daemonset-without-extra-label.yaml
+        # statefulset
+        - assert:
+            file: 02-assert-statefulset-without-extra-label.yaml
diff --git a/tests/e2e/node-selector-collector/00-install-collectors-without-node-selector.yaml b/tests/e2e/node-selector-collector/00-install-collectors-without-node-selector.yaml
index b4e3044ef0..baad346f14 100644
--- a/tests/e2e/node-selector-collector/00-install-collectors-without-node-selector.yaml
+++ b/tests/e2e/node-selector-collector/00-install-collectors-without-node-selector.yaml
@@ -1,4 +1,4 @@
-apiVersion: opentelemetry.io/v1alpha1
+apiVersion: opentelemetry.io/v1beta1
 kind: OpenTelemetryCollector
 metadata:
   name: deployment
@@ -7,16 +7,16 @@ metadata:
 spec:
   mode: deployment
   nodeSelector:
-  config: |
+  config:
     receivers:
       otlp:
         protocols:
-          grpc:
-          http:
-    processors:
+          grpc: {}
+          http: {}
+    processors: {}
 
     exporters:
-      debug:
+      debug: {}
 
     service:
       pipelines:
@@ -25,7 +25,7 @@ spec:
           exporters: [debug]
 
 ---
-apiVersion: opentelemetry.io/v1alpha1
+apiVersion: opentelemetry.io/v1beta1
 kind: OpenTelemetryCollector
 metadata:
   name: daemonset
@@ -34,16 +34,16 @@ metadata:
 spec:
   mode: daemonset
   nodeSelector:
-  config: |
+  config:
     receivers:
       otlp:
         protocols:
-          grpc:
-          http:
-    processors:
+          grpc: {}
+          http: {}
+    processors: {}
 
     exporters:
-      debug:
+      debug: {}
 
     service:
       pipelines:
@@ -52,7 +52,7 @@ spec:
           exporters: [debug]
 
 ---
-apiVersion: opentelemetry.io/v1alpha1
+apiVersion: opentelemetry.io/v1beta1
 kind: OpenTelemetryCollector
 metadata:
   name: statefulset
@@ -61,19 +61,19 @@ metadata:
 spec:
   mode: statefulset
   nodeSelector:
-  config: |
+  config:
     receivers:
       otlp:
         protocols:
-          grpc:
-          http:
-    processors:
+          grpc: {}
+          http: {}
+    processors: {}
 
     exporters:
-      debug:
+      debug: {}
 
     service:
       pipelines:
         traces:
           receivers: [otlp]
-          exporters: [debug]
\ No newline at end of file
+          exporters: [debug]
diff --git a/tests/e2e/node-selector-collector/01-install-collectors-with-node-selector.yaml b/tests/e2e/node-selector-collector/01-install-collectors-with-node-selector.yaml
index b03ae2569e..f83f56eb2c 100644
--- a/tests/e2e/node-selector-collector/01-install-collectors-with-node-selector.yaml
+++ b/tests/e2e/node-selector-collector/01-install-collectors-with-node-selector.yaml
@@ -1,4 +1,4 @@
-apiVersion: opentelemetry.io/v1alpha1
+apiVersion: opentelemetry.io/v1beta1
 kind: OpenTelemetryCollector
 metadata:
   name: deployment
@@ -8,16 +8,16 @@ spec:
   mode: deployment
   nodeSelector:
     kubernetes.io/os: linux
-  config: |
+  config:
     receivers:
       otlp:
         protocols:
-          grpc:
-          http:
-    processors:
+          grpc: {}
+          http: {}
+    processors: {}
 
     exporters:
-      debug:
+      debug: {}
 
     service:
       pipelines:
@@ -26,7 +26,7 @@ spec:
           exporters: [debug]
 
 ---
-apiVersion: opentelemetry.io/v1alpha1
+apiVersion: opentelemetry.io/v1beta1
 kind: OpenTelemetryCollector
 metadata:
   name: daemonset
@@ -36,16 +36,16 @@ spec:
   mode: daemonset
   nodeSelector:
     kubernetes.io/os: linux
-  config: |
+  config:
     receivers:
       otlp:
         protocols:
-          grpc:
-          http:
-    processors:
+          grpc: {}
+          http: {}
+    processors: {}
 
     exporters:
-      debug:
+      debug: {}
 
     service:
       pipelines:
@@ -54,7 +54,7 @@ spec:
           exporters: [debug]
 
 ---
-apiVersion: opentelemetry.io/v1alpha1
+apiVersion: opentelemetry.io/v1beta1
 kind: OpenTelemetryCollector
 metadata:
   name: statefulset
@@ -64,19 +64,19 @@ spec:
   mode: statefulset
   nodeSelector:
     kubernetes.io/os: linux
-  config: |
+  config:
     receivers:
       otlp:
         protocols:
-          grpc:
-          http:
-    processors:
+          grpc: {}
+          http: {}
+    processors: {}
 
     exporters:
-      debug:
+      debug: {}
 
     service:
       pipelines:
         traces:
           receivers: [otlp]
-          exporters: [debug]
\ No newline at end of file
+          exporters: [debug]
diff --git a/tests/e2e/volume-claim-label/00-assert.yaml b/tests/e2e/volume-claim-label/00-assert.yaml
new file mode 100644
index 0000000000..471bb7ede9
--- /dev/null
+++ b/tests/e2e/volume-claim-label/00-assert.yaml
@@ -0,0 +1,42 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: stateful-collector
+spec:
+  podManagementPolicy: Parallel
+  template:
+    spec:
+       containers:
+       - args:
+         - --config=/conf/collector.yaml
+         name: otc-container
+         volumeMounts:
+         - mountPath: /conf
+           name: otc-internal
+         - mountPath: /usr/share/testvolume
+           name: testvolume
+       volumes:
+       - configMap:
+           items:
+           - key: collector.yaml
+             path: collector.yaml
+         name: otc-internal
+       - emptyDir: {}
+         name: testvolume
+  volumeClaimTemplates:
+  - apiVersion: v1
+    kind: PersistentVolumeClaim
+    metadata:
+      name: testvolume
+      labels:
+        test: "true"
+    spec:
+      accessModes:
+      - ReadWriteOnce
+      resources:
+        requests:
+          storage: 1Gi
+      volumeMode: Filesystem
+status:
+  replicas: 3
+  readyReplicas: 3
diff --git a/tests/e2e/volume-claim-label/00-install.yaml b/tests/e2e/volume-claim-label/00-install.yaml
new file mode 100644
index 0000000000..07f49c18c4
--- /dev/null
+++ b/tests/e2e/volume-claim-label/00-install.yaml
@@ -0,0 +1,35 @@
+apiVersion: opentelemetry.io/v1alpha1
+kind: OpenTelemetryCollector
+metadata:
+  name: stateful
+spec:
+  mode: statefulset
+  replicas: 3
+  volumes:
+  - name: testvolume
+  volumeMounts:
+  - name: testvolume
+    mountPath: /usr/share/testvolume
+  volumeClaimTemplates:
+  - metadata:
+      name: testvolume
+      labels:
+        test: "true"
+    spec:
+      accessModes: [ "ReadWriteOnce" ]
+      resources:
+        requests:
+          storage: 1Gi
+  config: |
+    receivers:
+      jaeger:
+        protocols:
+          grpc:
+    processors:
+    exporters:
+      debug:
+    service:
+      pipelines:
+        traces:
+          receivers: [jaeger]
+          exporters: [debug]
diff --git a/tests/e2e/volume-claim-label/01-assert.yaml b/tests/e2e/volume-claim-label/01-assert.yaml
new file mode 100644
index 0000000000..438efa163f
--- /dev/null
+++ b/tests/e2e/volume-claim-label/01-assert.yaml
@@ -0,0 +1,42 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: stateful-collector
+spec:
+  podManagementPolicy: Parallel
+  template:
+    spec:
+       containers:
+       - args:
+         - --config=/conf/collector.yaml
+         name: otc-container
+         volumeMounts:
+         - mountPath: /conf
+           name: otc-internal
+         - mountPath: /usr/share/testvolume
+           name: testvolume
+       volumes:
+       - configMap:
+           items:
+           - key: collector.yaml
+             path: collector.yaml
+         name: otc-internal
+       - emptyDir: {}
+         name: testvolume
+  volumeClaimTemplates:
+  - apiVersion: v1
+    kind: PersistentVolumeClaim
+    metadata:
+      name: testvolume
+      labels:
+        test: "updated"
+    spec:
+      accessModes:
+      - ReadWriteOnce
+      resources:
+        requests:
+          storage: 1Gi
+      volumeMode: Filesystem
+status:
+  replicas: 3
+  readyReplicas: 3
diff --git a/tests/e2e/volume-claim-label/01-update-volume-claim-template-labels.yaml b/tests/e2e/volume-claim-label/01-update-volume-claim-template-labels.yaml
new file mode 100644
index 0000000000..5b1b68ea33
--- /dev/null
+++ b/tests/e2e/volume-claim-label/01-update-volume-claim-template-labels.yaml
@@ -0,0 +1,35 @@
+apiVersion: opentelemetry.io/v1alpha1
+kind: OpenTelemetryCollector
+metadata:
+  name: stateful
+spec:
+  mode: statefulset
+  replicas: 3
+  volumes:
+  - name: testvolume
+  volumeMounts:
+  - name: testvolume
+    mountPath: /usr/share/testvolume
+  volumeClaimTemplates:
+  - metadata:
+      name: testvolume
+      labels:
+        test: "updated"
+    spec:
+      accessModes: [ "ReadWriteOnce" ]
+      resources:
+        requests:
+          storage: 1Gi
+  config: |
+    receivers:
+      jaeger:
+        protocols:
+          grpc:
+    processors:
+    exporters:
+      debug:
+    service:
+      pipelines:
+        traces:
+          receivers: [jaeger]
+          exporters: [debug]
diff --git a/tests/e2e/volume-claim-label/chainsaw-test.yaml b/tests/e2e/volume-claim-label/chainsaw-test.yaml
new file mode 100755
index 0000000000..e079f6a8ae
--- /dev/null
+++ b/tests/e2e/volume-claim-label/chainsaw-test.yaml
@@ -0,0 +1,20 @@
+# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json
+apiVersion: chainsaw.kyverno.io/v1alpha1
+kind: Test
+metadata:
+  creationTimestamp: null
+  name: persistent-volume-claim-label
+spec:
+  steps:
+  - name: step-00
+    try:
+    - apply:
+        file: 00-install.yaml
+    - assert:
+        file: 00-assert.yaml
+  - name: step-01
+    try:
+    - apply:
+        file: 01-update-volume-claim-template-labels.yaml
+    - assert:
+        file: 01-assert.yaml