Skip to content

Commit

Permalink
Delete fails on notfound errors.
Browse files Browse the repository at this point in the history
If deleting multiple resources, command will continue on error and
report not found resources at the end.
  • Loading branch information
j3ffml committed May 27, 2015
1 parent 0bea034 commit 3cf4d9b
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 31 deletions.
2 changes: 2 additions & 0 deletions contrib/completions/bash/kubectl
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ _kubectl_delete()
flags+=("--grace-period=")
flags+=("--help")
flags+=("-h")
flags+=("--ignore-not-found")
flags+=("--selector=")
two_word_flags+=("-l")

Expand Down Expand Up @@ -591,6 +592,7 @@ _kubectl_stop()
flags+=("--grace-period=")
flags+=("--help")
flags+=("-h")
flags+=("--ignore-not-found")
flags+=("--selector=")
two_word_flags+=("-l")

Expand Down
9 changes: 5 additions & 4 deletions docs/kubectl_delete.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ $ kubectl delete pods --all
### Options

```
--all=false: [-all] to select all the specified resources
--all=false: [-all] to select all the specified resources.
--cascade=true: If true, cascade the delete resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.
-f, --filename=[]: Filename, directory, or URL to a file containing the resource to delete
-f, --filename=[]: Filename, directory, or URL to a file containing the resource to delete.
--grace-period=-1: Period of time in seconds given to the resource to terminate gracefully. Ignored if negative.
-h, --help=false: help for delete
-l, --selector="": Selector (label query) to filter on
--ignore-not-found=false: Treat "resource not found" as a successful delete.
-l, --selector="": Selector (label query) to filter on.
```

### Options inherited from parent commands
Expand Down Expand Up @@ -82,6 +83,6 @@ $ kubectl delete pods --all
### SEE ALSO
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager

###### Auto generated by spf13/cobra at 2015-05-21 10:33:11.18056941 +0000 UTC
###### Auto generated by spf13/cobra at 2015-05-21 18:30:45.437003409 +0000 UTC

[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/kubectl_delete.md?pixel)]()
9 changes: 5 additions & 4 deletions docs/kubectl_stop.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ $ kubectl stop -f path/to/resources
### Options

```
--all=false: [-all] to select all the specified resources
-f, --filename=[]: Filename, directory, or URL to file of resource(s) to be stopped
--all=false: [-all] to select all the specified resources.
-f, --filename=[]: Filename, directory, or URL to file of resource(s) to be stopped.
--grace-period=-1: Period of time in seconds given to the resource to terminate gracefully. Ignored if negative.
-h, --help=false: help for stop
-l, --selector="": Selector (label query) to filter on
--ignore-not-found=false: Treat "resource not found" as a successful stop.
-l, --selector="": Selector (label query) to filter on.
```

### Options inherited from parent commands
Expand Down Expand Up @@ -72,6 +73,6 @@ $ kubectl stop -f path/to/resources
### SEE ALSO
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager

###### Auto generated by spf13/cobra at 2015-05-21 10:33:11.190996891 +0000 UTC
###### Auto generated by spf13/cobra at 2015-05-21 18:30:45.439945376 +0000 UTC

[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/kubectl_stop.md?pixel)]()
10 changes: 7 additions & 3 deletions docs/man/man1/kubectl-delete.1
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ will be lost along with the rest of the resource.
.SH OPTIONS
.PP
\fB\-\-all\fP=false
[\-all] to select all the specified resources
[\-all] to select all the specified resources.

.PP
\fB\-\-cascade\fP=true
If true, cascade the delete resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.

.PP
\fB\-f\fP, \fB\-\-filename\fP=[]
Filename, directory, or URL to a file containing the resource to delete
Filename, directory, or URL to a file containing the resource to delete.

.PP
\fB\-\-grace\-period\fP=\-1
Expand All @@ -49,9 +49,13 @@ will be lost along with the rest of the resource.
\fB\-h\fP, \fB\-\-help\fP=false
help for delete

.PP
\fB\-\-ignore\-not\-found\fP=false
Treat "resource not found" as a successful delete.

.PP
\fB\-l\fP, \fB\-\-selector\fP=""
Selector (label query) to filter on
Selector (label query) to filter on.


