196 lines
5.7 KiB
Go
196 lines
5.7 KiB
Go
package helper
|
|
|
|
import (
|
|
"time"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
|
|
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
|
)
|
|
|
|
// TaintExists checks if the given taint exists in list of taints. Returns true if exists false otherwise.
|
|
func TaintExists(taints []corev1.Taint, taintToFind *corev1.Taint) bool {
|
|
for _, taint := range taints {
|
|
if taint.MatchTaint(taintToFind) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// TolerationExists checks if the given toleration exists in list of tolerations. Returns true if exists false otherwise.
|
|
func TolerationExists(tolerations []corev1.Toleration, tolerationToFind *corev1.Toleration) bool {
|
|
for _, toleration := range tolerations {
|
|
if toleration.MatchToleration(tolerationToFind) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// SetCurrentClusterTaints sets current cluster taints which need to be updated.
|
|
func SetCurrentClusterTaints(taintsToAdd, taintsToRemove []*corev1.Taint, cluster *clusterv1alpha1.Cluster) []corev1.Taint {
|
|
taints := cluster.Spec.Taints
|
|
|
|
var clusterTaintsToAdd, clusterTaintsToRemove []corev1.Taint
|
|
// Find which taints need to be added.
|
|
for _, taintToAdd := range taintsToAdd {
|
|
if !TaintExists(taints, taintToAdd) {
|
|
clusterTaintsToAdd = append(clusterTaintsToAdd, *taintToAdd)
|
|
}
|
|
}
|
|
// Find which taints need to be removed.
|
|
for _, taintToRemove := range taintsToRemove {
|
|
if TaintExists(taints, taintToRemove) {
|
|
clusterTaintsToRemove = append(clusterTaintsToRemove, *taintToRemove)
|
|
}
|
|
}
|
|
// If no taints need to be added and removed, just return.
|
|
if len(clusterTaintsToAdd) == 0 && len(clusterTaintsToRemove) == 0 {
|
|
return taints
|
|
}
|
|
|
|
taints = make([]corev1.Taint, 0, len(taints)+len(clusterTaintsToAdd)-len(clusterTaintsToRemove))
|
|
// Remove taints which need to be removed.
|
|
for i := range cluster.Spec.Taints {
|
|
if !TaintExists(clusterTaintsToRemove, &cluster.Spec.Taints[i]) {
|
|
taints = append(taints, cluster.Spec.Taints[i])
|
|
}
|
|
}
|
|
|
|
// Add taints.
|
|
for _, taintToAdd := range clusterTaintsToAdd {
|
|
now := metav1.Now()
|
|
taintToAdd.TimeAdded = &now
|
|
taints = append(taints, taintToAdd)
|
|
}
|
|
|
|
return taints
|
|
}
|
|
|
|
// AddTolerations add some tolerations if not existed.
|
|
func AddTolerations(placement *policyv1alpha1.Placement, tolerationsToAdd ...*corev1.Toleration) {
|
|
for _, tolerationToAdd := range tolerationsToAdd {
|
|
if !TolerationExists(placement.ClusterTolerations, tolerationToAdd) {
|
|
placement.ClusterTolerations = append(placement.ClusterTolerations, *tolerationToAdd)
|
|
}
|
|
}
|
|
}
|
|
|
|
// HasNoExecuteTaints check if NoExecute taints exist.
|
|
func HasNoExecuteTaints(taints []corev1.Taint) bool {
|
|
for i := range taints {
|
|
if taints[i].Effect == corev1.TaintEffectNoExecute {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// GetNoExecuteTaints will get all NoExecute taints.
|
|
func GetNoExecuteTaints(taints []corev1.Taint) []corev1.Taint {
|
|
var result []corev1.Taint
|
|
for i := range taints {
|
|
if taints[i].Effect == corev1.TaintEffectNoExecute {
|
|
result = append(result, taints[i])
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// GetMinTolerationTime returns minimal toleration time from the given slice, or -1 if it's infinite.
|
|
func GetMinTolerationTime(noExecuteTaints []corev1.Taint, usedTolerations []corev1.Toleration) time.Duration {
|
|
if len(noExecuteTaints) == 0 {
|
|
return -1
|
|
}
|
|
if len(usedTolerations) == 0 {
|
|
return 0
|
|
}
|
|
|
|
// Get all trigger time.
|
|
var triggerTimes []time.Time
|
|
for i := range usedTolerations {
|
|
if usedTolerations[i].TolerationSeconds == nil {
|
|
continue
|
|
}
|
|
tolerationSeconds := *(usedTolerations[i].TolerationSeconds)
|
|
for j := range noExecuteTaints {
|
|
// should not happen
|
|
if noExecuteTaints[j].TimeAdded == nil {
|
|
continue
|
|
}
|
|
timeAdded := *noExecuteTaints[j].TimeAdded
|
|
if usedTolerations[i].ToleratesTaint(&noExecuteTaints[j]) {
|
|
triggerTimes = append(triggerTimes, timeAdded.Add(time.Duration(tolerationSeconds)*time.Second))
|
|
}
|
|
}
|
|
}
|
|
|
|
// If triggerTimes is empty, it means all taints would be tolerated forever.
|
|
if len(triggerTimes) == 0 {
|
|
return -1
|
|
}
|
|
|
|
// Find the latest trigger time.
|
|
t := triggerTimes[0]
|
|
for i := 1; i < len(triggerTimes); i++ {
|
|
if triggerTimes[i].Before(t) {
|
|
t = triggerTimes[i]
|
|
}
|
|
}
|
|
|
|
// If trigger time is up, don't tolerate.
|
|
if t.Before(time.Now()) {
|
|
return 0
|
|
}
|
|
|
|
return time.Until(t)
|
|
}
|
|
|
|
// GetMatchingTolerations returns true and list of Tolerations matching all Taints if all are tolerated, or false otherwise.
|
|
func GetMatchingTolerations(taints []corev1.Taint, tolerations []corev1.Toleration) (bool, []corev1.Toleration) {
|
|
if len(taints) == 0 {
|
|
return true, []corev1.Toleration{}
|
|
}
|
|
if len(tolerations) == 0 && len(taints) > 0 {
|
|
return false, []corev1.Toleration{}
|
|
}
|
|
var result []corev1.Toleration
|
|
for i := range taints {
|
|
tolerated := false
|
|
for j := range tolerations {
|
|
if tolerations[j].ToleratesTaint(&taints[i]) {
|
|
result = append(result, tolerations[j])
|
|
tolerated = true
|
|
break
|
|
}
|
|
}
|
|
if !tolerated {
|
|
return false, []corev1.Toleration{}
|
|
}
|
|
}
|
|
return true, result
|
|
}
|
|
|
|
// NewNotReadyToleration returns a default not ready toleration.
|
|
func NewNotReadyToleration(tolerationSeconds int64) *corev1.Toleration {
|
|
return &corev1.Toleration{
|
|
Key: clusterv1alpha1.TaintClusterNotReady,
|
|
Operator: corev1.TolerationOpExists,
|
|
Effect: corev1.TaintEffectNoExecute,
|
|
TolerationSeconds: &tolerationSeconds,
|
|
}
|
|
}
|
|
|
|
// NewUnreachableToleration returns a default unreachable toleration.
|
|
func NewUnreachableToleration(tolerationSeconds int64) *corev1.Toleration {
|
|
return &corev1.Toleration{
|
|
Key: clusterv1alpha1.TaintClusterUnreachable,
|
|
Operator: corev1.TolerationOpExists,
|
|
Effect: corev1.TaintEffectNoExecute,
|
|
TolerationSeconds: &tolerationSeconds,
|
|
}
|
|
}
|