controller_history_test.go 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704
  1. /*
  2. Copyright 2016 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 history
  14. import (
  15. "bytes"
  16. "encoding/json"
  17. "fmt"
  18. "reflect"
  19. "testing"
  20. apps "k8s.io/api/apps/v1"
  21. "k8s.io/api/core/v1"
  22. "k8s.io/client-go/informers"
  23. "k8s.io/client-go/kubernetes/fake"
  24. "k8s.io/kubernetes/pkg/api/legacyscheme"
  25. "k8s.io/kubernetes/pkg/api/testapi"
  26. "k8s.io/kubernetes/pkg/controller"
  27. "k8s.io/apimachinery/pkg/api/errors"
  28. "k8s.io/apimachinery/pkg/api/resource"
  29. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  30. "k8s.io/apimachinery/pkg/labels"
  31. "k8s.io/apimachinery/pkg/runtime"
  32. "k8s.io/apimachinery/pkg/types"
  33. "k8s.io/apimachinery/pkg/util/strategicpatch"
  34. core "k8s.io/client-go/testing"
  35. "time"
  36. )
  37. func TestRealHistory_ListControllerRevisions(t *testing.T) {
  38. type testcase struct {
  39. name string
  40. parent metav1.Object
  41. selector labels.Selector
  42. revisions []*apps.ControllerRevision
  43. want map[string]bool
  44. }
  45. testFn := func(test *testcase, t *testing.T) {
  46. client := fake.NewSimpleClientset()
  47. informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  48. stop := make(chan struct{})
  49. defer close(stop)
  50. informerFactory.Start(stop)
  51. informer := informerFactory.Apps().V1().ControllerRevisions()
  52. informerFactory.WaitForCacheSync(stop)
  53. for i := range test.revisions {
  54. informer.Informer().GetIndexer().Add(test.revisions[i])
  55. }
  56. history := NewHistory(client, informer.Lister())
  57. revisions, err := history.ListControllerRevisions(test.parent, test.selector)
  58. if err != nil {
  59. t.Errorf("%s: %s", test.name, err)
  60. }
  61. got := make(map[string]bool)
  62. for i := range revisions {
  63. got[revisions[i].Name] = true
  64. }
  65. if !reflect.DeepEqual(test.want, got) {
  66. t.Errorf("%s: want %v got %v", test.name, test.want, got)
  67. }
  68. }
  69. ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  70. ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  71. sel1, err := metav1.LabelSelectorAsSelector(ss1.Spec.Selector)
  72. if err != nil {
  73. t.Fatal(err)
  74. }
  75. ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, nil)
  76. if err != nil {
  77. t.Fatal(err)
  78. }
  79. ss1Rev1.Namespace = ss1.Namespace
  80. ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, nil)
  81. if err != nil {
  82. t.Fatal(err)
  83. }
  84. ss1Rev2.Namespace = ss1.Namespace
  85. ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, nil)
  86. if err != nil {
  87. t.Fatal(err)
  88. }
  89. ss2Rev1.Namespace = ss2.Namespace
  90. ss1Orphan, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 3, nil)
  91. if err != nil {
  92. t.Fatal(err)
  93. }
  94. ss1Orphan.Namespace = ss1.Namespace
  95. ss1Orphan.OwnerReferences = nil
  96. tests := []testcase{
  97. {
  98. name: "selects none",
  99. parent: &ss1.ObjectMeta,
  100. selector: sel1,
  101. revisions: nil,
  102. want: map[string]bool{},
  103. },
  104. {
  105. name: "selects all",
  106. parent: &ss1.ObjectMeta,
  107. selector: sel1,
  108. revisions: []*apps.ControllerRevision{ss1Rev1, ss1Rev2},
  109. want: map[string]bool{ss1Rev1.Name: true, ss1Rev2.Name: true},
  110. },
  111. {
  112. name: "doesn't select another Objects history",
  113. parent: &ss1.ObjectMeta,
  114. selector: sel1,
  115. revisions: []*apps.ControllerRevision{ss1Rev1, ss1Rev2, ss2Rev1},
  116. want: map[string]bool{ss1Rev1.Name: true, ss1Rev2.Name: true},
  117. },
  118. {
  119. name: "selects orphans",
  120. parent: &ss1.ObjectMeta,
  121. selector: sel1,
  122. revisions: []*apps.ControllerRevision{ss1Rev1, ss1Rev2, ss1Orphan},
  123. want: map[string]bool{ss1Rev1.Name: true, ss1Rev2.Name: true, ss1Orphan.Name: true},
  124. },
  125. }
  126. for i := range tests {
  127. testFn(&tests[i], t)
  128. }
  129. }
  130. func TestFakeHistory_ListControllerRevisions(t *testing.T) {
  131. type testcase struct {
  132. name string
  133. parent metav1.Object
  134. selector labels.Selector
  135. revisions []*apps.ControllerRevision
  136. want map[string]bool
  137. }
  138. testFn := func(test *testcase, t *testing.T) {
  139. client := fake.NewSimpleClientset()
  140. informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  141. stop := make(chan struct{})
  142. defer close(stop)
  143. informerFactory.Start(stop)
  144. informer := informerFactory.Apps().V1().ControllerRevisions()
  145. informerFactory.WaitForCacheSync(stop)
  146. for i := range test.revisions {
  147. informer.Informer().GetIndexer().Add(test.revisions[i])
  148. }
  149. history := NewFakeHistory(informer)
  150. revisions, err := history.ListControllerRevisions(test.parent, test.selector)
  151. if err != nil {
  152. t.Errorf("%s: %s", test.name, err)
  153. }
  154. got := make(map[string]bool)
  155. for i := range revisions {
  156. got[revisions[i].Name] = true
  157. }
  158. if !reflect.DeepEqual(test.want, got) {
  159. t.Errorf("%s: want %v got %v", test.name, test.want, got)
  160. }
  161. }
  162. ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  163. ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  164. sel1, err := metav1.LabelSelectorAsSelector(ss1.Spec.Selector)
  165. if err != nil {
  166. t.Fatal(err)
  167. }
  168. ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, nil)
  169. if err != nil {
  170. t.Fatal(err)
  171. }
  172. ss1Rev1.Namespace = ss1.Namespace
  173. ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, nil)
  174. if err != nil {
  175. t.Fatal(err)
  176. }
  177. ss1Rev2.Namespace = ss1.Namespace
  178. ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, nil)
  179. if err != nil {
  180. t.Fatal(err)
  181. }
  182. ss2Rev1.Namespace = ss2.Namespace
  183. ss1Orphan, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 3, nil)
  184. if err != nil {
  185. t.Fatal(err)
  186. }
  187. ss1Orphan.Namespace = ss1.Namespace
  188. ss1Orphan.OwnerReferences = nil
  189. tests := []testcase{
  190. {
  191. name: "selects none",
  192. parent: &ss1.ObjectMeta,
  193. selector: sel1,
  194. revisions: nil,
  195. want: map[string]bool{},
  196. },
  197. {
  198. name: "selects all",
  199. parent: &ss1.ObjectMeta,
  200. selector: sel1,
  201. revisions: []*apps.ControllerRevision{ss1Rev1, ss1Rev2},
  202. want: map[string]bool{ss1Rev1.Name: true, ss1Rev2.Name: true},
  203. },
  204. {
  205. name: "doesn't select another Objects history",
  206. parent: &ss1.ObjectMeta,
  207. selector: sel1,
  208. revisions: []*apps.ControllerRevision{ss1Rev1, ss1Rev2, ss2Rev1},
  209. want: map[string]bool{ss1Rev1.Name: true, ss1Rev2.Name: true},
  210. },
  211. {
  212. name: "selects orphans",
  213. parent: &ss1.ObjectMeta,
  214. selector: sel1,
  215. revisions: []*apps.ControllerRevision{ss1Rev1, ss1Rev2, ss1Orphan},
  216. want: map[string]bool{ss1Rev1.Name: true, ss1Rev2.Name: true, ss1Orphan.Name: true},
  217. },
  218. }
  219. for i := range tests {
  220. testFn(&tests[i], t)
  221. }
  222. }
  223. func TestRealHistory_CreateControllerRevision(t *testing.T) {
  224. type testcase struct {
  225. name string
  226. parent metav1.Object
  227. revision *apps.ControllerRevision
  228. existing []struct {
  229. parent metav1.Object
  230. revision *apps.ControllerRevision
  231. }
  232. rename bool
  233. }
  234. testFn := func(test *testcase, t *testing.T) {
  235. client := fake.NewSimpleClientset()
  236. informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  237. stop := make(chan struct{})
  238. defer close(stop)
  239. informerFactory.Start(stop)
  240. informer := informerFactory.Apps().V1().ControllerRevisions()
  241. informerFactory.WaitForCacheSync(stop)
  242. history := NewHistory(client, informer.Lister())
  243. var collisionCount int32
  244. for _, item := range test.existing {
  245. _, err := client.AppsV1().ControllerRevisions(item.parent.GetNamespace()).Create(item.revision)
  246. if err != nil {
  247. t.Fatal(err)
  248. }
  249. }
  250. // Clear collisionCount before creating the test revision
  251. collisionCount = 0
  252. created, err := history.CreateControllerRevision(test.parent, test.revision, &collisionCount)
  253. if err != nil {
  254. t.Errorf("%s: %s", test.name, err)
  255. }
  256. if test.rename {
  257. if created.Name == test.revision.Name {
  258. t.Errorf("%s: wanted rename got %s %s", test.name, created.Name, test.revision.Name)
  259. }
  260. expectedName := ControllerRevisionName(test.parent.GetName(), HashControllerRevision(test.revision, &collisionCount))
  261. if created.Name != expectedName {
  262. t.Errorf("%s: on name collision wanted new name %s got %s", test.name, expectedName, created.Name)
  263. }
  264. // Second name collision will be caused by an identical revision, so no need to do anything
  265. _, err = history.CreateControllerRevision(test.parent, test.revision, &collisionCount)
  266. if err != nil {
  267. t.Errorf("%s: %s", test.name, err)
  268. }
  269. if collisionCount != 1 {
  270. t.Errorf("%s: on second name collision wanted collisionCount 1 got %d", test.name, collisionCount)
  271. }
  272. }
  273. if !test.rename && created.Name != test.revision.Name {
  274. t.Errorf("%s: wanted %s got %s", test.name, test.revision.Name, created.Name)
  275. }
  276. }
  277. ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  278. ss1.Status.CollisionCount = new(int32)
  279. ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  280. ss2.Status.CollisionCount = new(int32)
  281. ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  282. if err != nil {
  283. t.Fatal(err)
  284. }
  285. ss1Rev1.Namespace = ss1.Namespace
  286. // Create a new revision with the same name and hash label as an existing revision, but with
  287. // a different template. This could happen as a result of a hash collision, but in this test
  288. // this situation is created by setting name and hash label to values known to be in use by
  289. // an existing revision.
  290. modTemplate := ss1.Spec.Template.DeepCopy()
  291. modTemplate.Labels["foo"] = "not_bar"
  292. ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(modTemplate), 2, ss1.Status.CollisionCount)
  293. ss1Rev2.Name = ss1Rev1.Name
  294. ss1Rev2.Labels[ControllerRevisionHashLabel] = ss1Rev1.Labels[ControllerRevisionHashLabel]
  295. if err != nil {
  296. t.Fatal(err)
  297. }
  298. ss1Rev2.Namespace = ss1.Namespace
  299. ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
  300. if err != nil {
  301. t.Fatal(err)
  302. }
  303. ss2Rev1.Namespace = ss2.Namespace
  304. tests := []testcase{
  305. {
  306. name: "creates new",
  307. parent: &ss1.ObjectMeta,
  308. revision: ss1Rev1,
  309. existing: nil,
  310. rename: false,
  311. },
  312. {
  313. name: "create doesn't conflict when parents differ",
  314. parent: &ss2.ObjectMeta,
  315. revision: ss2Rev1,
  316. existing: []struct {
  317. parent metav1.Object
  318. revision *apps.ControllerRevision
  319. }{
  320. {
  321. parent: ss1,
  322. revision: ss1Rev1,
  323. },
  324. },
  325. rename: false,
  326. },
  327. {
  328. name: "create renames on conflict",
  329. parent: &ss1.ObjectMeta,
  330. revision: ss1Rev1,
  331. existing: []struct {
  332. parent metav1.Object
  333. revision *apps.ControllerRevision
  334. }{
  335. {
  336. parent: ss1,
  337. revision: ss1Rev2,
  338. },
  339. },
  340. rename: true,
  341. },
  342. }
  343. for i := range tests {
  344. testFn(&tests[i], t)
  345. }
  346. }
  347. func TestFakeHistory_CreateControllerRevision(t *testing.T) {
  348. type testcase struct {
  349. name string
  350. parent metav1.Object
  351. revision *apps.ControllerRevision
  352. existing []struct {
  353. parent metav1.Object
  354. revision *apps.ControllerRevision
  355. }
  356. rename bool
  357. }
  358. testFn := func(test *testcase, t *testing.T) {
  359. client := fake.NewSimpleClientset()
  360. informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  361. stop := make(chan struct{})
  362. defer close(stop)
  363. informerFactory.Start(stop)
  364. informer := informerFactory.Apps().V1().ControllerRevisions()
  365. informerFactory.WaitForCacheSync(stop)
  366. history := NewFakeHistory(informer)
  367. var collisionCount int32
  368. for i := range test.existing {
  369. _, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
  370. if err != nil {
  371. t.Fatal(err)
  372. }
  373. }
  374. // Clear collisionCount before creating the test revision
  375. collisionCount = 0
  376. created, err := history.CreateControllerRevision(test.parent, test.revision, &collisionCount)
  377. if err != nil {
  378. t.Errorf("%s: %s", test.name, err)
  379. }
  380. if test.rename {
  381. if created.Name == test.revision.Name {
  382. t.Errorf("%s: wanted rename got %s %s", test.name, created.Name, test.revision.Name)
  383. }
  384. expectedName := ControllerRevisionName(test.parent.GetName(), HashControllerRevision(test.revision, &collisionCount))
  385. if created.Name != expectedName {
  386. t.Errorf("%s: on name collision wanted new name %s got %s", test.name, expectedName, created.Name)
  387. }
  388. // Second name collision should have incremented collisionCount to 2
  389. _, err = history.CreateControllerRevision(test.parent, test.revision, &collisionCount)
  390. if err != nil {
  391. t.Errorf("%s: %s", test.name, err)
  392. }
  393. if collisionCount != 2 {
  394. t.Errorf("%s: on second name collision wanted collisionCount 1 got %d", test.name, collisionCount)
  395. }
  396. }
  397. if !test.rename && created.Name != test.revision.Name {
  398. t.Errorf("%s: wanted %s got %s", test.name, test.revision.Name, created.Name)
  399. }
  400. }
  401. ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  402. ss1.Status.CollisionCount = new(int32)
  403. ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  404. ss2.Status.CollisionCount = new(int32)
  405. ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  406. if err != nil {
  407. t.Fatal(err)
  408. }
  409. ss1Rev1.Namespace = ss1.Namespace
  410. ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  411. if err != nil {
  412. t.Fatal(err)
  413. }
  414. ss1Rev2.Namespace = ss1.Namespace
  415. ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
  416. if err != nil {
  417. t.Fatal(err)
  418. }
  419. ss2Rev1.Namespace = ss2.Namespace
  420. tests := []testcase{
  421. {
  422. name: "creates new",
  423. parent: &ss1.ObjectMeta,
  424. revision: ss1Rev1,
  425. existing: nil,
  426. rename: false,
  427. },
  428. {
  429. name: "create doesn't conflict when parents differ",
  430. parent: &ss2.ObjectMeta,
  431. revision: ss2Rev1,
  432. existing: []struct {
  433. parent metav1.Object
  434. revision *apps.ControllerRevision
  435. }{
  436. {
  437. parent: ss1,
  438. revision: ss1Rev1,
  439. },
  440. },
  441. rename: false,
  442. },
  443. {
  444. name: "create renames on conflict",
  445. parent: &ss1.ObjectMeta,
  446. revision: ss1Rev1,
  447. existing: []struct {
  448. parent metav1.Object
  449. revision *apps.ControllerRevision
  450. }{
  451. {
  452. parent: ss1,
  453. revision: ss1Rev1,
  454. },
  455. },
  456. rename: true,
  457. },
  458. }
  459. for i := range tests {
  460. testFn(&tests[i], t)
  461. }
  462. }
  463. func TestRealHistory_UpdateControllerRevision(t *testing.T) {
  464. conflictAttempts := 0
  465. type testcase struct {
  466. name string
  467. revision *apps.ControllerRevision
  468. newRevision int64
  469. existing []struct {
  470. parent metav1.Object
  471. revision *apps.ControllerRevision
  472. }
  473. reactor core.ReactionFunc
  474. err bool
  475. }
  476. conflictSuccess := func(action core.Action) (bool, runtime.Object, error) {
  477. defer func() {
  478. conflictAttempts++
  479. }()
  480. switch action.(type) {
  481. case core.UpdateActionImpl:
  482. update := action.(core.UpdateAction)
  483. if conflictAttempts < 2 {
  484. return true, update.GetObject(), errors.NewConflict(update.GetResource().GroupResource(), "", fmt.Errorf("conflict"))
  485. }
  486. return true, update.GetObject(), nil
  487. default:
  488. return false, nil, nil
  489. }
  490. }
  491. internalError := func(action core.Action) (bool, runtime.Object, error) {
  492. switch action.(type) {
  493. case core.UpdateActionImpl:
  494. return true, nil, errors.NewInternalError(fmt.Errorf("internal error"))
  495. default:
  496. return false, nil, nil
  497. }
  498. }
  499. testFn := func(test *testcase, t *testing.T) {
  500. client := fake.NewSimpleClientset()
  501. informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  502. stop := make(chan struct{})
  503. defer close(stop)
  504. informerFactory.Start(stop)
  505. informer := informerFactory.Apps().V1().ControllerRevisions()
  506. informerFactory.WaitForCacheSync(stop)
  507. history := NewHistory(client, informer.Lister())
  508. var collisionCount int32
  509. for i := range test.existing {
  510. _, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
  511. if err != nil {
  512. t.Fatal(err)
  513. }
  514. }
  515. if test.reactor != nil {
  516. client.PrependReactor("*", "*", test.reactor)
  517. }
  518. updated, err := history.UpdateControllerRevision(test.revision, test.newRevision)
  519. if !test.err && err != nil {
  520. t.Errorf("%s: %s", test.name, err)
  521. }
  522. if !test.err && updated.Revision != test.newRevision {
  523. t.Errorf("%s: got %d want %d", test.name, updated.Revision, test.newRevision)
  524. }
  525. if test.err && err == nil {
  526. t.Errorf("%s: expected error", test.name)
  527. }
  528. }
  529. ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  530. ss1.Status.CollisionCount = new(int32)
  531. ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  532. if err != nil {
  533. t.Fatal(err)
  534. }
  535. ss1Rev1.Namespace = ss1.Namespace
  536. ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  537. if err != nil {
  538. t.Fatal(err)
  539. }
  540. ss1Rev2.Namespace = ss1.Namespace
  541. tests := []testcase{
  542. {
  543. name: "update succeeds",
  544. revision: ss1Rev1,
  545. newRevision: ss1Rev1.Revision + 1,
  546. existing: []struct {
  547. parent metav1.Object
  548. revision *apps.ControllerRevision
  549. }{
  550. {
  551. parent: ss1,
  552. revision: ss1Rev1,
  553. },
  554. },
  555. reactor: nil,
  556. err: false,
  557. },
  558. {
  559. name: "update succeeds no noop",
  560. revision: ss1Rev1,
  561. newRevision: ss1Rev1.Revision,
  562. existing: []struct {
  563. parent metav1.Object
  564. revision *apps.ControllerRevision
  565. }{
  566. {
  567. parent: ss1,
  568. revision: ss1Rev1,
  569. },
  570. },
  571. reactor: nil,
  572. err: false,
  573. }, {
  574. name: "update fails on error",
  575. revision: ss1Rev1,
  576. newRevision: ss1Rev1.Revision + 10,
  577. existing: []struct {
  578. parent metav1.Object
  579. revision *apps.ControllerRevision
  580. }{
  581. {
  582. parent: ss1,
  583. revision: ss1Rev1,
  584. },
  585. },
  586. reactor: internalError,
  587. err: true,
  588. },
  589. {
  590. name: "update on succeeds on conflict",
  591. revision: ss1Rev1,
  592. newRevision: ss1Rev1.Revision + 1,
  593. existing: []struct {
  594. parent metav1.Object
  595. revision *apps.ControllerRevision
  596. }{
  597. {
  598. parent: ss1,
  599. revision: ss1Rev1,
  600. },
  601. },
  602. reactor: conflictSuccess,
  603. err: false,
  604. },
  605. }
  606. for i := range tests {
  607. conflictAttempts = 0
  608. testFn(&tests[i], t)
  609. }
  610. }
  611. func TestFakeHistory_UpdateControllerRevision(t *testing.T) {
  612. type testcase struct {
  613. name string
  614. revision *apps.ControllerRevision
  615. newRevision int64
  616. existing []struct {
  617. parent metav1.Object
  618. revision *apps.ControllerRevision
  619. }
  620. err bool
  621. }
  622. testFn := func(test *testcase, t *testing.T) {
  623. client := fake.NewSimpleClientset()
  624. informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  625. stop := make(chan struct{})
  626. defer close(stop)
  627. informerFactory.Start(stop)
  628. informer := informerFactory.Apps().V1().ControllerRevisions()
  629. informerFactory.WaitForCacheSync(stop)
  630. history := NewFakeHistory(informer)
  631. var collisionCount int32
  632. for i := range test.existing {
  633. _, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
  634. if err != nil {
  635. t.Fatal(err)
  636. }
  637. }
  638. updated, err := history.UpdateControllerRevision(test.revision, test.newRevision)
  639. if !test.err && err != nil {
  640. t.Errorf("%s: %s", test.name, err)
  641. }
  642. if !test.err && updated.Revision != test.newRevision {
  643. t.Errorf("%s: got %d want %d", test.name, updated.Revision, test.newRevision)
  644. }
  645. if test.err && err == nil {
  646. t.Errorf("%s: expected error", test.name)
  647. }
  648. }
  649. ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  650. ss1.Status.CollisionCount = new(int32)
  651. ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  652. if err != nil {
  653. t.Fatal(err)
  654. }
  655. ss1Rev1.Namespace = ss1.Namespace
  656. ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  657. if err != nil {
  658. t.Fatal(err)
  659. }
  660. ss1Rev2.Namespace = ss1.Namespace
  661. tests := []testcase{
  662. {
  663. name: "update succeeds",
  664. revision: ss1Rev1,
  665. newRevision: ss1Rev1.Revision + 1,
  666. existing: []struct {
  667. parent metav1.Object
  668. revision *apps.ControllerRevision
  669. }{
  670. {
  671. parent: ss1,
  672. revision: ss1Rev1,
  673. },
  674. },
  675. err: false,
  676. },
  677. {
  678. name: "update succeeds no noop",
  679. revision: ss1Rev1,
  680. newRevision: ss1Rev1.Revision,
  681. existing: []struct {
  682. parent metav1.Object
  683. revision *apps.ControllerRevision
  684. }{
  685. {
  686. parent: ss1,
  687. revision: ss1Rev1,
  688. },
  689. },
  690. err: false,
  691. },
  692. }
  693. for i := range tests {
  694. testFn(&tests[i], t)
  695. }
  696. }
  697. func TestRealHistory_DeleteControllerRevision(t *testing.T) {
  698. type testcase struct {
  699. name string
  700. revision *apps.ControllerRevision
  701. existing []struct {
  702. parent metav1.Object
  703. revision *apps.ControllerRevision
  704. }
  705. err bool
  706. }
  707. testFn := func(test *testcase, t *testing.T) {
  708. client := fake.NewSimpleClientset()
  709. informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  710. stop := make(chan struct{})
  711. defer close(stop)
  712. informerFactory.Start(stop)
  713. informer := informerFactory.Apps().V1().ControllerRevisions()
  714. informerFactory.WaitForCacheSync(stop)
  715. history := NewHistory(client, informer.Lister())
  716. var collisionCount int32
  717. for i := range test.existing {
  718. _, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
  719. if err != nil {
  720. t.Fatal(err)
  721. }
  722. }
  723. err := history.DeleteControllerRevision(test.revision)
  724. if !test.err && err != nil {
  725. t.Errorf("%s: %s", test.name, err)
  726. }
  727. if test.err && err == nil {
  728. t.Errorf("%s: expected error", test.name)
  729. }
  730. }
  731. ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  732. ss1.Status.CollisionCount = new(int32)
  733. ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  734. ss2.Status.CollisionCount = new(int32)
  735. ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  736. if err != nil {
  737. t.Fatal(err)
  738. }
  739. ss1Rev1.Namespace = ss1.Namespace
  740. ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  741. if err != nil {
  742. t.Fatal(err)
  743. }
  744. ss1Rev2.Namespace = ss1.Namespace
  745. ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
  746. if err != nil {
  747. t.Fatal(err)
  748. }
  749. ss2Rev1.Namespace = ss2.Namespace
  750. ss2Rev2, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 2, ss2.Status.CollisionCount)
  751. if err != nil {
  752. t.Fatal(err)
  753. }
  754. ss2Rev2.Namespace = ss2.Namespace
  755. tests := []testcase{
  756. {
  757. name: "delete empty fails",
  758. revision: ss1Rev1,
  759. existing: nil,
  760. err: true,
  761. },
  762. {
  763. name: "delete existing succeeds",
  764. revision: ss1Rev1,
  765. existing: []struct {
  766. parent metav1.Object
  767. revision *apps.ControllerRevision
  768. }{
  769. {
  770. parent: ss1,
  771. revision: ss1Rev1,
  772. },
  773. },
  774. err: false,
  775. }, {
  776. name: "delete non-existing fails",
  777. revision: ss1Rev1,
  778. existing: []struct {
  779. parent metav1.Object
  780. revision *apps.ControllerRevision
  781. }{
  782. {
  783. parent: ss2,
  784. revision: ss2Rev1,
  785. },
  786. {
  787. parent: ss2,
  788. revision: ss2Rev2,
  789. },
  790. },
  791. err: true,
  792. },
  793. }
  794. for i := range tests {
  795. testFn(&tests[i], t)
  796. }
  797. }
  798. func TestFakeHistory_DeleteControllerRevision(t *testing.T) {
  799. type testcase struct {
  800. name string
  801. revision *apps.ControllerRevision
  802. existing []struct {
  803. parent metav1.Object
  804. revision *apps.ControllerRevision
  805. }
  806. err bool
  807. }
  808. testFn := func(test *testcase, t *testing.T) {
  809. client := fake.NewSimpleClientset()
  810. informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  811. stop := make(chan struct{})
  812. defer close(stop)
  813. informerFactory.Start(stop)
  814. informer := informerFactory.Apps().V1().ControllerRevisions()
  815. informerFactory.WaitForCacheSync(stop)
  816. history := NewFakeHistory(informer)
  817. var collisionCount int32
  818. for i := range test.existing {
  819. _, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
  820. if err != nil {
  821. t.Fatal(err)
  822. }
  823. }
  824. err := history.DeleteControllerRevision(test.revision)
  825. if !test.err && err != nil {
  826. t.Errorf("%s: %s", test.name, err)
  827. }
  828. if test.err && err == nil {
  829. t.Errorf("%s: expected error", test.name)
  830. }
  831. }
  832. ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  833. ss1.Status.CollisionCount = new(int32)
  834. ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  835. ss2.Status.CollisionCount = new(int32)
  836. ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  837. if err != nil {
  838. t.Fatal(err)
  839. }
  840. ss1Rev1.Namespace = ss1.Namespace
  841. ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  842. if err != nil {
  843. t.Fatal(err)
  844. }
  845. ss1Rev2.Namespace = ss1.Namespace
  846. ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
  847. if err != nil {
  848. t.Fatal(err)
  849. }
  850. ss2Rev1.Namespace = ss2.Namespace
  851. ss2Rev2, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 2, ss2.Status.CollisionCount)
  852. if err != nil {
  853. t.Fatal(err)
  854. }
  855. ss2Rev2.Namespace = ss2.Namespace
  856. tests := []testcase{
  857. {
  858. name: "delete empty fails",
  859. revision: ss1Rev1,
  860. existing: nil,
  861. err: true,
  862. },
  863. {
  864. name: "delete existing succeeds",
  865. revision: ss1Rev1,
  866. existing: []struct {
  867. parent metav1.Object
  868. revision *apps.ControllerRevision
  869. }{
  870. {
  871. parent: ss1,
  872. revision: ss1Rev1,
  873. },
  874. },
  875. err: false,
  876. }, {
  877. name: "delete non-existing fails",
  878. revision: ss1Rev1,
  879. existing: []struct {
  880. parent metav1.Object
  881. revision *apps.ControllerRevision
  882. }{
  883. {
  884. parent: ss2,
  885. revision: ss2Rev1,
  886. },
  887. {
  888. parent: ss2,
  889. revision: ss2Rev2,
  890. },
  891. },
  892. err: true,
  893. },
  894. }
  895. for i := range tests {
  896. testFn(&tests[i], t)
  897. }
  898. }
  899. func TestRealHistory_AdoptControllerRevision(t *testing.T) {
  900. type testcase struct {
  901. name string
  902. parent metav1.Object
  903. revision *apps.ControllerRevision
  904. existing []struct {
  905. parent metav1.Object
  906. revision *apps.ControllerRevision
  907. }
  908. err bool
  909. }
  910. testFn := func(test *testcase, t *testing.T) {
  911. client := fake.NewSimpleClientset()
  912. client.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) {
  913. switch action := action.(type) {
  914. case core.PatchActionImpl:
  915. var found *apps.ControllerRevision
  916. for i := range test.existing {
  917. if test.revision.Name == test.existing[i].revision.Name &&
  918. test.revision.Namespace == test.existing[i].revision.Namespace {
  919. found = test.existing[i].revision
  920. break
  921. }
  922. }
  923. if found == nil {
  924. return true, nil, errors.NewNotFound(apps.Resource("controllerrevisions"), test.revision.Name)
  925. }
  926. b, err := strategicpatch.StrategicMergePatch(
  927. []byte(runtime.EncodeOrDie(testapi.Apps.Codec(), test.revision)),
  928. action.GetPatch(), test.revision)
  929. if err != nil {
  930. return true, nil, err
  931. }
  932. obj, err := runtime.Decode(testapi.Apps.Codec(), b)
  933. if err != nil {
  934. return true, nil, err
  935. }
  936. patched, err := legacyscheme.Scheme.ConvertToVersion(obj, apps.SchemeGroupVersion)
  937. if err != nil {
  938. return true, nil, err
  939. }
  940. return true, patched, err
  941. default:
  942. return false, nil, nil
  943. }
  944. })
  945. informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  946. stop := make(chan struct{})
  947. defer close(stop)
  948. informerFactory.Start(stop)
  949. informer := informerFactory.Apps().V1().ControllerRevisions()
  950. informerFactory.WaitForCacheSync(stop)
  951. history := NewHistory(client, informer.Lister())
  952. var collisionCount int32
  953. for i := range test.existing {
  954. _, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
  955. if err != nil {
  956. t.Fatal(err)
  957. }
  958. }
  959. adopted, err := history.AdoptControllerRevision(test.parent, parentKind, test.revision)
  960. if !test.err && err != nil {
  961. t.Errorf("%s: %s", test.name, err)
  962. }
  963. if !test.err && !metav1.IsControlledBy(adopted, test.parent) {
  964. t.Errorf("%s: adoption failed", test.name)
  965. }
  966. if test.err && err == nil {
  967. t.Errorf("%s: expected error", test.name)
  968. }
  969. }
  970. ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  971. ss1.Status.CollisionCount = new(int32)
  972. ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  973. ss2.Status.CollisionCount = new(int32)
  974. ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  975. if err != nil {
  976. t.Fatal(err)
  977. }
  978. ss1Rev1.Namespace = ss1.Namespace
  979. ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  980. if err != nil {
  981. t.Fatal(err)
  982. }
  983. ss1Rev2.Namespace = ss1.Namespace
  984. ss1Rev2.OwnerReferences = []metav1.OwnerReference{}
  985. ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
  986. if err != nil {
  987. t.Fatal(err)
  988. }
  989. ss2Rev1.Namespace = ss2.Namespace
  990. tests := []testcase{
  991. {
  992. name: "adopting an orphan succeeds",
  993. parent: ss1,
  994. revision: ss1Rev2,
  995. existing: []struct {
  996. parent metav1.Object
  997. revision *apps.ControllerRevision
  998. }{
  999. {
  1000. parent: ss1,
  1001. revision: ss1Rev2,
  1002. },
  1003. },
  1004. err: false,
  1005. },
  1006. {
  1007. name: "adopting an owned revision fails",
  1008. parent: ss1,
  1009. revision: ss2Rev1,
  1010. existing: []struct {
  1011. parent metav1.Object
  1012. revision *apps.ControllerRevision
  1013. }{
  1014. {
  1015. parent: ss2,
  1016. revision: ss2Rev1,
  1017. },
  1018. },
  1019. err: true,
  1020. },
  1021. {
  1022. name: "adopting a non-existent revision fails",
  1023. parent: ss1,
  1024. revision: ss1Rev2,
  1025. existing: nil,
  1026. err: true,
  1027. },
  1028. }
  1029. for i := range tests {
  1030. testFn(&tests[i], t)
  1031. }
  1032. }
  1033. func TestFakeHistory_AdoptControllerRevision(t *testing.T) {
  1034. type testcase struct {
  1035. name string
  1036. parent metav1.Object
  1037. parentType *metav1.TypeMeta
  1038. revision *apps.ControllerRevision
  1039. existing []struct {
  1040. parent metav1.Object
  1041. revision *apps.ControllerRevision
  1042. }
  1043. err bool
  1044. }
  1045. testFn := func(test *testcase, t *testing.T) {
  1046. client := fake.NewSimpleClientset()
  1047. informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  1048. stop := make(chan struct{})
  1049. defer close(stop)
  1050. informerFactory.Start(stop)
  1051. informer := informerFactory.Apps().V1().ControllerRevisions()
  1052. informerFactory.WaitForCacheSync(stop)
  1053. history := NewFakeHistory(informer)
  1054. var collisionCount int32
  1055. for i := range test.existing {
  1056. _, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
  1057. if err != nil {
  1058. t.Fatal(err)
  1059. }
  1060. }
  1061. adopted, err := history.AdoptControllerRevision(test.parent, parentKind, test.revision)
  1062. if !test.err && err != nil {
  1063. t.Errorf("%s: %s", test.name, err)
  1064. }
  1065. if !test.err && !metav1.IsControlledBy(adopted, test.parent) {
  1066. t.Errorf("%s: adoption failed", test.name)
  1067. }
  1068. if test.err && err == nil {
  1069. t.Errorf("%s: expected error", test.name)
  1070. }
  1071. }
  1072. ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  1073. ss1.Status.CollisionCount = new(int32)
  1074. ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  1075. ss2.Status.CollisionCount = new(int32)
  1076. ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  1077. if err != nil {
  1078. t.Fatal(err)
  1079. }
  1080. ss1Rev1.Namespace = ss1.Namespace
  1081. ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  1082. if err != nil {
  1083. t.Fatal(err)
  1084. }
  1085. ss1Rev2.Namespace = ss1.Namespace
  1086. ss1Rev2.OwnerReferences = []metav1.OwnerReference{}
  1087. ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
  1088. if err != nil {
  1089. t.Fatal(err)
  1090. }
  1091. ss2Rev1.Namespace = ss2.Namespace
  1092. tests := []testcase{
  1093. {
  1094. name: "adopting an orphan succeeds",
  1095. parent: ss1,
  1096. parentType: &ss1.TypeMeta,
  1097. revision: ss1Rev2,
  1098. existing: []struct {
  1099. parent metav1.Object
  1100. revision *apps.ControllerRevision
  1101. }{
  1102. {
  1103. parent: ss1,
  1104. revision: ss1Rev2,
  1105. },
  1106. },
  1107. err: false,
  1108. },
  1109. {
  1110. name: "adopting an owned revision fails",
  1111. parent: ss1,
  1112. parentType: &ss1.TypeMeta,
  1113. revision: ss2Rev1,
  1114. existing: []struct {
  1115. parent metav1.Object
  1116. revision *apps.ControllerRevision
  1117. }{
  1118. {
  1119. parent: ss2,
  1120. revision: ss2Rev1,
  1121. },
  1122. },
  1123. err: true,
  1124. },
  1125. {
  1126. name: "adopting a non-existent revision fails",
  1127. parent: ss1,
  1128. parentType: &ss1.TypeMeta,
  1129. revision: ss1Rev2,
  1130. existing: nil,
  1131. err: true,
  1132. },
  1133. }
  1134. for i := range tests {
  1135. testFn(&tests[i], t)
  1136. }
  1137. }
  1138. func TestRealHistory_ReleaseControllerRevision(t *testing.T) {
  1139. type testcase struct {
  1140. name string
  1141. parent metav1.Object
  1142. revision *apps.ControllerRevision
  1143. existing []struct {
  1144. parent metav1.Object
  1145. revision *apps.ControllerRevision
  1146. }
  1147. err bool
  1148. }
  1149. testFn := func(test *testcase, t *testing.T) {
  1150. client := fake.NewSimpleClientset()
  1151. client.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) {
  1152. switch action := action.(type) {
  1153. case core.PatchActionImpl:
  1154. var found *apps.ControllerRevision
  1155. for i := range test.existing {
  1156. if test.revision.Name == test.existing[i].revision.Name &&
  1157. test.revision.Namespace == test.existing[i].revision.Namespace {
  1158. found = test.existing[i].revision
  1159. break
  1160. }
  1161. }
  1162. if found == nil {
  1163. return true, nil, errors.NewNotFound(apps.Resource("controllerrevisions"), test.revision.Name)
  1164. }
  1165. if !metav1.IsControlledBy(test.revision, test.parent) {
  1166. return true, nil, errors.NewInvalid(
  1167. test.revision.GroupVersionKind().GroupKind(), test.revision.Name, nil)
  1168. }
  1169. b, err := strategicpatch.StrategicMergePatch(
  1170. []byte(runtime.EncodeOrDie(testapi.Apps.Codec(), test.revision)),
  1171. action.GetPatch(), test.revision)
  1172. if err != nil {
  1173. return true, nil, err
  1174. }
  1175. obj, err := runtime.Decode(testapi.Apps.Codec(), b)
  1176. if err != nil {
  1177. return true, nil, err
  1178. }
  1179. patched, err := legacyscheme.Scheme.ConvertToVersion(obj, apps.SchemeGroupVersion)
  1180. if err != nil {
  1181. return true, nil, err
  1182. }
  1183. return true, patched, err
  1184. default:
  1185. return false, nil, nil
  1186. }
  1187. })
  1188. informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  1189. stop := make(chan struct{})
  1190. defer close(stop)
  1191. informerFactory.Start(stop)
  1192. informer := informerFactory.Apps().V1().ControllerRevisions()
  1193. informerFactory.WaitForCacheSync(stop)
  1194. history := NewHistory(client, informer.Lister())
  1195. var collisionCount int32
  1196. for i := range test.existing {
  1197. _, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
  1198. if err != nil {
  1199. t.Fatal(err)
  1200. }
  1201. }
  1202. adopted, err := history.ReleaseControllerRevision(test.parent, test.revision)
  1203. if !test.err {
  1204. if err != nil {
  1205. t.Errorf("%s: %s", test.name, err)
  1206. }
  1207. if adopted == nil {
  1208. return
  1209. }
  1210. if metav1.IsControlledBy(adopted, test.parent) {
  1211. t.Errorf("%s: release failed", test.name)
  1212. }
  1213. }
  1214. if test.err && err == nil {
  1215. t.Errorf("%s: expected error", test.name)
  1216. }
  1217. }
  1218. ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  1219. ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  1220. ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, nil)
  1221. if err != nil {
  1222. t.Fatal(err)
  1223. }
  1224. ss1Rev1.Namespace = ss1.Namespace
  1225. ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, nil)
  1226. if err != nil {
  1227. t.Fatal(err)
  1228. }
  1229. ss1Rev2.Namespace = ss1.Namespace
  1230. ss1Rev2.OwnerReferences = []metav1.OwnerReference{}
  1231. ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, nil)
  1232. if err != nil {
  1233. t.Fatal(err)
  1234. }
  1235. ss2Rev1.Namespace = ss2.Namespace
  1236. tests := []testcase{
  1237. {
  1238. name: "releasing an owned revision succeeds",
  1239. parent: ss1,
  1240. revision: ss1Rev1,
  1241. existing: []struct {
  1242. parent metav1.Object
  1243. revision *apps.ControllerRevision
  1244. }{
  1245. {
  1246. parent: ss1,
  1247. revision: ss1Rev1,
  1248. },
  1249. },
  1250. err: false,
  1251. },
  1252. {
  1253. name: "releasing an orphan succeeds",
  1254. parent: ss1,
  1255. revision: ss1Rev2,
  1256. existing: []struct {
  1257. parent metav1.Object
  1258. revision *apps.ControllerRevision
  1259. }{
  1260. {
  1261. parent: ss1,
  1262. revision: ss1Rev2,
  1263. },
  1264. },
  1265. err: false,
  1266. },
  1267. {
  1268. name: "releasing a revision owned by another controller succeeds",
  1269. parent: ss1,
  1270. revision: ss2Rev1,
  1271. existing: []struct {
  1272. parent metav1.Object
  1273. revision *apps.ControllerRevision
  1274. }{
  1275. {
  1276. parent: ss2,
  1277. revision: ss2Rev1,
  1278. },
  1279. },
  1280. err: false,
  1281. },
  1282. {
  1283. name: "releasing a non-existent revision succeeds",
  1284. parent: ss1,
  1285. revision: ss1Rev1,
  1286. existing: nil,
  1287. err: false,
  1288. },
  1289. }
  1290. for i := range tests {
  1291. testFn(&tests[i], t)
  1292. }
  1293. }
  1294. func TestFakeHistory_ReleaseControllerRevision(t *testing.T) {
  1295. type testcase struct {
  1296. name string
  1297. parent metav1.Object
  1298. revision *apps.ControllerRevision
  1299. existing []struct {
  1300. parent metav1.Object
  1301. revision *apps.ControllerRevision
  1302. }
  1303. err bool
  1304. }
  1305. testFn := func(test *testcase, t *testing.T) {
  1306. client := fake.NewSimpleClientset()
  1307. informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  1308. stop := make(chan struct{})
  1309. defer close(stop)
  1310. informerFactory.Start(stop)
  1311. informer := informerFactory.Apps().V1().ControllerRevisions()
  1312. informerFactory.WaitForCacheSync(stop)
  1313. history := NewFakeHistory(informer)
  1314. var collisionCount int32
  1315. for i := range test.existing {
  1316. _, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
  1317. if err != nil {
  1318. t.Fatal(err)
  1319. }
  1320. }
  1321. adopted, err := history.ReleaseControllerRevision(test.parent, test.revision)
  1322. if !test.err {
  1323. if err != nil {
  1324. t.Errorf("%s: %s", test.name, err)
  1325. }
  1326. if adopted == nil {
  1327. return
  1328. }
  1329. if metav1.IsControlledBy(adopted, test.parent) {
  1330. t.Errorf("%s: release failed", test.name)
  1331. }
  1332. }
  1333. if test.err && err == nil {
  1334. t.Errorf("%s: expected error", test.name)
  1335. }
  1336. }
  1337. ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  1338. ss1.Status.CollisionCount = new(int32)
  1339. ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  1340. ss2.Status.CollisionCount = new(int32)
  1341. ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  1342. if err != nil {
  1343. t.Fatal(err)
  1344. }
  1345. ss1Rev1.Namespace = ss1.Namespace
  1346. ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  1347. if err != nil {
  1348. t.Fatal(err)
  1349. }
  1350. ss1Rev2.Namespace = ss1.Namespace
  1351. ss1Rev2.OwnerReferences = []metav1.OwnerReference{}
  1352. ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
  1353. if err != nil {
  1354. t.Fatal(err)
  1355. }
  1356. ss2Rev1.Namespace = ss2.Namespace
  1357. tests := []testcase{
  1358. {
  1359. name: "releasing an owned revision succeeds",
  1360. parent: ss1,
  1361. revision: ss1Rev1,
  1362. existing: []struct {
  1363. parent metav1.Object
  1364. revision *apps.ControllerRevision
  1365. }{
  1366. {
  1367. parent: ss1,
  1368. revision: ss1Rev1,
  1369. },
  1370. },
  1371. err: false,
  1372. },
  1373. {
  1374. name: "releasing an orphan succeeds",
  1375. parent: ss1,
  1376. revision: ss1Rev2,
  1377. existing: []struct {
  1378. parent metav1.Object
  1379. revision *apps.ControllerRevision
  1380. }{
  1381. {
  1382. parent: ss1,
  1383. revision: ss1Rev2,
  1384. },
  1385. },
  1386. err: false,
  1387. },
  1388. {
  1389. name: "releasing a revision owned by another controller succeeds",
  1390. parent: ss1,
  1391. revision: ss2Rev1,
  1392. existing: []struct {
  1393. parent metav1.Object
  1394. revision *apps.ControllerRevision
  1395. }{
  1396. {
  1397. parent: ss2,
  1398. revision: ss2Rev1,
  1399. },
  1400. },
  1401. err: false,
  1402. },
  1403. {
  1404. name: "releasing a non-existent revision succeeds",
  1405. parent: ss1,
  1406. revision: ss1Rev1,
  1407. existing: nil,
  1408. err: false,
  1409. },
  1410. }
  1411. for i := range tests {
  1412. testFn(&tests[i], t)
  1413. }
  1414. }
  1415. func TestFindEqualRevisions(t *testing.T) {
  1416. type testcase struct {
  1417. name string
  1418. revision *apps.ControllerRevision
  1419. revisions []*apps.ControllerRevision
  1420. want map[string]bool
  1421. }
  1422. testFn := func(test *testcase, t *testing.T) {
  1423. found := FindEqualRevisions(test.revisions, test.revision)
  1424. if len(found) != len(test.want) {
  1425. t.Errorf("%s: want %d revisions found %d", test.name, len(test.want), len(found))
  1426. }
  1427. for i := range found {
  1428. if !test.want[found[i].Name] {
  1429. t.Errorf("%s: wanted %s not found", test.name, found[i].Name)
  1430. }
  1431. }
  1432. }
  1433. ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  1434. ss1.Status.CollisionCount = new(int32)
  1435. ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  1436. ss2.Status.CollisionCount = new(int32)
  1437. ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  1438. if err != nil {
  1439. t.Fatal(err)
  1440. }
  1441. ss1Rev1.Namespace = ss1.Namespace
  1442. ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  1443. if err != nil {
  1444. t.Fatal(err)
  1445. }
  1446. ss1Rev2.Namespace = ss1.Namespace
  1447. ss1Rev2.OwnerReferences = []metav1.OwnerReference{}
  1448. ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
  1449. if err != nil {
  1450. t.Fatal(err)
  1451. }
  1452. ss2Rev1.Namespace = ss2.Namespace
  1453. ss2Rev2, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 2, ss2.Status.CollisionCount)
  1454. if err != nil {
  1455. t.Fatal(err)
  1456. }
  1457. ss2Rev2.Namespace = ss2.Namespace
  1458. tests := []testcase{
  1459. {
  1460. name: "finds equivalent",
  1461. revision: ss1Rev1,
  1462. revisions: []*apps.ControllerRevision{ss1Rev1, ss2Rev1, ss2Rev2},
  1463. want: map[string]bool{ss1Rev1.Name: true},
  1464. },
  1465. {
  1466. name: "finds nothing when empty",
  1467. revision: ss1Rev1,
  1468. revisions: nil,
  1469. want: map[string]bool{},
  1470. },
  1471. {
  1472. name: "finds nothing with no matches",
  1473. revision: ss1Rev1,
  1474. revisions: []*apps.ControllerRevision{ss2Rev2, ss2Rev1},
  1475. want: map[string]bool{},
  1476. },
  1477. }
  1478. for i := range tests {
  1479. testFn(&tests[i], t)
  1480. }
  1481. }
  1482. func TestSortControllerRevisions(t *testing.T) {
  1483. type testcase struct {
  1484. name string
  1485. revisions []*apps.ControllerRevision
  1486. want []string
  1487. }
  1488. testFn := func(test *testcase, t *testing.T) {
  1489. t.Run(test.name, func(t *testing.T) {
  1490. SortControllerRevisions(test.revisions)
  1491. for i := range test.revisions {
  1492. if test.revisions[i].Name != test.want[i] {
  1493. t.Errorf("%s: want %s at %d got %s", test.name, test.want[i], i, test.revisions[i].Name)
  1494. }
  1495. }
  1496. })
  1497. }
  1498. ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  1499. ss1.Status.CollisionCount = new(int32)
  1500. ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  1501. if err != nil {
  1502. t.Fatal(err)
  1503. }
  1504. ss1Rev1.Namespace = ss1.Namespace
  1505. ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  1506. if err != nil {
  1507. t.Fatal(err)
  1508. }
  1509. ss1Rev2.Namespace = ss1.Namespace
  1510. ss1Rev3, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 3, ss1.Status.CollisionCount)
  1511. if err != nil {
  1512. t.Fatal(err)
  1513. }
  1514. ss1Rev3Time2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 3, ss1.Status.CollisionCount)
  1515. if err != nil {
  1516. t.Fatal(err)
  1517. }
  1518. ss1Rev3Time2.Namespace = ss1.Namespace
  1519. ss1Rev3Time2.CreationTimestamp = metav1.Time{Time: ss1Rev3.CreationTimestamp.Add(time.Second)}
  1520. ss1Rev3Time2Name2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 3, ss1.Status.CollisionCount)
  1521. if err != nil {
  1522. t.Fatal(err)
  1523. }
  1524. ss1Rev3Time2Name2.Namespace = ss1.Namespace
  1525. ss1Rev3Time2Name2.CreationTimestamp = metav1.Time{Time: ss1Rev3.CreationTimestamp.Add(time.Second)}
  1526. tests := []testcase{
  1527. {
  1528. name: "out of order",
  1529. revisions: []*apps.ControllerRevision{ss1Rev2, ss1Rev1, ss1Rev3},
  1530. want: []string{ss1Rev1.Name, ss1Rev2.Name, ss1Rev3.Name},
  1531. },
  1532. {
  1533. name: "sorted",
  1534. revisions: []*apps.ControllerRevision{ss1Rev1, ss1Rev2, ss1Rev3},
  1535. want: []string{ss1Rev1.Name, ss1Rev2.Name, ss1Rev3.Name},
  1536. },
  1537. {
  1538. name: "reversed",
  1539. revisions: []*apps.ControllerRevision{ss1Rev3, ss1Rev2, ss1Rev1},
  1540. want: []string{ss1Rev1.Name, ss1Rev2.Name, ss1Rev3.Name},
  1541. },
  1542. {
  1543. name: "with ties",
  1544. revisions: []*apps.ControllerRevision{ss1Rev3, ss1Rev3Time2, ss1Rev2, ss1Rev1},
  1545. want: []string{ss1Rev1.Name, ss1Rev2.Name, ss1Rev3.Name, ss1Rev3Time2.Name, ss1Rev3Time2Name2.Name},
  1546. },
  1547. {
  1548. name: "empty",
  1549. revisions: nil,
  1550. want: nil,
  1551. },
  1552. }
  1553. for i := range tests {
  1554. testFn(&tests[i], t)
  1555. }
  1556. }
  1557. func newStatefulSet(replicas int, name string, uid types.UID, labels map[string]string) *apps.StatefulSet {
  1558. // Converting all the map-only selectors to set-based selectors.
  1559. var testMatchExpressions []metav1.LabelSelectorRequirement
  1560. for key, value := range labels {
  1561. sel := metav1.LabelSelectorRequirement{
  1562. Key: key,
  1563. Operator: metav1.LabelSelectorOpIn,
  1564. Values: []string{value},
  1565. }
  1566. testMatchExpressions = append(testMatchExpressions, sel)
  1567. }
  1568. return &apps.StatefulSet{
  1569. TypeMeta: metav1.TypeMeta{
  1570. Kind: "StatefulSet",
  1571. APIVersion: "apps/v1",
  1572. },
  1573. ObjectMeta: metav1.ObjectMeta{
  1574. Name: name,
  1575. Namespace: v1.NamespaceDefault,
  1576. UID: uid,
  1577. },
  1578. Spec: apps.StatefulSetSpec{
  1579. Selector: &metav1.LabelSelector{
  1580. // Purposely leaving MatchLabels nil, so to ensure it will break if any link
  1581. // in the chain ignores the set-based MatchExpressions.
  1582. MatchLabels: nil,
  1583. MatchExpressions: testMatchExpressions,
  1584. },
  1585. Replicas: func() *int32 { i := int32(replicas); return &i }(),
  1586. Template: v1.PodTemplateSpec{
  1587. ObjectMeta: metav1.ObjectMeta{
  1588. Labels: labels,
  1589. },
  1590. Spec: v1.PodSpec{
  1591. Containers: []v1.Container{
  1592. {
  1593. Name: "nginx",
  1594. Image: "nginx",
  1595. VolumeMounts: []v1.VolumeMount{
  1596. {Name: "datadir", MountPath: "/tmp/"},
  1597. {Name: "home", MountPath: "/home"},
  1598. },
  1599. },
  1600. },
  1601. Volumes: []v1.Volume{{
  1602. Name: "home",
  1603. VolumeSource: v1.VolumeSource{
  1604. HostPath: &v1.HostPathVolumeSource{
  1605. Path: fmt.Sprintf("/tmp/%v", "home"),
  1606. },
  1607. }}},
  1608. },
  1609. },
  1610. VolumeClaimTemplates: []v1.PersistentVolumeClaim{
  1611. {
  1612. ObjectMeta: metav1.ObjectMeta{Name: "datadir"},
  1613. Spec: v1.PersistentVolumeClaimSpec{
  1614. Resources: v1.ResourceRequirements{
  1615. Requests: v1.ResourceList{
  1616. v1.ResourceStorage: *resource.NewQuantity(1, resource.BinarySI),
  1617. },
  1618. },
  1619. },
  1620. },
  1621. },
  1622. ServiceName: "governingsvc",
  1623. },
  1624. }
  1625. }
  1626. var parentKind = apps.SchemeGroupVersion.WithKind("StatefulSet")
  1627. func rawTemplate(template *v1.PodTemplateSpec) runtime.RawExtension {
  1628. buf := new(bytes.Buffer)
  1629. enc := json.NewEncoder(buf)
  1630. if err := enc.Encode(template); err != nil {
  1631. panic(err)
  1632. }
  1633. return runtime.RawExtension{Raw: buf.Bytes()}
  1634. }