mirror of https://github.com/k3s-io/k3s
support force apply
parent
fbe29f43ea
commit
750449ba3c
|
@ -40,15 +40,18 @@ import (
|
|||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
"k8s.io/kubernetes/pkg/util/strategicpatch"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
)
|
||||
|
||||
type ApplyOptions struct {
|
||||
FilenameOptions resource.FilenameOptions
|
||||
Selector string
|
||||
Force bool
|
||||
Prune bool
|
||||
Cascade bool
|
||||
GracePeriod int
|
||||
PruneResources []pruneResource
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -101,6 +104,8 @@ func NewCmdApply(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
|||
cmd.Flags().BoolVar(&options.Prune, "prune", false, "Automatically delete resource objects that do not appear in the configs")
|
||||
cmd.Flags().BoolVar(&options.Cascade, "cascade", true, "Only relevant during a prune. If true, cascade the deletion of the resources managed by pruned resources (e.g. Pods created by a ReplicationController).")
|
||||
cmd.Flags().IntVar(&options.GracePeriod, "grace-period", -1, "Period of time in seconds given to pruned resources to terminate gracefully. Ignored if negative.")
|
||||
cmd.Flags().BoolVar(&options.Force, "force", false, "Delete and re-create the specified resource")
|
||||
cmd.Flags().DurationVar(&options.Timeout, "timeout", 0, "Only relevant during a force apply. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object. Any other values should contain a corresponding time unit (e.g. 1s, 2m, 3h).")
|
||||
cmdutil.AddValidateFlags(cmd)
|
||||
cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on")
|
||||
cmd.Flags().Bool("all", false, "[-all] to select all the specified resources.")
|
||||
|
@ -246,7 +251,19 @@ func RunApply(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *App
|
|||
if !dryRun {
|
||||
overwrite := cmdutil.GetFlagBool(cmd, "overwrite")
|
||||
helper := resource.NewHelper(info.Client, info.Mapping)
|
||||
patcher := NewPatcher(encoder, decoder, info.Mapping, helper, overwrite)
|
||||
patcher := &patcher{
|
||||
encoder: encoder,
|
||||
decoder: decoder,
|
||||
mapping: info.Mapping,
|
||||
helper: helper,
|
||||
clientsetFunc: f.ClientSet,
|
||||
overwrite: overwrite,
|
||||
backOff: clockwork.NewRealClock(),
|
||||
force: options.Force,
|
||||
cascade: options.Cascade,
|
||||
timeout: options.Timeout,
|
||||
gracePeriod: options.GracePeriod,
|
||||
}
|
||||
|
||||
patchBytes, err := patcher.patch(info.Object, modified, info.Source, info.Namespace, info.Name)
|
||||
if err != nil {
|
||||
|
@ -438,10 +455,17 @@ func (p *pruner) prune(namespace string, mapping *meta.RESTMapping, shortOutput
|
|||
}
|
||||
|
||||
func (p *pruner) delete(namespace, name string, mapping *meta.RESTMapping, c resource.RESTClient) error {
|
||||
if !p.cascade {
|
||||
return resource.NewHelper(c, mapping).Delete(namespace, name)
|
||||
return runDelete(namespace, name, mapping, c, nil, p.cascade, p.gracePeriod, p.clientsetFunc)
|
||||
}
|
||||
|
||||
func runDelete(namespace, name string, mapping *meta.RESTMapping, c resource.RESTClient, helper *resource.Helper, cascade bool, gracePeriod int, clientsetFunc func() (*internalclientset.Clientset, error)) error {
|
||||
if !cascade {
|
||||
if helper == nil {
|
||||
helper = resource.NewHelper(c, mapping)
|
||||
}
|
||||
return helper.Delete(namespace, name)
|
||||
}
|
||||
cs, err := p.clientsetFunc()
|
||||
cs, err := clientsetFunc()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -452,32 +476,35 @@ func (p *pruner) delete(namespace, name string, mapping *meta.RESTMapping, c res
|
|||
}
|
||||
return resource.NewHelper(c, mapping).Delete(namespace, name)
|
||||
}
|
||||
if err := r.Stop(namespace, name, 2*time.Minute, api.NewDeleteOptions(int64(p.gracePeriod))); err != nil {
|
||||
var options *api.DeleteOptions
|
||||
if gracePeriod >= 0 {
|
||||
options = api.NewDeleteOptions(int64(gracePeriod))
|
||||
}
|
||||
if err := r.Stop(namespace, name, 2*time.Minute, options); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *patcher) delete(namespace, name string) error {
|
||||
return runDelete(namespace, name, p.mapping, nil, p.helper, p.cascade, p.gracePeriod, p.clientsetFunc)
|
||||
}
|
||||
|
||||
type patcher struct {
|
||||
encoder runtime.Encoder
|
||||
decoder runtime.Decoder
|
||||
|
||||
mapping *meta.RESTMapping
|
||||
helper *resource.Helper
|
||||
mapping *meta.RESTMapping
|
||||
helper *resource.Helper
|
||||
clientsetFunc func() (*internalclientset.Clientset, error)
|
||||
|
||||
overwrite bool
|
||||
backOff clockwork.Clock
|
||||
}
|
||||
|
||||
func NewPatcher(encoder runtime.Encoder, decoder runtime.Decoder, mapping *meta.RESTMapping, helper *resource.Helper, overwrite bool) *patcher {
|
||||
return &patcher{
|
||||
encoder: encoder,
|
||||
decoder: decoder,
|
||||
mapping: mapping,
|
||||
helper: helper,
|
||||
overwrite: overwrite,
|
||||
backOff: clockwork.NewRealClock(),
|
||||
}
|
||||
force bool
|
||||
cascade bool
|
||||
timeout time.Duration
|
||||
gracePeriod int
|
||||
}
|
||||
|
||||
func (p *patcher) patchSimple(obj runtime.Object, modified []byte, source, namespace, name string) ([]byte, error) {
|
||||
|
@ -527,6 +554,30 @@ func (p *patcher) patch(current runtime.Object, modified []byte, source, namespa
|
|||
}
|
||||
patchBytes, err = p.patchSimple(current, modified, source, namespace, name)
|
||||
}
|
||||
|
||||
if err != nil && p.force {
|
||||
patchBytes, err = p.deleteAndCreate(modified, namespace, name)
|
||||
}
|
||||
return patchBytes, err
|
||||
}
|
||||
|
||||
func (p *patcher) deleteAndCreate(modified []byte, namespace, name string) ([]byte, error) {
|
||||
err := p.delete(namespace, name)
|
||||
if err != nil {
|
||||
return modified, err
|
||||
}
|
||||
err = wait.PollImmediate(kubectl.Interval, p.timeout, func() (bool, error) {
|
||||
if _, err := p.helper.Get(namespace, name, false); !errors.IsNotFound(err) {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
if err != nil {
|
||||
return modified, err
|
||||
}
|
||||
versionedObject, _, err := p.decoder.Decode(modified, nil, nil)
|
||||
if err != nil {
|
||||
return modified, err
|
||||
}
|
||||
_, err = p.helper.Create(namespace, true, versionedObject)
|
||||
return modified, err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue