Skip to content

Commit 0c4cb58

Browse files
authored
reimplement cluster connect cmd (GreptimeTeam#180)
Signed-off-by: sh2 <[email protected]>
1 parent 412ad43 commit 0c4cb58

File tree

12 files changed

+139
-357
lines changed

12 files changed

+139
-357
lines changed

cmd/gtctl/cluster_connect.go

Lines changed: 19 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,10 @@ import (
1818
"context"
1919
"fmt"
2020

21-
greptimedbclusterv1alpha1 "github.com/GreptimeTeam/greptimedb-operator/apis/v1alpha1"
2221
"github.com/spf13/cobra"
23-
"k8s.io/apimachinery/pkg/api/errors"
24-
"k8s.io/apimachinery/pkg/types"
2522

26-
"github.com/GreptimeTeam/gtctl/pkg/connector"
27-
"github.com/GreptimeTeam/gtctl/pkg/deployer/k8s"
23+
opt "github.com/GreptimeTeam/gtctl/pkg/cluster"
24+
"github.com/GreptimeTeam/gtctl/pkg/cluster/kubernetes"
2825
"github.com/GreptimeTeam/gtctl/pkg/logger"
2926
)
3027

@@ -34,11 +31,6 @@ type clusterConnectCliOptions struct {
3431
}
3532

3633
func NewConnectCommand(l logger.Logger) *cobra.Command {
37-
const (
38-
connectionProtocolMySQL = "mysql"
39-
connectionProtocolPostgres = "pg"
40-
)
41-
4234
var options clusterConnectCliOptions
4335

4436
cmd := &cobra.Command{
@@ -50,50 +42,37 @@ func NewConnectCommand(l logger.Logger) *cobra.Command {
5042
return fmt.Errorf("cluster name should be set")
5143
}
5244

53-
k8sDeployer, err := k8s.NewDeployer(l)
54-
if err != nil {
55-
return err
56-
}
57-
5845
var (
5946
ctx = context.TODO()
6047
clusterName = args[0]
61-
namespace = options.Namespace
48+
protocol opt.ConnectProtocol
6249
)
6350

64-
name := types.NamespacedName{
65-
Namespace: options.Namespace,
66-
Name: clusterName,
67-
}.String()
68-
cluster, err := k8sDeployer.GetGreptimeDBCluster(ctx, name, nil)
69-
if err != nil && errors.IsNotFound(err) {
70-
l.Errorf("cluster %s in %s not found\n", clusterName, namespace)
71-
return nil
72-
}
73-
74-
rawCluster, ok := cluster.Raw.(*greptimedbclusterv1alpha1.GreptimeDBCluster)
75-
if !ok {
76-
return fmt.Errorf("invalid cluster type")
51+
cluster, err := kubernetes.NewCluster(l)
52+
if err != nil {
53+
return err
7754
}
7855

7956
switch options.Protocol {
80-
case connectionProtocolMySQL:
81-
if err = connector.MySQLConnectCommand(rawCluster, l); err != nil {
82-
return fmt.Errorf("error connecting to mysql: %v", err)
83-
}
84-
case connectionProtocolPostgres:
85-
if err = connector.PostgresSQLConnectCommand(rawCluster, l); err != nil {
86-
return fmt.Errorf("error connecting to postgres: %v", err)
87-
}
57+
case "mysql":
58+
protocol = opt.MySQL
59+
case "pg", "psql", "postgres":
60+
protocol = opt.Postgres
8861
default:
89-
return fmt.Errorf("database type not supported: %s", options.Protocol)
62+
return fmt.Errorf("unsupported connection protocol: %s", options.Protocol)
9063
}
91-
return nil
64+
connectOptions := &opt.ConnectOptions{
65+
Namespace: options.Namespace,
66+
Name: clusterName,
67+
Protocol: protocol,
68+
}
69+
70+
return cluster.Connect(ctx, connectOptions)
9271
},
9372
}
9473

9574
cmd.Flags().StringVarP(&options.Namespace, "namespace", "n", "default", "Namespace of GreptimeDB cluster.")
96-
cmd.Flags().StringVarP(&options.Protocol, "protocol", "p", "mysql", "Specify a database, like mysql or pg.")
75+
cmd.Flags().StringVarP(&options.Protocol, "protocol", "p", "mysql", "Specify a database protocol, like mysql or pg.")
9776

9877
return cmd
9978
}

cmd/gtctl/cluster_create.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ func NewCluster(args []string, options *clusterCreateCliOptions, l logger.Logger
172172
UseGreptimeCNArtifacts: options.UseGreptimeCNArtifacts,
173173
ValuesFile: options.GreptimeDBClusterValuesFile,
174174
},
175+
Spinner: spinner,
175176
}
176177

