Commit 3de11e2f authored by Mike Danese's avatar Mike Danese

reenable patch serverside using strategic-merge-patch

parent 458cbd3b
...@@ -337,10 +337,12 @@ _kubectl_update() ...@@ -337,10 +337,12 @@ _kubectl_update()
flags_completion+=("__handle_filename_extension_flag json|yaml|yml") flags_completion+=("__handle_filename_extension_flag json|yaml|yml")
flags+=("--help") flags+=("--help")
flags+=("-h") flags+=("-h")
flags+=("--patch=")
must_have_one_flag=() must_have_one_flag=()
must_have_one_flag+=("--filename=") must_have_one_flag+=("--filename=")
must_have_one_flag+=("-f") must_have_one_flag+=("-f")
must_have_one_flag+=("--patch=")
must_have_one_noun=() must_have_one_noun=()
} }
......
...@@ -21,6 +21,9 @@ $ kubectl update -f pod.json ...@@ -21,6 +21,9 @@ $ kubectl update -f pod.json
// Update a pod based on the JSON passed into stdin. // Update a pod based on the JSON passed into stdin.
$ cat pod.json | kubectl update -f - $ cat pod.json | kubectl update -f -
// Partially update a node using strategic merge patch
kubectl --api-version=v1 update node k8s-node-1 --patch='{"spec":{"unschedulable":true}}'
``` ```
### Options ### Options
...@@ -28,6 +31,7 @@ $ cat pod.json | kubectl update -f - ...@@ -28,6 +31,7 @@ $ cat pod.json | kubectl update -f -
``` ```
-f, --filename=[]: Filename, directory, or URL to file to use to update the resource. -f, --filename=[]: Filename, directory, or URL to file to use to update the resource.
-h, --help=false: help for update -h, --help=false: help for update
--patch="": A JSON document to override the existing resource. The resource is downloaded, patched with the JSON, then updated.
``` ```
### Options inherited from parent commands ### Options inherited from parent commands
...@@ -62,6 +66,6 @@ $ cat pod.json | kubectl update -f - ...@@ -62,6 +66,6 @@ $ cat pod.json | kubectl update -f -
### SEE ALSO ### SEE ALSO
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager * [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
###### Auto generated by spf13/cobra at 2015-05-29 01:11:24.431126385 +0000 UTC ###### Auto generated by spf13/cobra at 2015-06-18 19:03:00.935576604 +0000 UTC
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/kubectl_update.md?pixel)]() [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/kubectl_update.md?pixel)]()
...@@ -28,6 +28,10 @@ JSON and YAML formats are accepted. ...@@ -28,6 +28,10 @@ JSON and YAML formats are accepted.
\fB\-h\fP, \fB\-\-help\fP=false \fB\-h\fP, \fB\-\-help\fP=false
help for update help for update
.PP
\fB\-\-patch\fP=""
A JSON document to override the existing resource. The resource is downloaded, patched with the JSON, then updated.
.SH OPTIONS INHERITED FROM PARENT COMMANDS .SH OPTIONS INHERITED FROM PARENT COMMANDS
.PP .PP
...@@ -138,6 +142,9 @@ $ kubectl update \-f pod.json ...@@ -138,6 +142,9 @@ $ kubectl update \-f pod.json
// Update a pod based on the JSON passed into stdin. // Update a pod based on the JSON passed into stdin.
$ cat pod.json | kubectl update \-f \- $ cat pod.json | kubectl update \-f \-
// Partially update a node using strategic merge patch
kubectl \-\-api\-version=v1 update node k8s\-node\-1 \-\-patch='\{"spec":\{"unschedulable":true\}\}'
.fi .fi
.RE .RE
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
"net/http" "net/http"
"net/url" "net/url"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
) )
...@@ -47,6 +48,10 @@ func (c *FakeRESTClient) Put() *Request { ...@@ -47,6 +48,10 @@ func (c *FakeRESTClient) Put() *Request {
return NewRequest(c, "PUT", &url.URL{Host: "localhost"}, testapi.Version(), c.Codec) return NewRequest(c, "PUT", &url.URL{Host: "localhost"}, testapi.Version(), c.Codec)
} }
func (c *FakeRESTClient) Patch(_ api.PatchType) *Request {
return NewRequest(c, "PATCH", &url.URL{Host: "localhost"}, testapi.Version(), c.Codec)
}
func (c *FakeRESTClient) Post() *Request { func (c *FakeRESTClient) Post() *Request {
return NewRequest(c, "POST", &url.URL{Host: "localhost"}, testapi.Version(), c.Codec) return NewRequest(c, "POST", &url.URL{Host: "localhost"}, testapi.Version(), c.Codec)
} }
......
...@@ -22,6 +22,7 @@ import ( ...@@ -22,6 +22,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
...@@ -36,7 +37,10 @@ JSON and YAML formats are accepted.` ...@@ -36,7 +37,10 @@ JSON and YAML formats are accepted.`
$ kubectl update -f pod.json $ kubectl update -f pod.json
// Update a pod based on the JSON passed into stdin. // Update a pod based on the JSON passed into stdin.
$ cat pod.json | kubectl update -f -` $ cat pod.json | kubectl update -f -
// Partially update a node using strategic merge patch
kubectl --api-version=v1 update node k8s-node-1 --patch='{"spec":{"unschedulable":true}}'`
) )
func NewCmdUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command { func NewCmdUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
...@@ -54,9 +58,8 @@ func NewCmdUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command { ...@@ -54,9 +58,8 @@ func NewCmdUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
usage := "Filename, directory, or URL to file to use to update the resource." usage := "Filename, directory, or URL to file to use to update the resource."
kubectl.AddJsonFilenameFlag(cmd, &filenames, usage) kubectl.AddJsonFilenameFlag(cmd, &filenames, usage)
cmd.MarkFlagRequired("filename") cmd.MarkFlagRequired("filename")
// TODO: re-enable --patch and make it use strategic-merge-patch cmd.Flags().String("patch", "", "A JSON document to override the existing resource. The resource is downloaded, patched with the JSON, then updated.")
// cmd.Flags().String("patch", "", "A JSON document to override the existing resource. The resource is downloaded, patched with the JSON, then updated.") cmd.MarkFlagRequired("patch")
// cmd.MarkFlagRequired("patch")
return cmd return cmd
} }
...@@ -71,7 +74,7 @@ func RunUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str ...@@ -71,7 +74,7 @@ func RunUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
return err return err
} }
/* patch := cmdutil.GetFlagString(cmd, "patch") patch := cmdutil.GetFlagString(cmd, "patch")
if len(filenames) == 0 && len(patch) == 0 { if len(filenames) == 0 && len(patch) == 0 {
return cmdutil.UsageError(cmd, "Must specify --filename or --patch to update") return cmdutil.UsageError(cmd, "Must specify --filename or --patch to update")
} }
...@@ -87,7 +90,7 @@ func RunUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str ...@@ -87,7 +90,7 @@ func RunUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
} }
fmt.Fprintf(out, "%s\n", name) fmt.Fprintf(out, "%s\n", name)
return nil return nil
} */ }
if len(filenames) == 0 { if len(filenames) == 0 {
return cmdutil.UsageError(cmd, "Must specify --filename to update") return cmdutil.UsageError(cmd, "Must specify --filename to update")
} }
...@@ -154,21 +157,6 @@ func updateWithPatch(cmd *cobra.Command, args []string, f *cmdutil.Factory, patc ...@@ -154,21 +157,6 @@ func updateWithPatch(cmd *cobra.Command, args []string, f *cmdutil.Factory, patc
name, namespace := infos[0].Name, infos[0].Namespace name, namespace := infos[0].Name, infos[0].Namespace
helper := resource.NewHelper(client, mapping) helper := resource.NewHelper(client, mapping)
obj, err := helper.Get(namespace, name) _, err = helper.Patch(namespace, name, api.StrategicMergePatchType, []byte(patch))
if err != nil {
return "", err
}
patchedObj, err := cmdutil.Merge(obj, patch, mapping.Kind)
if err != nil {
return "", err
}
data, err := helper.Codec.Encode(patchedObj)
if err != nil {
return "", err
}
_, err = helper.Update(namespace, name, true, data)
return name, err return name, err
} }
...@@ -17,6 +17,7 @@ limitations under the License. ...@@ -17,6 +17,7 @@ limitations under the License.
package kubectl package kubectl
import ( import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
) )
...@@ -25,6 +26,7 @@ import ( ...@@ -25,6 +26,7 @@ import (
type RESTClient interface { type RESTClient interface {
Get() *client.Request Get() *client.Request
Post() *client.Request Post() *client.Request
Patch(api.PatchType) *client.Request
Delete() *client.Request Delete() *client.Request
Put() *client.Request Put() *client.Request
} }
...@@ -17,6 +17,7 @@ limitations under the License. ...@@ -17,6 +17,7 @@ limitations under the License.
package resource package resource
import ( import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
...@@ -43,11 +44,10 @@ type Helper struct { ...@@ -43,11 +44,10 @@ type Helper struct {
// NewHelper creates a Helper from a ResourceMapping // NewHelper creates a Helper from a ResourceMapping
func NewHelper(client RESTClient, mapping *meta.RESTMapping) *Helper { func NewHelper(client RESTClient, mapping *meta.RESTMapping) *Helper {
return &Helper{ return &Helper{
RESTClient: client, RESTClient: client,
Resource: mapping.Resource, Resource: mapping.Resource,
Codec: mapping.Codec, Codec: mapping.Codec,
Versioner: mapping.MetadataAccessor, Versioner: mapping.MetadataAccessor,
NamespaceScoped: mapping.Scope.Name() == meta.RESTScopeNameNamespace, NamespaceScoped: mapping.Scope.Name() == meta.RESTScopeNameNamespace,
} }
} }
...@@ -133,6 +133,15 @@ func (m *Helper) Create(namespace string, modify bool, data []byte) (runtime.Obj ...@@ -133,6 +133,15 @@ func (m *Helper) Create(namespace string, modify bool, data []byte) (runtime.Obj
func (m *Helper) createResource(c RESTClient, resource, namespace string, data []byte) (runtime.Object, error) { func (m *Helper) createResource(c RESTClient, resource, namespace string, data []byte) (runtime.Object, error) {
return c.Post().NamespaceIfScoped(namespace, m.NamespaceScoped).Resource(resource).Body(data).Do().Get() return c.Post().NamespaceIfScoped(namespace, m.NamespaceScoped).Resource(resource).Body(data).Do().Get()
} }
func (m *Helper) Patch(namespace, name string, pt api.PatchType, data []byte) (runtime.Object, error) {
return m.RESTClient.Patch(pt).
NamespaceIfScoped(namespace, m.NamespaceScoped).
Resource(m.Resource).
Name(name).
Body(data).
Do().
Get()
}
func (m *Helper) Update(namespace, name string, overwrite bool, data []byte) (runtime.Object, error) { func (m *Helper) Update(namespace, name string, overwrite bool, data []byte) (runtime.Object, error) {
c := m.RESTClient c := m.RESTClient
......
...@@ -17,6 +17,7 @@ limitations under the License. ...@@ -17,6 +17,7 @@ limitations under the License.
package resource package resource
import ( import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
) )
...@@ -26,6 +27,7 @@ import ( ...@@ -26,6 +27,7 @@ import (
type RESTClient interface { type RESTClient interface {
Get() *client.Request Get() *client.Request
Post() *client.Request Post() *client.Request
Patch(api.PatchType) *client.Request
Delete() *client.Request Delete() *client.Request
Put() *client.Request Put() *client.Request
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment