mirror of https://github.com/k3s-io/k3s
Allow delete multiple resources with the same name
parent
ebe50ea692
commit
943c57ff4e
|
@ -174,6 +174,9 @@ $ kubectl delete \-f ./pod.json
|
||||||
# Delete a pod based on the type and name in the JSON passed into stdin.
|
# Delete a pod based on the type and name in the JSON passed into stdin.
|
||||||
$ cat pod.json | kubectl delete \-f \-
|
$ cat pod.json | kubectl delete \-f \-
|
||||||
|
|
||||||
|
# Delete pods and services with same names "baz" and "foo"
|
||||||
|
$ kubectl delete pod,service baz foo
|
||||||
|
|
||||||
# Delete pods and services with label name=myLabel.
|
# Delete pods and services with label name=myLabel.
|
||||||
$ kubectl delete pods,services \-l name=myLabel
|
$ kubectl delete pods,services \-l name=myLabel
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,9 @@ $ kubectl delete -f ./pod.json
|
||||||
# Delete a pod based on the type and name in the JSON passed into stdin.
|
# Delete a pod based on the type and name in the JSON passed into stdin.
|
||||||
$ cat pod.json | kubectl delete -f -
|
$ cat pod.json | kubectl delete -f -
|
||||||
|
|
||||||
|
# Delete pods and services with same names "baz" and "foo"
|
||||||
|
$ kubectl delete pod,service baz foo
|
||||||
|
|
||||||
# Delete pods and services with label name=myLabel.
|
# Delete pods and services with label name=myLabel.
|
||||||
$ kubectl delete pods,services -l name=myLabel
|
$ kubectl delete pods,services -l name=myLabel
|
||||||
|
|
||||||
|
@ -118,7 +121,7 @@ $ kubectl delete pods --all
|
||||||
|
|
||||||
* [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-08-20 22:01:12.476048394 +0000 UTC
|
###### Auto generated by spf13/cobra at 2015-08-21 06:18:47.444397685 +0000 UTC
|
||||||
|
|
||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_delete.md?pixel)]()
|
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_delete.md?pixel)]()
|
||||||
|
|
|
@ -47,6 +47,9 @@ $ kubectl delete -f ./pod.json
|
||||||
# Delete a pod based on the type and name in the JSON passed into stdin.
|
# Delete a pod based on the type and name in the JSON passed into stdin.
|
||||||
$ cat pod.json | kubectl delete -f -
|
$ cat pod.json | kubectl delete -f -
|
||||||
|
|
||||||
|
# Delete pods and services with same names "baz" and "foo"
|
||||||
|
$ kubectl delete pod,service baz foo
|
||||||
|
|
||||||
# Delete pods and services with label name=myLabel.
|
# Delete pods and services with label name=myLabel.
|
||||||
$ kubectl delete pods,services -l name=myLabel
|
$ kubectl delete pods,services -l name=myLabel
|
||||||
|
|
||||||
|
|
|
@ -335,6 +335,41 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeleteMultipleResourcesWithTheSameName(t *testing.T) {
|
||||||
|
_, svc, rc := 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/replicationcontrollers/baz" && m == "DELETE":
|
||||||
|
return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil
|
||||||
|
case p == "/namespaces/test/replicationcontrollers/foo" && m == "DELETE":
|
||||||
|
return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil
|
||||||
|
case p == "/namespaces/test/services/baz" && m == "DELETE":
|
||||||
|
return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil
|
||||||
|
case p == "/namespaces/test/services/foo" && m == "DELETE":
|
||||||
|
return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil
|
||||||
|
default:
|
||||||
|
// Ensures no GET is performed when deleting by name
|
||||||
|
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
tf.Namespace = "test"
|
||||||
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
cmd := NewCmdDelete(f, buf)
|
||||||
|
cmd.Flags().Set("namespace", "test")
|
||||||
|
cmd.Flags().Set("cascade", "false")
|
||||||
|
cmd.Flags().Set("output", "name")
|
||||||
|
cmd.Run(cmd, []string{"replicationcontrollers,services", "baz", "foo"})
|
||||||
|
if buf.String() != "replicationcontroller/baz\nreplicationcontroller/foo\nservice/baz\nservice/foo\n" {
|
||||||
|
t.Errorf("unexpected output: %s", buf.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDeleteDirectory(t *testing.T) {
|
func TestDeleteDirectory(t *testing.T) {
|
||||||
_, svc, rc := testData()
|
_, svc, rc := testData()
|
||||||
|
|
||||||
|
|
|
@ -256,6 +256,23 @@ func (b *Builder) SelectAllParam(selectAll bool) *Builder {
|
||||||
// When two or more arguments are received, they must be a single type and resource name(s).
|
// When two or more arguments are received, they must be a single type and resource name(s).
|
||||||
// The allowEmptySelector permits to select all the resources (via Everything func).
|
// The allowEmptySelector permits to select all the resources (via Everything func).
|
||||||
func (b *Builder) ResourceTypeOrNameArgs(allowEmptySelector bool, args ...string) *Builder {
|
func (b *Builder) ResourceTypeOrNameArgs(allowEmptySelector bool, args ...string) *Builder {
|
||||||
|
// convert multiple resources to resource tuples, a,b,c d as a transform to a/d b/d c/d
|
||||||
|
if len(args) >= 2 {
|
||||||
|
resources := []string{}
|
||||||
|
resources = append(resources, SplitResourceArgument(args[0])...)
|
||||||
|
if len(resources) > 1 {
|
||||||
|
names := []string{}
|
||||||
|
names = append(names, args[1:]...)
|
||||||
|
newArgs := []string{}
|
||||||
|
for _, resource := range resources {
|
||||||
|
for _, name := range names {
|
||||||
|
newArgs = append(newArgs, strings.Join([]string{resource, name}, "/"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
args = newArgs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ok, err := hasCombinedTypeArgs(args); ok {
|
if ok, err := hasCombinedTypeArgs(args); ok {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.errs = append(b.errs, err)
|
b.errs = append(b.errs, err)
|
||||||
|
|
|
@ -380,6 +380,38 @@ func TestResourceByName(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMultipleResourceByTheSameName(t *testing.T) {
|
||||||
|
pods, svcs := testData()
|
||||||
|
b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClientWith("", t, map[string]string{
|
||||||
|
"/namespaces/test/pods/foo": runtime.EncodeOrDie(latest.Codec, &pods.Items[0]),
|
||||||
|
"/namespaces/test/pods/baz": runtime.EncodeOrDie(latest.Codec, &pods.Items[1]),
|
||||||
|
"/namespaces/test/services/foo": runtime.EncodeOrDie(latest.Codec, &svcs.Items[0]),
|
||||||
|
"/namespaces/test/services/baz": runtime.EncodeOrDie(latest.Codec, &svcs.Items[0]),
|
||||||
|
})).
|
||||||
|
NamespaceParam("test")
|
||||||
|
|
||||||
|
test := &testVisitor{}
|
||||||
|
singular := false
|
||||||
|
|
||||||
|
if b.Do().Err() == nil {
|
||||||
|
t.Errorf("unexpected non-error")
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResourceTypeOrNameArgs(true, "pods,services", "foo", "baz")
|
||||||
|
|
||||||
|
err := b.Do().IntoSingular(&singular).Visit(test.Handle)
|
||||||
|
if err != nil || singular || len(test.Infos) != 4 {
|
||||||
|
t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos)
|
||||||
|
}
|
||||||
|
if !api.Semantic.DeepDerivative([]runtime.Object{&pods.Items[0], &pods.Items[1], &svcs.Items[0], &svcs.Items[0]}, test.Objects()) {
|
||||||
|
t.Errorf("unexpected visited objects: %#v", test.Objects())
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := b.Do().ResourceMapping(); err == nil {
|
||||||
|
t.Errorf("unexpected non-error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestResourceByNameWithoutRequireObject(t *testing.T) {
|
func TestResourceByNameWithoutRequireObject(t *testing.T) {
|
||||||
b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClientWith("", t, map[string]string{})).
|
b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClientWith("", t, map[string]string{})).
|
||||||
NamespaceParam("test")
|
NamespaceParam("test")
|
||||||
|
|
Loading…
Reference in New Issue