.SH OPTIONS INHERITED FROM PARENT COMMANDS
Expand Down
10 changes: 7 additions & 3 deletions docs/man/man1/kubectl-stop.1
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ If the resource is scalable it will be scaled to 0 before deletion.
.SH OPTIONS
.PP
\fB\-\-all\fP=false
[\-all] to select all the specified resources
[\-all] to select all the specified resources.

.PP
\fB\-f\fP, \fB\-\-filename\fP=[]
Filename, directory, or URL to file of resource(s) to be stopped
Filename, directory, or URL to file of resource(s) to be stopped.

.PP
\fB\-\-grace\-period\fP=\-1
Expand All @@ -37,9 +37,13 @@ If the resource is scalable it will be scaled to 0 before deletion.
\fB\-h\fP, \fB\-\-help\fP=false
help for stop

.PP
\fB\-\-ignore\-not\-found\fP=false
Treat "resource not found" as a successful stop.

.PP
\fB\-l\fP, \fB\-\-selector\fP=""
Selector (label query) to filter on
Selector (label query) to filter on.


.SH OPTIONS INHERITED FROM PARENT COMMANDS
Expand Down
2 changes: 1 addition & 1 deletion hooks/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ if ! hack/verify-gendocs.sh > /dev/null; then
echo "${red}ERROR!"
echo "Some docs are out of sync between CLI and markdown."
echo "To regenerate docs, run:"
echo " hack/run-gendocs.sh > docs/kubectl.md"
echo " hack/run-gendocs.sh"
exit_code=1
else
echo "${green}OK"
Expand Down
28 changes: 18 additions & 10 deletions pkg/kubectl/cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@ func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.CheckErr(err)
},
}
usage := "Filename, directory, or URL to a file containing the resource to delete"
usage := "Filename, directory, or URL to a file containing the resource to delete."
kubectl.AddJsonFilenameFlag(cmd, &filenames, usage)
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
cmd.Flags().Bool("all", false, "[-all] to select all the specified resources")
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on.")
cmd.Flags().Bool("all", false, "[-all] to select all the specified resources.")
cmd.Flags().Bool("ignore-not-found", false, "Treat \"resource not found\" as a successful delete.")
cmd.Flags().Bool("cascade", true, "If true, cascade the delete resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.")
cmd.Flags().Int("grace-period", -1, "Period of time in seconds given to the resource to terminate gracefully. Ignored if negative.")
return cmd
Expand All @@ -98,20 +99,24 @@ func RunDelete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
return err
}

ignoreNotFound := cmdutil.GetFlagBool(cmd, "ignore-not-found")
// By default use a reaper to delete all related resources.
if cmdutil.GetFlagBool(cmd, "cascade") {
return ReapResult(r, f, out, cmdutil.GetFlagBool(cmd, "cascade"), cmdutil.GetFlagInt(cmd, "grace-period"))
return ReapResult(r, f, out, cmdutil.GetFlagBool(cmd, "cascade"), ignoreNotFound, cmdutil.GetFlagInt(cmd, "grace-period"))
}
return DeleteResult(r, out)
return DeleteResult(r, out, ignoreNotFound)
}

