1
16
17 package set
18
19 import (
20 "reflect"
21 "strings"
22 "testing"
23
24 "github.com/stretchr/testify/assert"
25 batchv1 "k8s.io/api/batch/v1"
26 "k8s.io/api/core/v1"
27 extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29 "k8s.io/apimachinery/pkg/runtime"
30 "k8s.io/cli-runtime/pkg/genericclioptions"
31 "k8s.io/cli-runtime/pkg/genericiooptions"
32 "k8s.io/cli-runtime/pkg/printers"
33 "k8s.io/cli-runtime/pkg/resource"
34 )
35
36 func TestUpdateSelectorForObjectTypes(t *testing.T) {
37 before := metav1.LabelSelector{MatchLabels: map[string]string{"fee": "true"},
38 MatchExpressions: []metav1.LabelSelectorRequirement{
39 {
40 Key: "foo",
41 Operator: metav1.LabelSelectorOpIn,
42 Values: []string{"on", "yes"},
43 },
44 }}
45
46 rc := v1.ReplicationController{}
47 ser := v1.Service{}
48 dep := extensionsv1beta1.Deployment{Spec: extensionsv1beta1.DeploymentSpec{Selector: &before}}
49 ds := extensionsv1beta1.DaemonSet{Spec: extensionsv1beta1.DaemonSetSpec{Selector: &before}}
50 rs := extensionsv1beta1.ReplicaSet{Spec: extensionsv1beta1.ReplicaSetSpec{Selector: &before}}
51 job := batchv1.Job{Spec: batchv1.JobSpec{Selector: &before}}
52 pvc := v1.PersistentVolumeClaim{Spec: v1.PersistentVolumeClaimSpec{Selector: &before}}
53 sa := v1.ServiceAccount{}
54 type args struct {
55 obj runtime.Object
56 selector metav1.LabelSelector
57 }
58 tests := []struct {
59 name string
60 args args
61 wantErr bool
62 }{
63 {name: "rc",
64 args: args{
65 obj: &rc,
66 selector: metav1.LabelSelector{},
67 },
68 wantErr: true,
69 },
70 {name: "ser",
71 args: args{
72 obj: &ser,
73 selector: metav1.LabelSelector{},
74 },
75 wantErr: false,
76 },
77 {name: "dep",
78 args: args{
79 obj: &dep,
80 selector: metav1.LabelSelector{},
81 },
82 wantErr: true,
83 },
84 {name: "ds",
85 args: args{
86 obj: &ds,
87 selector: metav1.LabelSelector{},
88 },
89 wantErr: true,
90 },
91 {name: "rs",
92 args: args{
93 obj: &rs,
94 selector: metav1.LabelSelector{},
95 },
96 wantErr: true,
97 },
98 {name: "job",
99 args: args{
100 obj: &job,
101 selector: metav1.LabelSelector{},
102 },
103 wantErr: true,
104 },
105 {name: "pvc - no updates",
106 args: args{
107 obj: &pvc,
108 selector: metav1.LabelSelector{},
109 },
110 wantErr: true,
111 },
112 {name: "sa - no selector",
113 args: args{
114 obj: &sa,
115 selector: metav1.LabelSelector{},
116 },
117 wantErr: true,
118 },
119 }
120 for _, tt := range tests {
121 if err := updateSelectorForObject(tt.args.obj, tt.args.selector); (err != nil) != tt.wantErr {
122 t.Errorf("%q. updateSelectorForObject() error = %v, wantErr %v", tt.name, err, tt.wantErr)
123 }
124 }
125 }
126
127 func TestUpdateNewSelectorValuesForObject(t *testing.T) {
128 ser := v1.Service{}
129 type args struct {
130 obj runtime.Object
131 selector metav1.LabelSelector
132 }
133 tests := []struct {
134 name string
135 args args
136 wantErr bool
137 }{
138 {name: "empty",
139 args: args{
140 obj: &ser,
141 selector: metav1.LabelSelector{
142 MatchLabels: map[string]string{},
143 MatchExpressions: []metav1.LabelSelectorRequirement{},
144 },
145 },
146 wantErr: false,
147 },
148 {name: "label-only",
149 args: args{
150 obj: &ser,
151 selector: metav1.LabelSelector{
152 MatchLabels: map[string]string{"b": "u"},
153 MatchExpressions: []metav1.LabelSelectorRequirement{},
154 },
155 },
156 wantErr: false,
157 },
158 }
159 for _, tt := range tests {
160 if err := updateSelectorForObject(tt.args.obj, tt.args.selector); (err != nil) != tt.wantErr {
161 t.Errorf("%q. updateSelectorForObject() error = %v, wantErr %v", tt.name, err, tt.wantErr)
162 }
163
164 assert.EqualValues(t, tt.args.selector.MatchLabels, ser.Spec.Selector, tt.name)
165
166 }
167 }
168
169 func TestUpdateOldSelectorValuesForObject(t *testing.T) {
170 ser := v1.Service{Spec: v1.ServiceSpec{Selector: map[string]string{"fee": "true"}}}
171 type args struct {
172 obj runtime.Object
173 selector metav1.LabelSelector
174 }
175 tests := []struct {
176 name string
177 args args
178 wantErr bool
179 }{
180 {name: "empty",
181 args: args{
182 obj: &ser,
183 selector: metav1.LabelSelector{
184 MatchLabels: map[string]string{},
185 MatchExpressions: []metav1.LabelSelectorRequirement{},
186 },
187 },
188 wantErr: false,
189 },
190 {name: "label-only",
191 args: args{
192 obj: &ser,
193 selector: metav1.LabelSelector{
194 MatchLabels: map[string]string{"fee": "false", "x": "y"},
195 MatchExpressions: []metav1.LabelSelectorRequirement{},
196 },
197 },
198 wantErr: false,
199 },
200 {name: "expr-only - err",
201 args: args{
202 obj: &ser,
203 selector: metav1.LabelSelector{
204 MatchLabels: map[string]string{},
205 MatchExpressions: []metav1.LabelSelectorRequirement{
206 {
207 Key: "a",
208 Operator: "In",
209 Values: []string{"x", "y"},
210 },
211 },
212 },
213 },
214 wantErr: true,
215 },
216 {name: "both - err",
217 args: args{
218 obj: &ser,
219 selector: metav1.LabelSelector{
220 MatchLabels: map[string]string{"b": "u"},
221 MatchExpressions: []metav1.LabelSelectorRequirement{
222 {
223 Key: "a",
224 Operator: "In",
225 Values: []string{"x", "y"},
226 },
227 },
228 },
229 },
230 wantErr: true,
231 },
232 }
233 for _, tt := range tests {
234 err := updateSelectorForObject(tt.args.obj, tt.args.selector)
235 if (err != nil) != tt.wantErr {
236 t.Errorf("%q. updateSelectorForObject() error = %v, wantErr %v", tt.name, err, tt.wantErr)
237 } else if !tt.wantErr {
238 assert.EqualValues(t, tt.args.selector.MatchLabels, ser.Spec.Selector, tt.name)
239 }
240 }
241 }
242
243 func TestGetResourcesAndSelector(t *testing.T) {
244 type args struct {
245 args []string
246 }
247 tests := []struct {
248 name string
249 args args
250 wantResources []string
251 wantSelector *metav1.LabelSelector
252 wantErr bool
253 }{
254 {
255 name: "basic match",
256 args: args{args: []string{"rc/foo", "healthy=true"}},
257 wantResources: []string{"rc/foo"},
258 wantErr: false,
259 wantSelector: &metav1.LabelSelector{
260 MatchLabels: map[string]string{"healthy": "true"},
261 MatchExpressions: []metav1.LabelSelectorRequirement{},
262 },
263 },
264 {
265 name: "basic expression",
266 args: args{args: []string{"rc/foo", "buildType notin (debug, test)"}},
267 wantResources: []string{"rc/foo"},
268 wantErr: false,
269 wantSelector: &metav1.LabelSelector{
270 MatchLabels: map[string]string{},
271 MatchExpressions: []metav1.LabelSelectorRequirement{
272 {
273 Key: "buildType",
274 Operator: "NotIn",
275 Values: []string{"debug", "test"},
276 },
277 },
278 },
279 },
280 {
281 name: "selector error",
282 args: args{args: []string{"rc/foo", "buildType notthis (debug, test)"}},
283 wantResources: []string{"rc/foo"},
284 wantErr: true,
285 wantSelector: &metav1.LabelSelector{
286 MatchLabels: map[string]string{},
287 MatchExpressions: []metav1.LabelSelectorRequirement{},
288 },
289 },
290 {
291 name: "no resource and selector",
292 args: args{args: []string{}},
293 wantResources: []string{},
294 wantErr: false,
295 wantSelector: nil,
296 },
297 }
298 for _, tt := range tests {
299 gotResources, gotSelector, err := getResourcesAndSelector(tt.args.args)
300 if err != nil {
301 if !tt.wantErr {
302 t.Errorf("%q. getResourcesAndSelector() error = %v, wantErr %v", tt.name, err, tt.wantErr)
303 }
304 continue
305 }
306 if !reflect.DeepEqual(gotResources, tt.wantResources) {
307 t.Errorf("%q. getResourcesAndSelector() gotResources = %v, want %v", tt.name, gotResources, tt.wantResources)
308 }
309 if !reflect.DeepEqual(gotSelector, tt.wantSelector) {
310 t.Errorf("%q. getResourcesAndSelector() gotSelector = %v, want %v", tt.name, gotSelector, tt.wantSelector)
311 }
312 }
313 }
314
315 func TestSelectorTest(t *testing.T) {
316 info := &resource.Info{
317 Object: &v1.Service{
318 TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Service"},
319 ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "cassandra"},
320 },
321 }
322
323 labelToSet, err := metav1.ParseToLabelSelector("environment=qa")
324 if err != nil {
325 t.Fatal(err)
326 }
327
328 iostreams, _, buf, _ := genericiooptions.NewTestIOStreams()
329 o := &SetSelectorOptions{
330 selector: labelToSet,
331 ResourceFinder: genericclioptions.NewSimpleFakeResourceFinder(info),
332 Recorder: genericclioptions.NoopRecorder{},
333 PrintObj: (&printers.NamePrinter{}).PrintObj,
334 IOStreams: iostreams,
335 }
336
337 if err := o.RunSelector(); err != nil {
338 t.Fatal(err)
339 }
340 if !strings.Contains(buf.String(), "service/cassandra") {
341 t.Errorf("did not set selector: %s", buf.String())
342 }
343 }
344
View as plain text