package status import ( "sync" "time" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1" ) type clusterData struct { // readyCondition is the last observed ready condition of the cluster. readyCondition metav1.ConditionStatus // thresholdStartTime is the time that the ready condition changed. thresholdStartTime time.Time } type clusterConditionStore struct { clusterDataMap sync.Map // failureThreshold is the duration of failure for the cluster to be considered unhealthy. failureThreshold time.Duration } func (c *clusterConditionStore) thresholdAdjustedReadyCondition(cluster *clusterv1alpha1.Cluster, observedReadyCondition *metav1.Condition) *metav1.Condition { saved := c.get(cluster.Name) if saved == nil { // the cluster is just joined c.update(cluster.Name, &clusterData{ readyCondition: observedReadyCondition.Status, }) return observedReadyCondition } curReadyCondition := meta.FindStatusCondition(cluster.Status.Conditions, clusterv1alpha1.ClusterConditionReady) if curReadyCondition == nil { return observedReadyCondition } now := time.Now() if saved.readyCondition != observedReadyCondition.Status { // ready condition status changed, record the threshold start time saved = &clusterData{ readyCondition: observedReadyCondition.Status, thresholdStartTime: now, } c.update(cluster.Name, saved) } if observedReadyCondition.Status != metav1.ConditionTrue && curReadyCondition.Status == metav1.ConditionTrue && now.Before(saved.thresholdStartTime.Add(c.failureThreshold)) { // retain old status until threshold exceeded to avoid network unstable problems. return curReadyCondition } return observedReadyCondition } func (c *clusterConditionStore) get(cluster string) *clusterData { condition, ok := c.clusterDataMap.Load(cluster) if !ok { return nil } return condition.(*clusterData) } func (c *clusterConditionStore) update(cluster string, data *clusterData) { // ready condition status changed, record the threshold start time c.clusterDataMap.Store(cluster, data) } func (c *clusterConditionStore) delete(cluster string) { c.clusterDataMap.Delete(cluster) }