From f216273008c46084c317bc5221cbe06f15cc468d Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Wed, 30 Sep 2020 22:17:12 +0200 Subject: [PATCH 1/2] Make use of `GetCondition` from `pkg/apis/meta` --- cmd/gotk/create_helmrelease.go | 13 ++++++------- cmd/gotk/create_kustomization.go | 13 ++++++------- cmd/gotk/create_source_git.go | 13 ++++++------- cmd/gotk/get_helmrelease.go | 23 ++++++++++------------- cmd/gotk/get_kustomization.go | 23 ++++++++++------------- cmd/gotk/get_source_bucket.go | 22 +++++++++++++--------- cmd/gotk/get_source_git.go | 22 +++++++++++++--------- cmd/gotk/get_source_helm.go | 22 +++++++++++++--------- cmd/gotk/reconcile_helmrelease.go | 13 ++++++------- cmd/gotk/reconcile_source_bucket.go | 13 ++++++------- cmd/gotk/reconcile_source_helm.go | 13 ++++++------- cmd/gotk/resume_helmrelease.go | 18 ++++++++---------- cmd/gotk/resume_kustomization.go | 18 ++++++++---------- 13 files changed, 111 insertions(+), 115 deletions(-) diff --git a/cmd/gotk/create_helmrelease.go b/cmd/gotk/create_helmrelease.go index 81d6a834..64c343f4 100644 --- a/cmd/gotk/create_helmrelease.go +++ b/cmd/gotk/create_helmrelease.go @@ -275,13 +275,12 @@ func isHelmChartReady(ctx context.Context, kubeClient client.Client, name, names return false, err } - for _, condition := range helmChart.Status.Conditions { - if condition.Type == meta.ReadyCondition { - if condition.Status == corev1.ConditionTrue { - return true, nil - } else if condition.Status == corev1.ConditionFalse { - return false, fmt.Errorf(condition.Message) - } + if c := meta.GetCondition(helmChart.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionTrue: + return true, nil + case corev1.ConditionFalse: + return false, fmt.Errorf(c.Message) } } return false, nil diff --git a/cmd/gotk/create_kustomization.go b/cmd/gotk/create_kustomization.go index da575c54..d3b6e390 100644 --- a/cmd/gotk/create_kustomization.go +++ b/cmd/gotk/create_kustomization.go @@ -306,13 +306,12 @@ func isKustomizationReady(ctx context.Context, kubeClient client.Client, name, n return false, err } - for _, condition := range kustomization.Status.Conditions { - if condition.Type == meta.ReadyCondition { - if condition.Status == corev1.ConditionTrue { - return true, nil - } else if condition.Status == corev1.ConditionFalse { - return false, fmt.Errorf(condition.Message) - } + if c := meta.GetCondition(kustomization.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionTrue: + return true, nil + case corev1.ConditionFalse: + return false, fmt.Errorf(c.Message) } } return false, nil diff --git a/cmd/gotk/create_source_git.go b/cmd/gotk/create_source_git.go index 5597393d..86831ec9 100644 --- a/cmd/gotk/create_source_git.go +++ b/cmd/gotk/create_source_git.go @@ -373,13 +373,12 @@ func isGitRepositoryReady(ctx context.Context, kubeClient client.Client, name, n return false, err } - for _, condition := range gitRepository.Status.Conditions { - if condition.Type == meta.ReadyCondition { - if condition.Status == corev1.ConditionTrue { - return true, nil - } else if condition.Status == corev1.ConditionFalse { - return false, fmt.Errorf(condition.Message) - } + if c := meta.GetCondition(gitRepository.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionTrue: + return true, nil + case corev1.ConditionFalse: + return false, fmt.Errorf(c.Message) } } return false, nil diff --git a/cmd/gotk/get_helmrelease.go b/cmd/gotk/get_helmrelease.go index 4d2a89ae..29ef63aa 100644 --- a/cmd/gotk/get_helmrelease.go +++ b/cmd/gotk/get_helmrelease.go @@ -68,20 +68,17 @@ func getHelmReleaseCmdRun(cmd *cobra.Command, args []string) error { continue } isInitialized := false - for _, condition := range helmRelease.Status.Conditions { - if condition.Type == meta.ReadyCondition { - if condition.Status != corev1.ConditionFalse { - if helmRelease.Status.LastAppliedRevision != "" { - logger.Successf("%s last applied revision %s", helmRelease.GetName(), helmRelease.Status.LastAppliedRevision) - } else { - logger.Successf("%s reconciling", helmRelease.GetName()) - } - } else { - logger.Failuref("%s %s", helmRelease.GetName(), condition.Message) - } - isInitialized = true - break + if c := meta.GetCondition(helmRelease.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionTrue: + logger.Successf("%s last applied revision %s", helmRelease.GetName(), helmRelease.Status.LastAppliedRevision) + case corev1.ConditionUnknown: + logger.Successf("%s reconciling", helmRelease.GetName()) + default: + logger.Failuref("%s %s", helmRelease.GetName(), c.Message) } + isInitialized = true + break } if !isInitialized { logger.Failuref("%s is not ready", helmRelease.GetName()) diff --git a/cmd/gotk/get_kustomization.go b/cmd/gotk/get_kustomization.go index 9bc225fc..32e973b6 100644 --- a/cmd/gotk/get_kustomization.go +++ b/cmd/gotk/get_kustomization.go @@ -67,20 +67,17 @@ func getKsCmdRun(cmd *cobra.Command, args []string) error { continue } isInitialized := false - for _, condition := range kustomization.Status.Conditions { - if condition.Type == meta.ReadyCondition { - if condition.Status != corev1.ConditionFalse { - if kustomization.Status.LastAppliedRevision != "" { - logger.Successf("%s last applied revision %s", kustomization.GetName(), kustomization.Status.LastAppliedRevision) - } else { - logger.Successf("%s reconciling", kustomization.GetName()) - } - } else { - logger.Failuref("%s %s", kustomization.GetName(), condition.Message) - } - isInitialized = true - break + if c := meta.GetCondition(kustomization.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionTrue: + logger.Successf("%s last applied revision %s", kustomization.GetName(), kustomization.Status.LastAppliedRevision) + case corev1.ConditionUnknown: + logger.Successf("%s reconciling", kustomization.GetName()) + default: + logger.Failuref("%s %s", kustomization.GetName(), c.Message) } + isInitialized = true + break } if !isInitialized { logger.Failuref("%s is not ready", kustomization.GetName()) diff --git a/cmd/gotk/get_source_bucket.go b/cmd/gotk/get_source_bucket.go index e6324dd5..c0eb7a4c 100644 --- a/cmd/gotk/get_source_bucket.go +++ b/cmd/gotk/get_source_bucket.go @@ -60,18 +60,22 @@ func getSourceBucketCmdRun(cmd *cobra.Command, args []string) error { return nil } + // TODO(hidde): this should print a table, and should produce better output + // for items that have an artifact attached while they are in a reconciling + // 'Unknown' state. for _, source := range list.Items { isInitialized := false - for _, condition := range source.Status.Conditions { - if condition.Type == meta.ReadyCondition { - if condition.Status != corev1.ConditionFalse { - logger.Successf("%s last fetched revision: %s", source.GetName(), source.Status.Artifact.Revision) - } else { - logger.Failuref("%s %s", source.GetName(), condition.Message) - } - isInitialized = true - break + if c := meta.GetCondition(source.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionTrue: + logger.Successf("%s last fetched revision: %s", source.GetName(), source.GetArtifact().Revision) + case corev1.ConditionUnknown: + logger.Successf("%s reconciling", source.GetName()) + default: + logger.Failuref("%s %s", source.GetName(), c.Message) } + isInitialized = true + break } if !isInitialized { logger.Failuref("%s is not ready", source.GetName()) diff --git a/cmd/gotk/get_source_git.go b/cmd/gotk/get_source_git.go index 25a93afc..5004bb2d 100644 --- a/cmd/gotk/get_source_git.go +++ b/cmd/gotk/get_source_git.go @@ -60,18 +60,22 @@ func getSourceGitCmdRun(cmd *cobra.Command, args []string) error { return nil } + // TODO(hidde): this should print a table, and should produce better output + // for items that have an artifact attached while they are in a reconciling + // 'Unknown' state. for _, source := range list.Items { isInitialized := false - for _, condition := range source.Status.Conditions { - if condition.Type == meta.ReadyCondition { - if condition.Status != corev1.ConditionFalse { - logger.Successf("%s last fetched revision: %s", source.GetName(), source.Status.Artifact.Revision) - } else { - logger.Failuref("%s %s", source.GetName(), condition.Message) - } - isInitialized = true - break + if c := meta.GetCondition(source.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionTrue: + logger.Successf("%s last fetched revision: %s", source.GetName(), source.GetArtifact().Revision) + case corev1.ConditionUnknown: + logger.Successf("%s reconciling", source.GetName()) + default: + logger.Failuref("%s %s", source.GetName(), c.Message) } + isInitialized = true + break } if !isInitialized { logger.Failuref("%s is not ready", source.GetName()) diff --git a/cmd/gotk/get_source_helm.go b/cmd/gotk/get_source_helm.go index 80b14a5b..9383b2d3 100644 --- a/cmd/gotk/get_source_helm.go +++ b/cmd/gotk/get_source_helm.go @@ -60,18 +60,22 @@ func getSourceHelmCmdRun(cmd *cobra.Command, args []string) error { return nil } + // TODO(hidde): this should print a table, and should produce better output + // for items that have an artifact attached while they are in a reconciling + // 'Unknown' state. for _, source := range list.Items { isInitialized := false - for _, condition := range source.Status.Conditions { - if condition.Type == meta.ReadyCondition { - if condition.Status != corev1.ConditionFalse { - logger.Successf("%s last fetched revision: %s", source.GetName(), source.Status.Artifact.Revision) - } else { - logger.Failuref("%s %s", source.GetName(), condition.Message) - } - isInitialized = true - break + if c := meta.GetCondition(source.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionTrue: + logger.Successf("%s last fetched revision: %s", source.GetName(), source.GetArtifact().Revision) + case corev1.ConditionUnknown: + logger.Successf("%s reconciling", source.GetName()) + default: + logger.Failuref("%s %s", source.GetName(), c.Message) } + isInitialized = true + break } if !isInitialized { logger.Failuref("%s is not ready", source.GetName()) diff --git a/cmd/gotk/reconcile_helmrelease.go b/cmd/gotk/reconcile_helmrelease.go index e62849b8..541e4afd 100644 --- a/cmd/gotk/reconcile_helmrelease.go +++ b/cmd/gotk/reconcile_helmrelease.go @@ -143,13 +143,12 @@ func isHelmReleaseReady(ctx context.Context, kubeClient client.Client, name, nam return false, err } - for _, condition := range helmRelease.Status.Conditions { - if condition.Type == meta.ReadyCondition { - if condition.Status == corev1.ConditionTrue { - return true, nil - } else if condition.Status == corev1.ConditionFalse && helmRelease.Status.LastAttemptedRevision != "" { - return false, fmt.Errorf(condition.Message) - } + if c := meta.GetCondition(helmRelease.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionTrue: + return true, nil + case corev1.ConditionFalse: + return false, fmt.Errorf(c.Message) } } return false, nil diff --git a/cmd/gotk/reconcile_source_bucket.go b/cmd/gotk/reconcile_source_bucket.go index 1b20f112..5ac0c156 100644 --- a/cmd/gotk/reconcile_source_bucket.go +++ b/cmd/gotk/reconcile_source_bucket.go @@ -117,13 +117,12 @@ func isBucketReady(ctx context.Context, kubeClient client.Client, name, namespac return false, err } - for _, condition := range bucket.Status.Conditions { - if condition.Type == meta.ReadyCondition { - if condition.Status == corev1.ConditionTrue { - return true, nil - } else if condition.Status == corev1.ConditionFalse { - return false, fmt.Errorf(condition.Message) - } + if c := meta.GetCondition(bucket.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionTrue: + return true, nil + case corev1.ConditionFalse: + return false, fmt.Errorf(c.Message) } } return false, nil diff --git a/cmd/gotk/reconcile_source_helm.go b/cmd/gotk/reconcile_source_helm.go index 10aa07e0..ea1ad3b8 100644 --- a/cmd/gotk/reconcile_source_helm.go +++ b/cmd/gotk/reconcile_source_helm.go @@ -117,13 +117,12 @@ func isHelmRepositoryReady(ctx context.Context, kubeClient client.Client, name, return false, err } - for _, condition := range helmRepository.Status.Conditions { - if condition.Type == meta.ReadyCondition { - if condition.Status == corev1.ConditionTrue { - return true, nil - } else if condition.Status == corev1.ConditionFalse { - return false, fmt.Errorf(condition.Message) - } + if c := meta.GetCondition(helmRepository.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionTrue: + return true, nil + case corev1.ConditionFalse: + return false, fmt.Errorf(c.Message) } } return false, nil diff --git a/cmd/gotk/resume_helmrelease.go b/cmd/gotk/resume_helmrelease.go index a192c1e1..2484b0dd 100644 --- a/cmd/gotk/resume_helmrelease.go +++ b/cmd/gotk/resume_helmrelease.go @@ -112,17 +112,15 @@ func isHelmReleaseResumed(ctx context.Context, kubeClient client.Client, name, n return false, err } - for _, condition := range helmRelease.Status.Conditions { - if condition.Type == meta.ReadyCondition { - if condition.Status == corev1.ConditionTrue { - return true, nil - } else if condition.Status == corev1.ConditionFalse { - if condition.Reason == meta.SuspendedReason { - return false, nil - } - - return false, fmt.Errorf(condition.Message) + if c := meta.GetCondition(helmRelease.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionTrue: + return true, nil + case corev1.ConditionFalse: + if c.Reason == meta.SuspendedReason { + return false, nil } + return false, fmt.Errorf(c.Message) } } return false, nil diff --git a/cmd/gotk/resume_kustomization.go b/cmd/gotk/resume_kustomization.go index cc9b9451..faef0e64 100644 --- a/cmd/gotk/resume_kustomization.go +++ b/cmd/gotk/resume_kustomization.go @@ -111,17 +111,15 @@ func isKustomizationResumed(ctx context.Context, kubeClient client.Client, name, return false, err } - for _, condition := range kustomization.Status.Conditions { - if condition.Type == meta.ReadyCondition { - if condition.Status == corev1.ConditionTrue { - return true, nil - } else if condition.Status == corev1.ConditionFalse { - if condition.Reason == meta.SuspendedReason { - return false, nil - } - - return false, fmt.Errorf(condition.Message) + if c := meta.GetCondition(kustomization.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionTrue: + return true, nil + case corev1.ConditionFalse: + if c.Reason == meta.SuspendedReason { + return false, nil } + return false, fmt.Errorf(c.Message) } } return false, nil From 84e36ed847a1fedee6810f5f422c92bf80a60e3f Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Wed, 30 Sep 2020 23:21:32 +0200 Subject: [PATCH 2/2] Use `LastHandledReconcileAt` in reconcile commands --- .github/workflows/e2e.yaml | 5 ++- cmd/gotk/create_helmrelease.go | 25 +++++++++++ cmd/gotk/reconcile_helmrelease.go | 57 ++++++++++++------------- cmd/gotk/reconcile_kustomization.go | 65 ++++++++++++++++++++--------- 4 files changed, 101 insertions(+), 51 deletions(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index fae83adb..a73450ea 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -63,7 +63,7 @@ jobs: --health-check="Deployment/frontend.dev" \ --health-check="Deployment/backend.dev" \ --health-check-timeout=3m - - name: gotk sync kustomization --with-source + - name: gotk reconcile kustomization --with-source run: | ./bin/gotk reconcile kustomization podinfo --with-source - name: gotk get kustomizations @@ -99,6 +99,9 @@ jobs: --target-namespace=default \ --source=GitRepository/podinfo \ --chart=./charts/podinfo + - name: gotk reconcile helmrelease --with-source + run: | + ./bin/gotk reconcile helmrelease podinfo-git --with-source - name: gotk get helmreleases run: | ./bin/gotk get helmreleases diff --git a/cmd/gotk/create_helmrelease.go b/cmd/gotk/create_helmrelease.go index 64c343f4..7dd6cbea 100644 --- a/cmd/gotk/create_helmrelease.go +++ b/cmd/gotk/create_helmrelease.go @@ -286,3 +286,28 @@ func isHelmChartReady(ctx context.Context, kubeClient client.Client, name, names return false, nil } } + +func isHelmReleaseReady(ctx context.Context, kubeClient client.Client, name, namespace string) wait.ConditionFunc { + return func() (bool, error) { + var helmRelease helmv2.HelmRelease + namespacedName := types.NamespacedName{ + Namespace: namespace, + Name: name, + } + + err := kubeClient.Get(ctx, namespacedName, &helmRelease) + if err != nil { + return false, err + } + + if c := meta.GetCondition(helmRelease.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionTrue: + return true, nil + case corev1.ConditionFalse: + return false, fmt.Errorf(c.Message) + } + } + return false, nil + } +} diff --git a/cmd/gotk/reconcile_helmrelease.go b/cmd/gotk/reconcile_helmrelease.go index 541e4afd..d5f9ecda 100644 --- a/cmd/gotk/reconcile_helmrelease.go +++ b/cmd/gotk/reconcile_helmrelease.go @@ -19,11 +19,12 @@ package main import ( "context" "fmt" - "github.com/fluxcd/pkg/apis/meta" "time" - "github.com/spf13/cobra" + "github.com/fluxcd/pkg/apis/meta" corev1 "k8s.io/api/core/v1" + + "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" "sigs.k8s.io/controller-runtime/pkg/client" @@ -94,24 +95,25 @@ func reconcileHrCmdRun(cmd *cobra.Command, args []string) error { if err != nil { return err } - } else { - logger.Actionf("annotating HelmRelease %s in %s namespace", name, namespace) - if helmRelease.Annotations == nil { - helmRelease.Annotations = map[string]string{ - meta.ReconcileAtAnnotation: time.Now().Format(time.RFC3339Nano), - } - } else { - helmRelease.Annotations[meta.ReconcileAtAnnotation] = time.Now().Format(time.RFC3339Nano) - } - if err := kubeClient.Update(ctx, &helmRelease); err != nil { - return err + } + + logger.Actionf("annotating HelmRelease %s in %s namespace", name, namespace) + if helmRelease.Annotations == nil { + helmRelease.Annotations = map[string]string{ + meta.ReconcileAtAnnotation: time.Now().Format(time.RFC3339Nano), } - logger.Successf("HelmRelease annotated") + } else { + helmRelease.Annotations[meta.ReconcileAtAnnotation] = time.Now().Format(time.RFC3339Nano) + } + if err := kubeClient.Update(ctx, &helmRelease); err != nil { + return err } + logger.Successf("HelmRelease annotated") logger.Waitingf("waiting for HelmRelease reconciliation") if err := wait.PollImmediate(pollInterval, timeout, - isHelmReleaseReady(ctx, kubeClient, name, namespace)); err != nil { + helmReleaseReconciliationHandled(ctx, kubeClient, name, namespace, helmRelease.Status.LastHandledReconcileAt), + ); err != nil { return err } @@ -121,16 +123,19 @@ func reconcileHrCmdRun(cmd *cobra.Command, args []string) error { if err != nil { return err } - - if helmRelease.Status.LastAppliedRevision != "" { - logger.Successf("reconciled revision %s", helmRelease.Status.LastAppliedRevision) - } else { - return fmt.Errorf("HelmRelease reconciliation failed") + if c := meta.GetCondition(helmRelease.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionFalse: + return fmt.Errorf("HelmRelease reconciliation failed") + default: + logger.Successf("reconciled revision %s", helmRelease.Status.LastAppliedRevision) + } } return nil } -func isHelmReleaseReady(ctx context.Context, kubeClient client.Client, name, namespace string) wait.ConditionFunc { +func helmReleaseReconciliationHandled(ctx context.Context, kubeClient client.Client, + name, namespace, lastHandledReconcileAt string) wait.ConditionFunc { return func() (bool, error) { var helmRelease helmv2.HelmRelease namespacedName := types.NamespacedName{ @@ -143,14 +148,6 @@ func isHelmReleaseReady(ctx context.Context, kubeClient client.Client, name, nam return false, err } - if c := meta.GetCondition(helmRelease.Status.Conditions, meta.ReadyCondition); c != nil { - switch c.Status { - case corev1.ConditionTrue: - return true, nil - case corev1.ConditionFalse: - return false, fmt.Errorf(c.Message) - } - } - return false, nil + return helmRelease.Status.LastHandledReconcileAt != lastHandledReconcileAt, nil } } diff --git a/cmd/gotk/reconcile_kustomization.go b/cmd/gotk/reconcile_kustomization.go index 7ca0d5d1..dee82809 100644 --- a/cmd/gotk/reconcile_kustomization.go +++ b/cmd/gotk/reconcile_kustomization.go @@ -19,9 +19,12 @@ package main import ( "context" "fmt" - "github.com/fluxcd/pkg/apis/meta" "time" + "github.com/fluxcd/pkg/apis/meta" + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" @@ -90,24 +93,26 @@ func reconcileKsCmdRun(cmd *cobra.Command, args []string) error { if err != nil { return err } - } else { - logger.Actionf("annotating kustomization %s in %s namespace", name, namespace) - if kustomization.Annotations == nil { - kustomization.Annotations = map[string]string{ - meta.ReconcileAtAnnotation: time.Now().Format(time.RFC3339Nano), - } - } else { - kustomization.Annotations[meta.ReconcileAtAnnotation] = time.Now().Format(time.RFC3339Nano) - } - if err := kubeClient.Update(ctx, &kustomization); err != nil { - return err + } + + logger.Actionf("annotating kustomization %s in %s namespace", name, namespace) + if kustomization.Annotations == nil { + kustomization.Annotations = map[string]string{ + meta.ReconcileAtAnnotation: time.Now().Format(time.RFC3339Nano), } - logger.Successf("kustomization annotated") + } else { + kustomization.Annotations[meta.ReconcileAtAnnotation] = time.Now().Format(time.RFC3339Nano) + } + if err := kubeClient.Update(ctx, &kustomization); err != nil { + return err } + logger.Successf("kustomization annotated") logger.Waitingf("waiting for kustomization reconciliation") - if err := wait.PollImmediate(pollInterval, timeout, - isKustomizationReady(ctx, kubeClient, name, namespace)); err != nil { + if err := wait.PollImmediate( + pollInterval, timeout, + kustomizeReconciliationHandled(ctx, kubeClient, name, namespace, kustomization.Status.LastHandledReconcileAt), + ); err != nil { return err } @@ -117,11 +122,31 @@ func reconcileKsCmdRun(cmd *cobra.Command, args []string) error { if err != nil { return err } - - if kustomization.Status.LastAppliedRevision != "" { - logger.Successf("reconciled revision %s", kustomization.Status.LastAppliedRevision) - } else { - return fmt.Errorf("kustomization sync failed") + if c := meta.GetCondition(kustomization.Status.Conditions, meta.ReadyCondition); c != nil { + switch c.Status { + case corev1.ConditionFalse: + return fmt.Errorf("kustomization reconciliation failed") + default: + logger.Successf("reconciled revision %s", kustomization.Status.LastAppliedRevision) + } } return nil } + +func kustomizeReconciliationHandled(ctx context.Context, kubeClient client.Client, + name, namespace, lastHandledReconcileAt string) wait.ConditionFunc { + return func() (bool, error) { + var kustomize kustomizev1.Kustomization + namespacedName := types.NamespacedName{ + Namespace: namespace, + Name: name, + } + + err := kubeClient.Get(ctx, namespacedName, &kustomize) + if err != nil { + return false, err + } + + return kustomize.Status.LastHandledReconcileAt != lastHandledReconcileAt, nil + } +}