Skip to content

Commit

Permalink
feat: tenant management
Browse files Browse the repository at this point in the history
chore: add alias for commands

refactor: refactor create generic

feat: tenant delete

feat: parameter config for obcluster

feat: tenant list

chore: add ci and dockerfile for cli

fix: check when creating tenant

fix: bug in creating tenant and cluster

feat: changepwd of obtenant

feat: tenant upgrade, changepwd, switchover, show ,list, etc.

feat: tenant management finish

chore: make lint

refactor: add status error handler

chore: add alias for cmds

feat: add more cmd for tenant management

refactor: scale and show in cluster

refactor: check if flags changed
  • Loading branch information
lizzy-0323 committed Sep 26, 2024
1 parent 0c2fb7e commit e621b00
Show file tree
Hide file tree
Showing 45 changed files with 2,332 additions and 159 deletions.
19 changes: 19 additions & 0 deletions build/Dockerfile.cli
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Build the manager binary
FROM golang:1.22 as builder

ARG GOPROXY=https://goproxy.io,direct
ARG GOSUMDB=sum.golang.org

WORKDIR /workspace
# copy everything
COPY . .
RUN make cli-dep-install cli-build

# start build docker image
FROM openanolis/anolisos:8.8
WORKDIR /
COPY --from=builder /workspace/bin/obocli .
RUN yum update -y && yum clean all
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

ENTRYPOINT ["/obocli"]
135 changes: 77 additions & 58 deletions internal/cli/cluster/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ See the Mulan PSL v2 for more details.
package cluster

import (
"errors"
"fmt"

apitypes "github.com/oceanbase/ob-operator/api/types"
Expand All @@ -28,13 +29,14 @@ import (
apiresource "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/oceanbase/ob-operator/internal/cli/generic"
utils "github.com/oceanbase/ob-operator/internal/cli/utils"
modelcommon "github.com/oceanbase/ob-operator/internal/dashboard/model/common"
param "github.com/oceanbase/ob-operator/internal/dashboard/model/param"
)

type CreateOptions struct {
ResourceOptions
generic.ResourceOptions
ClusterName string `json:"clusterName"`
ClusterId int64 `json:"clusterId"`
RootPassword string `json:"rootPassword"`
Expand All @@ -44,6 +46,7 @@ type CreateOptions struct {
Parameters []modelcommon.KVPair `json:"parameters"`
BackupVolume *param.NFSVolumeSpec `json:"backupVolume"`
Zones map[string]string `json:"zones"`
KvParameters map[string]string `json:"kvParameters"`
Mode string `json:"mode"`
}

Expand All @@ -59,6 +62,9 @@ func NewCreateOptions() *CreateOptions {
}

func (o *CreateOptions) Validate() error {
if o.Namespace == "" {
return errors.New("namespace not specified")
}
if !utils.CheckPassword(o.RootPassword) {
return fmt.Errorf("Password is not secure, must contain at least 2 uppercase and lowercase letters, numbers and special characters")
}
Expand All @@ -73,6 +79,11 @@ func (o *CreateOptions) Parse(_ *cobra.Command, args []string) error {
if err != nil {
return err
}
parameters, err := utils.MapParameters(o.KvParameters)
if err != nil {
return err
}
o.Parameters = parameters
o.Topology = topology
o.Name = args[0]
return nil
Expand All @@ -81,7 +92,7 @@ func (o *CreateOptions) Parse(_ *cobra.Command, args []string) error {
func (o *CreateOptions) Complete() error {
// if not specific id, using timestamp
if o.ClusterId == 0 {
o.ClusterId = utils.GenerateClusterId()
o.ClusterId = utils.GenerateClusterID()
}
// if not specific password, using random password, range [8,32]
if o.RootPassword == "" {
Expand All @@ -93,62 +104,6 @@ func (o *CreateOptions) Complete() error {
return nil
}

func (o *CreateOptions) AddFlags(cmd *cobra.Command) {
// Add base and specific feature flags, Only support observer and zone config
o.AddBaseFlags(cmd)
o.AddObserverFlags(cmd)
o.AddZoneFlags(cmd)
}

// AddZoneFlags adds the zone-related flags to the command.
func (o *CreateOptions) AddZoneFlags(cmd *cobra.Command) {
zoneFlags := pflag.NewFlagSet("zone", pflag.ContinueOnError)
zoneFlags.StringToStringVarP(&o.Zones, "zones", "z", map[string]string{"z1": "1"}, "The zones of the cluster in the format 'zone=value', multiple values can be provided separated by commas")
cmd.Flags().AddFlagSet(zoneFlags)
}

// AddBaseFlags adds the base flags to the command.
func (o *CreateOptions) AddBaseFlags(cmd *cobra.Command) {
baseFlags := cmd.Flags()
baseFlags.StringVar(&o.Name, "name", "", "The name in k8s, if not specified, use cluster name")
baseFlags.StringVar(&o.Namespace, "namespace", "default", "The namespace of the cluster")
baseFlags.Int64Var(&o.ClusterId, "id", 0, "The id of the cluster")
baseFlags.StringVar(&o.RootPassword, "root-password", "", "The root password of the cluster")
baseFlags.StringVar(&o.Mode, "mode", "", "The mode of the cluster")
}

// AddObserverFlags adds the observer-related flags to the command.
func (o *CreateOptions) AddObserverFlags(cmd *cobra.Command) {
observerFlags := pflag.NewFlagSet("observer", pflag.ContinueOnError)
observerFlags.StringVar(&o.OBServer.Image, "image", "oceanbase/oceanbase-cloud-native:4.2.1.6-106000012024042515", "The image of the observer")
observerFlags.Int64Var(&o.OBServer.Resource.Cpu, "cpu", 2, "The cpu of the observer")
observerFlags.Int64Var(&o.OBServer.Resource.MemoryGB, "memory", 10, "The memory of the observer")
observerFlags.StringVar(&o.OBServer.Storage.Data.StorageClass, "data-storage-class", "local-path", "The storage class of the data storage")
observerFlags.StringVar(&o.OBServer.Storage.RedoLog.StorageClass, "redo-log-storage-class", "local-path", "The storage class of the redo log storage")
observerFlags.StringVar(&o.OBServer.Storage.Log.StorageClass, "log-storage-class", "local-path", "The storage class of the log storage")
observerFlags.Int64Var(&o.OBServer.Storage.Data.SizeGB, "data-storage-size", 50, "The size of the data storage")
observerFlags.Int64Var(&o.OBServer.Storage.RedoLog.SizeGB, "redo-log-storage-size", 50, "The size of the redo log storage")
observerFlags.Int64Var(&o.OBServer.Storage.Log.SizeGB, "log-storage-size", 20, "The size of the log storage")
cmd.Flags().AddFlagSet(observerFlags)
}

// AddMonitorFlags adds the monitor-related flags to the command.
func (o *CreateOptions) AddMonitorFlags(cmd *cobra.Command) {
monitorFlags := pflag.NewFlagSet("monitor", pflag.ContinueOnError)
monitorFlags.StringVar(&o.Monitor.Image, "monitor-image", "oceanbase/obagent:4.2.1-100000092023101717", "The image of the monitor")
monitorFlags.Int64Var(&o.Monitor.Resource.Cpu, "monitor-cpu", 1, "The cpu of the monitor")
monitorFlags.Int64Var(&o.Monitor.Resource.MemoryGB, "monitor-memory", 1, "The memory of the monitor")
cmd.Flags().AddFlagSet(monitorFlags)
}

// AddBackupVolumeFlags adds the backup-volume-related flags to the command.
func (o *CreateOptions) AddBackupVolumeFlags(cmd *cobra.Command) {
backupVolumeFlags := pflag.NewFlagSet("backup-volume", pflag.ContinueOnError)
backupVolumeFlags.StringVar(&o.BackupVolume.Address, "backup-storage-class", "local-path", "The storage class of the backup storage")
backupVolumeFlags.StringVar(&o.BackupVolume.Path, "backup-storage-size", "/opt/nfs", "The size of the backup storage")
cmd.Flags().AddFlagSet(backupVolumeFlags)
}

func buildOBServerTemplate(observerSpec *param.OBServerSpec) *apitypes.OBServerTemplate {
if observerSpec == nil {
return nil
Expand Down Expand Up @@ -334,3 +289,67 @@ func CreateOBClusterInstance(param *CreateOptions) *v1alpha1.OBCluster {
}
return obcluster
}

// AddFlags adds base and specific feature flags, Only support observer and zone config
func (o *CreateOptions) AddFlags(cmd *cobra.Command) {
o.AddBaseFlags(cmd)
o.AddObserverFlags(cmd)
o.AddZoneFlags(cmd)
o.AddParameterFlags(cmd)
}

// AddZoneFlags adds the zone-related flags to the command.
func (o *CreateOptions) AddZoneFlags(cmd *cobra.Command) {
zoneFlags := pflag.NewFlagSet("zone", pflag.ContinueOnError)
zoneFlags.StringToStringVarP(&o.Zones, "zones", "z", map[string]string{"z1": "1"}, "The zones of the cluster in the format 'Zone=Replica', multiple values can be provided separated by commas")
cmd.Flags().AddFlagSet(zoneFlags)
}

// AddBaseFlags adds the base flags to the command.
func (o *CreateOptions) AddBaseFlags(cmd *cobra.Command) {
baseFlags := cmd.Flags()
baseFlags.StringVarP(&o.ClusterName, "cluster-name", "n", "", "Cluster name, if not specified, use resource name in k8s instead")
baseFlags.StringVar(&o.Namespace, "namespace", "default", "The namespace of the cluster")
baseFlags.Int64Var(&o.ClusterId, "id", 0, "The id of the cluster")
baseFlags.StringVarP(&o.RootPassword, "root-password", "p", "", "The root password of the cluster")
baseFlags.StringVar(&o.Mode, "mode", "", "The mode of the cluster")
}

// AddObserverFlags adds the observer-related flags to the command.
func (o *CreateOptions) AddObserverFlags(cmd *cobra.Command) {
observerFlags := pflag.NewFlagSet("observer", pflag.ContinueOnError)
observerFlags.StringVar(&o.OBServer.Image, "image", "oceanbase/oceanbase-cloud-native:4.2.1.6-106000012024042515", "The image of the observer")
observerFlags.Int64Var(&o.OBServer.Resource.Cpu, "cpu", 2, "The cpu of the observer")
observerFlags.Int64Var(&o.OBServer.Resource.MemoryGB, "memory", 10, "The memory of the observer")
observerFlags.StringVar(&o.OBServer.Storage.Data.StorageClass, "data-storage-class", "local-path", "The storage class of the data storage")
observerFlags.StringVar(&o.OBServer.Storage.RedoLog.StorageClass, "redo-log-storage-class", "local-path", "The storage class of the redo log storage")
observerFlags.StringVar(&o.OBServer.Storage.Log.StorageClass, "log-storage-class", "local-path", "The storage class of the log storage")
observerFlags.Int64Var(&o.OBServer.Storage.Data.SizeGB, "data-storage-size", 50, "The size of the data storage")
observerFlags.Int64Var(&o.OBServer.Storage.RedoLog.SizeGB, "redo-log-storage-size", 50, "The size of the redo log storage")
observerFlags.Int64Var(&o.OBServer.Storage.Log.SizeGB, "log-storage-size", 20, "The size of the log storage")
cmd.Flags().AddFlagSet(observerFlags)
}

// AddMonitorFlags adds the monitor-related flags to the command.
func (o *CreateOptions) AddMonitorFlags(cmd *cobra.Command) {
monitorFlags := pflag.NewFlagSet("monitor", pflag.ContinueOnError)
monitorFlags.StringVar(&o.Monitor.Image, "monitor-image", "oceanbase/obagent:4.2.1-100000092023101717", "The image of the monitor")
monitorFlags.Int64Var(&o.Monitor.Resource.Cpu, "monitor-cpu", 1, "The cpu of the monitor")
monitorFlags.Int64Var(&o.Monitor.Resource.MemoryGB, "monitor-memory", 1, "The memory of the monitor")
cmd.Flags().AddFlagSet(monitorFlags)
}

// AddBackupVolumeFlags adds the backup-volume-related flags to the command.
func (o *CreateOptions) AddBackupVolumeFlags(cmd *cobra.Command) {
backupVolumeFlags := pflag.NewFlagSet("backup-volume", pflag.ContinueOnError)
backupVolumeFlags.StringVar(&o.BackupVolume.Address, "backup-storage-class", "local-path", "The storage class of the backup storage")
backupVolumeFlags.StringVar(&o.BackupVolume.Path, "backup-storage-size", "/opt/nfs", "The size of the backup storage")
cmd.Flags().AddFlagSet(backupVolumeFlags)
}

// AddParameterFlags adds the parameter-related flags, e.g. __min_full_resource_pool_memory, to the command
func (o *CreateOptions) AddParameterFlags(cmd *cobra.Command) {
parameterFlags := pflag.NewFlagSet("parameters", pflag.ContinueOnError)
parameterFlags.StringToStringVar(&o.KvParameters, "parameters", map[string]string{"__min_full_resource_pool_memory": "2147483648", "system_memory": "1G"}, "Other parameter settings in obcluster, e.g., __min_full_resource_pool_memory")
cmd.Flags().AddFlagSet(parameterFlags)
}
13 changes: 12 additions & 1 deletion internal/cli/cluster/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,21 @@ See the Mulan PSL v2 for more details.
*/
package cluster

import (
"github.com/spf13/cobra"

"github.com/oceanbase/ob-operator/internal/cli/generic"
)

type DeleteOptions struct {
ResourceOptions
generic.ResourceOptions
}

func NewDeleteOptions() *DeleteOptions {
return &DeleteOptions{}
}

// AddFlags add basic flags for cluster management
func (o *DeleteOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.Namespace, "namespace", "default", "namespace of ob cluster")
}
7 changes: 4 additions & 3 deletions internal/cli/cluster/scale.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ import (
apiconst "github.com/oceanbase/ob-operator/api/constants"
apitypes "github.com/oceanbase/ob-operator/api/types"
"github.com/oceanbase/ob-operator/api/v1alpha1"
"github.com/oceanbase/ob-operator/internal/cli/generic"
utils "github.com/oceanbase/ob-operator/internal/cli/utils"
oceanbaseconst "github.com/oceanbase/ob-operator/internal/const/oceanbase"
param "github.com/oceanbase/ob-operator/internal/dashboard/model/param"
)

type ScaleOptions struct {
ResourceOptions
generic.ResourceOptions
Zones map[string]string `json:"zones"`
Topology []param.ZoneTopology `json:"topology"`
OldTopology []apitypes.OBZoneTopology `json:"oldTopology"`
Expand Down Expand Up @@ -138,7 +139,7 @@ func (o *ScaleOptions) Validate() error {
if !found {
typeAdd = true
}
if typeDelete && zoneNum-deleteNum < maxDeleteNum {
if typeDelete && deleteNum > maxDeleteNum {
return fmt.Errorf("Obcluster has %d Zones, can only delete %d zones", zoneNum, maxDeleteNum)
}
}
Expand All @@ -156,7 +157,7 @@ func (o *ScaleOptions) Validate() error {
o.ScaleType = "addZones"
}
if trueCount > 1 {
return fmt.Errorf("Only one type of scale is allower at a time")
return fmt.Errorf("Only one type of scale is allowed at a time")
}
if trueCount == 0 {
return fmt.Errorf("No scale type specified")
Expand Down
13 changes: 12 additions & 1 deletion internal/cli/cluster/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,21 @@ See the Mulan PSL v2 for more details.
*/
package cluster

import (
"github.com/spf13/cobra"

"github.com/oceanbase/ob-operator/internal/cli/generic"
)

type ShowOptions struct {
ResourceOptions
generic.ResourceOptions
}

func NewShowOptions() *ShowOptions {
return &ShowOptions{}
}

// AddFlags add basic flags for cluster management
func (o *ShowOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.Namespace, "namespace", "default", "namespace of ob cluster")
}
7 changes: 4 additions & 3 deletions internal/cli/cluster/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ import (
apiconst "github.com/oceanbase/ob-operator/api/constants"
"github.com/oceanbase/ob-operator/api/types"
"github.com/oceanbase/ob-operator/api/v1alpha1"
"github.com/oceanbase/ob-operator/internal/cli/generic"
oceanbaseconst "github.com/oceanbase/ob-operator/internal/const/oceanbase"
"github.com/oceanbase/ob-operator/internal/dashboard/business/constant"
"github.com/oceanbase/ob-operator/internal/dashboard/model/common"
param "github.com/oceanbase/ob-operator/internal/dashboard/model/param"
)

type UpdateOptions struct {
ResourceOptions
generic.ResourceOptions
Resource common.ResourceSpec `json:"resource"`
Storage *param.OBServerStorageSpec `json:"storage"`
UpdateType string `json:"updateType"`
Expand All @@ -44,8 +45,8 @@ func NewUpdateOptions() *UpdateOptions {
}
}

// GetUpdateOperations creates update opertaions
func GetUpdateOperations(o *UpdateOptions) *v1alpha1.OBClusterOperation {
// GetUpdateOperation creates update opertaions
func GetUpdateOperation(o *UpdateOptions) *v1alpha1.OBClusterOperation {
updateOp := &v1alpha1.OBClusterOperation{
ObjectMeta: v1.ObjectMeta{
Name: o.Name + "-update-" + rand.String(6),
Expand Down
7 changes: 4 additions & 3 deletions internal/cli/cluster/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,21 @@ import (

apiconst "github.com/oceanbase/ob-operator/api/constants"
"github.com/oceanbase/ob-operator/api/v1alpha1"
"github.com/oceanbase/ob-operator/internal/cli/generic"
oceanbaseconst "github.com/oceanbase/ob-operator/internal/const/oceanbase"
)

type UpgradeOptions struct {
ResourceOptions
generic.ResourceOptions
Image string `json:"image"`
}

func NewUpgradeOptions() *UpgradeOptions {
return &UpgradeOptions{}
}

// GetUpgradeOperations creates upgrade opertaions
func GetUpgradeOperations(o *UpgradeOptions) *v1alpha1.OBClusterOperation {
// GetUpgradeOperation creates upgrade opertaions
func GetUpgradeOperation(o *UpgradeOptions) *v1alpha1.OBClusterOperation {
upgradeOp := &v1alpha1.OBClusterOperation{
ObjectMeta: v1.ObjectMeta{
Name: o.Name + "-upgrade-" + rand.String(6),
Expand Down
7 changes: 4 additions & 3 deletions internal/cli/cmd/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ import (
// NewCmd is command for cluster management
func NewCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "cluster <subcommand>",
Short: "Command for cluster management",
Long: `Command for cluster management, such as Create, UpGrade, Delete, Scale, Show.`,
Use: "cluster <subcommand>",
Aliases: []string{"c"},
Short: "Command for cluster management",
Long: `Command for cluster management, such as Create, UpGrade, Delete, Scale, Show.`,
}
cmd.AddCommand(NewCreateCmd())
cmd.AddCommand(NewDeleteCmd())
Expand Down
3 changes: 1 addition & 2 deletions internal/cli/cmd/cluster/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
cluster "github.com/oceanbase/ob-operator/internal/cli/cluster"
cmdUtil "github.com/oceanbase/ob-operator/internal/cli/cmd/util"
"github.com/oceanbase/ob-operator/internal/clients"
oberr "github.com/oceanbase/ob-operator/pkg/errors"
)

// NewCreateCmd create an ob cluster
Expand All @@ -46,7 +45,7 @@ func NewCreateCmd() *cobra.Command {
}
_, err := clients.CreateOBCluster(cmd.Context(), obcluster)
if err != nil {
logger.Fatalln(oberr.NewInternal(err.Error()))
logger.Fatalln(err)
}
logger.Printf("Create obcluster instance: %s", o.ClusterName)
logger.Printf("Run `echo $(kubectl get secret %s -o jsonpath='{.data.password}'|base64 --decode)` to get the secrets", obcluster.Spec.UserSecrets.Root)
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/cmd/cluster/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"github.com/oceanbase/ob-operator/internal/clients"
)

// NewDeleteCmd delete ob clusters
// NewDeleteCmd delete ob cluster
func NewDeleteCmd() *cobra.Command {
o := cluster.NewDeleteOptions()
logger := cmdUtil.GetDefaultLoggerInstance()
Expand Down
Loading

0 comments on commit e621b00

Please sign in to comment.