Skip to content

Commit

Permalink
Add Healthy status condition
Browse files Browse the repository at this point in the history
- 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 <stefan.prodan@gmail.com>
  • Loading branch information
stefanprodan committed Feb 2, 2021
1 parent 26ec841 commit 5e17dd4
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 6 deletions.
4 changes: 4 additions & 0 deletions api/v1beta1/condition_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
13 changes: 13 additions & 0 deletions api/v1beta1/kustomization_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand All @@ -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
Expand All @@ -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
Expand Down
6 changes: 3 additions & 3 deletions controllers/kustomization_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 13 additions & 3 deletions controllers/kustomization_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
. "github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/clientcmd"
Expand Down Expand Up @@ -170,26 +171,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())
Expand Down

0 comments on commit 5e17dd4

Please sign in to comment.