From adca92c41735ff92156d50323547e05067daf74d Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Tue, 2 Feb 2021 13:15:10 +0200 Subject: [PATCH] Add Healthy status condition - record the last health assessment result in a dedicated status condition - use the condition status when issuing events to prevent notifications spam Signed-off-by: Stefan Prodan --- api/v1beta1/condition_types.go | 4 ++++ api/v1beta1/kustomization_types.go | 13 +++++++++++++ controllers/kustomization_controller.go | 6 +++--- controllers/kustomization_controller_test.go | 15 ++++++++++++--- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/api/v1beta1/condition_types.go b/api/v1beta1/condition_types.go index 972dad332..dd635f934 100644 --- a/api/v1beta1/condition_types.go +++ b/api/v1beta1/condition_types.go @@ -17,6 +17,10 @@ limitations under the License. package v1beta1 const ( + // HealthyCondition is the condition type used + // to record the last health assessment result. + HealthyCondition string = "Healthy" + // PruneFailedReason represents the fact that the // pruning of the Kustomization failed. PruneFailedReason string = "PruneFailed" diff --git a/api/v1beta1/kustomization_types.go b/api/v1beta1/kustomization_types.go index 85d9e8f9b..b5dd906c1 100644 --- a/api/v1beta1/kustomization_types.go +++ b/api/v1beta1/kustomization_types.go @@ -17,6 +17,7 @@ limitations under the License. package v1beta1 import ( + apimeta "k8s.io/apimachinery/pkg/api/meta" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -184,6 +185,16 @@ func KustomizationProgressing(k Kustomization) Kustomization { return k } +// SetKustomizationHealthiness sets the HealthyCondition status for a Kustomization. +func SetKustomizationHealthiness(k *Kustomization, status metav1.ConditionStatus, reason, message string) { + switch len(k.Spec.HealthChecks) { + case 0: + apimeta.RemoveStatusCondition(k.GetStatusConditions(), HealthyCondition) + default: + meta.SetResourceCondition(k, HealthyCondition, status, reason, trimString(message, MaxConditionMessageLength)) + } +} + // SetKustomizeReadiness sets the ReadyCondition, ObservedGeneration, and LastAttemptedRevision, // on the Kustomization. func SetKustomizationReadiness(k *Kustomization, status metav1.ConditionStatus, reason, message string, revision string) { @@ -205,6 +216,7 @@ func KustomizationNotReady(k Kustomization, revision, reason, message string) Ku // including a Snapshot. func KustomizationNotReadySnapshot(k Kustomization, snapshot *Snapshot, revision, reason, message string) Kustomization { SetKustomizationReadiness(&k, metav1.ConditionFalse, reason, trimString(message, MaxConditionMessageLength), revision) + SetKustomizationHealthiness(&k, metav1.ConditionFalse, reason, reason) k.Status.Snapshot = snapshot k.Status.LastAttemptedRevision = revision return k @@ -213,6 +225,7 @@ func KustomizationNotReadySnapshot(k Kustomization, snapshot *Snapshot, revision // KustomizationReady registers a successful apply attempt of the given Kustomization. func KustomizationReady(k Kustomization, snapshot *Snapshot, revision, reason, message string) Kustomization { SetKustomizationReadiness(&k, metav1.ConditionTrue, reason, trimString(message, MaxConditionMessageLength), revision) + SetKustomizationHealthiness(&k, metav1.ConditionTrue, reason, reason) k.Status.Snapshot = snapshot k.Status.LastAppliedRevision = revision return k diff --git a/controllers/kustomization_controller.go b/controllers/kustomization_controller.go index 6a5bc1004..42d105772 100644 --- a/controllers/kustomization_controller.go +++ b/controllers/kustomization_controller.go @@ -695,10 +695,10 @@ func (r *KustomizationReconciler) checkHealth(ctx context.Context, statusPoller return err } - readiness := apimeta.FindStatusCondition(kustomization.Status.Conditions, meta.ReadyCondition) - ready := readiness != nil && readiness.Status == metav1.ConditionTrue + healthiness := apimeta.FindStatusCondition(kustomization.Status.Conditions, kustomizev1.HealthyCondition) + healthy := healthiness != nil && healthiness.Status == metav1.ConditionTrue - if !ready || (kustomization.Status.LastAppliedRevision != revision && changed) { + if !healthy || (kustomization.Status.LastAppliedRevision != revision && changed) { r.event(ctx, kustomization, revision, events.EventSeverityInfo, "Health check passed", nil) } return nil diff --git a/controllers/kustomization_controller_test.go b/controllers/kustomization_controller_test.go index 298941dd0..5a274b902 100644 --- a/controllers/kustomization_controller_test.go +++ b/controllers/kustomization_controller_test.go @@ -170,26 +170,35 @@ var _ = Describe("KustomizationReconciler", func() { Suspend: false, Timeout: nil, Validation: "client", + //HealthChecks: []meta.NamespacedObjectKindReference{ + // { + // APIVersion: "v1", + // Kind: "ServiceAccount", + // Name: "test", + // Namespace: "test", + // }, + //}, }, } Expect(k8sClient.Create(context.Background(), k)).Should(Succeed()) defer k8sClient.Delete(context.Background(), k) got := &kustomizev1.Kustomization{} - var cond metav1.Condition + var readyCondition metav1.Condition Eventually(func() bool { _ = k8sClient.Get(context.Background(), kName, got) for _, c := range got.Status.Conditions { if c.Reason == t.waitForReason { - cond = c + readyCondition = c return true } } return false }, timeout, interval).Should(BeTrue()) - Expect(cond.Status).To(Equal(t.expectStatus)) + Expect(readyCondition.Status).To(Equal(t.expectStatus)) Expect(got.Status.LastAppliedRevision).To(Equal(t.expectRevision)) + //Expect(apimeta.IsStatusConditionTrue(got.Status.Conditions, kustomizev1.HealthyCondition)).To(BeTrue()) ns := &corev1.Namespace{} Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: "test"}, ns)).Should(Succeed())