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