Skip to content

Commit

Permalink
feat: kbcli support list-service-reference (#5578)
Browse files Browse the repository at this point in the history
Co-authored-by: 1aal <[email protected]>
  • Loading branch information
1aal and 1aal authored Oct 24, 2023
1 parent 4e7433d commit 2dfa9f0
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 5 deletions.
1 change: 1 addition & 0 deletions docs/user_docs/cli/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion docs/user_docs/cli/kbcli_cluster_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions docs/user_docs/cli/kbcli_clusterdefinition.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

2 changes: 1 addition & 1 deletion pkg/cli/cmd/cluster/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down
1 change: 1 addition & 0 deletions pkg/cli/cmd/clusterdefinition/clusterdefinition.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/cmd/clusterdefinition/list_component_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())

})

Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/cmd/clusterdefinition/list_components.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()
Expand Down
101 changes: 101 additions & 0 deletions pkg/cli/cmd/clusterdefinition/list_service_reference.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
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 <http://www.gnu.org/licenses/>.
*/

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/pkg/cli/list"
"github.com/apecloud/kubeblocks/pkg/cli/printer"
"github.com/apecloud/kubeblocks/pkg/cli/types"
"github.com/apecloud/kubeblocks/pkg/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("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 {
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(cd.Name, 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
}
91 changes: 91 additions & 0 deletions pkg/cli/cmd/clusterdefinition/list_service_reference_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +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 <http://www.gnu.org/licenses/>.
*/

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"

appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1"
"github.com/apecloud/kubeblocks/pkg/cli/testing"
"github.com/apecloud/kubeblocks/pkg/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
)

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 := `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())
})

})

0 comments on commit 2dfa9f0

Please sign in to comment.