Skip to content

Commit

Permalink
playground support k3d and aws
Browse files Browse the repository at this point in the history
  • Loading branch information
yipeng1030 committed Oct 21, 2024
1 parent 0a8c01b commit 1e442d2
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 84 deletions.
21 changes: 6 additions & 15 deletions docs/user_docs/cli/kbcli_playground_init.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,6 @@ kbcli playground init [flags]
# create an AWS EKS cluster and install KubeBlocks, the region is required
kbcli playground init --cloud-provider aws --region us-west-1
# create an Alibaba cloud ACK cluster and install KubeBlocks, the region is required
kbcli playground init --cloud-provider alicloud --region cn-hangzhou
# create a Tencent cloud TKE cluster and install KubeBlocks, the region is required
kbcli playground init --cloud-provider tencentcloud --region ap-chengdu
# create a Google cloud GKE cluster and install KubeBlocks, the region is required
kbcli playground init --cloud-provider gcp --region us-east1
# after init, run the following commands to experience KubeBlocks quickly
# list database cluster and check its status
kbcli cluster list
Expand All @@ -52,13 +43,13 @@ kbcli playground init [flags]
### Options

```
--auto-approve Skip interactive approval during the initialization of playground
--auto-approve Skip interactive approval during the initialization of playground
--cluster-type string Specify the cluster type to create, use 'kbcli cluster create --help' to get the available cluster type. (default "apecloud-mysql")
--cloud-provider string Cloud provider type, one of [local aws gcp alicloud tencentcloud] (default "local")
--cluster-definition string Specify the cluster definition, run "kbcli cd list" to get the available cluster definitions (default "apecloud-mysql")
-h, --help help for init
--region string The region to create kubernetes cluster
--timeout duration Time to wait for init playground, such as --timeout=10m (default 10m0s)
--version string KubeBlocks version
-h, --help help for init
--region string The region to create kubernetes cluster
--timeout duration Time to wait for init playground, such as --timeout=10m (default 10m0s)
--version string KubeBlocks version
```

