karmada/pkg/controllers/applicationfailover/common.go

104 lines
3.0 KiB
Go

package applicationfailover
import (
"sync"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
)
type workloadUnhealthyMap struct {
sync.RWMutex
// key is the NamespacedName of the binding
// value is also a map. Its key is the cluster where the unhealthy workload resides.
// Its value is the time when the unhealthy state was first observed.
workloadUnhealthy map[types.NamespacedName]map[string]metav1.Time
}
func newWorkloadUnhealthyMap() *workloadUnhealthyMap {
return &workloadUnhealthyMap{
workloadUnhealthy: make(map[types.NamespacedName]map[string]metav1.Time),
}
}
func (m *workloadUnhealthyMap) delete(key types.NamespacedName) {
m.Lock()
defer m.Unlock()
delete(m.workloadUnhealthy, key)
}
func (m *workloadUnhealthyMap) hasWorkloadBeenUnhealthy(key types.NamespacedName, cluster string) bool {
m.RLock()
defer m.RUnlock()
unhealthyClusters := m.workloadUnhealthy[key]
if unhealthyClusters == nil {
return false
}
_, exist := unhealthyClusters[cluster]
return exist
}
func (m *workloadUnhealthyMap) setTimeStamp(key types.NamespacedName, cluster string) {
m.Lock()
defer m.Unlock()
unhealthyClusters := m.workloadUnhealthy[key]
if unhealthyClusters == nil {
unhealthyClusters = make(map[string]metav1.Time)
}
unhealthyClusters[cluster] = metav1.Now()
m.workloadUnhealthy[key] = unhealthyClusters
}
func (m *workloadUnhealthyMap) getTimeStamp(key types.NamespacedName, cluster string) metav1.Time {
m.RLock()
defer m.RUnlock()
unhealthyClusters := m.workloadUnhealthy[key]
return unhealthyClusters[cluster]
}
func (m *workloadUnhealthyMap) deleteIrrelevantClusters(key types.NamespacedName, allClusters sets.Set[string], healthyClusters []string) {
m.Lock()
defer m.Unlock()
unhealthyClusters := m.workloadUnhealthy[key]
if unhealthyClusters == nil {
return
}
for cluster := range unhealthyClusters {
if !allClusters.Has(cluster) {
delete(unhealthyClusters, cluster)
}
}
for _, cluster := range healthyClusters {
delete(unhealthyClusters, cluster)
}
m.workloadUnhealthy[key] = unhealthyClusters
}
// distinguishUnhealthyClustersWithOthers distinguishes clusters which is in the unHealthy state(not in the process of eviction) with others.
func distinguishUnhealthyClustersWithOthers(aggregatedStatusItems []workv1alpha2.AggregatedStatusItem, resourceBindingSpec workv1alpha2.ResourceBindingSpec) ([]string, []string) {
var unhealthyClusters, others []string
for _, aggregatedStatusItem := range aggregatedStatusItems {
cluster := aggregatedStatusItem.ClusterName
if aggregatedStatusItem.Health == workv1alpha2.ResourceUnhealthy && !resourceBindingSpec.ClusterInGracefulEvictionTasks(cluster) {
unhealthyClusters = append(unhealthyClusters, cluster)
}
if aggregatedStatusItem.Health == workv1alpha2.ResourceHealthy || aggregatedStatusItem.Health == workv1alpha2.ResourceUnknown {
others = append(others, cluster)
}
}
return unhealthyClusters, others
}