Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: playground init command waits cd and cv #424

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ require (
github.com/go-git/go-git/v5 v5.6.1
github.com/go-logr/logr v1.4.1
github.com/google/uuid v1.6.0
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/go-version v1.7.0
github.com/hashicorp/hc-install v0.5.2
github.com/hashicorp/terraform-exec v0.18.0
github.com/jedib0t/go-pretty/v6 v6.4.6
Expand Down
7 changes: 2 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,6 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuW
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18=
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM=
github.com/apecloud/kubeblocks v0.9.0-beta.32 h1:DUztOHGW17ceN0etYMdYIj8dUK1MPCXX+gkd2CUf6XM=
github.com/apecloud/kubeblocks v0.9.0-beta.32/go.mod h1:kp9nenBgXsO03SbxN7a5S2HdNTsIQlpTcSgY8Mf2KS0=
github.com/apecloud/kubeblocks v0.9.1-beta.6 h1:/7k80XnLzJxhW+CaUgiIThm6JlCto+giNqscl6fKU6s=
github.com/apecloud/kubeblocks v0.9.1-beta.6/go.mod h1:kp9nenBgXsO03SbxN7a5S2HdNTsIQlpTcSgY8Mf2KS0=
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
Expand Down Expand Up @@ -753,8 +751,9 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
Expand Down Expand Up @@ -2101,8 +2100,6 @@ k8s.io/cli-runtime v0.28.3/go.mod h1:jeX37ZPjIcENVuXDDTskG3+FnVuZms5D9omDXS/2Jjc
k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4=
k8s.io/client-go v0.28.3/go.mod h1:LTykbBp9gsA7SwqirlCXBWtK0guzfhpoW4qSm7i9dxo=
k8s.io/code-generator v0.28.3/go.mod h1:A2EAHTRYvCvBrb/MM2zZBNipeCk3f8NtpdNIKawC43M=
k8s.io/component-base v0.28.3 h1:rDy68eHKxq/80RiMb2Ld/tbH8uAE75JdCqJyi6lXMzI=
k8s.io/component-base v0.28.3/go.mod h1:fDJ6vpVNSk6cRo5wmDa6eKIG7UlIQkaFmZN2fYgIUD8=
k8s.io/component-base v0.29.0 h1:T7rjd5wvLnPBV1vC4zWd/iWRbV8Mdxs+nGaoaFzGw3s=
k8s.io/component-base v0.29.0/go.mod h1:sADonFTQ9Zc9yFLghpDpmNXEdHyQmFIGbiuZbqAXQ1M=
k8s.io/component-helpers v0.28.3 h1:te9ieTGzcztVktUs92X53P6BamAoP73MK0qQP0WmDqc=
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/cluster/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ func NewCreateCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.
registerFlagCompletionFunc(cmd, f)

// add all subcommands for supported cluster type
cmd.AddCommand(buildCreateSubCmds(&o.CreateOptions)...)
cmd.AddCommand(BuildCreateSubCmds(&o.CreateOptions)...)

o.Cmd = cmd

Expand Down
10 changes: 5 additions & 5 deletions pkg/cmd/cluster/create_subcmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func NewSubCmdsOptions(createOptions *action.CreateOptions, t cluster.ClusterTyp
return o, nil
}

func buildCreateSubCmds(createOptions *action.CreateOptions) []*cobra.Command {
func BuildCreateSubCmds(createOptions *action.CreateOptions) []*cobra.Command {
var cmds []*cobra.Command

for _, t := range cluster.SupportedTypes() {
Expand All @@ -86,8 +86,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 All @@ -102,7 +102,7 @@ func buildCreateSubCmds(createOptions *action.CreateOptions) []*cobra.Command {
return cmds
}

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 Down Expand Up @@ -154,7 +154,7 @@ func (o *CreateSubCmdsOptions) complete(cmd *cobra.Command) error {
return nil
}

func (o *CreateSubCmdsOptions) validate() error {
func (o *CreateSubCmdsOptions) Validate() error {
return cluster.ValidateValues(o.ChartInfo, o.Values)
}

Expand Down
6 changes: 3 additions & 3 deletions pkg/cmd/cluster/create_subcmds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ var _ = Describe("create cluster by cluster type", func() {

It("create mysql cluster command", func() {
By("create commands")
cmds := buildCreateSubCmds(createOptions)
cmds := BuildCreateSubCmds(createOptions)
Expect(cmds).ShouldNot(BeNil())
Expect(cmds[0].HasFlags()).Should(BeTrue())

Expand All @@ -110,14 +110,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
111 changes: 110 additions & 1 deletion pkg/cmd/playground/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package playground

import (
"context"
"fmt"
"os"
"path/filepath"
Expand All @@ -29,15 +30,19 @@ import (
gv "github.com/hashicorp/go-version"
"github.com/pkg/errors"
"github.com/spf13/cobra"

"golang.org/x/exp/slices"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/rand"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/cli-runtime/pkg/genericiooptions"
"k8s.io/klog/v2"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"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"
Expand All @@ -47,6 +52,7 @@ import (
"github.com/apecloud/kbcli/pkg/util/helm"
"github.com/apecloud/kbcli/pkg/util/prompt"
"github.com/apecloud/kbcli/version"
"github.com/apecloud/kubeblocks/pkg/constant"
)

var (
Expand Down Expand Up @@ -419,6 +425,9 @@ func (o *initOptions) installKBAndCluster(info *cp.K8sClusterInfo) error {
}
s := spinner.New(o.Out, spinnerMsg("Create cluster %s (%s)", kbClusterName, clusterInfo))
defer s.Fail()
if err = o.waitClusterDef(); err != nil {
return errors.Wrapf(err, "failed to find clusterDefinition %s", o.clusterDef)
}
if err = o.createCluster(); err != nil && !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "failed to create cluster %s", kbClusterName)
}
Expand Down Expand Up @@ -519,7 +528,14 @@ func (o *initOptions) createCluster() error {
// if we are running on cloud, create cluster with three replicas
c.Values = append(c.Values, "replicas=3")
}

if err := o.checkClusterVersion(c); err != nil {
// if kubeblocks version greater than 1.0.0-alpha.0 or clusterVersion is not found
// within 30s, create cluster by create subcommand
if apierrors.IsNotFound(err) {
return o.createClusterBySubcmd(c)
}
return err
}
if err := c.CreateOptions.Complete(); err != nil {
return err
}
Expand All @@ -532,6 +548,99 @@ func (o *initOptions) createCluster() error {
return c.Run()
}

func (o *initOptions) checkClusterVersion(createOption *cmdcluster.CreateOptions) error {
v1, _ := gv.NewVersion("1.0.0-alpha.0")
version, _ := gv.NewVersion(o.kbVersion)
if len(o.kbVersion) == 0 || !version.LessThan(v1) {
// kubeblocks version greater than 1.0.0-alpha.0, there is no clusterVersion
return apierrors.NewNotFound(types.ClusterVersionGVR().GroupResource(), createOption.ClusterVersionRef)
}
// kubeblocks version less than 1.0.0-alpha.0, check clusterVersion
// assume clusterVersion is not defined if cannot find cluterVersion within 30s
dynamic, err := createOption.Factory.DynamicClient()
if err != nil {
return err
}
conditionFunc := func(_ context.Context) (bool, error) {
objs, err := dynamic.Resource(types.ClusterVersionGVR()).List(context.TODO(), metav1.ListOptions{
LabelSelector: fmt.Sprintf("%s=%s", constant.ClusterDefLabelKey, createOption.ClusterDefRef),
})
if err != nil && !apierrors.IsNotFound(err) {
return false, err
}
if objs == nil || len(objs.Items) == 0 {
return false, nil
}
return true, nil
}
// wait clusterVersion to be found, or a 30-second timeout
if err := wait.PollUntilContextTimeout(context.Background(), 5*time.Second, 30*time.Second, true, conditionFunc); err != nil {
if err == context.DeadlineExceeded {
return apierrors.NewNotFound(types.ClusterVersionGVR().GroupResource(), createOption.ClusterVersionRef)
}
return err
}
return nil
}

func (o *initOptions) createClusterBySubcmd(createOption *cmdcluster.CreateOptions) error {
opt, err := cmdcluster.NewSubCmdsOptions(&createOption.CreateOptions, cluster.ClusterType(o.clusterDef))
if err != nil {
return err
}
opt.CreateOptions.Format = "yaml"
if err := opt.CreateOptions.Complete(); err != nil {
return nil
}
if err := opt.Complete(&cobra.Command{}); err != nil {
return nil
}
if opt.Values == nil {
opt.Values = map[string]interface{}{}
}
// if we are running on local, create cluster with one replica
if o.cloudProvider == cp.Local {
opt.Values["replicas"] = int(1)
} else {
// if we are running on cloud, create cluster with three replicas
opt.Values["replicas"] = int(3)
if o.clusterDef == "apecloud-mysql" {
opt.Values["mode"] = "raftGroup"
}
}
if err := opt.Validate(); err != nil {
return err
}
if err := opt.Run(); err != nil {
return err
}
return nil
}

func (o *initOptions) waitClusterDef() error {
f := util.NewFactory()
dynamic, err := f.DynamicClient()
if err != nil {
return err
}
conditionFunc := func(_ context.Context) (bool, error) {
_, err := dynamic.Resource(types.ClusterDefGVR()).Get(context.Background(), o.clusterDef, metav1.GetOptions{})
if err == nil {
return true, nil
}
if apierrors.IsNotFound(err) {
return false, nil
}
return false, err
}

// wait clusterDefinition to be found, or timeout
if err := wait.PollUntilContextTimeout(context.Background(), 5*time.Second, o.Timeout, true, conditionFunc); err != nil {
return err
}
return nil
}

// checkExistedCluster checks playground kubernetes cluster exists or not, a kbcli client only
// support a single playground, they are bound to each other with a hidden context config file,
// the hidden file ensures that when destroy the playground it always goes with the fixed context,
Expand Down
Loading