rollout_undo.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package rollout
  14. import (
  15. "fmt"
  16. "github.com/spf13/cobra"
  17. "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
  18. "k8s.io/cli-runtime/pkg/genericclioptions"
  19. "k8s.io/cli-runtime/pkg/printers"
  20. "k8s.io/cli-runtime/pkg/resource"
  21. cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
  22. "k8s.io/kubernetes/pkg/kubectl/scheme"
  23. "k8s.io/kubernetes/pkg/kubectl/util/i18n"
  24. "k8s.io/kubernetes/pkg/kubectl/util/templates"
  25. )
  26. // UndoOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
  27. // referencing the cmd.Flags()
  28. type UndoOptions struct {
  29. PrintFlags *genericclioptions.PrintFlags
  30. ToPrinter func(string) (printers.ResourcePrinter, error)
  31. Builder func() *resource.Builder
  32. ToRevision int64
  33. DryRun bool
  34. Resources []string
  35. Namespace string
  36. EnforceNamespace bool
  37. RESTClientGetter genericclioptions.RESTClientGetter
  38. resource.FilenameOptions
  39. genericclioptions.IOStreams
  40. }
  41. var (
  42. undoLong = templates.LongDesc(`
  43. Rollback to a previous rollout.`)
  44. undoExample = templates.Examples(`
  45. # Rollback to the previous deployment
  46. kubectl rollout undo deployment/abc
  47. # Rollback to daemonset revision 3
  48. kubectl rollout undo daemonset/abc --to-revision=3
  49. # Rollback to the previous deployment with dry-run
  50. kubectl rollout undo --dry-run=true deployment/abc`)
  51. )
  52. // NewRolloutUndoOptions returns an initialized UndoOptions instance
  53. func NewRolloutUndoOptions(streams genericclioptions.IOStreams) *UndoOptions {
  54. return &UndoOptions{
  55. PrintFlags: genericclioptions.NewPrintFlags("rolled back").WithTypeSetter(scheme.Scheme),
  56. IOStreams: streams,
  57. ToRevision: int64(0),
  58. }
  59. }
  60. // NewCmdRolloutUndo returns a Command instance for the 'rollout undo' sub command
  61. func NewCmdRolloutUndo(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
  62. o := NewRolloutUndoOptions(streams)
  63. validArgs := []string{"deployment", "daemonset", "statefulset"}
  64. cmd := &cobra.Command{
  65. Use: "undo (TYPE NAME | TYPE/NAME) [flags]",
  66. DisableFlagsInUseLine: true,
  67. Short: i18n.T("Undo a previous rollout"),
  68. Long: undoLong,
  69. Example: undoExample,
  70. Run: func(cmd *cobra.Command, args []string) {
  71. cmdutil.CheckErr(o.Complete(f, cmd, args))
  72. cmdutil.CheckErr(o.Validate())
  73. cmdutil.CheckErr(o.RunUndo())
  74. },
  75. ValidArgs: validArgs,
  76. }
  77. cmd.Flags().Int64Var(&o.ToRevision, "to-revision", o.ToRevision, "The revision to rollback to. Default to 0 (last revision).")
  78. usage := "identifying the resource to get from a server."
  79. cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
  80. cmdutil.AddDryRunFlag(cmd)
  81. o.PrintFlags.AddFlags(cmd)
  82. return cmd
  83. }
  84. // Complete completes al the required options
  85. func (o *UndoOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
  86. o.Resources = args
  87. o.DryRun = cmdutil.GetDryRunFlag(cmd)
  88. var err error
  89. if o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace(); err != nil {
  90. return err
  91. }
  92. o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) {
  93. o.PrintFlags.NamePrintFlags.Operation = operation
  94. if o.DryRun {
  95. o.PrintFlags.Complete("%s (dry run)")
  96. }
  97. return o.PrintFlags.ToPrinter()
  98. }
  99. o.RESTClientGetter = f
  100. o.Builder = f.NewBuilder
  101. return err
  102. }
  103. func (o *UndoOptions) Validate() error {
  104. if len(o.Resources) == 0 && cmdutil.IsFilenameSliceEmpty(o.Filenames, o.Kustomize) {
  105. return fmt.Errorf("required resource not specified")
  106. }
  107. return nil
  108. }
  109. // RunUndo performs the execution of 'rollout undo' sub command
  110. func (o *UndoOptions) RunUndo() error {
  111. r := o.Builder().
  112. WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
  113. NamespaceParam(o.Namespace).DefaultNamespace().
  114. FilenameParam(o.EnforceNamespace, &o.FilenameOptions).
  115. ResourceTypeOrNameArgs(true, o.Resources...).
  116. ContinueOnError().
  117. Latest().
  118. Flatten().
  119. Do()
  120. if err := r.Err(); err != nil {
  121. return err
  122. }
  123. err := r.Visit(func(info *resource.Info, err error) error {
  124. if err != nil {
  125. return err
  126. }
  127. rollbacker, err := polymorphichelpers.RollbackerFn(o.RESTClientGetter, info.ResourceMapping())
  128. if err != nil {
  129. return err
  130. }
  131. result, err := rollbacker.Rollback(info.Object, nil, o.ToRevision, o.DryRun)
  132. if err != nil {
  133. return err
  134. }
  135. printer, err := o.ToPrinter(result)
  136. if err != nil {
  137. return err
  138. }
  139. return printer.PrintObj(info.Object, o.Out)
  140. })
  141. return err
  142. }