diff --git a/apis/applications/v1alpha1/types.go b/apis/applications/v1alpha1/types.go index d4b5ea0..e0fd47c 100644 --- a/apis/applications/v1alpha1/types.go +++ b/apis/applications/v1alpha1/types.go @@ -51,6 +51,9 @@ type ApplicationParameters struct { // Annotations that will be applied to the ArgoCD Application Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,12,opt,name=annotations"` + + // Finalizers added to the ArgoCD Application + Finalizers []string `json:"finalizers,omitempty" protobuf:"bytes,13,opt,name=finalizers"` } // ResourceIgnoreDifferences contains resource filter and list of json paths which should be ignored during comparison with live state. diff --git a/apis/applications/v1alpha1/zz_generated.deepcopy.go b/apis/applications/v1alpha1/zz_generated.deepcopy.go index 0acc5a8..1adc613 100644 --- a/apis/applications/v1alpha1/zz_generated.deepcopy.go +++ b/apis/applications/v1alpha1/zz_generated.deepcopy.go @@ -198,6 +198,11 @@ func (in *ApplicationParameters) DeepCopyInto(out *ApplicationParameters) { (*out)[key] = val } } + if in.Finalizers != nil { + in, out := &in.Finalizers, &out.Finalizers + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationParameters. diff --git a/examples/application/application-with-finalizers.yaml b/examples/application/application-with-finalizers.yaml new file mode 100644 index 0000000..293ac50 --- /dev/null +++ b/examples/application/application-with-finalizers.yaml @@ -0,0 +1,23 @@ +--- +# Example using finalizers +apiVersion: applications.argocd.crossplane.io/v1alpha1 +kind: Application +metadata: + name: example-application-finalizers +spec: + providerConfigRef: + name: argocd-provider + forProvider: + finalizers: + - resources-finalizer.argocd.argoproj.io + destination: + namespace: default + server: https://kubernetes.default.svc + project: default + source: + repoURL: https://github.com/bonilla-cesar/argocd + path: resources/cm + targetRevision: HEAD + + + diff --git a/package/crds/applications.argocd.crossplane.io_applications.yaml b/package/crds/applications.argocd.crossplane.io_applications.yaml index 8a8b6b7..557da89 100644 --- a/package/crds/applications.argocd.crossplane.io_applications.yaml +++ b/package/crds/applications.argocd.crossplane.io_applications.yaml @@ -248,6 +248,11 @@ spec: type: object type: object type: object + finalizers: + description: Finalizers added to the ArgoCD Application + items: + type: string + type: array ignoreDifferences: description: IgnoreDifferences is a list of resources and their fields which should be ignored during comparison diff --git a/pkg/controller/applications/comp.go b/pkg/controller/applications/comp.go index adec412..72d2315 100644 --- a/pkg/controller/applications/comp.go +++ b/pkg/controller/applications/comp.go @@ -1,6 +1,9 @@ package applications import ( + "maps" + "slices" + argocdv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" @@ -19,5 +22,10 @@ func IsApplicationUpToDate(cr *v1alpha1.ApplicationParameters, remote *argocdv1a // the unexported fields should not bother here, since we don't copy them or write them cmpopts.IgnoreUnexported(argocdv1alpha1.ApplicationDestination{}), } - return cmp.Equal(*cluster, remote.Spec, opts...) && cmp.Equal(cr.Annotations, remote.Annotations, opts...) + + // Sort finalizer slices for comparison + slices.Sort(cr.Finalizers) + slices.Sort(remote.Finalizers) + + return cmp.Equal(*cluster, remote.Spec, opts...) && maps.Equal(cr.Annotations, remote.Annotations) && slices.Equal(cr.Finalizers, remote.Finalizers) } diff --git a/pkg/controller/applications/controller.go b/pkg/controller/applications/controller.go index 54ad662..08cc7b2 100644 --- a/pkg/controller/applications/controller.go +++ b/pkg/controller/applications/controller.go @@ -217,6 +217,7 @@ func generateCreateApplicationRequest(cr *v1alpha1.Application) *application.App ObjectMeta: metav1.ObjectMeta{ Name: meta.GetExternalName(cr), Annotations: cr.Spec.ForProvider.Annotations, + Finalizers: cr.Spec.ForProvider.Finalizers, }, Spec: *spec, } @@ -238,6 +239,7 @@ func generateUpdateRepositoryOptions(cr *v1alpha1.Application) *application.Appl ObjectMeta: metav1.ObjectMeta{ Name: meta.GetExternalName(cr), Annotations: cr.Spec.ForProvider.Annotations, + Finalizers: cr.Spec.ForProvider.Finalizers, }, Spec: *spec, } diff --git a/pkg/controller/applications/controller_test.go b/pkg/controller/applications/controller_test.go index 670e773..42a633b 100644 --- a/pkg/controller/applications/controller_test.go +++ b/pkg/controller/applications/controller_test.go @@ -47,7 +47,8 @@ var ( chartPath = "charts/podinfo" revision = "HEAD" selfHealEnabled = true - testApplicationAnnotations = map[string]string{"annotation1": "value1"} + testApplicationAnnotations = map[string]string{"annotation1": "value1", "annotation2": "value2"} + testApplicationFinalizers = []string{"resources-finalizer.argocd.argoproj.io"} ) type args struct { @@ -126,6 +127,7 @@ func TestObserve(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: testApplicationExternalName, Annotations: testApplicationAnnotations, + Finalizers: testApplicationFinalizers, }, Spec: argocdv1alpha1.ApplicationSpec{ Project: testProjectName, @@ -165,6 +167,7 @@ func TestObserve(t *testing.T) { }, }, Annotations: testApplicationAnnotations, + Finalizers: testApplicationFinalizers, }), ), }, @@ -187,6 +190,7 @@ func TestObserve(t *testing.T) { }, }, Annotations: testApplicationAnnotations, + Finalizers: testApplicationFinalizers, }), withConditions(xpv1.Available()), withObservation(initializedArgoAppStatus()), @@ -216,6 +220,7 @@ func TestObserve(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: testApplicationExternalName, Annotations: testApplicationAnnotations, + Finalizers: testApplicationFinalizers, }, Spec: argocdv1alpha1.ApplicationSpec{ Project: testProjectName, @@ -250,6 +255,7 @@ func TestObserve(t *testing.T) { }, }, Annotations: testApplicationAnnotations, + Finalizers: testApplicationFinalizers, }), ), }, @@ -272,6 +278,7 @@ func TestObserve(t *testing.T) { }, }, Annotations: testApplicationAnnotations, + Finalizers: testApplicationFinalizers, }), withConditions(xpv1.Available()), withObservation(initializedArgoAppStatus()), @@ -505,6 +512,7 @@ func TestUpdate(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: testApplicationExternalName, Annotations: testApplicationAnnotations, + Finalizers: testApplicationFinalizers, }, Spec: argocdv1alpha1.ApplicationSpec{ Project: testProjectName, @@ -518,6 +526,7 @@ func TestUpdate(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: testApplicationExternalName, Annotations: testApplicationAnnotations, + Finalizers: testApplicationFinalizers, }, }, nil) }), @@ -529,6 +538,7 @@ func TestUpdate(t *testing.T) { Namespace: &testDestinationNamespace, }, Annotations: testApplicationAnnotations, + Finalizers: testApplicationFinalizers, }), withExternalName(testApplicationExternalName), ), @@ -542,6 +552,7 @@ func TestUpdate(t *testing.T) { Namespace: &testDestinationNamespace, }, Annotations: testApplicationAnnotations, + Finalizers: testApplicationFinalizers, }), withExternalName(testApplicationExternalName), ),