diff --git a/cmd/flux/alert.go b/cmd/flux/alert.go index 1ccb94f5..ea8012b9 100644 --- a/cmd/flux/alert.go +++ b/cmd/flux/alert.go @@ -37,6 +37,10 @@ func (a alertAdapter) asClientObject() client.Object { return a.Alert } +func (a alertAdapter) deepCopyClientObject() client.Object { + return a.Alert.DeepCopy() +} + // notificationv1.Alert type alertListAdapter struct { diff --git a/cmd/flux/alert_provider.go b/cmd/flux/alert_provider.go index 07963b05..fb7cb063 100644 --- a/cmd/flux/alert_provider.go +++ b/cmd/flux/alert_provider.go @@ -37,6 +37,10 @@ func (a alertProviderAdapter) asClientObject() client.Object { return a.Provider } +func (a alertProviderAdapter) deepCopyClientObject() client.Object { + return a.Provider.DeepCopy() +} + // notificationv1.Provider type alertProviderListAdapter struct { diff --git a/cmd/flux/helmrelease.go b/cmd/flux/helmrelease.go index 91a30d22..c4ae564a 100644 --- a/cmd/flux/helmrelease.go +++ b/cmd/flux/helmrelease.go @@ -37,6 +37,10 @@ func (h helmReleaseAdapter) asClientObject() client.Object { return h.HelmRelease } +func (h helmReleaseAdapter) deepCopyClientObject() client.Object { + return h.HelmRelease.DeepCopy() +} + // helmv2.HelmReleaseList type helmReleaseListAdapter struct { diff --git a/cmd/flux/image.go b/cmd/flux/image.go index 4727e4b2..b54aa25d 100644 --- a/cmd/flux/image.go +++ b/cmd/flux/image.go @@ -42,6 +42,10 @@ func (a imageRepositoryAdapter) asClientObject() client.Object { return a.ImageRepository } +func (a imageRepositoryAdapter) deepCopyClientObject() client.Object { + return a.ImageRepository.DeepCopy() +} + // imagev1.ImageRepositoryList type imageRepositoryListAdapter struct { @@ -100,6 +104,10 @@ func (a imageUpdateAutomationAdapter) asClientObject() client.Object { return a.ImageUpdateAutomation } +func (a imageUpdateAutomationAdapter) deepCopyClientObject() client.Object { + return a.ImageUpdateAutomation.DeepCopy() +} + // autov1.ImageUpdateAutomationList type imageUpdateAutomationListAdapter struct { diff --git a/cmd/flux/kustomization.go b/cmd/flux/kustomization.go index 35976108..304d8065 100644 --- a/cmd/flux/kustomization.go +++ b/cmd/flux/kustomization.go @@ -37,6 +37,10 @@ func (a kustomizationAdapter) asClientObject() client.Object { return a.Kustomization } +func (a kustomizationAdapter) deepCopyClientObject() client.Object { + return a.Kustomization.DeepCopy() +} + // kustomizev1.KustomizationList type kustomizationListAdapter struct { diff --git a/cmd/flux/object.go b/cmd/flux/object.go index 75a20298..0c68fcba 100644 --- a/cmd/flux/object.go +++ b/cmd/flux/object.go @@ -39,6 +39,13 @@ type adapter interface { asClientObject() client.Object } +// copyable is an interface for a wrapper or alias from which we can +// get a deep copied client.Object, required when you e.g. want to +// calculate a patch. +type copyable interface { + deepCopyClientObject() client.Object +} + // listAdapater is the analogue to adapter, but for lists; the // controller runtime distinguishes between methods dealing with // objects and lists. diff --git a/cmd/flux/receiver.go b/cmd/flux/receiver.go index 1662e558..9266e99a 100644 --- a/cmd/flux/receiver.go +++ b/cmd/flux/receiver.go @@ -37,6 +37,10 @@ func (a receiverAdapter) asClientObject() client.Object { return a.Receiver } +func (a receiverAdapter) deepCopyClientObject() client.Object { + return a.Receiver.DeepCopy() +} + // notificationv1.Receiver type receiverListAdapter struct { diff --git a/cmd/flux/reconcile.go b/cmd/flux/reconcile.go index 8b5280af..eece61be 100644 --- a/cmd/flux/reconcile.go +++ b/cmd/flux/reconcile.go @@ -52,6 +52,7 @@ type reconcileCommand struct { type reconcilable interface { adapter // to be able to load from the cluster + copyable // to be able to calculate patches suspendable // to tell if it's suspended // these are implemented by anything embedding metav1.ObjectMeta @@ -142,6 +143,7 @@ func requestReconciliation(ctx context.Context, kubeClient client.Client, if err := kubeClient.Get(ctx, namespacedName, obj.asClientObject()); err != nil { return err } + patch := client.MergeFrom(obj.deepCopyClientObject()) if ann := obj.GetAnnotations(); ann == nil { obj.SetAnnotations(map[string]string{ meta.ReconcileRequestAnnotation: time.Now().Format(time.RFC3339Nano), @@ -150,7 +152,7 @@ func requestReconciliation(ctx context.Context, kubeClient client.Client, ann[meta.ReconcileRequestAnnotation] = time.Now().Format(time.RFC3339Nano) obj.SetAnnotations(ann) } - return kubeClient.Update(ctx, obj.asClientObject()) + return kubeClient.Patch(ctx, obj.asClientObject(), patch) }) } diff --git a/cmd/flux/source.go b/cmd/flux/source.go index 2cf0477f..29dce7d5 100644 --- a/cmd/flux/source.go +++ b/cmd/flux/source.go @@ -41,6 +41,10 @@ func (a bucketAdapter) asClientObject() client.Object { return a.Bucket } +func (a bucketAdapter) deepCopyClientObject() client.Object { + return a.Bucket.DeepCopy() +} + // sourcev1.BucketList type bucketListAdapter struct { @@ -70,6 +74,10 @@ func (a helmChartAdapter) asClientObject() client.Object { return a.HelmChart } +func (a helmChartAdapter) deepCopyClientObject() client.Object { + return a.HelmChart.DeepCopy() +} + // sourcev1.HelmChartList type helmChartListAdapter struct { @@ -99,6 +107,10 @@ func (a gitRepositoryAdapter) asClientObject() client.Object { return a.GitRepository } +func (a gitRepositoryAdapter) deepCopyClientObject() client.Object { + return a.GitRepository.DeepCopy() +} + // sourcev1.GitRepositoryList type gitRepositoryListAdapter struct { @@ -128,6 +140,10 @@ func (a helmRepositoryAdapter) asClientObject() client.Object { return a.HelmRepository } +func (a helmRepositoryAdapter) deepCopyClientObject() client.Object { + return a.HelmRepository.DeepCopy() +} + // sourcev1.HelmRepositoryList type helmRepositoryListAdapter struct {