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

feat: add support to set all the arguments of greptime helm chart #99

Merged
merged 5 commits into from
Aug 1, 2023
Merged
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: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/onsi/ginkgo/v2 v2.4.0
github.com/onsi/gomega v1.23.0
github.com/spf13/cobra v1.6.1
github.com/stretchr/testify v1.8.2
gopkg.in/yaml.v3 v3.0.1
helm.sh/helm/v3 v3.11.1
k8s.io/api v0.26.0
Expand Down Expand Up @@ -102,6 +103,7 @@ require (
github.com/opencontainers/image-spec v1.1.0-rc2 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
Expand Down
90 changes: 90 additions & 0 deletions pkg/cmd/gtctl/cluster/create/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright 2023 Greptime Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package create

import (
"fmt"
"strings"
)

const (
// Various of support config type
configOperator = "operator"
configCluster = "cluster"
configEtcd = "etcd"
)

type configValues struct {
rawConfig []string

operatorConfig string
clusterConfig string
etcdConfig string
}

// parseConfig parse raw config values and classify it to different
// categories of config type by its prefix.
func (c *configValues) parseConfig() error {
var (
operatorConfig []string
clusterConfig []string
etcdConfig []string
)

for _, raw := range c.rawConfig {
if len(raw) == 0 {
return fmt.Errorf("cannot parse empty config values")
}

var configPrefix, configValue string
values := strings.Split(raw, ",")

for _, value := range values {
value = strings.Trim(value, " ")
config := strings.SplitN(value, ".", 2)
configPrefix = config[0]
if len(config) == 2 {
configValue = config[1]
} else {
configValue = configPrefix
}
zyy17 marked this conversation as resolved.
Show resolved Hide resolved

switch configPrefix {
case configOperator:
operatorConfig = append(operatorConfig, configValue)
case configCluster:
clusterConfig = append(clusterConfig, configValue)
case configEtcd:
etcdConfig = append(etcdConfig, configValue)
default:
clusterConfig = append(clusterConfig, value)
zyy17 marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

if len(operatorConfig) > 0 {
c.operatorConfig = strings.Join(operatorConfig, ",")
}

if len(clusterConfig) > 0 {
c.clusterConfig = strings.Join(clusterConfig, ",")
}

if len(etcdConfig) > 0 {
c.etcdConfig = strings.Join(etcdConfig, ",")
}

return nil
}
80 changes: 80 additions & 0 deletions pkg/cmd/gtctl/cluster/create/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright 2023 Greptime Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package create

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestParseConfig(t *testing.T) {
testCases := []struct {
name string
config []string
expect configValues
err bool
}{
{
name: "all-with-prefix",
config: []string{"cluster.foo=bar", "etcd.foo=bar", "operator.foo=bar"},
expect: configValues{
clusterConfig: "foo=bar",
etcdConfig: "foo=bar",
operatorConfig: "foo=bar",
},
},
{
name: "all-without-prefix",
config: []string{"foo=bar", "foo.boo=bar", "foo.boo.coo=bar"},
expect: configValues{
clusterConfig: "foo=bar,foo.boo=bar,foo.boo.coo=bar",
},
},
{
name: "mix-with-prefix",
config: []string{"etcd.foo=bar", "foo.boo=bar", "foo.boo.coo=bar"},
expect: configValues{
clusterConfig: "foo.boo=bar,foo.boo.coo=bar",
etcdConfig: "foo=bar",
},
},
{
name: "empty-values",
config: []string{""},
err: true,
},
{
name: "empty-config",
config: []string{},
expect: configValues{},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
actual := configValues{rawConfig: tc.config}
err := actual.parseConfig()

if tc.err {
assert.Error(t, err)
return
}

tc.expect.rawConfig = tc.config
assert.Equal(t, tc.expect, actual)
})
}
}
21 changes: 15 additions & 6 deletions pkg/cmd/gtctl/cluster/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package create
import (
"context"
"fmt"
"io/ioutil"
"os"
"time"

Expand Down Expand Up @@ -59,6 +58,7 @@ type createClusterCliOptions struct {
// Common options.
Timeout int
DryRun bool
Set configValues
}

func NewCreateClusterCommand(l logger.Logger) *cobra.Command {
Expand Down Expand Up @@ -96,18 +96,23 @@ func NewCreateClusterCommand(l logger.Logger) *cobra.Command {
l.V(0).Infof("Creating GreptimeDB cluster '%s' on bare-metal environment...", logger.Bold(clusterName))
}

// Parse config values that set in command line
if err = options.Set.parseConfig(); err != nil {
return err
}

if !options.BareMetal {
if err := deployGreptimeDBOperator(ctx, l, &options, spinner, clusterDeployer); err != nil {
if err = deployGreptimeDBOperator(ctx, l, &options, spinner, clusterDeployer); err != nil {
return err
}
}

if err := deployEtcdCluster(ctx, l, &options, spinner, clusterDeployer, clusterName); err != nil {
if err = deployEtcdCluster(ctx, l, &options, spinner, clusterDeployer, clusterName); err != nil {
spinner.Stop(false, "Installing etcd cluster failed")
return err
}

if err := deployGreptimeDBCluster(ctx, l, &options, spinner, clusterDeployer, clusterName); err != nil {
if err = deployGreptimeDBCluster(ctx, l, &options, spinner, clusterDeployer, clusterName); err != nil {
return err
}

Expand Down Expand Up @@ -144,10 +149,11 @@ func NewCreateClusterCommand(l logger.Logger) *cobra.Command {
cmd.Flags().StringVarP(&options.Namespace, "namespace", "n", "default", "Namespace of GreptimeDB cluster.")
cmd.Flags().BoolVar(&options.DryRun, "dry-run", false, "Output the manifests without applying them.")
cmd.Flags().IntVar(&options.Timeout, "timeout", -1, "Timeout in seconds for the command to complete, default is no timeout.")
cmd.Flags().StringArrayVar(&options.Set.rawConfig, "set", []string{}, "set values on the command line for greptimedb cluster, etcd and operator (can specify multiple or separate values with commas: eg. cluster.key1=val1,etcd.key2=val2).")
cmd.Flags().StringVar(&options.GreptimeDBChartVersion, "greptimedb-chart-version", "", "The greptimedb helm chart version, use latest version if not specified.")
cmd.Flags().StringVar(&options.GreptimeDBOperatorChartVersion, "greptimedb-operator-chart-version", "", "The greptimedb-operator helm chart version, use latest version if not specified.")
cmd.Flags().StringVar(&options.EtcdChartVersion, "etcd-chart-version", "", "The greptimedb-etcd helm chart version, use latest version if not specified.")
cmd.Flags().StringVar(&options.ImageRegistry, "image-registry", "", "The image registry")
cmd.Flags().StringVar(&options.ImageRegistry, "image-registry", "", "The image registry.")
cmd.Flags().StringVar(&options.EtcdNamespace, "etcd-namespace", "default", "The namespace of etcd cluster.")
cmd.Flags().StringVar(&options.EtcdStorageClassName, "etcd-storage-class-name", "standard", "The etcd storage class name.")
cmd.Flags().StringVar(&options.EtcdStorageSize, "etcd-storage-size", "10Gi", "the etcd persistent volume size.")
Expand Down Expand Up @@ -178,7 +184,7 @@ func newDeployer(l logger.Logger, clusterName string, options *createClusterCliO

if options.Config != "" {
var config baremetal.Config
data, err := ioutil.ReadFile(options.Config)
data, err := os.ReadFile(options.Config)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -210,6 +216,7 @@ func deployGreptimeDBOperator(ctx context.Context, l logger.Logger, options *cre
createGreptimeDBOperatorOptions := &deployer.CreateGreptimeDBOperatorOptions{
GreptimeDBOperatorChartVersion: options.GreptimeDBOperatorChartVersion,
ImageRegistry: options.ImageRegistry,
ConfigValues: options.Set.operatorConfig,
}

name := types.NamespacedName{Namespace: options.OperatorNamespace, Name: "greptimedb-operator"}.String()
Expand Down Expand Up @@ -238,6 +245,7 @@ func deployEtcdCluster(ctx context.Context, l logger.Logger, options *createClus
EtcdStorageClassName: options.EtcdStorageClassName,
EtcdStorageSize: options.EtcdStorageSize,
EtcdDataDir: options.EtcdDataDir,
ConfigValues: options.Set.etcdConfig,
}

var name string
Expand Down Expand Up @@ -274,6 +282,7 @@ func deployGreptimeDBCluster(ctx context.Context, l logger.Logger, options *crea
DatanodeStorageSize: options.StorageSize,
DatanodeStorageRetainPolicy: options.StorageRetainPolicy,
EtcdEndPoint: fmt.Sprintf("%s.%s:2379", common.EtcdClusterName(clusterName), options.EtcdNamespace),
ConfigValues: options.Set.clusterConfig,
}

var name string
Expand Down
3 changes: 3 additions & 0 deletions pkg/deployer/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ type CreateGreptimeDBClusterOptions struct {
DatanodeStorageSize string `helm:"datanode.storage.storageSize"`
DatanodeStorageRetainPolicy string `helm:"datanode.storage.storageRetainPolicy"`
EtcdEndPoint string `helm:"etcdEndpoints"`
ConfigValues string `helm:"*"`
}

// UpdateGreptimeDBClusterOptions is the options to update a GreptimeDB cluster.
Expand All @@ -94,6 +95,7 @@ type CreateEtcdClusterOptions struct {
EtcdStorageClassName string `helm:"storage.storageClassName"`
EtcdStorageSize string `helm:"storage.volumeSize"`
EtcdDataDir string `helm:"storage.dataDir"`
ConfigValues string `helm:"*"`
}

// DeleteEtcdClusterOption is the options to delete an etcd cluster.
Expand All @@ -104,4 +106,5 @@ type CreateGreptimeDBOperatorOptions struct {
GreptimeDBOperatorChartVersion string

ImageRegistry string `helm:"image.registry"`
ConfigValues string `helm:"*"`
}
8 changes: 6 additions & 2 deletions pkg/helm/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,12 @@ func (r *Render) GenerateHelmValues(input interface{}) (map[string]interface{},
typeOf := reflect.TypeOf(input)
for i := 0; i < valueOf.NumField(); i++ {
helmValueKey := typeOf.Field(i).Tag.Get(helmFieldTag)
if helmValueKey != "" && valueOf.Field(i).Len() > 0 {
rawArgs = append(rawArgs, fmt.Sprintf("%s=%s", helmValueKey, valueOf.Field(i)))
if len(helmValueKey) > 0 && valueOf.Field(i).Len() > 0 {
if helmValueKey == "*" {
shawnh2 marked this conversation as resolved.
Show resolved Hide resolved
rawArgs = append(rawArgs, valueOf.Field(i).String())
} else {
rawArgs = append(rawArgs, fmt.Sprintf("%s=%s", helmValueKey, valueOf.Field(i)))
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions pkg/helm/helm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ func TestRender_GenerateGreptimeDBHelmValues(t *testing.T) {
DatanodeStorageRetainPolicy: "Delete",
EtcdEndPoint: "127.0.0.1:2379",
InitializerImageRegistry: "registry.cn-hangzhou.aliyuncs.com",
ConfigValues: "meta.replicas=4",
}

r := &Render{}
Expand All @@ -122,6 +123,7 @@ func TestRender_GenerateGreptimeDBHelmValues(t *testing.T) {
"datanode.storage.storageRetainPolicy=Delete",
"etcdEndpoints=127.0.0.1:2379",
"initializer.registry=registry.cn-hangzhou.aliyuncs.com",
"meta.replicas=4",
}

valuesWanted, err := strvals.Parse(strings.Join(ArgsStr, ","))
Expand All @@ -139,6 +141,7 @@ func TestRender_GenerateGreptimeDBOperatorHelmValues(t *testing.T) {
options := deployer.CreateGreptimeDBOperatorOptions{
GreptimeDBOperatorChartVersion: "",
ImageRegistry: "registry.cn-hangzhou.aliyuncs.com",
ConfigValues: "replicas=3",
}

r := &Render{}
Expand All @@ -149,6 +152,7 @@ func TestRender_GenerateGreptimeDBOperatorHelmValues(t *testing.T) {

ArgsStr := []string{
"image.registry=registry.cn-hangzhou.aliyuncs.com",
"replicas=3",
}

valuesWanted, err := strvals.Parse(strings.Join(ArgsStr, ","))
Expand All @@ -169,6 +173,7 @@ func TestRender_GenerateEtcdHelmValues(t *testing.T) {
EtcdStorageClassName: "ebs-sc",
EtcdStorageSize: "11Gi",
EtcdDataDir: "/var/etcd",
ConfigValues: "image.tag=latest",
}

r := &Render{}
Expand All @@ -182,6 +187,7 @@ func TestRender_GenerateEtcdHelmValues(t *testing.T) {
"storage.storageClassName=ebs-sc",
"storage.volumeSize=11Gi",
"storage.dataDir=/var/etcd",
"image.tag=latest",
}

valuesWanted, err := strvals.Parse(strings.Join(ArgsStr, ","))
Expand Down
Loading