replicationcontroller_test.go 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  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 replicationcontroller
  14. import (
  15. "context"
  16. "fmt"
  17. "net/http/httptest"
  18. "reflect"
  19. "testing"
  20. "time"
  21. "k8s.io/api/core/v1"
  22. apierrors "k8s.io/apimachinery/pkg/api/errors"
  23. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  24. "k8s.io/apimachinery/pkg/labels"
  25. "k8s.io/apimachinery/pkg/util/uuid"
  26. "k8s.io/apimachinery/pkg/util/wait"
  27. "k8s.io/client-go/informers"
  28. clientset "k8s.io/client-go/kubernetes"
  29. typedv1 "k8s.io/client-go/kubernetes/typed/core/v1"
  30. restclient "k8s.io/client-go/rest"
  31. "k8s.io/client-go/tools/cache"
  32. "k8s.io/client-go/util/retry"
  33. podutil "k8s.io/kubernetes/pkg/api/v1/pod"
  34. "k8s.io/kubernetes/pkg/controller/replication"
  35. "k8s.io/kubernetes/test/integration/framework"
  36. )
  37. const (
  38. interval = 100 * time.Millisecond
  39. timeout = 60 * time.Second
  40. )
  41. func labelMap() map[string]string {
  42. return map[string]string{"foo": "bar"}
  43. }
  44. func newRC(name, namespace string, replicas int) *v1.ReplicationController {
  45. replicasCopy := int32(replicas)
  46. return &v1.ReplicationController{
  47. TypeMeta: metav1.TypeMeta{
  48. Kind: "ReplicationController",
  49. APIVersion: "v1",
  50. },
  51. ObjectMeta: metav1.ObjectMeta{
  52. Namespace: namespace,
  53. Name: name,
  54. },
  55. Spec: v1.ReplicationControllerSpec{
  56. Selector: labelMap(),
  57. Replicas: &replicasCopy,
  58. Template: &v1.PodTemplateSpec{
  59. ObjectMeta: metav1.ObjectMeta{
  60. Labels: labelMap(),
  61. },
  62. Spec: v1.PodSpec{
  63. Containers: []v1.Container{
  64. {
  65. Name: "fake-name",
  66. Image: "fakeimage",
  67. },
  68. },
  69. },
  70. },
  71. },
  72. }
  73. }
  74. func newMatchingPod(podName, namespace string) *v1.Pod {
  75. return &v1.Pod{
  76. TypeMeta: metav1.TypeMeta{
  77. Kind: "Pod",
  78. APIVersion: "v1",
  79. },
  80. ObjectMeta: metav1.ObjectMeta{
  81. Name: podName,
  82. Namespace: namespace,
  83. Labels: labelMap(),
  84. },
  85. Spec: v1.PodSpec{
  86. Containers: []v1.Container{
  87. {
  88. Name: "fake-name",
  89. Image: "fakeimage",
  90. },
  91. },
  92. },
  93. Status: v1.PodStatus{
  94. Phase: v1.PodRunning,
  95. },
  96. }
  97. }
  98. func rmSetup(t *testing.T) (*httptest.Server, framework.CloseFunc, *replication.ReplicationManager, informers.SharedInformerFactory, clientset.Interface) {
  99. masterConfig := framework.NewIntegrationTestMasterConfig()
  100. _, s, closeFn := framework.RunAMaster(masterConfig)
  101. config := restclient.Config{Host: s.URL}
  102. clientSet, err := clientset.NewForConfig(&config)
  103. if err != nil {
  104. t.Fatalf("Error in create clientset: %v", err)
  105. }
  106. resyncPeriod := 12 * time.Hour
  107. informers := informers.NewSharedInformerFactory(clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "rc-informers")), resyncPeriod)
  108. rm := replication.NewReplicationManager(
  109. informers.Core().V1().Pods(),
  110. informers.Core().V1().ReplicationControllers(),
  111. clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "replication-controller")),
  112. replication.BurstReplicas,
  113. )
  114. if err != nil {
  115. t.Fatalf("Failed to create replication controller")
  116. }
  117. return s, closeFn, rm, informers, clientSet
  118. }
  119. // Run RC controller and informers
  120. func runControllerAndInformers(t *testing.T, rm *replication.ReplicationManager, informers informers.SharedInformerFactory, podNum int) chan struct{} {
  121. stopCh := make(chan struct{})
  122. informers.Start(stopCh)
  123. waitToObservePods(t, informers.Core().V1().Pods().Informer(), podNum)
  124. go rm.Run(5, stopCh)
  125. return stopCh
  126. }
  127. // wait for the podInformer to observe the pods. Call this function before
  128. // running the RC controller to prevent the rc manager from creating new pods
  129. // rather than adopting the existing ones.
  130. func waitToObservePods(t *testing.T, podInformer cache.SharedIndexInformer, podNum int) {
  131. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  132. objects := podInformer.GetIndexer().List()
  133. return len(objects) == podNum, nil
  134. }); err != nil {
  135. t.Fatalf("Error encountered when waiting for podInformer to observe the pods: %v", err)
  136. }
  137. }
  138. func createRCsPods(t *testing.T, clientSet clientset.Interface, rcs []*v1.ReplicationController, pods []*v1.Pod) ([]*v1.ReplicationController, []*v1.Pod) {
  139. var createdRCs []*v1.ReplicationController
  140. var createdPods []*v1.Pod
  141. for _, rc := range rcs {
  142. createdRC, err := clientSet.CoreV1().ReplicationControllers(rc.Namespace).Create(context.TODO(), rc, metav1.CreateOptions{})
  143. if err != nil {
  144. t.Fatalf("Failed to create replication controller %s: %v", rc.Name, err)
  145. }
  146. createdRCs = append(createdRCs, createdRC)
  147. }
  148. for _, pod := range pods {
  149. createdPod, err := clientSet.CoreV1().Pods(pod.Namespace).Create(context.TODO(), pod, metav1.CreateOptions{})
  150. if err != nil {
  151. t.Fatalf("Failed to create pod %s: %v", pod.Name, err)
  152. }
  153. createdPods = append(createdPods, createdPod)
  154. }
  155. return createdRCs, createdPods
  156. }
  157. // Verify .Status.Replicas is equal to .Spec.Replicas
  158. func waitRCStable(t *testing.T, clientSet clientset.Interface, rc *v1.ReplicationController) {
  159. rcClient := clientSet.CoreV1().ReplicationControllers(rc.Namespace)
  160. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  161. newRC, err := rcClient.Get(context.TODO(), rc.Name, metav1.GetOptions{})
  162. if err != nil {
  163. return false, err
  164. }
  165. return newRC.Status.Replicas == *rc.Spec.Replicas, nil
  166. }); err != nil {
  167. t.Fatalf("Failed to verify .Status.Replicas is equal to .Spec.Replicas for rc %s: %v", rc.Name, err)
  168. }
  169. }
  170. // Update .Spec.Replicas to replicas and verify .Status.Replicas is changed accordingly
  171. func scaleRC(t *testing.T, c clientset.Interface, rc *v1.ReplicationController, replicas int32) {
  172. rcClient := c.CoreV1().ReplicationControllers(rc.Namespace)
  173. rc = updateRC(t, rcClient, rc.Name, func(rc *v1.ReplicationController) {
  174. *rc.Spec.Replicas = replicas
  175. })
  176. waitRCStable(t, c, rc)
  177. }
  178. func updatePod(t *testing.T, podClient typedv1.PodInterface, podName string, updateFunc func(*v1.Pod)) *v1.Pod {
  179. var pod *v1.Pod
  180. if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
  181. newPod, err := podClient.Get(context.TODO(), podName, metav1.GetOptions{})
  182. if err != nil {
  183. return err
  184. }
  185. updateFunc(newPod)
  186. pod, err = podClient.Update(context.TODO(), newPod, metav1.UpdateOptions{})
  187. return err
  188. }); err != nil {
  189. t.Fatalf("Failed to update pod %s: %v", podName, err)
  190. }
  191. return pod
  192. }
  193. func updatePodStatus(t *testing.T, podClient typedv1.PodInterface, pod *v1.Pod, updateStatusFunc func(*v1.Pod)) {
  194. if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
  195. newPod, err := podClient.Get(context.TODO(), pod.Name, metav1.GetOptions{})
  196. if err != nil {
  197. return err
  198. }
  199. updateStatusFunc(newPod)
  200. _, err = podClient.UpdateStatus(context.TODO(), newPod, metav1.UpdateOptions{})
  201. return err
  202. }); err != nil {
  203. t.Fatalf("Failed to update status of pod %s: %v", pod.Name, err)
  204. }
  205. }
  206. func getPods(t *testing.T, podClient typedv1.PodInterface, labelMap map[string]string) *v1.PodList {
  207. podSelector := labels.Set(labelMap).AsSelector()
  208. options := metav1.ListOptions{LabelSelector: podSelector.String()}
  209. pods, err := podClient.List(context.TODO(), options)
  210. if err != nil {
  211. t.Fatalf("Failed obtaining a list of pods that match the pod labels %v: %v", labelMap, err)
  212. }
  213. return pods
  214. }
  215. func updateRC(t *testing.T, rcClient typedv1.ReplicationControllerInterface, rcName string, updateFunc func(*v1.ReplicationController)) *v1.ReplicationController {
  216. var rc *v1.ReplicationController
  217. if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
  218. newRC, err := rcClient.Get(context.TODO(), rcName, metav1.GetOptions{})
  219. if err != nil {
  220. return err
  221. }
  222. updateFunc(newRC)
  223. rc, err = rcClient.Update(context.TODO(), newRC, metav1.UpdateOptions{})
  224. return err
  225. }); err != nil {
  226. t.Fatalf("Failed to update rc %s: %v", rcName, err)
  227. }
  228. return rc
  229. }
  230. // Verify ControllerRef of a RC pod that has incorrect attributes is automatically patched by the RC
  231. func testPodControllerRefPatch(t *testing.T, c clientset.Interface, pod *v1.Pod, ownerReference *metav1.OwnerReference, rc *v1.ReplicationController, expectedOwnerReferenceNum int) {
  232. ns := rc.Namespace
  233. podClient := c.CoreV1().Pods(ns)
  234. updatePod(t, podClient, pod.Name, func(pod *v1.Pod) {
  235. pod.OwnerReferences = []metav1.OwnerReference{*ownerReference}
  236. })
  237. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  238. newPod, err := podClient.Get(context.TODO(), pod.Name, metav1.GetOptions{})
  239. if err != nil {
  240. return false, err
  241. }
  242. return metav1.GetControllerOf(newPod) != nil, nil
  243. }); err != nil {
  244. t.Fatalf("Failed to verify ControllerRef for the pod %s is not nil: %v", pod.Name, err)
  245. }
  246. newPod, err := podClient.Get(context.TODO(), pod.Name, metav1.GetOptions{})
  247. if err != nil {
  248. t.Fatalf("Failed to obtain pod %s: %v", pod.Name, err)
  249. }
  250. controllerRef := metav1.GetControllerOf(newPod)
  251. if controllerRef.UID != rc.UID {
  252. t.Fatalf("RC owner of the pod %s has a different UID: Expected %v, got %v", newPod.Name, rc.UID, controllerRef.UID)
  253. }
  254. ownerReferenceNum := len(newPod.GetOwnerReferences())
  255. if ownerReferenceNum != expectedOwnerReferenceNum {
  256. t.Fatalf("Unexpected number of owner references for pod %s: Expected %d, got %d", newPod.Name, expectedOwnerReferenceNum, ownerReferenceNum)
  257. }
  258. }
  259. func setPodsReadyCondition(t *testing.T, clientSet clientset.Interface, pods *v1.PodList, conditionStatus v1.ConditionStatus, lastTransitionTime time.Time) {
  260. replicas := int32(len(pods.Items))
  261. var readyPods int32
  262. err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  263. readyPods = 0
  264. for i := range pods.Items {
  265. pod := &pods.Items[i]
  266. if podutil.IsPodReady(pod) {
  267. readyPods++
  268. continue
  269. }
  270. pod.Status.Phase = v1.PodRunning
  271. _, condition := podutil.GetPodCondition(&pod.Status, v1.PodReady)
  272. if condition != nil {
  273. condition.Status = conditionStatus
  274. condition.LastTransitionTime = metav1.Time{Time: lastTransitionTime}
  275. } else {
  276. condition = &v1.PodCondition{
  277. Type: v1.PodReady,
  278. Status: conditionStatus,
  279. LastTransitionTime: metav1.Time{Time: lastTransitionTime},
  280. }
  281. pod.Status.Conditions = append(pod.Status.Conditions, *condition)
  282. }
  283. _, err := clientSet.CoreV1().Pods(pod.Namespace).UpdateStatus(context.TODO(), pod, metav1.UpdateOptions{})
  284. if err != nil {
  285. // When status fails to be updated, we continue to next pod
  286. continue
  287. }
  288. readyPods++
  289. }
  290. return readyPods >= replicas, nil
  291. })
  292. if err != nil {
  293. t.Fatalf("failed to mark all ReplicationController pods to ready: %v", err)
  294. }
  295. }
  296. func testScalingUsingScaleSubresource(t *testing.T, c clientset.Interface, rc *v1.ReplicationController, replicas int32) {
  297. ns := rc.Namespace
  298. rcClient := c.CoreV1().ReplicationControllers(ns)
  299. newRC, err := rcClient.Get(context.TODO(), rc.Name, metav1.GetOptions{})
  300. if err != nil {
  301. t.Fatalf("Failed to obtain rc %s: %v", rc.Name, err)
  302. }
  303. scale, err := c.CoreV1().ReplicationControllers(ns).GetScale(context.TODO(), rc.Name, metav1.GetOptions{})
  304. if err != nil {
  305. t.Fatalf("Failed to obtain scale subresource for rc %s: %v", rc.Name, err)
  306. }
  307. if scale.Spec.Replicas != *newRC.Spec.Replicas {
  308. t.Fatalf("Scale subresource for rc %s does not match .Spec.Replicas: expected %d, got %d", rc.Name, *newRC.Spec.Replicas, scale.Spec.Replicas)
  309. }
  310. if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
  311. scale, err := c.CoreV1().ReplicationControllers(ns).GetScale(context.TODO(), rc.Name, metav1.GetOptions{})
  312. if err != nil {
  313. return err
  314. }
  315. scale.Spec.Replicas = replicas
  316. _, err = c.CoreV1().ReplicationControllers(ns).UpdateScale(context.TODO(), rc.Name, scale, metav1.UpdateOptions{})
  317. return err
  318. }); err != nil {
  319. t.Fatalf("Failed to set .Spec.Replicas of scale subresource for rc %s: %v", rc.Name, err)
  320. }
  321. newRC, err = rcClient.Get(context.TODO(), rc.Name, metav1.GetOptions{})
  322. if err != nil {
  323. t.Fatalf("Failed to obtain rc %s: %v", rc.Name, err)
  324. }
  325. if *newRC.Spec.Replicas != replicas {
  326. t.Fatalf(".Spec.Replicas of rc %s does not match its scale subresource: expected %d, got %d", rc.Name, replicas, *newRC.Spec.Replicas)
  327. }
  328. }
  329. func TestAdoption(t *testing.T) {
  330. boolPtr := func(b bool) *bool { return &b }
  331. testCases := []struct {
  332. name string
  333. existingOwnerReferences func(rc *v1.ReplicationController) []metav1.OwnerReference
  334. expectedOwnerReferences func(rc *v1.ReplicationController) []metav1.OwnerReference
  335. }{
  336. {
  337. "pod refers rc as an owner, not a controller",
  338. func(rc *v1.ReplicationController) []metav1.OwnerReference {
  339. return []metav1.OwnerReference{{UID: rc.UID, Name: rc.Name, APIVersion: "v1", Kind: "ReplicationController"}}
  340. },
  341. func(rc *v1.ReplicationController) []metav1.OwnerReference {
  342. return []metav1.OwnerReference{{UID: rc.UID, Name: rc.Name, APIVersion: "v1", Kind: "ReplicationController", Controller: boolPtr(true), BlockOwnerDeletion: boolPtr(true)}}
  343. },
  344. },
  345. {
  346. "pod doesn't have owner references",
  347. func(rc *v1.ReplicationController) []metav1.OwnerReference {
  348. return []metav1.OwnerReference{}
  349. },
  350. func(rc *v1.ReplicationController) []metav1.OwnerReference {
  351. return []metav1.OwnerReference{{UID: rc.UID, Name: rc.Name, APIVersion: "v1", Kind: "ReplicationController", Controller: boolPtr(true), BlockOwnerDeletion: boolPtr(true)}}
  352. },
  353. },
  354. {
  355. "pod refers rc as a controller",
  356. func(rc *v1.ReplicationController) []metav1.OwnerReference {
  357. return []metav1.OwnerReference{{UID: rc.UID, Name: rc.Name, APIVersion: "v1", Kind: "ReplicationController", Controller: boolPtr(true)}}
  358. },
  359. func(rc *v1.ReplicationController) []metav1.OwnerReference {
  360. return []metav1.OwnerReference{{UID: rc.UID, Name: rc.Name, APIVersion: "v1", Kind: "ReplicationController", Controller: boolPtr(true)}}
  361. },
  362. },
  363. {
  364. "pod refers other rc as the controller, refers the rc as an owner",
  365. func(rc *v1.ReplicationController) []metav1.OwnerReference {
  366. return []metav1.OwnerReference{
  367. {UID: "1", Name: "anotherRC", APIVersion: "v1", Kind: "ReplicationController", Controller: boolPtr(true)},
  368. {UID: rc.UID, Name: rc.Name, APIVersion: "v1", Kind: "ReplicationController"},
  369. }
  370. },
  371. func(rc *v1.ReplicationController) []metav1.OwnerReference {
  372. return []metav1.OwnerReference{
  373. {UID: "1", Name: "anotherRC", APIVersion: "v1", Kind: "ReplicationController", Controller: boolPtr(true)},
  374. {UID: rc.UID, Name: rc.Name, APIVersion: "v1", Kind: "ReplicationController"},
  375. }
  376. },
  377. },
  378. }
  379. for i, tc := range testCases {
  380. func() {
  381. s, closeFn, rm, informers, clientSet := rmSetup(t)
  382. defer closeFn()
  383. ns := framework.CreateTestingNamespace(fmt.Sprintf("rc-adoption-%d", i), s, t)
  384. defer framework.DeleteTestingNamespace(ns, s, t)
  385. rcClient := clientSet.CoreV1().ReplicationControllers(ns.Name)
  386. podClient := clientSet.CoreV1().Pods(ns.Name)
  387. const rcName = "rc"
  388. rc, err := rcClient.Create(context.TODO(), newRC(rcName, ns.Name, 1), metav1.CreateOptions{})
  389. if err != nil {
  390. t.Fatalf("Failed to create replication controllers: %v", err)
  391. }
  392. podName := fmt.Sprintf("pod%d", i)
  393. pod := newMatchingPod(podName, ns.Name)
  394. pod.OwnerReferences = tc.existingOwnerReferences(rc)
  395. _, err = podClient.Create(context.TODO(), pod, metav1.CreateOptions{})
  396. if err != nil {
  397. t.Fatalf("Failed to create Pod: %v", err)
  398. }
  399. stopCh := runControllerAndInformers(t, rm, informers, 1)
  400. defer close(stopCh)
  401. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  402. updatedPod, err := podClient.Get(context.TODO(), pod.Name, metav1.GetOptions{})
  403. if err != nil {
  404. return false, err
  405. }
  406. e, a := tc.expectedOwnerReferences(rc), updatedPod.OwnerReferences
  407. if reflect.DeepEqual(e, a) {
  408. return true, nil
  409. }
  410. t.Logf("ownerReferences don't match, expect %v, got %v", e, a)
  411. return false, nil
  412. }); err != nil {
  413. t.Fatalf("test %q failed: %v", tc.name, err)
  414. }
  415. }()
  416. }
  417. }
  418. func TestSpecReplicasChange(t *testing.T) {
  419. s, closeFn, rm, informers, c := rmSetup(t)
  420. defer closeFn()
  421. ns := framework.CreateTestingNamespace("test-spec-replicas-change", s, t)
  422. defer framework.DeleteTestingNamespace(ns, s, t)
  423. stopCh := runControllerAndInformers(t, rm, informers, 0)
  424. defer close(stopCh)
  425. rc := newRC("rc", ns.Name, 2)
  426. rcs, _ := createRCsPods(t, c, []*v1.ReplicationController{rc}, []*v1.Pod{})
  427. rc = rcs[0]
  428. waitRCStable(t, c, rc)
  429. // Update .Spec.Replicas and verify .Status.Replicas is changed accordingly
  430. scaleRC(t, c, rc, 3)
  431. scaleRC(t, c, rc, 0)
  432. scaleRC(t, c, rc, 2)
  433. // Add a template annotation change to test RC's status does update
  434. // without .Spec.Replicas change
  435. rcClient := c.CoreV1().ReplicationControllers(ns.Name)
  436. var oldGeneration int64
  437. newRC := updateRC(t, rcClient, rc.Name, func(rc *v1.ReplicationController) {
  438. oldGeneration = rc.Generation
  439. rc.Spec.Template.Annotations = map[string]string{"test": "annotation"}
  440. })
  441. savedGeneration := newRC.Generation
  442. if savedGeneration == oldGeneration {
  443. t.Fatalf("Failed to verify .Generation has incremented for rc %s", rc.Name)
  444. }
  445. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  446. newRC, err := rcClient.Get(context.TODO(), rc.Name, metav1.GetOptions{})
  447. if err != nil {
  448. return false, err
  449. }
  450. return newRC.Status.ObservedGeneration >= savedGeneration, nil
  451. }); err != nil {
  452. t.Fatalf("Failed to verify .Status.ObservedGeneration has incremented for rc %s: %v", rc.Name, err)
  453. }
  454. }
  455. func TestDeletingAndFailedPods(t *testing.T) {
  456. s, closeFn, rm, informers, c := rmSetup(t)
  457. defer closeFn()
  458. ns := framework.CreateTestingNamespace("test-deleting-and-failed-pods", s, t)
  459. defer framework.DeleteTestingNamespace(ns, s, t)
  460. stopCh := runControllerAndInformers(t, rm, informers, 0)
  461. defer close(stopCh)
  462. rc := newRC("rc", ns.Name, 2)
  463. rcs, _ := createRCsPods(t, c, []*v1.ReplicationController{rc}, []*v1.Pod{})
  464. rc = rcs[0]
  465. waitRCStable(t, c, rc)
  466. // Verify RC creates 2 pods
  467. podClient := c.CoreV1().Pods(ns.Name)
  468. pods := getPods(t, podClient, labelMap())
  469. if len(pods.Items) != 2 {
  470. t.Fatalf("len(pods) = %d, want 2", len(pods.Items))
  471. }
  472. // Set first pod as deleting pod
  473. // Set finalizers for the pod to simulate pending deletion status
  474. deletingPod := &pods.Items[0]
  475. updatePod(t, podClient, deletingPod.Name, func(pod *v1.Pod) {
  476. pod.Finalizers = []string{"fake.example.com/blockDeletion"}
  477. })
  478. if err := c.CoreV1().Pods(ns.Name).Delete(context.TODO(), deletingPod.Name, &metav1.DeleteOptions{}); err != nil {
  479. t.Fatalf("Error deleting pod %s: %v", deletingPod.Name, err)
  480. }
  481. // Set second pod as failed pod
  482. failedPod := &pods.Items[1]
  483. updatePodStatus(t, podClient, failedPod, func(pod *v1.Pod) {
  484. pod.Status.Phase = v1.PodFailed
  485. })
  486. // Pool until 2 new pods have been created to replace deleting and failed pods
  487. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  488. pods = getPods(t, podClient, labelMap())
  489. return len(pods.Items) == 4, nil
  490. }); err != nil {
  491. t.Fatalf("Failed to verify 2 new pods have been created (expected 4 pods): %v", err)
  492. }
  493. // Verify deleting and failed pods are among the four pods
  494. foundDeletingPod := false
  495. foundFailedPod := false
  496. for _, pod := range pods.Items {
  497. if pod.UID == deletingPod.UID {
  498. foundDeletingPod = true
  499. }
  500. if pod.UID == failedPod.UID {
  501. foundFailedPod = true
  502. }
  503. }
  504. // Verify deleting pod exists
  505. if !foundDeletingPod {
  506. t.Fatalf("expected deleting pod %s exists, but it is not found", deletingPod.Name)
  507. }
  508. // Verify failed pod exists
  509. if !foundFailedPod {
  510. t.Fatalf("expected failed pod %s exists, but it is not found", failedPod.Name)
  511. }
  512. }
  513. func TestOverlappingRCs(t *testing.T) {
  514. s, closeFn, rm, informers, c := rmSetup(t)
  515. defer closeFn()
  516. ns := framework.CreateTestingNamespace("test-overlapping-rcs", s, t)
  517. defer framework.DeleteTestingNamespace(ns, s, t)
  518. stopCh := runControllerAndInformers(t, rm, informers, 0)
  519. defer close(stopCh)
  520. // Create 2 RCs with identical selectors
  521. for i := 0; i < 2; i++ {
  522. // One RC has 1 replica, and another has 2 replicas
  523. rc := newRC(fmt.Sprintf("rc-%d", i+1), ns.Name, i+1)
  524. rcs, _ := createRCsPods(t, c, []*v1.ReplicationController{rc}, []*v1.Pod{})
  525. waitRCStable(t, c, rcs[0])
  526. }
  527. // Expect 3 total Pods to be created
  528. podClient := c.CoreV1().Pods(ns.Name)
  529. pods := getPods(t, podClient, labelMap())
  530. if len(pods.Items) != 3 {
  531. t.Errorf("len(pods) = %d, want 3", len(pods.Items))
  532. }
  533. // Expect both RCs have .status.replicas = .spec.replicas
  534. for i := 0; i < 2; i++ {
  535. newRC, err := c.CoreV1().ReplicationControllers(ns.Name).Get(context.TODO(), fmt.Sprintf("rc-%d", i+1), metav1.GetOptions{})
  536. if err != nil {
  537. t.Fatalf("failed to obtain rc rc-%d: %v", i+1, err)
  538. }
  539. if newRC.Status.Replicas != *newRC.Spec.Replicas {
  540. t.Fatalf(".Status.Replicas %d is not equal to .Spec.Replicas %d", newRC.Status.Replicas, *newRC.Spec.Replicas)
  541. }
  542. }
  543. }
  544. func TestPodOrphaningAndAdoptionWhenLabelsChange(t *testing.T) {
  545. s, closeFn, rm, informers, c := rmSetup(t)
  546. defer closeFn()
  547. ns := framework.CreateTestingNamespace("test-pod-orphaning-and-adoption-when-labels-change", s, t)
  548. defer framework.DeleteTestingNamespace(ns, s, t)
  549. stopCh := runControllerAndInformers(t, rm, informers, 0)
  550. defer close(stopCh)
  551. rc := newRC("rc", ns.Name, 1)
  552. rcs, _ := createRCsPods(t, c, []*v1.ReplicationController{rc}, []*v1.Pod{})
  553. rc = rcs[0]
  554. waitRCStable(t, c, rc)
  555. // Orphaning: RC should remove OwnerReference from a pod when the pod's labels change to not match its labels
  556. podClient := c.CoreV1().Pods(ns.Name)
  557. pods := getPods(t, podClient, labelMap())
  558. if len(pods.Items) != 1 {
  559. t.Fatalf("len(pods) = %d, want 1", len(pods.Items))
  560. }
  561. pod := &pods.Items[0]
  562. // Start by verifying ControllerRef for the pod is not nil
  563. if metav1.GetControllerOf(pod) == nil {
  564. t.Fatalf("ControllerRef of pod %s is nil", pod.Name)
  565. }
  566. newLabelMap := map[string]string{"new-foo": "new-bar"}
  567. updatePod(t, podClient, pod.Name, func(pod *v1.Pod) {
  568. pod.Labels = newLabelMap
  569. })
  570. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  571. newPod, err := podClient.Get(context.TODO(), pod.Name, metav1.GetOptions{})
  572. if err != nil {
  573. return false, err
  574. }
  575. pod = newPod
  576. return metav1.GetControllerOf(newPod) == nil, nil
  577. }); err != nil {
  578. t.Fatalf("Failed to verify ControllerRef for the pod %s is nil: %v", pod.Name, err)
  579. }
  580. // Adoption: RC should add ControllerRef to a pod when the pod's labels change to match its labels
  581. updatePod(t, podClient, pod.Name, func(pod *v1.Pod) {
  582. pod.Labels = labelMap()
  583. })
  584. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  585. newPod, err := podClient.Get(context.TODO(), pod.Name, metav1.GetOptions{})
  586. if err != nil {
  587. // If the pod is not found, it means the RC picks the pod for deletion (it is extra)
  588. // Verify there is only one pod in namespace and it has ControllerRef to the RC
  589. if apierrors.IsNotFound(err) {
  590. pods := getPods(t, podClient, labelMap())
  591. if len(pods.Items) != 1 {
  592. return false, fmt.Errorf("Expected 1 pod in current namespace, got %d", len(pods.Items))
  593. }
  594. // Set the pod accordingly
  595. pod = &pods.Items[0]
  596. return true, nil
  597. }
  598. return false, err
  599. }
  600. // Always update the pod so that we can save a GET call to API server later
  601. pod = newPod
  602. // If the pod is found, verify the pod has a ControllerRef
  603. return metav1.GetControllerOf(newPod) != nil, nil
  604. }); err != nil {
  605. t.Fatalf("Failed to verify ControllerRef for pod %s is not nil: %v", pod.Name, err)
  606. }
  607. // Verify the pod has a ControllerRef to the RC
  608. // Do nothing if the pod is nil (i.e., has been picked for deletion)
  609. if pod != nil {
  610. controllerRef := metav1.GetControllerOf(pod)
  611. if controllerRef.UID != rc.UID {
  612. t.Fatalf("RC owner of the pod %s has a different UID: Expected %v, got %v", pod.Name, rc.UID, controllerRef.UID)
  613. }
  614. }
  615. }
  616. func TestGeneralPodAdoption(t *testing.T) {
  617. s, closeFn, rm, informers, c := rmSetup(t)
  618. defer closeFn()
  619. ns := framework.CreateTestingNamespace("test-general-pod-adoption", s, t)
  620. defer framework.DeleteTestingNamespace(ns, s, t)
  621. stopCh := runControllerAndInformers(t, rm, informers, 0)
  622. defer close(stopCh)
  623. rc := newRC("rc", ns.Name, 1)
  624. rcs, _ := createRCsPods(t, c, []*v1.ReplicationController{rc}, []*v1.Pod{})
  625. rc = rcs[0]
  626. waitRCStable(t, c, rc)
  627. podClient := c.CoreV1().Pods(ns.Name)
  628. pods := getPods(t, podClient, labelMap())
  629. if len(pods.Items) != 1 {
  630. t.Fatalf("len(pods) = %d, want 1", len(pods.Items))
  631. }
  632. pod := &pods.Items[0]
  633. var falseVar = false
  634. // When the only OwnerReference of the pod points to another type of API object such as statefulset
  635. // with Controller=false, the RC should add a second OwnerReference (ControllerRef) pointing to itself
  636. // with Controller=true
  637. ownerReference := metav1.OwnerReference{UID: uuid.NewUUID(), APIVersion: "apps/v1beta1", Kind: "StatefulSet", Name: rc.Name, Controller: &falseVar}
  638. testPodControllerRefPatch(t, c, pod, &ownerReference, rc, 2)
  639. // When the only OwnerReference of the pod points to the RC, but Controller=false
  640. ownerReference = metav1.OwnerReference{UID: rc.UID, APIVersion: "v1", Kind: "ReplicationController", Name: rc.Name, Controller: &falseVar}
  641. testPodControllerRefPatch(t, c, pod, &ownerReference, rc, 1)
  642. }
  643. func TestReadyAndAvailableReplicas(t *testing.T) {
  644. s, closeFn, rm, informers, c := rmSetup(t)
  645. defer closeFn()
  646. ns := framework.CreateTestingNamespace("test-ready-and-available-replicas", s, t)
  647. defer framework.DeleteTestingNamespace(ns, s, t)
  648. stopCh := runControllerAndInformers(t, rm, informers, 0)
  649. defer close(stopCh)
  650. rc := newRC("rc", ns.Name, 3)
  651. rc.Spec.MinReadySeconds = 3600
  652. rcs, _ := createRCsPods(t, c, []*v1.ReplicationController{rc}, []*v1.Pod{})
  653. rc = rcs[0]
  654. waitRCStable(t, c, rc)
  655. // First verify no pod is available
  656. if rc.Status.AvailableReplicas != 0 {
  657. t.Fatalf("Unexpected .Status.AvailableReplicas: Expected 0, saw %d", rc.Status.AvailableReplicas)
  658. }
  659. podClient := c.CoreV1().Pods(ns.Name)
  660. pods := getPods(t, podClient, labelMap())
  661. if len(pods.Items) != 3 {
  662. t.Fatalf("len(pods) = %d, want 3", len(pods.Items))
  663. }
  664. // Separate 3 pods into their own list
  665. firstPodList := &v1.PodList{Items: pods.Items[:1]}
  666. secondPodList := &v1.PodList{Items: pods.Items[1:2]}
  667. thirdPodList := &v1.PodList{Items: pods.Items[2:]}
  668. // First pod: Running, but not Ready
  669. // by setting the Ready condition to false with LastTransitionTime to be now
  670. setPodsReadyCondition(t, c, firstPodList, v1.ConditionFalse, time.Now())
  671. // Second pod: Running and Ready, but not Available
  672. // by setting LastTransitionTime to now
  673. setPodsReadyCondition(t, c, secondPodList, v1.ConditionTrue, time.Now())
  674. // Third pod: Running, Ready, and Available
  675. // by setting LastTransitionTime to more than 3600 seconds ago
  676. setPodsReadyCondition(t, c, thirdPodList, v1.ConditionTrue, time.Now().Add(-120*time.Minute))
  677. rcClient := c.CoreV1().ReplicationControllers(ns.Name)
  678. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  679. newRC, err := rcClient.Get(context.TODO(), rc.Name, metav1.GetOptions{})
  680. if err != nil {
  681. return false, err
  682. }
  683. // Verify 3 pods exist, 2 pods are Ready, and 1 pod is Available
  684. return newRC.Status.Replicas == 3 && newRC.Status.ReadyReplicas == 2 && newRC.Status.AvailableReplicas == 1, nil
  685. }); err != nil {
  686. t.Fatalf("Failed to verify number of Replicas, ReadyReplicas and AvailableReplicas of rc %s to be as expected: %v", rc.Name, err)
  687. }
  688. }
  689. func TestRCScaleSubresource(t *testing.T) {
  690. s, closeFn, rm, informers, c := rmSetup(t)
  691. defer closeFn()
  692. ns := framework.CreateTestingNamespace("test-rc-scale-subresource", s, t)
  693. defer framework.DeleteTestingNamespace(ns, s, t)
  694. stopCh := runControllerAndInformers(t, rm, informers, 0)
  695. defer close(stopCh)
  696. rc := newRC("rc", ns.Name, 1)
  697. rcs, _ := createRCsPods(t, c, []*v1.ReplicationController{rc}, []*v1.Pod{})
  698. rc = rcs[0]
  699. waitRCStable(t, c, rc)
  700. // Use scale subresource to scale up .Spec.Replicas to 3
  701. testScalingUsingScaleSubresource(t, c, rc, 3)
  702. // Use the scale subresource to scale down .Spec.Replicas to 0
  703. testScalingUsingScaleSubresource(t, c, rc, 0)
  704. }
  705. func TestExtraPodsAdoptionAndDeletion(t *testing.T) {
  706. s, closeFn, rm, informers, c := rmSetup(t)
  707. defer closeFn()
  708. ns := framework.CreateTestingNamespace("test-extra-pods-adoption-and-deletion", s, t)
  709. defer framework.DeleteTestingNamespace(ns, s, t)
  710. rc := newRC("rc", ns.Name, 2)
  711. // Create 3 pods, RC should adopt only 2 of them
  712. podList := []*v1.Pod{}
  713. for i := 0; i < 3; i++ {
  714. pod := newMatchingPod(fmt.Sprintf("pod-%d", i+1), ns.Name)
  715. pod.Labels = labelMap()
  716. podList = append(podList, pod)
  717. }
  718. rcs, _ := createRCsPods(t, c, []*v1.ReplicationController{rc}, podList)
  719. rc = rcs[0]
  720. stopCh := runControllerAndInformers(t, rm, informers, 3)
  721. defer close(stopCh)
  722. waitRCStable(t, c, rc)
  723. // Verify the extra pod is deleted eventually by determining whether number of
  724. // all pods within namespace matches .spec.replicas of the RC (2 in this case)
  725. podClient := c.CoreV1().Pods(ns.Name)
  726. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  727. // All pods have labelMap as their labels
  728. pods := getPods(t, podClient, labelMap())
  729. return int32(len(pods.Items)) == *rc.Spec.Replicas, nil
  730. }); err != nil {
  731. t.Fatalf("Failed to verify number of all pods within current namespace matches .spec.replicas of rc %s: %v", rc.Name, err)
  732. }
  733. }
  734. func TestFullyLabeledReplicas(t *testing.T) {
  735. s, closeFn, rm, informers, c := rmSetup(t)
  736. defer closeFn()
  737. ns := framework.CreateTestingNamespace("test-fully-labeled-replicas", s, t)
  738. defer framework.DeleteTestingNamespace(ns, s, t)
  739. stopCh := runControllerAndInformers(t, rm, informers, 0)
  740. defer close(stopCh)
  741. extraLabelMap := map[string]string{"foo": "bar", "extraKey": "extraValue"}
  742. rc := newRC("rc", ns.Name, 2)
  743. rcs, _ := createRCsPods(t, c, []*v1.ReplicationController{rc}, []*v1.Pod{})
  744. rc = rcs[0]
  745. waitRCStable(t, c, rc)
  746. // Change RC's template labels to have extra labels, but not its selector
  747. rcClient := c.CoreV1().ReplicationControllers(ns.Name)
  748. updateRC(t, rcClient, rc.Name, func(rc *v1.ReplicationController) {
  749. rc.Spec.Template.Labels = extraLabelMap
  750. })
  751. // Set one of the pods to have extra labels
  752. podClient := c.CoreV1().Pods(ns.Name)
  753. pods := getPods(t, podClient, labelMap())
  754. if len(pods.Items) != 2 {
  755. t.Fatalf("len(pods) = %d, want 2", len(pods.Items))
  756. }
  757. fullyLabeledPod := &pods.Items[0]
  758. updatePod(t, podClient, fullyLabeledPod.Name, func(pod *v1.Pod) {
  759. pod.Labels = extraLabelMap
  760. })
  761. // Verify only one pod is fully labeled
  762. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  763. newRC, err := rcClient.Get(context.TODO(), rc.Name, metav1.GetOptions{})
  764. if err != nil {
  765. return false, err
  766. }
  767. return (newRC.Status.Replicas == 2 && newRC.Status.FullyLabeledReplicas == 1), nil
  768. }); err != nil {
  769. t.Fatalf("Failed to verify only one pod is fully labeled: %v", err)
  770. }
  771. }