deployment_controller_test.go 31 KB

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