/
override_policy_templatemanager.go
153 lines (128 loc) · 3.54 KB
/
override_policy_templatemanager.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package templatemanager
import (
"bytes"
"encoding/json"
"text/template"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
policyv1alpha1 "github.com/k-cloud-labs/pkg/apis/policy/v1alpha1"
"github.com/k-cloud-labs/pkg/utils/interrupter/model"
)
// NewOverrideTemplateManager init override policy template manager.
func NewOverrideTemplateManager(ts *TemplateSource) (TemplateManager, error) {
t, err := NewTemplateManager(ts,
template.FuncMap{
"marshal": func(v interface{}) string {
buf := &bytes.Buffer{}
en := json.NewEncoder(buf)
if err := en.Encode(v); err != nil {
return ""
}
return buf.String()
},
"isValidOp": func(v interface{}) bool {
rule, ok := v.(*model.OverridePolicyRenderData)
if !ok {
return false
}
return validateOp(rule)
},
"convertQuantity": func(v interface{}) int64 {
q, ok := v.(resource.Quantity)
if !ok {
return 0
}
return q.Value()
},
// only support string map
"isMap": func(v interface{}) bool {
_, ok := v.(map[string]string)
return ok
},
// convert to map
"convertToMap": func(v interface{}) map[string]string {
m, ok := v.(map[string]string)
if ok {
return m
}
return map[string]string{}
},
})
if err != nil {
return nil, err
}
return t, nil
}
func validateOp(rule *model.OverridePolicyRenderData) bool {
switch rule.Type {
case policyv1alpha1.OverrideRuleTypeAnnotations:
return true
case policyv1alpha1.OverrideRuleTypeLabels:
return true
case policyv1alpha1.OverrideRuleTypeResourcesOversell:
return rule.ResourcesOversell != nil
case policyv1alpha1.OverrideRuleTypeResources:
return rule.Resources != nil
case policyv1alpha1.OverrideRuleTypeTolerations:
return true
case policyv1alpha1.OverrideRuleTypeAffinity:
return validateAffinity(rule)
}
return false
}
func validateAffinity(rule *model.OverridePolicyRenderData) bool {
a := rule.Affinity
if a == nil {
return false
}
if a.NodeAffinity == nil && a.PodAffinity == nil && a.PodAntiAffinity == nil {
return false
}
return isNodeAffinityValid(a.NodeAffinity) || isPodAffinityValid(a.PodAffinity) || isPodAntiAffinityValid(a.PodAntiAffinity)
}
func isNodeAffinityValid(na *corev1.NodeAffinity) bool {
if na == nil {
return false
}
isRequireValid := func(req *corev1.NodeSelector) bool {
if req == nil {
return false
}
if len(na.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms) == 0 {
return false
}
for _, term := range na.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms {
if len(term.MatchExpressions) > 0 || len(term.MatchFields) > 0 {
return true
}
}
return false
}
isPreferredValid := func(list []corev1.PreferredSchedulingTerm) bool {
if len(list) == 0 {
return false
}
for _, term := range list {
if len(term.Preference.MatchExpressions) > 0 || len(term.Preference.MatchFields) > 0 {
return true
}
}
return false
}
return isRequireValid(na.RequiredDuringSchedulingIgnoredDuringExecution) ||
isPreferredValid(na.PreferredDuringSchedulingIgnoredDuringExecution)
}
func isPodAffinityValid(pa *corev1.PodAffinity) bool {
if pa == nil {
return false
}
return len(pa.RequiredDuringSchedulingIgnoredDuringExecution) > 0 ||
len(pa.PreferredDuringSchedulingIgnoredDuringExecution) > 0
}
func isPodAntiAffinityValid(pa *corev1.PodAntiAffinity) bool {
if pa == nil {
return false
}
return len(pa.RequiredDuringSchedulingIgnoredDuringExecution) > 0 ||
len(pa.PreferredDuringSchedulingIgnoredDuringExecution) > 0
}