Repository: argoproj-labs/argocd-operator
Pull request #810 (2022-11-23 12:38:48)

feat: Bring new resource customizations to release-0.5 branch
**What type of PR is this?**
> Uncomment only one ` /kind` line, and delete the rest.
> For example, `> /kind bug` would simply become: `/kind bug`

> /kind bug
> /kind chore
> /kind cleanup
> /kind failing-test
/kind enhancement
> /kind documentation
> /kind code-refactoring


**What does this PR do / why we need it**:
brings new resource customizations to release-0.5 branch
see https://github.com/argoproj-labs/argocd-operator/pull/793 for details

**Have you updated the necessary documentation?**

* [ ] Documentation update is required by this PR.
* [ ] Documentation has been updated.

**Which issue(s) this PR fixes**:

Fixes #?

**How to test changes / Special notes to the reviewer**:



Patch:
diff --git a/api/v1alpha1/argocd_types.go b/api/v1alpha1/argocd_types.go
index c618b5c6..9e483e6c 100644
--- a/api/v1alpha1/argocd_types.go
+++ b/api/v1alpha1/argocd_types.go
@@ -541,6 +541,39 @@ type ArgoCDServerServiceSpec struct {
 	Type corev1.ServiceType `json:"type"`
 }
 
+// Resource Customization for custom health check
+type ResourceHealthCheck struct {
+	Group string `json:"group,omitempty"`
+	Kind  string `json:"kind,omitempty"`
+	Check string `json:"check,omitempty"`
+}
+
+// Resource Customization for ignore difference
+type ResourceIgnoreDifference struct {
+	All                 *IgnoreDifferenceCustomization `json:"all,omitempty"`
+	ResourceIdentifiers []ResourceIdentifiers          `json:"resourceIdentifiers,omitempty"`
+}
+
+// Resource Customization fields for ignore difference
+type ResourceIdentifiers struct {
+	Group         string                        `json:"group,omitempty"`
+	Kind          string                        `json:"kind,omitempty"`
+	Customization IgnoreDifferenceCustomization `json:"customization,omitempty"`
+}
+
+type IgnoreDifferenceCustomization struct {
+	JqPathExpressions     []string `json:"jqPathExpressions,omitempty"`
+	JsonPointers          []string `json:"jsonPointers,omitempty"`
+	ManagedFieldsManagers []string `json:"managedFieldsManagers,omitempty"`
+}
+
+// Resource Customization for custom action
+type ResourceAction struct {
+	Group  string `json:"group,omitempty"`
+	Kind   string `json:"kind,omitempty"`
+	Action string `json:"action,omitempty"`
+}
+
 // SSOProviderType string defines the type of SSO provider.
 type SSOProviderType string
 
