@@ -34,6 +34,7 @@ import (
3434 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3535 "k8s.io/apimachinery/pkg/runtime/schema"
3636 apiTypes "k8s.io/apimachinery/pkg/types"
37+ "k8s.io/apimachinery/pkg/watch"
3738 "k8s.io/client-go/discovery"
3839 "k8s.io/client-go/dynamic"
3940)
@@ -64,11 +65,12 @@ type ConditionFunc func(obj model.K8sMeta) bool
6465
6566// SyncOptions provides the caller with options for the sync operation.
6667type 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
7274}
7375
7476// DeleteOptions provides the caller with options for the delete operation.
@@ -647,6 +649,35 @@ func (c *Client) maybeCreate(obj model.K8sLocalObject, opts SyncOptions) (*updat
647649 return result , nil
648650}
649651
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+ if err != nil {
667+ return nil , err
668+ }
669+
670+ sio .Debugln ("wait " + c .DisplayName (obj ))
671+ for {
672+ ev := <- watcher .ResultChan ()
673+ if ev .Type == watch .Deleted {
674+ break
675+ }
676+ }
677+ watcher .Stop ()
678+ return c .maybeCreate (obj , opts )
679+ }
680+
650681func (c * Client ) maybeUpdate (obj model.K8sLocalObject , remObj * unstructured.Unstructured , opts SyncOptions ) (* updateResult , error ) {
651682 if opts .DisableUpdateFn (model .NewK8sObject (remObj .Object )) {
652683 return & updateResult {
@@ -686,10 +717,16 @@ func (c *Client) maybeUpdate(obj model.K8sLocalObject, remObj *unstructured.Unst
686717 }
687718
688719 var result * updateResult
689- if opts . DryRun {
690- result , err = p .getPatchContents (remObj , obj )
691- } else {
692- result , err = p . patch ( remObj , obj )
720+
721+ patch , err : = p .getPatchContents (remObj , obj )
722+ if err != nil || opts . DryRun {
723+ return patch , err
693724 }
725+ if patch .SkipReason != identicalObjects && opts .RecreateUpdateFn (model .NewK8sObject (remObj .Object )) {
726+ return c .doRecreate (obj , opts )
727+ }
728+
729+ result , err = p .patch (remObj , obj )
730+
694731 return result , err
695732}
0 commit comments