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 + } +}