apply_view_last_applied.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. Copyright 2017 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 apply
  14. import (
  15. "bytes"
  16. "encoding/json"
  17. "fmt"
  18. "github.com/spf13/cobra"
  19. "k8s.io/cli-runtime/pkg/genericclioptions"
  20. "k8s.io/cli-runtime/pkg/resource"
  21. "k8s.io/kubernetes/pkg/kubectl"
  22. cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
  23. "k8s.io/kubernetes/pkg/kubectl/util/i18n"
  24. "k8s.io/kubernetes/pkg/kubectl/util/templates"
  25. "sigs.k8s.io/yaml"
  26. )
  27. // ViewLastAppliedOptions defines options for the `apply view-last-applied` command.`
  28. type ViewLastAppliedOptions struct {
  29. FilenameOptions resource.FilenameOptions
  30. Selector string
  31. LastAppliedConfigurationList []string
  32. OutputFormat string
  33. All bool
  34. Factory cmdutil.Factory
  35. genericclioptions.IOStreams
  36. }
  37. var (
  38. applyViewLastAppliedLong = templates.LongDesc(i18n.T(`
  39. View the latest last-applied-configuration annotations by type/name or file.
  40. The default output will be printed to stdout in YAML format. One can use -o option
  41. to change output format.`))
  42. applyViewLastAppliedExample = templates.Examples(i18n.T(`
  43. # View the last-applied-configuration annotations by type/name in YAML.
  44. kubectl apply view-last-applied deployment/nginx
  45. # View the last-applied-configuration annotations by file in JSON
  46. kubectl apply view-last-applied -f deploy.yaml -o json`))
  47. )
  48. // NewViewLastAppliedOptions takes option arguments from a CLI stream and returns it at ViewLastAppliedOptions type.
  49. func NewViewLastAppliedOptions(ioStreams genericclioptions.IOStreams) *ViewLastAppliedOptions {
  50. return &ViewLastAppliedOptions{
  51. OutputFormat: "yaml",
  52. IOStreams: ioStreams,
  53. }
  54. }
  55. // NewCmdApplyViewLastApplied creates the cobra CLI `apply` subcommand `view-last-applied`.`
  56. func NewCmdApplyViewLastApplied(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
  57. options := NewViewLastAppliedOptions(ioStreams)
  58. cmd := &cobra.Command{
  59. Use: "view-last-applied (TYPE [NAME | -l label] | TYPE/NAME | -f FILENAME)",
  60. DisableFlagsInUseLine: true,
  61. Short: i18n.T("View latest last-applied-configuration annotations of a resource/object"),
  62. Long: applyViewLastAppliedLong,
  63. Example: applyViewLastAppliedExample,
  64. Run: func(cmd *cobra.Command, args []string) {
  65. cmdutil.CheckErr(options.Complete(cmd, f, args))
  66. cmdutil.CheckErr(options.Validate(cmd))
  67. cmdutil.CheckErr(options.RunApplyViewLastApplied(cmd))
  68. },
  69. }
  70. cmd.Flags().StringVarP(&options.OutputFormat, "output", "o", options.OutputFormat, "Output format. Must be one of yaml|json")
  71. cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
  72. cmd.Flags().BoolVar(&options.All, "all", options.All, "Select all resources in the namespace of the specified resource types")
  73. usage := "that contains the last-applied-configuration annotations"
  74. cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
  75. return cmd
  76. }
  77. // Complete checks an object for last-applied-configuration annotations.
  78. func (o *ViewLastAppliedOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args []string) error {
  79. cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace()
  80. if err != nil {
  81. return err
  82. }
  83. r := f.NewBuilder().
  84. Unstructured().
  85. NamespaceParam(cmdNamespace).DefaultNamespace().
  86. FilenameParam(enforceNamespace, &o.FilenameOptions).
  87. ResourceTypeOrNameArgs(enforceNamespace, args...).
  88. SelectAllParam(o.All).
  89. LabelSelectorParam(o.Selector).
  90. Latest().
  91. Flatten().
  92. Do()
  93. err = r.Err()
  94. if err != nil {
  95. return err
  96. }
  97. err = r.Visit(func(info *resource.Info, err error) error {
  98. if err != nil {
  99. return err
  100. }
  101. configString, err := kubectl.GetOriginalConfiguration(info.Object)
  102. if err != nil {
  103. return err
  104. }
  105. if configString == nil {
  106. return cmdutil.AddSourceToErr(fmt.Sprintf("no last-applied-configuration annotation found on resource: %s\n", info.Name), info.Source, err)
  107. }
  108. o.LastAppliedConfigurationList = append(o.LastAppliedConfigurationList, string(configString))
  109. return nil
  110. })
  111. if err != nil {
  112. return err
  113. }
  114. return nil
  115. }
  116. // Validate checks ViewLastAppliedOptions for validity.
  117. func (o *ViewLastAppliedOptions) Validate(cmd *cobra.Command) error {
  118. return nil
  119. }
  120. // RunApplyViewLastApplied executes the `view-last-applied` command according to ViewLastAppliedOptions.
  121. func (o *ViewLastAppliedOptions) RunApplyViewLastApplied(cmd *cobra.Command) error {
  122. for _, str := range o.LastAppliedConfigurationList {
  123. switch o.OutputFormat {
  124. case "json":
  125. jsonBuffer := &bytes.Buffer{}
  126. err := json.Indent(jsonBuffer, []byte(str), "", " ")
  127. if err != nil {
  128. return err
  129. }
  130. fmt.Fprint(o.Out, string(jsonBuffer.Bytes()))
  131. case "yaml":
  132. yamlOutput, err := yaml.JSONToYAML([]byte(str))
  133. if err != nil {
  134. return err
  135. }
  136. fmt.Fprint(o.Out, string(yamlOutput))
  137. default:
  138. return cmdutil.UsageErrorf(
  139. cmd,
  140. "Unexpected -o output mode: %s, the flag 'output' must be one of yaml|json",
  141. o.OutputFormat)
  142. }
  143. }
  144. return nil
  145. }