tolerations.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  2. Copyright 2017 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package tolerations
  14. import (
  15. apiequality "k8s.io/apimachinery/pkg/api/equality"
  16. "k8s.io/klog"
  17. api "k8s.io/kubernetes/pkg/apis/core"
  18. )
  19. // VerifyAgainstWhitelist checks if the provided tolerations
  20. // satisfy the provided whitelist and returns true, otherwise returns false
  21. func VerifyAgainstWhitelist(tolerations, whitelist []api.Toleration) bool {
  22. if len(whitelist) == 0 || len(tolerations) == 0 {
  23. return true
  24. }
  25. next:
  26. for _, t := range tolerations {
  27. for _, w := range whitelist {
  28. if isSuperset(w, t) {
  29. continue next
  30. }
  31. }
  32. return false
  33. }
  34. return true
  35. }
  36. // MergeTolerations merges two sets of tolerations into one. If one toleration is a superset of
  37. // another, only the superset is kept.
  38. func MergeTolerations(first, second []api.Toleration) []api.Toleration {
  39. all := append(first, second...)
  40. var merged []api.Toleration
  41. next:
  42. for i, t := range all {
  43. for _, t2 := range merged {
  44. if isSuperset(t2, t) {
  45. continue next // t is redundant; ignore it
  46. }
  47. }
  48. if i+1 < len(all) {
  49. for _, t2 := range all[i+1:] {
  50. // If the tolerations are equal, prefer the first.
  51. if !apiequality.Semantic.DeepEqual(&t, &t2) && isSuperset(t2, t) {
  52. continue next // t is redundant; ignore it
  53. }
  54. }
  55. }
  56. merged = append(merged, t)
  57. }
  58. return merged
  59. }
  60. // isSuperset checks whether ss tolerates a superset of t.
  61. func isSuperset(ss, t api.Toleration) bool {
  62. if apiequality.Semantic.DeepEqual(&t, &ss) {
  63. return true
  64. }
  65. if t.Key != ss.Key &&
  66. // An empty key with Exists operator means match all keys & values.
  67. (ss.Key != "" || ss.Operator != api.TolerationOpExists) {
  68. return false
  69. }
  70. // An empty effect means match all effects.
  71. if t.Effect != ss.Effect && ss.Effect != "" {
  72. return false
  73. }
  74. if ss.Effect == api.TaintEffectNoExecute {
  75. if ss.TolerationSeconds != nil {
  76. if t.TolerationSeconds == nil ||
  77. *t.TolerationSeconds > *ss.TolerationSeconds {
  78. return false
  79. }
  80. }
  81. }
  82. switch ss.Operator {
  83. case api.TolerationOpEqual, "": // empty operator means Equal
  84. return t.Operator == api.TolerationOpEqual && t.Value == ss.Value
  85. case api.TolerationOpExists:
  86. return true
  87. default:
  88. klog.Errorf("Unknown toleration operator: %s", ss.Operator)
  89. return false
  90. }
  91. }