From ca300c180cae828a31b03f42959f4795f9407c0a Mon Sep 17 00:00:00 2001 From: hurf Date: Sat, 14 Nov 2015 03:07:21 +0800 Subject: [PATCH] Add printer options to Annotate 1. add return message as "resource name annotated" 2. add printer options to annotate 3. move all parameter into AnnotateOptions to make sure runT function has no parameter. --- contrib/completions/bash/kubectl | 9 ++++++ docs/man/man1/kubectl-annotate.1 | 27 +++++++++++++++++ docs/user-guide/kubectl/kubectl_annotate.md | 8 ++++- pkg/kubectl/cmd/annotate.go | 33 ++++++++++++++++----- pkg/kubectl/cmd/annotate_test.go | 23 +++++++++----- 5 files changed, 85 insertions(+), 15 deletions(-) diff --git a/contrib/completions/bash/kubectl b/contrib/completions/bash/kubectl index e6860231cb7..124ed7367cd 100644 --- a/contrib/completions/bash/kubectl +++ b/contrib/completions/bash/kubectl @@ -975,8 +975,17 @@ _kubectl_annotate() two_word_flags+=("-f") flags_with_completion+=("-f") flags_completion+=("__handle_filename_extension_flag json|yaml|yml") + flags+=("--no-headers") + flags+=("--output=") + two_word_flags+=("-o") + flags+=("--output-version=") flags+=("--overwrite") flags+=("--resource-version=") + flags+=("--show-all") + flags+=("-a") + flags+=("--sort-by=") + flags+=("--template=") + two_word_flags+=("-t") must_have_one_flag=() must_have_one_noun=() diff --git a/docs/man/man1/kubectl-annotate.1 b/docs/man/man1/kubectl-annotate.1 index 15396b5ae77..7568a5ba82e 100644 --- a/docs/man/man1/kubectl-annotate.1 +++ b/docs/man/man1/kubectl-annotate.1 @@ -37,6 +37,20 @@ resourcequotas (quota) or secrets. \fB\-f\fP, \fB\-\-filename\fP=[] Filename, directory, or URL to a file identifying the resource to update the annotation +.PP +\fB\-\-no\-headers\fP=false + When using the default output, don't print headers. + +.PP +\fB\-o\fP, \fB\-\-output\fP="" + Output format. One of: json|yaml|wide|name|go\-template=...|go\-template\-file=...|jsonpath=...|jsonpath\-file=... See golang template [ +\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]] and jsonpath template [ +\[la]http://releases.k8s.io/HEAD/docs/user-guide/jsonpath.md\[ra]]. + +.PP +\fB\-\-output\-version\fP="" + Output the formatted object with the given version (default api\-version). + .PP \fB\-\-overwrite\fP=false If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations. @@ -45,6 +59,19 @@ resourcequotas (quota) or secrets. \fB\-\-resource\-version\fP="" If non\-empty, the annotation update will only succeed if this is the current resource\-version for the object. Only valid when specifying a single resource. +.PP +\fB\-a\fP, \fB\-\-show\-all\fP=false + When printing, show all resources (default hide terminated pods.) + +.PP +\fB\-\-sort\-by\fP="" + If non\-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. 'ObjectMeta.Name'). The field in the API resource specified by this JSONPath expression must be an integer or a string. + +.PP +\fB\-\-template\fP="" + Template string or path to template file to use when \-o=go\-template, \-o=go\-template\-file. The template format is golang templates [ +\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]]. + .SH OPTIONS INHERITED FROM PARENT COMMANDS .PP diff --git a/docs/user-guide/kubectl/kubectl_annotate.md b/docs/user-guide/kubectl/kubectl_annotate.md index 96bf878ebc9..7d917d0db26 100644 --- a/docs/user-guide/kubectl/kubectl_annotate.md +++ b/docs/user-guide/kubectl/kubectl_annotate.md @@ -83,8 +83,14 @@ $ kubectl annotate pods foo description- ``` --all[=false]: select all resources in the namespace of the specified resource types -f, --filename=[]: Filename, directory, or URL to a file identifying the resource to update the annotation + --no-headers[=false]: When using the default output, don't print headers. + -o, --output="": Output format. One of: json|yaml|wide|name|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://releases.k8s.io/HEAD/docs/user-guide/jsonpath.md]. + --output-version="": Output the formatted object with the given version (default api-version). --overwrite[=false]: If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations. --resource-version="": If non-empty, the annotation update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource. + -a, --show-all[=false]: When printing, show all resources (default hide terminated pods.) + --sort-by="": If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. 'ObjectMeta.Name'). The field in the API resource specified by this JSONPath expression must be an integer or a string. + --template="": Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview]. ``` ### Options inherited from parent commands @@ -119,7 +125,7 @@ $ kubectl annotate pods foo description- * [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager -###### Auto generated by spf13/cobra at 2015-09-22 12:53:42.293299401 +0000 UTC +###### Auto generated by spf13/cobra on 14-Nov-2015 [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_annotate.md?pixel)]() diff --git a/pkg/kubectl/cmd/annotate.go b/pkg/kubectl/cmd/annotate.go index e4dff167e54..51e244e5ba1 100644 --- a/pkg/kubectl/cmd/annotate.go +++ b/pkg/kubectl/cmd/annotate.go @@ -43,6 +43,10 @@ type AnnotateOptions struct { overwrite bool all bool resourceVersion string + + f *cmdutil.Factory + out io.Writer + cmd *cobra.Command } const ( @@ -87,17 +91,18 @@ func NewCmdAnnotate(f *cmdutil.Factory, out io.Writer) *cobra.Command { Long: annotate_long, Example: annotate_example, Run: func(cmd *cobra.Command, args []string) { - if err := options.Complete(f, args); err != nil { + if err := options.Complete(f, out, cmd, args); err != nil { cmdutil.CheckErr(err) } if err := options.Validate(args); err != nil { cmdutil.CheckErr(cmdutil.UsageError(cmd, err.Error())) } - if err := options.RunAnnotate(f); err != nil { + if err := options.RunAnnotate(); err != nil { cmdutil.CheckErr(err) } }, } + cmdutil.AddPrinterFlags(cmd) cmd.Flags().BoolVar(&options.overwrite, "overwrite", false, "If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.") cmd.Flags().BoolVar(&options.all, "all", false, "select all resources in the namespace of the specified resource types") cmd.Flags().StringVar(&options.resourceVersion, "resource-version", "", "If non-empty, the annotation update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.") @@ -107,7 +112,8 @@ func NewCmdAnnotate(f *cmdutil.Factory, out io.Writer) *cobra.Command { } // Complete adapts from the command line args and factory to the data required. -func (o *AnnotateOptions) Complete(f *cmdutil.Factory, args []string) (err error) { +func (o *AnnotateOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) (err error) { + namespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err @@ -151,6 +157,10 @@ func (o *AnnotateOptions) Complete(f *cmdutil.Factory, args []string) (err error Flatten(). Latest() + o.f = f + o.out = out + o.cmd = cmd + return nil } @@ -169,7 +179,7 @@ func (o AnnotateOptions) Validate(args []string) error { } // RunAnnotate does the work -func (o AnnotateOptions) RunAnnotate(f *cmdutil.Factory) error { +func (o AnnotateOptions) RunAnnotate() error { r := o.builder.Do() if err := r.Err(); err != nil { return err @@ -198,14 +208,23 @@ func (o AnnotateOptions) RunAnnotate(f *cmdutil.Factory) error { } mapping := info.ResourceMapping() - client, err := f.RESTClient(mapping) + client, err := o.f.RESTClient(mapping) if err != nil { return err } helper := resource.NewHelper(client, mapping) - _, err = helper.Patch(namespace, name, api.StrategicMergePatchType, patchBytes) - return err + outputObj, err := helper.Patch(namespace, name, api.StrategicMergePatchType, patchBytes) + if err != nil { + return err + } + outputFormat := cmdutil.GetFlagString(o.cmd, "output") + if outputFormat != "" { + return o.f.PrintObject(o.cmd, outputObj, o.out) + } + mapper, _ := o.f.Object() + cmdutil.PrintSuccess(mapper, false, o.out, info.Mapping.Resource, info.Name, "annotated") + return nil }) } diff --git a/pkg/kubectl/cmd/annotate_test.go b/pkg/kubectl/cmd/annotate_test.go index e7597ecc40d..fdcf2a3d08d 100644 --- a/pkg/kubectl/cmd/annotate_test.go +++ b/pkg/kubectl/cmd/annotate_test.go @@ -402,7 +402,7 @@ func TestAnnotateErrors(t *testing.T) { cmd.Flags().Set(k, v) } options := &AnnotateOptions{} - err := options.Complete(f, testCase.args) + err := options.Complete(f, buf, cmd, testCase.args) if !testCase.errFn(err) { t.Errorf("%s: unexpected error: %v", k, err) continue @@ -450,15 +450,18 @@ func TestAnnotateObject(t *testing.T) { tf.Namespace = "test" tf.ClientConfig = &client.Config{Version: testapi.Default.Version()} + buf := bytes.NewBuffer([]byte{}) + cmd := NewCmdAnnotate(f, buf) + cmd.SetOutput(buf) options := &AnnotateOptions{} args := []string{"pods/foo", "a=b", "c-"} - if err := options.Complete(f, args); err != nil { + if err := options.Complete(f, buf, cmd, args); err != nil { t.Fatalf("unexpected error: %v", err) } if err := options.Validate(args); err != nil { t.Fatalf("unexpected error: %v", err) } - if err := options.RunAnnotate(f); err != nil { + if err := options.RunAnnotate(); err != nil { t.Fatalf("unexpected error: %v", err) } } @@ -497,16 +500,19 @@ func TestAnnotateObjectFromFile(t *testing.T) { tf.Namespace = "test" tf.ClientConfig = &client.Config{Version: testapi.Default.Version()} + buf := bytes.NewBuffer([]byte{}) + cmd := NewCmdAnnotate(f, buf) + cmd.SetOutput(buf) options := &AnnotateOptions{} options.filenames = []string{"../../../examples/cassandra/cassandra.yaml"} args := []string{"a=b", "c-"} - if err := options.Complete(f, args); err != nil { + if err := options.Complete(f, buf, cmd, args); err != nil { t.Fatalf("unexpected error: %v", err) } if err := options.Validate(args); err != nil { t.Fatalf("unexpected error: %v", err) } - if err := options.RunAnnotate(f); err != nil { + if err := options.RunAnnotate(); err != nil { t.Fatalf("unexpected error: %v", err) } } @@ -547,16 +553,19 @@ func TestAnnotateMultipleObjects(t *testing.T) { tf.Namespace = "test" tf.ClientConfig = &client.Config{Version: testapi.Default.Version()} + buf := bytes.NewBuffer([]byte{}) + cmd := NewCmdAnnotate(f, buf) + cmd.SetOutput(buf) options := &AnnotateOptions{} options.all = true args := []string{"pods", "a=b", "c-"} - if err := options.Complete(f, args); err != nil { + if err := options.Complete(f, buf, cmd, args); err != nil { t.Fatalf("unexpected error: %v", err) } if err := options.Validate(args); err != nil { t.Fatalf("unexpected error: %v", err) } - if err := options.RunAnnotate(f); err != nil { + if err := options.RunAnnotate(); err != nil { t.Fatalf("unexpected error: %v", err) } }