vendor update for CSI 0.3.0

This commit is contained in:
gman
2018-07-18 16:47:22 +02:00
parent 6f484f92fc
commit 8ea659f0d5
6810 changed files with 438061 additions and 193861 deletions

View File

@ -18,20 +18,28 @@ package cmd
import (
"fmt"
"io"
"strings"
"time"
"github.com/golang/glog"
"github.com/spf13/cobra"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/kubernetes/pkg/kubectl"
"k8s.io/client-go/dynamic"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
kubectlwait "k8s.io/kubernetes/pkg/kubectl/cmd/wait"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
)
@ -90,7 +98,8 @@ var (
type DeleteOptions struct {
resource.FilenameOptions
Selector string
LabelSelector string
FieldSelector string
DeleteAll bool
IgnoreNotFound bool
Cascade bool
@ -101,20 +110,17 @@ type DeleteOptions struct {
GracePeriod int
Timeout time.Duration
Include3rdParty bool
Output string
Output string
Mapper meta.RESTMapper
Result *resource.Result
DynamicClient dynamic.Interface
Mapper meta.RESTMapper
Result *resource.Result
f cmdutil.Factory
Out io.Writer
ErrOut io.Writer
genericclioptions.IOStreams
}
func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
options := &DeleteOptions{Include3rdParty: true}
validArgs := cmdutil.ValidArgList(f)
func NewCmdDelete(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
deleteFlags := NewDeleteCommandFlags("containing the resource to delete.")
cmd := &cobra.Command{
Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])",
@ -123,50 +129,52 @@ func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
Long: delete_long,
Example: delete_example,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd))
if err := options.Complete(f, out, errOut, args, cmd); err != nil {
cmdutil.CheckErr(err)
}
if err := options.Validate(cmd); err != nil {
cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, err.Error()))
}
if err := options.RunDelete(); err != nil {
cmdutil.CheckErr(err)
}
o := deleteFlags.ToOptions(nil, streams)
cmdutil.CheckErr(o.Complete(f, args, cmd))
cmdutil.CheckErr(o.Validate(cmd))
cmdutil.CheckErr(o.RunDelete())
},
SuggestFor: []string{"rm"},
ValidArgs: validArgs,
ArgAliases: kubectl.ResourceAliases(validArgs),
}
usage := "containing the resource to delete."
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones.")
cmd.Flags().BoolVar(&options.DeleteAll, "all", options.DeleteAll, "Delete all resources, including uninitialized ones, in the namespace of the specified resource types.")
cmd.Flags().BoolVar(&options.IgnoreNotFound, "ignore-not-found", false, "Treat \"resource not found\" as a successful delete. Defaults to \"true\" when --all is specified.")
cmd.Flags().BoolVar(&options.Cascade, "cascade", true, "If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.")
cmd.Flags().IntVar(&options.GracePeriod, "grace-period", -1, "Period of time in seconds given to the resource to terminate gracefully. Ignored if negative.")
cmd.Flags().BoolVar(&options.DeleteNow, "now", false, "If true, resources are signaled for immediate shutdown (same as --grace-period=1).")
cmd.Flags().BoolVar(&options.ForceDeletion, "force", false, "Immediate deletion of some resources may result in inconsistency or data loss and requires confirmation.")
cmd.Flags().DurationVar(&options.Timeout, "timeout", 0, "The length of time to wait before giving up on a delete, zero means determine a timeout from the size of the object")
cmdutil.AddOutputVarFlagsForMutation(cmd, &options.Output)
cmdutil.AddInclude3rdPartyVarFlags(cmd, &options.Include3rdParty)
deleteFlags.AddFlags(cmd)
cmdutil.AddIncludeUninitializedFlag(cmd)
return cmd
}
func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []string, cmd *cobra.Command) error {
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
func (o *DeleteOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Command) error {
cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace()
if err != nil {
return err
}
if o.DeleteAll || len(o.LabelSelector) > 0 || len(o.FieldSelector) > 0 {
if f := cmd.Flags().Lookup("ignore-not-found"); f != nil && !f.Changed {
// If the user didn't explicitly set the option, default to ignoring NotFound errors when used with --all, -l, or --field-selector
o.IgnoreNotFound = true
}
}
if o.DeleteNow {
if o.GracePeriod != -1 {
return fmt.Errorf("--now and --grace-period cannot be specified together")
}
o.GracePeriod = 1
}
if o.GracePeriod == 0 && !o.ForceDeletion {
// To preserve backwards compatibility, but prevent accidental data loss, we convert --grace-period=0
// into --grace-period=1. Users may provide --force to bypass this conversion.
o.GracePeriod = 1
}
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
r := f.NewBuilder().
Unstructured().
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, &o.FilenameOptions).
LabelSelectorParam(o.Selector).
LabelSelectorParam(o.LabelSelector).
FieldSelectorParam(o.FieldSelector).
IncludeUninitialized(includeUninitialized).
SelectAllParam(o.DeleteAll).
ResourceTypeOrNameArgs(false, args...).RequireObject(false).
@ -177,151 +185,185 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args
return err
}
o.Result = r
o.Mapper = r.Mapper().RESTMapper
o.f = f
// Set up writer
o.Out = out
o.ErrOut = errOut
o.Mapper, err = f.ToRESTMapper()
if err != nil {
return err
}
o.DynamicClient, err = f.DynamicClient()
if err != nil {
return err
}
return nil
}
func (o *DeleteOptions) Validate(cmd *cobra.Command) error {
if o.DeleteAll && len(o.Selector) > 0 {
if o.Output != "" && o.Output != "name" {
return cmdutil.UsageErrorf(cmd, "Unexpected -o output mode: %v. We only support '-o name'.", o.Output)
}
if o.DeleteAll && len(o.LabelSelector) > 0 {
return fmt.Errorf("cannot set --all and --selector at the same time")
}
if o.DeleteAll {
f := cmd.Flags().Lookup("ignore-not-found")
// The flag should never be missing
if f == nil {
return fmt.Errorf("missing --ignore-not-found flag")
}
// If the user didn't explicitly set the option, default to ignoring NotFound errors when used with --all
if !f.Changed {
o.IgnoreNotFound = true
}
if o.DeleteAll && len(o.FieldSelector) > 0 {
return fmt.Errorf("cannot set --all and --field-selector at the same time")
}
if o.DeleteNow {
if o.GracePeriod != -1 {
return fmt.Errorf("--now and --grace-period cannot be specified together")
}
o.GracePeriod = 1
if o.GracePeriod == 0 && !o.ForceDeletion && !o.WaitForDeletion {
// With the explicit --wait flag we need extra validation for backward compatibility
return fmt.Errorf("--grace-period=0 must have either --force specified, or --wait to be set to true")
}
if o.GracePeriod == 0 {
if o.ForceDeletion {
fmt.Fprintf(o.ErrOut, "warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.\n")
} else {
// To preserve backwards compatibility, but prevent accidental data loss, we convert --grace-period=0
// into --grace-period=1 and wait until the object is successfully deleted. Users may provide --force
// to bypass this wait.
o.WaitForDeletion = true
o.GracePeriod = 1
}
switch {
case o.GracePeriod == 0 && o.ForceDeletion:
fmt.Fprintf(o.ErrOut, "warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.\n")
case o.ForceDeletion:
fmt.Fprintf(o.ErrOut, "warning: --force is ignored because --grace-period is not 0.\n")
}
return nil
}
func (o *DeleteOptions) RunDelete() error {
shortOutput := o.Output == "name"
// By default use a reaper to delete all related resources.
if o.Cascade {
return ReapResult(o.Result, o.f, o.Out, true, o.IgnoreNotFound, o.Timeout, o.GracePeriod, o.WaitForDeletion, shortOutput, false)
}
return DeleteResult(o.Result, o.Out, o.IgnoreNotFound, o.GracePeriod, shortOutput)
return o.DeleteResult(o.Result)
}
func ReapResult(r *resource.Result, f cmdutil.Factory, out io.Writer, isDefaultDelete, ignoreNotFound bool, timeout time.Duration, gracePeriod int, waitForDeletion, shortOutput bool, quiet bool) error {
func (o *DeleteOptions) DeleteResult(r *resource.Result) error {
found := 0
if ignoreNotFound {
r = r.IgnoreErrors(errors.IsNotFound)
}
err := r.Visit(func(info *resource.Info, err error) error {
if err != nil {
return err
}
found++
reaper, err := f.Reaper(info.Mapping)
if err != nil {
// If there is no reaper for this resources and the user didn't explicitly ask for stop.
if kubectl.IsNoSuchReaperError(err) && isDefaultDelete {
// No client side reaper found. Let the server do cascading deletion.
return cascadingDeleteResource(info, out, shortOutput)
}
return cmdutil.AddSourceToErr("reaping", info.Source, err)
}
var options *metav1.DeleteOptions
if gracePeriod >= 0 {
options = metav1.NewDeleteOptions(int64(gracePeriod))
}
if err := reaper.Stop(info.Namespace, info.Name, timeout, options); err != nil {
return cmdutil.AddSourceToErr("stopping", info.Source, err)
}
if waitForDeletion {
if err := waitForObjectDeletion(info, timeout); err != nil {
return cmdutil.AddSourceToErr("stopping", info.Source, err)
}
}
if !quiet {
printDeletion(info, out, shortOutput)
}
return nil
})
if err != nil {
return err
}
if found == 0 {
fmt.Fprintf(out, "No resources found\n")
}
return nil
}
func DeleteResult(r *resource.Result, out io.Writer, ignoreNotFound bool, gracePeriod int, shortOutput bool) error {
found := 0
if ignoreNotFound {
if o.IgnoreNotFound {
r = r.IgnoreErrors(errors.IsNotFound)
}
deletedInfos := []*resource.Info{}
err := r.Visit(func(info *resource.Info, err error) error {
if err != nil {
return err
}
deletedInfos = append(deletedInfos, info)
found++
// if we're here, it means that cascade=false (not the default), so we should orphan as requested
orphan := true
options := &metav1.DeleteOptions{}
if gracePeriod >= 0 {
options = metav1.NewDeleteOptions(int64(gracePeriod))
if o.GracePeriod >= 0 {
options = metav1.NewDeleteOptions(int64(o.GracePeriod))
}
options.OrphanDependents = &orphan
return deleteResource(info, out, shortOutput, options)
policy := metav1.DeletePropagationBackground
if !o.Cascade {
policy = metav1.DeletePropagationOrphan
}
options.PropagationPolicy = &policy
return o.deleteResource(info, options)
})
if err != nil {
return err
}
if found == 0 {
fmt.Fprintf(out, "No resources found\n")
fmt.Fprintf(o.Out, "No resources found\n")
return nil
}
return nil
if !o.WaitForDeletion {
return nil
}
// if we don't have a dynamic client, we don't want to wait. Eventually when delete is cleaned up, this will likely
// drop out.
if o.DynamicClient == nil {
return nil
}
effectiveTimeout := o.Timeout
if effectiveTimeout == 0 {
// if we requested to wait forever, set it to a week.
effectiveTimeout = 168 * time.Hour
}
waitOptions := kubectlwait.WaitOptions{
ResourceFinder: genericclioptions.ResourceFinderForResult(resource.InfoListVisitor(deletedInfos)),
DynamicClient: o.DynamicClient,
Timeout: effectiveTimeout,
Printer: printers.NewDiscardingPrinter(),
ConditionFn: kubectlwait.IsDeleted,
IOStreams: o.IOStreams,
}
err = waitOptions.RunWait()
if errors.IsForbidden(err) {
// if we're forbidden from waiting, we shouldn't fail.
glog.V(1).Info(err)
return nil
}
return err
}
func cascadingDeleteResource(info *resource.Info, out io.Writer, shortOutput bool) error {
falseVar := false
deleteOptions := &metav1.DeleteOptions{OrphanDependents: &falseVar}
return deleteResource(info, out, shortOutput, deleteOptions)
}
func (o *DeleteOptions) deleteResource(info *resource.Info, deleteOptions *metav1.DeleteOptions) error {
// TODO: Remove this in or after 1.12 release.
// Server version >= 1.11 no longer needs this hack.
mapping := info.ResourceMapping()
if mapping.Resource.GroupResource() == (schema.GroupResource{Group: "extensions", Resource: "daemonsets"}) ||
mapping.Resource.GroupResource() == (schema.GroupResource{Group: "apps", Resource: "daemonsets"}) {
if err := updateDaemonSet(info.Namespace, info.Name, o.DynamicClient); err != nil {
return err
}
}
func deleteResource(info *resource.Info, out io.Writer, shortOutput bool, deleteOptions *metav1.DeleteOptions) error {
if err := resource.NewHelper(info.Client, info.Mapping).DeleteWithOptions(info.Namespace, info.Name, deleteOptions); err != nil {
return cmdutil.AddSourceToErr("deleting", info.Source, err)
}
printDeletion(info, out, shortOutput)
o.PrintObj(info)
return nil
}
// deletion printing is special because they don't have an object to print. This logic mirrors PrintSuccess
func printDeletion(info *resource.Info, out io.Writer, shortOutput bool) {
// TODO: Remove this in or after 1.12 release.
// Server version >= 1.11 no longer needs this hack.
func updateDaemonSet(namespace, name string, dynamicClient dynamic.Interface) error {
dsClient := dynamicClient.Resource(schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "daemonsets"}).Namespace(namespace)
obj, err := dsClient.Get(name, metav1.GetOptions{})
if err != nil {
return err
}
ds := &appsv1.DaemonSet{}
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, ds); err != nil {
return err
}
// We set the nodeSelector to a random label. This label is nearly guaranteed
// to not be set on any node so the DameonSetController will start deleting
// daemon pods. Once it's done deleting the daemon pods, it's safe to delete
// the DaemonSet.
ds.Spec.Template.Spec.NodeSelector = map[string]string{
string(uuid.NewUUID()): string(uuid.NewUUID()),
}
// force update to avoid version conflict
ds.ResourceVersion = ""
out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(ds)
if err != nil {
return err
}
if _, err = dsClient.Update(&unstructured.Unstructured{Object: out}); err != nil {
return err
}
// Wait for the daemon set controller to kill all the daemon pods.
if err := wait.Poll(1*time.Second, 5*time.Minute, func() (bool, error) {
updatedObj, err := dsClient.Get(name, metav1.GetOptions{})
if err != nil {
return false, nil
}
updatedDS := &appsv1.DaemonSet{}
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(updatedObj.Object, ds); err != nil {
return false, nil
}
return updatedDS.Status.CurrentNumberScheduled+updatedDS.Status.NumberMisscheduled == 0, nil
}); err != nil {
return err
}
return nil
}
// deletion printing is special because we do not have an object to print.
// This mirrors name printer behavior
func (o *DeleteOptions) PrintObj(info *resource.Info) {
operation := "deleted"
groupKind := info.Mapping.GroupVersionKind
kindString := fmt.Sprintf("%s.%s", strings.ToLower(groupKind.Kind), groupKind.Group)
@ -329,33 +371,16 @@ func printDeletion(info *resource.Info, out io.Writer, shortOutput bool) {
kindString = strings.ToLower(groupKind.Kind)
}
if shortOutput {
if o.GracePeriod == 0 {
operation = "force deleted"
}
if o.Output == "name" {
// -o name: prints resource/name
fmt.Fprintf(out, "%s/%s\n", kindString, info.Name)
fmt.Fprintf(o.Out, "%s/%s\n", kindString, info.Name)
return
}
// understandable output by default
fmt.Fprintf(out, "%s \"%s\" %s\n", kindString, info.Name, operation)
}
// objectDeletionWaitInterval is the interval to wait between checks for deletion.
var objectDeletionWaitInterval = time.Second
// waitForObjectDeletion refreshes the object, waiting until it is deleted, a timeout is reached, or
// an error is encountered. It checks once a second.
func waitForObjectDeletion(info *resource.Info, timeout time.Duration) error {
copied := *info
info = &copied
// TODO: refactor Reaper so that we can pass the "wait" option into it, and then check for UID change.
return wait.PollImmediate(objectDeletionWaitInterval, timeout, func() (bool, error) {
switch err := info.Get(); {
case err == nil:
return false, nil
case errors.IsNotFound(err):
return true, nil
default:
return false, err
}
})
fmt.Fprintf(o.Out, "%s \"%s\" %s\n", kindString, info.Name, operation)
}