From d0d260fd03cb4a86190e5dfd4703f1cc2f92993c Mon Sep 17 00:00:00 2001 From: Chao Xu Date: Tue, 13 Oct 2015 22:25:18 -0700 Subject: [PATCH] let kubectl annotate use patch instead of replace --- pkg/kubectl/cmd/annotate.go | 43 +++++++++++++++++++++++--------- pkg/kubectl/cmd/annotate_test.go | 12 ++++----- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/pkg/kubectl/cmd/annotate.go b/pkg/kubectl/cmd/annotate.go index 5e15105605496..e4dff167e549e 100644 --- a/pkg/kubectl/cmd/annotate.go +++ b/pkg/kubectl/cmd/annotate.go @@ -18,6 +18,7 @@ package cmd import ( "bytes" + "encoding/json" "fmt" "io" "strings" @@ -28,6 +29,7 @@ import ( cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/runtime" + "k8s.io/kubernetes/pkg/util/strategicpatch" ) // AnnotateOptions have the data required to perform the annotate operation @@ -91,7 +93,7 @@ func NewCmdAnnotate(f *cmdutil.Factory, out io.Writer) *cobra.Command { if err := options.Validate(args); err != nil { cmdutil.CheckErr(cmdutil.UsageError(cmd, err.Error())) } - if err := options.RunAnnotate(); err != nil { + if err := options.RunAnnotate(f); err != nil { cmdutil.CheckErr(err) } }, @@ -167,26 +169,43 @@ func (o AnnotateOptions) Validate(args []string) error { } // RunAnnotate does the work -func (o AnnotateOptions) RunAnnotate() error { +func (o AnnotateOptions) RunAnnotate(f *cmdutil.Factory) error { r := o.builder.Do() if err := r.Err(); err != nil { return err } + return r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } - _, uErr := cmdutil.UpdateObject(info, func(obj runtime.Object) error { - err := o.updateAnnotations(obj) - if err != nil { - return err - } - return nil - }) - if uErr != nil { - return uErr + + name, namespace, obj := info.Name, info.Namespace, info.Object + oldData, err := json.Marshal(obj) + if err != nil { + return err + } + if err := o.updateAnnotations(obj); err != nil { + return err + } + newData, err := json.Marshal(obj) + if err != nil { + return err } - return nil + patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj) + if err != nil { + return err + } + + mapping := info.ResourceMapping() + client, err := f.RESTClient(mapping) + if err != nil { + return err + } + helper := resource.NewHelper(client, mapping) + + _, err = helper.Patch(namespace, name, api.StrategicMergePatchType, patchBytes) + return err }) } diff --git a/pkg/kubectl/cmd/annotate_test.go b/pkg/kubectl/cmd/annotate_test.go index d518846bc3f49..5060a4dc4a147 100644 --- a/pkg/kubectl/cmd/annotate_test.go +++ b/pkg/kubectl/cmd/annotate_test.go @@ -433,7 +433,7 @@ func TestAnnotateObject(t *testing.T) { t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) return nil, nil } - case "PUT": + case "PATCH": switch req.URL.Path { case "/namespaces/test/pods/foo": return &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, nil @@ -458,7 +458,7 @@ func TestAnnotateObject(t *testing.T) { if err := options.Validate(args); err != nil { t.Fatalf("unexpected error: %v", err) } - if err := options.RunAnnotate(); err != nil { + if err := options.RunAnnotate(f); err != nil { t.Fatalf("unexpected error: %v", err) } } @@ -480,7 +480,7 @@ func TestAnnotateObjectFromFile(t *testing.T) { t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) return nil, nil } - case "PUT": + case "PATCH": switch req.URL.Path { case "/namespaces/test/pods/cassandra": return &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, nil @@ -506,7 +506,7 @@ func TestAnnotateObjectFromFile(t *testing.T) { if err := options.Validate(args); err != nil { t.Fatalf("unexpected error: %v", err) } - if err := options.RunAnnotate(); err != nil { + if err := options.RunAnnotate(f); err != nil { t.Fatalf("unexpected error: %v", err) } } @@ -528,7 +528,7 @@ func TestAnnotateMultipleObjects(t *testing.T) { t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) return nil, nil } - case "PUT": + case "PATCH": switch req.URL.Path { case "/namespaces/test/pods/foo": return &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, nil @@ -556,7 +556,7 @@ func TestAnnotateMultipleObjects(t *testing.T) { if err := options.Validate(args); err != nil { t.Fatalf("unexpected error: %v", err) } - if err := options.RunAnnotate(); err != nil { + if err := options.RunAnnotate(f); err != nil { t.Fatalf("unexpected error: %v", err) } }