177178
var cluster opt.Operations
@@ -211,7 +212,7 @@ func NewCluster(args []string, options *clusterCreateCliOptions, l logger.Logger
211212
}
212213
}
213214

214-
if err = cluster.Create(ctx, createOptions, spinner); err != nil {
215+
if err = cluster.Create(ctx, createOptions); err != nil {
215216
return err
216217
}
217218

pkg/artifacts/constants.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const (
2121
// GreptimeChartReleaseDownloadURL is the URL of the Greptime charts that stored in the GitHub release.
2222
GreptimeChartReleaseDownloadURL = "https://github.com/GreptimeTeam/helm-charts/releases/download"
2323

24-
// Greptime release bucket public endpoint in CN region.
24+
// GreptimeReleaseBucketCN releases bucket public endpoint in CN region.
2525
GreptimeReleaseBucketCN = "https://downloads.greptime.cn/releases"
2626

2727
// GreptimeCNCharts is the URL of the Greptime charts that stored in the S3 bucket of the CN region.

pkg/cluster/baremetal/create.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,27 @@ import (
2626
"github.com/GreptimeTeam/gtctl/pkg/artifacts"
2727
opt "github.com/GreptimeTeam/gtctl/pkg/cluster"
2828
"github.com/GreptimeTeam/gtctl/pkg/logger"
29-
"github.com/GreptimeTeam/gtctl/pkg/status"
3029
fileutils "github.com/GreptimeTeam/gtctl/pkg/utils/file"
3130
)
3231

33-
func (c *Cluster) Create(ctx context.Context, options *opt.CreateOptions, spinner *status.Spinner) error {
32+
func (c *Cluster) Create(ctx context.Context, options *opt.CreateOptions) error {
33+
spinner := options.Spinner
34+
3435
withSpinner := func(target string, f func(context.Context, *opt.CreateOptions) error) error {
35-
spinner.Start(fmt.Sprintf("Installing %s...", target))
36+
if spinner != nil {
37+
spinner.Start(fmt.Sprintf("Installing %s...", target))
38+
}
39+
3640
if err := f(ctx, options); err != nil {
37-
spinner.Stop(false, fmt.Sprintf("Installing %s failed", target))
41+
if spinner != nil {
42+
spinner.Stop(false, fmt.Sprintf("Installing %s failed", target))
43+
}
3844
return err
3945
}
40-
spinner.Stop(true, fmt.Sprintf("Installing %s successfully 🎉", target))
46+
47+
if spinner != nil {
48+
spinner.Stop(true, fmt.Sprintf("Installing %s successfully 🎉", target))
49+
}
4150
return nil
4251
}
4352

pkg/cluster/baremetal/not_implemented.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,7 @@ func (c *Cluster) List(ctx context.Context, options *opt.ListOptions) error {
2828
func (c *Cluster) Scale(ctx context.Context, options *opt.ScaleOptions) error {
2929
return fmt.Errorf("do not support")
3030
}
31+
32+
func (c *Cluster) Connect(ctx context.Context, options *opt.ConnectOptions) error {
33+
return fmt.Errorf("do not support")
34+
}

pkg/cluster/kubernetes/connect.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2023 Greptime Team
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package kubernetes
16+
17+
import (
18+
"context"
19+
"fmt"
20+
"strconv"
21+
22+
greptimedbclusterv1alpha1 "github.com/GreptimeTeam/greptimedb-operator/apis/v1alpha1"
23+
"k8s.io/apimachinery/pkg/api/errors"
24+
25+
opt "github.com/GreptimeTeam/gtctl/pkg/cluster"
26+
"github.com/GreptimeTeam/gtctl/pkg/connector"
27+
)
28+
29+
func (c *Cluster) Connect(ctx context.Context, options *opt.ConnectOptions) error {
30+
cluster, err := c.get(ctx, &opt.GetOptions{
31+
Namespace: options.Namespace,
32+
Name: options.Name,
33+
})
34+
if err != nil && errors.IsNotFound(err) {
35+
c.logger.V(0).Infof("cluster %s in %s not found", options.Name, options.Namespace)
36+
return nil
37+
}
38+
39+
switch options.Protocol {
40+
case opt.MySQL:
41+
if err = c.connectMySQL(cluster); err != nil {
42+
return fmt.Errorf("error connecting to mysql: %v", err)
43+
}
44+
case opt.Postgres:
45+
if err = c.connectPostgres(cluster); err != nil {
46+
return fmt.Errorf("error connecting to postgres: %v", err)
47+
}
48+
default:
49+
return fmt.Errorf("unsupported connect protocol type")
50+
}
51+
52+
return nil
53+
}
54+
55+
func (c *Cluster) connectMySQL(cluster *greptimedbclusterv1alpha1.GreptimeDBCluster) error {
56+
return connector.Mysql(strconv.Itoa(int(cluster.Spec.MySQLServicePort)), cluster.Name, c.logger)
57+
}
58+
59+
func (c *Cluster) connectPostgres(cluster *greptimedbclusterv1alpha1.GreptimeDBCluster) error {
60+
return connector.PostgresSQL(strconv.Itoa(int(cluster.Spec.PostgresServicePort)), cluster.Name, c.logger)
61+
}

pkg/cluster/kubernetes/create.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"github.com/GreptimeTeam/gtctl/pkg/artifacts"
2222
opt "github.com/GreptimeTeam/gtctl/pkg/cluster"
2323
"github.com/GreptimeTeam/gtctl/pkg/helm"
24-
"github.com/GreptimeTeam/gtctl/pkg/status"
2524
)
2625

2726
const (
@@ -30,17 +29,25 @@ const (
3029
disableRBACConfig = "auth.rbac.create=false,auth.rbac.token.enabled=false,"
3130
)
3231

33-
func (c *Cluster) Create(ctx context.Context, options *opt.CreateOptions, spinner *status.Spinner) error {
32+
func (c *Cluster) Create(ctx context.Context, options *opt.CreateOptions) error {
33+
spinner := options.Spinner
34+
3435
withSpinner := func(target string, f func(context.Context, *opt.CreateOptions) error) error {
35-
if !c.dryRun {
36+
if !c.dryRun && spinner != nil {
3637
spinner.Start(fmt.Sprintf("Installing %s...", target))
3738
}
39+
3840
if err := f(ctx, options); err != nil {
39-
spinner.Stop(false, fmt.Sprintf("Installing %s failed", target))
41+
if spinner != nil {
42+
spinner.Stop(false, fmt.Sprintf("Installing %s failed", target))
43+
}
4044
return err
4145
}
46+
4247
if !c.dryRun {
43-
spinner.Stop(true, fmt.Sprintf("Installing %s successfully 🎉", target))
48+
if spinner != nil {
49+
spinner.Stop(true, fmt.Sprintf("Installing %s successfully 🎉", target))
50+
}
4451
}
4552
return nil
4653
}

pkg/cluster/types.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,13 @@ type Operations interface {
3535
Scale(ctx context.Context, options *ScaleOptions) error
3636

3737
// Create creates a new cluster.
38-
Create(ctx context.Context, options *CreateOptions, spinner *status.Spinner) error
38+
Create(ctx context.Context, options *CreateOptions) error
3939

4040
// Delete deletes a specific cluster.
4141
Delete(ctx context.Context, options *DeleteOptions) error
42+
43+
// Connect connects to a specific cluster.
44+
Connect(ctx context.Context, options *ConnectOptions) error
4245
}
4346

4447
type GetOptions struct {
@@ -74,6 +77,8 @@ type CreateOptions struct {
7477
Cluster *CreateClusterOptions
7578
Operator *CreateOperatorOptions
7679
Etcd *CreateEtcdOptions
80+
81+
Spinner *status.Spinner
7782
}
7883

7984
// CreateClusterOptions is the options to create a GreptimeDB cluster.
@@ -114,3 +119,16 @@ type CreateEtcdOptions struct {
114119
EtcdStorageSize string `helm:"persistence.size"`
115120
ConfigValues string `helm:"*"`
116121
}
122+
123+
type ConnectProtocol int
124+
125+
const (
126+
MySQL ConnectProtocol = iota
127+
Postgres
128+
)
129+
130+
type ConnectOptions struct {
131+
Namespace string
132+
Name string
133+
Protocol ConnectProtocol
134+
}

pkg/connector/mysql.go

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,9 @@ import (
2121
"net"
2222
"os"
2323
"os/exec"
24-
"strconv"
2524
"sync"
2625
"syscall"
2726

28-
greptimedbclusterv1alpha1 "github.com/GreptimeTeam/greptimedb-operator/apis/v1alpha1"
2927
"github.com/go-sql-driver/mysql"
3028

3129
"github.com/GreptimeTeam/gtctl/pkg/logger"
@@ -43,16 +41,11 @@ const (
4341
portForward = "port-forward"
4442
)
4543

46-
// MySQLConnectCommand connects to a GreptimeDB cluster
47-
func MySQLConnectCommand(rawCluster *greptimedbclusterv1alpha1.GreptimeDBCluster, l logger.Logger) error {
48-
return mysqlConnect(strconv.Itoa(int(rawCluster.Spec.MySQLServicePort)), rawCluster.Name, l)
49-
}
50-
51-
// mysqlConnect connects to a GreptimeDB cluster
52-
func mysqlConnect(port, clusterName string, l logger.Logger) error {
44+
// Mysql connects to a GreptimeDB cluster using mysql protocol.
45+
func Mysql(port, clusterName string, l logger.Logger) error {
5346
waitGroup := sync.WaitGroup{}
5447

55-
// TODO(sh2): is there any elegant way to enable port-forward?
48+
// TODO: is there any elegant way to enable port-forward?
5649
cmd := exec.CommandContext(context.Background(), kubectl, portForward, "-n", "default", "svc/"+clusterName+"-frontend", fmt.Sprintf("%s:%s", port, port))
5750
if err := cmd.Start(); err != nil {
5851
l.Errorf("Error starting port-forwarding: %v", err)

pkg/connector/postgres.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@ import (
2020
"net"
2121
"os"
2222
"os/exec"
23-
"strconv"
2423
"sync"
2524
"syscall"
2625

27-
greptimedbclusterv1alpha1 "github.com/GreptimeTeam/greptimedb-operator/apis/v1alpha1"
2826
"github.com/go-pg/pg/v10"
2927

3028
"github.com/GreptimeTeam/gtctl/pkg/logger"
@@ -41,14 +39,11 @@ const (
4139
postgresSQLDatabaseArg = "-d"
4240
)
4341

44-
func PostgresSQLConnectCommand(rawCluster *greptimedbclusterv1alpha1.GreptimeDBCluster, l logger.Logger) error {
45-
return postgresSQLConnect(strconv.Itoa(int(rawCluster.Spec.PostgresServicePort)), rawCluster.Name, l)
46-
}
47-
48-
func postgresSQLConnect(port, clusterName string, l logger.Logger) error {
42+
// PostgresSQL connects to a GreptimeDB cluster using postgres protocol.
43+
func PostgresSQL(port, clusterName string, l logger.Logger) error {
4944
waitGroup := sync.WaitGroup{}
5045

51-
// TODO(sh2): is there any elegant way to enable port-forward?
46+
// TODO: is there any elegant way to enable port-forward?
5247
cmd := exec.CommandContext(context.Background(), kubectl, portForward, "-n", "default", "svc/"+clusterName+"-frontend", fmt.Sprintf("%s:%s", port, port))
5348
if err := cmd.Start(); err != nil {
5449
l.Errorf("Error starting port-forwarding: %v", err)

0 commit comments

Comments
 (0)