From 18338957c45459c3fa3caf1af85684a2370f319c Mon Sep 17 00:00:00 2001 From: Pradeep Murugesan Date: Thu, 17 Oct 2019 12:32:16 +0530 Subject: [PATCH] refactor(kumactl) generalized the delete command in order to use for all resource types Right now the design is to handle the resource types via subcommands. Refactored so that the delete command accepts a resourceType arg. Based on the passed resource type arg the corresponding resource will be deleted. * returns an error in case of no mesh with the given name. Fix #279 --- app/kumactl/cmd/delete/delete.go | 60 +++++++++++++-- app/kumactl/cmd/delete/delete_meshes.go | 44 ----------- app/kumactl/cmd/delete/delete_meshes_test.go | 6 +- app/kumactl/cmd/delete/delete_test.go | 78 ++++++++++++++++++++ 4 files changed, 134 insertions(+), 54 deletions(-) delete mode 100644 app/kumactl/cmd/delete/delete_meshes.go create mode 100644 app/kumactl/cmd/delete/delete_test.go diff --git a/app/kumactl/cmd/delete/delete.go b/app/kumactl/cmd/delete/delete.go index 7ff4f56e4549..bc3ec205361e 100644 --- a/app/kumactl/cmd/delete/delete.go +++ b/app/kumactl/cmd/delete/delete.go @@ -1,23 +1,69 @@ package delete import ( + "context" kumactl_cmd "github.com/Kong/kuma/app/kumactl/pkg/cmd" + "github.com/Kong/kuma/pkg/core/resources/apis/mesh" + "github.com/Kong/kuma/pkg/core/resources/model" + "github.com/Kong/kuma/pkg/core/resources/registry" + "github.com/Kong/kuma/pkg/core/resources/store" + "github.com/pkg/errors" "github.com/spf13/cobra" ) -type deleteContext struct { - *kumactl_cmd.RootContext -} - func NewDeleteCmd(pctx *kumactl_cmd.RootContext) *cobra.Command { - ctx := &deleteContext{RootContext: pctx} cmd := &cobra.Command{ Use: "delete", Short: "Delete Kuma resources", Long: `Delete Kuma resources.`, + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + rs, err := pctx.CurrentResourceStore() + if err != nil { + return err + } + resourceTypeArg := args[0] + name := args[1] + + var resource model.Resource + var resourceType model.ResourceType + switch resourceTypeArg { + case "mesh": + resourceType = model.ResourceType(mesh.MeshType) + + default: + return errors.Errorf("unknown resource type: %s. Allowed types: mesh, dataplane, proxytemplate, traffic-log, traffic-permission", resourceTypeArg) + } + + if resource, err = registry.Global().NewObject(resourceType); err != nil { + return err + } + + if err := deleteResource(name, resource, resourceType, rs); err != nil { + return err + } + + cmd.Printf("deleted %s %q\n", resourceType, name) + return nil + }, } - // sub-commands - cmd.AddCommand(newDeleteMeshCmd(ctx)) return cmd } + +func deleteResource(name string, resource model.Resource, resourceType model.ResourceType, rs store.ResourceStore) error { + getOptions := store.GetByKey(model.DefaultNamespace, name, name) + if err := rs.Get(context.Background(), resource, getOptions); err != nil { + if store.IsResourceNotFound(err) { + return errors.Errorf("there is no %s with name %q", resourceType, name) + } + return errors.Wrapf(err, "failed to get %s with the name %q", resourceType, name) + } + + deleteOptions := store.DeleteByKey(model.DefaultNamespace, name, name) + if err := rs.Delete(context.Background(), resource, deleteOptions); err != nil { + return errors.Wrapf(err, "failed to delete %s with the name %q", resourceType, name) + } + + return nil +} diff --git a/app/kumactl/cmd/delete/delete_meshes.go b/app/kumactl/cmd/delete/delete_meshes.go deleted file mode 100644 index cf5730a76661..000000000000 --- a/app/kumactl/cmd/delete/delete_meshes.go +++ /dev/null @@ -1,44 +0,0 @@ -package delete - -import ( - "context" - "github.com/Kong/kuma/pkg/core/resources/apis/mesh" - "github.com/Kong/kuma/pkg/core/resources/model" - "github.com/Kong/kuma/pkg/core/resources/store" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -func newDeleteMeshCmd(pctx *deleteContext) *cobra.Command { - cmd := &cobra.Command{ - Use: "mesh", - Short: "Delete Mesh", - Long: `Delete Mesh.`, - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - rs, err := pctx.CurrentResourceStore() - if err != nil { - return err - } - meshName := args[0] - - getOptions := store.GetByKey(model.DefaultNamespace, meshName, meshName) - meshDetails := mesh.MeshResource{} - if err := rs.Get(context.Background(), &meshDetails, getOptions); err != nil { - if store.IsResourceNotFound(err) { - return errors.Errorf("there is no Mesh with name %q", meshName) - } - return errors.Wrapf(err, "failed to get Mesh with the name %q", meshName) - } - - deleteOptions := store.DeleteByKey(model.DefaultNamespace, meshName, meshName) - if err := rs.Delete(context.Background(), &mesh.MeshResource{}, deleteOptions); err != nil { - return errors.Wrapf(err, "failed to delete Mesh with the name %q", meshName) - } - - cmd.Printf("deleted Mesh %q\n", meshName) - return nil - }, - } - return cmd -} diff --git a/app/kumactl/cmd/delete/delete_meshes_test.go b/app/kumactl/cmd/delete/delete_meshes_test.go index 35c71cc52d00..878bfc0e44cd 100644 --- a/app/kumactl/cmd/delete/delete_meshes_test.go +++ b/app/kumactl/cmd/delete/delete_meshes_test.go @@ -66,7 +66,7 @@ var _ = Describe("kumactl delete mesh", func() { }, } - Describe("DeleteMeshCommand", func() { + Describe("Delete Mesh", func() { var rootCtx *kumactl_cmd.RootContext var rootCmd *cobra.Command @@ -111,9 +111,9 @@ var _ = Describe("kumactl delete mesh", func() { // then Expect(err).To(HaveOccurred()) // and - Expect(err.Error()).To(Equal("accepts 1 arg(s), received 0")) + Expect(err.Error()).To(Equal("accepts 2 arg(s), received 1")) // and - Expect(outbuf.String()).To(MatchRegexp(`Error: accepts 1 arg\(s\), received 0`)) + Expect(outbuf.String()).To(MatchRegexp(`Error: accepts 2 arg\(s\), received 1`)) // and Expect(errbuf.Bytes()).To(BeEmpty()) }) diff --git a/app/kumactl/cmd/delete/delete_test.go b/app/kumactl/cmd/delete/delete_test.go new file mode 100644 index 000000000000..c5e6b8d2dd19 --- /dev/null +++ b/app/kumactl/cmd/delete/delete_test.go @@ -0,0 +1,78 @@ +package delete_test + +import ( + "bytes" + "github.com/Kong/kuma/app/kumactl/cmd" + kumactl_cmd "github.com/Kong/kuma/app/kumactl/pkg/cmd" + config_proto "github.com/Kong/kuma/pkg/config/app/kumactl/v1alpha1" + core_store "github.com/Kong/kuma/pkg/core/resources/store" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/spf13/cobra" + "path/filepath" + "time" +) + +var _ = Describe("kumactl delete ", func() { + Describe("Delete Command", func() { + var rootCtx *kumactl_cmd.RootContext + var rootCmd *cobra.Command + var outbuf, errbuf *bytes.Buffer + var store core_store.ResourceStore + + BeforeEach(func() { + // setup + rootCtx = &kumactl_cmd.RootContext{ + Runtime: kumactl_cmd.RootRuntime{ + Now: func() time.Time { return time.Now() }, + NewResourceStore: func(*config_proto.ControlPlaneCoordinates_ApiServer) (core_store.ResourceStore, error) { + return store, nil + }, + }, + } + rootCmd = cmd.NewRootCmd(rootCtx) + outbuf = &bytes.Buffer{} + errbuf = &bytes.Buffer{} + rootCmd.SetOut(outbuf) + rootCmd.SetErr(errbuf) + }) + + It("should throw an error in case of no args", func() { + // given + rootCmd.SetArgs([]string{ + "--config-file", filepath.Join("..", "testdata", "sample-kumactl.config.yaml"), + "delete"}) + + // when + err := rootCmd.Execute() + + // then + Expect(err).To(HaveOccurred()) + // and + Expect(err.Error()).To(Equal("accepts 2 arg(s), received 0")) + // and + Expect(outbuf.String()).To(MatchRegexp(`Error: accepts 2 arg\(s\), received 0`)) + // and + Expect(errbuf.Bytes()).To(BeEmpty()) + }) + + It("should throw an error in case of unsupported resource type", func() { + // given + rootCmd.SetArgs([]string{ + "--config-file", filepath.Join("..", "testdata", "sample-kumactl.config.yaml"), + "delete", "some-type", "some-name"}) + + // when + err := rootCmd.Execute() + + // then + Expect(err).To(HaveOccurred()) + // and + Expect(err.Error()).To(Equal("unknown resource type: some-type. Allowed types: mesh, dataplane, proxytemplate, traffic-log, traffic-permission")) + // and + Expect(outbuf.String()).To(MatchRegexp(`unknown resource type: some-type. Allowed types: mesh, dataplane, proxytemplate, traffic-log, traffic-permission`)) + // and + Expect(errbuf.Bytes()).To(BeEmpty()) + }) + }) +}) \ No newline at end of file