1
16
17 package apply
18
19 import (
20 "bytes"
21 "encoding/json"
22 "fmt"
23
24 "github.com/spf13/cobra"
25 "k8s.io/cli-runtime/pkg/genericiooptions"
26 "k8s.io/cli-runtime/pkg/resource"
27 cmdutil "k8s.io/kubectl/pkg/cmd/util"
28 "k8s.io/kubectl/pkg/util"
29 "k8s.io/kubectl/pkg/util/completion"
30 "k8s.io/kubectl/pkg/util/i18n"
31 "k8s.io/kubectl/pkg/util/templates"
32 "sigs.k8s.io/yaml"
33 )
34
35
36 type ViewLastAppliedOptions struct {
37 FilenameOptions resource.FilenameOptions
38 Selector string
39 LastAppliedConfigurationList []string
40 OutputFormat string
41 All bool
42 Factory cmdutil.Factory
43
44 genericiooptions.IOStreams
45 }
46
47 var (
48 applyViewLastAppliedLong = templates.LongDesc(i18n.T(`
49 View the latest last-applied-configuration annotations by type/name or file.
50
51 The default output will be printed to stdout in YAML format. You can use the -o option
52 to change the output format.`))
53
54 applyViewLastAppliedExample = templates.Examples(i18n.T(`
55 # View the last-applied-configuration annotations by type/name in YAML
56 kubectl apply view-last-applied deployment/nginx
57
58 # View the last-applied-configuration annotations by file in JSON
59 kubectl apply view-last-applied -f deploy.yaml -o json`))
60 )
61
62
63 func NewViewLastAppliedOptions(ioStreams genericiooptions.IOStreams) *ViewLastAppliedOptions {
64 return &ViewLastAppliedOptions{
65 OutputFormat: "yaml",
66
67 IOStreams: ioStreams,
68 }
69 }
70
71
72 func NewCmdApplyViewLastApplied(f cmdutil.Factory, ioStreams genericiooptions.IOStreams) *cobra.Command {
73 options := NewViewLastAppliedOptions(ioStreams)
74
75 cmd := &cobra.Command{
76 Use: "view-last-applied (TYPE [NAME | -l label] | TYPE/NAME | -f FILENAME)",
77 DisableFlagsInUseLine: true,
78 Short: i18n.T("View the latest last-applied-configuration annotations of a resource/object"),
79 Long: applyViewLastAppliedLong,
80 Example: applyViewLastAppliedExample,
81 ValidArgsFunction: completion.ResourceTypeAndNameCompletionFunc(f),
82 Run: func(cmd *cobra.Command, args []string) {
83 cmdutil.CheckErr(options.Complete(cmd, f, args))
84 cmdutil.CheckErr(options.Validate())
85 cmdutil.CheckErr(options.RunApplyViewLastApplied(cmd))
86 },
87 }
88
89 cmd.Flags().StringVarP(&options.OutputFormat, "output", "o", options.OutputFormat, `Output format. Must be one of (yaml, json)`)
90 cmd.Flags().BoolVar(&options.All, "all", options.All, "Select all resources in the namespace of the specified resource types")
91 usage := "that contains the last-applied-configuration annotations"
92 cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
93 cmdutil.AddLabelSelectorFlagVar(cmd, &options.Selector)
94
95 return cmd
96 }
97
98
99 func (o *ViewLastAppliedOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args []string) error {
100 cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace()
101 if err != nil {
102 return err
103 }
104
105 r := f.NewBuilder().
106 Unstructured().
107 NamespaceParam(cmdNamespace).DefaultNamespace().
108 FilenameParam(enforceNamespace, &o.FilenameOptions).
109 ResourceTypeOrNameArgs(enforceNamespace, args...).
110 SelectAllParam(o.All).
111 LabelSelectorParam(o.Selector).
112 Latest().
113 Flatten().
114 Do()
115 err = r.Err()
116 if err != nil {
117 return err
118 }
119
120 err = r.Visit(func(info *resource.Info, err error) error {
121 if err != nil {
122 return err
123 }
124
125 configString, err := util.GetOriginalConfiguration(info.Object)
126 if err != nil {
127 return err
128 }
129 if configString == nil {
130 return cmdutil.AddSourceToErr(fmt.Sprintf("no last-applied-configuration annotation found on resource: %s\n", info.Name), info.Source, err)
131 }
132 o.LastAppliedConfigurationList = append(o.LastAppliedConfigurationList, string(configString))
133 return nil
134 })
135
136 if err != nil {
137 return err
138 }
139
140 return nil
141 }
142
143
144 func (o *ViewLastAppliedOptions) Validate() error {
145 return nil
146 }
147
148
149 func (o *ViewLastAppliedOptions) RunApplyViewLastApplied(cmd *cobra.Command) error {
150 for _, str := range o.LastAppliedConfigurationList {
151 switch o.OutputFormat {
152 case "json":
153 jsonBuffer := &bytes.Buffer{}
154 err := json.Indent(jsonBuffer, []byte(str), "", " ")
155 if err != nil {
156 return err
157 }
158 fmt.Fprint(o.Out, string(jsonBuffer.Bytes()))
159 case "yaml":
160 yamlOutput, err := yaml.JSONToYAML([]byte(str))
161 if err != nil {
162 return err
163 }
164 fmt.Fprint(o.Out, string(yamlOutput))
165 default:
166 return cmdutil.UsageErrorf(
167 cmd,
168 "Unexpected -o output mode: %s, the flag 'output' must be one of yaml|json",
169 o.OutputFormat)
170 }
171 }
172
173 return nil
174 }
175
View as plain text