diff --git a/applylib/applyset/applyset.go b/applylib/applyset/applyset.go index 489c5af8..45e034b8 100644 --- a/applylib/applyset/applyset.go +++ b/applylib/applyset/applyset.go @@ -257,8 +257,9 @@ func (a *ApplySet) ApplyOnce(ctx context.Context) (*ApplyResults, error) { visitedUids.Insert(lastApplied.GetUID()) tracker.lastApplied = lastApplied results.applySuccess(gvk, nn) - tracker.isHealthy = isHealthy(lastApplied) - results.reportHealth(gvk, nn, tracker.isHealthy) + message := "" + tracker.isHealthy, message = isHealthy(lastApplied) + results.reportHealth(gvk, nn, tracker.isHealthy, message) } // We want to be more cautions on pruning and only do it if all manifests are applied. diff --git a/applylib/applyset/health.go b/applylib/applyset/health.go index 15eb8d9b..9dcaace9 100644 --- a/applylib/applyset/health.go +++ b/applylib/applyset/health.go @@ -26,27 +26,27 @@ import ( // isHealthy reports whether the object should be considered "healthy" // TODO: Replace with kstatus library -func isHealthy(u *unstructured.Unstructured) bool { +func isHealthy(u *unstructured.Unstructured) (bool, string) { result, err := status.Compute(u) if err != nil { klog.Infof("unable to compute condition for %s", humanName(u)) - return false + return false, result.Message } switch result.Status { case status.InProgressStatus: - return false + return false, result.Message case status.FailedStatus: - return false + return false, result.Message case status.TerminatingStatus: - return false + return false, result.Message case status.UnknownStatus: klog.Warningf("unknown status for %s", humanName(u)) - return false + return false, result.Message case status.CurrentStatus: - return true + return true, result.Message default: klog.Warningf("unknown status value %s", result.Status) - return false + return false, result.Message } } diff --git a/applylib/applyset/results.go b/applylib/applyset/results.go index ae0f82bd..901484c1 100644 --- a/applylib/applyset/results.go +++ b/applylib/applyset/results.go @@ -22,6 +22,15 @@ import ( "k8s.io/klog/v2" ) +type ObjectStatus struct { + GVK schema.GroupVersionKind + NameNamespace types.NamespacedName + IsHealthy bool + IsPruned bool + Message string + Error error +} + // ApplyResults contains the results of an Apply operation. type ApplyResults struct { total int @@ -31,6 +40,7 @@ type ApplyResults struct { pruneFailCount int healthyCount int unhealthyCount int + Objects []ObjectStatus } // AllApplied is true if the desired state has been successfully applied for all objects. @@ -62,6 +72,14 @@ func (r *ApplyResults) checkInvariants() { // applyError records that the apply of an object failed with an error. func (r *ApplyResults) applyError(gvk schema.GroupVersionKind, nn types.NamespacedName, err error) { r.applyFailCount++ + r.Objects = append(r.Objects, ObjectStatus{ + GVK: gvk, + NameNamespace: nn, + IsHealthy: false, + IsPruned: false, + Message: "Apply Error", + Error: err, + }) klog.Warningf("error from apply on %s %s: %v", gvk, nn, err) } @@ -72,17 +90,37 @@ func (r *ApplyResults) applySuccess(gvk schema.GroupVersionKind, nn types.Namesp // pruneError records that the prune of an object failed with an error. func (r *ApplyResults) pruneError(gvk schema.GroupVersionKind, nn types.NamespacedName, err error) { + r.Objects = append(r.Objects, ObjectStatus{ + GVK: gvk, + NameNamespace: nn, + IsHealthy: true, + IsPruned: true, + Message: "Prune Error", + Error: err, + }) r.pruneFailCount++ klog.Warningf("error from pruning on %s %s: %v", gvk, nn, err) } // pruneSuccess records that an object was pruned and this succeeded. func (r *ApplyResults) pruneSuccess(gvk schema.GroupVersionKind, nn types.NamespacedName) { + r.Objects = append(r.Objects, ObjectStatus{ + GVK: gvk, + NameNamespace: nn, + IsPruned: true, + }) r.pruneSuccessCount++ } // reportHealth records the health of an object. -func (r *ApplyResults) reportHealth(gvk schema.GroupVersionKind, nn types.NamespacedName, isHealthy bool) { +func (r *ApplyResults) reportHealth(gvk schema.GroupVersionKind, nn types.NamespacedName, isHealthy bool, message string) { + r.Objects = append(r.Objects, ObjectStatus{ + GVK: gvk, + NameNamespace: nn, + IsHealthy: isHealthy, + IsPruned: false, + Message: message, + }) if isHealthy { r.healthyCount++ } else {