diff --git a/docs/kubectl.md b/docs/kubectl.md index db3f856dee3..a3243ceefaf 100644 --- a/docs/kubectl.md +++ b/docs/kubectl.md @@ -236,6 +236,9 @@ Examples: $ cat pod.json | kubectl update -f - + + $ kubectl update pods my-pod --patch='{ "labels": { "foo": "bar" } }' + Usage: ``` @@ -261,6 +264,7 @@ Usage: --match-server-version=false: Require server version to match client version -n, --namespace="": If present, the namespace scope for this CLI request. --ns-path="/home/username/.kubernetes_ns": Path to the namespace info file that holds the namespace context to use for CLI requests. + --patch="": A JSON document to override the existing resource. The resource is downloaded, then patched with the JSON, the re-updated -s, --server="": The address of the Kubernetes API server --stderrthreshold=2: logs at or above this threshold go to stderr --token="": Bearer token for authentication to the API server. diff --git a/pkg/kubectl/cmd/update.go b/pkg/kubectl/cmd/update.go index 13403b20bf1..b09bab95146 100644 --- a/pkg/kubectl/cmd/update.go +++ b/pkg/kubectl/cmd/update.go @@ -37,27 +37,68 @@ Examples: $ cat pod.json | kubectl update -f - - `, + + + $ kubectl update pods my-pod --patch='{ "labels": { "foo": "bar" } }' + `, Run: func(cmd *cobra.Command, args []string) { filename := GetFlagString(cmd, "filename") - if len(filename) == 0 { - usageError(cmd, "Must specify filename to update") + patch := GetFlagString(cmd, "patch") + if len(filename) == 0 && len(patch) == 0 { + usageError(cmd, "Must specify --filename or --patch to update") + } + if len(filename) != 0 && len(patch) != 0 { + usageError(cmd, "Can not specify both --filename and --patch") + } + var name string + if len(filename) > 0 { + name = updateWithFile(cmd, f, filename) + } else { + name = updateWithPatch(cmd, args, f, patch) } - schema, err := f.Validator(cmd) - checkErr(err) - mapper, typer := f.Object(cmd) - mapping, namespace, name, data := ResourceFromFile(cmd, filename, typer, mapper, schema) - client, err := f.RESTClient(cmd, mapping) - checkErr(err) - - err = CompareNamespaceFromFile(cmd, namespace) - checkErr(err) - - err = resource.NewHelper(client, mapping).Update(namespace, name, true, data) - checkErr(err) fmt.Fprintf(out, "%s\n", name) }, } cmd.Flags().StringP("filename", "f", "", "Filename or URL to file to use to update the resource") + cmd.Flags().String("patch", "", "A JSON document to override the existing resource. The resource is downloaded, then patched with the JSON, the re-updated") return cmd } + +func updateWithPatch(cmd *cobra.Command, args []string, f *Factory, patch string) string { + mapper, _ := f.Object(cmd) + mapping, namespace, name := ResourceFromArgs(cmd, args, mapper) + client, err := f.RESTClient(cmd, mapping) + checkErr(err) + + helper := resource.NewHelper(client, mapping) + obj, err := helper.Get(namespace, name) + checkErr(err) + + Merge(obj, patch, mapping.Kind) + + data, err := helper.Codec.Encode(obj) + checkErr(err) + + err = helper.Update(namespace, name, true, data) + checkErr(err) + return name +} + +func updateWithFile(cmd *cobra.Command, f *Factory, filename string) string { + schema, err := f.Validator(cmd) + checkErr(err) + mapper, typer := f.Object(cmd) + + mapping, namespace, name, data := ResourceFromFile(cmd, filename, typer, mapper, schema) + + client, err := f.RESTClient(cmd, mapping) + checkErr(err) + + err = CompareNamespaceFromFile(cmd, namespace) + checkErr(err) + + err = resource.NewHelper(client, mapping).Update(namespace, name, true, data) + checkErr(err) + + return name +}