...

Source file src/k8s.io/kubectl/pkg/cmd/rollout/rollout_resume.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  // ResumeOptions 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 ResumeOptions struct {
    42  	PrintFlags *genericclioptions.PrintFlags
    43  	ToPrinter  func(string) (printers.ResourcePrinter, error)
    44  
    45  	Resources []string
    46  
    47  	Builder          func() *resource.Builder
    48  	Resumer          polymorphichelpers.ObjectResumerFunc
    49  	Namespace        string
    50  	EnforceNamespace bool
    51  	LabelSelector    string
    52  
    53  	resource.FilenameOptions
    54  	genericiooptions.IOStreams
    55  
    56  	fieldManager string
    57  }
    58  
    59  var (
    60  	resumeLong = templates.LongDesc(i18n.T(`
    61  		Resume a paused resource.
    62  
    63  		Paused resources will not be reconciled by a controller. By resuming a
    64  		resource, we allow it to be reconciled again.
    65  		Currently only deployments support being resumed.`))
    66  
    67  	resumeExample = templates.Examples(`
    68  		# Resume an already paused deployment
    69  		kubectl rollout resume deployment/nginx`)
    70  )
    71  
    72  // NewRolloutResumeOptions returns an initialized ResumeOptions instance
    73  func NewRolloutResumeOptions(streams genericiooptions.IOStreams) *ResumeOptions {
    74  	return &ResumeOptions{
    75  		PrintFlags: genericclioptions.NewPrintFlags("resumed").WithTypeSetter(scheme.Scheme),
    76  		IOStreams:  streams,
    77  	}
    78  }
    79  
    80  // NewCmdRolloutResume returns a Command instance for 'rollout resume' sub command
    81  func NewCmdRolloutResume(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command {
    82  	o := NewRolloutResumeOptions(streams)
    83  
    84  	validArgs := []string{"deployment"}
    85  
    86  	cmd := &cobra.Command{
    87  		Use:                   "resume RESOURCE",
    88  		DisableFlagsInUseLine: true,
    89  		Short:                 i18n.T("Resume a paused resource"),
    90  		Long:                  resumeLong,
    91  		Example:               resumeExample,
    92  		ValidArgsFunction:     completion.SpecifiedResourceTypeAndNameCompletionFunc(f, validArgs),
    93  		Run: func(cmd *cobra.Command, args []string) {
    94  			cmdutil.CheckErr(o.Complete(f, cmd, args))
    95  			cmdutil.CheckErr(o.Validate())
    96  			cmdutil.CheckErr(o.RunResume())
    97  		},
    98  	}
    99  
   100  	usage := "identifying the resource to get from a server."
   101  	cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
   102  	cmdutil.AddFieldManagerFlagVar(cmd, &o.fieldManager, "kubectl-rollout")
   103  	cmdutil.AddLabelSelectorFlagVar(cmd, &o.LabelSelector)
   104  	o.PrintFlags.AddFlags(cmd)
   105  	return cmd
   106  }
   107  
   108  // Complete completes all the required options
   109  func (o *ResumeOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
   110  	o.Resources = args
   111  
   112  	o.Resumer = polymorphichelpers.ObjectResumerFn
   113  
   114  	var err error
   115  	o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
   116  	if err != nil {
   117  		return err
   118  	}
   119  
   120  	o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) {
   121  		o.PrintFlags.NamePrintFlags.Operation = operation
   122  		return o.PrintFlags.ToPrinter()
   123  	}
   124  
   125  	o.Builder = f.NewBuilder
   126  
   127  	return nil
   128  }
   129  
   130  func (o *ResumeOptions) Validate() error {
   131  	if len(o.Resources) == 0 && cmdutil.IsFilenameSliceEmpty(o.Filenames, o.Kustomize) {
   132  		return fmt.Errorf("required resource not specified")
   133  	}
   134  	return nil
   135  }
   136  
   137  // RunResume performs the execution of 'rollout resume' sub command
   138  func (o ResumeOptions) RunResume() error {
   139  	r := o.Builder().
   140  		WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
   141  		NamespaceParam(o.Namespace).DefaultNamespace().
   142  		LabelSelectorParam(o.LabelSelector).
   143  		FilenameParam(o.EnforceNamespace, &o.FilenameOptions).
   144  		ResourceTypeOrNameArgs(true, o.Resources...).
   145  		ContinueOnError().
   146  		Latest().
   147  		Flatten().
   148  		Do()
   149  	if err := r.Err(); err != nil {
   150  		return err
   151  	}
   152  
   153  	allErrs := []error{}
   154  	infos, err := r.Infos()
   155  	if err != nil {
   156  		// restore previous command behavior where
   157  		// an error caused by retrieving infos due to
   158  		// at least a single broken object did not result
   159  		// in an immediate return, but rather an overall
   160  		// aggregation of errors.
   161  		allErrs = append(allErrs, err)
   162  	}
   163  
   164  	patches := set.CalculatePatches(infos, scheme.DefaultJSONEncoder(), set.PatchFn(o.Resumer))
   165  
   166  	if len(patches) == 0 && len(allErrs) == 0 {
   167  		fmt.Fprintf(o.ErrOut, "No resources found in %s namespace.\n", o.Namespace)
   168  		return nil
   169  	}
   170  
   171  	for _, patch := range patches {
   172  		info := patch.Info
   173  
   174  		if patch.Err != nil {
   175  			resourceString := info.Mapping.Resource.Resource
   176  			if len(info.Mapping.Resource.Group) > 0 {
   177  				resourceString = resourceString + "." + info.Mapping.Resource.Group
   178  			}
   179  			allErrs = append(allErrs, fmt.Errorf("error: %s %q %v", resourceString, info.Name, patch.Err))
   180  			continue
   181  		}
   182  
   183  		if string(patch.Patch) == "{}" || len(patch.Patch) == 0 {
   184  			printer, err := o.ToPrinter("already resumed")
   185  			if err != nil {
   186  				allErrs = append(allErrs, err)
   187  				continue
   188  			}
   189  			if err = printer.PrintObj(info.Object, o.Out); err != nil {
   190  				allErrs = append(allErrs, err)
   191  			}
   192  			continue
   193  		}
   194  
   195  		obj, err := resource.NewHelper(info.Client, info.Mapping).
   196  			WithFieldManager(o.fieldManager).
   197  			Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch, nil)
   198  		if err != nil {
   199  			allErrs = append(allErrs, fmt.Errorf("failed to patch: %v", err))
   200  			continue
   201  		}
   202  
   203  		info.Refresh(obj, true)
   204  		printer, err := o.ToPrinter("resumed")
   205  		if err != nil {
   206  			allErrs = append(allErrs, err)
   207  			continue
   208  		}
   209  		if err = printer.PrintObj(info.Object, o.Out); err != nil {
   210  			allErrs = append(allErrs, err)
   211  		}
   212  	}
   213  
   214  	return utilerrors.NewAggregate(allErrs)
   215  }
   216  

View as plain text