...

Source file src/k8s.io/kubectl/pkg/cmd/rollout/rollout_pause.go

Documentation: k8s.io/kubectl/pkg/cmd/rollout

     1  /*
     2  Copyright 2016 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package rollout
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/spf13/cobra"
    23  
    24  	"k8s.io/apimachinery/pkg/types"
    25  	utilerrors "k8s.io/apimachinery/pkg/util/errors"
    26  	"k8s.io/cli-runtime/pkg/genericclioptions"
    27  	"k8s.io/cli-runtime/pkg/genericiooptions"
    28  	"k8s.io/cli-runtime/pkg/printers"
    29  	"k8s.io/cli-runtime/pkg/resource"
    30  	"k8s.io/kubectl/pkg/cmd/set"
    31  	cmdutil "k8s.io/kubectl/pkg/cmd/util"
    32  	"k8s.io/kubectl/pkg/polymorphichelpers"
    33  	"k8s.io/kubectl/pkg/scheme"
    34  	"k8s.io/kubectl/pkg/util/completion"
    35  	"k8s.io/kubectl/pkg/util/i18n"
    36  	"k8s.io/kubectl/pkg/util/templates"
    37  )
    38  
    39  // PauseOptions is the start of the data required to perform the operation.  As new fields are added, add them here instead of
    40  // referencing the cmd.Flags()
    41  type PauseOptions struct {
    42  	PrintFlags *genericclioptions.PrintFlags
    43  	ToPrinter  func(string) (printers.ResourcePrinter, error)
    44  
    45  	Pauser           polymorphichelpers.ObjectPauserFunc
    46  	Builder          func() *resource.Builder
    47  	Namespace        string
    48  	EnforceNamespace bool
    49  	Resources        []string
    50  	LabelSelector    string
    51  
    52  	resource.FilenameOptions
    53  	genericiooptions.IOStreams
    54  
    55  	fieldManager string
    56  }
    57  
    58  var (
    59  	pauseLong = templates.LongDesc(i18n.T(`
    60  		Mark the provided resource as paused.
    61  
    62  		Paused resources will not be reconciled by a controller.
    63  		Use "kubectl rollout resume" to resume a paused resource.
    64  		Currently only deployments support being paused.`))
    65  
    66  	pauseExample = templates.Examples(`
    67  		# Mark the nginx deployment as paused
    68  		# Any current state of the deployment will continue its function; new updates
    69  		# to the deployment will not have an effect as long as the deployment is paused
    70  		kubectl rollout pause deployment/nginx`)
    71  )
    72  
    73  // NewCmdRolloutPause returns a Command instance for 'rollout pause' sub command
    74  func NewCmdRolloutPause(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command {
    75  	o := &PauseOptions{
    76  		PrintFlags: genericclioptions.NewPrintFlags("paused").WithTypeSetter(scheme.Scheme),
    77  		IOStreams:  streams,
    78  	}
    79  
    80  	validArgs := []string{"deployment"}
    81  
    82  	cmd := &cobra.Command{
    83  		Use:                   "pause RESOURCE",
    84  		DisableFlagsInUseLine: true,
    85  		Short:                 i18n.T("Mark the provided resource as paused"),
    86  		Long:                  pauseLong,
    87  		Example:               pauseExample,
    88  		ValidArgsFunction:     completion.SpecifiedResourceTypeAndNameCompletionFunc(f, validArgs),
    89  		Run: func(cmd *cobra.Command, args []string) {
    90  			cmdutil.CheckErr(o.Complete(f, cmd, args))
    91  			cmdutil.CheckErr(o.Validate())
    92  			cmdutil.CheckErr(o.RunPause())
    93  		},
    94  	}
    95  
    96  	o.PrintFlags.AddFlags(cmd)
    97  
    98  	usage := "identifying the resource to get from a server."
    99  	cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
   100  	cmdutil.AddFieldManagerFlagVar(cmd, &o.fieldManager, "kubectl-rollout")
   101  	cmdutil.AddLabelSelectorFlagVar(cmd, &o.LabelSelector)
   102  	return cmd
   103  }
   104  
   105  // Complete completes all the required options
   106  func (o *PauseOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
   107  	o.Pauser = polymorphichelpers.ObjectPauserFn
   108  
   109  	var err error
   110  	o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
   111  	if err != nil {
   112  		return err
   113  	}
   114  
   115  	o.Resources = args
   116  	o.Builder = f.NewBuilder
   117  
   118  	o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) {
   119  		o.PrintFlags.NamePrintFlags.Operation = operation
   120  		return o.PrintFlags.ToPrinter()
   121  	}
   122  
   123  	return nil
   124  }
   125  
   126  func (o *PauseOptions) Validate() error {
   127  	if len(o.Resources) == 0 && cmdutil.IsFilenameSliceEmpty(o.Filenames, o.Kustomize) {
   128  		return fmt.Errorf("required resource not specified")
   129  	}
   130  	return nil
   131  }
   132  
   133  // RunPause performs the execution of 'rollout pause' sub command
   134  func (o *PauseOptions) RunPause() error {
   135  	r := o.Builder().
   136  		WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
   137  		NamespaceParam(o.Namespace).DefaultNamespace().
   138  		LabelSelectorParam(o.LabelSelector).
   139  		FilenameParam(o.EnforceNamespace, &o.FilenameOptions).
   140  		ResourceTypeOrNameArgs(true, o.Resources...).
   141  		ContinueOnError().
   142  		Latest().
   143  		Flatten().
   144  		Do()
   145  	if err := r.Err(); err != nil {
   146  		return err
   147  	}
   148  
   149  	allErrs := []error{}
   150  	infos, err := r.Infos()
   151  	if err != nil {
   152  		// restore previous command behavior where
   153  		// an error caused by retrieving infos due to
   154  		// at least a single broken object did not result
   155  		// in an immediate return, but rather an overall
   156  		// aggregation of errors.
   157  		allErrs = append(allErrs, err)
   158  	}
   159  
   160  	patches := set.CalculatePatches(infos, scheme.DefaultJSONEncoder(), set.PatchFn(o.Pauser))
   161  
   162  	if len(patches) == 0 && len(allErrs) == 0 {
   163  		fmt.Fprintf(o.ErrOut, "No resources found in %s namespace.\n", o.Namespace)
   164  		return nil
   165  	}
   166  
   167  	for _, patch := range patches {
   168  		info := patch.Info
   169  
   170  		if patch.Err != nil {
   171  			resourceString := info.Mapping.Resource.Resource
   172  			if len(info.Mapping.Resource.Group) > 0 {
   173  				resourceString = resourceString + "." + info.Mapping.Resource.Group
   174  			}
   175  			allErrs = append(allErrs, fmt.Errorf("error: %s %q %v", resourceString, info.Name, patch.Err))
   176  			continue
   177  		}
   178  
   179  		if string(patch.Patch) == "{}" || len(patch.Patch) == 0 {
   180  			printer, err := o.ToPrinter("already paused")
   181  			if err != nil {
   182  				allErrs = append(allErrs, err)
   183  				continue
   184  			}
   185  			if err = printer.PrintObj(info.Object, o.Out); err != nil {
   186  				allErrs = append(allErrs, err)
   187  			}
   188  			continue
   189  		}
   190  
   191  		obj, err := resource.NewHelper(info.Client, info.Mapping).
   192  			WithFieldManager(o.fieldManager).
   193  			Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch, nil)
   194  		if err != nil {
   195  			allErrs = append(allErrs, fmt.Errorf("failed to patch: %v", err))
   196  			continue
   197  		}
   198  
   199  		info.Refresh(obj, true)
   200  		printer, err := o.ToPrinter("paused")
   201  		if err != nil {
   202  			allErrs = append(allErrs, err)
   203  			continue
   204  		}
   205  		if err = printer.PrintObj(info.Object, o.Out); err != nil {
   206  			allErrs = append(allErrs, err)
   207  		}
   208  	}
   209  
   210  	return utilerrors.NewAggregate(allErrs)
   211  }
   212  

View as plain text