From 3f79e4fa25eb1069b2f11e1222a985202699a658 Mon Sep 17 00:00:00 2001 From: Chmouel Boudjnah Date: Wed, 12 Feb 2020 22:35:49 +0100 Subject: [PATCH 1/3] Add --keep to --all, to keep the last N pipelineruns Closes #718 Signed-off-by: Chmouel Boudjnah Signed-off-by: Vincent Demeester --- docs/cmd/tkn_pipelinerun_delete.md | 1 + docs/man/man1/tkn-pipelinerun-delete.1 | 4 ++++ pkg/cmd/pipelinerun/delete.go | 19 +++++++++++++++---- pkg/cmd/pipelinerun/delete_test.go | 16 ++++++++++++++++ pkg/helper/options/delete.go | 16 ++++++++++++++-- 5 files changed, 50 insertions(+), 6 deletions(-) diff --git a/docs/cmd/tkn_pipelinerun_delete.md b/docs/cmd/tkn_pipelinerun_delete.md index 6fff0a576..fdc521287 100644 --- a/docs/cmd/tkn_pipelinerun_delete.md +++ b/docs/cmd/tkn_pipelinerun_delete.md @@ -32,6 +32,7 @@ or --allow-missing-template-keys If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats. (default true) -f, --force Whether to force deletion (default: false) -h, --help help for delete + --keep int Keep n least recent number of pipelineruns when deleting alls -o, --output string Output format. One of: json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-file. -p, --pipeline string The name of a pipeline whose pipelineruns should be deleted (does not delete the pipeline) --template string Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview]. diff --git a/docs/man/man1/tkn-pipelinerun-delete.1 b/docs/man/man1/tkn-pipelinerun-delete.1 index ba7c03c05..c6ec94ce1 100644 --- a/docs/man/man1/tkn-pipelinerun-delete.1 +++ b/docs/man/man1/tkn-pipelinerun-delete.1 @@ -35,6 +35,10 @@ Delete pipelineruns in a namespace \fB\-h\fP, \fB\-\-help\fP[=false] help for delete +.PP +\fB\-\-keep\fP=0 + Keep n least recent number of pipelineruns when deleting alls + .PP \fB\-o\fP, \fB\-\-output\fP="" Output format. One of: json|yaml|name|go\-template|go\-template\-file|template|templatefile|jsonpath|jsonpath\-file. diff --git a/pkg/cmd/pipelinerun/delete.go b/pkg/cmd/pipelinerun/delete.go index 6291104dc..6d4b8e995 100644 --- a/pkg/cmd/pipelinerun/delete.go +++ b/pkg/cmd/pipelinerun/delete.go @@ -22,6 +22,7 @@ import ( "github.com/tektoncd/cli/pkg/cli" "github.com/tektoncd/cli/pkg/helper/deleter" "github.com/tektoncd/cli/pkg/helper/options" + prhsort "github.com/tektoncd/cli/pkg/helper/pipelinerun/sort" validate "github.com/tektoncd/cli/pkg/helper/validate" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" cliopts "k8s.io/cli-runtime/pkg/genericclioptions" @@ -70,6 +71,7 @@ or f.AddFlags(c) c.Flags().BoolVarP(&opts.ForceDelete, "force", "f", false, "Whether to force deletion (default: false)") c.Flags().StringVarP(&opts.ParentResourceName, "pipeline", "p", "", "The name of a pipeline whose pipelineruns should be deleted (does not delete the pipeline)") + c.Flags().IntVarP(&opts.Keep, "keep", "", 0, "Keep n least recent number of pipelineruns when deleting alls") c.Flags().BoolVarP(&opts.DeleteAllNs, "all", "", false, "Delete all pipelineruns in a namespace (default: false)") _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_pipelinerun") return c @@ -86,7 +88,7 @@ func deletePipelineRuns(s *cli.Stream, p cli.Params, prNames []string, opts *opt d = deleter.New("PipelineRun", func(pipelineRunName string) error { return cs.Tekton.TektonV1alpha1().PipelineRuns(p.Namespace()).Delete(pipelineRunName, &metav1.DeleteOptions{}) }) - prs, err := allPipelineRunNames(p, cs) + prs, err := allPipelineRunNames(p, cs, opts.Keep) if err != nil { return err } @@ -109,7 +111,11 @@ func deletePipelineRuns(s *cli.Stream, p cli.Params, prNames []string, opts *opt d.PrintSuccesses(s) } else if opts.DeleteAllNs { if d.Errors() == nil { - fmt.Fprintf(s.Out, "All PipelineRuns deleted in namespace %q\n", p.Namespace()) + if opts.Keep > 0 { + fmt.Fprintf(s.Out, "All but %d PipelineRuns deleted in namespace %q\n", opts.Keep, p.Namespace()) + } else { + fmt.Fprintf(s.Out, "All PipelineRuns deleted in namespace %q\n", p.Namespace()) + } } } return d.Errors() @@ -132,13 +138,18 @@ func pipelineRunLister(p cli.Params, cs *cli.Clients) func(string) ([]string, er } } -func allPipelineRunNames(p cli.Params, cs *cli.Clients) ([]string, error) { +func allPipelineRunNames(p cli.Params, cs *cli.Clients, keep int) ([]string, error) { pipelineRuns, err := cs.Tekton.TektonV1alpha1().PipelineRuns(p.Namespace()).List(metav1.ListOptions{}) if err != nil { return nil, err } var names []string - for _, pr := range pipelineRuns.Items { + var counter = 0 + for _, pr := range prhsort.SortPipelineRunsByStartTime(pipelineRuns.Items) { + if keep > 0 && counter != keep { + counter++ + continue + } names = append(names, pr.Name) } return names, nil diff --git a/pkg/cmd/pipelinerun/delete_test.go b/pkg/cmd/pipelinerun/delete_test.go index 8d80a89ea..45f4666ab 100644 --- a/pkg/cmd/pipelinerun/delete_test.go +++ b/pkg/cmd/pipelinerun/delete_test.go @@ -193,6 +193,22 @@ func TestPipelineRunDelete(t *testing.T) { wantError: false, want: "All PipelineRuns deleted in namespace \"ns\"\n", }, + { + name: "Delete all keeping 2", + command: []string{"delete", "--all", "-f", "--keep", "2", "-n", "ns"}, + input: seeds[4], + inputStream: nil, + wantError: false, + want: "All but 2 PipelineRuns deleted in namespace \"ns\"\n", + }, + { + name: "Keep -1 is a no go", + command: []string{"delete", "--all", "-f", "--keep", "-1", "-n", "ns"}, + input: seeds[4], + inputStream: nil, + wantError: true, + want: "keep option should not be lower than 0", + }, { name: "Error from using pipelinerun name with --all", command: []string{"delete", "pipelinerun", "--all", "-n", "ns"}, diff --git a/pkg/helper/options/delete.go b/pkg/helper/options/delete.go index 36d317691..ecdb3398a 100644 --- a/pkg/helper/options/delete.go +++ b/pkg/helper/options/delete.go @@ -31,9 +31,13 @@ type DeleteOptions struct { DeleteRelated bool DeleteAllNs bool DeleteAll bool + Keep int } func (o *DeleteOptions) CheckOptions(s *cli.Stream, resourceNames []string, ns string) error { + if o.Keep > 0 && !(o.DeleteAllNs || o.DeleteAll) { + return fmt.Errorf("must provide pipelineruns to delete or --pipeline flag") + } // make sure no resource names are provided when using --all flag if len(resourceNames) > 0 && (o.DeleteAllNs || o.DeleteAll) { return fmt.Errorf("--all flag should not have any arguments or flags specified with it") @@ -51,17 +55,25 @@ func (o *DeleteOptions) CheckOptions(s *cli.Stream, resourceNames []string, ns s return fmt.Errorf("must provide %s name(s) or use --all flag with delete", o.Resource) } + if o.Keep < 0 { + return fmt.Errorf("keep option should not be lower than 0") + } + if o.ForceDelete { return nil } formattedNames := names.QuotedList(resourceNames) + keepStr := "" + if o.Keep > 0 { + keepStr = fmt.Sprintf(" keeping %d %ss", o.Keep, o.Resource) + } switch { case o.DeleteAllNs: - fmt.Fprintf(s.Out, "Are you sure you want to delete all %ss in namespace %q (y/n): ", o.Resource, ns) + fmt.Fprintf(s.Out, "Are you sure you want to delete all %ss in namespace %q%s (y/n): ", o.Resource, ns, keepStr) case o.DeleteAll: - fmt.Fprintf(s.Out, "Are you sure you want to delete all %ss (y/n): ", o.Resource) + fmt.Fprintf(s.Out, "Are you sure you want to delete all %ss%s (y/n): ", o.Resource, keepStr) case o.ParentResource != "" && o.ParentResourceName != "": fmt.Fprintf(s.Out, "Are you sure you want to delete all %ss related to %s %q (y/n): ", o.Resource, o.ParentResource, o.ParentResourceName) case o.DeleteRelated: From 82702636d28c5d41d9a8579f3cb954b80cf32abe Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Thu, 27 Feb 2020 15:25:18 +0100 Subject: [PATCH 2/3] Add --keep to --all, to keep the last N taskruns Closes #718 Signed-off-by: Vincent Demeester --- docs/cmd/tkn_taskrun_delete.md | 1 + docs/man/man1/tkn-taskrun-delete.1 | 4 ++++ pkg/cmd/taskrun/delete.go | 16 +++++++++++++--- pkg/cmd/taskrun/delete_test.go | 16 ++++++++++++++++ 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/docs/cmd/tkn_taskrun_delete.md b/docs/cmd/tkn_taskrun_delete.md index 69bf04b96..003437528 100644 --- a/docs/cmd/tkn_taskrun_delete.md +++ b/docs/cmd/tkn_taskrun_delete.md @@ -32,6 +32,7 @@ or --allow-missing-template-keys If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats. (default true) -f, --force Whether to force deletion (default: false) -h, --help help for delete + --keep int Keep n least recent number of pipelineruns when deleting alls -o, --output string Output format. One of: json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-file. -t, --task string The name of a task whose taskruns should be deleted (does not delete the task) --template string Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview]. diff --git a/docs/man/man1/tkn-taskrun-delete.1 b/docs/man/man1/tkn-taskrun-delete.1 index 3f2a88586..4d93b5076 100644 --- a/docs/man/man1/tkn-taskrun-delete.1 +++ b/docs/man/man1/tkn-taskrun-delete.1 @@ -35,6 +35,10 @@ Delete taskruns in a namespace \fB\-h\fP, \fB\-\-help\fP[=false] help for delete +.PP +\fB\-\-keep\fP=0 + Keep n least recent number of pipelineruns when deleting alls + .PP \fB\-o\fP, \fB\-\-output\fP="" Output format. One of: json|yaml|name|go\-template|go\-template\-file|template|templatefile|jsonpath|jsonpath\-file. diff --git a/pkg/cmd/taskrun/delete.go b/pkg/cmd/taskrun/delete.go index 7919e417f..a64f8ff37 100644 --- a/pkg/cmd/taskrun/delete.go +++ b/pkg/cmd/taskrun/delete.go @@ -71,6 +71,7 @@ or c.Flags().BoolVarP(&opts.ForceDelete, "force", "f", false, "Whether to force deletion (default: false)") c.Flags().StringVarP(&opts.ParentResourceName, "task", "t", "", "The name of a task whose taskruns should be deleted (does not delete the task)") c.Flags().BoolVarP(&opts.DeleteAllNs, "all", "", false, "Delete all taskruns in a namespace (default: false)") + c.Flags().IntVarP(&opts.Keep, "keep", "", 0, "Keep n least recent number of pipelineruns when deleting alls") _ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_taskrun") return c } @@ -86,7 +87,7 @@ func deleteTaskRuns(s *cli.Stream, p cli.Params, trNames []string, opts *options d = deleter.New("TaskRun", func(taskRunName string) error { return cs.Tekton.TektonV1alpha1().TaskRuns(p.Namespace()).Delete(taskRunName, &metav1.DeleteOptions{}) }) - trs, err := allTaskRunNames(p, cs) + trs, err := allTaskRunNames(p, cs, opts.Keep) if err != nil { return err } @@ -109,7 +110,11 @@ func deleteTaskRuns(s *cli.Stream, p cli.Params, trNames []string, opts *options d.PrintSuccesses(s) } else if opts.DeleteAllNs { if d.Errors() == nil { - fmt.Fprintf(s.Out, "All TaskRuns deleted in namespace %q\n", p.Namespace()) + if opts.Keep > 0 { + fmt.Fprintf(s.Out, "All but %d TaskRuns deleted in namespace %q\n", opts.Keep, p.Namespace()) + } else { + fmt.Fprintf(s.Out, "All TaskRuns deleted in namespace %q\n", p.Namespace()) + } } } return d.Errors() @@ -132,13 +137,18 @@ func taskRunLister(p cli.Params, cs *cli.Clients) func(string) ([]string, error) } } -func allTaskRunNames(p cli.Params, cs *cli.Clients) ([]string, error) { +func allTaskRunNames(p cli.Params, cs *cli.Clients, keep int) ([]string, error) { taskRuns, err := cs.Tekton.TektonV1alpha1().TaskRuns(p.Namespace()).List(metav1.ListOptions{}) if err != nil { return nil, err } var names []string + var counter = 0 for _, tr := range taskRuns.Items { + if keep > 0 && counter != keep { + counter++ + continue + } names = append(names, tr.Name) } return names, nil diff --git a/pkg/cmd/taskrun/delete_test.go b/pkg/cmd/taskrun/delete_test.go index bd7173c71..9c58c88de 100644 --- a/pkg/cmd/taskrun/delete_test.go +++ b/pkg/cmd/taskrun/delete_test.go @@ -164,6 +164,22 @@ func TestTaskRunDelete(t *testing.T) { wantError: false, want: "All TaskRuns deleted in namespace \"ns\"\n", }, + { + name: "Delete all keeping 2", + command: []string{"delete", "--all", "-f", "--keep", "2", "-n", "ns"}, + input: seeds[4], + inputStream: nil, + wantError: false, + want: "All but 2 TaskRuns deleted in namespace \"ns\"\n", + }, + { + name: "Keep -1 is a no go", + command: []string{"delete", "--all", "-f", "--keep", "-1", "-n", "ns"}, + input: seeds[4], + inputStream: nil, + wantError: true, + want: "keep option should not be lower than 0", + }, { name: "Error from using taskrun name with --all", command: []string{"delete", "taskrun", "--all", "-n", "ns"}, From ab2e8e0e679cda43ac7ba6874c466021da092686 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Thu, 27 Feb 2020 16:10:43 +0100 Subject: [PATCH 3/3] =?UTF-8?q?Enhance=20the=20error=20message=20for=20--k?= =?UTF-8?q?eep=20=E2=8C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Vincent Demeester --- pkg/helper/options/delete.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/helper/options/delete.go b/pkg/helper/options/delete.go index ecdb3398a..8c6540849 100644 --- a/pkg/helper/options/delete.go +++ b/pkg/helper/options/delete.go @@ -36,7 +36,7 @@ type DeleteOptions struct { func (o *DeleteOptions) CheckOptions(s *cli.Stream, resourceNames []string, ns string) error { if o.Keep > 0 && !(o.DeleteAllNs || o.DeleteAll) { - return fmt.Errorf("must provide pipelineruns to delete or --pipeline flag") + return fmt.Errorf("must use --all flag with --keep") } // make sure no resource names are provided when using --all flag if len(resourceNames) > 0 && (o.DeleteAllNs || o.DeleteAll) {