@@ -17,114 +17,91 @@ limitations under the License.
17
17
package tolerations
18
18
19
19
import (
20
+ apiequality "k8s.io/apimachinery/pkg/api/equality"
21
+ "k8s.io/klog"
20
22
api "k8s.io/kubernetes/pkg/apis/core"
21
23
)
22
24
23
- type key struct {
24
- tolerationKey string
25
- effect api.TaintEffect
26
- }
27
-
28
- func convertTolerationToKey (in api.Toleration ) key {
29
- return key {in .Key , in .Effect }
30
- }
31
-
32
25
// VerifyAgainstWhitelist checks if the provided tolerations
33
26
// satisfy the provided whitelist and returns true, otherwise returns false
34
- func VerifyAgainstWhitelist (tolerations []api. Toleration , whitelist []api.Toleration ) bool {
35
- if len (whitelist ) == 0 {
27
+ func VerifyAgainstWhitelist (tolerations , whitelist []api.Toleration ) bool {
28
+ if len (whitelist ) == 0 || len ( tolerations ) == 0 {
36
29
return true
37
30
}
38
31
39
- t := ConvertTolerationToAMap ( tolerations )
40
- w := ConvertTolerationToAMap ( whitelist )
41
-
42
- for k1 , v1 := range t {
43
- if v2 , ok := w [ k1 ]; ! ok || ! AreEqual ( v1 , v2 ) {
44
- return false
32
+ next:
33
+ for _ , t := range tolerations {
34
+ for _ , w := range whitelist {
35
+ if isSuperset ( w , t ) {
36
+ continue next
37
+ }
45
38
}
39
+ return false
46
40
}
41
+
47
42
return true
48
43
}
49
44
50
- // IsConflict returns true if the key of two tolerations match
51
- // but one or more other fields differ, otherwise returns false
52
- func IsConflict (first []api.Toleration , second []api.Toleration ) bool {
53
- firstMap := ConvertTolerationToAMap (first )
54
- secondMap := ConvertTolerationToAMap (second )
55
-
56
- for k1 , v1 := range firstMap {
57
- if v2 , ok := secondMap [k1 ]; ok && ! AreEqual (v1 , v2 ) {
58
- return true
45
+ // MergeTolerations merges two sets of tolerations into one. If one toleration is a superset of
46
+ // another, only the superset is kept.
47
+ func MergeTolerations (first , second []api.Toleration ) []api.Toleration {
48
+ all := append (first , second ... )
49
+ var merged []api.Toleration
50
+
51
+ next:
52
+ for i , t := range all {
53
+ for _ , t2 := range merged {
54
+ if isSuperset (t2 , t ) {
55
+ continue next // t is redundant; ignore it
56
+ }
59
57
}
60
- }
61
- return false
62
- }
63
-
64
- // MergeTolerations merges two sets of tolerations into one
65
- // it does not check for conflicts
66
- func MergeTolerations (first []api.Toleration , second []api.Toleration ) []api.Toleration {
67
- var mergedTolerations []api.Toleration
68
- mergedTolerations = append (mergedTolerations , second ... )
69
- firstMap := ConvertTolerationToAMap (first )
70
- secondMap := ConvertTolerationToAMap (second )
71
- // preserve order of first when merging
72
- for _ , v := range first {
73
- k := convertTolerationToKey (v )
74
- // if first contains key conflicts, the last one takes precedence
75
- if _ , ok := secondMap [k ]; ! ok && firstMap [k ] == v {
76
- mergedTolerations = append (mergedTolerations , v )
58
+ if i + 1 < len (all ) {
59
+ for _ , t2 := range all [i + 1 :] {
60
+ // If the tolerations are equal, prefer the first.
61
+ if ! apiequality .Semantic .DeepEqual (& t , & t2 ) && isSuperset (t2 , t ) {
62
+ continue next // t is redundant; ignore it
63
+ }
64
+ }
77
65
}
66
+ merged = append (merged , t )
78
67
}
79
- return mergedTolerations
68
+
69
+ return merged
80
70
}
81
71
82
- // EqualTolerations returns true if two sets of tolerations are equal, otherwise false
83
- // it assumes no duplicates in individual set of tolerations
84
- func EqualTolerations (first []api.Toleration , second []api.Toleration ) bool {
85
- if len (first ) != len (second ) {
86
- return false
72
+ // isSuperset checks whether ss tolerates a superset of t.
73
+ func isSuperset (ss , t api.Toleration ) bool {
74
+ if apiequality .Semantic .DeepEqual (& t , & ss ) {
75
+ return true
87
76
}
88
77
89
- firstMap := ConvertTolerationToAMap (first )
90
- secondMap := ConvertTolerationToAMap (second )
91
-
92
- for k1 , v1 := range firstMap {
93
- if v2 , ok := secondMap [k1 ]; ! ok || ! AreEqual (v1 , v2 ) {
94
- return false
95
- }
78
+ if t .Key != ss .Key &&
79
+ // An empty key with Exists operator means match all keys & values.
80
+ (ss .Key != "" || ss .Operator != api .TolerationOpExists ) {
81
+ return false
96
82
}
97
- return true
98
- }
99
83
100
- // ConvertTolerationToAMap converts toleration list into a map[string]api.Toleration
101
- func ConvertTolerationToAMap (in []api.Toleration ) map [key ]api.Toleration {
102
- out := map [key ]api.Toleration {}
103
- for _ , v := range in {
104
- out [convertTolerationToKey (v )] = v
84
+ // An empty effect means match all effects.
85
+ if t .Effect != ss .Effect && ss .Effect != "" {
86
+ return false
105
87
}
106
- return out
107
- }
108
88
109
- // AreEqual checks if two provided tolerations are equal or not.
110
- func AreEqual (first , second api.Toleration ) bool {
111
- if first .Key == second .Key &&
112
- first .Operator == second .Operator &&
113
- first .Value == second .Value &&
114
- first .Effect == second .Effect &&
115
- AreTolerationSecondsEqual (first .TolerationSeconds , second .TolerationSeconds ) {
116
- return true
89
+ if ss .Effect == api .TaintEffectNoExecute {
90
+ if ss .TolerationSeconds != nil {
91
+ if t .TolerationSeconds == nil ||
92
+ * t .TolerationSeconds > * ss .TolerationSeconds {
93
+ return false
94
+ }
95
+ }
117
96
}
118
- return false
119
- }
120
97
121
- // AreTolerationSecondsEqual checks if two provided TolerationSeconds are equal or not.
122
- func AreTolerationSecondsEqual (ts1 , ts2 * int64 ) bool {
123
- if ts1 == ts2 {
124
- return true
125
- }
126
- if ts1 != nil && ts2 != nil && * ts1 == * ts2 {
98
+ switch ss .Operator {
99
+ case api .TolerationOpEqual , "" : // empty operator means Equal
100
+ return t .Operator == api .TolerationOpEqual && t .Value == ss .Value
101
+ case api .TolerationOpExists :
127
102
return true
103
+ default :
104
+ klog .Errorf ("Unknown toleration operator: %s" , ss .Operator )
105
+ return false
128
106
}
129
- return false
130
107
}
0 commit comments