diff --git a/cmd/flux/resume_alert.go b/cmd/flux/resume_alert.go index 713aebb3..7ed29221 100644 --- a/cmd/flux/resume_alert.go +++ b/cmd/flux/resume_alert.go @@ -49,6 +49,9 @@ func (obj alertAdapter) getObservedGeneration() int64 { func (obj alertAdapter) setUnsuspended() { obj.Alert.Spec.Suspend = false + if _, ok := obj.Alert.Annotations[SuspendReasonAnnotation]; ok { + delete(obj.Alert.Annotations, SuspendReasonAnnotation) + } } func (obj alertAdapter) successMessage() string { diff --git a/cmd/flux/resume_helmrelease.go b/cmd/flux/resume_helmrelease.go index b058d273..6acbd2b3 100644 --- a/cmd/flux/resume_helmrelease.go +++ b/cmd/flux/resume_helmrelease.go @@ -52,6 +52,9 @@ func (obj helmReleaseAdapter) getObservedGeneration() int64 { func (obj helmReleaseAdapter) setUnsuspended() { obj.HelmRelease.Spec.Suspend = false + if _, ok := obj.HelmRelease.Annotations[SuspendReasonAnnotation]; ok { + delete(obj.HelmRelease.Annotations, SuspendReasonAnnotation) + } } func (obj helmReleaseAdapter) successMessage() string { diff --git a/cmd/flux/resume_image_repository.go b/cmd/flux/resume_image_repository.go index a9ab36cd..b1e49364 100644 --- a/cmd/flux/resume_image_repository.go +++ b/cmd/flux/resume_image_repository.go @@ -48,6 +48,9 @@ func (obj imageRepositoryAdapter) getObservedGeneration() int64 { func (obj imageRepositoryAdapter) setUnsuspended() { obj.ImageRepository.Spec.Suspend = false + if _, ok := obj.ImageRepository.Annotations[SuspendReasonAnnotation]; ok { + delete(obj.ImageRepository.Annotations, SuspendReasonAnnotation) + } } func (a imageRepositoryListAdapter) resumeItem(i int) resumable { diff --git a/cmd/flux/resume_image_updateauto.go b/cmd/flux/resume_image_updateauto.go index d50fddf7..d0131c98 100644 --- a/cmd/flux/resume_image_updateauto.go +++ b/cmd/flux/resume_image_updateauto.go @@ -44,6 +44,9 @@ func init() { func (obj imageUpdateAutomationAdapter) setUnsuspended() { obj.ImageUpdateAutomation.Spec.Suspend = false + if _, ok := obj.ImageUpdateAutomation.Annotations[SuspendReasonAnnotation]; ok { + delete(obj.ImageUpdateAutomation.Annotations, SuspendReasonAnnotation) + } } func (obj imageUpdateAutomationAdapter) getObservedGeneration() int64 { diff --git a/cmd/flux/resume_kustomization.go b/cmd/flux/resume_kustomization.go index a03aed62..ab8ed7dc 100644 --- a/cmd/flux/resume_kustomization.go +++ b/cmd/flux/resume_kustomization.go @@ -52,6 +52,9 @@ func (obj kustomizationAdapter) getObservedGeneration() int64 { func (obj kustomizationAdapter) setUnsuspended() { obj.Kustomization.Spec.Suspend = false + if _, ok := obj.Kustomization.Annotations[SuspendReasonAnnotation]; ok { + delete(obj.Kustomization.Annotations, SuspendReasonAnnotation) + } } func (obj kustomizationAdapter) successMessage() string { diff --git a/cmd/flux/resume_receiver.go b/cmd/flux/resume_receiver.go index c99bd755..1659c6bf 100644 --- a/cmd/flux/resume_receiver.go +++ b/cmd/flux/resume_receiver.go @@ -49,6 +49,9 @@ func (obj receiverAdapter) getObservedGeneration() int64 { func (obj receiverAdapter) setUnsuspended() { obj.Receiver.Spec.Suspend = false + if _, ok := obj.Receiver.Annotations[SuspendReasonAnnotation]; ok { + delete(obj.Receiver.Annotations, SuspendReasonAnnotation) + } } func (obj receiverAdapter) successMessage() string { diff --git a/cmd/flux/resume_source_bucket.go b/cmd/flux/resume_source_bucket.go index ea1fe37d..de0ec2b6 100644 --- a/cmd/flux/resume_source_bucket.go +++ b/cmd/flux/resume_source_bucket.go @@ -48,6 +48,9 @@ func (obj bucketAdapter) getObservedGeneration() int64 { func (obj bucketAdapter) setUnsuspended() { obj.Bucket.Spec.Suspend = false + if _, ok := obj.Bucket.Annotations[SuspendReasonAnnotation]; ok { + delete(obj.Bucket.Annotations, SuspendReasonAnnotation) + } } func (a bucketListAdapter) resumeItem(i int) resumable { diff --git a/cmd/flux/resume_source_chart.go b/cmd/flux/resume_source_chart.go index 6322f06f..beb3ed97 100644 --- a/cmd/flux/resume_source_chart.go +++ b/cmd/flux/resume_source_chart.go @@ -50,6 +50,9 @@ func (obj helmChartAdapter) getObservedGeneration() int64 { func (obj helmChartAdapter) setUnsuspended() { obj.HelmChart.Spec.Suspend = false + if _, ok := obj.HelmChart.Annotations[SuspendReasonAnnotation]; ok { + delete(obj.HelmChart.Annotations, SuspendReasonAnnotation) + } } func (obj helmChartAdapter) successMessage() string { diff --git a/cmd/flux/resume_source_git.go b/cmd/flux/resume_source_git.go index 751714a4..23289870 100644 --- a/cmd/flux/resume_source_git.go +++ b/cmd/flux/resume_source_git.go @@ -48,6 +48,9 @@ func (obj gitRepositoryAdapter) getObservedGeneration() int64 { func (obj gitRepositoryAdapter) setUnsuspended() { obj.GitRepository.Spec.Suspend = false + if _, ok := obj.GitRepository.Annotations[SuspendReasonAnnotation]; ok { + delete(obj.GitRepository.Annotations, SuspendReasonAnnotation) + } } func (a gitRepositoryListAdapter) resumeItem(i int) resumable { diff --git a/cmd/flux/resume_source_helm.go b/cmd/flux/resume_source_helm.go index 0ac641eb..54531cb8 100644 --- a/cmd/flux/resume_source_helm.go +++ b/cmd/flux/resume_source_helm.go @@ -48,6 +48,9 @@ func (obj helmRepositoryAdapter) getObservedGeneration() int64 { func (obj helmRepositoryAdapter) setUnsuspended() { obj.HelmRepository.Spec.Suspend = false + if _, ok := obj.HelmRepository.Annotations[SuspendReasonAnnotation]; ok { + delete(obj.HelmRepository.Annotations, SuspendReasonAnnotation) + } } func (a helmRepositoryListAdapter) resumeItem(i int) resumable { diff --git a/cmd/flux/resume_source_oci.go b/cmd/flux/resume_source_oci.go index 04b20a4b..db40ec05 100644 --- a/cmd/flux/resume_source_oci.go +++ b/cmd/flux/resume_source_oci.go @@ -48,6 +48,9 @@ func (obj ociRepositoryAdapter) getObservedGeneration() int64 { func (obj ociRepositoryAdapter) setUnsuspended() { obj.OCIRepository.Spec.Suspend = false + if _, ok := obj.OCIRepository.Annotations[SuspendReasonAnnotation]; ok { + delete(obj.OCIRepository.Annotations, SuspendReasonAnnotation) + } } func (a ociRepositoryListAdapter) resumeItem(i int) resumable { diff --git a/cmd/flux/suspend.go b/cmd/flux/suspend.go index e0023c7e..2ac84f94 100644 --- a/cmd/flux/suspend.go +++ b/cmd/flux/suspend.go @@ -34,7 +34,8 @@ var suspendCmd = &cobra.Command{ } type SuspendFlags struct { - all bool + all bool + reason string } var suspendArgs SuspendFlags @@ -42,6 +43,8 @@ var suspendArgs SuspendFlags func init() { suspendCmd.PersistentFlags().BoolVarP(&suspendArgs.all, "all", "", false, "suspend all resources in that namespace") + suspendCmd.PersistentFlags().StringVarP(&suspendArgs.reason, "reason", "r", "suspended", + "set a reason for why the resource is suspended") rootCmd.AddCommand(suspendCmd) } @@ -49,7 +52,7 @@ type suspendable interface { adapter copyable isSuspended() bool - setSuspended() + setSuspended(reason string) } type suspendCommand struct { @@ -76,6 +79,7 @@ func (suspend suspendCommand) run(cmd *cobra.Command, args []string) error { return err } + // in case of all, get all in namespace and patch 'em if len(args) < 1 && suspendArgs.all { listOpts := []client.ListOption{ client.InNamespace(*kubeconfigArgs.Namespace), @@ -88,6 +92,7 @@ func (suspend suspendCommand) run(cmd *cobra.Command, args []string) error { return nil } + // when not all, patch list of args processed := make(map[string]struct{}, len(args)) for _, arg := range args { if _, has := processed[arg]; has { @@ -130,7 +135,7 @@ func (suspend suspendCommand) patch(ctx context.Context, kubeClient client.WithW obj := suspend.list.item(i) patch := client.MergeFrom(obj.deepCopyClientObject()) - obj.setSuspended() + obj.setSuspended(suspendArgs.reason) if err := kubeClient.Patch(ctx, obj.asClientObject(), patch); err != nil { return err } @@ -140,3 +145,6 @@ func (suspend suspendCommand) patch(ctx context.Context, kubeClient client.WithW return nil } + +// SuspendReasonAnnotation is the metadata key used to store the reason for resource suspension +const SuspendReasonAnnotation string = "suspend.fluxcd.io/reason" diff --git a/cmd/flux/suspend_alert.go b/cmd/flux/suspend_alert.go index 17cdd801..87262765 100644 --- a/cmd/flux/suspend_alert.go +++ b/cmd/flux/suspend_alert.go @@ -47,8 +47,9 @@ func (obj alertAdapter) isSuspended() bool { return obj.Alert.Spec.Suspend } -func (obj alertAdapter) setSuspended() { +func (obj alertAdapter) setSuspended(reason string) { obj.Alert.Spec.Suspend = true + obj.Alert.Annotations[SuspendReasonAnnotation] = reason } func (a alertListAdapter) item(i int) suspendable { diff --git a/cmd/flux/suspend_helmrelease.go b/cmd/flux/suspend_helmrelease.go index 5872c8b4..88d78742 100644 --- a/cmd/flux/suspend_helmrelease.go +++ b/cmd/flux/suspend_helmrelease.go @@ -48,8 +48,9 @@ func (obj helmReleaseAdapter) isSuspended() bool { return obj.HelmRelease.Spec.Suspend } -func (obj helmReleaseAdapter) setSuspended() { +func (obj helmReleaseAdapter) setSuspended(reason string) { obj.HelmRelease.Spec.Suspend = true + obj.HelmRelease.Annotations[SuspendReasonAnnotation] = reason } func (a helmReleaseListAdapter) item(i int) suspendable { diff --git a/cmd/flux/suspend_image_repository.go b/cmd/flux/suspend_image_repository.go index c6e562d1..3b9f901c 100644 --- a/cmd/flux/suspend_image_repository.go +++ b/cmd/flux/suspend_image_repository.go @@ -47,8 +47,9 @@ func (obj imageRepositoryAdapter) isSuspended() bool { return obj.ImageRepository.Spec.Suspend } -func (obj imageRepositoryAdapter) setSuspended() { +func (obj imageRepositoryAdapter) setSuspended(reason string) { obj.ImageRepository.Spec.Suspend = true + obj.ImageRepository.Annotations[SuspendReasonAnnotation] = reason } func (a imageRepositoryListAdapter) item(i int) suspendable { diff --git a/cmd/flux/suspend_image_updateauto.go b/cmd/flux/suspend_image_updateauto.go index 1c8f11ef..5649fa4e 100644 --- a/cmd/flux/suspend_image_updateauto.go +++ b/cmd/flux/suspend_image_updateauto.go @@ -47,8 +47,9 @@ func (update imageUpdateAutomationAdapter) isSuspended() bool { return update.ImageUpdateAutomation.Spec.Suspend } -func (update imageUpdateAutomationAdapter) setSuspended() { +func (update imageUpdateAutomationAdapter) setSuspended(reason string) { update.ImageUpdateAutomation.Spec.Suspend = true + update.ImageUpdateAutomation.Annotations[SuspendReasonAnnotation] = reason } func (a imageUpdateAutomationListAdapter) item(i int) suspendable { diff --git a/cmd/flux/suspend_kustomization.go b/cmd/flux/suspend_kustomization.go index ac6c72e1..7689c904 100644 --- a/cmd/flux/suspend_kustomization.go +++ b/cmd/flux/suspend_kustomization.go @@ -48,8 +48,9 @@ func (obj kustomizationAdapter) isSuspended() bool { return obj.Kustomization.Spec.Suspend } -func (obj kustomizationAdapter) setSuspended() { +func (obj kustomizationAdapter) setSuspended(reason string) { obj.Kustomization.Spec.Suspend = true + obj.Kustomization.Annotations[SuspendReasonAnnotation] = reason } func (a kustomizationListAdapter) item(i int) suspendable { diff --git a/cmd/flux/suspend_receiver.go b/cmd/flux/suspend_receiver.go index 7f2e6dd7..b512238b 100644 --- a/cmd/flux/suspend_receiver.go +++ b/cmd/flux/suspend_receiver.go @@ -47,8 +47,9 @@ func (obj receiverAdapter) isSuspended() bool { return obj.Receiver.Spec.Suspend } -func (obj receiverAdapter) setSuspended() { +func (obj receiverAdapter) setSuspended(reason string) { obj.Receiver.Spec.Suspend = true + obj.Receiver.Annotations[SuspendReasonAnnotation] = reason } func (a receiverListAdapter) item(i int) suspendable { diff --git a/cmd/flux/suspend_source_bucket.go b/cmd/flux/suspend_source_bucket.go index 7fdcfced..1a625f3f 100644 --- a/cmd/flux/suspend_source_bucket.go +++ b/cmd/flux/suspend_source_bucket.go @@ -47,8 +47,9 @@ func (obj bucketAdapter) isSuspended() bool { return obj.Bucket.Spec.Suspend } -func (obj bucketAdapter) setSuspended() { +func (obj bucketAdapter) setSuspended(reason string) { obj.Bucket.Spec.Suspend = true + obj.Bucket.Annotations[SuspendReasonAnnotation] = reason } func (a bucketListAdapter) item(i int) suspendable { diff --git a/cmd/flux/suspend_source_chart.go b/cmd/flux/suspend_source_chart.go index e91327e8..aeccf034 100644 --- a/cmd/flux/suspend_source_chart.go +++ b/cmd/flux/suspend_source_chart.go @@ -47,8 +47,9 @@ func (obj helmChartAdapter) isSuspended() bool { return obj.HelmChart.Spec.Suspend } -func (obj helmChartAdapter) setSuspended() { +func (obj helmChartAdapter) setSuspended(reason string) { obj.HelmChart.Spec.Suspend = true + obj.HelmChart.Annotations[SuspendReasonAnnotation] = reason } func (a helmChartListAdapter) item(i int) suspendable { diff --git a/cmd/flux/suspend_source_git.go b/cmd/flux/suspend_source_git.go index 4decf796..a40cdb05 100644 --- a/cmd/flux/suspend_source_git.go +++ b/cmd/flux/suspend_source_git.go @@ -47,8 +47,9 @@ func (obj gitRepositoryAdapter) isSuspended() bool { return obj.GitRepository.Spec.Suspend } -func (obj gitRepositoryAdapter) setSuspended() { +func (obj gitRepositoryAdapter) setSuspended(reason string) { obj.GitRepository.Spec.Suspend = true + obj.GitRepository.Annotations[SuspendReasonAnnotation] = reason } func (a gitRepositoryListAdapter) item(i int) suspendable { diff --git a/cmd/flux/suspend_source_helm.go b/cmd/flux/suspend_source_helm.go index 22598c64..6b7a7669 100644 --- a/cmd/flux/suspend_source_helm.go +++ b/cmd/flux/suspend_source_helm.go @@ -47,8 +47,9 @@ func (obj helmRepositoryAdapter) isSuspended() bool { return obj.HelmRepository.Spec.Suspend } -func (obj helmRepositoryAdapter) setSuspended() { +func (obj helmRepositoryAdapter) setSuspended(reason string) { obj.HelmRepository.Spec.Suspend = true + obj.HelmRepository.Annotations[SuspendReasonAnnotation] = reason } func (a helmRepositoryListAdapter) item(i int) suspendable { diff --git a/cmd/flux/suspend_source_oci.go b/cmd/flux/suspend_source_oci.go index 3b8e36d6..e756b06f 100644 --- a/cmd/flux/suspend_source_oci.go +++ b/cmd/flux/suspend_source_oci.go @@ -47,8 +47,9 @@ func (obj ociRepositoryAdapter) isSuspended() bool { return obj.OCIRepository.Spec.Suspend } -func (obj ociRepositoryAdapter) setSuspended() { +func (obj ociRepositoryAdapter) setSuspended(reason string) { obj.OCIRepository.Spec.Suspend = true + obj.OCIRepository.Annotations[SuspendReasonAnnotation] = reason } func (a ociRepositoryListAdapter) item(i int) suspendable {