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 }