mirror of https://github.com/k3s-io/k3s
Merge pull request #12388 from feihujiang/kubectlPatchAcceptFileNameParam
Auto commit by PR queue botpull/6/head
commit
15281a5e01
|
@ -371,6 +371,12 @@ _kubectl_patch()
|
|||
flags_with_completion=()
|
||||
flags_completion=()
|
||||
|
||||
flags+=("--filename=")
|
||||
flags_with_completion+=("--filename")
|
||||
flags_completion+=("__handle_filename_extension_flag json|yaml|yml")
|
||||
two_word_flags+=("-f")
|
||||
flags_with_completion+=("-f")
|
||||
flags_completion+=("__handle_filename_extension_flag json|yaml|yml")
|
||||
flags+=("--help")
|
||||
flags+=("-h")
|
||||
flags+=("--output=")
|
||||
|
|
|
@ -24,6 +24,10 @@ Please refer to the models in
|
|||
|
||||
|
||||
.SH OPTIONS
|
||||
.PP
|
||||
\fB\-f\fP, \fB\-\-filename\fP=[]
|
||||
Filename, directory, or URL to a file identifying the resource to update
|
||||
|
||||
.PP
|
||||
\fB\-h\fP, \fB\-\-help\fP=false
|
||||
help for patch
|
||||
|
@ -144,6 +148,9 @@ Please refer to the models in
|
|||
# Partially update a node using strategic merge patch
|
||||
kubectl patch node k8s\-node\-1 \-p '{"spec":{"unschedulable":true}}'
|
||||
|
||||
# Partially update a node identified by the type and name specified in "node.json" using strategic merge patch
|
||||
kubectl patch \-f node.json \-p '{"spec":{"unschedulable":true}}'
|
||||
|
||||
# Update a container's image; spec.containers[*].name is required because it's a merge key
|
||||
kubectl patch pod valid\-pod \-p '{"spec":{"containers":[{"name":"kubernetes\-serve\-hostname","image":"new image"}]}}'
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ JSON and YAML formats are accepted.
|
|||
Please refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/HEAD/docs/api-reference/definitions.html to find if a field is mutable.
|
||||
|
||||
```
|
||||
kubectl patch TYPE NAME -p PATCH
|
||||
kubectl patch (-f FILENAME | TYPE NAME) -p PATCH
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
@ -55,6 +55,9 @@ kubectl patch TYPE NAME -p PATCH
|
|||
# Partially update a node using strategic merge patch
|
||||
kubectl patch node k8s-node-1 -p '{"spec":{"unschedulable":true}}'
|
||||
|
||||
# Partially update a node identified by the type and name specified in "node.json" using strategic merge patch
|
||||
kubectl patch -f node.json -p '{"spec":{"unschedulable":true}}'
|
||||
|
||||
# Update a container's image; spec.containers[*].name is required because it's a merge key
|
||||
kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve-hostname","image":"new image"}]}}'
|
||||
```
|
||||
|
@ -62,6 +65,7 @@ kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve
|
|||
### Options
|
||||
|
||||
```
|
||||
-f, --filename=[]: Filename, directory, or URL to a file identifying the resource to update
|
||||
-h, --help[=false]: help for patch
|
||||
-o, --output="": Output mode. Use "-o name" for shorter output (resource/name).
|
||||
-p, --patch="": The patch to be applied to the resource JSON file.
|
||||
|
@ -100,7 +104,7 @@ kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve
|
|||
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-08-12 21:51:38.836855054 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-08-13 02:12:21.577994505 +0000 UTC
|
||||
|
||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_patch.md?pixel)]()
|
||||
|
|
|
@ -385,6 +385,11 @@ runTests() {
|
|||
kubectl patch "${kube_flags[@]}" pod valid-pod -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "nginx"}]}}'
|
||||
# Post-condition: valid-pod POD has image nginx
|
||||
kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:'
|
||||
## Patch pod from JSON can change image
|
||||
# Command
|
||||
kubectl patch "${kube_flags[@]}" -f docs/admin/limitrange/valid-pod.yaml -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "kubernetes/pause"}]}}'
|
||||
# Post-condition: valid-pod POD has image kubernetes/pause
|
||||
kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'kubernetes/pause:'
|
||||
|
||||
## --force replace pod can change other field, e.g., spec.container.name
|
||||
# Command
|
||||
|
|
|
@ -17,11 +17,12 @@ limitations under the License.
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||
)
|
||||
|
@ -36,13 +37,16 @@ Please refer to the models in https://htmlpreview.github.io/?https://github.com/
|
|||
# Partially update a node using strategic merge patch
|
||||
kubectl patch node k8s-node-1 -p '{"spec":{"unschedulable":true}}'
|
||||
|
||||
# Partially update a node identified by the type and name specified in "node.json" using strategic merge patch
|
||||
kubectl patch -f node.json -p '{"spec":{"unschedulable":true}}'
|
||||
|
||||
# Update a container's image; spec.containers[*].name is required because it's a merge key
|
||||
kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve-hostname","image":"new image"}]}}'`
|
||||
)
|
||||
|
||||
func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "patch TYPE NAME -p PATCH",
|
||||
Use: "patch (-f FILENAME | TYPE NAME) -p PATCH",
|
||||
Short: "Update field(s) of a resource by stdin.",
|
||||
Long: patch_long,
|
||||
Example: patch_example,
|
||||
|
@ -56,11 +60,14 @@ func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
|||
cmd.Flags().StringP("patch", "p", "", "The patch to be applied to the resource JSON file.")
|
||||
cmd.MarkFlagRequired("patch")
|
||||
cmdutil.AddOutputFlagsForMutation(cmd)
|
||||
|
||||
usage := "Filename, directory, or URL to a file identifying the resource to update"
|
||||
kubectl.AddJsonFilenameFlag(cmd, usage)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool) error {
|
||||
cmdNamespace, _, err := f.DefaultNamespace()
|
||||
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -74,6 +81,7 @@ func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
|
|||
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, cmdutil.GetFlagStringSlice(cmd, "filename")...).
|
||||
ResourceTypeOrNameArgs(false, args...).
|
||||
Flatten().
|
||||
Do()
|
||||
|
@ -81,20 +89,21 @@ func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mapping, err := r.ResourceMapping()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client, err := f.RESTClient(mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
infos, err := r.Infos()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
name, namespace := infos[0].Name, infos[0].Namespace
|
||||
if len(infos) > 1 {
|
||||
return fmt.Errorf("multiple resources provided")
|
||||
}
|
||||
info := infos[0]
|
||||
name, namespace := info.Name, info.Namespace
|
||||
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, []byte(patch))
|
||||
|
|
|
@ -55,3 +55,36 @@ func TestPatchObject(t *testing.T) {
|
|||
t.Errorf("unexpected output: %s", buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestPatchObjectFromFile(t *testing.T) {
|
||||
_, svc, _ := testData()
|
||||
|
||||
f, tf, codec := NewAPIFactory()
|
||||
tf.Printer = &testPrinter{}
|
||||
tf.Client = &client.FakeRESTClient{
|
||||
Codec: codec,
|
||||
Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) {
|
||||
switch p, m := req.URL.Path, req.Method; {
|
||||
case p == "/namespaces/test/services/frontend" && (m == "PATCH" || m == "GET"):
|
||||
return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil
|
||||
default:
|
||||
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
|
||||
return nil, nil
|
||||
}
|
||||
}),
|
||||
}
|
||||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := NewCmdPatch(f, buf)
|
||||
cmd.Flags().Set("namespace", "test")
|
||||
cmd.Flags().Set("patch", `{"spec":{"type":"NodePort"}}`)
|
||||
cmd.Flags().Set("output", "name")
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.yaml")
|
||||
cmd.Run(cmd, []string{})
|
||||
|
||||
// uses the name from the file, not the response
|
||||
if buf.String() != "frontend\n" {
|
||||
t.Errorf("unexpected output: %s", buf.String())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue