@@ -34,6 +34,7 @@ import (
34
34
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
35
35
"k8s.io/apimachinery/pkg/runtime/schema"
36
36
apiTypes "k8s.io/apimachinery/pkg/types"
37
+ "k8s.io/apimachinery/pkg/watch"
37
38
"k8s.io/client-go/discovery"
38
39
"k8s.io/client-go/dynamic"
39
40
)
@@ -64,11 +65,12 @@ type ConditionFunc func(obj model.K8sMeta) bool
64
65
65
66
// SyncOptions provides the caller with options for the sync operation.
66
67
type SyncOptions struct {
67
- DryRun bool // do not actually create or update objects, return what would happen
68
- DisableCreate bool // only update objects if they exist, do not create new ones
69
- DisableUpdateFn ConditionFunc // do not update an existing object
70
- WaitOptions TypeWaitOptions // opts for waiting
71
- ShowSecrets bool // show secrets in patches and creations
68
+ DryRun bool // do not actually create or update objects, return what would happen
69
+ DisableCreate bool // only update objects if they exist, do not create new ones
70
+ DisableUpdateFn ConditionFunc // do not update an existing object
71
+ RecreateUpdateFn ConditionFunc // recreate existing object on update
72
+ WaitOptions TypeWaitOptions // opts for waiting
73
+ ShowSecrets bool // show secrets in patches and creations
72
74
}
73
75
74
76
// DeleteOptions provides the caller with options for the delete operation.
@@ -647,6 +649,37 @@ func (c *Client) maybeCreate(obj model.K8sLocalObject, opts SyncOptions) (*updat
647
649
return result , nil
648
650
}
649
651
652
+ func (c * Client ) doRecreate (obj model.K8sLocalObject , opts SyncOptions ) (* updateResult , error ) {
653
+ ri , err := c .resourceInterfaceWithDefaultNs (obj .GroupVersionKind (), obj .GetNamespace ())
654
+ if err != nil {
655
+ return nil , errors .Wrap (err , "get resource interface" )
656
+ }
657
+
658
+ sio .Debugln ("delete " + c .DisplayName (obj ))
659
+ pp := metav1 .DeletePropagationForeground
660
+ err = ri .Delete (obj .GetName (), & metav1.DeleteOptions {PropagationPolicy : & pp })
661
+ if err != nil && ! apiErrors .IsNotFound (err ) {
662
+ return nil , err
663
+ }
664
+
665
+ watcher , err := ri .Watch (metav1.ListOptions {
666
+ FieldSelector : "metadata.name=" + obj .GetName (),
667
+ })
668
+ if err != nil {
669
+ return nil , err
670
+ }
671
+
672
+ sio .Debugln ("wait " + c .DisplayName (obj ))
673
+ for {
674
+ ev := <- watcher .ResultChan ()
675
+ if ev .Type == watch .Deleted {
676
+ break
677
+ }
678
+ }
679
+ watcher .Stop ()
680
+ return c .maybeCreate (obj , opts )
681
+ }
682
+
650
683
func (c * Client ) maybeUpdate (obj model.K8sLocalObject , remObj * unstructured.Unstructured , opts SyncOptions ) (* updateResult , error ) {
651
684
if opts .DisableUpdateFn (model .NewK8sObject (remObj .Object )) {
652
685
return & updateResult {
@@ -686,10 +719,16 @@ func (c *Client) maybeUpdate(obj model.K8sLocalObject, remObj *unstructured.Unst
686
719
}
687
720
688
721
var result * updateResult
689
- if opts . DryRun {
690
- result , err = p .getPatchContents (remObj , obj )
691
- } else {
692
- result , err = p . patch ( remObj , obj )
722
+
723
+ patch , err : = p .getPatchContents (remObj , obj )
724
+ if err != nil || opts . DryRun {
725
+ return patch , err
693
726
}
727
+ if patch .SkipReason != identicalObjects && opts .RecreateUpdateFn (model .NewK8sObject (remObj .Object )) {
728
+ return c .doRecreate (obj , opts )
729
+ }
730
+
731
+ result , err = p .patch (remObj , obj )
732
+
694
733
return result , err
695
734
}
0 commit comments