replicaset_test.go 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  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. "context"
  16. "fmt"
  17. "net/http/httptest"
  18. "reflect"
  19. "strings"
  20. "testing"
  21. "time"
  22. apps "k8s.io/api/apps/v1"
  23. "k8s.io/api/core/v1"
  24. apierrors "k8s.io/apimachinery/pkg/api/errors"
  25. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  26. "k8s.io/apimachinery/pkg/labels"
  27. "k8s.io/apimachinery/pkg/util/uuid"
  28. "k8s.io/apimachinery/pkg/util/wait"
  29. "k8s.io/client-go/informers"
  30. clientset "k8s.io/client-go/kubernetes"
  31. appsclient "k8s.io/client-go/kubernetes/typed/apps/v1"
  32. typedv1 "k8s.io/client-go/kubernetes/typed/core/v1"
  33. restclient "k8s.io/client-go/rest"
  34. "k8s.io/client-go/tools/cache"
  35. "k8s.io/client-go/util/retry"
  36. podutil "k8s.io/kubernetes/pkg/api/v1/pod"
  37. "k8s.io/kubernetes/pkg/controller/replicaset"
  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(context.TODO(), rs, metav1.CreateOptions{})
  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(context.TODO(), pod, metav1.CreateOptions{})
  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(context.TODO(), podName, metav1.GetOptions{})
  191. if err != nil {
  192. return err
  193. }
  194. updateFunc(newPod)
  195. pod, err = podClient.Update(context.TODO(), newPod, metav1.UpdateOptions{})
  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(context.TODO(), pod.Name, metav1.GetOptions{})
  205. if err != nil {
  206. return err
  207. }
  208. updateStatusFunc(newPod)
  209. _, err = podClient.UpdateStatus(context.TODO(), newPod, metav1.UpdateOptions{})
  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(context.TODO(), 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(context.TODO(), rsName, metav1.GetOptions{})
  228. if err != nil {
  229. return err
  230. }
  231. updateFunc(newRS)
  232. rs, err = rsClient.Update(context.TODO(), newRS, metav1.UpdateOptions{})
  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(context.TODO(), 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(context.TODO(), 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(context.TODO(), pod, metav1.UpdateOptions{})
  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(context.TODO(), 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(context.TODO(), 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(context.TODO(), rs.Name, metav1.GetOptions{})
  321. if err != nil {
  322. return err
  323. }
  324. scale.Spec.Replicas = replicas
  325. _, err = c.AppsV1().ReplicaSets(ns).UpdateScale(context.TODO(), rs.Name, scale, metav1.UpdateOptions{})
  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(context.TODO(), 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(context.TODO(), newRS(rsName, ns.Name, 1), metav1.CreateOptions{})
  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(context.TODO(), pod, metav1.CreateOptions{})
  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(context.TODO(), 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 apps/v1 selector is immutable
  436. rsV1, err := clientSet.AppsV1().ReplicaSets(ns.Name).Get(context.TODO(), rs.Name, metav1.GetOptions{})
  437. if err != nil {
  438. t.Fatalf("failed to get apps/v1 replicaset %s: %v", rs.Name, err)
  439. }
  440. newSelectorLabels := map[string]string{"changed_name_apps_v1": "changed_test_apps_v1"}
  441. rsV1.Spec.Selector.MatchLabels = newSelectorLabels
  442. rsV1.Spec.Template.Labels = newSelectorLabels
  443. _, err = clientSet.AppsV1().ReplicaSets(ns.Name).Update(context.TODO(), rsV1, metav1.UpdateOptions{})
  444. if err == nil {
  445. t.Fatalf("failed to provide validation error when changing immutable selector when updating apps/v1 replicaset %s", rsV1.Name)
  446. }
  447. expectedErrType := "Invalid value"
  448. expectedErrDetail := "field is immutable"
  449. if !strings.Contains(err.Error(), expectedErrType) || !strings.Contains(err.Error(), expectedErrDetail) {
  450. t.Errorf("error message does not match, expected type: %s, expected detail: %s, got: %s", expectedErrType, expectedErrDetail, err.Error())
  451. }
  452. }
  453. func TestSpecReplicasChange(t *testing.T) {
  454. s, closeFn, rm, informers, c := rmSetup(t)
  455. defer closeFn()
  456. ns := framework.CreateTestingNamespace("test-spec-replicas-change", s, t)
  457. defer framework.DeleteTestingNamespace(ns, s, t)
  458. stopCh := runControllerAndInformers(t, rm, informers, 0)
  459. defer close(stopCh)
  460. rs := newRS("rs", ns.Name, 2)
  461. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  462. rs = rss[0]
  463. waitRSStable(t, c, rs)
  464. // Update .Spec.Replicas and verify .Status.Replicas is changed accordingly
  465. scaleRS(t, c, rs, 3)
  466. scaleRS(t, c, rs, 0)
  467. scaleRS(t, c, rs, 2)
  468. // Add a template annotation change to test RS's status does update
  469. // without .Spec.Replicas change
  470. rsClient := c.AppsV1().ReplicaSets(ns.Name)
  471. var oldGeneration int64
  472. newRS := updateRS(t, rsClient, rs.Name, func(rs *apps.ReplicaSet) {
  473. oldGeneration = rs.Generation
  474. rs.Spec.Template.Annotations = map[string]string{"test": "annotation"}
  475. })
  476. savedGeneration := newRS.Generation
  477. if savedGeneration == oldGeneration {
  478. t.Fatalf("Failed to verify .Generation has incremented for rs %s", rs.Name)
  479. }
  480. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  481. newRS, err := rsClient.Get(context.TODO(), rs.Name, metav1.GetOptions{})
  482. if err != nil {
  483. return false, err
  484. }
  485. return newRS.Status.ObservedGeneration >= savedGeneration, nil
  486. }); err != nil {
  487. t.Fatalf("Failed to verify .Status.ObservedGeneration has incremented for rs %s: %v", rs.Name, err)
  488. }
  489. }
  490. func TestDeletingAndFailedPods(t *testing.T) {
  491. s, closeFn, rm, informers, c := rmSetup(t)
  492. defer closeFn()
  493. ns := framework.CreateTestingNamespace("test-deleting-and-failed-pods", s, t)
  494. defer framework.DeleteTestingNamespace(ns, s, t)
  495. stopCh := runControllerAndInformers(t, rm, informers, 0)
  496. defer close(stopCh)
  497. rs := newRS("rs", ns.Name, 2)
  498. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  499. rs = rss[0]
  500. waitRSStable(t, c, rs)
  501. // Verify RS creates 2 pods
  502. podClient := c.CoreV1().Pods(ns.Name)
  503. pods := getPods(t, podClient, labelMap())
  504. if len(pods.Items) != 2 {
  505. t.Fatalf("len(pods) = %d, want 2", len(pods.Items))
  506. }
  507. // Set first pod as deleting pod
  508. // Set finalizers for the pod to simulate pending deletion status
  509. deletingPod := &pods.Items[0]
  510. updatePod(t, podClient, deletingPod.Name, func(pod *v1.Pod) {
  511. pod.Finalizers = []string{"fake.example.com/blockDeletion"}
  512. })
  513. if err := c.CoreV1().Pods(ns.Name).Delete(context.TODO(), deletingPod.Name, &metav1.DeleteOptions{}); err != nil {
  514. t.Fatalf("Error deleting pod %s: %v", deletingPod.Name, err)
  515. }
  516. // Set second pod as failed pod
  517. failedPod := &pods.Items[1]
  518. updatePodStatus(t, podClient, failedPod, func(pod *v1.Pod) {
  519. pod.Status.Phase = v1.PodFailed
  520. })
  521. // Pool until 2 new pods have been created to replace deleting and failed pods
  522. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  523. pods = getPods(t, podClient, labelMap())
  524. return len(pods.Items) == 4, nil
  525. }); err != nil {
  526. t.Fatalf("Failed to verify 2 new pods have been created (expected 4 pods): %v", err)
  527. }
  528. // Verify deleting and failed pods are among the four pods
  529. foundDeletingPod := false
  530. foundFailedPod := false
  531. for _, pod := range pods.Items {
  532. if pod.UID == deletingPod.UID {
  533. foundDeletingPod = true
  534. }
  535. if pod.UID == failedPod.UID {
  536. foundFailedPod = true
  537. }
  538. }
  539. // Verify deleting pod exists
  540. if !foundDeletingPod {
  541. t.Fatalf("expected deleting pod %s exists, but it is not found", deletingPod.Name)
  542. }
  543. // Verify failed pod exists
  544. if !foundFailedPod {
  545. t.Fatalf("expected failed pod %s exists, but it is not found", failedPod.Name)
  546. }
  547. }
  548. func TestOverlappingRSs(t *testing.T) {
  549. s, closeFn, rm, informers, c := rmSetup(t)
  550. defer closeFn()
  551. ns := framework.CreateTestingNamespace("test-overlapping-rss", s, t)
  552. defer framework.DeleteTestingNamespace(ns, s, t)
  553. stopCh := runControllerAndInformers(t, rm, informers, 0)
  554. defer close(stopCh)
  555. // Create 2 RSs with identical selectors
  556. for i := 0; i < 2; i++ {
  557. // One RS has 1 replica, and another has 2 replicas
  558. rs := newRS(fmt.Sprintf("rs-%d", i+1), ns.Name, i+1)
  559. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  560. waitRSStable(t, c, rss[0])
  561. }
  562. // Expect 3 total Pods to be created
  563. podClient := c.CoreV1().Pods(ns.Name)
  564. pods := getPods(t, podClient, labelMap())
  565. if len(pods.Items) != 3 {
  566. t.Errorf("len(pods) = %d, want 3", len(pods.Items))
  567. }
  568. // Expect both RSs have .status.replicas = .spec.replicas
  569. for i := 0; i < 2; i++ {
  570. newRS, err := c.AppsV1().ReplicaSets(ns.Name).Get(context.TODO(), fmt.Sprintf("rs-%d", i+1), metav1.GetOptions{})
  571. if err != nil {
  572. t.Fatalf("failed to obtain rs rs-%d: %v", i+1, err)
  573. }
  574. if newRS.Status.Replicas != *newRS.Spec.Replicas {
  575. t.Fatalf(".Status.Replicas %d is not equal to .Spec.Replicas %d", newRS.Status.Replicas, *newRS.Spec.Replicas)
  576. }
  577. }
  578. }
  579. func TestPodOrphaningAndAdoptionWhenLabelsChange(t *testing.T) {
  580. s, closeFn, rm, informers, c := rmSetup(t)
  581. defer closeFn()
  582. ns := framework.CreateTestingNamespace("test-pod-orphaning-and-adoption-when-labels-change", s, t)
  583. defer framework.DeleteTestingNamespace(ns, s, t)
  584. stopCh := runControllerAndInformers(t, rm, informers, 0)
  585. defer close(stopCh)
  586. rs := newRS("rs", ns.Name, 1)
  587. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  588. rs = rss[0]
  589. waitRSStable(t, c, rs)
  590. // Orphaning: RS should remove OwnerReference from a pod when the pod's labels change to not match its labels
  591. podClient := c.CoreV1().Pods(ns.Name)
  592. pods := getPods(t, podClient, labelMap())
  593. if len(pods.Items) != 1 {
  594. t.Fatalf("len(pods) = %d, want 1", len(pods.Items))
  595. }
  596. pod := &pods.Items[0]
  597. // Start by verifying ControllerRef for the pod is not nil
  598. if metav1.GetControllerOf(pod) == nil {
  599. t.Fatalf("ControllerRef of pod %s is nil", pod.Name)
  600. }
  601. newLabelMap := map[string]string{"new-foo": "new-bar"}
  602. updatePod(t, podClient, pod.Name, func(pod *v1.Pod) {
  603. pod.Labels = newLabelMap
  604. })
  605. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  606. newPod, err := podClient.Get(context.TODO(), pod.Name, metav1.GetOptions{})
  607. if err != nil {
  608. return false, err
  609. }
  610. pod = newPod
  611. return metav1.GetControllerOf(newPod) == nil, nil
  612. }); err != nil {
  613. t.Fatalf("Failed to verify ControllerRef for the pod %s is nil: %v", pod.Name, err)
  614. }
  615. // Adoption: RS should add ControllerRef to a pod when the pod's labels change to match its labels
  616. updatePod(t, podClient, pod.Name, func(pod *v1.Pod) {
  617. pod.Labels = labelMap()
  618. })
  619. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  620. newPod, err := podClient.Get(context.TODO(), pod.Name, metav1.GetOptions{})
  621. if err != nil {
  622. // If the pod is not found, it means the RS picks the pod for deletion (it is extra)
  623. // Verify there is only one pod in namespace and it has ControllerRef to the RS
  624. if apierrors.IsNotFound(err) {
  625. pods := getPods(t, podClient, labelMap())
  626. if len(pods.Items) != 1 {
  627. return false, fmt.Errorf("Expected 1 pod in current namespace, got %d", len(pods.Items))
  628. }
  629. // Set the pod accordingly
  630. pod = &pods.Items[0]
  631. return true, nil
  632. }
  633. return false, err
  634. }
  635. // Always update the pod so that we can save a GET call to API server later
  636. pod = newPod
  637. // If the pod is found, verify the pod has a ControllerRef
  638. return metav1.GetControllerOf(newPod) != nil, nil
  639. }); err != nil {
  640. t.Fatalf("Failed to verify ControllerRef for pod %s is not nil: %v", pod.Name, err)
  641. }
  642. // Verify the pod has a ControllerRef to the RS
  643. // Do nothing if the pod is nil (i.e., has been picked for deletion)
  644. if pod != nil {
  645. controllerRef := metav1.GetControllerOf(pod)
  646. if controllerRef.UID != rs.UID {
  647. t.Fatalf("RS owner of the pod %s has a different UID: Expected %v, got %v", pod.Name, rs.UID, controllerRef.UID)
  648. }
  649. }
  650. }
  651. func TestGeneralPodAdoption(t *testing.T) {
  652. s, closeFn, rm, informers, c := rmSetup(t)
  653. defer closeFn()
  654. ns := framework.CreateTestingNamespace("test-general-pod-adoption", s, t)
  655. defer framework.DeleteTestingNamespace(ns, s, t)
  656. stopCh := runControllerAndInformers(t, rm, informers, 0)
  657. defer close(stopCh)
  658. rs := newRS("rs", ns.Name, 1)
  659. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  660. rs = rss[0]
  661. waitRSStable(t, c, rs)
  662. podClient := c.CoreV1().Pods(ns.Name)
  663. pods := getPods(t, podClient, labelMap())
  664. if len(pods.Items) != 1 {
  665. t.Fatalf("len(pods) = %d, want 1", len(pods.Items))
  666. }
  667. pod := &pods.Items[0]
  668. var falseVar = false
  669. // When the only OwnerReference of the pod points to another type of API object such as statefulset
  670. // with Controller=false, the RS should add a second OwnerReference (ControllerRef) pointing to itself
  671. // with Controller=true
  672. ownerReference := metav1.OwnerReference{UID: uuid.NewUUID(), APIVersion: "apps/v1", Kind: "StatefulSet", Name: rs.Name, Controller: &falseVar}
  673. testPodControllerRefPatch(t, c, pod, &ownerReference, rs, 2)
  674. // When the only OwnerReference of the pod points to the RS, but Controller=false
  675. ownerReference = metav1.OwnerReference{UID: rs.UID, APIVersion: "apps/v1", Kind: "ReplicaSet", Name: rs.Name, Controller: &falseVar}
  676. testPodControllerRefPatch(t, c, pod, &ownerReference, rs, 1)
  677. }
  678. func TestReadyAndAvailableReplicas(t *testing.T) {
  679. s, closeFn, rm, informers, c := rmSetup(t)
  680. defer closeFn()
  681. ns := framework.CreateTestingNamespace("test-ready-and-available-replicas", s, t)
  682. defer framework.DeleteTestingNamespace(ns, s, t)
  683. stopCh := runControllerAndInformers(t, rm, informers, 0)
  684. defer close(stopCh)
  685. rs := newRS("rs", ns.Name, 3)
  686. rs.Spec.MinReadySeconds = 3600
  687. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  688. rs = rss[0]
  689. waitRSStable(t, c, rs)
  690. // First verify no pod is available
  691. if rs.Status.AvailableReplicas != 0 {
  692. t.Fatalf("Unexpected .Status.AvailableReplicas: Expected 0, saw %d", rs.Status.AvailableReplicas)
  693. }
  694. podClient := c.CoreV1().Pods(ns.Name)
  695. pods := getPods(t, podClient, labelMap())
  696. if len(pods.Items) != 3 {
  697. t.Fatalf("len(pods) = %d, want 3", len(pods.Items))
  698. }
  699. // Separate 3 pods into their own list
  700. firstPodList := &v1.PodList{Items: pods.Items[:1]}
  701. secondPodList := &v1.PodList{Items: pods.Items[1:2]}
  702. thirdPodList := &v1.PodList{Items: pods.Items[2:]}
  703. // First pod: Running, but not Ready
  704. // by setting the Ready condition to false with LastTransitionTime to be now
  705. setPodsReadyCondition(t, c, firstPodList, v1.ConditionFalse, time.Now())
  706. // Second pod: Running and Ready, but not Available
  707. // by setting LastTransitionTime to now
  708. setPodsReadyCondition(t, c, secondPodList, v1.ConditionTrue, time.Now())
  709. // Third pod: Running, Ready, and Available
  710. // by setting LastTransitionTime to more than 3600 seconds ago
  711. setPodsReadyCondition(t, c, thirdPodList, v1.ConditionTrue, time.Now().Add(-120*time.Minute))
  712. rsClient := c.AppsV1().ReplicaSets(ns.Name)
  713. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  714. newRS, err := rsClient.Get(context.TODO(), rs.Name, metav1.GetOptions{})
  715. if err != nil {
  716. return false, err
  717. }
  718. // Verify 3 pods exist, 2 pods are Ready, and 1 pod is Available
  719. return newRS.Status.Replicas == 3 && newRS.Status.ReadyReplicas == 2 && newRS.Status.AvailableReplicas == 1, nil
  720. }); err != nil {
  721. t.Fatalf("Failed to verify number of Replicas, ReadyReplicas and AvailableReplicas of rs %s to be as expected: %v", rs.Name, err)
  722. }
  723. }
  724. func TestRSScaleSubresource(t *testing.T) {
  725. s, closeFn, rm, informers, c := rmSetup(t)
  726. defer closeFn()
  727. ns := framework.CreateTestingNamespace("test-rs-scale-subresource", s, t)
  728. defer framework.DeleteTestingNamespace(ns, s, t)
  729. stopCh := runControllerAndInformers(t, rm, informers, 0)
  730. defer close(stopCh)
  731. rs := newRS("rs", ns.Name, 1)
  732. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  733. rs = rss[0]
  734. waitRSStable(t, c, rs)
  735. // Use scale subresource to scale up .Spec.Replicas to 3
  736. testScalingUsingScaleSubresource(t, c, rs, 3)
  737. // Use the scale subresource to scale down .Spec.Replicas to 0
  738. testScalingUsingScaleSubresource(t, c, rs, 0)
  739. }
  740. func TestExtraPodsAdoptionAndDeletion(t *testing.T) {
  741. s, closeFn, rm, informers, c := rmSetup(t)
  742. defer closeFn()
  743. ns := framework.CreateTestingNamespace("test-extra-pods-adoption-and-deletion", s, t)
  744. defer framework.DeleteTestingNamespace(ns, s, t)
  745. rs := newRS("rs", ns.Name, 2)
  746. // Create 3 pods, RS should adopt only 2 of them
  747. podList := []*v1.Pod{}
  748. for i := 0; i < 3; i++ {
  749. pod := newMatchingPod(fmt.Sprintf("pod-%d", i+1), ns.Name)
  750. pod.Labels = labelMap()
  751. podList = append(podList, pod)
  752. }
  753. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, podList)
  754. rs = rss[0]
  755. stopCh := runControllerAndInformers(t, rm, informers, 3)
  756. defer close(stopCh)
  757. waitRSStable(t, c, rs)
  758. // Verify the extra pod is deleted eventually by determining whether number of
  759. // all pods within namespace matches .spec.replicas of the RS (2 in this case)
  760. podClient := c.CoreV1().Pods(ns.Name)
  761. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  762. // All pods have labelMap as their labels
  763. pods := getPods(t, podClient, labelMap())
  764. return int32(len(pods.Items)) == *rs.Spec.Replicas, nil
  765. }); err != nil {
  766. t.Fatalf("Failed to verify number of all pods within current namespace matches .spec.replicas of rs %s: %v", rs.Name, err)
  767. }
  768. }
  769. func TestFullyLabeledReplicas(t *testing.T) {
  770. s, closeFn, rm, informers, c := rmSetup(t)
  771. defer closeFn()
  772. ns := framework.CreateTestingNamespace("test-fully-labeled-replicas", s, t)
  773. defer framework.DeleteTestingNamespace(ns, s, t)
  774. stopCh := runControllerAndInformers(t, rm, informers, 0)
  775. defer close(stopCh)
  776. extraLabelMap := map[string]string{"foo": "bar", "extraKey": "extraValue"}
  777. rs := newRS("rs", ns.Name, 2)
  778. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  779. rs = rss[0]
  780. waitRSStable(t, c, rs)
  781. // Change RS's template labels to have extra labels, but not its selector
  782. rsClient := c.AppsV1().ReplicaSets(ns.Name)
  783. updateRS(t, rsClient, rs.Name, func(rs *apps.ReplicaSet) {
  784. rs.Spec.Template.Labels = extraLabelMap
  785. })
  786. // Set one of the pods to have extra labels
  787. podClient := c.CoreV1().Pods(ns.Name)
  788. pods := getPods(t, podClient, labelMap())
  789. if len(pods.Items) != 2 {
  790. t.Fatalf("len(pods) = %d, want 2", len(pods.Items))
  791. }
  792. fullyLabeledPod := &pods.Items[0]
  793. updatePod(t, podClient, fullyLabeledPod.Name, func(pod *v1.Pod) {
  794. pod.Labels = extraLabelMap
  795. })
  796. // Verify only one pod is fully labeled
  797. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  798. newRS, err := rsClient.Get(context.TODO(), rs.Name, metav1.GetOptions{})
  799. if err != nil {
  800. return false, err
  801. }
  802. return (newRS.Status.Replicas == 2 && newRS.Status.FullyLabeledReplicas == 1), nil
  803. }); err != nil {
  804. t.Fatalf("Failed to verify only one pod is fully labeled: %v", err)
  805. }
  806. }
  807. func TestReplicaSetsAppsV1DefaultGCPolicy(t *testing.T) {
  808. s, closeFn, rm, informers, c := rmSetup(t)
  809. defer closeFn()
  810. ns := framework.CreateTestingNamespace("test-default-gc-v1", s, t)
  811. defer framework.DeleteTestingNamespace(ns, s, t)
  812. stopCh := runControllerAndInformers(t, rm, informers, 0)
  813. defer close(stopCh)
  814. rs := newRS("rs", ns.Name, 2)
  815. fakeFinalizer := "kube.io/dummy-finalizer"
  816. rs.Finalizers = []string{fakeFinalizer}
  817. rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  818. rs = rss[0]
  819. waitRSStable(t, c, rs)
  820. // Verify RS creates 2 pods
  821. podClient := c.CoreV1().Pods(ns.Name)
  822. pods := getPods(t, podClient, labelMap())
  823. if len(pods.Items) != 2 {
  824. t.Fatalf("len(pods) = %d, want 2", len(pods.Items))
  825. }
  826. rsClient := c.AppsV1().ReplicaSets(ns.Name)
  827. err := rsClient.Delete(context.TODO(), rs.Name, nil)
  828. if err != nil {
  829. t.Fatalf("Failed to delete rs: %v", err)
  830. }
  831. // Verify no new finalizer has been added
  832. if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  833. newRS, err := rsClient.Get(context.TODO(), rs.Name, metav1.GetOptions{})
  834. if err != nil {
  835. return false, err
  836. }
  837. if newRS.DeletionTimestamp == nil {
  838. return false, nil
  839. }
  840. if got, want := newRS.Finalizers, []string{fakeFinalizer}; !reflect.DeepEqual(got, want) {
  841. return false, fmt.Errorf("got finalizers: %+v; want: %+v", got, want)
  842. }
  843. return true, nil
  844. }); err != nil {
  845. t.Fatalf("Failed to verify the finalizer: %v", err)
  846. }
  847. updateRS(t, c.AppsV1().ReplicaSets(ns.Name), rs.Name, func(rs *apps.ReplicaSet) {
  848. var finalizers []string
  849. // remove fakeFinalizer
  850. for _, finalizer := range rs.Finalizers {
  851. if finalizer != fakeFinalizer {
  852. finalizers = append(finalizers, finalizer)
  853. }
  854. }
  855. rs.Finalizers = finalizers
  856. })
  857. rsClient.Delete(context.TODO(), rs.Name, nil)
  858. }