@@ -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,37 @@ 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+ 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+
650683func (c * Client ) maybeUpdate (obj model.K8sLocalObject , remObj * unstructured.Unstructured , opts SyncOptions ) (* updateResult , error ) {
651684 if opts .DisableUpdateFn (model .NewK8sObject (remObj .Object )) {
652685 return & updateResult {
@@ -686,10 +719,16 @@ func (c *Client) maybeUpdate(obj model.K8sLocalObject, remObj *unstructured.Unst
686719 }
687720
688721 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
693726 }
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+
694733 return result , err
695734}
0 commit comments