2016-04-25 19:24:40 +00:00
|
|
|
/*
|
2016-06-03 00:25:58 +00:00
|
|
|
Copyright 2016 The Kubernetes Authors.
|
2016-04-25 19:24:40 +00:00
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2017-01-16 08:23:43 +00:00
|
|
|
package statefulset
|
2016-04-25 19:24:40 +00:00
|
|
|
|
|
|
|
import (
|
2017-02-24 00:27:20 +00:00
|
|
|
"reflect"
|
2017-02-08 19:30:14 +00:00
|
|
|
"sort"
|
2016-04-25 19:24:40 +00:00
|
|
|
"testing"
|
2017-02-08 19:30:14 +00:00
|
|
|
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
2017-03-11 01:13:51 +00:00
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
2017-01-24 14:11:51 +00:00
|
|
|
"k8s.io/client-go/tools/cache"
|
2016-11-18 20:50:17 +00:00
|
|
|
"k8s.io/kubernetes/pkg/api/v1"
|
|
|
|
apps "k8s.io/kubernetes/pkg/apis/apps/v1beta1"
|
2017-02-14 19:03:00 +00:00
|
|
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake"
|
|
|
|
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/externalversions"
|
2016-04-25 19:24:40 +00:00
|
|
|
"k8s.io/kubernetes/pkg/controller"
|
|
|
|
)
|
|
|
|
|
2017-02-14 19:03:00 +00:00
|
|
|
func alwaysReady() bool { return true }
|
|
|
|
|
2017-02-08 19:30:14 +00:00
|
|
|
func TestStatefulSetControllerCreates(t *testing.T) {
|
|
|
|
set := newStatefulSet(3)
|
2017-03-11 01:13:51 +00:00
|
|
|
ssc, spc := newFakeStatefulSetController(set)
|
2017-02-08 19:30:14 +00:00
|
|
|
if err := scaleUpStatefulSetController(set, ssc, spc); err != nil {
|
|
|
|
t.Errorf("Failed to turn up StatefulSet : %s", err)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
if obj, _, err := spc.setsIndexer.Get(set); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else {
|
|
|
|
set = obj.(*apps.StatefulSet)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
if set.Status.Replicas != 3 {
|
|
|
|
t.Error("Falied to scale statefulset to 3 replicas")
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-26 20:44:07 +00:00
|
|
|
func TestStatefulSetControllerDeletes(t *testing.T) {
|
2017-02-08 19:30:14 +00:00
|
|
|
set := newStatefulSet(3)
|
2017-03-11 01:13:51 +00:00
|
|
|
ssc, spc := newFakeStatefulSetController(set)
|
2017-02-08 19:30:14 +00:00
|
|
|
if err := scaleUpStatefulSetController(set, ssc, spc); err != nil {
|
|
|
|
t.Errorf("Failed to turn up StatefulSet : %s", err)
|
|
|
|
}
|
|
|
|
if obj, _, err := spc.setsIndexer.Get(set); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else {
|
|
|
|
set = obj.(*apps.StatefulSet)
|
|
|
|
}
|
|
|
|
if set.Status.Replicas != 3 {
|
|
|
|
t.Error("Falied to scale statefulset to 3 replicas")
|
|
|
|
}
|
|
|
|
*set.Spec.Replicas = 0
|
|
|
|
if err := scaleDownStatefulSetController(set, ssc, spc); err != nil {
|
|
|
|
t.Errorf("Failed to turn down StatefulSet : %s", err)
|
|
|
|
}
|
|
|
|
if obj, _, err := spc.setsIndexer.Get(set); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else {
|
|
|
|
set = obj.(*apps.StatefulSet)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
if set.Status.Replicas != 0 {
|
|
|
|
t.Error("Falied to scale statefulset to 3 replicas")
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-26 20:44:07 +00:00
|
|
|
func TestStatefulSetControllerRespectsTermination(t *testing.T) {
|
2017-02-08 19:30:14 +00:00
|
|
|
set := newStatefulSet(3)
|
2017-03-11 01:13:51 +00:00
|
|
|
ssc, spc := newFakeStatefulSetController(set)
|
2017-02-08 19:30:14 +00:00
|
|
|
if err := scaleUpStatefulSetController(set, ssc, spc); err != nil {
|
|
|
|
t.Errorf("Failed to turn up StatefulSet : %s", err)
|
|
|
|
}
|
|
|
|
if obj, _, err := spc.setsIndexer.Get(set); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else {
|
|
|
|
set = obj.(*apps.StatefulSet)
|
|
|
|
}
|
|
|
|
if set.Status.Replicas != 3 {
|
|
|
|
t.Error("Falied to scale statefulset to 3 replicas")
|
|
|
|
}
|
2017-04-20 16:10:46 +00:00
|
|
|
pods, err := spc.addTerminatingPod(set, 3)
|
2016-08-30 09:31:06 +00:00
|
|
|
if err != nil {
|
2017-02-08 19:30:14 +00:00
|
|
|
t.Error(err)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-04-20 16:10:46 +00:00
|
|
|
pods, err = spc.addTerminatingPod(set, 4)
|
2017-02-08 19:30:14 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
ssc.syncStatefulSet(set, pods)
|
|
|
|
selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
|
2016-08-30 09:31:06 +00:00
|
|
|
if err != nil {
|
2017-02-08 19:30:14 +00:00
|
|
|
t.Error(err)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
pods, err = spc.podsLister.Pods(set.Namespace).List(selector)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
if len(pods) != 5 {
|
|
|
|
t.Error("StatefulSet does not respect termination")
|
|
|
|
}
|
|
|
|
sort.Sort(ascendingOrdinal(pods))
|
|
|
|
spc.DeleteStatefulPod(set, pods[3])
|
|
|
|
spc.DeleteStatefulPod(set, pods[4])
|
|
|
|
*set.Spec.Replicas = 0
|
|
|
|
if err := scaleDownStatefulSetController(set, ssc, spc); err != nil {
|
|
|
|
t.Errorf("Failed to turn down StatefulSet : %s", err)
|
|
|
|
}
|
|
|
|
if obj, _, err := spc.setsIndexer.Get(set); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else {
|
|
|
|
set = obj.(*apps.StatefulSet)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
if set.Status.Replicas != 0 {
|
|
|
|
t.Error("Falied to scale statefulset to 3 replicas")
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-26 20:44:07 +00:00
|
|
|
func TestStatefulSetControllerBlocksScaling(t *testing.T) {
|
2017-02-08 19:30:14 +00:00
|
|
|
set := newStatefulSet(3)
|
2017-03-11 01:13:51 +00:00
|
|
|
ssc, spc := newFakeStatefulSetController(set)
|
2017-02-08 19:30:14 +00:00
|
|
|
if err := scaleUpStatefulSetController(set, ssc, spc); err != nil {
|
|
|
|
t.Errorf("Failed to turn up StatefulSet : %s", err)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
if obj, _, err := spc.setsIndexer.Get(set); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else {
|
|
|
|
set = obj.(*apps.StatefulSet)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
if set.Status.Replicas != 3 {
|
|
|
|
t.Error("Falied to scale statefulset to 3 replicas")
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
*set.Spec.Replicas = 5
|
|
|
|
fakeResourceVersion(set)
|
|
|
|
spc.setsIndexer.Update(set)
|
|
|
|
pods, err := spc.setPodTerminated(set, 0)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("Failed to set pod terminated at ordinal 0")
|
|
|
|
}
|
|
|
|
ssc.enqueueStatefulSet(set)
|
|
|
|
fakeWorker(ssc)
|
|
|
|
selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
pods, err = spc.podsLister.Pods(set.Namespace).List(selector)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
if len(pods) != 3 {
|
|
|
|
t.Error("StatefulSet does not block scaling")
|
|
|
|
}
|
|
|
|
sort.Sort(ascendingOrdinal(pods))
|
|
|
|
spc.DeleteStatefulPod(set, pods[0])
|
|
|
|
ssc.enqueueStatefulSet(set)
|
|
|
|
fakeWorker(ssc)
|
|
|
|
pods, err = spc.podsLister.Pods(set.Namespace).List(selector)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
if len(pods) != 3 {
|
|
|
|
t.Error("StatefulSet does not resume when terminated Pod is removed")
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-11 01:13:51 +00:00
|
|
|
func TestStatefulSetControllerDeletionTimestamp(t *testing.T) {
|
|
|
|
set := newStatefulSet(3)
|
|
|
|
set.DeletionTimestamp = new(metav1.Time)
|
|
|
|
ssc, spc := newFakeStatefulSetController(set)
|
|
|
|
|
|
|
|
spc.setsIndexer.Add(set)
|
|
|
|
|
|
|
|
// Force a sync. It should not try to create any Pods.
|
|
|
|
ssc.enqueueStatefulSet(set)
|
|
|
|
fakeWorker(ssc)
|
|
|
|
|
|
|
|
selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
pods, err := spc.podsLister.Pods(set.Namespace).List(selector)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if got, want := len(pods), 0; got != want {
|
|
|
|
t.Errorf("len(pods) = %v, want %v", got, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStatefulSetControllerDeletionTimestampRace(t *testing.T) {
|
|
|
|
set := newStatefulSet(3)
|
|
|
|
// The bare client says it IS deleted.
|
|
|
|
set.DeletionTimestamp = new(metav1.Time)
|
|
|
|
ssc, spc := newFakeStatefulSetController(set)
|
|
|
|
|
|
|
|
// The lister (cache) says it's NOT deleted.
|
|
|
|
set2 := *set
|
|
|
|
set2.DeletionTimestamp = nil
|
|
|
|
spc.setsIndexer.Add(&set2)
|
|
|
|
|
|
|
|
// The recheck occurs in the presence of a matching orphan.
|
|
|
|
pod := newStatefulSetPod(set, 1)
|
|
|
|
pod.OwnerReferences = nil
|
|
|
|
spc.podsIndexer.Add(pod)
|
|
|
|
|
|
|
|
// Force a sync. It should not try to create any Pods.
|
|
|
|
ssc.enqueueStatefulSet(set)
|
|
|
|
fakeWorker(ssc)
|
|
|
|
|
|
|
|
selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
pods, err := spc.podsLister.Pods(set.Namespace).List(selector)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if got, want := len(pods), 1; got != want {
|
|
|
|
t.Errorf("len(pods) = %v, want %v", got, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-24 20:56:10 +00:00
|
|
|
func TestStatefulSetControllerAddPod(t *testing.T) {
|
2017-02-08 19:30:14 +00:00
|
|
|
ssc, spc := newFakeStatefulSetController()
|
2017-02-24 20:56:10 +00:00
|
|
|
set1 := newStatefulSet(3)
|
|
|
|
set2 := newStatefulSet(3)
|
|
|
|
pod1 := newStatefulSetPod(set1, 0)
|
|
|
|
pod2 := newStatefulSetPod(set2, 0)
|
|
|
|
spc.setsIndexer.Add(set1)
|
|
|
|
spc.setsIndexer.Add(set2)
|
|
|
|
|
|
|
|
ssc.addPod(pod1)
|
2017-02-08 19:30:14 +00:00
|
|
|
key, done := ssc.queue.Get()
|
|
|
|
if key == nil || done {
|
2017-02-24 20:56:10 +00:00
|
|
|
t.Error("failed to enqueue StatefulSet")
|
2017-02-08 19:30:14 +00:00
|
|
|
} else if key, ok := key.(string); !ok {
|
2017-02-24 20:56:10 +00:00
|
|
|
t.Error("key is not a string")
|
|
|
|
} else if expectedKey, _ := controller.KeyFunc(set1); expectedKey != key {
|
|
|
|
t.Errorf("expected StatefulSet key %s found %s", expectedKey, key)
|
|
|
|
}
|
|
|
|
ssc.queue.Done(key)
|
|
|
|
|
|
|
|
ssc.addPod(pod2)
|
|
|
|
key, done = ssc.queue.Get()
|
|
|
|
if key == nil || done {
|
|
|
|
t.Error("failed to enqueue StatefulSet")
|
|
|
|
} else if key, ok := key.(string); !ok {
|
|
|
|
t.Error("key is not a string")
|
|
|
|
} else if expectedKey, _ := controller.KeyFunc(set2); expectedKey != key {
|
|
|
|
t.Errorf("expected StatefulSet key %s found %s", expectedKey, key)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-02-24 20:56:10 +00:00
|
|
|
ssc.queue.Done(key)
|
2017-02-08 19:30:14 +00:00
|
|
|
}
|
2016-04-25 19:24:40 +00:00
|
|
|
|
2017-02-24 20:56:10 +00:00
|
|
|
func TestStatefulSetControllerAddPodOrphan(t *testing.T) {
|
|
|
|
ssc, spc := newFakeStatefulSetController()
|
|
|
|
set1 := newStatefulSet(3)
|
|
|
|
set2 := newStatefulSet(3)
|
|
|
|
set2.Name = "foo2"
|
|
|
|
set3 := newStatefulSet(3)
|
|
|
|
set3.Name = "foo3"
|
|
|
|
set3.Spec.Selector.MatchLabels = map[string]string{"foo3": "bar"}
|
|
|
|
pod := newStatefulSetPod(set1, 0)
|
|
|
|
spc.setsIndexer.Add(set1)
|
|
|
|
spc.setsIndexer.Add(set2)
|
|
|
|
spc.setsIndexer.Add(set3)
|
|
|
|
|
|
|
|
// Make pod an orphan. Expect matching sets to be queued.
|
|
|
|
pod.OwnerReferences = nil
|
|
|
|
ssc.addPod(pod)
|
|
|
|
if got, want := ssc.queue.Len(), 2; got != want {
|
|
|
|
t.Errorf("queue.Len() = %v, want %v", got, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStatefulSetControllerAddPodNoSet(t *testing.T) {
|
2017-02-08 19:30:14 +00:00
|
|
|
ssc, _ := newFakeStatefulSetController()
|
|
|
|
set := newStatefulSet(3)
|
|
|
|
pod := newStatefulSetPod(set, 0)
|
|
|
|
ssc.addPod(pod)
|
|
|
|
ssc.queue.ShutDown()
|
|
|
|
key, _ := ssc.queue.Get()
|
|
|
|
if key != nil {
|
|
|
|
t.Errorf("StatefulSet enqueued key for Pod with no Set %s", key)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
}
|
2016-04-25 19:24:40 +00:00
|
|
|
|
2017-02-08 19:30:14 +00:00
|
|
|
func TestStatefulSetControllerUpdatePod(t *testing.T) {
|
|
|
|
ssc, spc := newFakeStatefulSetController()
|
2017-02-24 20:56:10 +00:00
|
|
|
set1 := newStatefulSet(3)
|
|
|
|
set2 := newStatefulSet(3)
|
|
|
|
set2.Name = "foo2"
|
|
|
|
pod1 := newStatefulSetPod(set1, 0)
|
|
|
|
pod2 := newStatefulSetPod(set2, 0)
|
|
|
|
spc.setsIndexer.Add(set1)
|
|
|
|
spc.setsIndexer.Add(set2)
|
|
|
|
|
|
|
|
prev := *pod1
|
|
|
|
fakeResourceVersion(pod1)
|
|
|
|
ssc.updatePod(&prev, pod1)
|
2017-02-08 19:30:14 +00:00
|
|
|
key, done := ssc.queue.Get()
|
|
|
|
if key == nil || done {
|
2017-02-24 20:56:10 +00:00
|
|
|
t.Error("failed to enqueue StatefulSet")
|
2017-02-08 19:30:14 +00:00
|
|
|
} else if key, ok := key.(string); !ok {
|
2017-02-24 20:56:10 +00:00
|
|
|
t.Error("key is not a string")
|
|
|
|
} else if expectedKey, _ := controller.KeyFunc(set1); expectedKey != key {
|
|
|
|
t.Errorf("expected StatefulSet key %s found %s", expectedKey, key)
|
|
|
|
}
|
|
|
|
|
|
|
|
prev = *pod2
|
|
|
|
fakeResourceVersion(pod2)
|
|
|
|
ssc.updatePod(&prev, pod2)
|
|
|
|
key, done = ssc.queue.Get()
|
|
|
|
if key == nil || done {
|
|
|
|
t.Error("failed to enqueue StatefulSet")
|
|
|
|
} else if key, ok := key.(string); !ok {
|
|
|
|
t.Error("key is not a string")
|
|
|
|
} else if expectedKey, _ := controller.KeyFunc(set2); expectedKey != key {
|
|
|
|
t.Errorf("expected StatefulSet key %s found %s", expectedKey, key)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
}
|
2016-04-25 19:24:40 +00:00
|
|
|
|
2017-02-08 19:30:14 +00:00
|
|
|
func TestStatefulSetControllerUpdatePodWithNoSet(t *testing.T) {
|
|
|
|
ssc, _ := newFakeStatefulSetController()
|
|
|
|
set := newStatefulSet(3)
|
|
|
|
pod := newStatefulSetPod(set, 0)
|
|
|
|
prev := *pod
|
|
|
|
fakeResourceVersion(pod)
|
|
|
|
ssc.updatePod(&prev, pod)
|
|
|
|
ssc.queue.ShutDown()
|
|
|
|
key, _ := ssc.queue.Get()
|
|
|
|
if key != nil {
|
|
|
|
t.Errorf("StatefulSet enqueued key for Pod with no Set %s", key)
|
2016-04-25 19:24:40 +00:00
|
|
|
}
|
|
|
|
}
|
2016-09-06 10:50:32 +00:00
|
|
|
|
2017-02-08 19:30:14 +00:00
|
|
|
func TestStatefulSetControllerUpdatePodWithSameVersion(t *testing.T) {
|
|
|
|
ssc, spc := newFakeStatefulSetController()
|
|
|
|
set := newStatefulSet(3)
|
|
|
|
pod := newStatefulSetPod(set, 0)
|
|
|
|
spc.setsIndexer.Add(set)
|
|
|
|
ssc.updatePod(pod, pod)
|
|
|
|
ssc.queue.ShutDown()
|
|
|
|
key, _ := ssc.queue.Get()
|
|
|
|
if key != nil {
|
|
|
|
t.Errorf("StatefulSet enqueued key for Pod with no Set %s", key)
|
2016-09-06 10:50:32 +00:00
|
|
|
}
|
|
|
|
}
|
2016-09-07 10:53:24 +00:00
|
|
|
|
2017-02-24 20:56:10 +00:00
|
|
|
func TestStatefulSetControllerUpdatePodOrphanWithNewLabels(t *testing.T) {
|
2017-02-08 19:30:14 +00:00
|
|
|
ssc, spc := newFakeStatefulSetController()
|
|
|
|
set := newStatefulSet(3)
|
|
|
|
pod := newStatefulSetPod(set, 0)
|
2017-02-24 20:56:10 +00:00
|
|
|
pod.OwnerReferences = nil
|
2017-02-08 19:30:14 +00:00
|
|
|
set2 := newStatefulSet(3)
|
|
|
|
set2.Name = "foo2"
|
|
|
|
spc.setsIndexer.Add(set)
|
|
|
|
spc.setsIndexer.Add(set2)
|
|
|
|
clone := *pod
|
|
|
|
clone.Labels = map[string]string{"foo2": "bar2"}
|
|
|
|
fakeResourceVersion(&clone)
|
2017-02-24 20:56:10 +00:00
|
|
|
ssc.updatePod(&clone, pod)
|
|
|
|
if got, want := ssc.queue.Len(), 2; got != want {
|
|
|
|
t.Errorf("queue.Len() = %v, want %v", got, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStatefulSetControllerUpdatePodChangeControllerRef(t *testing.T) {
|
|
|
|
ssc, spc := newFakeStatefulSetController()
|
|
|
|
set := newStatefulSet(3)
|
|
|
|
set2 := newStatefulSet(3)
|
|
|
|
set2.Name = "foo2"
|
|
|
|
pod := newStatefulSetPod(set, 0)
|
|
|
|
pod2 := newStatefulSetPod(set2, 0)
|
|
|
|
spc.setsIndexer.Add(set)
|
|
|
|
spc.setsIndexer.Add(set2)
|
|
|
|
clone := *pod
|
|
|
|
clone.OwnerReferences = pod2.OwnerReferences
|
|
|
|
fakeResourceVersion(&clone)
|
|
|
|
ssc.updatePod(&clone, pod)
|
|
|
|
if got, want := ssc.queue.Len(), 2; got != want {
|
|
|
|
t.Errorf("queue.Len() = %v, want %v", got, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStatefulSetControllerUpdatePodRelease(t *testing.T) {
|
|
|
|
ssc, spc := newFakeStatefulSetController()
|
|
|
|
set := newStatefulSet(3)
|
|
|
|
set2 := newStatefulSet(3)
|
|
|
|
set2.Name = "foo2"
|
|
|
|
pod := newStatefulSetPod(set, 0)
|
|
|
|
spc.setsIndexer.Add(set)
|
|
|
|
spc.setsIndexer.Add(set2)
|
|
|
|
clone := *pod
|
|
|
|
clone.OwnerReferences = nil
|
|
|
|
fakeResourceVersion(&clone)
|
2017-02-08 19:30:14 +00:00
|
|
|
ssc.updatePod(pod, &clone)
|
2017-02-24 20:56:10 +00:00
|
|
|
if got, want := ssc.queue.Len(), 2; got != want {
|
|
|
|
t.Errorf("queue.Len() = %v, want %v", got, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStatefulSetControllerDeletePod(t *testing.T) {
|
|
|
|
ssc, spc := newFakeStatefulSetController()
|
|
|
|
set1 := newStatefulSet(3)
|
|
|
|
set2 := newStatefulSet(3)
|
|
|
|
set2.Name = "foo2"
|
|
|
|
pod1 := newStatefulSetPod(set1, 0)
|
|
|
|
pod2 := newStatefulSetPod(set2, 0)
|
|
|
|
spc.setsIndexer.Add(set1)
|
|
|
|
spc.setsIndexer.Add(set2)
|
|
|
|
|
|
|
|
ssc.deletePod(pod1)
|
2017-02-08 19:30:14 +00:00
|
|
|
key, done := ssc.queue.Get()
|
|
|
|
if key == nil || done {
|
2017-02-24 20:56:10 +00:00
|
|
|
t.Error("failed to enqueue StatefulSet")
|
2017-02-08 19:30:14 +00:00
|
|
|
} else if key, ok := key.(string); !ok {
|
2017-02-24 20:56:10 +00:00
|
|
|
t.Error("key is not a string")
|
|
|
|
} else if expectedKey, _ := controller.KeyFunc(set1); expectedKey != key {
|
|
|
|
t.Errorf("expected StatefulSet key %s found %s", expectedKey, key)
|
2017-02-08 19:30:14 +00:00
|
|
|
}
|
2017-02-24 20:56:10 +00:00
|
|
|
|
|
|
|
ssc.deletePod(pod2)
|
2017-02-08 19:30:14 +00:00
|
|
|
key, done = ssc.queue.Get()
|
|
|
|
if key == nil || done {
|
2017-02-24 20:56:10 +00:00
|
|
|
t.Error("failed to enqueue StatefulSet")
|
2017-02-08 19:30:14 +00:00
|
|
|
} else if key, ok := key.(string); !ok {
|
2017-02-24 20:56:10 +00:00
|
|
|
t.Error("key is not a string")
|
|
|
|
} else if expectedKey, _ := controller.KeyFunc(set2); expectedKey != key {
|
|
|
|
t.Errorf("expected StatefulSet key %s found %s", expectedKey, key)
|
2017-02-08 19:30:14 +00:00
|
|
|
}
|
2016-09-07 10:53:24 +00:00
|
|
|
}
|
|
|
|
|
2017-02-24 20:56:10 +00:00
|
|
|
func TestStatefulSetControllerDeletePodOrphan(t *testing.T) {
|
2017-02-08 19:30:14 +00:00
|
|
|
ssc, spc := newFakeStatefulSetController()
|
2017-02-24 20:56:10 +00:00
|
|
|
set1 := newStatefulSet(3)
|
|
|
|
set2 := newStatefulSet(3)
|
|
|
|
set2.Name = "foo2"
|
|
|
|
pod1 := newStatefulSetPod(set1, 0)
|
|
|
|
spc.setsIndexer.Add(set1)
|
|
|
|
spc.setsIndexer.Add(set2)
|
|
|
|
|
|
|
|
pod1.OwnerReferences = nil
|
|
|
|
ssc.deletePod(pod1)
|
|
|
|
if got, want := ssc.queue.Len(), 0; got != want {
|
|
|
|
t.Errorf("queue.Len() = %v, want %v", got, want)
|
2017-02-08 19:30:14 +00:00
|
|
|
}
|
|
|
|
}
|
2017-02-24 20:56:10 +00:00
|
|
|
|
2017-02-08 19:30:14 +00:00
|
|
|
func TestStatefulSetControllerDeletePodTombstone(t *testing.T) {
|
|
|
|
ssc, spc := newFakeStatefulSetController()
|
|
|
|
set := newStatefulSet(3)
|
|
|
|
pod := newStatefulSetPod(set, 0)
|
|
|
|
spc.setsIndexer.Add(set)
|
|
|
|
tombstoneKey, _ := controller.KeyFunc(pod)
|
|
|
|
tombstone := cache.DeletedFinalStateUnknown{Key: tombstoneKey, Obj: pod}
|
|
|
|
ssc.deletePod(tombstone)
|
|
|
|
key, done := ssc.queue.Get()
|
|
|
|
if key == nil || done {
|
2017-02-24 20:56:10 +00:00
|
|
|
t.Error("failed to enqueue StatefulSet")
|
2017-02-08 19:30:14 +00:00
|
|
|
} else if key, ok := key.(string); !ok {
|
2017-02-24 20:56:10 +00:00
|
|
|
t.Error("key is not a string")
|
2017-02-08 19:30:14 +00:00
|
|
|
} else if expectedKey, _ := controller.KeyFunc(set); expectedKey != key {
|
2017-02-24 20:56:10 +00:00
|
|
|
t.Errorf("expected StatefulSet key %s found %s", expectedKey, key)
|
2017-02-08 19:30:14 +00:00
|
|
|
}
|
2016-09-07 10:53:24 +00:00
|
|
|
}
|
|
|
|
|
2017-02-24 20:56:10 +00:00
|
|
|
func TestStatefulSetControllerGetStatefulSetsForPod(t *testing.T) {
|
2017-02-08 19:30:14 +00:00
|
|
|
ssc, spc := newFakeStatefulSetController()
|
2017-02-24 20:56:10 +00:00
|
|
|
set1 := newStatefulSet(3)
|
2017-02-08 19:30:14 +00:00
|
|
|
set2 := newStatefulSet(3)
|
|
|
|
set2.Name = "foo2"
|
2017-02-24 20:56:10 +00:00
|
|
|
pod := newStatefulSetPod(set1, 0)
|
|
|
|
spc.setsIndexer.Add(set1)
|
2017-02-08 19:30:14 +00:00
|
|
|
spc.setsIndexer.Add(set2)
|
|
|
|
spc.podsIndexer.Add(pod)
|
2017-02-24 20:56:10 +00:00
|
|
|
sets := ssc.getStatefulSetsForPod(pod)
|
|
|
|
if got, want := len(sets), 2; got != want {
|
|
|
|
t.Errorf("len(sets) = %v, want %v", got, want)
|
2017-02-08 19:30:14 +00:00
|
|
|
}
|
2016-09-07 10:53:24 +00:00
|
|
|
}
|
|
|
|
|
2017-02-24 00:27:20 +00:00
|
|
|
func TestGetPodsForStatefulSetAdopt(t *testing.T) {
|
|
|
|
set := newStatefulSet(5)
|
2017-03-11 01:13:51 +00:00
|
|
|
ssc, spc := newFakeStatefulSetController(set)
|
2017-02-24 00:27:20 +00:00
|
|
|
pod1 := newStatefulSetPod(set, 1)
|
|
|
|
// pod2 is an orphan with matching labels and name.
|
|
|
|
pod2 := newStatefulSetPod(set, 2)
|
|
|
|
pod2.OwnerReferences = nil
|
|
|
|
// pod3 has wrong labels.
|
|
|
|
pod3 := newStatefulSetPod(set, 3)
|
|
|
|
pod3.OwnerReferences = nil
|
|
|
|
pod3.Labels = nil
|
|
|
|
// pod4 has wrong name.
|
|
|
|
pod4 := newStatefulSetPod(set, 4)
|
|
|
|
pod4.OwnerReferences = nil
|
|
|
|
pod4.Name = "x" + pod4.Name
|
|
|
|
|
|
|
|
spc.podsIndexer.Add(pod1)
|
|
|
|
spc.podsIndexer.Add(pod2)
|
|
|
|
spc.podsIndexer.Add(pod3)
|
|
|
|
spc.podsIndexer.Add(pod4)
|
|
|
|
selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
pods, err := ssc.getPodsForStatefulSet(set, selector)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("getPodsForStatefulSet() error: %v", err)
|
|
|
|
}
|
|
|
|
var got []string
|
|
|
|
for _, pod := range pods {
|
|
|
|
got = append(got, pod.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// pod2 should be claimed, pod3 and pod4 ignored
|
|
|
|
want := []string{pod1.Name, pod2.Name}
|
|
|
|
sort.Strings(got)
|
|
|
|
sort.Strings(want)
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("getPodsForStatefulSet() = %v, want %v", got, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetPodsForStatefulSetRelease(t *testing.T) {
|
|
|
|
set := newStatefulSet(3)
|
2017-03-11 01:13:51 +00:00
|
|
|
ssc, spc := newFakeStatefulSetController(set)
|
2017-02-24 00:27:20 +00:00
|
|
|
pod1 := newStatefulSetPod(set, 1)
|
|
|
|
// pod2 is owned but has wrong name.
|
|
|
|
pod2 := newStatefulSetPod(set, 2)
|
|
|
|
pod2.Name = "x" + pod2.Name
|
|
|
|
// pod3 is owned but has wrong labels.
|
|
|
|
pod3 := newStatefulSetPod(set, 3)
|
|
|
|
pod3.Labels = nil
|
|
|
|
// pod4 is an orphan that doesn't match.
|
|
|
|
pod4 := newStatefulSetPod(set, 4)
|
|
|
|
pod4.OwnerReferences = nil
|
|
|
|
pod4.Labels = nil
|
|
|
|
|
|
|
|
spc.podsIndexer.Add(pod1)
|
|
|
|
spc.podsIndexer.Add(pod2)
|
|
|
|
spc.podsIndexer.Add(pod3)
|
|
|
|
selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
pods, err := ssc.getPodsForStatefulSet(set, selector)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("getPodsForStatefulSet() error: %v", err)
|
|
|
|
}
|
|
|
|
var got []string
|
|
|
|
for _, pod := range pods {
|
|
|
|
got = append(got, pod.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Expect only pod1 (pod2 and pod3 should be released, pod4 ignored).
|
|
|
|
want := []string{pod1.Name}
|
|
|
|
sort.Strings(got)
|
|
|
|
sort.Strings(want)
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("getPodsForStatefulSet() = %v, want %v", got, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-11 01:13:51 +00:00
|
|
|
func newFakeStatefulSetController(initialObjects ...runtime.Object) (*StatefulSetController, *fakeStatefulPodControl) {
|
|
|
|
client := fake.NewSimpleClientset(initialObjects...)
|
2017-02-14 19:03:00 +00:00
|
|
|
informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
|
|
|
|
fpc := newFakeStatefulPodControl(informerFactory.Core().V1().Pods(), informerFactory.Apps().V1beta1().StatefulSets())
|
|
|
|
ssc := NewStatefulSetController(
|
|
|
|
informerFactory.Core().V1().Pods(),
|
|
|
|
informerFactory.Apps().V1beta1().StatefulSets(),
|
2017-02-24 14:31:40 +00:00
|
|
|
informerFactory.Core().V1().PersistentVolumeClaims(),
|
2017-02-14 19:03:00 +00:00
|
|
|
client,
|
|
|
|
)
|
|
|
|
ssc.podListerSynced = alwaysReady
|
|
|
|
ssc.setListerSynced = alwaysReady
|
|
|
|
ssc.control = NewDefaultStatefulSetControl(fpc)
|
|
|
|
|
2017-02-08 19:30:14 +00:00
|
|
|
return ssc, fpc
|
2016-09-07 10:53:24 +00:00
|
|
|
}
|
|
|
|
|
2017-02-08 19:30:14 +00:00
|
|
|
func fakeWorker(ssc *StatefulSetController) {
|
|
|
|
if obj, done := ssc.queue.Get(); !done {
|
|
|
|
ssc.sync(obj.(string))
|
|
|
|
ssc.queue.Done(obj)
|
|
|
|
}
|
2016-09-07 10:53:24 +00:00
|
|
|
}
|
|
|
|
|
2017-02-08 19:30:14 +00:00
|
|
|
func getPodAtOrdinal(pods []*v1.Pod, ordinal int) *v1.Pod {
|
|
|
|
if 0 > ordinal || ordinal >= len(pods) {
|
|
|
|
return nil
|
2016-09-07 10:53:24 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
sort.Sort(ascendingOrdinal(pods))
|
|
|
|
return pods[ordinal]
|
|
|
|
}
|
2016-09-07 10:53:24 +00:00
|
|
|
|
2017-02-08 19:30:14 +00:00
|
|
|
func scaleUpStatefulSetController(set *apps.StatefulSet, ssc *StatefulSetController, spc *fakeStatefulPodControl) error {
|
|
|
|
spc.setsIndexer.Add(set)
|
|
|
|
ssc.enqueueStatefulSet(set)
|
|
|
|
fakeWorker(ssc)
|
|
|
|
selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for set.Status.Replicas < *set.Spec.Replicas {
|
|
|
|
pods, err := spc.podsLister.Pods(set.Namespace).List(selector)
|
|
|
|
ord := len(pods) - 1
|
|
|
|
pod := getPodAtOrdinal(pods, ord)
|
|
|
|
if pods, err = spc.setPodPending(set, ord); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
pod = getPodAtOrdinal(pods, ord)
|
|
|
|
ssc.addPod(pod)
|
|
|
|
fakeWorker(ssc)
|
|
|
|
pod = getPodAtOrdinal(pods, ord)
|
|
|
|
prev := *pod
|
|
|
|
if pods, err = spc.setPodRunning(set, ord); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
pod = getPodAtOrdinal(pods, ord)
|
|
|
|
ssc.updatePod(&prev, pod)
|
|
|
|
fakeWorker(ssc)
|
|
|
|
pod = getPodAtOrdinal(pods, ord)
|
|
|
|
prev = *pod
|
|
|
|
if pods, err = spc.setPodReady(set, ord); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
pod = getPodAtOrdinal(pods, ord)
|
|
|
|
ssc.updatePod(&prev, pod)
|
|
|
|
fakeWorker(ssc)
|
|
|
|
if err := assertInvariants(set, spc); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if obj, _, err := spc.setsIndexer.Get(set); err != nil {
|
|
|
|
return err
|
|
|
|
} else {
|
|
|
|
set = obj.(*apps.StatefulSet)
|
|
|
|
}
|
2016-09-07 10:53:24 +00:00
|
|
|
|
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
return assertInvariants(set, spc)
|
|
|
|
}
|
2016-09-07 10:53:24 +00:00
|
|
|
|
2017-02-08 19:30:14 +00:00
|
|
|
func scaleDownStatefulSetController(set *apps.StatefulSet, ssc *StatefulSetController, spc *fakeStatefulPodControl) error {
|
|
|
|
selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
pods, err := spc.podsLister.Pods(set.Namespace).List(selector)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
ord := len(pods) - 1
|
|
|
|
pod := getPodAtOrdinal(pods, ord)
|
|
|
|
prev := *pod
|
|
|
|
fakeResourceVersion(set)
|
|
|
|
spc.setsIndexer.Add(set)
|
|
|
|
ssc.enqueueStatefulSet(set)
|
|
|
|
fakeWorker(ssc)
|
2017-04-20 16:10:46 +00:00
|
|
|
pods, err = spc.addTerminatingPod(set, ord)
|
2017-02-08 19:30:14 +00:00
|
|
|
pod = getPodAtOrdinal(pods, ord)
|
|
|
|
ssc.updatePod(&prev, pod)
|
|
|
|
fakeWorker(ssc)
|
|
|
|
spc.DeleteStatefulPod(set, pod)
|
|
|
|
ssc.deletePod(pod)
|
|
|
|
fakeWorker(ssc)
|
|
|
|
for set.Status.Replicas > *set.Spec.Replicas {
|
|
|
|
pods, err = spc.podsLister.Pods(set.Namespace).List(selector)
|
|
|
|
ord := len(pods)
|
2017-04-20 16:10:46 +00:00
|
|
|
pods, err = spc.addTerminatingPod(set, ord)
|
2017-02-08 19:30:14 +00:00
|
|
|
pod = getPodAtOrdinal(pods, ord)
|
|
|
|
ssc.updatePod(&prev, pod)
|
|
|
|
fakeWorker(ssc)
|
|
|
|
spc.DeleteStatefulPod(set, pod)
|
|
|
|
ssc.deletePod(pod)
|
|
|
|
fakeWorker(ssc)
|
|
|
|
if obj, _, err := spc.setsIndexer.Get(set); err != nil {
|
|
|
|
return err
|
|
|
|
} else {
|
|
|
|
set = obj.(*apps.StatefulSet)
|
|
|
|
}
|
2016-09-07 10:53:24 +00:00
|
|
|
}
|
2017-02-08 19:30:14 +00:00
|
|
|
return assertInvariants(set, spc)
|
2016-09-07 10:53:24 +00:00
|
|
|
}
|