deployment_controller_test.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  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 deployment
  14. import (
  15. "strconv"
  16. "testing"
  17. apps "k8s.io/api/apps/v1"
  18. "k8s.io/api/core/v1"
  19. extensions "k8s.io/api/extensions/v1beta1"
  20. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  21. "k8s.io/apimachinery/pkg/runtime"
  22. "k8s.io/apimachinery/pkg/runtime/schema"
  23. "k8s.io/apimachinery/pkg/util/intstr"
  24. "k8s.io/apimachinery/pkg/util/uuid"
  25. "k8s.io/client-go/informers"
  26. "k8s.io/client-go/kubernetes/fake"
  27. core "k8s.io/client-go/testing"
  28. "k8s.io/client-go/tools/record"
  29. _ "k8s.io/kubernetes/pkg/apis/apps/install"
  30. _ "k8s.io/kubernetes/pkg/apis/authentication/install"
  31. _ "k8s.io/kubernetes/pkg/apis/authorization/install"
  32. _ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
  33. _ "k8s.io/kubernetes/pkg/apis/batch/install"
  34. _ "k8s.io/kubernetes/pkg/apis/certificates/install"
  35. _ "k8s.io/kubernetes/pkg/apis/core/install"
  36. _ "k8s.io/kubernetes/pkg/apis/policy/install"
  37. _ "k8s.io/kubernetes/pkg/apis/rbac/install"
  38. _ "k8s.io/kubernetes/pkg/apis/settings/install"
  39. _ "k8s.io/kubernetes/pkg/apis/storage/install"
  40. "k8s.io/kubernetes/pkg/controller"
  41. "k8s.io/kubernetes/pkg/controller/deployment/util"
  42. "k8s.io/kubernetes/pkg/controller/testutil"
  43. )
  44. var (
  45. alwaysReady = func() bool { return true }
  46. noTimestamp = metav1.Time{}
  47. )
  48. func rs(name string, replicas int, selector map[string]string, timestamp metav1.Time) *apps.ReplicaSet {
  49. return &apps.ReplicaSet{
  50. ObjectMeta: metav1.ObjectMeta{
  51. Name: name,
  52. CreationTimestamp: timestamp,
  53. Namespace: metav1.NamespaceDefault,
  54. },
  55. Spec: apps.ReplicaSetSpec{
  56. Replicas: func() *int32 { i := int32(replicas); return &i }(),
  57. Selector: &metav1.LabelSelector{MatchLabels: selector},
  58. Template: v1.PodTemplateSpec{},
  59. },
  60. }
  61. }
  62. func newRSWithStatus(name string, specReplicas, statusReplicas int, selector map[string]string) *apps.ReplicaSet {
  63. rs := rs(name, specReplicas, selector, noTimestamp)
  64. rs.Status = apps.ReplicaSetStatus{
  65. Replicas: int32(statusReplicas),
  66. }
  67. return rs
  68. }
  69. func newDeployment(name string, replicas int, revisionHistoryLimit *int32, maxSurge, maxUnavailable *intstr.IntOrString, selector map[string]string) *apps.Deployment {
  70. d := apps.Deployment{
  71. TypeMeta: metav1.TypeMeta{APIVersion: "apps/v1", Kind: "Deployment"},
  72. ObjectMeta: metav1.ObjectMeta{
  73. UID: uuid.NewUUID(),
  74. Name: name,
  75. Namespace: metav1.NamespaceDefault,
  76. Annotations: make(map[string]string),
  77. },
  78. Spec: apps.DeploymentSpec{
  79. Strategy: apps.DeploymentStrategy{
  80. Type: apps.RollingUpdateDeploymentStrategyType,
  81. RollingUpdate: &apps.RollingUpdateDeployment{
  82. MaxUnavailable: func() *intstr.IntOrString { i := intstr.FromInt(0); return &i }(),
  83. MaxSurge: func() *intstr.IntOrString { i := intstr.FromInt(0); return &i }(),
  84. },
  85. },
  86. Replicas: func() *int32 { i := int32(replicas); return &i }(),
  87. Selector: &metav1.LabelSelector{MatchLabels: selector},
  88. Template: v1.PodTemplateSpec{
  89. ObjectMeta: metav1.ObjectMeta{
  90. Labels: selector,
  91. },
  92. Spec: v1.PodSpec{
  93. Containers: []v1.Container{
  94. {
  95. Image: "foo/bar",
  96. },
  97. },
  98. },
  99. },
  100. RevisionHistoryLimit: revisionHistoryLimit,
  101. },
  102. }
  103. if maxSurge != nil {
  104. d.Spec.Strategy.RollingUpdate.MaxSurge = maxSurge
  105. }
  106. if maxUnavailable != nil {
  107. d.Spec.Strategy.RollingUpdate.MaxUnavailable = maxUnavailable
  108. }
  109. return &d
  110. }
  111. func newReplicaSet(d *apps.Deployment, name string, replicas int) *apps.ReplicaSet {
  112. return &apps.ReplicaSet{
  113. TypeMeta: metav1.TypeMeta{Kind: "ReplicaSet"},
  114. ObjectMeta: metav1.ObjectMeta{
  115. Name: name,
  116. UID: uuid.NewUUID(),
  117. Namespace: metav1.NamespaceDefault,
  118. Labels: d.Spec.Selector.MatchLabels,
  119. OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(d, controllerKind)},
  120. },
  121. Spec: apps.ReplicaSetSpec{
  122. Selector: d.Spec.Selector,
  123. Replicas: func() *int32 { i := int32(replicas); return &i }(),
  124. Template: d.Spec.Template,
  125. },
  126. }
  127. }
  128. type fixture struct {
  129. t *testing.T
  130. client *fake.Clientset
  131. // Objects to put in the store.
  132. dLister []*apps.Deployment
  133. rsLister []*apps.ReplicaSet
  134. podLister []*v1.Pod
  135. // Actions expected to happen on the client. Objects from here are also
  136. // preloaded into NewSimpleFake.
  137. actions []core.Action
  138. objects []runtime.Object
  139. }
  140. func (f *fixture) expectGetDeploymentAction(d *apps.Deployment) {
  141. action := core.NewGetAction(schema.GroupVersionResource{Resource: "deployments"}, d.Namespace, d.Name)
  142. f.actions = append(f.actions, action)
  143. }
  144. func (f *fixture) expectUpdateDeploymentStatusAction(d *apps.Deployment) {
  145. action := core.NewUpdateAction(schema.GroupVersionResource{Resource: "deployments"}, d.Namespace, d)
  146. action.Subresource = "status"
  147. f.actions = append(f.actions, action)
  148. }
  149. func (f *fixture) expectUpdateDeploymentAction(d *apps.Deployment) {
  150. action := core.NewUpdateAction(schema.GroupVersionResource{Resource: "deployments"}, d.Namespace, d)
  151. f.actions = append(f.actions, action)
  152. }
  153. func (f *fixture) expectCreateRSAction(rs *apps.ReplicaSet) {
  154. f.actions = append(f.actions, core.NewCreateAction(schema.GroupVersionResource{Resource: "replicasets"}, rs.Namespace, rs))
  155. }
  156. func newFixture(t *testing.T) *fixture {
  157. f := &fixture{}
  158. f.t = t
  159. f.objects = []runtime.Object{}
  160. return f
  161. }
  162. func (f *fixture) newController() (*DeploymentController, informers.SharedInformerFactory, error) {
  163. f.client = fake.NewSimpleClientset(f.objects...)
  164. informers := informers.NewSharedInformerFactory(f.client, controller.NoResyncPeriodFunc())
  165. c, err := NewDeploymentController(informers.Apps().V1().Deployments(), informers.Apps().V1().ReplicaSets(), informers.Core().V1().Pods(), f.client)
  166. if err != nil {
  167. return nil, nil, err
  168. }
  169. c.eventRecorder = &record.FakeRecorder{}
  170. c.dListerSynced = alwaysReady
  171. c.rsListerSynced = alwaysReady
  172. c.podListerSynced = alwaysReady
  173. for _, d := range f.dLister {
  174. informers.Apps().V1().Deployments().Informer().GetIndexer().Add(d)
  175. }
  176. for _, rs := range f.rsLister {
  177. informers.Apps().V1().ReplicaSets().Informer().GetIndexer().Add(rs)
  178. }
  179. for _, pod := range f.podLister {
  180. informers.Core().V1().Pods().Informer().GetIndexer().Add(pod)
  181. }
  182. return c, informers, nil
  183. }
  184. func (f *fixture) runExpectError(deploymentName string, startInformers bool) {
  185. f.run_(deploymentName, startInformers, true)
  186. }
  187. func (f *fixture) run(deploymentName string) {
  188. f.run_(deploymentName, true, false)
  189. }
  190. func (f *fixture) run_(deploymentName string, startInformers bool, expectError bool) {
  191. c, informers, err := f.newController()
  192. if err != nil {
  193. f.t.Fatalf("error creating Deployment controller: %v", err)
  194. }
  195. if startInformers {
  196. stopCh := make(chan struct{})
  197. defer close(stopCh)
  198. informers.Start(stopCh)
  199. }
  200. err = c.syncDeployment(deploymentName)
  201. if !expectError && err != nil {
  202. f.t.Errorf("error syncing deployment: %v", err)
  203. } else if expectError && err == nil {
  204. f.t.Error("expected error syncing deployment, got nil")
  205. }
  206. actions := filterInformerActions(f.client.Actions())
  207. for i, action := range actions {
  208. if len(f.actions) < i+1 {
  209. f.t.Errorf("%d unexpected actions: %+v", len(actions)-len(f.actions), actions[i:])
  210. break
  211. }
  212. expectedAction := f.actions[i]
  213. if !(expectedAction.Matches(action.GetVerb(), action.GetResource().Resource) && action.GetSubresource() == expectedAction.GetSubresource()) {
  214. f.t.Errorf("Expected\n\t%#v\ngot\n\t%#v", expectedAction, action)
  215. continue
  216. }
  217. }
  218. if len(f.actions) > len(actions) {
  219. f.t.Errorf("%d additional expected actions:%+v", len(f.actions)-len(actions), f.actions[len(actions):])
  220. }
  221. }
  222. func filterInformerActions(actions []core.Action) []core.Action {
  223. ret := []core.Action{}
  224. for _, action := range actions {
  225. if len(action.GetNamespace()) == 0 &&
  226. (action.Matches("list", "pods") ||
  227. action.Matches("list", "deployments") ||
  228. action.Matches("list", "replicasets") ||
  229. action.Matches("watch", "pods") ||
  230. action.Matches("watch", "deployments") ||
  231. action.Matches("watch", "replicasets")) {
  232. continue
  233. }
  234. ret = append(ret, action)
  235. }
  236. return ret
  237. }
  238. func TestSyncDeploymentCreatesReplicaSet(t *testing.T) {
  239. f := newFixture(t)
  240. d := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  241. f.dLister = append(f.dLister, d)
  242. f.objects = append(f.objects, d)
  243. rs := newReplicaSet(d, "deploymentrs-4186632231", 1)
  244. f.expectCreateRSAction(rs)
  245. f.expectUpdateDeploymentStatusAction(d)
  246. f.expectUpdateDeploymentStatusAction(d)
  247. f.run(testutil.GetKey(d, t))
  248. }
  249. func TestSyncDeploymentDontDoAnythingDuringDeletion(t *testing.T) {
  250. f := newFixture(t)
  251. d := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  252. now := metav1.Now()
  253. d.DeletionTimestamp = &now
  254. f.dLister = append(f.dLister, d)
  255. f.objects = append(f.objects, d)
  256. f.expectUpdateDeploymentStatusAction(d)
  257. f.run(testutil.GetKey(d, t))
  258. }
  259. func TestSyncDeploymentDeletionRace(t *testing.T) {
  260. f := newFixture(t)
  261. d := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  262. d2 := *d
  263. // Lister (cache) says NOT deleted.
  264. f.dLister = append(f.dLister, d)
  265. // Bare client says it IS deleted. This should be presumed more up-to-date.
  266. now := metav1.Now()
  267. d2.DeletionTimestamp = &now
  268. f.objects = append(f.objects, &d2)
  269. // The recheck is only triggered if a matching orphan exists.
  270. rs := newReplicaSet(d, "rs1", 1)
  271. rs.OwnerReferences = nil
  272. f.objects = append(f.objects, rs)
  273. f.rsLister = append(f.rsLister, rs)
  274. // Expect to only recheck DeletionTimestamp.
  275. f.expectGetDeploymentAction(d)
  276. // Sync should fail and requeue to let cache catch up.
  277. // Don't start informers, since we don't want cache to catch up for this test.
  278. f.runExpectError(testutil.GetKey(d, t), false)
  279. }
  280. // issue: https://github.com/kubernetes/kubernetes/issues/23218
  281. func TestDontSyncDeploymentsWithEmptyPodSelector(t *testing.T) {
  282. f := newFixture(t)
  283. d := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  284. d.Spec.Selector = &metav1.LabelSelector{}
  285. f.dLister = append(f.dLister, d)
  286. f.objects = append(f.objects, d)
  287. // Normally there should be a status update to sync observedGeneration but the fake
  288. // deployment has no generation set so there is no action happpening here.
  289. f.run(testutil.GetKey(d, t))
  290. }
  291. func TestReentrantRollback(t *testing.T) {
  292. f := newFixture(t)
  293. d := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  294. d.Annotations = map[string]string{util.RevisionAnnotation: "2"}
  295. setRollbackTo(d, &extensions.RollbackConfig{Revision: 0})
  296. f.dLister = append(f.dLister, d)
  297. rs1 := newReplicaSet(d, "deploymentrs-old", 0)
  298. rs1.Annotations = map[string]string{util.RevisionAnnotation: "1"}
  299. one := int64(1)
  300. rs1.Spec.Template.Spec.TerminationGracePeriodSeconds = &one
  301. rs1.Spec.Selector.MatchLabels[apps.DefaultDeploymentUniqueLabelKey] = "hash"
  302. rs2 := newReplicaSet(d, "deploymentrs-new", 1)
  303. rs2.Annotations = map[string]string{util.RevisionAnnotation: "2"}
  304. rs2.Spec.Selector.MatchLabels[apps.DefaultDeploymentUniqueLabelKey] = "hash"
  305. f.rsLister = append(f.rsLister, rs1, rs2)
  306. f.objects = append(f.objects, d, rs1, rs2)
  307. // Rollback is done here
  308. f.expectUpdateDeploymentAction(d)
  309. // Expect no update on replica sets though
  310. f.run(testutil.GetKey(d, t))
  311. }
  312. // TestPodDeletionEnqueuesRecreateDeployment ensures that the deletion of a pod
  313. // will requeue a Recreate deployment iff there is no other pod returned from the
  314. // client.
  315. func TestPodDeletionEnqueuesRecreateDeployment(t *testing.T) {
  316. f := newFixture(t)
  317. foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  318. foo.Spec.Strategy.Type = apps.RecreateDeploymentStrategyType
  319. rs := newReplicaSet(foo, "foo-1", 1)
  320. pod := generatePodFromRS(rs)
  321. f.dLister = append(f.dLister, foo)
  322. f.rsLister = append(f.rsLister, rs)
  323. f.objects = append(f.objects, foo, rs)
  324. c, _, err := f.newController()
  325. if err != nil {
  326. t.Fatalf("error creating Deployment controller: %v", err)
  327. }
  328. enqueued := false
  329. c.enqueueDeployment = func(d *apps.Deployment) {
  330. if d.Name == "foo" {
  331. enqueued = true
  332. }
  333. }
  334. c.deletePod(pod)
  335. if !enqueued {
  336. t.Errorf("expected deployment %q to be queued after pod deletion", foo.Name)
  337. }
  338. }
  339. // TestPodDeletionDoesntEnqueueRecreateDeployment ensures that the deletion of a pod
  340. // will not requeue a Recreate deployment iff there are other pods returned from the
  341. // client.
  342. func TestPodDeletionDoesntEnqueueRecreateDeployment(t *testing.T) {
  343. f := newFixture(t)
  344. foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  345. foo.Spec.Strategy.Type = apps.RecreateDeploymentStrategyType
  346. rs1 := newReplicaSet(foo, "foo-1", 1)
  347. rs2 := newReplicaSet(foo, "foo-1", 1)
  348. pod1 := generatePodFromRS(rs1)
  349. pod2 := generatePodFromRS(rs2)
  350. f.dLister = append(f.dLister, foo)
  351. // Let's pretend this is a different pod. The gist is that the pod lister needs to
  352. // return a non-empty list.
  353. f.podLister = append(f.podLister, pod1, pod2)
  354. c, _, err := f.newController()
  355. if err != nil {
  356. t.Fatalf("error creating Deployment controller: %v", err)
  357. }
  358. enqueued := false
  359. c.enqueueDeployment = func(d *apps.Deployment) {
  360. if d.Name == "foo" {
  361. enqueued = true
  362. }
  363. }
  364. c.deletePod(pod1)
  365. if enqueued {
  366. t.Errorf("expected deployment %q not to be queued after pod deletion", foo.Name)
  367. }
  368. }
  369. // TestPodDeletionPartialReplicaSetOwnershipEnqueueRecreateDeployment ensures that
  370. // the deletion of a pod will requeue a Recreate deployment iff there is no other
  371. // pod returned from the client in the case where a deployment has multiple replica
  372. // sets, some of which have empty owner references.
  373. func TestPodDeletionPartialReplicaSetOwnershipEnqueueRecreateDeployment(t *testing.T) {
  374. f := newFixture(t)
  375. foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  376. foo.Spec.Strategy.Type = apps.RecreateDeploymentStrategyType
  377. rs1 := newReplicaSet(foo, "foo-1", 1)
  378. rs2 := newReplicaSet(foo, "foo-2", 2)
  379. rs2.OwnerReferences = nil
  380. pod := generatePodFromRS(rs1)
  381. f.dLister = append(f.dLister, foo)
  382. f.rsLister = append(f.rsLister, rs1, rs2)
  383. f.objects = append(f.objects, foo, rs1, rs2)
  384. c, _, err := f.newController()
  385. if err != nil {
  386. t.Fatalf("error creating Deployment controller: %v", err)
  387. }
  388. enqueued := false
  389. c.enqueueDeployment = func(d *apps.Deployment) {
  390. if d.Name == "foo" {
  391. enqueued = true
  392. }
  393. }
  394. c.deletePod(pod)
  395. if !enqueued {
  396. t.Errorf("expected deployment %q to be queued after pod deletion", foo.Name)
  397. }
  398. }
  399. // TestPodDeletionPartialReplicaSetOwnershipDoesntEnqueueRecreateDeployment that the
  400. // deletion of a pod will not requeue a Recreate deployment iff there are other pods
  401. // returned from the client in the case where a deployment has multiple replica sets,
  402. // some of which have empty owner references.
  403. func TestPodDeletionPartialReplicaSetOwnershipDoesntEnqueueRecreateDeployment(t *testing.T) {
  404. f := newFixture(t)
  405. foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  406. foo.Spec.Strategy.Type = apps.RecreateDeploymentStrategyType
  407. rs1 := newReplicaSet(foo, "foo-1", 1)
  408. rs2 := newReplicaSet(foo, "foo-2", 2)
  409. rs2.OwnerReferences = nil
  410. pod := generatePodFromRS(rs1)
  411. f.dLister = append(f.dLister, foo)
  412. f.rsLister = append(f.rsLister, rs1, rs2)
  413. f.objects = append(f.objects, foo, rs1, rs2)
  414. // Let's pretend this is a different pod. The gist is that the pod lister needs to
  415. // return a non-empty list.
  416. f.podLister = append(f.podLister, pod)
  417. c, _, err := f.newController()
  418. if err != nil {
  419. t.Fatalf("error creating Deployment controller: %v", err)
  420. }
  421. enqueued := false
  422. c.enqueueDeployment = func(d *apps.Deployment) {
  423. if d.Name == "foo" {
  424. enqueued = true
  425. }
  426. }
  427. c.deletePod(pod)
  428. if enqueued {
  429. t.Errorf("expected deployment %q not to be queued after pod deletion", foo.Name)
  430. }
  431. }
  432. func TestGetReplicaSetsForDeployment(t *testing.T) {
  433. f := newFixture(t)
  434. // Two Deployments with same labels.
  435. d1 := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  436. d2 := newDeployment("bar", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  437. // Two ReplicaSets that match labels for both Deployments,
  438. // but have ControllerRefs to make ownership explicit.
  439. rs1 := newReplicaSet(d1, "rs1", 1)
  440. rs2 := newReplicaSet(d2, "rs2", 1)
  441. f.dLister = append(f.dLister, d1, d2)
  442. f.rsLister = append(f.rsLister, rs1, rs2)
  443. f.objects = append(f.objects, d1, d2, rs1, rs2)
  444. // Start the fixture.
  445. c, informers, err := f.newController()
  446. if err != nil {
  447. t.Fatalf("error creating Deployment controller: %v", err)
  448. }
  449. stopCh := make(chan struct{})
  450. defer close(stopCh)
  451. informers.Start(stopCh)
  452. rsList, err := c.getReplicaSetsForDeployment(d1)
  453. if err != nil {
  454. t.Fatalf("getReplicaSetsForDeployment() error: %v", err)
  455. }
  456. rsNames := []string{}
  457. for _, rs := range rsList {
  458. rsNames = append(rsNames, rs.Name)
  459. }
  460. if len(rsNames) != 1 || rsNames[0] != rs1.Name {
  461. t.Errorf("getReplicaSetsForDeployment() = %v, want [%v]", rsNames, rs1.Name)
  462. }
  463. rsList, err = c.getReplicaSetsForDeployment(d2)
  464. if err != nil {
  465. t.Fatalf("getReplicaSetsForDeployment() error: %v", err)
  466. }
  467. rsNames = []string{}
  468. for _, rs := range rsList {
  469. rsNames = append(rsNames, rs.Name)
  470. }
  471. if len(rsNames) != 1 || rsNames[0] != rs2.Name {
  472. t.Errorf("getReplicaSetsForDeployment() = %v, want [%v]", rsNames, rs2.Name)
  473. }
  474. }
  475. func TestGetReplicaSetsForDeploymentAdoptRelease(t *testing.T) {
  476. f := newFixture(t)
  477. d := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  478. // RS with matching labels, but orphaned. Should be adopted and returned.
  479. rsAdopt := newReplicaSet(d, "rsAdopt", 1)
  480. rsAdopt.OwnerReferences = nil
  481. // RS with matching ControllerRef, but wrong labels. Should be released.
  482. rsRelease := newReplicaSet(d, "rsRelease", 1)
  483. rsRelease.Labels = map[string]string{"foo": "notbar"}
  484. f.dLister = append(f.dLister, d)
  485. f.rsLister = append(f.rsLister, rsAdopt, rsRelease)
  486. f.objects = append(f.objects, d, rsAdopt, rsRelease)
  487. // Start the fixture.
  488. c, informers, err := f.newController()
  489. if err != nil {
  490. t.Fatalf("error creating Deployment controller: %v", err)
  491. }
  492. stopCh := make(chan struct{})
  493. defer close(stopCh)
  494. informers.Start(stopCh)
  495. rsList, err := c.getReplicaSetsForDeployment(d)
  496. if err != nil {
  497. t.Fatalf("getReplicaSetsForDeployment() error: %v", err)
  498. }
  499. rsNames := []string{}
  500. for _, rs := range rsList {
  501. rsNames = append(rsNames, rs.Name)
  502. }
  503. if len(rsNames) != 1 || rsNames[0] != rsAdopt.Name {
  504. t.Errorf("getReplicaSetsForDeployment() = %v, want [%v]", rsNames, rsAdopt.Name)
  505. }
  506. }
  507. func TestGetPodMapForReplicaSets(t *testing.T) {
  508. f := newFixture(t)
  509. d := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  510. rs1 := newReplicaSet(d, "rs1", 1)
  511. rs2 := newReplicaSet(d, "rs2", 1)
  512. // Add a Pod for each ReplicaSet.
  513. pod1 := generatePodFromRS(rs1)
  514. pod2 := generatePodFromRS(rs2)
  515. // Add a Pod that has matching labels, but no ControllerRef.
  516. pod3 := generatePodFromRS(rs1)
  517. pod3.Name = "pod3"
  518. pod3.OwnerReferences = nil
  519. // Add a Pod that has matching labels and ControllerRef, but is inactive.
  520. pod4 := generatePodFromRS(rs1)
  521. pod4.Name = "pod4"
  522. pod4.Status.Phase = v1.PodFailed
  523. f.dLister = append(f.dLister, d)
  524. f.rsLister = append(f.rsLister, rs1, rs2)
  525. f.podLister = append(f.podLister, pod1, pod2, pod3, pod4)
  526. f.objects = append(f.objects, d, rs1, rs2, pod1, pod2, pod3, pod4)
  527. // Start the fixture.
  528. c, informers, err := f.newController()
  529. if err != nil {
  530. t.Fatalf("error creating Deployment controller: %v", err)
  531. }
  532. stopCh := make(chan struct{})
  533. defer close(stopCh)
  534. informers.Start(stopCh)
  535. podMap, err := c.getPodMapForDeployment(d, f.rsLister)
  536. if err != nil {
  537. t.Fatalf("getPodMapForDeployment() error: %v", err)
  538. }
  539. podCount := 0
  540. for _, podList := range podMap {
  541. podCount += len(podList.Items)
  542. }
  543. if got, want := podCount, 3; got != want {
  544. t.Errorf("podCount = %v, want %v", got, want)
  545. }
  546. if got, want := len(podMap), 2; got != want {
  547. t.Errorf("len(podMap) = %v, want %v", got, want)
  548. }
  549. if got, want := len(podMap[rs1.UID].Items), 2; got != want {
  550. t.Errorf("len(podMap[rs1]) = %v, want %v", got, want)
  551. }
  552. expect := map[string]struct{}{"rs1-pod": {}, "pod4": {}}
  553. for _, pod := range podMap[rs1.UID].Items {
  554. if _, ok := expect[pod.Name]; !ok {
  555. t.Errorf("unexpected pod name for rs1: %s", pod.Name)
  556. }
  557. }
  558. if got, want := len(podMap[rs2.UID].Items), 1; got != want {
  559. t.Errorf("len(podMap[rs2]) = %v, want %v", got, want)
  560. }
  561. if got, want := podMap[rs2.UID].Items[0].Name, "rs2-pod"; got != want {
  562. t.Errorf("podMap[rs2] = [%v], want [%v]", got, want)
  563. }
  564. }
  565. func TestAddReplicaSet(t *testing.T) {
  566. f := newFixture(t)
  567. d1 := newDeployment("d1", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  568. d2 := newDeployment("d2", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  569. // Two ReplicaSets that match labels for both Deployments,
  570. // but have ControllerRefs to make ownership explicit.
  571. rs1 := newReplicaSet(d1, "rs1", 1)
  572. rs2 := newReplicaSet(d2, "rs2", 1)
  573. f.dLister = append(f.dLister, d1, d2)
  574. f.objects = append(f.objects, d1, d2, rs1, rs2)
  575. // Create the fixture but don't start it,
  576. // so nothing happens in the background.
  577. dc, _, err := f.newController()
  578. if err != nil {
  579. t.Fatalf("error creating Deployment controller: %v", err)
  580. }
  581. dc.addReplicaSet(rs1)
  582. if got, want := dc.queue.Len(), 1; got != want {
  583. t.Fatalf("queue.Len() = %v, want %v", got, want)
  584. }
  585. key, done := dc.queue.Get()
  586. if key == nil || done {
  587. t.Fatalf("failed to enqueue controller for rs %v", rs1.Name)
  588. }
  589. expectedKey, _ := controller.KeyFunc(d1)
  590. if got, want := key.(string), expectedKey; got != want {
  591. t.Errorf("queue.Get() = %v, want %v", got, want)
  592. }
  593. dc.addReplicaSet(rs2)
  594. if got, want := dc.queue.Len(), 1; got != want {
  595. t.Fatalf("queue.Len() = %v, want %v", got, want)
  596. }
  597. key, done = dc.queue.Get()
  598. if key == nil || done {
  599. t.Fatalf("failed to enqueue controller for rs %v", rs2.Name)
  600. }
  601. expectedKey, _ = controller.KeyFunc(d2)
  602. if got, want := key.(string), expectedKey; got != want {
  603. t.Errorf("queue.Get() = %v, want %v", got, want)
  604. }
  605. }
  606. func TestAddReplicaSetOrphan(t *testing.T) {
  607. f := newFixture(t)
  608. // 2 will match the RS, 1 won't.
  609. d1 := newDeployment("d1", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  610. d2 := newDeployment("d2", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  611. d3 := newDeployment("d3", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  612. d3.Spec.Selector.MatchLabels = map[string]string{"foo": "notbar"}
  613. // Make the RS an orphan. Expect matching Deployments to be queued.
  614. rs := newReplicaSet(d1, "rs1", 1)
  615. rs.OwnerReferences = nil
  616. f.dLister = append(f.dLister, d1, d2, d3)
  617. f.objects = append(f.objects, d1, d2, d3)
  618. // Create the fixture but don't start it,
  619. // so nothing happens in the background.
  620. dc, _, err := f.newController()
  621. if err != nil {
  622. t.Fatalf("error creating Deployment controller: %v", err)
  623. }
  624. dc.addReplicaSet(rs)
  625. if got, want := dc.queue.Len(), 2; got != want {
  626. t.Fatalf("queue.Len() = %v, want %v", got, want)
  627. }
  628. }
  629. func TestUpdateReplicaSet(t *testing.T) {
  630. f := newFixture(t)
  631. d1 := newDeployment("d1", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  632. d2 := newDeployment("d2", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  633. // Two ReplicaSets that match labels for both Deployments,
  634. // but have ControllerRefs to make ownership explicit.
  635. rs1 := newReplicaSet(d1, "rs1", 1)
  636. rs2 := newReplicaSet(d2, "rs2", 1)
  637. f.dLister = append(f.dLister, d1, d2)
  638. f.rsLister = append(f.rsLister, rs1, rs2)
  639. f.objects = append(f.objects, d1, d2, rs1, rs2)
  640. // Create the fixture but don't start it,
  641. // so nothing happens in the background.
  642. dc, _, err := f.newController()
  643. if err != nil {
  644. t.Fatalf("error creating Deployment controller: %v", err)
  645. }
  646. prev := *rs1
  647. next := *rs1
  648. bumpResourceVersion(&next)
  649. dc.updateReplicaSet(&prev, &next)
  650. if got, want := dc.queue.Len(), 1; got != want {
  651. t.Fatalf("queue.Len() = %v, want %v", got, want)
  652. }
  653. key, done := dc.queue.Get()
  654. if key == nil || done {
  655. t.Fatalf("failed to enqueue controller for rs %v", rs1.Name)
  656. }
  657. expectedKey, _ := controller.KeyFunc(d1)
  658. if got, want := key.(string), expectedKey; got != want {
  659. t.Errorf("queue.Get() = %v, want %v", got, want)
  660. }
  661. prev = *rs2
  662. next = *rs2
  663. bumpResourceVersion(&next)
  664. dc.updateReplicaSet(&prev, &next)
  665. if got, want := dc.queue.Len(), 1; got != want {
  666. t.Fatalf("queue.Len() = %v, want %v", got, want)
  667. }
  668. key, done = dc.queue.Get()
  669. if key == nil || done {
  670. t.Fatalf("failed to enqueue controller for rs %v", rs2.Name)
  671. }
  672. expectedKey, _ = controller.KeyFunc(d2)
  673. if got, want := key.(string), expectedKey; got != want {
  674. t.Errorf("queue.Get() = %v, want %v", got, want)
  675. }
  676. }
  677. func TestUpdateReplicaSetOrphanWithNewLabels(t *testing.T) {
  678. f := newFixture(t)
  679. d1 := newDeployment("d1", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  680. d2 := newDeployment("d2", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  681. // RS matches both, but is an orphan.
  682. rs := newReplicaSet(d1, "rs1", 1)
  683. rs.OwnerReferences = nil
  684. f.dLister = append(f.dLister, d1, d2)
  685. f.rsLister = append(f.rsLister, rs)
  686. f.objects = append(f.objects, d1, d2, rs)
  687. // Create the fixture but don't start it,
  688. // so nothing happens in the background.
  689. dc, _, err := f.newController()
  690. if err != nil {
  691. t.Fatalf("error creating Deployment controller: %v", err)
  692. }
  693. // Change labels and expect all matching controllers to queue.
  694. prev := *rs
  695. prev.Labels = map[string]string{"foo": "notbar"}
  696. next := *rs
  697. bumpResourceVersion(&next)
  698. dc.updateReplicaSet(&prev, &next)
  699. if got, want := dc.queue.Len(), 2; got != want {
  700. t.Fatalf("queue.Len() = %v, want %v", got, want)
  701. }
  702. }
  703. func TestUpdateReplicaSetChangeControllerRef(t *testing.T) {
  704. f := newFixture(t)
  705. d1 := newDeployment("d1", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  706. d2 := newDeployment("d2", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  707. rs := newReplicaSet(d1, "rs1", 1)
  708. f.dLister = append(f.dLister, d1, d2)
  709. f.rsLister = append(f.rsLister, rs)
  710. f.objects = append(f.objects, d1, d2, rs)
  711. // Create the fixture but don't start it,
  712. // so nothing happens in the background.
  713. dc, _, err := f.newController()
  714. if err != nil {
  715. t.Fatalf("error creating Deployment controller: %v", err)
  716. }
  717. // Change ControllerRef and expect both old and new to queue.
  718. prev := *rs
  719. prev.OwnerReferences = []metav1.OwnerReference{*metav1.NewControllerRef(d2, controllerKind)}
  720. next := *rs
  721. bumpResourceVersion(&next)
  722. dc.updateReplicaSet(&prev, &next)
  723. if got, want := dc.queue.Len(), 2; got != want {
  724. t.Fatalf("queue.Len() = %v, want %v", got, want)
  725. }
  726. }
  727. func TestUpdateReplicaSetRelease(t *testing.T) {
  728. f := newFixture(t)
  729. d1 := newDeployment("d1", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  730. d2 := newDeployment("d2", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  731. rs := newReplicaSet(d1, "rs1", 1)
  732. f.dLister = append(f.dLister, d1, d2)
  733. f.rsLister = append(f.rsLister, rs)
  734. f.objects = append(f.objects, d1, d2, rs)
  735. // Create the fixture but don't start it,
  736. // so nothing happens in the background.
  737. dc, _, err := f.newController()
  738. if err != nil {
  739. t.Fatalf("error creating Deployment controller: %v", err)
  740. }
  741. // Remove ControllerRef and expect all matching controller to sync orphan.
  742. prev := *rs
  743. next := *rs
  744. next.OwnerReferences = nil
  745. bumpResourceVersion(&next)
  746. dc.updateReplicaSet(&prev, &next)
  747. if got, want := dc.queue.Len(), 2; got != want {
  748. t.Fatalf("queue.Len() = %v, want %v", got, want)
  749. }
  750. }
  751. func TestDeleteReplicaSet(t *testing.T) {
  752. f := newFixture(t)
  753. d1 := newDeployment("d1", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  754. d2 := newDeployment("d2", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  755. // Two ReplicaSets that match labels for both Deployments,
  756. // but have ControllerRefs to make ownership explicit.
  757. rs1 := newReplicaSet(d1, "rs1", 1)
  758. rs2 := newReplicaSet(d2, "rs2", 1)
  759. f.dLister = append(f.dLister, d1, d2)
  760. f.rsLister = append(f.rsLister, rs1, rs2)
  761. f.objects = append(f.objects, d1, d2, rs1, rs2)
  762. // Create the fixture but don't start it,
  763. // so nothing happens in the background.
  764. dc, _, err := f.newController()
  765. if err != nil {
  766. t.Fatalf("error creating Deployment controller: %v", err)
  767. }
  768. dc.deleteReplicaSet(rs1)
  769. if got, want := dc.queue.Len(), 1; got != want {
  770. t.Fatalf("queue.Len() = %v, want %v", got, want)
  771. }
  772. key, done := dc.queue.Get()
  773. if key == nil || done {
  774. t.Fatalf("failed to enqueue controller for rs %v", rs1.Name)
  775. }
  776. expectedKey, _ := controller.KeyFunc(d1)
  777. if got, want := key.(string), expectedKey; got != want {
  778. t.Errorf("queue.Get() = %v, want %v", got, want)
  779. }
  780. dc.deleteReplicaSet(rs2)
  781. if got, want := dc.queue.Len(), 1; got != want {
  782. t.Fatalf("queue.Len() = %v, want %v", got, want)
  783. }
  784. key, done = dc.queue.Get()
  785. if key == nil || done {
  786. t.Fatalf("failed to enqueue controller for rs %v", rs2.Name)
  787. }
  788. expectedKey, _ = controller.KeyFunc(d2)
  789. if got, want := key.(string), expectedKey; got != want {
  790. t.Errorf("queue.Get() = %v, want %v", got, want)
  791. }
  792. }
  793. func TestDeleteReplicaSetOrphan(t *testing.T) {
  794. f := newFixture(t)
  795. d1 := newDeployment("d1", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  796. d2 := newDeployment("d2", 1, nil, nil, nil, map[string]string{"foo": "bar"})
  797. // Make the RS an orphan. Expect matching Deployments to be queued.
  798. rs := newReplicaSet(d1, "rs1", 1)
  799. rs.OwnerReferences = nil
  800. f.dLister = append(f.dLister, d1, d2)
  801. f.rsLister = append(f.rsLister, rs)
  802. f.objects = append(f.objects, d1, d2, rs)
  803. // Create the fixture but don't start it,
  804. // so nothing happens in the background.
  805. dc, _, err := f.newController()
  806. if err != nil {
  807. t.Fatalf("error creating Deployment controller: %v", err)
  808. }
  809. dc.deleteReplicaSet(rs)
  810. if got, want := dc.queue.Len(), 0; got != want {
  811. t.Fatalf("queue.Len() = %v, want %v", got, want)
  812. }
  813. }
  814. func bumpResourceVersion(obj metav1.Object) {
  815. ver, _ := strconv.ParseInt(obj.GetResourceVersion(), 10, 32)
  816. obj.SetResourceVersion(strconv.FormatInt(ver+1, 10))
  817. }
  818. // generatePodFromRS creates a pod, with the input ReplicaSet's selector and its template
  819. func generatePodFromRS(rs *apps.ReplicaSet) *v1.Pod {
  820. trueVar := true
  821. return &v1.Pod{
  822. ObjectMeta: metav1.ObjectMeta{
  823. Name: rs.Name + "-pod",
  824. Namespace: rs.Namespace,
  825. Labels: rs.Spec.Selector.MatchLabels,
  826. OwnerReferences: []metav1.OwnerReference{
  827. {UID: rs.UID, APIVersion: "v1beta1", Kind: "ReplicaSet", Name: rs.Name, Controller: &trueVar},
  828. },
  829. },
  830. Spec: rs.Spec.Template.Spec,
  831. }
  832. }