Refactor health check completed logic

This commit is contained in:
Philip Laine 2020-09-08 23:21:47 +02:00
parent c113c2043f
commit 4e45c916e2
3 changed files with 115 additions and 118 deletions

View File

@ -76,8 +76,7 @@ spec:
type: string
type: array
healthChecks:
description: A list of workloads (Deployments, DaemonSets and StatefulSets)
to be included in the health assessment.
description: A list of resources to be included in the health assessment.
items:
description: CrossNamespaceObjectReference contains enough information
to let you locate the typed referenced object at cluster level

View File

@ -37,6 +37,8 @@ import (
kuberecorder "k8s.io/client-go/tools/record"
"k8s.io/client-go/tools/reference"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/aggregator"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/collector"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/event"
"sigs.k8s.io/cli-utils/pkg/kstatus/status"
"sigs.k8s.io/cli-utils/pkg/object"
@ -645,22 +647,8 @@ func toObjMetadata(cr []kustomizev1.CrossNamespaceObjectReference) ([]object.Obj
return oo, nil
}
func toHealthySet(oo []object.ObjMetadata) map[string]bool {
hs := map[string]bool{}
for _, o := range oo {
hs[o.String()] = false
}
return hs
}
func filterHealthSet(hs map[string]bool, healthy bool) []string {
res := []string{}
for k, v := range hs {
if v == healthy {
res = append(res, k)
}
}
return res
func objMetadataToString(om object.ObjMetadata) string {
return fmt.Sprintf("%s '%s/%s'", om.GroupKind.Kind, om.Namespace, om.Name)
}
func (r *KustomizationReconciler) checkHealth(kustomization kustomizev1.Kustomization, revision string) error {
@ -678,46 +666,44 @@ func (r *KustomizationReconciler) checkHealth(kustomization kustomizev1.Kustomiz
defer cancel()
opts := polling.Options{PollInterval: 500 * time.Millisecond, UseCache: true}
healthySet := toHealthySet(objMetadata)
eventsChan := r.Poller.Poll(ctx, objMetadata, opts)
for {
select {
case <-ctx.Done():
notHealthy := filterHealthSet(healthySet, false)
return fmt.Errorf("Health check timed out for [%v]", strings.Join(notHealthy, ", "))
case e := <-eventsChan:
switch e.EventType {
case event.ResourceUpdateEvent:
if e.Resource.Status == status.CurrentStatus {
healthySet[e.Resource.Identifier.String()] = true
r.Log.WithValues(
strings.ToLower(kustomization.Kind),
fmt.Sprintf("%s/%s", kustomization.GetNamespace(), kustomization.GetName()),
).Info(fmt.Sprintf("Health check passed for %s", e.Resource.Identifier.String()))
} else {
healthySet[e.Resource.Identifier.String()] = false
}
case event.ErrorEvent:
return e.Error
// Event does not behave like expected and will not occur when all the
// resources are in a current state.
/*case event.CompletedEvent:
if alerts != "" && kustomization.Status.LastAppliedRevision != revision {
r.event(kustomization, revision, recorder.EventSeverityInfo, alerts)
}
return nil*/
coll := collector.NewResourceStatusCollector(objMetadata)
done := coll.ListenWithObserver(eventsChan, collector.ObserverFunc(
func(statusCollector *collector.ResourceStatusCollector) {
var rss []*event.ResourceStatus
for _, rs := range statusCollector.ResourceStatuses {
rss = append(rss, rs)
}
desired := status.CurrentStatus
aggStatus := aggregator.AggregateStatus(rss, desired)
if aggStatus == desired {
cancel()
return
}
}),
)
if len(filterHealthSet(healthySet, false)) == 0 {
if kustomization.Status.LastAppliedRevision != revision {
healthy := filterHealthSet(healthySet, true)
r.event(kustomization, revision, recorder.EventSeverityInfo, "Health check passed for "+strings.Join(healthy, ", "))
}
return nil
<-done
if coll.Error != nil {
return coll.Error
}
if ctx.Err() == context.DeadlineExceeded {
ids := []string{}
for _, rs := range coll.ResourceStatuses {
if rs.Status != status.CurrentStatus {
id := objMetadataToString(rs.Identifier)
ids = append(ids, id)
}
}
return fmt.Errorf("Health check timed out for [%v]", strings.Join(ids, ", "))
}
if kustomization.Status.LastAppliedRevision != revision {
r.event(kustomization, revision, recorder.EventSeverityInfo, "Health check passed")
}
return nil
}
func (r *KustomizationReconciler) lock(name string) (unlock func(), err error) {

View File

@ -134,15 +134,14 @@ bool
<td>
<code>healthChecks</code><br>
<em>
<a href="#kustomize.toolkit.fluxcd.io/v1alpha1.WorkloadReference">
[]WorkloadReference
<a href="#kustomize.toolkit.fluxcd.io/v1alpha1.CrossNamespaceObjectReference">
[]CrossNamespaceObjectReference
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>A list of workloads (Deployments, DaemonSets and StatefulSets)
to be included in the health assessment.</p>
<p>A list of resources to be included in the health assessment.</p>
</td>
</tr>
<tr>
@ -163,8 +162,8 @@ ServiceAccount
<td>
<code>sourceRef</code><br>
<em>
<a href="#kustomize.toolkit.fluxcd.io/v1alpha1.CrossNamespaceObjectReference">
CrossNamespaceObjectReference
<a href="#kustomize.toolkit.fluxcd.io/v1alpha1.CrossNamespaceSourceReference">
CrossNamespaceSourceReference
</a>
</em>
</td>
@ -388,6 +387,74 @@ string
</table>
</div>
</div>
<h3 id="kustomize.toolkit.fluxcd.io/v1alpha1.CrossNamespaceSourceReference">CrossNamespaceSourceReference
</h3>
<p>
(<em>Appears on:</em>
<a href="#kustomize.toolkit.fluxcd.io/v1alpha1.KustomizationSpec">KustomizationSpec</a>)
</p>
<p>CrossNamespaceSourceReference contains enough information to let you locate the
typed referenced object at cluster level</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
<thead>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>apiVersion</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>API version of the referent</p>
</td>
</tr>
<tr>
<td>
<code>kind</code><br>
<em>
string
</em>
</td>
<td>
<p>Kind of the referent</p>
</td>
</tr>
<tr>
<td>
<code>name</code><br>
<em>
string
</em>
</td>
<td>
<p>Name of the referent</p>
</td>
</tr>
<tr>
<td>
<code>namespace</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Namespace of the referent</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<h3 id="kustomize.toolkit.fluxcd.io/v1alpha1.Decryption">Decryption
</h3>
<p>
@ -517,15 +584,14 @@ bool
<td>
<code>healthChecks</code><br>
<em>
<a href="#kustomize.toolkit.fluxcd.io/v1alpha1.WorkloadReference">
[]WorkloadReference
<a href="#kustomize.toolkit.fluxcd.io/v1alpha1.CrossNamespaceObjectReference">
[]CrossNamespaceObjectReference
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>A list of workloads (Deployments, DaemonSets and StatefulSets)
to be included in the health assessment.</p>
<p>A list of resources to be included in the health assessment.</p>
</td>
</tr>
<tr>
@ -546,8 +612,8 @@ ServiceAccount
<td>
<code>sourceRef</code><br>
<em>
<a href="#kustomize.toolkit.fluxcd.io/v1alpha1.CrossNamespaceObjectReference">
CrossNamespaceObjectReference
<a href="#kustomize.toolkit.fluxcd.io/v1alpha1.CrossNamespaceSourceReference">
CrossNamespaceSourceReference
</a>
</em>
</td>
@ -819,60 +885,6 @@ map[string]string
</table>
</div>
</div>
<h3 id="kustomize.toolkit.fluxcd.io/v1alpha1.WorkloadReference">WorkloadReference
</h3>
<p>
(<em>Appears on:</em>
<a href="#kustomize.toolkit.fluxcd.io/v1alpha1.KustomizationSpec">KustomizationSpec</a>)
</p>
<p>WorkloadReference defines a reference to a Deployment, DaemonSet or StatefulSet.</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
<thead>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>kind</code><br>
<em>
string
</em>
</td>
<td>
<p>Kind is the type of resource being referenced.</p>
</td>
</tr>
<tr>
<td>
<code>name</code><br>
<em>
string
</em>
</td>
<td>
<p>Name is the name of resource being referenced.</p>
</td>
</tr>
<tr>
<td>
<code>namespace</code><br>
<em>
string
</em>
</td>
<td>
<p>Namespace is the namespace of resource being referenced.</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="admonition note">
<p class="last">This page was automatically generated with <code>gen-crd-api-reference-docs</code></p>
</div>