func ReapResult(r *resource.Result, f *cmdutil.Factory, out io.Writer, isDefaultDelete bool, gracePeriod int) error {
func ReapResult(r *resource.Result, f *cmdutil.Factory, out io.Writer, isDefaultDelete, ignoreNotFound bool, gracePeriod int) error {
found := 0
err := r.IgnoreErrors(errors.IsNotFound).Visit(func(info *resource.Info) error {
if ignoreNotFound {
r = r.IgnoreErrors(errors.IsNotFound)
}
err := r.Visit(func(info *resource.Info) error {
found++
reaper, err := f.Reaper(info.Mapping)
if err != nil {
// If the error is "not found" and the user didn't explicitly ask for stop.
// If there is no reaper for this resources and the user didn't explicitly ask for stop.
if kubectl.IsNoSuchReaperError(err) && isDefaultDelete {
return deleteResource(info, out)
}
Expand All @@ -136,9 +141,12 @@ func ReapResult(r *resource.Result, f *cmdutil.Factory, out io.Writer, isDefault
return nil
}

func DeleteResult(r *resource.Result, out io.Writer) error {
func DeleteResult(r *resource.Result, out io.Writer, ignoreNotFound bool) error {
found := 0
err := r.IgnoreErrors(errors.IsNotFound).Visit(func(info *resource.Info) error {
if ignoreNotFound {
r = r.IgnoreErrors(errors.IsNotFound)
}
err := r.Visit(func(info *resource.Info) error {
found++
return deleteResource(info, out)
})
Expand Down
41 changes: 39 additions & 2 deletions pkg/kubectl/cmd/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@ package cmd

import (
"bytes"
"fmt"
"net/http"
"strings"
"testing"

"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)

func TestDeleteObjectByTuple(t *testing.T) {
Expand Down Expand Up @@ -120,6 +123,34 @@ func TestDeleteObject(t *testing.T) {
}
}

func TestDeleteObjectNotFound(t *testing.T) {
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/redis-master" && m == "DELETE":
return &http.Response{StatusCode: 404, Body: stringBody("")}, nil
default:
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("filename", "../../../examples/guestbook/redis-master-controller.json")
cmd.Flags().Set("cascade", "false")
filenames := cmd.Flags().Lookup("filename").Value.(*util.StringList)
err := RunDelete(f, buf, cmd, []string{}, *filenames)
if err == nil || !errors.IsNotFound(err) {
t.Errorf("unexpected error: expected NotFound, got %v", err)
}
}

func TestDeleteObjectIgnoreNotFound(t *testing.T) {
f, tf, codec := NewAPIFactory()
tf.Printer = &testPrinter{}
Expand All @@ -141,6 +172,7 @@ func TestDeleteObjectIgnoreNotFound(t *testing.T) {
cmd := NewCmdDelete(f, buf)
cmd.Flags().Set("filename", "../../../examples/guestbook/redis-master-controller.json")
cmd.Flags().Set("cascade", "false")
cmd.Flags().Set("ignore-not-found", "true")
cmd.Run(cmd, []string{})

if buf.String() != "" {
Expand Down Expand Up @@ -181,7 +213,7 @@ func TestDeleteMultipleObject(t *testing.T) {
}
}

func TestDeleteMultipleObjectIgnoreMissing(t *testing.T) {
func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) {
_, svc, _ := testData()

f, tf, codec := NewAPIFactory()
Expand All @@ -207,7 +239,12 @@ func TestDeleteMultipleObjectIgnoreMissing(t *testing.T) {
cmd.Flags().Set("filename", "../../../examples/guestbook/redis-master-controller.json")
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
cmd.Flags().Set("cascade", "false")
cmd.Run(cmd, []string{})
filenames := cmd.Flags().Lookup("filename").Value.(*util.StringList)
fmt.Printf("filenames: %v\n", filenames)
err := RunDelete(f, buf, cmd, []string{}, *filenames)
if err == nil || !errors.IsNotFound(err) {
t.Errorf("unexpected error: expected NotFound, got %v", err)
}

if buf.String() != "services/frontend\n" {
t.Errorf("unexpected output: %s", buf.String())
Expand Down
9 changes: 5 additions & 4 deletions pkg/kubectl/cmd/stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,11 @@ func NewCmdStop(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.CheckErr(RunStop(f, cmd, args, flags.Filenames, out))
},
}
usage := "Filename, directory, or URL to file of resource(s) to be stopped"
usage := "Filename, directory, or URL to file of resource(s) to be stopped."
kubectl.AddJsonFilenameFlag(cmd, &flags.Filenames, usage)
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
cmd.Flags().Bool("all", false, "[-all] to select all the specified resources")
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on.")
cmd.Flags().Bool("all", false, "[-all] to select all the specified resources.")
cmd.Flags().Bool("ignore-not-found", false, "Treat \"resource not found\" as a successful stop.")
cmd.Flags().Int("grace-period", -1, "Period of time in seconds given to the resource to terminate gracefully. Ignored if negative.")
return cmd
}
Expand All @@ -83,5 +84,5 @@ func RunStop(f *cmdutil.Factory, cmd *cobra.Command, args []string, filenames ut
if r.Err() != nil {
return r.Err()
}
return ReapResult(r, f, out, false, cmdutil.GetFlagInt(cmd, "grace-period"))
return ReapResult(r, f, out, false, cmdutil.GetFlagBool(cmd, "ignore-not-found"), cmdutil.GetFlagInt(cmd, "grace-period"))
}

0 comments on commit 3cf4d9b

Please sign in to comment.