@@ -689,10 +722,22 @@ type ArgoCDSpec struct {
 	// RepositoryCredentials are the Git pull credentials to configure Argo CD with upon creation of the cluster.
 	RepositoryCredentials string `json:"repositoryCredentials,omitempty"`
 
-	// ResourceCustomizations customizes resource behavior. Keys are in the form: group/Kind.
+	// ResourceCustomizations customizes resource behavior. Keys are in the form: group/Kind. Please note that this is being deprecated in favor of ResourceHealthChecks, ResourceIgnoreDifferences, and ResourceActions.
 	//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Resource Customizations'",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text","urn:alm:descriptor:com.tectonic.ui:advanced"}
 	ResourceCustomizations string `json:"resourceCustomizations,omitempty"`
 
+	// ResourceHealthChecks customizes resource health check behavior.
+	//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Resource Health Check Customizations'",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text","urn:alm:descriptor:com.tectonic.ui:advanced"}
+	ResourceHealthChecks []ResourceHealthCheck `json:"resourceHealthChecks,omitempty"`
+
+	// ResourceIgnoreDifferences customizes resource ignore difference behavior.
+	//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Resource Ignore Difference Customizations'",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text","urn:alm:descriptor:com.tectonic.ui:advanced"}
+	ResourceIgnoreDifferences *ResourceIgnoreDifference `json:"resourceIgnoreDifferences,omitempty"`
+
+	// ResourceActions customizes resource action behavior.
+	//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Resource Action Customizations'",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text","urn:alm:descriptor:com.tectonic.ui:advanced"}
+	ResourceActions []ResourceAction `json:"resourceActions,omitempty"`
+
 	// ResourceExclusions is used to completely ignore entire classes of resource group/kinds.
 	//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Resource Exclusions'",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text","urn:alm:descriptor:com.tectonic.ui:advanced"}
 	ResourceExclusions string `json:"resourceExclusions,omitempty"`
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 79f4b023..f98cbe95 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -903,6 +903,21 @@ func (in *ArgoCDSpec) DeepCopyInto(out *ArgoCDSpec) {
 	in.RBAC.DeepCopyInto(&out.RBAC)
 	in.Redis.DeepCopyInto(&out.Redis)
 	in.Repo.DeepCopyInto(&out.Repo)
+	if in.ResourceHealthChecks != nil {
+		in, out := &in.ResourceHealthChecks, &out.ResourceHealthChecks
+		*out = make([]ResourceHealthCheck, len(*in))
+		copy(*out, *in)
+	}
+	if in.ResourceIgnoreDifferences != nil {
+		in, out := &in.ResourceIgnoreDifferences, &out.ResourceIgnoreDifferences
+		*out = new(ResourceIgnoreDifference)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.ResourceActions != nil {
+		in, out := &in.ResourceActions, &out.ResourceActions
+		*out = make([]ResourceAction, len(*in))
+		copy(*out, *in)
+	}
 	in.Server.DeepCopyInto(&out.Server)
 	if in.SourceNamespaces != nil {
 		in, out := &in.SourceNamespaces, &out.SourceNamespaces
@@ -985,6 +1000,36 @@ func (in *Banner) DeepCopy() *Banner {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *IgnoreDifferenceCustomization) DeepCopyInto(out *IgnoreDifferenceCustomization) {
+	*out = *in
+	if in.JqPathExpressions != nil {
+		in, out := &in.JqPathExpressions, &out.JqPathExpressions
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.JsonPointers != nil {
+		in, out := &in.JsonPointers, &out.JsonPointers
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.ManagedFieldsManagers != nil {
+		in, out := &in.ManagedFieldsManagers, &out.ManagedFieldsManagers
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IgnoreDifferenceCustomization.
+func (in *IgnoreDifferenceCustomization) DeepCopy() *IgnoreDifferenceCustomization {
+	if in == nil {
+		return nil
+	}
+	out := new(IgnoreDifferenceCustomization)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *KustomizeVersionSpec) DeepCopyInto(out *KustomizeVersionSpec) {
 	*out = *in
@@ -1000,6 +1045,79 @@ func (in *KustomizeVersionSpec) DeepCopy() *KustomizeVersionSpec {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ResourceAction) DeepCopyInto(out *ResourceAction) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceAction.
+func (in *ResourceAction) DeepCopy() *ResourceAction {
+	if in == nil {
+		return nil
+	}
+	out := new(ResourceAction)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ResourceHealthCheck) DeepCopyInto(out *ResourceHealthCheck) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceHealthCheck.
+func (in *ResourceHealthCheck) DeepCopy() *ResourceHealthCheck {
+	if in == nil {
+		return nil
+	}
+	out := new(ResourceHealthCheck)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ResourceIdentifiers) DeepCopyInto(out *ResourceIdentifiers) {
+	*out = *in
+	in.Customization.DeepCopyInto(&out.Customization)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceIdentifiers.
+func (in *ResourceIdentifiers) DeepCopy() *ResourceIdentifiers {
+	if in == nil {
+		return nil
+	}
+	out := new(ResourceIdentifiers)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ResourceIgnoreDifference) DeepCopyInto(out *ResourceIgnoreDifference) {
+	*out = *in
+	if in.All != nil {
+		in, out := &in.All, &out.All
+		*out = new(IgnoreDifferenceCustomization)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.ResourceIdentifiers != nil {
+		in, out := &in.ResourceIdentifiers, &out.ResourceIdentifiers
+		*out = make([]ResourceIdentifiers, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceIgnoreDifference.
+func (in *ResourceIgnoreDifference) DeepCopy() *ResourceIgnoreDifference {
+	if in == nil {
+		return nil
+	}
+	out := new(ResourceIgnoreDifference)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *SSHHostsSpec) DeepCopyInto(out *SSHHostsSpec) {
 	*out = *in
diff --git a/bundle/manifests/argocd-operator.clusterserviceversion.yaml b/bundle/manifests/argocd-operator.clusterserviceversion.yaml
index 59fb1b2a..e4532565 100644
--- a/bundle/manifests/argocd-operator.clusterserviceversion.yaml
+++ b/bundle/manifests/argocd-operator.clusterserviceversion.yaml
@@ -591,8 +591,15 @@ spec:
         x-descriptors:
         - urn:alm:descriptor:com.tectonic.ui:fieldGroup:Repo
         - urn:alm:descriptor:com.tectonic.ui:resourceRequirements
+      - description: ResourceActions customizes resource action behavior.
+        displayName: Resource Action Customizations'
+        path: resourceActions
+        x-descriptors:
+        - urn:alm:descriptor:com.tectonic.ui:text
+        - urn:alm:descriptor:com.tectonic.ui:advanced
       - description: 'ResourceCustomizations customizes resource behavior. Keys are
-          in the form: group/Kind.'
+          in the form: group/Kind. Please note that this is being deprecated in favor
+          of ResourceHealthChecks, ResourceIgnoreDifferences, and ResourceActions.'
         displayName: Resource Customizations'
         path: resourceCustomizations
         x-descriptors:
@@ -605,6 +612,19 @@ spec:
         x-descriptors:
         - urn:alm:descriptor:com.tectonic.ui:text
         - urn:alm:descriptor:com.tectonic.ui:advanced
+      - description: ResourceHealthChecks customizes resource health check behavior.
+        displayName: Resource Health Check Customizations'
+        path: resourceHealthChecks
+        x-descriptors:
+        - urn:alm:descriptor:com.tectonic.ui:text
+        - urn:alm:descriptor:com.tectonic.ui:advanced
+      - description: ResourceIgnoreDifferences customizes resource ignore difference
+          behavior.
+        displayName: Resource Ignore Difference Customizations'
+        path: resourceIgnoreDifferences
+        x-descriptors:
+        - urn:alm:descriptor:com.tectonic.ui:text
+        - urn:alm:descriptor:com.tectonic.ui:advanced
       - description: ResourceTrackingMethod defines how Argo CD should track resources
           that it manages
         displayName: Resource Tracking Method'
diff --git a/bundle/manifests/argoproj.io_argocds.yaml b/bundle/manifests/argoproj.io_argocds.yaml
index d0aab458..ac9429ea 100644
--- a/bundle/manifests/argoproj.io_argocds.yaml
+++ b/bundle/manifests/argoproj.io_argocds.yaml
@@ -5480,14 +5480,88 @@ spec:
                 description: RepositoryCredentials are the Git pull credentials to
                   configure Argo CD with upon creation of the cluster.
                 type: string
+              resourceActions:
+                description: ResourceActions customizes resource action behavior.
+                items:
+                  description: Resource Customization for custom action
+                  properties:
+                    action:
+                      type: string
+                    group:
+                      type: string
+                    kind:
+                      type: string
+                  type: object
+                type: array
               resourceCustomizations:
                 description: 'ResourceCustomizations customizes resource behavior.
-                  Keys are in the form: group/Kind.'
+                  Keys are in the form: group/Kind. Please note that this is being
+                  deprecated in favor of ResourceHealthChecks, ResourceIgnoreDifferences,
+                  and ResourceActions.'
                 type: string
               resourceExclusions:
                 description: ResourceExclusions is used to completely ignore entire
                   classes of resource group/kinds.
                 type: string
+              resourceHealthChecks:
+                description: ResourceHealthChecks customizes resource health check
+                  behavior.
+                items:
+                  description: Resource Customization for custom health check
+                  properties:
+                    check:
+                      type: string
+                    group:
+                      type: string
+                    kind:
+                      type: string
+                  type: object
+                type: array
+              resourceIgnoreDifferences:
+                description: ResourceIgnoreDifferences customizes resource ignore
+                  difference behavior.
+                properties:
+                  all:
+                    properties:
+                      jqPathExpressions:
+                        items:
+                          type: string
+                        type: array
+                      jsonPointers:
+                        items:
+                          type: string
+                        type: array
+                      managedFieldsManagers:
+                        items:
+                          type: string
+                        type: array
+                    type: object
+                  resourceIdentifiers:
+                    items:
+                      description: Resource Customization fields for ignore difference
+                      properties:
+                        customization:
+                          properties:
+                            jqPathExpressions:
+                              items:
+                                type: string
+                              type: array
+                            jsonPointers:
+                              items:
+                                type: string
+                              type: array
+                            managedFieldsManagers:
+                              items:
+                                type: string
+                              type: array
+                          type: object
+                        group:
+                          type: string
+                        kind:
+                          type: string
+                      type: object
+                    type: array
+                type: object
               resourceInclusions:
                 description: ResourceInclusions is used to only include specific group/kinds
                   in the reconciliation process.
diff --git a/config/crd/bases/argoproj.io_argocds.yaml b/config/crd/bases/argoproj.io_argocds.yaml
index 7fbf7dd5..f361245e 100644
--- a/config/crd/bases/argoproj.io_argocds.yaml
+++ b/config/crd/bases/argoproj.io_argocds.yaml
@@ -5482,14 +5482,88 @@ spec:
                 description: RepositoryCredentials are the Git pull credentials to
                   configure Argo CD with upon creation of the cluster.
                 type: string
+              resourceActions:
+                description: ResourceActions customizes resource action behavior.
+                items:
+                  description: Resource Customization for custom action
+                  properties:
+                    action:
+                      type: string
+                    group:
+                      type: string
+                    kind:
+                      type: string
+                  type: object
+                type: array
               resourceCustomizations:
                 description: 'ResourceCustomizations customizes resource behavior.
-                  Keys are in the form: group/Kind.'
+                  Keys are in the form: group/Kind. Please note that this is being
+                  deprecated in favor of ResourceHealthChecks, ResourceIgnoreDifferences,
+                  and ResourceActions.'
                 type: string
               resourceExclusions:
                 description: ResourceExclusions is used to completely ignore entire
                   classes of resource group/kinds.
                 type: string
+              resourceHealthChecks:
+                description: ResourceHealthChecks customizes resource health check
+                  behavior.
+                items:
+                  description: Resource Customization for custom health check
+                  properties:
+                    check:
+                      type: string
+                    group:
+                      type: string
+                    kind:
+                      type: string
+                  type: object
+                type: array
+              resourceIgnoreDifferences:
+                description: ResourceIgnoreDifferences customizes resource ignore
+                  difference behavior.
+                properties:
+                  all:
+                    properties:
+                      jqPathExpressions:
+                        items:
+                          type: string
+                        type: array
+                      jsonPointers:
+                        items:
+                          type: string
+                        type: array
+                      managedFieldsManagers:
+                        items:
+                          type: string
+                        type: array
+                    type: object
+                  resourceIdentifiers:
+                    items:
+                      description: Resource Customization fields for ignore difference
+                      properties:
+                        customization:
+                          properties:
+                            jqPathExpressions:
+                              items:
+                                type: string
+                              type: array
+                            jsonPointers:
+                              items:
+                                type: string
+                              type: array
+                            managedFieldsManagers:
+                              items:
+                                type: string
+                              type: array
+                          type: object
+                        group:
+                          type: string
+                        kind:
+                          type: string
+                      type: object
+                    type: array
+                type: object
               resourceInclusions:
                 description: ResourceInclusions is used to only include specific group/kinds
                   in the reconciliation process.
diff --git a/config/manifests/bases/argocd-operator.clusterserviceversion.yaml b/config/manifests/bases/argocd-operator.clusterserviceversion.yaml
index 88db44a0..ac62e881 100644
--- a/config/manifests/bases/argocd-operator.clusterserviceversion.yaml
+++ b/config/manifests/bases/argocd-operator.clusterserviceversion.yaml
@@ -465,8 +465,15 @@ spec:
         x-descriptors:
         - urn:alm:descriptor:com.tectonic.ui:fieldGroup:Repo
         - urn:alm:descriptor:com.tectonic.ui:resourceRequirements
+      - description: ResourceActions customizes resource action behavior.
+        displayName: Resource Action Customizations'
+        path: resourceActions
+        x-descriptors:
+        - urn:alm:descriptor:com.tectonic.ui:text
+        - urn:alm:descriptor:com.tectonic.ui:advanced
       - description: 'ResourceCustomizations customizes resource behavior. Keys are
-          in the form: group/Kind.'
+          in the form: group/Kind. Please note that this is being deprecated in favor
+          of ResourceHealthChecks, ResourceIgnoreDifferences, and ResourceActions.'
         displayName: Resource Customizations'
         path: resourceCustomizations
         x-descriptors:
@@ -479,6 +486,19 @@ spec:
         x-descriptors:
         - urn:alm:descriptor:com.tectonic.ui:text
         - urn:alm:descriptor:com.tectonic.ui:advanced
+      - description: ResourceHealthChecks customizes resource health check behavior.
+        displayName: Resource Health Check Customizations'
+        path: resourceHealthChecks
+        x-descriptors:
+        - urn:alm:descriptor:com.tectonic.ui:text
+        - urn:alm:descriptor:com.tectonic.ui:advanced
+      - description: ResourceIgnoreDifferences customizes resource ignore difference
+          behavior.
+        displayName: Resource Ignore Difference Customizations'
+        path: resourceIgnoreDifferences
+        x-descriptors:
+        - urn:alm:descriptor:com.tectonic.ui:text
+        - urn:alm:descriptor:com.tectonic.ui:advanced
       - description: ResourceTrackingMethod defines how Argo CD should track resources
           that it manages
         displayName: Resource Tracking Method'
diff --git a/controllers/argocd/configmap.go b/controllers/argocd/configmap.go
index a59dceb1..7fdff3e9 100644
--- a/controllers/argocd/configmap.go
+++ b/controllers/argocd/configmap.go
@@ -22,6 +22,7 @@ import (
 	"reflect"
 	"strings"
 
+	"gopkg.in/yaml.v2"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
@@ -144,15 +145,71 @@ func getRBACScopes(cr *argoprojv1a1.ArgoCD) string {
 	return scopes
 }
 
-// getResourceCustomizations will return the resource customizations for the given ArgoCD.
+// getResourceCustomizations loads Resource Customizations from argocd-cm ConfigMap
 func getResourceCustomizations(cr *argoprojv1a1.ArgoCD) string {
 	rc := common.ArgoCDDefaultResourceCustomizations
 	if cr.Spec.ResourceCustomizations != "" {
 		rc = cr.Spec.ResourceCustomizations
 	}
+
 	return rc
 }
 
+// getResourceHealthChecks loads health customizations to `resource.customizations.health` from argocd-cm ConfigMap
+func getResourceHealthChecks(cr *argoprojv1a1.ArgoCD) map[string]string {
+	healthCheck := make(map[string]string)
+	if cr.Spec.ResourceHealthChecks != nil {
+		resourceHealthChecks := cr.Spec.ResourceHealthChecks
+		for _, healthCustomization := range resourceHealthChecks {
+			subkey := "resource.customizations.health." + healthCustomization.Group + "_" + healthCustomization.Kind
+			subvalue := healthCustomization.Check
+			healthCheck[subkey] = subvalue
+		}
+	}
+	return healthCheck
+}
+
+// getResourceIgnoreDifferences loads ignore differences customizations to `resource.customizations.ignoreDifferences` from argocd-cm ConfigMap
+func getResourceIgnoreDifferences(cr *argoprojv1a1.ArgoCD) (map[string]string, error) {
+	ignoreDiff := make(map[string]string)
+	if cr.Spec.ResourceIgnoreDifferences != nil {
+		resourceIgnoreDiff := cr.Spec.ResourceIgnoreDifferences
+		if resourceIgnoreDiff.All != nil {
+			subkey := "resource.customizations.ignoreDifferences.all"
+			bytes, err := yaml.Marshal(resourceIgnoreDiff.All)
+			if err != nil {
+				return ignoreDiff, err
+			}
+			subvalue := string(bytes)
+			ignoreDiff[subkey] = subvalue
+		}
+		for _, ignoreDiffCustomization := range resourceIgnoreDiff.ResourceIdentifiers {
+			subkey := "resource.customizations.ignoreDifferences." + ignoreDiffCustomization.Group + "_" + ignoreDiffCustomization.Kind
+			bytes, err := yaml.Marshal(ignoreDiffCustomization.Customization)
+			if err != nil {
+				return ignoreDiff, err
+			}
+			subvalue := string(bytes)
+			ignoreDiff[subkey] = subvalue
+		}
+	}
+	return ignoreDiff, nil
+}
+
+// getResourceActions loads custom actions to `resource.customizations.actions` from argocd-cm ConfigMap
+func getResourceActions(cr *argoprojv1a1.ArgoCD) map[string]string {
+	action := make(map[string]string)
+	if cr.Spec.ResourceActions != nil {
+		resourceAction := cr.Spec.ResourceActions
+		for _, actionCustomization := range resourceAction {
+			subkey := "resource.customizations.actions." + actionCustomization.Group + "_" + actionCustomization.Kind
+			subvalue := actionCustomization.Action
+			action[subkey] = subvalue
+		}
+	}
+	return action
+}
+
 // getResourceExclusions will return the resource exclusions for the given ArgoCD.
 func getResourceExclusions(cr *argoprojv1a1.ArgoCD) string {
 	re := common.ArgoCDDefaultResourceExclusions
@@ -331,9 +388,47 @@ func (r *ReconcileArgoCD) reconcileArgoConfigMap(cr *argoprojv1a1.ArgoCD) error
 	}
 
 	cm.Data[common.ArgoCDKeyOIDCConfig] = getOIDCConfig(cr)
+
+	if c := getResourceHealthChecks(cr); c != nil {
+		for k, v := range c {
+			cm.Data[k] = v
+		}
+	}
+
+	if c, err := getResourceIgnoreDifferences(cr); c != nil && err == nil {
+		for k, v := range c {
+			cm.Data[k] = v
+		}
+	} else {
+		return err
+	}
+
+	if c := getResourceActions(cr); c != nil {
+		for k, v := range c {
+			cm.Data[k] = v
+		}
+	}
+
+	// old format of ResourceCustomizations
 	if c := getResourceCustomizations(cr); c != "" {
+
+		// Emit event providing users with deprecation notice for ResourceCustomization if not emitted already
+		if currentInstanceEventEmissionStatus, ok := DeprecationEventEmissionTracker[cr.Namespace]; !ok || !currentInstanceEventEmissionStatus.ResourceCustomizationsDeprecationWarningEmitted {
+			err := argoutil.CreateEvent(r.Client, "Warning", "Deprecated", "ResourceCustomizations is deprecated, please use the new formats `ResourceHealthChecks`, `ResourceIgnoreDifferences`, and `ResourceActions` instead.", "DeprecationNotice", cr.ObjectMeta, cr.TypeMeta)
+			if err != nil {
+				return err
+			}
+
+			if !ok {
+				currentInstanceEventEmissionStatus = DeprecationEventEmissionStatus{ResourceCustomizationsDeprecationWarningEmitted: true}
+			} else {
+				currentInstanceEventEmissionStatus.ResourceCustomizationsDeprecationWarningEmitted = true
+			}
+			DeprecationEventEmissionTracker[cr.Namespace] = currentInstanceEventEmissionStatus
+		}
 		cm.Data[common.ArgoCDKeyResourceCustomizations] = c
 	}
+
 	cm.Data[common.ArgoCDKeyResourceExclusions] = getResourceExclusions(cr)
 	cm.Data[common.ArgoCDKeyResourceInclusions] = getResourceInclusions(cr)
 	cm.Data[common.ArgoCDKeyResourceTrackingMethod] = getResourceTrackingMethod(cr)
diff --git a/controllers/argocd/sso.go b/controllers/argocd/sso.go
index 961c8318..987ef291 100644
--- a/controllers/argocd/sso.go
+++ b/controllers/argocd/sso.go
@@ -36,24 +36,11 @@ const (
 	multipleSSOConfiguration string = "multiple SSO configuration: "
 )
 
-// DeprecationEventEmissionStatus is meant to track which deprecation events have been emitted already. This is temporary and can be removed in v0.0.6 once we have provided enough
-// deprecation notice
-type DeprecationEventEmissionStatus struct {
-	SSOSpecDeprecationWarningEmitted    bool
-	DexSpecDeprecationWarningEmitted    bool
-	DisableDexDeprecationWarningEmitted bool
-}
-
 var (
 	templateAPIFound     = false
 	ssoConfigLegalStatus string
 )
 
-// DeprecationEventEmissionTracker map stores the namespace containing ArgoCD instance as key and DeprecationEventEmissionStatus as value,
-// where DeprecationEventEmissionStatus tracks the events that have been emitted for the instance in the particular namespace.
-// This is temporary and can be removed in v0.0.6 when we remove the deprecated fields.
-var DeprecationEventEmissionTracker = make(map[string]DeprecationEventEmissionStatus)
-
 // IsTemplateAPIAvailable returns true if the template API is present.
 func IsTemplateAPIAvailable() bool {
 	return templateAPIFound
diff --git a/controllers/argocd/util.go b/controllers/argocd/util.go
index 3ad1b771..fc93596c 100644
--- a/controllers/argocd/util.go
+++ b/controllers/argocd/util.go
@@ -1160,6 +1160,20 @@ func containsString(arr []string, s string) bool {
 	return false
 }
 
+// DeprecationEventEmissionStatus is meant to track which deprecation events have been emitted already. This is temporary and can be removed in v0.0.6 once we have provided enough
+// deprecation notice
+type DeprecationEventEmissionStatus struct {
+	SSOSpecDeprecationWarningEmitted                bool
+	DexSpecDeprecationWarningEmitted                bool
+	DisableDexDeprecationWarningEmitted             bool
+	ResourceCustomizationsDeprecationWarningEmitted bool
+}
+
+// DeprecationEventEmissionTracker map stores the namespace containing ArgoCD instance as key and DeprecationEventEmissionStatus as value,
+// where DeprecationEventEmissionStatus tracks the events that have been emitted for the instance in the particular namespace.
+// This is temporary and can be removed in v0.0.6 when we remove the deprecated fields.
+var DeprecationEventEmissionTracker = make(map[string]DeprecationEventEmissionStatus)
+
 func namespaceFilterPredicate() predicate.Predicate {
 	return predicate.Funcs{
 		UpdateFunc: func(e event.UpdateEvent) bool {
diff --git a/deploy/olm-catalog/argocd-operator/0.5.0/argocd-operator.v0.5.0.clusterserviceversion.yaml b/deploy/olm-catalog/argocd-operator/0.5.0/argocd-operator.v0.5.0.clusterserviceversion.yaml
index 59fb1b2a..e4532565 100644
--- a/deploy/olm-catalog/argocd-operator/0.5.0/argocd-operator.v0.5.0.clusterserviceversion.yaml
+++ b/deploy/olm-catalog/argocd-operator/0.5.0/argocd-operator.v0.5.0.clusterserviceversion.yaml
@@ -591,8 +591,15 @@ spec:
         x-descriptors:
         - urn:alm:descriptor:com.tectonic.ui:fieldGroup:Repo
         - urn:alm:descriptor:com.tectonic.ui:resourceRequirements
+      - description: ResourceActions customizes resource action behavior.
+        displayName: Resource Action Customizations'
+        path: resourceActions
+        x-descriptors:
+        - urn:alm:descriptor:com.tectonic.ui:text
+        - urn:alm:descriptor:com.tectonic.ui:advanced
       - description: 'ResourceCustomizations customizes resource behavior. Keys are
-          in the form: group/Kind.'
+          in the form: group/Kind. Please note that this is being deprecated in favor
+          of ResourceHealthChecks, ResourceIgnoreDifferences, and ResourceActions.'
         displayName: Resource Customizations'
         path: resourceCustomizations
         x-descriptors:
@@ -605,6 +612,19 @@ spec:
         x-descriptors:
         - urn:alm:descriptor:com.tectonic.ui:text
         - urn:alm:descriptor:com.tectonic.ui:advanced
+      - description: ResourceHealthChecks customizes resource health check behavior.
+        displayName: Resource Health Check Customizations'
+        path: resourceHealthChecks
+        x-descriptors:
+        - urn:alm:descriptor:com.tectonic.ui:text
+        - urn:alm:descriptor:com.tectonic.ui:advanced
+      - description: ResourceIgnoreDifferences customizes resource ignore difference
+          behavior.
+        displayName: Resource Ignore Difference Customizations'
+        path: resourceIgnoreDifferences
+        x-descriptors:
+        - urn:alm:descriptor:com.tectonic.ui:text
+        - urn:alm:descriptor:com.tectonic.ui:advanced
       - description: ResourceTrackingMethod defines how Argo CD should track resources
           that it manages
         displayName: Resource Tracking Method'
diff --git a/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_argocds.yaml b/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_argocds.yaml
index d0aab458..ac9429ea 100644
--- a/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_argocds.yaml
+++ b/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_argocds.yaml
@@ -5480,14 +5480,88 @@ spec:
                 description: RepositoryCredentials are the Git pull credentials to
                   configure Argo CD with upon creation of the cluster.
                 type: string
+              resourceActions:
+                description: ResourceActions customizes resource action behavior.
+                items:
+                  description: Resource Customization for custom action
+                  properties:
+                    action:
+                      type: string
+                    group:
+                      type: string
+                    kind:
+                      type: string
+                  type: object
+                type: array
               resourceCustomizations:
                 description: 'ResourceCustomizations customizes resource behavior.
-                  Keys are in the form: group/Kind.'
+                  Keys are in the form: group/Kind. Please note that this is being
+                  deprecated in favor of ResourceHealthChecks, ResourceIgnoreDifferences,
+                  and ResourceActions.'
                 type: string
               resourceExclusions:
                 description: ResourceExclusions is used to completely ignore entire
                   classes of resource group/kinds.
                 type: string
+              resourceHealthChecks:
+                description: ResourceHealthChecks customizes resource health check
+                  behavior.
+                items:
+                  description: Resource Customization for custom health check
+                  properties:
+                    check:
+                      type: string
+                    group:
+                      type: string
+                    kind:
+                      type: string
+                  type: object
+                type: array
+              resourceIgnoreDifferences:
+                description: ResourceIgnoreDifferences customizes resource ignore
+                  difference behavior.
+                properties:
+                  all:
+                    properties:
+                      jqPathExpressions:
+                        items:
+                          type: string
+                        type: array
+                      jsonPointers:
+                        items:
+                          type: string
+                        type: array
+                      managedFieldsManagers:
+                        items:
+                          type: string
+                        type: array
+                    type: object
+                  resourceIdentifiers:
+                    items:
+                      description: Resource Customization fields for ignore difference
+                      properties:
+                        customization:
+                          properties:
+                            jqPathExpressions:
+                              items:
+                                type: string
+                              type: array
+                            jsonPointers:
+                              items:
+                                type: string
+                              type: array
+                            managedFieldsManagers:
+                              items:
+                                type: string
+                              type: array
+                          type: object
+                        group:
+                          type: string
+                        kind:
+                          type: string
+                      type: object
+                    type: array
+                type: object
               resourceInclusions:
                 description: ResourceInclusions is used to only include specific group/kinds
                   in the reconciliation process.
diff --git a/docs/reference/argocd.md b/docs/reference/argocd.md
index 0fbd9a11..46c08dd2 100644
--- a/docs/reference/argocd.md
+++ b/docs/reference/argocd.md
@@ -957,10 +957,141 @@ spec:
 
 ## Resource Customizations
 
-The configuration to customize resource behavior. This property maps directly to the `resource.customizations` field in the `argocd-cm` ConfigMap.
+There are two ways to customize resource behavior- the first way, only available with release v0.5.0+, is with subkeys (`resourceHealthChecks`, `resourceIgnoreDifferences`, and `resourceActions`), the second is without subkeys (`resourceCustomizations`). `resourceCustomizations` maps directly to the `resource.customizations` field in the `argocd-cm` ConfigMap, while each of the subkeys maps directly to their own field in the `argocd-cm`. `resourceHealthChecks` will map to `resource.customizations.health`, `resourceIgnoreDifferences` to `resource.customizations.ignoreDifferences`, and `resourceActions` to `resource.customizations.actions`.
+
+!!! warning 
+    `resourceCustomizations` is being deprecated so is encouraged to use `resourceHealthChecks`, `resourceIgnoreDifferences`, and `resourceActions` instead. It is the user's responsibility to not provide conflicting resources if they choose to use both methods of resource customizations. 
+
+### Resource Customizations (with subkeys) Example
+
+Keys for `resourceHealthChecks`, `resourceIgnoreDifferences`, and `resourceActions` are in the form (respectively): `resource.customizations.health.<group_kind>`, `resource.customizations.ignoreDifferences.<group_kind>`, and `resource.customizations.actions.<group_kind>`. The following example defines a custom health check, custom action, and an ignoreDifferences config in the `argocd-cm` ConfigMap. Additionally, `.spec.resourceIgnoreDifferences.all` allows you to apply these specified settings to all resources managed by this Argo CD instance.
+
+``` yaml
+apiVersion: argoproj.io/v1alpha1
+kind: ArgoCD
+metadata:
+  name: argocd
+spec:
+  resourceIgnoreDifferences:
+    all:
+      jqPathExpressions:
+          - xyz
+          - abc
+      jsonPointers:
+          - xyz
+          - abc
+      managedFieldsManagers:
+          - xyz
+          - abc
+    resourceIdentifiers:
+      - group: apps
+        kind: deployments
+        customization:
+          jqPathExpressions:
+            - xyz
+            - abc
+          jsonPointers:
+            - xyz
+            - abc
+          managedFieldManagers:
+            - xyz
+            - abc
+      - group: batch
+        kind: jobs
+        customization:
+          jqPathExpressions:
+            - xyz
+            - abc
+          jsonPointers:
+            - xyz
+            - abc
+          managedFieldsManagers:
+            - xyz
+            - abc
+  resourceHealthChecks:
+    - group: certmanager.k8s.io
+      kind: Certificate
+      check: |
+        hs = {}
+        if obj.status ~= nil then
+          if obj.status.conditions ~= nil then
+            for i, condition in ipairs(obj.status.conditions) do
+              if condition.type == "Ready" and condition.status == "False" then
+                hs.status = "Degraded"
+                hs.message = condition.message
+                return hs
+              end
+              if condition.type == "Ready" and condition.status == "True" then
+                hs.status = "Healthy"
+                hs.message = condition.message
+                return hs
+              end
+            end
+          end
+        end
+        hs.status = "Progressing"
+        hs.message = "Waiting for certificate"
+        return hs
+  resourceActions:
+    - group: apps
+      kind: Deployment
+      action: |
+        discovery.lua: |
+        actions = {}
+        actions["restart"] = {}
+        return actions
+        definitions:
+        - name: restart
+          # Lua Script to modify the obj
+          action.lua: |
+            local os = require("os")
+            if obj.spec.template.metadata == nil then
+                obj.spec.template.metadata = {}
+            end
+            if obj.spec.template.metadata.annotations == nil then
+                obj.spec.template.metadata.annotations = {}
+            end
+            obj.spec.template.metadata.annotations["kubectl.kubernetes.io/restartedAt"] = os.date("!%Y-%m-%dT%XZ")
+            return obj
+```
+ After applying these changes your `argocd-cm` Configmap should contain the following fields: 
+
+```
+resource.customizations.ignoreDifferences.all: |
+    jqpathexpressions:
+    - xyz
+    - abc
+    jsonpointers:
+    - xyz
+    - abc
+    managedfieldsmanagers:
+    - xyz
+    - abc
+  resource.customizations.ignoreDifferences.apps_deployments: |
+    jqpathexpressions:
+    - xyz
+    - abc
+    jsonpointers:
+    - xyz
+    - abc
+    managedfieldsmanagers: []
+  resource.customizations.ignoreDifferences.batch_jobs: |
+    jqpathexpressions:
+    - xyz
+    - abc
+    jsonpointers:
+    - xyz
+    - abc
+    managedfieldsmanagers:
+    - xyz
+    - abc
+```
 
 ### Resource Customizations Example
 
+!!! warning 
+    `resourceCustomizations` is being deprecated in favor of `resourceHealthChecks`, `resourceIgnoreDifferences`, and `resourceActions`.
+
 The following example defines a custom PVC health check in the `argocd-cm` ConfigMap using the `ResourceCustomizations` property on the `ArgoCD` resource.
 
 ``` yaml
diff --git a/examples/argocd-resource-customizations.yaml b/examples/argocd-resource-customizations.yaml
new file mode 100644
index 00000000..e9eb96e8
--- /dev/null
+++ b/examples/argocd-resource-customizations.yaml
@@ -0,0 +1,86 @@
+apiVersion: argoproj.io/v1alpha1
+kind: ArgoCD
+metadata:
+  name: argocd
+spec:
+  resourceIgnoreDifferences:
+    all:
+      jqPathExpressions:
+          - xyz
+          - abc
+      jsonPointers:
+          - xyz
+          - abc
+      managedFieldsManagers:
+          - xyz
+          - abc
+    resourceIdentifiers:
+      - group: apps
+        kind: deployments
+        customization:
+          jqPathExpressions:
+            - xyz
+            - abc
+          jsonPointers:
+            - xyz
+            - abc
+          managedFieldManagers:
+            - xyz
+            - abc
+      - group: batch
+        kind: jobs
+        customization:
+          jqPathExpressions:
+            - xyz
+            - abc
+          jsonPointers:
+            - xyz
+            - abc
+          managedFieldsManagers:
+            - xyz
+            - abc
+  resourceHealthChecks:
+    - group: certmanager.k8s.io
+      kind: Certificate
+      check: |
+        hs = {}
+        if obj.status ~= nil then
+          if obj.status.conditions ~= nil then
+            for i, condition in ipairs(obj.status.conditions) do
+              if condition.type == "Ready" and condition.status == "False" then
+                hs.status = "Degraded"
+                hs.message = condition.message
+                return hs
+              end
+              if condition.type == "Ready" and condition.status == "True" then
+                hs.status = "Healthy"
+                hs.message = condition.message
+                return hs
+              end
+            end
+          end
+        end
+        hs.status = "Progressing"
+        hs.message = "Waiting for certificate"
+        return hs
+  resourceActions:
+    - group: apps
+      kind: Deployment
+      action: |
+        discovery.lua: |
+        actions = {}
+        actions["restart"] = {}
+        return actions
+        definitions:
+        - name: restart
+          # Lua Script to modify the obj
+          action.lua: |
+            local os = require("os")
+            if obj.spec.template.metadata == nil then
+                obj.spec.template.metadata = {}
+            end
+            if obj.spec.template.metadata.annotations == nil then
+                obj.spec.template.metadata.annotations = {}
+            end
+            obj.spec.template.metadata.annotations["kubectl.kubernetes.io/restartedAt"] = os.date("!%Y-%m-%dT%XZ")
+            return obj
\ No newline at end of file


Test patch:
diff --git a/controllers/argocd/configmap_test.go b/controllers/argocd/configmap_test.go
index 6d71b099..9fc0d8ad 100644
--- a/controllers/argocd/configmap_test.go
+++ b/controllers/argocd/configmap_test.go
@@ -791,6 +791,133 @@ func TestReconcileArgoCD_reconcileArgoConfigMap_withResourceCustomizations(t *te
 	}
 }
 
+func TestReconcileArgoCD_reconcileArgoConfigMap_withNewResourceCustomizations(t *testing.T) {
+	logf.SetLogger(ZapLogger(true))
+
+	desiredIgnoreDifferenceCustomization :=
+		`jqpathexpressions:
+- a
+- b
+jsonpointers:
+- a
+- b
+managedfieldsmanagers:
+- a
+- b
+`
+
+	health := []argoprojv1alpha1.ResourceHealthCheck{
+		{
+			Group: "healthFoo",
+			Kind:  "healthFoo",
+			Check: "healthFoo",
+		},
+		{
+			Group: "healthBar",
+			Kind:  "healthBar",
+			Check: "healthBar",
+		},
+	}
+	actions := []argoprojv1alpha1.ResourceAction{
+		{
+			Group:  "actionsFoo",
+			Kind:   "actionsFoo",
+			Action: "actionsFoo",
+		},
+		{
+			Group:  "actionsBar",
+			Kind:   "actionsBar",
+			Action: "actionsBar",
+		},
+	}
+	ignoreDifferences := argoprojv1alpha1.ResourceIgnoreDifference{
+		All: &v1alpha1.IgnoreDifferenceCustomization{
+			JqPathExpressions:     []string{"a", "b"},
+			JsonPointers:          []string{"a", "b"},
+			ManagedFieldsManagers: []string{"a", "b"},
+		},
+		ResourceIdentifiers: []argoprojv1alpha1.ResourceIdentifiers{
+			{
+				Group: "ignoreDiffBar",
+				Kind:  "ignoreDiffBar",
+				Customization: v1alpha1.IgnoreDifferenceCustomization{
+					JqPathExpressions:     []string{"a", "b"},
+					JsonPointers:          []string{"a", "b"},
+					ManagedFieldsManagers: []string{"a", "b"},
+				},
+			},
+		},
+	}
+
+	a := makeTestArgoCD(func(a *argoprojv1alpha1.ArgoCD) {
+		a.Spec.ResourceHealthChecks = health
+		a.Spec.ResourceActions = actions
+		a.Spec.ResourceIgnoreDifferences = &ignoreDifferences
+	})
+	r := makeTestReconciler(t, a)
+
+	err := r.reconcileArgoConfigMap(a)
+	assert.NoError(t, err)
+
+	cm := &corev1.ConfigMap{}
+	err = r.Client.Get(context.TODO(), types.NamespacedName{
+		Name:      common.ArgoCDConfigMapName,
+		Namespace: testNamespace,
+	}, cm)
+	assert.NoError(t, err)
+
+	desiredCM := make(map[string]string)
+	desiredCM["resource.customizations.health.healthFoo_healthFoo"] = "healthFoo"
+	desiredCM["resource.customizations.health.healthBar_healthBar"] = "healthBar"
+	desiredCM["resource.customizations.actions.actionsFoo_actionsFoo"] = "actionsFoo"
+	desiredCM["resource.customizations.actions.actionsBar_actionsBar"] = "actionsBar"
+	desiredCM["resource.customizations.ignoreDifferences.all"] = desiredIgnoreDifferenceCustomization
+	desiredCM["resource.customizations.ignoreDifferences.ignoreDiffBar_ignoreDiffBar"] = desiredIgnoreDifferenceCustomization
+
+	for k, v := range desiredCM {
+		if value, ok := cm.Data[k]; !ok || value != v {
+			t.Fatalf("reconcileArgoConfigMap failed got %q, want %q", value, desiredCM[k])
+		}
+	}
+}
+
+func TestReconcile_emitEventOnDeprecatedResourceCustomizations(t *testing.T) {
+	logf.SetLogger(ZapLogger(true))
+
+	DeprecationEventEmissionTracker = make(map[string]DeprecationEventEmissionStatus)
+
+	resourceCustomizationsEvent := &corev1.Event{
+		Reason:  "DeprecationNotice",
+		Message: "ResourceCustomizations is deprecated, please use the new formats `ResourceHealthChecks`, `ResourceIgnoreDifferences`, and `ResourceActions` instead.",
+		Action:  "Deprecated",
+	}
+
+	tests := []struct {
+		name       string
+		argoCD     *argoprojv1alpha1.ArgoCD
+		wantEvents []*corev1.Event
+	}{
+		{
+			name: "ResourceCustomizations used",
+			argoCD: makeTestArgoCD(func(ac *argoprojv1alpha1.ArgoCD) {
+				ac.Spec.ResourceCustomizations = "testing: testing"
+			}),
+			wantEvents: []*corev1.Event{resourceCustomizationsEvent},
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			r := makeFakeReconciler(t, test.argoCD)
+			err := r.reconcileArgoConfigMap(test.argoCD)
+			assert.NoError(t, err)
+			gotEventList := &corev1.EventList{}
+			err = r.Client.List(context.TODO(), gotEventList)
+			assert.NoError(t, err)
+			assert.Equal(t, len(test.wantEvents), len(gotEventList.Items))
+		})
+	}
+}
+
 func TestReconcileArgoCD_reconcileArgoConfigMap_withExtraConfig(t *testing.T) {
 	a := makeTestArgoCD()
 	r := makeTestReconciler(t, a)
diff --git a/tests/k8s/1-024_validate_resource_health_checks/01-argocd-with-resource-health-check.yaml b/tests/k8s/1-024_validate_resource_health_checks/01-argocd-with-resource-health-check.yaml
new file mode 100644
index 00000000..2e797c1e
--- /dev/null
+++ b/tests/k8s/1-024_validate_resource_health_checks/01-argocd-with-resource-health-check.yaml
@@ -0,0 +1,29 @@
+apiVersion: argoproj.io/v1alpha1
+kind: ArgoCD
+metadata:
+  name: example-argocd
+spec:
+  resourceHealthChecks:
+  - group: certmanager.k8s.io
+    kind: Certificate
+    check: |
+      hs = {}
+      if obj.status ~= nil then
+        if obj.status.conditions ~= nil then
+          for i, condition in ipairs(obj.status.conditions) do
+            if condition.type == "Ready" and condition.status == "False" then
+              hs.status = "Degraded"
+              hs.message = condition.message
+              return hs
+            end
+            if condition.type == "Ready" and condition.status == "True" then
+              hs.status = "Healthy"
+              hs.message = condition.message
+              return hs
+            end
+          end
+        end
+      end
+      hs.status = "Progressing"
+      hs.message = "Waiting for certificate"
+      return hs
\ No newline at end of file
diff --git a/tests/k8s/1-024_validate_resource_health_checks/01-assert.yaml b/tests/k8s/1-024_validate_resource_health_checks/01-assert.yaml
new file mode 100644
index 00000000..37edf42b
--- /dev/null
+++ b/tests/k8s/1-024_validate_resource_health_checks/01-assert.yaml
@@ -0,0 +1,37 @@
+apiVersion: kuttl.dev/v1beta1
+kind: TestAssert
+timeout: 120
+---
+apiVersion: argoproj.io/v1alpha1
+kind: ArgoCD
+metadata:
+  name: example-argocd
+status:
+  phase: Available
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: argocd-cm
+data:
+  resource.customizations.health.certmanager.k8s.io_Certificate: |
+    hs = {}
+    if obj.status ~= nil then
+      if obj.status.conditions ~= nil then
+        for i, condition in ipairs(obj.status.conditions) do
+          if condition.type == "Ready" and condition.status == "False" then
+            hs.status = "Degraded"
+            hs.message = condition.message
+            return hs
+          end
+          if condition.type == "Ready" and condition.status == "True" then
+            hs.status = "Healthy"
+            hs.message = condition.message
+            return hs
+          end
+        end
+      end
+    end
+    hs.status = "Progressing"
+    hs.message = "Waiting for certificate"
+    return hs
\ No newline at end of file
diff --git a/tests/k8s/1-025_validate_resource_ignore_differences/01-argocd-with-resource-ignore-difference.yaml b/tests/k8s/1-025_validate_resource_ignore_differences/01-argocd-with-resource-ignore-difference.yaml
new file mode 100644
index 00000000..f15ef2f7
--- /dev/null
+++ b/tests/k8s/1-025_validate_resource_ignore_differences/01-argocd-with-resource-ignore-difference.yaml
@@ -0,0 +1,41 @@
+apiVersion: argoproj.io/v1alpha1
+kind: ArgoCD
+metadata:
+  name: example-argocd
+spec:
+  resourceIgnoreDifferences:
+    all:
+      jqPathExpressions:
+          - xyz
+          - abc
+      jsonPointers:
+          - xyz
+          - abc
+      managedFieldsManagers:
+          - xyz
+          - abc
+    resourceIdentifiers:
+      - group: apps
+        kind: deployments
+        customization:
+          jqPathExpressions:
+            - xyz
+            - abc
+          jsonPointers:
+            - xyz
+            - abc
+          managedFieldManagers:
+            - xyz
+            - abc
+      - group: batch
+        kind: jobs
+        customization:
+          jqPathExpressions:
+            - xyz
+            - abc
+          jsonPointers:
+            - xyz
+            - abc
+          managedFieldsManagers:
+            - xyz
+            - abc
\ No newline at end of file
diff --git a/tests/k8s/1-025_validate_resource_ignore_differences/01-assert.yaml b/tests/k8s/1-025_validate_resource_ignore_differences/01-assert.yaml
new file mode 100644
index 00000000..1eedf003
--- /dev/null
+++ b/tests/k8s/1-025_validate_resource_ignore_differences/01-assert.yaml
@@ -0,0 +1,44 @@
+apiVersion: kuttl.dev/v1beta1
+kind: TestAssert
+timeout: 120
+---
+apiVersion: argoproj.io/v1alpha1
+kind: ArgoCD
+metadata:
+  name: example-argocd
+status:
+  phase: Available
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: argocd-cm
+data:
+  resource.customizations.ignoreDifferences.all: |
+    jqpathexpressions:
+    - xyz
+    - abc
+    jsonpointers:
+    - xyz
+    - abc
+    managedfieldsmanagers:
+    - xyz
+    - abc
+  resource.customizations.ignoreDifferences.apps_deployments: |
+    jqpathexpressions:
+    - xyz
+    - abc
+    jsonpointers:
+    - xyz
+    - abc
+    managedfieldsmanagers: []
+  resource.customizations.ignoreDifferences.batch_jobs: |
+    jqpathexpressions:
+    - xyz
+    - abc
+    jsonpointers:
+    - xyz
+    - abc
+    managedfieldsmanagers:
+    - xyz
+    - abc
\ No newline at end of file
diff --git a/tests/k8s/1-026_validate_resource_action/01-argocd-with-resource-action.yaml b/tests/k8s/1-026_validate_resource_action/01-argocd-with-resource-action.yaml
new file mode 100644
index 00000000..9e9ea49f
--- /dev/null
+++ b/tests/k8s/1-026_validate_resource_action/01-argocd-with-resource-action.yaml
@@ -0,0 +1,26 @@
+apiVersion: argoproj.io/v1alpha1
+kind: ArgoCD
+metadata:
+  name: example-argocd
+spec:
+  resourceActions:
+  - group: apps
+    kind: Deployment
+    action: |
+      discovery.lua: |
+        actions = {}
+        actions["restart"] = {}
+        return actions
+      definitions:
+        - name: restart
+          # Lua Script to modify the obj
+          action.lua: |
+            local os = require("os")
+            if obj.spec.template.metadata == nil then
+                obj.spec.template.metadata = {}
+            end
+            if obj.spec.template.metadata.annotations == nil then
+                obj.spec.template.metadata.annotations = {}
+            end
+            obj.spec.template.metadata.annotations["kubectl.kubernetes.io/restartedAt"] = os.date("!%Y-%m-%dT%XZ")
+            return obj
\ No newline at end of file
diff --git a/tests/k8s/1-026_validate_resource_action/01-assert.yaml b/tests/k8s/1-026_validate_resource_action/01-assert.yaml
new file mode 100644
index 00000000..fd54b866
--- /dev/null
+++ b/tests/k8s/1-026_validate_resource_action/01-assert.yaml
@@ -0,0 +1,34 @@
+apiVersion: kuttl.dev/v1beta1
+kind: TestAssert
+timeout: 120
+---
+apiVersion: argoproj.io/v1alpha1
+kind: ArgoCD
+metadata:
+  name: example-argocd
+status:
+  phase: Available
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: argocd-cm
+data:
+  resource.customizations.actions.apps_Deployment: |
+    discovery.lua: |
+      actions = {}
+      actions["restart"] = {}
+      return actions
+    definitions:
+      - name: restart
+        # Lua Script to modify the obj
+        action.lua: |
+          local os = require("os")
+          if obj.spec.template.metadata == nil then
+              obj.spec.template.metadata = {}
+          end
+          if obj.spec.template.metadata.annotations == nil then
+              obj.spec.template.metadata.annotations = {}
+          end
+          obj.spec.template.metadata.annotations["kubectl.kubernetes.io/restartedAt"] = os.date("!%Y-%m-%dT%XZ")
+          return obj
\ No newline at end of file