replicaset_test.go 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package replicaset
  14. import (
  15. "fmt"
  16. "net/http/httptest"
  17. "reflect"
  18. "strings"
  19. "testing"
  20. "time"
  21. apps "k8s.io/api/apps/v1"
  22. "k8s.io/api/core/v1"
  23. "k8s.io/apimachinery/pkg/api/errors"
  24. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  25. "k8s.io/apimachinery/pkg/labels"
  26. "k8s.io/apimachinery/pkg/util/uuid"
  27. "k8s.io/apimachinery/pkg/util/wait"
  28. "k8s.io/client-go/informers"
  29. clientset "k8s.io/client-go/kubernetes"
  30. appsclient "k8s.io/client-go/kubernetes/typed/apps/v1"
  31. typedv1 "k8s.io/client-go/kubernetes/typed/core/v1"
  32. restclient "k8s.io/client-go/rest"
  33. "k8s.io/client-go/tools/cache"
  34. "k8s.io/client-go/util/retry"
  35. podutil "k8s.io/kubernetes/pkg/api/v1/pod"
  36. "k8s.io/kubernetes/pkg/controller/replicaset"
  37. "k8s.io/kubernetes/pkg/util/slice"
  38. "k8s.io/kubernetes/test/integration/framework"
  39. testutil "k8s.io/kubernetes/test/utils"
  40. )
  41. const (
  42. interval = 100 * time.Millisecond
  43. timeout = 60 * time.Second
  44. )
  45. func labelMap() map[string]string {
  46. return map[string]string{"foo": "bar"}
  47. }
  48. func newRS(name, namespace string, replicas int) *apps.ReplicaSet {
  49. replicasCopy := int32(replicas)
  50. return &apps.ReplicaSet{
  51. TypeMeta: metav1.TypeMeta{
  52. Kind: "ReplicaSet",
  53. APIVersion: "apps/v1",
  54. },
  55. ObjectMeta: metav1.ObjectMeta{
  56. Namespace: namespace,
  57. Name: name,
  58. },
  59. Spec: apps.ReplicaSetSpec{
  60. Selector: &metav1.LabelSelector{
  61. MatchLabels: labelMap(),
  62. },
  63. Replicas: &replicasCopy,
  64. Template: v1.PodTemplateSpec{
  65. ObjectMeta: metav1.ObjectMeta{
  66. Labels: labelMap(),
  67. },
  68. Spec: v1.PodSpec{
  69. Containers: []v1.Container{
  70. {
  71. Name: "fake-name",
  72. Image: "fakeimage",
  73. },
  74. },
  75. },
  76. },
  77. },
  78. }
  79. }
  80. func newMatchingPod(podName, namespace string) *v1.Pod {
  81. return &v1.Pod{
  82. TypeMeta: metav1.TypeMeta{
  83. Kind: "Pod",
  84. APIVersion: "v1",
  85. },
  86. ObjectMeta: metav1.ObjectMeta{
  87. Name: podName,
  88. Namespace: namespace,
  89. Labels: labelMap(),
  90. },
  91. Spec: v1.PodSpec{
  92. Containers: []v1.Container{
  93. {
  94. Name: "fake-name",
  95. Image: "fakeimage",
  96. },
  97. },
  98. },
  99. Status: v1.PodStatus{
  100. Phase: v1.PodRunning,
  101. },
  102. }
  103. }
  104. func rmSetup(t *testing.T) (*httptest.Server, framework.CloseFunc, *replicaset.ReplicaSetController, informers.SharedInformerFactory, clientset.Interface) {
  105. masterConfig := framework.NewIntegrationTestMasterConfig()
  106. _, s, closeFn := framework.RunAMaster(masterConfig)
  107. config := restclient.Config{Host: s.URL}
  108. clientSet, err := clientset.NewForConfig(&config)
  109. if err != nil {
  110. t.Fatalf("Error in create clientset: %v", err)
  111. }
  112. resyncPeriod := 12 * time.Hour
  113. informers := informers.NewSharedInformerFactory(clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "rs-informers")), resyncPeriod)
  114. rm := replicaset.NewReplicaSetController(
  115. informers.Apps().V1().ReplicaSets(),
  116. informers.Core().V1().Pods(),
  117. clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "replicaset-controller")),
  118. replicaset.BurstReplicas,
  119. )
  120. if err != nil {
  121. t.Fatalf("Failed to create replicaset controller")
  122. }
  123. return s, closeFn, rm, informers, clientSet
  124. }
  125. func rmSimpleSetup(t *testing.T) (*httptest.Server, framework.CloseFunc, clientset.Interface) {
  126. masterConfig := framework.NewIntegrationTestMasterConfig()
  127. _, s, closeFn := framework.RunAMaster(masterConfig)
  128. config := restclient.Config{Host: s.URL}
  129. clientSet, err := clientset.NewForConfig(&config)
  130. if err != nil {
  131. t.Fatalf("Error in create clientset: %v", err)
  132. }
  133. return s, closeFn, clientSet
  134. }
  135. // Run RS controller and informers
  136. func runControllerAndInformers(t *testing.T, rm *replicaset.ReplicaSetController, informers informers.SharedInformerFactory, podNum int) chan struct{} {
  137. stopCh := make(chan struct{})
  138. informers.Start(stopCh)
  139. waitToObservePods(t, informers.Core().V1().Pods().Informer(), podNum)
  140. go rm.Run(5, stopCh)
  141. return stopCh
  142. }
  143. // wait for the podInformer to observe the pods. Call this function before
  144. // running the RS controller to prevent the rc manager from creating new pods
  145. // rather than adopting the existing ones.
  146. func waitToObservePods(t *testing.T, podInformer cache.SharedIndexInformer, podNum int) {
  147. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  148. objects := podInformer.GetIndexer().List()
  149. return len(objects) == podNum, nil
  150. }); err != nil {
  151. t.Fatalf("Error encountered when waiting for podInformer to observe the pods: %v", err)
  152. }
  153. }
  154. func createRSsPods(t *testing.T, clientSet clientset.Interface, rss []*apps.ReplicaSet, pods []*v1.Pod) ([]*apps.ReplicaSet, []*v1.Pod) {
  155. var createdRSs []*apps.ReplicaSet
  156. var createdPods []*v1.Pod
  157. for _, rs := range rss {
  158. createdRS, err := clientSet.AppsV1().ReplicaSets(rs.Namespace).Create(rs)
  159. if err != nil {
  160. t.Fatalf("Failed to create replica set %s: %v", rs.Name, err)
  161. }
  162. createdRSs = append(createdRSs, createdRS)
  163. }
  164. for _, pod := range pods {
  165. createdPod, err := clientSet.CoreV1().Pods(pod.Namespace).Create(pod)
  166. if err != nil {
  167. t.Fatalf("Failed to create pod %s: %v", pod.Name, err)
  168. }
  169. createdPods = append(createdPods, createdPod)
  170. }
  171. return createdRSs, createdPods
  172. }
  173. // Verify .Status.Replicas is equal to .Spec.Replicas
  174. func waitRSStable(t *testing.T, clientSet clientset.Interface, rs *apps.ReplicaSet) {
  175. if err := testutil.WaitRSStable(t, clientSet, rs, interval, timeout); err != nil {
  176. t.Fatal(err)
  177. }
  178. }
  179. // Update .Spec.Replicas to replicas and verify .Status.Replicas is changed accordingly
  180. func scaleRS(t *testing.T, c clientset.Interface, rs *apps.ReplicaSet, replicas int32) {
  181. rsClient := c.AppsV1().ReplicaSets(rs.Namespace)
  182. rs = updateRS(t, rsClient, rs.Name, func(rs *apps.ReplicaSet) {
  183. *rs.Spec.Replicas = replicas
  184. })
  185. waitRSStable(t, c, rs)
  186. }
  187. func updatePod(t *testing.T, podClient typedv1.PodInterface, podName string, updateFunc func(*v1.Pod)) *v1.Pod {
  188. var pod *v1.Pod
  189. if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
  190. newPod, err := podClient.Get(podName, metav1.GetOptions{})
  191. if err != nil {
  192. return err
  193. }
  194. updateFunc(newPod)
  195. pod, err = podClient.Update(newPod)
  196. return err
  197. }); err != nil {
  198. t.Fatalf("Failed to update pod %s: %v", podName, err)
  199. }
  200. return pod
  201. }
  202. func updatePodStatus(t *testing.T, podClient typedv1.PodInterface, pod *v1.Pod, updateStatusFunc func(*v1.Pod)) {
  203. if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
  204. newPod, err := podClient.Get(pod.Name, metav1.GetOptions{})
  205. if err != nil {
  206. return err
  207. }
  208. updateStatusFunc(newPod)
  209. _, err = podClient.UpdateStatus(newPod)
  210. return err
  211. }); err != nil {
  212. t.Fatalf("Failed to update status of pod %s: %v", pod.Name, err)
  213. }
  214. }
  215. func getPods(t *testing.T, podClient typedv1.PodInterface, labelMap map[string]string) *v1.PodList {
  216. podSelector := labels.Set(labelMap).AsSelector()
  217. options := metav1.ListOptions{LabelSelector: podSelector.String()}
  218. pods, err := podClient.List(options)
  219. if err != nil {
  220. t.Fatalf("Failed obtaining a list of pods that match the pod labels %v: %v", labelMap, err)
  221. }
  222. return pods
  223. }
  224. func updateRS(t *testing.T, rsClient appsclient.ReplicaSetInterface, rsName string, updateFunc func(*apps.ReplicaSet)) *apps.ReplicaSet {
  225. var rs *apps.ReplicaSet
  226. if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
  227. newRS, err := rsClient.Get(rsName, metav1.GetOptions{})
  228. if err != nil {
  229. return err
  230. }
  231. updateFunc(newRS)
  232. rs, err = rsClient.Update(newRS)
  233. return err
  234. }); err != nil {
  235. t.Fatalf("Failed to update rs %s: %v", rsName, err)
  236. }
  237. return rs
  238. }
  239. // Verify ControllerRef of a RS pod that has incorrect attributes is automatically patched by the RS
  240. func testPodControllerRefPatch(t *testing.T, c clientset.Interface, pod *v1.Pod, ownerReference *metav1.OwnerReference, rs *apps.ReplicaSet, expectedOwnerReferenceNum int) {
  241. ns := rs.Namespace
  242. podClient := c.CoreV1().Pods(ns)
  243. updatePod(t, podClient, pod.Name, func(pod *v1.Pod) {
  244. pod.OwnerReferences = []metav1.OwnerReference{*ownerReference}
  245. })
  246. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  247. newPod, err := podClient.Get(pod.Name, metav1.GetOptions{})
  248. if err != nil {
  249. return false, err
  250. }
  251. return metav1.GetControllerOf(newPod) != nil, nil
  252. }); err != nil {
  253. t.Fatalf("Failed to verify ControllerRef for the pod %s is not nil: %v", pod.Name, err)
  254. }
  255. newPod, err := podClient.Get(pod.Name, metav1.GetOptions{})
  256. if err != nil {
  257. t.Fatalf("Failed to obtain pod %s: %v", pod.Name, err)
  258. }
  259. controllerRef := metav1.GetControllerOf(newPod)
  260. if controllerRef.UID != rs.UID {
  261. t.Fatalf("RS owner of the pod %s has a different UID: Expected %v, got %v", newPod.Name, rs.UID, controllerRef.UID)
  262. }
  263. ownerReferenceNum := len(newPod.GetOwnerReferences())
  264. if ownerReferenceNum != expectedOwnerReferenceNum {
  265. t.Fatalf("Unexpected number of owner references for pod %s: Expected %d, got %d", newPod.Name, expectedOwnerReferenceNum, ownerReferenceNum)
  266. }
  267. }
  268. func setPodsReadyCondition(t *testing.T, clientSet clientset.Interface, pods *v1.PodList, conditionStatus v1.ConditionStatus, lastTransitionTime time.Time) {
  269. replicas := int32(len(pods.Items))
  270. var readyPods int32
  271. err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  272. readyPods = 0
  273. for i := range pods.Items {
  274. pod := &pods.Items[i]
  275. if podutil.IsPodReady(pod) {
  276. readyPods++
  277. continue
  278. }
  279. pod.Status.Phase = v1.PodRunning
  280. _, condition := podutil.GetPodCondition(&pod.Status, v1.PodReady)
  281. if condition != nil {
  282. condition.Status = conditionStatus
  283. condition.LastTransitionTime = metav1.Time{Time: lastTransitionTime}
  284. } else {
  285. condition = &v1.PodCondition{
  286. Type: v1.PodReady,
  287. Status: conditionStatus,
  288. LastTransitionTime: metav1.Time{Time: lastTransitionTime},
  289. }
  290. pod.Status.Conditions = append(pod.Status.Conditions, *condition)
  291. }
  292. _, err := clientSet.CoreV1().Pods(pod.Namespace).UpdateStatus(pod)
  293. if err != nil {
  294. // When status fails to be updated, we continue to next pod
  295. continue
  296. }
  297. readyPods++
  298. }
  299. return readyPods >= replicas, nil
  300. })
  301. if err != nil {
  302. t.Fatalf("failed to mark all ReplicaSet pods to ready: %v", err)
  303. }
  304. }
  305. func testScalingUsingScaleSubresource(t *testing.T, c clientset.Interface, rs *apps.ReplicaSet, replicas int32) {
  306. ns := rs.Namespace
  307. rsClient := c.AppsV1().ReplicaSets(ns)
  308. newRS, err := rsClient.Get(rs.Name, metav1.GetOptions{})
  309. if err != nil {
  310. t.Fatalf("Failed to obtain rs %s: %v", rs.Name, err)
  311. }
  312. scale, err := c.AppsV1().ReplicaSets(ns).GetScale(rs.Name, metav1.GetOptions{})
  313. if err != nil {
  314. t.Fatalf("Failed to obtain scale subresource for rs %s: %v", rs.Name, err)
  315. }
  316. if scale.Spec.Replicas != *newRS.Spec.Replicas {
  317. t.Fatalf("Scale subresource for rs %s does not match .Spec.Replicas: expected %d, got %d", rs.Name, *newRS.Spec.Replicas, scale.Spec.Replicas)
  318. }
  319. if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
  320. scale, err := c.AppsV1().ReplicaSets(ns).GetScale(rs.Name, metav1.GetOptions{})
  321. if err != nil {
  322. return err
  323. }
  324. scale.Spec.Replicas = replicas
  325. _, err = c.AppsV1().ReplicaSets(ns).UpdateScale(rs.Name, scale)
  326. return err
  327. }); err != nil {
  328. t.Fatalf("Failed to set .Spec.Replicas of scale subresource for rs %s: %v", rs.Name, err)
  329. }
  330. newRS, err = rsClient.Get(rs.Name, metav1.GetOptions{})
  331. if err != nil {
  332. t.Fatalf("Failed to obtain rs %s: %v", rs.Name, err)
  333. }
  334. if *newRS.Spec.Replicas != replicas {
  335. t.Fatalf(".Spec.Replicas of rs %s does not match its scale subresource: expected %d, got %d", rs.Name, replicas, *newRS.Spec.Replicas)
  336. }
  337. }
  338. func TestAdoption(t *testing.T) {
  339. boolPtr := func(b bool) *bool { return &b }
  340. testCases := []struct {
  341. name string
  342. existingOwnerReferences func(rs *apps.ReplicaSet) []metav1.OwnerReference
  343. expectedOwnerReferences func(rs *apps.ReplicaSet) []metav1.OwnerReference
  344. }{
  345. {
  346. "pod refers rs as an owner, not a controller",
  347. func(rs *apps.ReplicaSet) []metav1.OwnerReference {
  348. return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet"}}
  349. },
  350. func(rs *apps.ReplicaSet) []metav1.OwnerReference {
  351. return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true), BlockOwnerDeletion: boolPtr(true)}}
  352. },
  353. },
  354. {
  355. "pod doesn't have owner references",
  356. func(rs *apps.ReplicaSet) []metav1.OwnerReference {
  357. return []metav1.OwnerReference{}
  358. },
  359. func(rs *apps.ReplicaSet) []metav1.OwnerReference {
  360. return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true), BlockOwnerDeletion: boolPtr(true)}}
  361. },
  362. },
  363. {
  364. "pod refers rs as a controller",
  365. func(rs *apps.ReplicaSet) []metav1.OwnerReference {
  366. return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true)}}
  367. },
  368. func(rs *apps.ReplicaSet) []metav1.OwnerReference {
  369. return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true)}}
  370. },
  371. },
  372. {
  373. "pod refers other rs as the controller, refers the rs as an owner",
  374. func(rs *apps.ReplicaSet) []metav1.OwnerReference {
  375. return []metav1.OwnerReference{
  376. {UID: "1", Name: "anotherRS", APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true)},
  377. {UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet"},
  378. }
  379. },
  380. func(rs *apps.ReplicaSet) []metav1.OwnerReference {
  381. return []metav1.OwnerReference{
  382. {UID: "1", Name: "anotherRS", APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true)},
  383. {UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet"},
  384. }
  385. },
  386. },
  387. }
  388. for i, tc := range testCases {
  389. func() {
  390. s, closeFn, rm, informers, clientSet := rmSetup(t)
  391. defer closeFn()
  392. ns := framework.CreateTestingNamespace(fmt.Sprintf("rs-adoption-%d", i), s, t)
  393. defer framework.DeleteTestingNamespace(ns, s, t)
  394. rsClient := clientSet.AppsV1().ReplicaSets(ns.Name)
  395. podClient := clientSet.CoreV1().Pods(ns.Name)
  396. const rsName = "rs"
  397. rs, err := rsClient.Create(newRS(rsName, ns.Name, 1))
  398. if err != nil {
  399. t.Fatalf("Failed to create replica set: %v", err)
  400. }
  401. podName := fmt.Sprintf("pod%d", i)
  402. pod := newMatchingPod(podName, ns.Name)
  403. pod.OwnerReferences = tc.existingOwnerReferences(rs)
  404. _, err = podClient.Create(pod)
  405. if err != nil {
  406. t.Fatalf("Failed to create Pod: %v", err)
  407. }
  408. stopCh := runControllerAndInformers(t, rm, informers, 1)
  409. defer close(stopCh)
  410. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  411. updatedPod, err := podClient.Get(pod.Name, metav1.GetOptions{})
  412. if err != nil {
  413. return false, err
  414. }
  415. e, a := tc.expectedOwnerReferences(rs), updatedPod.OwnerReferences
  416. if reflect.DeepEqual(e, a) {
  417. return true, nil
  418. }
  419. t.Logf("ownerReferences don't match, expect %v, got %v", e, a)
  420. return false, nil
  421. }); err != nil {
  422. t.Fatalf("test %q failed: %v", tc.name, err)
  423. }
  424. }()
  425. }
  426. }
  427. // selectors are IMMUTABLE for all API versions except extensions/v1beta1
  428. func TestRSSelectorImmutability(t *testing.T) {
  429. s, closeFn, clientSet := rmSimpleSetup(t)
  430. defer closeFn()
  431. ns := framework.CreateTestingNamespace("rs-selector-immutability", s, t)
  432. defer framework.DeleteTestingNamespace(ns, s, t)
  433. rs := newRS("rs", ns.Name, 0)
  434. createRSsPods(t, clientSet, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  435. // test to ensure extensions/v1beta1 selector is mutable
  436. // TODO: remove the extensions/v1beta1 portion of the test once we stop serving extensions/v1beta1
  437. newSelectorLabels := map[string]string{"changed_name_extensions_v1beta1": "changed_test_extensions_v1beta1"}
  438. rsExt, err := clientSet.ExtensionsV1beta1().ReplicaSets(ns.Name).Get(rs.Name, metav1.GetOptions{})
  439. if err != nil {
  440. t.Fatalf("failed to get extensions/v1beta replicaset %s: %v", rs.Name, err)
  441. }
  442. rsExt.Spec.Selector.MatchLabels = newSelectorLabels
  443. rsExt.Spec.Template.Labels = newSelectorLabels
  444. replicaset, err := clientSet.ExtensionsV1beta1().ReplicaSets(ns.Name).Update(rsExt)
  445. if err != nil {
  446. t.Fatalf("failed to update extensions/v1beta1 replicaset %s: %v", replicaset.Name, err)
  447. }
  448. if !reflect.DeepEqual(replicaset.Spec.Selector.MatchLabels, newSelectorLabels) {
  449. t.Errorf("selector should be changed for extensions/v1beta1, expected: %v, got: %v", newSelectorLabels, replicaset.Spec.Selector.MatchLabels)
  450. }
  451. // test to ensure apps/v1 selector is immutable
  452. rsV1, err := clientSet.AppsV1().ReplicaSets(ns.Name).Get(rs.Name, metav1.GetOptions{})
  453. if err != nil {
  454. t.Fatalf("failed to get apps/v1 replicaset %s: %v", rs.Name, err)
  455. }
  456. newSelectorLabels = map[string]string{"changed_name_apps_v1": "changed_test_apps_v1"}
  457. rsV1.Spec.Selector.MatchLabels = newSelectorLabels
  458. rsV1.Spec.Template.Labels = newSelectorLabels
  459. _, err = clientSet.AppsV1().ReplicaSets(ns.Name).Update(rsV1)
  460. if err == nil {
  461. t.Fatalf("failed to provide validation error when changing immutable selector when updating apps/v1 replicaset %s", rsV1.Name)
  462. }
  463. expectedErrType := "Invalid value"
  464. expectedErrDetail := "field is immutable"
  465. if !strings.Contains(err.Error(), expectedErrType) || !strings.Contains(err.Error(), expectedErrDetail) {
  466. t.Errorf("error message does not match, expected type: %s, expected detail: %s, got: %s", expectedErrType, expectedErrDetail, err.Error())
  467. }
  468. }
  469. func TestSpecReplicasChange(t *testing.T) {
  470. s, closeFn, rm, informers, c := rmSetup(t)
  471. defer closeFn()
  472. ns := framework.CreateTestingNamespace("test-spec-replicas-change", s, t)
  473. defer framework.DeleteTestingNamespace(ns, s, t)
  474. stopCh := runControllerAndInformers(t, rm, informers, 0)
  475. defer close(stopCh)
  476. rs := newRS("rs", ns.Name, 2)
  477. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  478. rs = rss[0]
  479. waitRSStable(t, c, rs)
  480. // Update .Spec.Replicas and verify .Status.Replicas is changed accordingly
  481. scaleRS(t, c, rs, 3)
  482. scaleRS(t, c, rs, 0)
  483. scaleRS(t, c, rs, 2)
  484. // Add a template annotation change to test RS's status does update
  485. // without .Spec.Replicas change
  486. rsClient := c.AppsV1().ReplicaSets(ns.Name)
  487. var oldGeneration int64
  488. newRS := updateRS(t, rsClient, rs.Name, func(rs *apps.ReplicaSet) {
  489. oldGeneration = rs.Generation
  490. rs.Spec.Template.Annotations = map[string]string{"test": "annotation"}
  491. })
  492. savedGeneration := newRS.Generation
  493. if savedGeneration == oldGeneration {
  494. t.Fatalf("Failed to verify .Generation has incremented for rs %s", rs.Name)
  495. }
  496. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  497. newRS, err := rsClient.Get(rs.Name, metav1.GetOptions{})
  498. if err != nil {
  499. return false, err
  500. }
  501. return newRS.Status.ObservedGeneration >= savedGeneration, nil
  502. }); err != nil {
  503. t.Fatalf("Failed to verify .Status.ObservedGeneration has incremented for rs %s: %v", rs.Name, err)
  504. }
  505. }
  506. func TestDeletingAndFailedPods(t *testing.T) {
  507. s, closeFn, rm, informers, c := rmSetup(t)
  508. defer closeFn()
  509. ns := framework.CreateTestingNamespace("test-deleting-and-failed-pods", s, t)
  510. defer framework.DeleteTestingNamespace(ns, s, t)
  511. stopCh := runControllerAndInformers(t, rm, informers, 0)
  512. defer close(stopCh)
  513. rs := newRS("rs", ns.Name, 2)
  514. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  515. rs = rss[0]
  516. waitRSStable(t, c, rs)
  517. // Verify RS creates 2 pods
  518. podClient := c.CoreV1().Pods(ns.Name)
  519. pods := getPods(t, podClient, labelMap())
  520. if len(pods.Items) != 2 {
  521. t.Fatalf("len(pods) = %d, want 2", len(pods.Items))
  522. }
  523. // Set first pod as deleting pod
  524. // Set finalizers for the pod to simulate pending deletion status
  525. deletingPod := &pods.Items[0]
  526. updatePod(t, podClient, deletingPod.Name, func(pod *v1.Pod) {
  527. pod.Finalizers = []string{"fake.example.com/blockDeletion"}
  528. })
  529. if err := c.CoreV1().Pods(ns.Name).Delete(deletingPod.Name, &metav1.DeleteOptions{}); err != nil {
  530. t.Fatalf("Error deleting pod %s: %v", deletingPod.Name, err)
  531. }
  532. // Set second pod as failed pod
  533. failedPod := &pods.Items[1]
  534. updatePodStatus(t, podClient, failedPod, func(pod *v1.Pod) {
  535. pod.Status.Phase = v1.PodFailed
  536. })
  537. // Pool until 2 new pods have been created to replace deleting and failed pods
  538. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  539. pods = getPods(t, podClient, labelMap())
  540. return len(pods.Items) == 4, nil
  541. }); err != nil {
  542. t.Fatalf("Failed to verify 2 new pods have been created (expected 4 pods): %v", err)
  543. }
  544. // Verify deleting and failed pods are among the four pods
  545. foundDeletingPod := false
  546. foundFailedPod := false
  547. for _, pod := range pods.Items {
  548. if pod.UID == deletingPod.UID {
  549. foundDeletingPod = true
  550. }
  551. if pod.UID == failedPod.UID {
  552. foundFailedPod = true
  553. }
  554. }
  555. // Verify deleting pod exists
  556. if !foundDeletingPod {
  557. t.Fatalf("expected deleting pod %s exists, but it is not found", deletingPod.Name)
  558. }
  559. // Verify failed pod exists
  560. if !foundFailedPod {
  561. t.Fatalf("expected failed pod %s exists, but it is not found", failedPod.Name)
  562. }
  563. }
  564. func TestOverlappingRSs(t *testing.T) {
  565. s, closeFn, rm, informers, c := rmSetup(t)
  566. defer closeFn()
  567. ns := framework.CreateTestingNamespace("test-overlapping-rss", s, t)
  568. defer framework.DeleteTestingNamespace(ns, s, t)
  569. stopCh := runControllerAndInformers(t, rm, informers, 0)
  570. defer close(stopCh)
  571. // Create 2 RSs with identical selectors
  572. for i := 0; i < 2; i++ {
  573. // One RS has 1 replica, and another has 2 replicas
  574. rs := newRS(fmt.Sprintf("rs-%d", i+1), ns.Name, i+1)
  575. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  576. waitRSStable(t, c, rss[0])
  577. }
  578. // Expect 3 total Pods to be created
  579. podClient := c.CoreV1().Pods(ns.Name)
  580. pods := getPods(t, podClient, labelMap())
  581. if len(pods.Items) != 3 {
  582. t.Errorf("len(pods) = %d, want 3", len(pods.Items))
  583. }
  584. // Expect both RSs have .status.replicas = .spec.replicas
  585. for i := 0; i < 2; i++ {
  586. newRS, err := c.AppsV1().ReplicaSets(ns.Name).Get(fmt.Sprintf("rs-%d", i+1), metav1.GetOptions{})
  587. if err != nil {
  588. t.Fatalf("failed to obtain rs rs-%d: %v", i+1, err)
  589. }
  590. if newRS.Status.Replicas != *newRS.Spec.Replicas {
  591. t.Fatalf(".Status.Replicas %d is not equal to .Spec.Replicas %d", newRS.Status.Replicas, *newRS.Spec.Replicas)
  592. }
  593. }
  594. }
  595. func TestPodOrphaningAndAdoptionWhenLabelsChange(t *testing.T) {
  596. s, closeFn, rm, informers, c := rmSetup(t)
  597. defer closeFn()
  598. ns := framework.CreateTestingNamespace("test-pod-orphaning-and-adoption-when-labels-change", s, t)
  599. defer framework.DeleteTestingNamespace(ns, s, t)
  600. stopCh := runControllerAndInformers(t, rm, informers, 0)
  601. defer close(stopCh)
  602. rs := newRS("rs", ns.Name, 1)
  603. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  604. rs = rss[0]
  605. waitRSStable(t, c, rs)
  606. // Orphaning: RS should remove OwnerReference from a pod when the pod's labels change to not match its labels
  607. podClient := c.CoreV1().Pods(ns.Name)
  608. pods := getPods(t, podClient, labelMap())
  609. if len(pods.Items) != 1 {
  610. t.Fatalf("len(pods) = %d, want 1", len(pods.Items))
  611. }
  612. pod := &pods.Items[0]
  613. // Start by verifying ControllerRef for the pod is not nil
  614. if metav1.GetControllerOf(pod) == nil {
  615. t.Fatalf("ControllerRef of pod %s is nil", pod.Name)
  616. }
  617. newLabelMap := map[string]string{"new-foo": "new-bar"}
  618. updatePod(t, podClient, pod.Name, func(pod *v1.Pod) {
  619. pod.Labels = newLabelMap
  620. })
  621. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  622. newPod, err := podClient.Get(pod.Name, metav1.GetOptions{})
  623. if err != nil {
  624. return false, err
  625. }
  626. pod = newPod
  627. return metav1.GetControllerOf(newPod) == nil, nil
  628. }); err != nil {
  629. t.Fatalf("Failed to verify ControllerRef for the pod %s is nil: %v", pod.Name, err)
  630. }
  631. // Adoption: RS should add ControllerRef to a pod when the pod's labels change to match its labels
  632. updatePod(t, podClient, pod.Name, func(pod *v1.Pod) {
  633. pod.Labels = labelMap()
  634. })
  635. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  636. newPod, err := podClient.Get(pod.Name, metav1.GetOptions{})
  637. if err != nil {
  638. // If the pod is not found, it means the RS picks the pod for deletion (it is extra)
  639. // Verify there is only one pod in namespace and it has ControllerRef to the RS
  640. if errors.IsNotFound(err) {
  641. pods := getPods(t, podClient, labelMap())
  642. if len(pods.Items) != 1 {
  643. return false, fmt.Errorf("Expected 1 pod in current namespace, got %d", len(pods.Items))
  644. }
  645. // Set the pod accordingly
  646. pod = &pods.Items[0]
  647. return true, nil
  648. }
  649. return false, err
  650. }
  651. // Always update the pod so that we can save a GET call to API server later
  652. pod = newPod
  653. // If the pod is found, verify the pod has a ControllerRef
  654. return metav1.GetControllerOf(newPod) != nil, nil
  655. }); err != nil {
  656. t.Fatalf("Failed to verify ControllerRef for pod %s is not nil: %v", pod.Name, err)
  657. }
  658. // Verify the pod has a ControllerRef to the RS
  659. // Do nothing if the pod is nil (i.e., has been picked for deletion)
  660. if pod != nil {
  661. controllerRef := metav1.GetControllerOf(pod)
  662. if controllerRef.UID != rs.UID {
  663. t.Fatalf("RS owner of the pod %s has a different UID: Expected %v, got %v", pod.Name, rs.UID, controllerRef.UID)
  664. }
  665. }
  666. }
  667. func TestGeneralPodAdoption(t *testing.T) {
  668. s, closeFn, rm, informers, c := rmSetup(t)
  669. defer closeFn()
  670. ns := framework.CreateTestingNamespace("test-general-pod-adoption", s, t)
  671. defer framework.DeleteTestingNamespace(ns, s, t)
  672. stopCh := runControllerAndInformers(t, rm, informers, 0)
  673. defer close(stopCh)
  674. rs := newRS("rs", ns.Name, 1)
  675. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  676. rs = rss[0]
  677. waitRSStable(t, c, rs)
  678. podClient := c.CoreV1().Pods(ns.Name)
  679. pods := getPods(t, podClient, labelMap())
  680. if len(pods.Items) != 1 {
  681. t.Fatalf("len(pods) = %d, want 1", len(pods.Items))
  682. }
  683. pod := &pods.Items[0]
  684. var falseVar = false
  685. // When the only OwnerReference of the pod points to another type of API object such as statefulset
  686. // with Controller=false, the RS should add a second OwnerReference (ControllerRef) pointing to itself
  687. // with Controller=true
  688. ownerReference := metav1.OwnerReference{UID: uuid.NewUUID(), APIVersion: "apps/v1", Kind: "StatefulSet", Name: rs.Name, Controller: &falseVar}
  689. testPodControllerRefPatch(t, c, pod, &ownerReference, rs, 2)
  690. // When the only OwnerReference of the pod points to the RS, but Controller=false
  691. ownerReference = metav1.OwnerReference{UID: rs.UID, APIVersion: "apps/v1", Kind: "ReplicaSet", Name: rs.Name, Controller: &falseVar}
  692. testPodControllerRefPatch(t, c, pod, &ownerReference, rs, 1)
  693. }
  694. func TestReadyAndAvailableReplicas(t *testing.T) {
  695. s, closeFn, rm, informers, c := rmSetup(t)
  696. defer closeFn()
  697. ns := framework.CreateTestingNamespace("test-ready-and-available-replicas", s, t)
  698. defer framework.DeleteTestingNamespace(ns, s, t)
  699. stopCh := runControllerAndInformers(t, rm, informers, 0)
  700. defer close(stopCh)
  701. rs := newRS("rs", ns.Name, 3)
  702. rs.Spec.MinReadySeconds = 3600
  703. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  704. rs = rss[0]
  705. waitRSStable(t, c, rs)
  706. // First verify no pod is available
  707. if rs.Status.AvailableReplicas != 0 {
  708. t.Fatalf("Unexpected .Status.AvailableReplicas: Expected 0, saw %d", rs.Status.AvailableReplicas)
  709. }
  710. podClient := c.CoreV1().Pods(ns.Name)
  711. pods := getPods(t, podClient, labelMap())
  712. if len(pods.Items) != 3 {
  713. t.Fatalf("len(pods) = %d, want 3", len(pods.Items))
  714. }
  715. // Separate 3 pods into their own list
  716. firstPodList := &v1.PodList{Items: pods.Items[:1]}
  717. secondPodList := &v1.PodList{Items: pods.Items[1:2]}
  718. thirdPodList := &v1.PodList{Items: pods.Items[2:]}
  719. // First pod: Running, but not Ready
  720. // by setting the Ready condition to false with LastTransitionTime to be now
  721. setPodsReadyCondition(t, c, firstPodList, v1.ConditionFalse, time.Now())
  722. // Second pod: Running and Ready, but not Available
  723. // by setting LastTransitionTime to now
  724. setPodsReadyCondition(t, c, secondPodList, v1.ConditionTrue, time.Now())
  725. // Third pod: Running, Ready, and Available
  726. // by setting LastTransitionTime to more than 3600 seconds ago
  727. setPodsReadyCondition(t, c, thirdPodList, v1.ConditionTrue, time.Now().Add(-120*time.Minute))
  728. rsClient := c.AppsV1().ReplicaSets(ns.Name)
  729. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  730. newRS, err := rsClient.Get(rs.Name, metav1.GetOptions{})
  731. if err != nil {
  732. return false, err
  733. }
  734. // Verify 3 pods exist, 2 pods are Ready, and 1 pod is Available
  735. return newRS.Status.Replicas == 3 && newRS.Status.ReadyReplicas == 2 && newRS.Status.AvailableReplicas == 1, nil
  736. }); err != nil {
  737. t.Fatalf("Failed to verify number of Replicas, ReadyReplicas and AvailableReplicas of rs %s to be as expected: %v", rs.Name, err)
  738. }
  739. }
  740. func TestRSScaleSubresource(t *testing.T) {
  741. s, closeFn, rm, informers, c := rmSetup(t)
  742. defer closeFn()
  743. ns := framework.CreateTestingNamespace("test-rs-scale-subresource", s, t)
  744. defer framework.DeleteTestingNamespace(ns, s, t)
  745. stopCh := runControllerAndInformers(t, rm, informers, 0)
  746. defer close(stopCh)
  747. rs := newRS("rs", ns.Name, 1)
  748. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  749. rs = rss[0]
  750. waitRSStable(t, c, rs)
  751. // Use scale subresource to scale up .Spec.Replicas to 3
  752. testScalingUsingScaleSubresource(t, c, rs, 3)
  753. // Use the scale subresource to scale down .Spec.Replicas to 0
  754. testScalingUsingScaleSubresource(t, c, rs, 0)
  755. }
  756. func TestExtraPodsAdoptionAndDeletion(t *testing.T) {
  757. s, closeFn, rm, informers, c := rmSetup(t)
  758. defer closeFn()
  759. ns := framework.CreateTestingNamespace("test-extra-pods-adoption-and-deletion", s, t)
  760. defer framework.DeleteTestingNamespace(ns, s, t)
  761. rs := newRS("rs", ns.Name, 2)
  762. // Create 3 pods, RS should adopt only 2 of them
  763. podList := []*v1.Pod{}
  764. for i := 0; i < 3; i++ {
  765. pod := newMatchingPod(fmt.Sprintf("pod-%d", i+1), ns.Name)
  766. pod.Labels = labelMap()
  767. podList = append(podList, pod)
  768. }
  769. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, podList)
  770. rs = rss[0]
  771. stopCh := runControllerAndInformers(t, rm, informers, 3)
  772. defer close(stopCh)
  773. waitRSStable(t, c, rs)
  774. // Verify the extra pod is deleted eventually by determining whether number of
  775. // all pods within namespace matches .spec.replicas of the RS (2 in this case)
  776. podClient := c.CoreV1().Pods(ns.Name)
  777. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  778. // All pods have labelMap as their labels
  779. pods := getPods(t, podClient, labelMap())
  780. return int32(len(pods.Items)) == *rs.Spec.Replicas, nil
  781. }); err != nil {
  782. t.Fatalf("Failed to verify number of all pods within current namespace matches .spec.replicas of rs %s: %v", rs.Name, err)
  783. }
  784. }
  785. func TestFullyLabeledReplicas(t *testing.T) {
  786. s, closeFn, rm, informers, c := rmSetup(t)
  787. defer closeFn()
  788. ns := framework.CreateTestingNamespace("test-fully-labeled-replicas", s, t)
  789. defer framework.DeleteTestingNamespace(ns, s, t)
  790. stopCh := runControllerAndInformers(t, rm, informers, 0)
  791. defer close(stopCh)
  792. extraLabelMap := map[string]string{"foo": "bar", "extraKey": "extraValue"}
  793. rs := newRS("rs", ns.Name, 2)
  794. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  795. rs = rss[0]
  796. waitRSStable(t, c, rs)
  797. // Change RS's template labels to have extra labels, but not its selector
  798. rsClient := c.AppsV1().ReplicaSets(ns.Name)
  799. updateRS(t, rsClient, rs.Name, func(rs *apps.ReplicaSet) {
  800. rs.Spec.Template.Labels = extraLabelMap
  801. })
  802. // Set one of the pods to have extra labels
  803. podClient := c.CoreV1().Pods(ns.Name)
  804. pods := getPods(t, podClient, labelMap())
  805. if len(pods.Items) != 2 {
  806. t.Fatalf("len(pods) = %d, want 2", len(pods.Items))
  807. }
  808. fullyLabeledPod := &pods.Items[0]
  809. updatePod(t, podClient, fullyLabeledPod.Name, func(pod *v1.Pod) {
  810. pod.Labels = extraLabelMap
  811. })
  812. // Verify only one pod is fully labeled
  813. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  814. newRS, err := rsClient.Get(rs.Name, metav1.GetOptions{})
  815. if err != nil {
  816. return false, err
  817. }
  818. return (newRS.Status.Replicas == 2 && newRS.Status.FullyLabeledReplicas == 1), nil
  819. }); err != nil {
  820. t.Fatalf("Failed to verify only one pod is fully labeled: %v", err)
  821. }
  822. }
  823. func TestReplicaSetsExtensionsV1beta1DefaultGCPolicy(t *testing.T) {
  824. s, closeFn, rm, informers, c := rmSetup(t)
  825. defer closeFn()
  826. ns := framework.CreateTestingNamespace("test-default-gc-extensions", s, t)
  827. defer framework.DeleteTestingNamespace(ns, s, t)
  828. stopCh := runControllerAndInformers(t, rm, informers, 0)
  829. defer close(stopCh)
  830. rs := newRS("rs", ns.Name, 2)
  831. fakeFinalizer := "kube.io/dummy-finalizer"
  832. rs.Finalizers = []string{fakeFinalizer}
  833. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  834. rs = rss[0]
  835. waitRSStable(t, c, rs)
  836. // Verify RS creates 2 pods
  837. podClient := c.CoreV1().Pods(ns.Name)
  838. pods := getPods(t, podClient, labelMap())
  839. if len(pods.Items) != 2 {
  840. t.Fatalf("len(pods) = %d, want 2", len(pods.Items))
  841. }
  842. // Delete via the extensions/v1beta1 endpoint.
  843. err := c.ExtensionsV1beta1().ReplicaSets(ns.Name).Delete(rs.Name, nil)
  844. if err != nil {
  845. t.Fatalf("Failed to delete rs: %v", err)
  846. }
  847. // Verify orphan finalizer has been added
  848. rsClient := c.AppsV1().ReplicaSets(ns.Name)
  849. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  850. newRS, err := rsClient.Get(rs.Name, metav1.GetOptions{})
  851. if err != nil {
  852. return false, err
  853. }
  854. return slice.ContainsString(newRS.Finalizers, metav1.FinalizerOrphanDependents, nil), nil
  855. }); err != nil {
  856. t.Fatalf("Failed to verify orphan finalizer is added: %v", err)
  857. }
  858. updateRS(t, rsClient, rs.Name, func(rs *apps.ReplicaSet) {
  859. var finalizers []string
  860. // remove fakeFinalizer
  861. for _, finalizer := range rs.Finalizers {
  862. if finalizer != fakeFinalizer {
  863. finalizers = append(finalizers, finalizer)
  864. }
  865. }
  866. rs.Finalizers = finalizers
  867. })
  868. rsClient.Delete(rs.Name, nil)
  869. }
  870. func TestReplicaSetsAppsV1DefaultGCPolicy(t *testing.T) {
  871. s, closeFn, rm, informers, c := rmSetup(t)
  872. defer closeFn()
  873. ns := framework.CreateTestingNamespace("test-default-gc-v1", s, t)
  874. defer framework.DeleteTestingNamespace(ns, s, t)
  875. stopCh := runControllerAndInformers(t, rm, informers, 0)
  876. defer close(stopCh)
  877. rs := newRS("rs", ns.Name, 2)
  878. fakeFinalizer := "kube.io/dummy-finalizer"
  879. rs.Finalizers = []string{fakeFinalizer}
  880. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  881. rs = rss[0]
  882. waitRSStable(t, c, rs)
  883. // Verify RS creates 2 pods
  884. podClient := c.CoreV1().Pods(ns.Name)
  885. pods := getPods(t, podClient, labelMap())
  886. if len(pods.Items) != 2 {
  887. t.Fatalf("len(pods) = %d, want 2", len(pods.Items))
  888. }
  889. rsClient := c.AppsV1().ReplicaSets(ns.Name)
  890. err := rsClient.Delete(rs.Name, nil)
  891. if err != nil {
  892. t.Fatalf("Failed to delete rs: %v", err)
  893. }
  894. // Verify no new finalizer has been added
  895. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  896. newRS, err := rsClient.Get(rs.Name, metav1.GetOptions{})
  897. if err != nil {
  898. return false, err
  899. }
  900. if newRS.DeletionTimestamp == nil {
  901. return false, nil
  902. }
  903. if got, want := newRS.Finalizers, []string{fakeFinalizer}; !reflect.DeepEqual(got, want) {
  904. return false, fmt.Errorf("got finalizers: %+v; want: %+v", got, want)
  905. }
  906. return true, nil
  907. }); err != nil {
  908. t.Fatalf("Failed to verify the finalizer: %v", err)
  909. }
  910. updateRS(t, c.AppsV1().ReplicaSets(ns.Name), rs.Name, func(rs *apps.ReplicaSet) {
  911. var finalizers []string
  912. // remove fakeFinalizer
  913. for _, finalizer := range rs.Finalizers {
  914. if finalizer != fakeFinalizer {
  915. finalizers = append(finalizers, finalizer)
  916. }
  917. }
  918. rs.Finalizers = finalizers
  919. })
  920. rsClient.Delete(rs.Name, nil)
  921. }