github.com/argoproj/argo-cd@v1.8.7/controller/clusterinfoupdater.go (about)

     1  package controller
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"github.com/argoproj/gitops-engine/pkg/cache"
     8  	"github.com/argoproj/gitops-engine/pkg/utils/kube"
     9  	log "github.com/sirupsen/logrus"
    10  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    11  	"k8s.io/apimachinery/pkg/labels"
    12  
    13  	"github.com/argoproj/argo-cd/controller/metrics"
    14  	appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
    15  	"github.com/argoproj/argo-cd/pkg/client/listers/application/v1alpha1"
    16  	"github.com/argoproj/argo-cd/util/argo"
    17  	appstatecache "github.com/argoproj/argo-cd/util/cache/appstate"
    18  	"github.com/argoproj/argo-cd/util/db"
    19  )
    20  
    21  const (
    22  	secretUpdateInterval = 10 * time.Second
    23  )
    24  
    25  type clusterInfoUpdater struct {
    26  	infoSource    metrics.HasClustersInfo
    27  	db            db.ArgoDB
    28  	appLister     v1alpha1.ApplicationNamespaceLister
    29  	cache         *appstatecache.Cache
    30  	clusterFilter func(cluster *appv1.Cluster) bool
    31  }
    32  
    33  func NewClusterInfoUpdater(
    34  	infoSource metrics.HasClustersInfo,
    35  	db db.ArgoDB,
    36  	appLister v1alpha1.ApplicationNamespaceLister,
    37  	cache *appstatecache.Cache,
    38  	clusterFilter func(cluster *appv1.Cluster) bool) *clusterInfoUpdater {
    39  
    40  	return &clusterInfoUpdater{infoSource, db, appLister, cache, clusterFilter}
    41  }
    42  
    43  func (c *clusterInfoUpdater) Run(ctx context.Context) {
    44  	c.updateClusters()
    45  	ticker := time.NewTicker(secretUpdateInterval)
    46  	for {
    47  		select {
    48  		case <-ctx.Done():
    49  			ticker.Stop()
    50  			break
    51  		case <-ticker.C:
    52  			c.updateClusters()
    53  		}
    54  	}
    55  }
    56  
    57  func (c *clusterInfoUpdater) updateClusters() {
    58  	infoByServer := make(map[string]*cache.ClusterInfo)
    59  	clustersInfo := c.infoSource.GetClustersInfo()
    60  	for i := range clustersInfo {
    61  		info := clustersInfo[i]
    62  		infoByServer[info.Server] = &info
    63  	}
    64  	clusters, err := c.db.ListClusters(context.Background())
    65  	if err != nil {
    66  		log.Warnf("Failed to save clusters info: %v", err)
    67  	}
    68  	var clustersFiltered []appv1.Cluster
    69  	if c.clusterFilter == nil {
    70  		clustersFiltered = clusters.Items
    71  	} else {
    72  		for i := range clusters.Items {
    73  			if c.clusterFilter(&clusters.Items[i]) {
    74  				clustersFiltered = append(clustersFiltered, clusters.Items[i])
    75  			}
    76  		}
    77  	}
    78  	_ = kube.RunAllAsync(len(clustersFiltered), func(i int) error {
    79  		cluster := clustersFiltered[i]
    80  		if err := c.updateClusterInfo(cluster, infoByServer[cluster.Server]); err != nil {
    81  			log.Warnf("Failed to save clusters info: %v", err)
    82  		}
    83  		return nil
    84  	})
    85  	log.Debugf("Successfully saved info of %d clusters", len(clustersFiltered))
    86  }
    87  
    88  func (c *clusterInfoUpdater) updateClusterInfo(cluster appv1.Cluster, info *cache.ClusterInfo) error {
    89  	apps, err := c.appLister.List(labels.Everything())
    90  	if err != nil {
    91  		return err
    92  	}
    93  	var appCount int64
    94  	for _, a := range apps {
    95  		if err := argo.ValidateDestination(context.Background(), &a.Spec.Destination, c.db); err != nil {
    96  			continue
    97  		}
    98  		if a.Spec.Destination.Server == cluster.Server {
    99  			appCount += 1
   100  		}
   101  	}
   102  	now := metav1.Now()
   103  	clusterInfo := appv1.ClusterInfo{
   104  		ConnectionState:   appv1.ConnectionState{ModifiedAt: &now},
   105  		ApplicationsCount: appCount,
   106  	}
   107  	if info != nil {
   108  		clusterInfo.ServerVersion = info.K8SVersion
   109  		if info.LastCacheSyncTime == nil {
   110  			clusterInfo.ConnectionState.Status = appv1.ConnectionStatusUnknown
   111  		} else if info.SyncError == nil {
   112  			clusterInfo.ConnectionState.Status = appv1.ConnectionStatusSuccessful
   113  			syncTime := metav1.NewTime(*info.LastCacheSyncTime)
   114  			clusterInfo.CacheInfo.LastCacheSyncTime = &syncTime
   115  			clusterInfo.CacheInfo.APIsCount = int64(info.APIsCount)
   116  			clusterInfo.CacheInfo.ResourcesCount = int64(info.ResourcesCount)
   117  		} else {
   118  			clusterInfo.ConnectionState.Status = appv1.ConnectionStatusFailed
   119  			clusterInfo.ConnectionState.Message = info.SyncError.Error()
   120  		}
   121  	} else {
   122  		clusterInfo.ConnectionState.Status = appv1.ConnectionStatusUnknown
   123  		if appCount == 0 {
   124  			clusterInfo.ConnectionState.Message = "Cluster has no application and not being monitored."
   125  		}
   126  	}
   127  
   128  	return c.cache.SetClusterInfo(cluster.Server, &clusterInfo)
   129  }