@@ -406,6 +406,195 @@ var _ = Describe("Controllerutil", func() {
406
406
})
407
407
})
408
408
409
+ Describe ("CreateOrPatch" , func () {
410
+ var deploy * appsv1.Deployment
411
+ var deplSpec appsv1.DeploymentSpec
412
+ var deplKey types.NamespacedName
413
+ var specr controllerutil.MutateFn
414
+
415
+ BeforeEach (func () {
416
+ deploy = & appsv1.Deployment {
417
+ ObjectMeta : metav1.ObjectMeta {
418
+ Name : fmt .Sprintf ("deploy-%d" , rand .Int31 ()),
419
+ Namespace : "default" ,
420
+ },
421
+ }
422
+
423
+ deplSpec = appsv1.DeploymentSpec {
424
+ Selector : & metav1.LabelSelector {
425
+ MatchLabels : map [string ]string {"foo" : "bar" },
426
+ },
427
+ Template : corev1.PodTemplateSpec {
428
+ ObjectMeta : metav1.ObjectMeta {
429
+ Labels : map [string ]string {
430
+ "foo" : "bar" ,
431
+ },
432
+ },
433
+ Spec : corev1.PodSpec {
434
+ Containers : []corev1.Container {
435
+ {
436
+ Name : "busybox" ,
437
+ Image : "busybox" ,
438
+ },
439
+ },
440
+ },
441
+ },
442
+ }
443
+
444
+ deplKey = types.NamespacedName {
445
+ Name : deploy .Name ,
446
+ Namespace : deploy .Namespace ,
447
+ }
448
+
449
+ specr = deploymentSpecr (deploy , deplSpec )
450
+ })
451
+
452
+ It ("creates a new object if one doesn't exists" , func () {
453
+ op , err := controllerutil .CreateOrPatch (context .TODO (), c , deploy , specr )
454
+
455
+ By ("returning no error" )
456
+ Expect (err ).NotTo (HaveOccurred ())
457
+
458
+ By ("returning OperationResultCreated" )
459
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultCreated ))
460
+
461
+ By ("actually having the deployment created" )
462
+ fetched := & appsv1.Deployment {}
463
+ Expect (c .Get (context .TODO (), deplKey , fetched )).To (Succeed ())
464
+
465
+ By ("being mutated by MutateFn" )
466
+ Expect (fetched .Spec .Template .Spec .Containers ).To (HaveLen (1 ))
467
+ Expect (fetched .Spec .Template .Spec .Containers [0 ].Name ).To (Equal (deplSpec .Template .Spec .Containers [0 ].Name ))
468
+ Expect (fetched .Spec .Template .Spec .Containers [0 ].Image ).To (Equal (deplSpec .Template .Spec .Containers [0 ].Image ))
469
+ })
470
+
471
+ It ("patches existing object" , func () {
472
+ var scale int32 = 2
473
+ op , err := controllerutil .CreateOrPatch (context .TODO (), c , deploy , specr )
474
+ Expect (err ).NotTo (HaveOccurred ())
475
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultCreated ))
476
+
477
+ op , err = controllerutil .CreateOrPatch (context .TODO (), c , deploy , deploymentScaler (deploy , scale ))
478
+ By ("returning no error" )
479
+ Expect (err ).NotTo (HaveOccurred ())
480
+
481
+ By ("returning OperationResultUpdated" )
482
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultUpdated ))
483
+
484
+ By ("actually having the deployment scaled" )
485
+ fetched := & appsv1.Deployment {}
486
+ Expect (c .Get (context .TODO (), deplKey , fetched )).To (Succeed ())
487
+ Expect (* fetched .Spec .Replicas ).To (Equal (scale ))
488
+ })
489
+
490
+ It ("patches only changed objects" , func () {
491
+ op , err := controllerutil .CreateOrPatch (context .TODO (), c , deploy , specr )
492
+
493
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultCreated ))
494
+ Expect (err ).NotTo (HaveOccurred ())
495
+
496
+ op , err = controllerutil .CreateOrPatch (context .TODO (), c , deploy , deploymentIdentity )
497
+ By ("returning no error" )
498
+ Expect (err ).NotTo (HaveOccurred ())
499
+
500
+ By ("returning OperationResultNone" )
501
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultNone ))
502
+ })
503
+
504
+ It ("patches only changed status" , func () {
505
+ op , err := controllerutil .CreateOrPatch (context .TODO (), c , deploy , specr )
506
+
507
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultCreated ))
508
+ Expect (err ).NotTo (HaveOccurred ())
509
+
510
+ deployStatus := appsv1.DeploymentStatus {
511
+ ReadyReplicas : 1 ,
512
+ Replicas : 3 ,
513
+ }
514
+ op , err = controllerutil .CreateOrPatch (context .TODO (), c , deploy , deploymentStatusr (deploy , deployStatus ))
515
+ By ("returning no error" )
516
+ Expect (err ).NotTo (HaveOccurred ())
517
+
518
+ By ("returning OperationResultUpdatedStatusOnly" )
519
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultUpdatedStatusOnly ))
520
+ })
521
+
522
+ It ("patches resource and status" , func () {
523
+ op , err := controllerutil .CreateOrPatch (context .TODO (), c , deploy , specr )
524
+
525
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultCreated ))
526
+ Expect (err ).NotTo (HaveOccurred ())
527
+
528
+ replicas := int32 (3 )
529
+ deployStatus := appsv1.DeploymentStatus {
530
+ ReadyReplicas : 1 ,
531
+ Replicas : replicas ,
532
+ }
533
+ op , err = controllerutil .CreateOrPatch (context .TODO (), c , deploy , func () error {
534
+ Expect (deploymentScaler (deploy , replicas )()).To (Succeed ())
535
+ return deploymentStatusr (deploy , deployStatus )()
536
+ })
537
+ By ("returning no error" )
538
+ Expect (err ).NotTo (HaveOccurred ())
539
+
540
+ By ("returning OperationResultUpdatedStatus" )
541
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultUpdatedStatus ))
542
+ })
543
+
544
+ It ("errors when MutateFn changes object name on creation" , func () {
545
+ op , err := controllerutil .CreateOrPatch (context .TODO (), c , deploy , func () error {
546
+ Expect (specr ()).To (Succeed ())
547
+ return deploymentRenamer (deploy )()
548
+ })
549
+
550
+ By ("returning error" )
551
+ Expect (err ).To (HaveOccurred ())
552
+
553
+ By ("returning OperationResultNone" )
554
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultNone ))
555
+ })
556
+
557
+ It ("errors when MutateFn renames an object" , func () {
558
+ op , err := controllerutil .CreateOrPatch (context .TODO (), c , deploy , specr )
559
+
560
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultCreated ))
561
+ Expect (err ).NotTo (HaveOccurred ())
562
+
563
+ op , err = controllerutil .CreateOrPatch (context .TODO (), c , deploy , deploymentRenamer (deploy ))
564
+
565
+ By ("returning error" )
566
+ Expect (err ).To (HaveOccurred ())
567
+
568
+ By ("returning OperationResultNone" )
569
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultNone ))
570
+ })
571
+
572
+ It ("errors when object namespace changes" , func () {
573
+ op , err := controllerutil .CreateOrPatch (context .TODO (), c , deploy , specr )
574
+
575
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultCreated ))
576
+ Expect (err ).NotTo (HaveOccurred ())
577
+
578
+ op , err = controllerutil .CreateOrPatch (context .TODO (), c , deploy , deploymentNamespaceChanger (deploy ))
579
+
580
+ By ("returning error" )
581
+ Expect (err ).To (HaveOccurred ())
582
+
583
+ By ("returning OperationResultNone" )
584
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultNone ))
585
+ })
586
+
587
+ It ("aborts immediately if there was an error initially retrieving the object" , func () {
588
+ op , err := controllerutil .CreateOrPatch (context .TODO (), errorReader {c }, deploy , func () error {
589
+ Fail ("Mutation method should not run" )
590
+ return nil
591
+ })
592
+
593
+ Expect (op ).To (BeEquivalentTo (controllerutil .OperationResultNone ))
594
+ Expect (err ).To (HaveOccurred ())
595
+ })
596
+ })
597
+
409
598
Describe ("Finalizers" , func () {
410
599
var obj runtime.Object = & errRuntimeObj {}
411
600
var deploy * appsv1.Deployment
@@ -473,6 +662,13 @@ func deploymentSpecr(deploy *appsv1.Deployment, spec appsv1.DeploymentSpec) cont
473
662
}
474
663
}
475
664
665
+ func deploymentStatusr (deploy * appsv1.Deployment , status appsv1.DeploymentStatus ) controllerutil.MutateFn {
666
+ return func () error {
667
+ deploy .Status = status
668
+ return nil
669
+ }
670
+ }
671
+
476
672
var deploymentIdentity controllerutil.MutateFn = func () error {
477
673
return nil
478
674
}
0 commit comments