From a123085fa3b3e61cbd209f182aec2f2890d744bd Mon Sep 17 00:00:00 2001 From: Pradeep Murugesan Date: Tue, 15 Oct 2019 09:10:48 +0530 Subject: [PATCH] feat(kumactl) add kumactl delete command Implemented the support for delete command. The delete command takes the mesh name as a parameter. Check if the the given mesh name exists and then delete. * returns an error in case of no mesh with the given name. Fix #279 --- app/kumactl/cmd/delete/delete.go | 23 +++ app/kumactl/cmd/delete/delete_meshes.go | 41 +++++ app/kumactl/cmd/delete/delete_meshes_test.go | 165 +++++++++++++++++++ app/kumactl/cmd/delete/delete_suite_test.go | 13 ++ app/kumactl/cmd/root.go | 2 + docs/cmd/kumactl/HELP.md | 1 + 6 files changed, 245 insertions(+) create mode 100644 app/kumactl/cmd/delete/delete.go create mode 100644 app/kumactl/cmd/delete/delete_meshes.go create mode 100644 app/kumactl/cmd/delete/delete_meshes_test.go create mode 100644 app/kumactl/cmd/delete/delete_suite_test.go diff --git a/app/kumactl/cmd/delete/delete.go b/app/kumactl/cmd/delete/delete.go new file mode 100644 index 000000000000..7ff4f56e4549 --- /dev/null +++ b/app/kumactl/cmd/delete/delete.go @@ -0,0 +1,23 @@ +package delete + +import ( + kumactl_cmd "github.com/Kong/kuma/app/kumactl/pkg/cmd" + "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.`, + } + + // sub-commands + cmd.AddCommand(newDeleteMeshCmd(ctx)) + return cmd +} diff --git a/app/kumactl/cmd/delete/delete_meshes.go b/app/kumactl/cmd/delete/delete_meshes.go new file mode 100644 index 000000000000..00cdc867f45d --- /dev/null +++ b/app/kumactl/cmd/delete/delete_meshes.go @@ -0,0 +1,41 @@ +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 { + return errors.Wrapf(err, "failed to get Mesh with the name %s", 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 new file mode 100644 index 000000000000..62ac02480570 --- /dev/null +++ b/app/kumactl/cmd/delete/delete_meshes_test.go @@ -0,0 +1,165 @@ +package delete_test + +import ( + "bytes" + "context" + "path/filepath" + "time" + + "github.com/Kong/kuma/api/mesh/v1alpha1" + "github.com/Kong/kuma/app/kumactl/cmd" + config_proto "github.com/Kong/kuma/pkg/config/app/kumactl/v1alpha1" + "github.com/Kong/kuma/pkg/core/resources/apis/mesh" + core_model "github.com/Kong/kuma/pkg/core/resources/model" + core_store "github.com/Kong/kuma/pkg/core/resources/store" + memory_resources "github.com/Kong/kuma/pkg/plugins/resources/memory" + test_model "github.com/Kong/kuma/pkg/test/resources/model" + + kumactl_cmd "github.com/Kong/kuma/app/kumactl/pkg/cmd" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/spf13/cobra" +) + +var _ = Describe("kumactl delete mesh", func() { + + sampleMeshes := []*mesh.MeshResource{ + { + Spec: v1alpha1.Mesh{ + Mtls: &v1alpha1.Mesh_Mtls{ + Enabled: true, + Ca: &v1alpha1.CertificateAuthority{ + Type: &v1alpha1.CertificateAuthority_Builtin_{ + Builtin: &v1alpha1.CertificateAuthority_Builtin{}, + }, + }, + }, + Logging: &v1alpha1.Logging{ + AccessLogs: &v1alpha1.Logging_AccessLogs{ + Enabled: true, + FilePath: "/tmp/access.log", + }, + }, + }, + Meta: &test_model.ResourceMeta{ + Mesh: "mesh1", + Name: "mesh1", + Namespace: "default", + }, + }, + { + Spec: v1alpha1.Mesh{ + Mtls: &v1alpha1.Mesh_Mtls{ + Enabled: false, + Ca: &v1alpha1.CertificateAuthority{ + Type: &v1alpha1.CertificateAuthority_Builtin_{ + Builtin: &v1alpha1.CertificateAuthority_Builtin{}, + }, + }, + }, + }, + Meta: &test_model.ResourceMeta{ + Mesh: "mesh2", + Name: "mesh2", + Namespace: "default", + }, + }, + } + + Describe("DeleteMeshCommand", 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 + }, + }, + } + + store = memory_resources.NewStore() + + for _, ds := range sampleMeshes { + key := core_model.MetaToResourceKey(ds.Meta) + err := store.Create(context.Background(), ds, core_store.CreateBy(key)) + Expect(err).ToNot(HaveOccurred()) + } + + 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", "mesh"}) + + // when + err := rootCmd.Execute() + + // then + Expect(err).To(HaveOccurred()) + // and + Expect(err.Error()).To(Equal("accepts 1 arg(s), received 0")) + // and + Expect(outbuf.String()).To(MatchRegexp(`Error: accepts 1 arg\(s\), received 0`)) + // and + Expect(errbuf.Bytes()).To(BeEmpty()) + }) + + It("should throw an error in case of a non existing mesh", func() { + // given + rootCmd.SetArgs([]string{ + "--config-file", filepath.Join("..", "testdata", "sample-kumactl.config.yaml"), + "delete", "mesh", "some-non-existing-mesh"}) + + // when + err := rootCmd.Execute() + + // then + Expect(err).To(HaveOccurred()) + // and + Expect(err.Error()).To(MatchRegexp("failed to get Mesh with the name some-non-existing-mesh: .*")) + // and + Expect(outbuf.String()).To(MatchRegexp("failed to get Mesh with the name some-non-existing-mesh: .*")) + // and + Expect(errbuf.Bytes()).To(BeEmpty()) + }) + + It("should delete the mesh if exists", func() { + + // given + rootCmd.SetArgs([]string{ + "--config-file", filepath.Join("..", "testdata", "sample-kumactl.config.yaml"), + "delete", "mesh", "mesh2"}) + + // when + err := rootCmd.Execute() + + // then + Expect(err).ToNot(HaveOccurred()) + + // and + list := &mesh.MeshResourceList{} + e := store.List(context.Background(), list, core_store.ListByNamespace("default")) + Expect(e).To(BeNil()) + Expect(len(list.Items)).To(Equal(1)) + // and + Expect(errbuf.String()).To(BeEmpty()) + // and + Expect(outbuf.String()).To(Equal("deleted Mesh \"mesh2\"\n")) + }) + }) + +}) diff --git a/app/kumactl/cmd/delete/delete_suite_test.go b/app/kumactl/cmd/delete/delete_suite_test.go new file mode 100644 index 000000000000..d50e69234715 --- /dev/null +++ b/app/kumactl/cmd/delete/delete_suite_test.go @@ -0,0 +1,13 @@ +package delete_test + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestDeleteCmd(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Delete Cmd Suite") +} diff --git a/app/kumactl/cmd/root.go b/app/kumactl/cmd/root.go index 25291c597ef4..62af1d761e92 100644 --- a/app/kumactl/cmd/root.go +++ b/app/kumactl/cmd/root.go @@ -6,6 +6,7 @@ import ( "github.com/Kong/kuma/app/kumactl/cmd/apply" "github.com/Kong/kuma/app/kumactl/cmd/config" + "github.com/Kong/kuma/app/kumactl/cmd/delete" "github.com/Kong/kuma/app/kumactl/cmd/get" "github.com/Kong/kuma/app/kumactl/cmd/inspect" "github.com/Kong/kuma/app/kumactl/cmd/install" @@ -59,6 +60,7 @@ func NewRootCmd(root *kumactl_cmd.RootContext) *cobra.Command { cmd.AddCommand(install.NewInstallCmd(root)) cmd.AddCommand(config.NewConfigCmd(root)) cmd.AddCommand(get.NewGetCmd(root)) + cmd.AddCommand(delete.NewDeleteCmd(root)) cmd.AddCommand(inspect.NewInspectCmd(root)) cmd.AddCommand(apply.NewApplyCmd(root)) cmd.AddCommand(version.NewVersionCmd()) diff --git a/docs/cmd/kumactl/HELP.md b/docs/cmd/kumactl/HELP.md index d43899030f91..3b909bda6c73 100644 --- a/docs/cmd/kumactl/HELP.md +++ b/docs/cmd/kumactl/HELP.md @@ -9,6 +9,7 @@ Usage: Available Commands: apply Create or modify Kuma resources config Manage kumactl config + delete Delete Kuma resources get Show Kuma resources help Help about any command inspect Inspect Kuma resources