1/*
2Copyright 2016 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package statefulset
18
19import (
20	"bytes"
21	"encoding/json"
22	"sort"
23	"testing"
24
25	apps "k8s.io/api/apps/v1"
26	v1 "k8s.io/api/core/v1"
27	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28	"k8s.io/apimachinery/pkg/runtime"
29	"k8s.io/apimachinery/pkg/types"
30	"k8s.io/apimachinery/pkg/util/sets"
31	"k8s.io/client-go/informers"
32	"k8s.io/client-go/kubernetes/fake"
33	"k8s.io/client-go/tools/cache"
34	"k8s.io/client-go/tools/record"
35	"k8s.io/kubernetes/pkg/controller"
36	"k8s.io/kubernetes/pkg/controller/history"
37)
38
39var parentKind = apps.SchemeGroupVersion.WithKind("StatefulSet")
40
41func alwaysReady() bool { return true }
42
43func TestStatefulSetControllerCreates(t *testing.T) {
44	set := newStatefulSet(3)
45	ssc, spc, _ := newFakeStatefulSetController(set)
46	if err := scaleUpStatefulSetController(set, ssc, spc); err != nil {
47		t.Errorf("Failed to turn up StatefulSet : %s", err)
48	}
49	if obj, _, err := spc.setsIndexer.Get(set); err != nil {
50		t.Error(err)
51	} else {
52		set = obj.(*apps.StatefulSet)
53	}
54	if set.Status.Replicas != 3 {
55		t.Errorf("set.Status.Replicas = %v; want 3", set.Status.Replicas)
56	}
57}
58
59func TestStatefulSetControllerDeletes(t *testing.T) {
60	set := newStatefulSet(3)
61	ssc, spc, _ := newFakeStatefulSetController(set)
62	if err := scaleUpStatefulSetController(set, ssc, spc); err != nil {
63		t.Errorf("Failed to turn up StatefulSet : %s", err)
64	}
65	if obj, _, err := spc.setsIndexer.Get(set); err != nil {
66		t.Error(err)
67	} else {
68		set = obj.(*apps.StatefulSet)
69	}
70	if set.Status.Replicas != 3 {
71		t.Errorf("set.Status.Replicas = %v; want 3", set.Status.Replicas)
72	}
73	*set.Spec.Replicas = 0
74	if err := scaleDownStatefulSetController(set, ssc, spc); err != nil {
75		t.Errorf("Failed to turn down StatefulSet : %s", err)
76	}
77	if obj, _, err := spc.setsIndexer.Get(set); err != nil {
78		t.Error(err)
79	} else {
80		set = obj.(*apps.StatefulSet)
81	}
82	if set.Status.Replicas != 0 {
83		t.Errorf("set.Status.Replicas = %v; want 0", set.Status.Replicas)
84	}
85}
86
87func TestStatefulSetControllerRespectsTermination(t *testing.T) {
88	set := newStatefulSet(3)
89	ssc, spc, _ := newFakeStatefulSetController(set)
90	if err := scaleUpStatefulSetController(set, ssc, spc); err != nil {
91		t.Errorf("Failed to turn up StatefulSet : %s", err)
92	}
93	if obj, _, err := spc.setsIndexer.Get(set); err != nil {
94		t.Error(err)
95	} else {
96		set = obj.(*apps.StatefulSet)
97	}
98	if set.Status.Replicas != 3 {
99		t.Errorf("set.Status.Replicas = %v; want 3", set.Status.Replicas)
100	}
101	_, err := spc.addTerminatingPod(set, 3)
102	if err != nil {
103		t.Error(err)
104	}
105	pods, err := spc.addTerminatingPod(set, 4)
106	if err != nil {
107		t.Error(err)
108	}
109	ssc.syncStatefulSet(set, pods)
110	selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
111	if err != nil {
112		t.Error(err)
113	}
114	pods, err = spc.podsLister.Pods(set.Namespace).List(selector)
115	if err != nil {
116		t.Error(err)
117	}
118	if len(pods) != 5 {
119		t.Error("StatefulSet does not respect termination")
120	}
121	sort.Sort(ascendingOrdinal(pods))
122	spc.DeleteStatefulPod(set, pods[3])
123	spc.DeleteStatefulPod(set, pods[4])
124	*set.Spec.Replicas = 0
125	if err := scaleDownStatefulSetController(set, ssc, spc); err != nil {
126		t.Errorf("Failed to turn down StatefulSet : %s", err)
127	}
128	if obj, _, err := spc.setsIndexer.Get(set); err != nil {
129		t.Error(err)
130	} else {
131		set = obj.(*apps.StatefulSet)
132	}
133	if set.Status.Replicas != 0 {
134		t.Errorf("set.Status.Replicas = %v; want 0", set.Status.Replicas)
135	}
136}
137
138func TestStatefulSetControllerBlocksScaling(t *testing.T) {
139	set := newStatefulSet(3)
140	ssc, spc, _ := newFakeStatefulSetController(set)
141	if err := scaleUpStatefulSetController(set, ssc, spc); err != nil {
142		t.Errorf("Failed to turn up StatefulSet : %s", err)
143	}
144	if obj, _, err := spc.setsIndexer.Get(set); err != nil {
145		t.Error(err)
146	} else {
147		set = obj.(*apps.StatefulSet)
148	}
149	if set.Status.Replicas != 3 {
150		t.Errorf("set.Status.Replicas = %v; want 3", set.Status.Replicas)
151	}
152	*set.Spec.Replicas = 5
153	fakeResourceVersion(set)
154	spc.setsIndexer.Update(set)
155	_, err := spc.setPodTerminated(set, 0)
156	if err != nil {
157		t.Error("Failed to set pod terminated at ordinal 0")
158	}
159	ssc.enqueueStatefulSet(set)
160	fakeWorker(ssc)
161	selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
162	if err != nil {
163		t.Error(err)
164	}
165	pods, err := spc.podsLister.Pods(set.Namespace).List(selector)
166	if err != nil {
167		t.Error(err)
168	}
169	if len(pods) != 3 {
170		t.Error("StatefulSet does not block scaling")
171	}
172	sort.Sort(ascendingOrdinal(pods))
173	spc.DeleteStatefulPod(set, pods[0])
174	ssc.enqueueStatefulSet(set)
175	fakeWorker(ssc)
176	pods, err = spc.podsLister.Pods(set.Namespace).List(selector)
177	if err != nil {
178		t.Error(err)
179	}
180	if len(pods) != 3 {
181		t.Error("StatefulSet does not resume when terminated Pod is removed")
182	}
183}
184
185func TestStatefulSetControllerDeletionTimestamp(t *testing.T) {
186	set := newStatefulSet(3)
187	set.DeletionTimestamp = new(metav1.Time)
188	ssc, spc, _ := newFakeStatefulSetController(set)
189
190	spc.setsIndexer.Add(set)
191
192	// Force a sync. It should not try to create any Pods.
193	ssc.enqueueStatefulSet(set)
194	fakeWorker(ssc)
195
196	selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
197	if err != nil {
198		t.Fatal(err)
199	}
200	pods, err := spc.podsLister.Pods(set.Namespace).List(selector)
201	if err != nil {
202		t.Fatal(err)
203	}
204	if got, want := len(pods), 0; got != want {
205		t.Errorf("len(pods) = %v, want %v", got, want)
206	}
207}
208
209func TestStatefulSetControllerDeletionTimestampRace(t *testing.T) {
210	set := newStatefulSet(3)
211	// The bare client says it IS deleted.
212	set.DeletionTimestamp = new(metav1.Time)
213	ssc, spc, ssh := newFakeStatefulSetController(set)
214
215	// The lister (cache) says it's NOT deleted.
216	set2 := *set
217	set2.DeletionTimestamp = nil
218	spc.setsIndexer.Add(&set2)
219
220	// The recheck occurs in the presence of a matching orphan.
221	pod := newStatefulSetPod(set, 1)
222	pod.OwnerReferences = nil
223	spc.podsIndexer.Add(pod)
224	set.Status.CollisionCount = new(int32)
225	revision, err := newRevision(set, 1, set.Status.CollisionCount)
226	if err != nil {
227		t.Fatal(err)
228	}
229	revision.OwnerReferences = nil
230	_, err = ssh.CreateControllerRevision(set, revision, set.Status.CollisionCount)
231	if err != nil {
232		t.Fatal(err)
233	}
234
235	// Force a sync. It should not try to create any Pods.
236	ssc.enqueueStatefulSet(set)
237	fakeWorker(ssc)
238
239	selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
240	if err != nil {
241		t.Fatal(err)
242	}
243	pods, err := spc.podsLister.Pods(set.Namespace).List(selector)
244	if err != nil {
245		t.Fatal(err)
246	}
247	if got, want := len(pods), 1; got != want {
248		t.Errorf("len(pods) = %v, want %v", got, want)
249	}
250
251	// It should not adopt pods.
252	for _, pod := range pods {
253		if len(pod.OwnerReferences) > 0 {
254			t.Errorf("unexpected pod owner references: %v", pod.OwnerReferences)
255		}
256	}
257
258	// It should not adopt revisions.
259	revisions, err := ssh.ListControllerRevisions(set, selector)
260	if err != nil {
261		t.Fatal(err)
262	}
263	if got, want := len(revisions), 1; got != want {
264		t.Errorf("len(revisions) = %v, want %v", got, want)
265	}
266	for _, revision := range revisions {
267		if len(revision.OwnerReferences) > 0 {
268			t.Errorf("unexpected revision owner references: %v", revision.OwnerReferences)
269		}
270	}
271}
272
273func TestStatefulSetControllerAddPod(t *testing.T) {
274	ssc, spc, _ := newFakeStatefulSetController()
275	set1 := newStatefulSet(3)
276	set2 := newStatefulSet(3)
277	pod1 := newStatefulSetPod(set1, 0)
278	pod2 := newStatefulSetPod(set2, 0)
279	spc.setsIndexer.Add(set1)
280	spc.setsIndexer.Add(set2)
281
282	ssc.addPod(pod1)
283	key, done := ssc.queue.Get()
284	if key == nil || done {
285		t.Error("failed to enqueue StatefulSet")
286	} else if key, ok := key.(string); !ok {
287		t.Error("key is not a string")
288	} else if expectedKey, _ := controller.KeyFunc(set1); expectedKey != key {
289		t.Errorf("expected StatefulSet key %s found %s", expectedKey, key)
290	}
291	ssc.queue.Done(key)
292
293	ssc.addPod(pod2)
294	key, done = ssc.queue.Get()
295	if key == nil || done {
296		t.Error("failed to enqueue StatefulSet")
297	} else if key, ok := key.(string); !ok {
298		t.Error("key is not a string")
299	} else if expectedKey, _ := controller.KeyFunc(set2); expectedKey != key {
300		t.Errorf("expected StatefulSet key %s found %s", expectedKey, key)
301	}
302	ssc.queue.Done(key)
303}
304
305func TestStatefulSetControllerAddPodOrphan(t *testing.T) {
306	ssc, spc, _ := newFakeStatefulSetController()
307	set1 := newStatefulSet(3)
308	set2 := newStatefulSet(3)
309	set2.Name = "foo2"
310	set3 := newStatefulSet(3)
311	set3.Name = "foo3"
312	set3.Spec.Selector.MatchLabels = map[string]string{"foo3": "bar"}
313	pod := newStatefulSetPod(set1, 0)
314	spc.setsIndexer.Add(set1)
315	spc.setsIndexer.Add(set2)
316	spc.setsIndexer.Add(set3)
317
318	// Make pod an orphan. Expect matching sets to be queued.
319	pod.OwnerReferences = nil
320	ssc.addPod(pod)
321	if got, want := ssc.queue.Len(), 2; got != want {
322		t.Errorf("queue.Len() = %v, want %v", got, want)
323	}
324}
325
326func TestStatefulSetControllerAddPodNoSet(t *testing.T) {
327	ssc, _, _ := newFakeStatefulSetController()
328	set := newStatefulSet(3)
329	pod := newStatefulSetPod(set, 0)
330	ssc.addPod(pod)
331	ssc.queue.ShutDown()
332	key, _ := ssc.queue.Get()
333	if key != nil {
334		t.Errorf("StatefulSet enqueued key for Pod with no Set %s", key)
335	}
336}
337
338func TestStatefulSetControllerUpdatePod(t *testing.T) {
339	ssc, spc, _ := newFakeStatefulSetController()
340	set1 := newStatefulSet(3)
341	set2 := newStatefulSet(3)
342	set2.Name = "foo2"
343	pod1 := newStatefulSetPod(set1, 0)
344	pod2 := newStatefulSetPod(set2, 0)
345	spc.setsIndexer.Add(set1)
346	spc.setsIndexer.Add(set2)
347
348	prev := *pod1
349	fakeResourceVersion(pod1)
350	ssc.updatePod(&prev, pod1)
351	key, done := ssc.queue.Get()
352	if key == nil || done {
353		t.Error("failed to enqueue StatefulSet")
354	} else if key, ok := key.(string); !ok {
355		t.Error("key is not a string")
356	} else if expectedKey, _ := controller.KeyFunc(set1); expectedKey != key {
357		t.Errorf("expected StatefulSet key %s found %s", expectedKey, key)
358	}
359
360	prev = *pod2
361	fakeResourceVersion(pod2)
362	ssc.updatePod(&prev, pod2)
363	key, done = ssc.queue.Get()
364	if key == nil || done {
365		t.Error("failed to enqueue StatefulSet")
366	} else if key, ok := key.(string); !ok {
367		t.Error("key is not a string")
368	} else if expectedKey, _ := controller.KeyFunc(set2); expectedKey != key {
369		t.Errorf("expected StatefulSet key %s found %s", expectedKey, key)
370	}
371}
372
373func TestStatefulSetControllerUpdatePodWithNoSet(t *testing.T) {
374	ssc, _, _ := newFakeStatefulSetController()
375	set := newStatefulSet(3)
376	pod := newStatefulSetPod(set, 0)
377	prev := *pod
378	fakeResourceVersion(pod)
379	ssc.updatePod(&prev, pod)
380	ssc.queue.ShutDown()
381	key, _ := ssc.queue.Get()
382	if key != nil {
383		t.Errorf("StatefulSet enqueued key for Pod with no Set %s", key)
384	}
385}
386
387func TestStatefulSetControllerUpdatePodWithSameVersion(t *testing.T) {
388	ssc, spc, _ := newFakeStatefulSetController()
389	set := newStatefulSet(3)
390	pod := newStatefulSetPod(set, 0)
391	spc.setsIndexer.Add(set)
392	ssc.updatePod(pod, pod)
393	ssc.queue.ShutDown()
394	key, _ := ssc.queue.Get()
395	if key != nil {
396		t.Errorf("StatefulSet enqueued key for Pod with no Set %s", key)
397	}
398}
399
400func TestStatefulSetControllerUpdatePodOrphanWithNewLabels(t *testing.T) {
401	ssc, spc, _ := newFakeStatefulSetController()
402	set := newStatefulSet(3)
403	pod := newStatefulSetPod(set, 0)
404	pod.OwnerReferences = nil
405	set2 := newStatefulSet(3)
406	set2.Name = "foo2"
407	spc.setsIndexer.Add(set)
408	spc.setsIndexer.Add(set2)
409	clone := *pod
410	clone.Labels = map[string]string{"foo2": "bar2"}
411	fakeResourceVersion(&clone)
412	ssc.updatePod(&clone, pod)
413	if got, want := ssc.queue.Len(), 2; got != want {
414		t.Errorf("queue.Len() = %v, want %v", got, want)
415	}
416}
417
418func TestStatefulSetControllerUpdatePodChangeControllerRef(t *testing.T) {
419	ssc, spc, _ := newFakeStatefulSetController()
420	set := newStatefulSet(3)
421	set2 := newStatefulSet(3)
422	set2.Name = "foo2"
423	pod := newStatefulSetPod(set, 0)
424	pod2 := newStatefulSetPod(set2, 0)
425	spc.setsIndexer.Add(set)
426	spc.setsIndexer.Add(set2)
427	clone := *pod
428	clone.OwnerReferences = pod2.OwnerReferences
429	fakeResourceVersion(&clone)
430	ssc.updatePod(&clone, pod)
431	if got, want := ssc.queue.Len(), 2; got != want {
432		t.Errorf("queue.Len() = %v, want %v", got, want)
433	}
434}
435
436func TestStatefulSetControllerUpdatePodRelease(t *testing.T) {
437	ssc, spc, _ := newFakeStatefulSetController()
438	set := newStatefulSet(3)
439	set2 := newStatefulSet(3)
440	set2.Name = "foo2"
441	pod := newStatefulSetPod(set, 0)
442	spc.setsIndexer.Add(set)
443	spc.setsIndexer.Add(set2)
444	clone := *pod
445	clone.OwnerReferences = nil
446	fakeResourceVersion(&clone)
447	ssc.updatePod(pod, &clone)
448	if got, want := ssc.queue.Len(), 2; got != want {
449		t.Errorf("queue.Len() = %v, want %v", got, want)
450	}
451}
452
453func TestStatefulSetControllerDeletePod(t *testing.T) {
454	ssc, spc, _ := newFakeStatefulSetController()
455	set1 := newStatefulSet(3)
456	set2 := newStatefulSet(3)
457	set2.Name = "foo2"
458	pod1 := newStatefulSetPod(set1, 0)
459	pod2 := newStatefulSetPod(set2, 0)
460	spc.setsIndexer.Add(set1)
461	spc.setsIndexer.Add(set2)
462
463	ssc.deletePod(pod1)
464	key, done := ssc.queue.Get()
465	if key == nil || done {
466		t.Error("failed to enqueue StatefulSet")
467	} else if key, ok := key.(string); !ok {
468		t.Error("key is not a string")
469	} else if expectedKey, _ := controller.KeyFunc(set1); expectedKey != key {
470		t.Errorf("expected StatefulSet key %s found %s", expectedKey, key)
471	}
472
473	ssc.deletePod(pod2)
474	key, done = ssc.queue.Get()
475	if key == nil || done {
476		t.Error("failed to enqueue StatefulSet")
477	} else if key, ok := key.(string); !ok {
478		t.Error("key is not a string")
479	} else if expectedKey, _ := controller.KeyFunc(set2); expectedKey != key {
480		t.Errorf("expected StatefulSet key %s found %s", expectedKey, key)
481	}
482}
483
484func TestStatefulSetControllerDeletePodOrphan(t *testing.T) {
485	ssc, spc, _ := newFakeStatefulSetController()
486	set1 := newStatefulSet(3)
487	set2 := newStatefulSet(3)
488	set2.Name = "foo2"
489	pod1 := newStatefulSetPod(set1, 0)
490	spc.setsIndexer.Add(set1)
491	spc.setsIndexer.Add(set2)
492
493	pod1.OwnerReferences = nil
494	ssc.deletePod(pod1)
495	if got, want := ssc.queue.Len(), 0; got != want {
496		t.Errorf("queue.Len() = %v, want %v", got, want)
497	}
498}
499
500func TestStatefulSetControllerDeletePodTombstone(t *testing.T) {
501	ssc, spc, _ := newFakeStatefulSetController()
502	set := newStatefulSet(3)
503	pod := newStatefulSetPod(set, 0)
504	spc.setsIndexer.Add(set)
505	tombstoneKey, _ := controller.KeyFunc(pod)
506	tombstone := cache.DeletedFinalStateUnknown{Key: tombstoneKey, Obj: pod}
507	ssc.deletePod(tombstone)
508	key, done := ssc.queue.Get()
509	if key == nil || done {
510		t.Error("failed to enqueue StatefulSet")
511	} else if key, ok := key.(string); !ok {
512		t.Error("key is not a string")
513	} else if expectedKey, _ := controller.KeyFunc(set); expectedKey != key {
514		t.Errorf("expected StatefulSet key %s found %s", expectedKey, key)
515	}
516}
517
518func TestStatefulSetControllerGetStatefulSetsForPod(t *testing.T) {
519	ssc, spc, _ := newFakeStatefulSetController()
520	set1 := newStatefulSet(3)
521	set2 := newStatefulSet(3)
522	set2.Name = "foo2"
523	pod := newStatefulSetPod(set1, 0)
524	spc.setsIndexer.Add(set1)
525	spc.setsIndexer.Add(set2)
526	spc.podsIndexer.Add(pod)
527	sets := ssc.getStatefulSetsForPod(pod)
528	if got, want := len(sets), 2; got != want {
529		t.Errorf("len(sets) = %v, want %v", got, want)
530	}
531}
532
533func TestGetPodsForStatefulSetAdopt(t *testing.T) {
534	set := newStatefulSet(5)
535	pod1 := newStatefulSetPod(set, 1)
536	// pod2 is an orphan with matching labels and name.
537	pod2 := newStatefulSetPod(set, 2)
538	pod2.OwnerReferences = nil
539	// pod3 has wrong labels.
540	pod3 := newStatefulSetPod(set, 3)
541	pod3.OwnerReferences = nil
542	pod3.Labels = nil
543	// pod4 has wrong name.
544	pod4 := newStatefulSetPod(set, 4)
545	pod4.OwnerReferences = nil
546	pod4.Name = "x" + pod4.Name
547
548	ssc, spc, _ := newFakeStatefulSetController(set, pod1, pod2, pod3, pod4)
549
550	spc.podsIndexer.Add(pod1)
551	spc.podsIndexer.Add(pod2)
552	spc.podsIndexer.Add(pod3)
553	spc.podsIndexer.Add(pod4)
554	selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
555	if err != nil {
556		t.Fatal(err)
557	}
558	pods, err := ssc.getPodsForStatefulSet(set, selector)
559	if err != nil {
560		t.Fatalf("getPodsForStatefulSet() error: %v", err)
561	}
562	got := sets.NewString()
563	for _, pod := range pods {
564		got.Insert(pod.Name)
565	}
566	// pod2 should be claimed, pod3 and pod4 ignored
567	want := sets.NewString(pod1.Name, pod2.Name)
568	if !got.Equal(want) {
569		t.Errorf("getPodsForStatefulSet() = %v, want %v", got, want)
570	}
571}
572
573func TestAdoptOrphanRevisions(t *testing.T) {
574	ss1 := newStatefulSetWithLabels(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
575	ss1.Status.CollisionCount = new(int32)
576	ss1Rev1, err := history.NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
577	if err != nil {
578		t.Fatal(err)
579	}
580	ss1Rev1.Namespace = ss1.Namespace
581	ss1.Spec.Template.Annotations = make(map[string]string)
582	ss1.Spec.Template.Annotations["ss1"] = "ss1"
583	ss1Rev2, err := history.NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
584	if err != nil {
585		t.Fatal(err)
586	}
587	ss1Rev2.Namespace = ss1.Namespace
588	ss1Rev2.OwnerReferences = []metav1.OwnerReference{}
589
590	ssc, spc, _ := newFakeStatefulSetController(ss1, ss1Rev1, ss1Rev2)
591
592	spc.revisionsIndexer.Add(ss1Rev1)
593	spc.revisionsIndexer.Add(ss1Rev2)
594
595	err = ssc.adoptOrphanRevisions(ss1)
596	if err != nil {
597		t.Errorf("adoptOrphanRevisions() error: %v", err)
598	}
599
600	if revisions, err := ssc.control.ListRevisions(ss1); err != nil {
601		t.Errorf("ListRevisions() error: %v", err)
602	} else {
603		var adopted bool
604		for i := range revisions {
605			if revisions[i].Name == ss1Rev2.Name && metav1.GetControllerOf(revisions[i]) != nil {
606				adopted = true
607			}
608		}
609		if !adopted {
610			t.Error("adoptOrphanRevisions() not adopt orphan revisions")
611		}
612	}
613}
614
615func TestGetPodsForStatefulSetRelease(t *testing.T) {
616	set := newStatefulSet(3)
617	ssc, spc, _ := newFakeStatefulSetController(set)
618	pod1 := newStatefulSetPod(set, 1)
619	// pod2 is owned but has wrong name.
620	pod2 := newStatefulSetPod(set, 2)
621	pod2.Name = "x" + pod2.Name
622	// pod3 is owned but has wrong labels.
623	pod3 := newStatefulSetPod(set, 3)
624	pod3.Labels = nil
625	// pod4 is an orphan that doesn't match.
626	pod4 := newStatefulSetPod(set, 4)
627	pod4.OwnerReferences = nil
628	pod4.Labels = nil
629
630	spc.podsIndexer.Add(pod1)
631	spc.podsIndexer.Add(pod2)
632	spc.podsIndexer.Add(pod3)
633	selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
634	if err != nil {
635		t.Fatal(err)
636	}
637	pods, err := ssc.getPodsForStatefulSet(set, selector)
638	if err != nil {
639		t.Fatalf("getPodsForStatefulSet() error: %v", err)
640	}
641	got := sets.NewString()
642	for _, pod := range pods {
643		got.Insert(pod.Name)
644	}
645
646	// Expect only pod1 (pod2 and pod3 should be released, pod4 ignored).
647	want := sets.NewString(pod1.Name)
648	if !got.Equal(want) {
649		t.Errorf("getPodsForStatefulSet() = %v, want %v", got, want)
650	}
651}
652
653func newFakeStatefulSetController(initialObjects ...runtime.Object) (*StatefulSetController, *fakeStatefulPodControl, history.Interface) {
654	client := fake.NewSimpleClientset(initialObjects...)
655	informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
656	fpc := newFakeStatefulPodControl(informerFactory.Core().V1().Pods(), informerFactory.Apps().V1().StatefulSets(), informerFactory.Apps().V1().ControllerRevisions())
657	ssu := newFakeStatefulSetStatusUpdater(informerFactory.Apps().V1().StatefulSets())
658	ssc := NewStatefulSetController(
659		informerFactory.Core().V1().Pods(),
660		informerFactory.Apps().V1().StatefulSets(),
661		informerFactory.Core().V1().PersistentVolumeClaims(),
662		informerFactory.Apps().V1().ControllerRevisions(),
663		client,
664	)
665	ssh := history.NewFakeHistory(informerFactory.Apps().V1().ControllerRevisions())
666	ssc.podListerSynced = alwaysReady
667	ssc.setListerSynced = alwaysReady
668	recorder := record.NewFakeRecorder(10)
669	ssc.control = NewDefaultStatefulSetControl(fpc, ssu, ssh, recorder)
670
671	return ssc, fpc, ssh
672}
673
674func fakeWorker(ssc *StatefulSetController) {
675	if obj, done := ssc.queue.Get(); !done {
676		ssc.sync(obj.(string))
677		ssc.queue.Done(obj)
678	}
679}
680
681func getPodAtOrdinal(pods []*v1.Pod, ordinal int) *v1.Pod {
682	if 0 > ordinal || ordinal >= len(pods) {
683		return nil
684	}
685	sort.Sort(ascendingOrdinal(pods))
686	return pods[ordinal]
687}
688
689func scaleUpStatefulSetController(set *apps.StatefulSet, ssc *StatefulSetController, spc *fakeStatefulPodControl) error {
690	spc.setsIndexer.Add(set)
691	ssc.enqueueStatefulSet(set)
692	fakeWorker(ssc)
693	selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
694	if err != nil {
695		return err
696	}
697	for set.Status.ReadyReplicas < *set.Spec.Replicas {
698		pods, err := spc.podsLister.Pods(set.Namespace).List(selector)
699		if err != nil {
700			return err
701		}
702		ord := len(pods) - 1
703		if pods, err = spc.setPodPending(set, ord); err != nil {
704			return err
705		}
706		pod := getPodAtOrdinal(pods, ord)
707		ssc.addPod(pod)
708		fakeWorker(ssc)
709		pod = getPodAtOrdinal(pods, ord)
710		prev := *pod
711		if pods, err = spc.setPodRunning(set, ord); err != nil {
712			return err
713		}
714		pod = getPodAtOrdinal(pods, ord)
715		ssc.updatePod(&prev, pod)
716		fakeWorker(ssc)
717		pod = getPodAtOrdinal(pods, ord)
718		prev = *pod
719		if pods, err = spc.setPodReady(set, ord); err != nil {
720			return err
721		}
722		pod = getPodAtOrdinal(pods, ord)
723		ssc.updatePod(&prev, pod)
724		fakeWorker(ssc)
725		if err := assertMonotonicInvariants(set, spc); err != nil {
726			return err
727		}
728		obj, _, err := spc.setsIndexer.Get(set)
729		if err != nil {
730			return err
731		}
732		set = obj.(*apps.StatefulSet)
733
734	}
735	return assertMonotonicInvariants(set, spc)
736}
737
738func scaleDownStatefulSetController(set *apps.StatefulSet, ssc *StatefulSetController, spc *fakeStatefulPodControl) error {
739	selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
740	if err != nil {
741		return err
742	}
743	pods, err := spc.podsLister.Pods(set.Namespace).List(selector)
744	if err != nil {
745		return err
746	}
747	ord := len(pods) - 1
748	pod := getPodAtOrdinal(pods, ord)
749	prev := *pod
750	fakeResourceVersion(set)
751	spc.setsIndexer.Add(set)
752	ssc.enqueueStatefulSet(set)
753	fakeWorker(ssc)
754	pods, err = spc.addTerminatingPod(set, ord)
755	if err != nil {
756		return err
757	}
758	pod = getPodAtOrdinal(pods, ord)
759	ssc.updatePod(&prev, pod)
760	fakeWorker(ssc)
761	spc.DeleteStatefulPod(set, pod)
762	ssc.deletePod(pod)
763	fakeWorker(ssc)
764	for set.Status.Replicas > *set.Spec.Replicas {
765		pods, err = spc.podsLister.Pods(set.Namespace).List(selector)
766		if err != nil {
767			return err
768		}
769
770		ord := len(pods)
771		pods, err = spc.addTerminatingPod(set, ord)
772		if err != nil {
773			return err
774		}
775		pod = getPodAtOrdinal(pods, ord)
776		ssc.updatePod(&prev, pod)
777		fakeWorker(ssc)
778		spc.DeleteStatefulPod(set, pod)
779		ssc.deletePod(pod)
780		fakeWorker(ssc)
781		obj, _, err := spc.setsIndexer.Get(set)
782		if err != nil {
783			return err
784		}
785		set = obj.(*apps.StatefulSet)
786
787	}
788	return assertMonotonicInvariants(set, spc)
789}
790
791func rawTemplate(template *v1.PodTemplateSpec) runtime.RawExtension {
792	buf := new(bytes.Buffer)
793	enc := json.NewEncoder(buf)
794	if err := enc.Encode(template); err != nil {
795		panic(err)
796	}
797	return runtime.RawExtension{Raw: buf.Bytes()}
798}
799