github.com/argoproj/argo-cd/v3@v3.2.1/controller/health.go (about)

     1  package controller
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/argoproj/gitops-engine/pkg/health"
     7  	hookutil "github.com/argoproj/gitops-engine/pkg/sync/hook"
     8  	"github.com/argoproj/gitops-engine/pkg/sync/ignore"
     9  	kubeutil "github.com/argoproj/gitops-engine/pkg/utils/kube"
    10  	log "github.com/sirupsen/logrus"
    11  	"k8s.io/apimachinery/pkg/runtime/schema"
    12  
    13  	"github.com/argoproj/argo-cd/v3/common"
    14  	"github.com/argoproj/argo-cd/v3/pkg/apis/application"
    15  	appv1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
    16  	applog "github.com/argoproj/argo-cd/v3/util/app/log"
    17  	"github.com/argoproj/argo-cd/v3/util/lua"
    18  )
    19  
    20  // setApplicationHealth updates the health statuses of all resources performed in the comparison
    21  func setApplicationHealth(resources []managedResource, statuses []appv1.ResourceStatus, resourceOverrides map[string]appv1.ResourceOverride, app *appv1.Application, persistResourceHealth bool) (health.HealthStatusCode, error) {
    22  	var savedErr error
    23  	var errCount uint
    24  
    25  	appHealthStatus := health.HealthStatusHealthy
    26  	for i, res := range resources {
    27  		if res.Target != nil && hookutil.Skip(res.Target) {
    28  			continue
    29  		}
    30  		if res.Live != nil && res.Live.GetAnnotations() != nil && res.Live.GetAnnotations()[common.AnnotationIgnoreHealthCheck] == "true" {
    31  			continue
    32  		}
    33  		if res.Live != nil && (hookutil.IsHook(res.Live) || ignore.Ignore(res.Live)) {
    34  			continue
    35  		}
    36  
    37  		var healthStatus *health.HealthStatus
    38  		var err error
    39  		healthOverrides := lua.ResourceHealthOverrides(resourceOverrides)
    40  		gvk := schema.GroupVersionKind{Group: res.Group, Version: res.Version, Kind: res.Kind}
    41  		if res.Live == nil {
    42  			healthStatus = &health.HealthStatus{Status: health.HealthStatusMissing}
    43  		} else {
    44  			// App the manages itself should not affect own health
    45  			if isSelfReferencedApp(app, kubeutil.GetObjectRef(res.Live)) {
    46  				continue
    47  			}
    48  			healthStatus, err = health.GetResourceHealth(res.Live, healthOverrides)
    49  			if err != nil && savedErr == nil {
    50  				errCount++
    51  				savedErr = fmt.Errorf("failed to get resource health for %q with name %q in namespace %q: %w", res.Live.GetKind(), res.Live.GetName(), res.Live.GetNamespace(), err)
    52  				// also log so we don't lose the message
    53  				log.WithFields(applog.GetAppLogFields(app)).Warn(savedErr)
    54  			}
    55  		}
    56  
    57  		if healthStatus == nil {
    58  			continue
    59  		}
    60  
    61  		if persistResourceHealth {
    62  			resHealth := appv1.HealthStatus{Status: healthStatus.Status, Message: healthStatus.Message}
    63  			statuses[i].Health = &resHealth
    64  		} else {
    65  			statuses[i].Health = nil
    66  		}
    67  
    68  		// Is health status is missing but resource has not built-in/custom health check then it should not affect parent app health
    69  		if _, hasOverride := healthOverrides[lua.GetConfigMapKey(gvk)]; healthStatus.Status == health.HealthStatusMissing && !hasOverride && health.GetHealthCheckFunc(gvk) == nil {
    70  			continue
    71  		}
    72  
    73  		// Missing or Unknown health status of child Argo CD app should not affect parent
    74  		if res.Kind == application.ApplicationKind && res.Group == application.Group && (healthStatus.Status == health.HealthStatusMissing || healthStatus.Status == health.HealthStatusUnknown) {
    75  			continue
    76  		}
    77  
    78  		if health.IsWorse(appHealthStatus, healthStatus.Status) {
    79  			appHealthStatus = healthStatus.Status
    80  		}
    81  	}
    82  	if persistResourceHealth {
    83  		app.Status.ResourceHealthSource = appv1.ResourceHealthLocationInline
    84  	} else {
    85  		app.Status.ResourceHealthSource = appv1.ResourceHealthLocationAppTree
    86  	}
    87  	if savedErr != nil && errCount > 1 {
    88  		savedErr = fmt.Errorf("see application-controller logs for %d other errors; most recent error was: %w", errCount-1, savedErr)
    89  	}
    90  	return appHealthStatus, savedErr
    91  }