### Options inherited from parent commands
Expand Down
2 changes: 1 addition & 1 deletion pkg/cloudprovider/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type Interface interface {

func New(provider, tfRootPath string, stdout, stderr io.Writer) (Interface, error) {
switch provider {
case AWS, TencentCloud, AliCloud, GCP:
case AWS:
return newCloudProvider(provider, tfRootPath, stdout, stderr)
case Local:
return newLocalCloudProvider(stdout, stderr), nil
Expand Down
18 changes: 5 additions & 13 deletions pkg/cloudprovider/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,19 @@ const (
)

const (
Local = "local"
AWS = "aws"
AliCloud = "alicloud"
Azure = "azure"
GCP = "gcp"
TencentCloud = "tencentcloud"
Local = "local"
AWS = "aws"
)

var (
cloudProviderK8sServiceMap = map[string]string{
Local: "k3s",
AWS: "eks",
AliCloud: "ack",
Azure: "aks",
GCP: "gke",
TencentCloud: "tke",
Local: "k3s",
AWS: "eks",
}
)

func CloudProviders() []string {
return []string{Local, AWS, Azure, GCP, AliCloud, TencentCloud}
return []string{Local, AWS}
}

func K8sService(provider string) string {
Expand Down
20 changes: 15 additions & 5 deletions pkg/cmd/cluster/create_subcmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"context"
"fmt"
"os"
"regexp"

"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/errors"
Expand Down Expand Up @@ -97,8 +98,8 @@ func buildCreateSubCmds(createOptions *action.CreateOptions) []*cobra.Command {
Run: func(cmd *cobra.Command, args []string) {
o.Args = args
cmdutil.CheckErr(o.CreateOptions.Complete())
cmdutil.CheckErr(o.complete(cmd))
cmdutil.CheckErr(o.validate())
cmdutil.CheckErr(o.Complete(cmd))
cmdutil.CheckErr(o.Validate())
cmdutil.CheckErr(o.Run())
},
}
Expand Down Expand Up @@ -150,7 +151,7 @@ func generateClusterName(dynamic dynamic.Interface, namespace string) (string, e
return "", fmt.Errorf("failed to generate cluster name")
}

func (o *CreateSubCmdsOptions) complete(cmd *cobra.Command) error {
func (o *CreateSubCmdsOptions) Complete(cmd *cobra.Command) error {
var err error

// if name is not specified, generate a random cluster name
Expand All @@ -162,7 +163,9 @@ func (o *CreateSubCmdsOptions) complete(cmd *cobra.Command) error {
}

// get values from flags
o.Values = getValuesFromFlags(cmd.LocalNonPersistentFlags())
if cmd != nil {
o.Values = getValuesFromFlags(cmd.LocalNonPersistentFlags())
}

// get all the rendered objects
objs, err := o.getObjectsInfo()
Expand Down Expand Up @@ -211,7 +214,14 @@ func (o *CreateSubCmdsOptions) complete(cmd *cobra.Command) error {
return nil
}

func (o *CreateSubCmdsOptions) validate() error {
func (o *CreateSubCmdsOptions) Validate() error {
matched, _ := regexp.MatchString(`^[a-z]([-a-z0-9]*[a-z0-9])?$`, o.Name)
if !matched {
return fmt.Errorf("cluster name must begin with a letter and can only contain lowercase letters, numbers, and '-'")
}
if len(o.Name) > 16 {
return fmt.Errorf("cluster name should be less than 16 characters")
}
return cluster.ValidateValues(o.ChartInfo, o.Values)
}

Expand Down
8 changes: 4 additions & 4 deletions pkg/cmd/cluster/create_subcmds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,14 @@ var _ = Describe("create cluster by cluster type", func() {
o.Client = testing.FakeClientSet()
fakeDiscovery1, _ := o.Client.Discovery().(*fakediscovery.FakeDiscovery)
fakeDiscovery1.FakedServerVersion = &version.Info{Major: "1", Minor: "27", GitVersion: "v1.27.0"}
Expect(o.complete(mysqlCmd)).Should(Succeed())
Expect(o.Complete(mysqlCmd)).Should(Succeed())
Expect(o.Name).ShouldNot(BeEmpty())
Expect(o.Values).ShouldNot(BeNil())
Expect(o.ChartInfo.ClusterDef).Should(Equal(apeCloudMysql))

By("validate")
o.Dynamic = testing.FakeDynamicClient()
Expect(o.validate()).Should(Succeed())
Expect(o.Validate()).Should(Succeed())

By("run")
o.DryRun = "client"
Expand Down Expand Up @@ -157,14 +157,14 @@ var _ = Describe("create cluster by cluster type", func() {
fakeDiscovery1.FakedServerVersion = &version.Info{Major: "1", Minor: "27", GitVersion: "v1.27.0"}

Expect(shardCmd.Flags().Set("mode", "cluster")).Should(Succeed())
Expect(o.complete(shardCmd)).Should(Succeed())
Expect(o.Complete(shardCmd)).Should(Succeed())
Expect(o.Name).ShouldNot(BeEmpty())
Expect(o.Values).ShouldNot(BeNil())
Expect(o.ChartInfo.ComponentDef[0]).Should(Equal(redisComponent))

By("validate")
o.Dynamic = testing.FakeDynamicClient()
Expect(o.validate()).Should(Succeed())
Expect(o.Validate()).Should(Succeed())

By("run")
o.DryRun = "client"
Expand Down
59 changes: 19 additions & 40 deletions pkg/cmd/playground/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ import (
"k8s.io/kubectl/pkg/util/templates"

cp "github.com/apecloud/kbcli/pkg/cloudprovider"
"github.com/apecloud/kbcli/pkg/cluster"
cmdcluster "github.com/apecloud/kbcli/pkg/cmd/cluster"
"github.com/apecloud/kbcli/pkg/cmd/kubeblocks"
"github.com/apecloud/kbcli/pkg/printer"
"github.com/apecloud/kbcli/pkg/spinner"
Expand All @@ -62,15 +64,6 @@ on the created kubernetes cluster, and an apecloud-mysql cluster named mycluster
# create an AWS EKS cluster and install KubeBlocks, the region is required
kbcli playground init --cloud-provider aws --region us-west-1
# create an Alibaba cloud ACK cluster and install KubeBlocks, the region is required
kbcli playground init --cloud-provider alicloud --region cn-hangzhou
# create a Tencent cloud TKE cluster and install KubeBlocks, the region is required
kbcli playground init --cloud-provider tencentcloud --region ap-chengdu
# create a Google cloud GKE cluster and install KubeBlocks, the region is required
kbcli playground init --cloud-provider gcp --region us-east1
# after init, run the following commands to experience KubeBlocks quickly
# list database cluster and check its status
kbcli cluster list
Expand All @@ -87,7 +80,7 @@ on the created kubernetes cluster, and an apecloud-mysql cluster named mycluster
# destroy playground
kbcli playground destroy`)

supportedCloudProviders = []string{cp.Local, cp.AWS, cp.GCP, cp.AliCloud, cp.TencentCloud}
supportedCloudProviders = []string{cp.Local, cp.AWS}

spinnerMsg = func(format string, a ...any) spinner.Option {
return spinner.WithMessage(fmt.Sprintf("%-50s", fmt.Sprintf(format, a...)))
Expand All @@ -97,7 +90,7 @@ on the created kubernetes cluster, and an apecloud-mysql cluster named mycluster
type initOptions struct {
genericiooptions.IOStreams
helmCfg *helm.Config
clusterDef string
clusterType string
kbVersion string
cloudProvider string
region string
Expand All @@ -124,7 +117,7 @@ func newInitCmd(streams genericiooptions.IOStreams) *cobra.Command {
},
}

cmd.Flags().StringVar(&o.clusterDef, "cluster-definition", defaultClusterDef, "Specify the cluster definition, run \"kbcli cd list\" to get the available cluster definitions")
cmd.Flags().StringVar(&o.clusterType, "cluster-type", defaultClusterType, "Specify the cluster type to create, use 'kbcli cluster create --help' to get the available cluster type.")
cmd.Flags().StringVar(&o.kbVersion, "version", version.DefaultKubeBlocksVersion, "KubeBlocks version")
cmd.Flags().StringVar(&o.cloudProvider, "cloud-provider", defaultCloudProvider, fmt.Sprintf("Cloud provider type, one of %v", supportedCloudProviders))
cmd.Flags().StringVar(&o.region, "region", "", "The region to create kubernetes cluster")
Expand Down Expand Up @@ -166,8 +159,8 @@ func (o *initOptions) validate() error {
return fmt.Errorf("region should be specified when cloud provider %s is specified", o.cloudProvider)
}

if o.clusterDef == "" {
return fmt.Errorf("a valid cluster definition is needed, use --cluster-definition to specify one")
if o.clusterType == "" {
return fmt.Errorf("a valid cluster type is needed, use --cluster-type to specify one")
}

if o.cloudProvider == cp.Local && o.dockerVersion.LessThan(version.MinimumDockerVersion) {
Expand Down Expand Up @@ -410,7 +403,7 @@ func (o *initOptions) installKBAndCluster(info *cp.K8sClusterInfo) error {
}
klog.V(1).Info("KubeBlocks installed successfully")
// install database cluster
clusterInfo := "ClusterDefinition: " + o.clusterDef
clusterInfo := "ClusterType: " + o.clusterType
s := spinner.New(o.Out, spinnerMsg("Create cluster %s (%s)", kbClusterName, clusterInfo))
defer s.Fail()
if err = o.createCluster(); err != nil && !apierrors.IsAlreadyExists(err) {
Expand Down Expand Up @@ -494,38 +487,24 @@ func (o *initOptions) installKubeBlocks(k8sClusterName string) error {

// createCluster constructs a cluster create options and run
func (o *initOptions) createCluster() error {
// TODO: Update with new creation cmd
/*c := cmdcluster.NewCreateOptions(util.NewFactory(), genericiooptions.NewTestIOStreamsDiscard())
c.ClusterDefRef = o.clusterDef
// c.ClusterVersionRef = o.clusterVersion
c.Namespace = defaultNamespace
c.Name = kbClusterName
c.UpdatableFlags = cmdcluster.UpdatableFlags{
TerminationPolicy: "WipeOut",
DisableExporter: false,
PodAntiAffinity: "Preferred",
Tenancy: "SharedNode",
}
// if we are running on local, create cluster with one replica
if o.cloudProvider == cp.Local {
c.Values = append(c.Values, "replicas=1")
} else {
// if we are running on cloud, create cluster with three replicas
c.Values = append(c.Values, "replicas=3")
c, err := cmdcluster.NewSubCmdsOptions(&cmdcluster.NewCreateOptions(util.NewFactory(), genericiooptions.NewTestIOStreamsDiscard()).CreateOptions, cluster.ClusterType(o.clusterType))
if err != nil {
return err
}
if err := c.CreateOptions.Complete(); err != nil {
c.Args = []string{kbClusterName}
err = c.CreateOptions.Complete()
if err != nil {
return err
}
if err := c.Validate(); err != nil {
err = c.Complete(nil)
if err != nil {
return err
}
if err := c.Complete(); err != nil {
err = c.Validate()
if err != nil {
return err
}
return c.Run()*/
return nil
return c.Run()
}

// checkExistedCluster checks playground kubernetes cluster exists or not, a kbcli client only
Expand Down
9 changes: 4 additions & 5 deletions pkg/cmd/playground/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ var _ = Describe("playground", func() {
Expect(cmd != nil).Should(BeTrue())

o := &initOptions{
clusterDef: clitesting.ClusterDefName,
clusterType: clitesting.ClusterType,
IOStreams: streams,
cloudProvider: defaultCloudProvider,
helmCfg: helm.NewConfig("", testKubeConfigPath, "", false),
Expand All @@ -61,14 +61,13 @@ var _ = Describe("playground", func() {
Expect(o.validate()).Should(Succeed())
Expect(o.run()).Should(HaveOccurred())
Expect(o.installKubeBlocks("test")).Should(HaveOccurred())
// TODO: re-add it when updating cluster creation function
// Expect(o.createCluster()).Should(HaveOccurred())
Expect(o.createCluster()).Should(HaveOccurred())
})

It("init at local host without outdate docker", func() {
var err error
o := &initOptions{
clusterDef: clitesting.ClusterDefName,
clusterType: clitesting.ClusterType,
IOStreams: streams,
cloudProvider: defaultCloudProvider,
helmCfg: helm.NewConfig("", testKubeConfigPath, "", false),
Expand All @@ -81,7 +80,7 @@ var _ = Describe("playground", func() {
It("init at remote cloud", func() {
o := &initOptions{
IOStreams: streams,
clusterDef: clitesting.ClusterDefName,
clusterType: clitesting.ClusterType,
cloudProvider: cp.AWS,
}
Expect(o.validate()).Should(HaveOccurred())
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/playground/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const (

const (
defaultCloudProvider = cloudprovider.Local
defaultClusterDef = "apecloud-mysql"
defaultClusterType = "apecloud-mysql"

// defaultNamespace is the namespace of playground cluster
defaultNamespace = "default"
Expand Down
1 change: 1 addition & 0 deletions pkg/testing/fake.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const (
ClusterName = "fake-cluster-name"
Namespace = "fake-namespace"
ClusterDefName = "fake-cluster-definition"
ClusterType = "fake-cluster-Type"
CompDefName = "fake-component-definition"
ComponentName = "fake-component-name"
NodeName = "fake-node-name"
Expand Down

0 comments on commit 1e442d2

Please sign in to comment.