1
16
17 package antiaffinity
18
19 import (
20 "context"
21 "testing"
22
23 v1 "k8s.io/api/core/v1"
24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25 "k8s.io/apimachinery/pkg/runtime"
26 "k8s.io/apiserver/pkg/admission"
27 api "k8s.io/kubernetes/pkg/apis/core"
28 )
29
30
31
32
33 func TestInterPodAffinityAdmission(t *testing.T) {
34 handler := NewInterPodAntiAffinity()
35 pod := api.Pod{
36 Spec: api.PodSpec{},
37 }
38 tests := []struct {
39 affinity *api.Affinity
40 errorExpected bool
41 }{
42
43 {
44 affinity: &api.Affinity{},
45 errorExpected: false,
46 },
47
48 {
49 affinity: &api.Affinity{
50 PodAntiAffinity: &api.PodAntiAffinity{
51 PreferredDuringSchedulingIgnoredDuringExecution: []api.WeightedPodAffinityTerm{
52 {
53 Weight: 5,
54 PodAffinityTerm: api.PodAffinityTerm{
55 LabelSelector: &metav1.LabelSelector{
56 MatchExpressions: []metav1.LabelSelectorRequirement{
57 {
58 Key: "security",
59 Operator: metav1.LabelSelectorOpIn,
60 Values: []string{"S2"},
61 },
62 },
63 },
64 TopologyKey: "az",
65 },
66 },
67 },
68 },
69 },
70 errorExpected: false,
71 },
72
73
74 {
75 affinity: &api.Affinity{
76 PodAntiAffinity: &api.PodAntiAffinity{
77 PreferredDuringSchedulingIgnoredDuringExecution: []api.WeightedPodAffinityTerm{
78 {
79 Weight: 5,
80 PodAffinityTerm: api.PodAffinityTerm{
81 LabelSelector: &metav1.LabelSelector{
82 MatchExpressions: []metav1.LabelSelectorRequirement{
83 {
84 Key: "security",
85 Operator: metav1.LabelSelectorOpIn,
86 Values: []string{"S2"},
87 },
88 },
89 },
90 TopologyKey: "az",
91 },
92 },
93 },
94 RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
95 {
96 LabelSelector: &metav1.LabelSelector{
97 MatchExpressions: []metav1.LabelSelectorRequirement{
98 {
99 Key: "security",
100 Operator: metav1.LabelSelectorOpIn,
101 Values: []string{"S2"},
102 },
103 },
104 },
105 TopologyKey: v1.LabelHostname,
106 },
107 },
108 },
109 },
110 errorExpected: false,
111 },
112
113 {
114 affinity: &api.Affinity{
115 PodAntiAffinity: &api.PodAntiAffinity{
116 RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
117 {
118 LabelSelector: &metav1.LabelSelector{
119 MatchExpressions: []metav1.LabelSelectorRequirement{
120 {
121 Key: "security",
122 Operator: metav1.LabelSelectorOpIn,
123 Values: []string{"S2"},
124 },
125 },
126 },
127 TopologyKey: v1.LabelHostname,
128 },
129 },
130 },
131 },
132 errorExpected: false,
133 },
134
135 {
136 affinity: &api.Affinity{
137 PodAntiAffinity: &api.PodAntiAffinity{
138 RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
139 {
140 LabelSelector: &metav1.LabelSelector{
141 MatchExpressions: []metav1.LabelSelectorRequirement{
142 {
143 Key: "security",
144 Operator: metav1.LabelSelectorOpIn,
145 Values: []string{"S2"},
146 },
147 },
148 },
149 TopologyKey: " zone ",
150 },
151 },
152 },
153 },
154 errorExpected: true,
155 },
156
157 {
158 affinity: &api.Affinity{
159 PodAntiAffinity: &api.PodAntiAffinity{
160 RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
161 {
162 LabelSelector: &metav1.LabelSelector{
163 MatchExpressions: []metav1.LabelSelectorRequirement{
164 {
165 Key: "security",
166 Operator: metav1.LabelSelectorOpIn,
167 Values: []string{"S2"},
168 },
169 },
170 },
171 TopologyKey: v1.LabelHostname,
172 }, {
173 LabelSelector: &metav1.LabelSelector{
174 MatchExpressions: []metav1.LabelSelectorRequirement{
175 {
176 Key: "security",
177 Operator: metav1.LabelSelectorOpIn,
178 Values: []string{"S2"},
179 },
180 },
181 },
182 TopologyKey: " zone ",
183 }, {
184 LabelSelector: &metav1.LabelSelector{
185 MatchExpressions: []metav1.LabelSelectorRequirement{
186 {
187 Key: "security",
188 Operator: metav1.LabelSelectorOpIn,
189 Values: []string{"S2"},
190 },
191 },
192 },
193 TopologyKey: v1.LabelHostname,
194 },
195 },
196 },
197 },
198 errorExpected: true,
199 },
200 }
201 for _, test := range tests {
202 pod.Spec.Affinity = test.affinity
203 err := handler.Validate(context.TODO(), admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil, false, nil), nil)
204
205 if test.errorExpected && err == nil {
206 t.Errorf("Expected error for Anti Affinity %+v but did not get an error", test.affinity)
207 }
208
209 if !test.errorExpected && err != nil {
210 t.Errorf("Unexpected error %v for AntiAffinity %+v", err, test.affinity)
211 }
212 }
213 }
214 func TestHandles(t *testing.T) {
215 handler := NewInterPodAntiAffinity()
216 tests := map[admission.Operation]bool{
217 admission.Update: true,
218 admission.Create: true,
219 admission.Delete: false,
220 admission.Connect: false,
221 }
222 for op, expected := range tests {
223 result := handler.Handles(op)
224 if result != expected {
225 t.Errorf("Unexpected result for operation %s: %v\n", op, result)
226 }
227 }
228 }
229
230
231
232 func TestOtherResources(t *testing.T) {
233 namespace := "testnamespace"
234 name := "testname"
235 pod := &api.Pod{
236 ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace},
237 }
238 tests := []struct {
239 name string
240 kind string
241 resource string
242 subresource string
243 object runtime.Object
244 expectError bool
245 }{
246 {
247 name: "non-pod resource",
248 kind: "Foo",
249 resource: "foos",
250 object: pod,
251 },
252 {
253 name: "pod subresource",
254 kind: "Pod",
255 resource: "pods",
256 subresource: "eviction",
257 object: pod,
258 },
259 {
260 name: "non-pod object",
261 kind: "Pod",
262 resource: "pods",
263 object: &api.Service{},
264 expectError: true,
265 },
266 }
267
268 for _, tc := range tests {
269 handler := &Plugin{}
270
271 err := handler.Validate(context.TODO(), admission.NewAttributesRecord(tc.object, nil, api.Kind(tc.kind).WithVersion("version"), namespace, name, api.Resource(tc.resource).WithVersion("version"), tc.subresource, admission.Create, &metav1.CreateOptions{}, false, nil), nil)
272
273 if tc.expectError {
274 if err == nil {
275 t.Errorf("%s: unexpected nil error", tc.name)
276 }
277 continue
278 }
279
280 if err != nil {
281 t.Errorf("%s: unexpected error: %v", tc.name, err)
282 continue
283 }
284 }
285 }
286
View as plain text