From ae54ea67f5f899fb246c0ef4adb68bf90f44e129 Mon Sep 17 00:00:00 2001 From: 1aal Date: Mon, 16 Oct 2023 21:45:52 +0800 Subject: [PATCH 1/7] support list service reference --- .../clusterdefinition/clusterdefinition.go | 1 + .../clusterdefinition/list_component_test.go | 2 +- .../cmd/clusterdefinition/list_components.go | 4 +- .../list_service_reference.go | 82 +++++++++++++++++++ .../list_service_reference_test.go | 28 +++++++ 5 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 internal/cli/cmd/clusterdefinition/list_service_reference.go create mode 100644 internal/cli/cmd/clusterdefinition/list_service_reference_test.go diff --git a/internal/cli/cmd/clusterdefinition/clusterdefinition.go b/internal/cli/cmd/clusterdefinition/clusterdefinition.go index 7d881d02443..ebba0260f03 100644 --- a/internal/cli/cmd/clusterdefinition/clusterdefinition.go +++ b/internal/cli/cmd/clusterdefinition/clusterdefinition.go @@ -44,6 +44,7 @@ func NewClusterDefinitionCmd(f cmdutil.Factory, streams genericiooptions.IOStrea cmd.AddCommand(NewListCmd(f, streams)) cmd.AddCommand(NewListComponentsCmd(f, streams)) cmd.AddCommand(NewDescribeCmd(f, streams)) + cmd.AddCommand(NewListServiceReferenceCmd(f, streams)) return cmd } diff --git a/internal/cli/cmd/clusterdefinition/list_component_test.go b/internal/cli/cmd/clusterdefinition/list_component_test.go index fab8c28a080..3b75c4dd214 100644 --- a/internal/cli/cmd/clusterdefinition/list_component_test.go +++ b/internal/cli/cmd/clusterdefinition/list_component_test.go @@ -98,7 +98,7 @@ var _ = Describe("clusterdefinition list components", func() { GroupVersion: schema.GroupVersion{Group: types.AppsAPIGroup, Version: types.AppsAPIVersion}, Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, testing.FakeResourceNotFound(types.ClusterDefGVR(), clusterdefinitionName+"-no-exist"))}, } - Expect(run(o)).Should(HaveOccurred()) + Expect(listComponents(o)).Should(HaveOccurred()) }) diff --git a/internal/cli/cmd/clusterdefinition/list_components.go b/internal/cli/cmd/clusterdefinition/list_components.go index 32b8d2ee0f4..f7ef300308e 100644 --- a/internal/cli/cmd/clusterdefinition/list_components.go +++ b/internal/cli/cmd/clusterdefinition/list_components.go @@ -54,7 +54,7 @@ func NewListComponentsCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) Run: func(cmd *cobra.Command, args []string) { util.CheckErr(validate(args)) o.Names = args - util.CheckErr(run(o)) + util.CheckErr(listComponents(o)) }, } return cmd @@ -67,7 +67,7 @@ func validate(args []string) error { return nil } -func run(o *list.ListOptions) error { +func listComponents(o *list.ListOptions) error { o.Print = false r, err := o.Run() diff --git a/internal/cli/cmd/clusterdefinition/list_service_reference.go b/internal/cli/cmd/clusterdefinition/list_service_reference.go new file mode 100644 index 00000000000..53c1c25ff43 --- /dev/null +++ b/internal/cli/cmd/clusterdefinition/list_service_reference.go @@ -0,0 +1,82 @@ +package clusterdefinition + +import ( + "fmt" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/cli-runtime/pkg/genericiooptions" + cmdutil "k8s.io/kubectl/pkg/cmd/util" + "k8s.io/kubectl/pkg/util/templates" + + "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" + "github.com/apecloud/kubeblocks/internal/cli/list" + "github.com/apecloud/kubeblocks/internal/cli/printer" + "github.com/apecloud/kubeblocks/internal/cli/types" + "github.com/apecloud/kubeblocks/internal/cli/util" +) + +var ( + listServiceRefExample = templates.Examples(` + # List cluster references name declared in a cluster definition. + kbcli clusterdefinition list-service-reference apecloud-mysql`) +) + +func NewListServiceReferenceCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command { + o := list.NewListOptions(f, streams, types.ClusterDefGVR()) + o.AllNamespaces = true + cmd := &cobra.Command{ + Use: "list-service-reference", + Short: "List cluster references declared in a cluster definition.", + Example: listServiceRefExample, + Aliases: []string{"ls-sr"}, + ValidArgsFunction: util.ResourceNameCompletionFunc(f, o.GVR), + Run: func(cmd *cobra.Command, args []string) { + util.CheckErr(validate(args)) + o.Names = args + util.CheckErr(listServiceRef(o)) + }, + } + return cmd +} + +func listServiceRef(o *list.ListOptions) error { + o.Print = false + + r, err := o.Run() + if err != nil { + return err + } + infos, err := r.Infos() + if err != nil { + return err + } + + p := printer.NewTablePrinter(o.Out) + p.SetHeader("NAME", "COMPONENT", "SERVICE-KIND", "SERVICE-VERSION") + p.SortBy(4, 1) + for _, info := range infos { + var cd v1alpha1.ClusterDefinition + if err = runtime.DefaultUnstructuredConverter.FromUnstructured(info.Object.(*unstructured.Unstructured).Object, &cd); err != nil { + return err + } + for _, comp := range cd.Spec.ComponentDefs { + if comp.ServiceRefDeclarations == nil { + continue + } + for _, serviceDec := range comp.ServiceRefDeclarations { + for _, ref := range serviceDec.ServiceRefDeclarationSpecs { + p.AddRow(serviceDec.Name, comp.Name, ref.ServiceKind, ref.ServiceVersion) + } + } + } + } + + if p.Tbl.Length() == 0 { + fmt.Printf("No service references are declared in cluster definition %s", o.Names) + } else { + p.Print() + } + return nil +} diff --git a/internal/cli/cmd/clusterdefinition/list_service_reference_test.go b/internal/cli/cmd/clusterdefinition/list_service_reference_test.go new file mode 100644 index 00000000000..5fe8ca88a64 --- /dev/null +++ b/internal/cli/cmd/clusterdefinition/list_service_reference_test.go @@ -0,0 +1,28 @@ +package clusterdefinition + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "k8s.io/cli-runtime/pkg/genericiooptions" + cmdtesting "k8s.io/kubectl/pkg/cmd/testing" +) + +// todo: wait #https://github.com/apecloud/kubeblocks/pull/5422 merge main and fix it + +var _ = Describe("clusterdefinition list components", func() { + var ( + streams genericiooptions.IOStreams + tf *cmdtesting.TestFactory + ) + + AfterEach(func() { + tf.Cleanup() + }) + + It("create list-components cmd", func() { + cmd := NewListComponentsCmd(tf, streams) + Expect(cmd).ShouldNot(BeNil()) + }) + +}) From cc95df6e2ac5ca8569fa9ea0bdd41976bc24ed3d Mon Sep 17 00:00:00 2001 From: 1aal Date: Mon, 16 Oct 2023 21:46:16 +0800 Subject: [PATCH 2/7] support list service reference --- .../cli/cmd/clusterdefinition/list_service_reference_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/internal/cli/cmd/clusterdefinition/list_service_reference_test.go b/internal/cli/cmd/clusterdefinition/list_service_reference_test.go index 5fe8ca88a64..b66636e4b50 100644 --- a/internal/cli/cmd/clusterdefinition/list_service_reference_test.go +++ b/internal/cli/cmd/clusterdefinition/list_service_reference_test.go @@ -16,10 +16,6 @@ var _ = Describe("clusterdefinition list components", func() { tf *cmdtesting.TestFactory ) - AfterEach(func() { - tf.Cleanup() - }) - It("create list-components cmd", func() { cmd := NewListComponentsCmd(tf, streams) Expect(cmd).ShouldNot(BeNil()) From e19c1cf6e4d6f27cbe27eb4a807823fec7169407 Mon Sep 17 00:00:00 2001 From: 1aal <1aal@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:50:28 +0000 Subject: [PATCH 3/7] chore: auto update cli doc changes --- docs/user_docs/cli/cli.md | 1 + docs/user_docs/cli/kbcli_clusterdefinition.md | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/user_docs/cli/cli.md b/docs/user_docs/cli/cli.md index e8fc0abaa6f..eb8d1370051 100644 --- a/docs/user_docs/cli/cli.md +++ b/docs/user_docs/cli/cli.md @@ -123,6 +123,7 @@ ClusterDefinition command. * [kbcli clusterdefinition describe](kbcli_clusterdefinition_describe.md) - Describe ClusterDefinition. * [kbcli clusterdefinition list](kbcli_clusterdefinition_list.md) - List ClusterDefinitions. * [kbcli clusterdefinition list-components](kbcli_clusterdefinition_list-components.md) - List cluster definition components. +* [kbcli clusterdefinition list-service-reference](kbcli_clusterdefinition_list-service-reference.md) - List cluster references declared in a cluster definition. ## [clusterversion](kbcli_clusterversion.md) diff --git a/docs/user_docs/cli/kbcli_clusterdefinition.md b/docs/user_docs/cli/kbcli_clusterdefinition.md index 12f63b314f7..0425a4e5cd2 100644 --- a/docs/user_docs/cli/kbcli_clusterdefinition.md +++ b/docs/user_docs/cli/kbcli_clusterdefinition.md @@ -40,6 +40,7 @@ ClusterDefinition command. * [kbcli clusterdefinition describe](kbcli_clusterdefinition_describe.md) - Describe ClusterDefinition. * [kbcli clusterdefinition list](kbcli_clusterdefinition_list.md) - List ClusterDefinitions. * [kbcli clusterdefinition list-components](kbcli_clusterdefinition_list-components.md) - List cluster definition components. +* [kbcli clusterdefinition list-service-reference](kbcli_clusterdefinition_list-service-reference.md) - List cluster references declared in a cluster definition. #### Go Back to [CLI Overview](cli.md) Homepage. From b332d58a6e95078a9e7bfd558dd5f506e0e13ec5 Mon Sep 17 00:00:00 2001 From: 1aal Date: Tue, 17 Oct 2023 09:46:43 +0800 Subject: [PATCH 4/7] support list service reference --- internal/cli/cmd/cluster/create.go | 2 +- .../list_service_reference.go | 19 +++++ .../list_service_reference_test.go | 75 ++++++++++++++++++- 3 files changed, 91 insertions(+), 5 deletions(-) diff --git a/internal/cli/cmd/cluster/create.go b/internal/cli/cmd/cluster/create.go index 4cec421105e..519c928c8af 100755 --- a/internal/cli/cmd/cluster/create.go +++ b/internal/cli/cmd/cluster/create.go @@ -148,7 +148,7 @@ var clusterCreateExample = templates.Examples(` kbcli cluster create --cluster-definition pulsar --pvc type=bookies,name=ledgers,size=20Gi --pvc type=bookies,name=journal,size=20Gi # Create a cluster with using a service reference to another KubeBlocks cluster - cluster create --cluster-definition pulsar --service-reference name=pulsarZookeeper,cluster=zookeeper,namespace=default + kbcli cluster create --cluster-definition pulsar --service-reference name=pulsarZookeeper,cluster=zookeeper,namespace=default `) const ( diff --git a/internal/cli/cmd/clusterdefinition/list_service_reference.go b/internal/cli/cmd/clusterdefinition/list_service_reference.go index 53c1c25ff43..4e9f8a6dd5a 100644 --- a/internal/cli/cmd/clusterdefinition/list_service_reference.go +++ b/internal/cli/cmd/clusterdefinition/list_service_reference.go @@ -1,3 +1,22 @@ +/* +Copyright (C) 2022-2023 ApeCloud Co., Ltd + +This file is part of KubeBlocks project + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ + package clusterdefinition import ( diff --git a/internal/cli/cmd/clusterdefinition/list_service_reference_test.go b/internal/cli/cmd/clusterdefinition/list_service_reference_test.go index b66636e4b50..a1ae6837116 100644 --- a/internal/cli/cmd/clusterdefinition/list_service_reference_test.go +++ b/internal/cli/cmd/clusterdefinition/list_service_reference_test.go @@ -1,24 +1,91 @@ +/* +Copyright (C) 2022-2023 ApeCloud Co., Ltd + +This file is part of KubeBlocks project + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ + package clusterdefinition import ( + "bytes" + "fmt" + "net/http" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/cli-runtime/pkg/genericiooptions" + "k8s.io/cli-runtime/pkg/resource" + "k8s.io/client-go/kubernetes/scheme" + clientfake "k8s.io/client-go/rest/fake" cmdtesting "k8s.io/kubectl/pkg/cmd/testing" -) -// todo: wait #https://github.com/apecloud/kubeblocks/pull/5422 merge main and fix it + appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" + "github.com/apecloud/kubeblocks/internal/cli/testing" + "github.com/apecloud/kubeblocks/internal/cli/types" +) var _ = Describe("clusterdefinition list components", func() { var ( + cmd *cobra.Command streams genericiooptions.IOStreams + out *bytes.Buffer tf *cmdtesting.TestFactory ) + const ( + namespace = testing.Namespace + clusterdefinitionName = testing.ClusterDefName + ) - It("create list-components cmd", func() { - cmd := NewListComponentsCmd(tf, streams) + mockClient := func(data runtime.Object) *cmdtesting.TestFactory { + tf := testing.NewTestFactory(namespace) + codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) + tf.UnstructuredClient = &clientfake.RESTClient{ + NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer, + GroupVersion: schema.GroupVersion{Group: types.AppsAPIGroup, Version: types.AppsAPIVersion}, + Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, data)}, + } + tf.Client = tf.UnstructuredClient + tf.FakeDynamicClient = testing.FakeDynamicClient(data) + return tf + } + + BeforeEach(func() { + _ = appsv1alpha1.AddToScheme(scheme.Scheme) + clusterDef := testing.FakeClusterDef() + tf = mockClient(clusterDef) + streams, _, out, _ = genericiooptions.NewTestIOStreams() + cmd = NewListServiceReferenceCmd(tf, streams) + }) + + It("create list-service-reference cmd", func() { + cmd := NewListServiceReferenceCmd(tf, streams) Expect(cmd).ShouldNot(BeNil()) }) + It("list-service", func() { + cmd.Run(cmd, []string{clusterdefinitionName}) + expected := `NAME COMPONENT SERVICE-KIND SERVICE-VERSION +fake-serviceRef fake-component-type mysql 8.0.\d{1,2}$ +` + Expect(expected).Should(Equal(out.String())) + fmt.Println(out.String()) + }) + }) From 6a77edca2e9a2bd104dfade0fc0f5c0196520870 Mon Sep 17 00:00:00 2001 From: 1aal <1aal@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:50:53 +0000 Subject: [PATCH 5/7] chore: auto update cli doc changes --- docs/user_docs/cli/kbcli_cluster_create.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user_docs/cli/kbcli_cluster_create.md b/docs/user_docs/cli/kbcli_cluster_create.md index 8c7a008ed34..92372f0a639 100644 --- a/docs/user_docs/cli/kbcli_cluster_create.md +++ b/docs/user_docs/cli/kbcli_cluster_create.md @@ -92,7 +92,7 @@ kbcli cluster create [NAME] [flags] kbcli cluster create --cluster-definition pulsar --pvc type=bookies,name=ledgers,size=20Gi --pvc type=bookies,name=journal,size=20Gi # Create a cluster with using a service reference to another KubeBlocks cluster - cluster create --cluster-definition pulsar --service-reference name=pulsarZookeeper,cluster=zookeeper,namespace=default + kbcli cluster create --cluster-definition pulsar --service-reference name=pulsarZookeeper,cluster=zookeeper,namespace=default ``` ### Options From 99bcccd5dd8802f4f504e336022ce38d4f77882a Mon Sep 17 00:00:00 2001 From: 1aal Date: Tue, 17 Oct 2023 20:30:19 +0800 Subject: [PATCH 6/7] adjust sort-by order --- internal/cli/cmd/clusterdefinition/list_service_reference.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cli/cmd/clusterdefinition/list_service_reference.go b/internal/cli/cmd/clusterdefinition/list_service_reference.go index 4e9f8a6dd5a..9611f80f883 100644 --- a/internal/cli/cmd/clusterdefinition/list_service_reference.go +++ b/internal/cli/cmd/clusterdefinition/list_service_reference.go @@ -74,7 +74,7 @@ func listServiceRef(o *list.ListOptions) error { p := printer.NewTablePrinter(o.Out) p.SetHeader("NAME", "COMPONENT", "SERVICE-KIND", "SERVICE-VERSION") - p.SortBy(4, 1) + p.SortBy(1) for _, info := range infos { var cd v1alpha1.ClusterDefinition if err = runtime.DefaultUnstructuredConverter.FromUnstructured(info.Object.(*unstructured.Unstructured).Object, &cd); err != nil { From 602b6bc22d5f6bdff3192593792c42c17b9850a4 Mon Sep 17 00:00:00 2001 From: 1aal Date: Fri, 20 Oct 2023 23:23:35 +0800 Subject: [PATCH 7/7] add cluster-definition for list --- .../cli/cmd/clusterdefinition/list_service_reference.go | 6 +++--- .../cmd/clusterdefinition/list_service_reference_test.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/cli/cmd/clusterdefinition/list_service_reference.go b/internal/cli/cmd/clusterdefinition/list_service_reference.go index 9611f80f883..a29814fa02e 100644 --- a/internal/cli/cmd/clusterdefinition/list_service_reference.go +++ b/internal/cli/cmd/clusterdefinition/list_service_reference.go @@ -73,8 +73,8 @@ func listServiceRef(o *list.ListOptions) error { } p := printer.NewTablePrinter(o.Out) - p.SetHeader("NAME", "COMPONENT", "SERVICE-KIND", "SERVICE-VERSION") - p.SortBy(1) + p.SetHeader("CLUSTER-DEFINITION", "NAME", "COMPONENT", "SERVICE-KIND", "SERVICE-VERSION") + p.SortBy(1, 2) for _, info := range infos { var cd v1alpha1.ClusterDefinition if err = runtime.DefaultUnstructuredConverter.FromUnstructured(info.Object.(*unstructured.Unstructured).Object, &cd); err != nil { @@ -86,7 +86,7 @@ func listServiceRef(o *list.ListOptions) error { } for _, serviceDec := range comp.ServiceRefDeclarations { for _, ref := range serviceDec.ServiceRefDeclarationSpecs { - p.AddRow(serviceDec.Name, comp.Name, ref.ServiceKind, ref.ServiceVersion) + p.AddRow(cd.Name, serviceDec.Name, comp.Name, ref.ServiceKind, ref.ServiceVersion) } } } diff --git a/internal/cli/cmd/clusterdefinition/list_service_reference_test.go b/internal/cli/cmd/clusterdefinition/list_service_reference_test.go index a1ae6837116..545f5b11f12 100644 --- a/internal/cli/cmd/clusterdefinition/list_service_reference_test.go +++ b/internal/cli/cmd/clusterdefinition/list_service_reference_test.go @@ -81,8 +81,8 @@ var _ = Describe("clusterdefinition list components", func() { It("list-service", func() { cmd.Run(cmd, []string{clusterdefinitionName}) - expected := `NAME COMPONENT SERVICE-KIND SERVICE-VERSION -fake-serviceRef fake-component-type mysql 8.0.\d{1,2}$ + expected := `CLUSTER-DEFINITION NAME COMPONENT SERVICE-KIND SERVICE-VERSION +fake-cluster-definition fake-serviceRef fake-component-type mysql 8.0.\d{1,2}$ ` Expect(expected).Should(Equal(out.String())) fmt.Println(out.String())