Skip to content

Commit

Permalink
feat: cli: tenant management (#577)
Browse files Browse the repository at this point in the history
  • Loading branch information
lizzy-0323 authored Sep 30, 2024
1 parent 3474c5a commit 60baa8b
Show file tree
Hide file tree
Showing 48 changed files with 2,426 additions and 184 deletions.
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.ResourceOption
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 is 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(FLAGSET_ZONE, pflag.ContinueOnError)
zoneFlags.StringToStringVarP(&o.Zones, FLAG_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, FLAG_CLUSTER_NAME, "n", "", "Cluster name, if not specified, use resource name in k8s instead")
baseFlags.StringVar(&o.Namespace, FLAG_NAMESPACE, "default", "The namespace of the cluster")
baseFlags.Int64Var(&o.ClusterId, FLAG_CLUSTER_ID, 0, "The id of the cluster")
baseFlags.StringVarP(&o.RootPassword, FLAG_ROOTPASSWD, "p", "", "The root password of the cluster")
baseFlags.StringVar(&o.Mode, FLAG_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(FLAGSET_OBSERVER, pflag.ContinueOnError)
observerFlags.StringVar(&o.OBServer.Image, FLAG_OBSERVER_IMAGE, "oceanbase/oceanbase-cloud-native:4.2.1.6-106000012024042515", "The image of the observer")
observerFlags.Int64Var(&o.OBServer.Resource.Cpu, FLAG_OBSERVER_CPU, 2, "The cpu of the observer")
observerFlags.Int64Var(&o.OBServer.Resource.MemoryGB, FLAG_MONITOR_MEMORY, 10, "The memory of the observer")
observerFlags.StringVar(&o.OBServer.Storage.Data.StorageClass, FLAG_DATA_STORAGE_CLASS, "local-path", "The storage class of the data storage")
observerFlags.StringVar(&o.OBServer.Storage.RedoLog.StorageClass, FLAG_REDO_LOG_STORAGE_CLASS, "local-path", "The storage class of the redo log storage")
observerFlags.StringVar(&o.OBServer.Storage.Log.StorageClass, FLAG_LOG_STORAGE_CLASS, "local-path", "The storage class of the log storage")
observerFlags.Int64Var(&o.OBServer.Storage.Data.SizeGB, FLAG_DATA_STORAGE_SIZE, 50, "The size of the data storage")
observerFlags.Int64Var(&o.OBServer.Storage.RedoLog.SizeGB, FLAG_REDO_LOG_STORAGE_SIZE, 50, "The size of the redo log storage")
observerFlags.Int64Var(&o.OBServer.Storage.Log.SizeGB, FLAG_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(FLAGSET_MONITOR, pflag.ContinueOnError)
monitorFlags.StringVar(&o.Monitor.Image, FLAG_MONITOR_IMAGE, "oceanbase/obagent:4.2.1-100000092023101717", "The image of the monitor")
monitorFlags.Int64Var(&o.Monitor.Resource.Cpu, FLAG_MONITOR_CPU, 1, "The cpu of the monitor")
monitorFlags.Int64Var(&o.Monitor.Resource.MemoryGB, FLAG_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(FLAGSET_BACKUP_VOLUME, pflag.ContinueOnError)
backupVolumeFlags.StringVar(&o.BackupVolume.Address, FLAG_BACKUP_ADDRESS, "local-path", "The storage class of the backup storage")
backupVolumeFlags.StringVar(&o.BackupVolume.Path, FLAG_BACKUP_PATH, "/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(FLAGSET_PARAMETERS, pflag.ContinueOnError)
parameterFlags.StringToStringVar(&o.KvParameters, FLAG_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.ResourceOption
}

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

// AddFlags add basic flags for cluster management
func (o *DeleteOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.Namespace, FLAG_NAMESPACE, "default", "namespace of ob cluster")
}
56 changes: 56 additions & 0 deletions internal/cli/cluster/enter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Copyright (c) 2024 OceanBase
ob-operator is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
package cluster

const (
// Flagsets for cluster
FLAGSET_ZONE = "zone"
FLAGSET_OBSERVER = "observer"
FLAGSET_MONITOR = "monitor"
FLAGSET_BACKUP_VOLUME = "backup-volume"
FLAGSET_PARAMETERS = "parameters"

// Flags for all the commands in cluster management
FLAG_CLUSTER_NAME = "cluster-name"
FLAG_NAMESPACE = "namespace"
FLAG_CLUSTER_ID = "id"
FLAG_ROOTPASSWD = "root-password"
FLAG_MODE = "mode"

// Flags for zone-related options
FLAG_ZONES = "zones"

// Flags for observer-related options
FLAG_OBSERVER_IMAGE = "image"
FLAG_OBSERVER_CPU = "cpu"
FLAG_OBSERVER_MEMORY = "memory"
FLAG_DATA_STORAGE_CLASS = "data-storage-class"
FLAG_REDO_LOG_STORAGE_CLASS = "redo-log-storage-class"
FLAG_LOG_STORAGE_CLASS = "log-storage-class"
FLAG_DATA_STORAGE_SIZE = "data-storage-size"
FLAG_REDO_LOG_STORAGE_SIZE = "redo-log-storage-size"
FLAG_LOG_STORAGE_SIZE = "log-storage-size"

// Flags for monitor-related options
FLAG_MONITOR_IMAGE = "monitor-image"
FLAG_MONITOR_CPU = "monitor-cpu"
FLAG_MONITOR_MEMORY = "monitor-memory"

// Flags for backup-volume-related options
FLAG_BACKUP_ADDRESS = "backup-storage-address"
FLAG_BACKUP_PATH = "backup-storage-path"

// Flags for parameter-related options
FLAG_PARAMETERS = "parameters"
)
11 changes: 6 additions & 5 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.ResourceOption
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 All @@ -166,6 +167,6 @@ func (o *ScaleOptions) Validate() error {

// Add Flags for scale options
func (o *ScaleOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.Namespace, "namespace", "default", "namespace of ob cluster")
cmd.Flags().StringToStringVar(&o.Zones, "zones", nil, "zone of ob cluster")
cmd.Flags().StringVar(&o.Namespace, FLAG_NAMESPACE, "default", "namespace of ob cluster")
cmd.Flags().StringToStringVar(&o.Zones, FLAG_ZONES, nil, "zone of ob cluster")
}
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.ResourceOption
}

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

// AddFlags add basic flags for cluster management
func (o *ShowOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.Namespace, FLAG_NAMESPACE, "default", "namespace of ob cluster")
}
25 changes: 13 additions & 12 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.ResourceOption
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 Expand Up @@ -127,13 +128,13 @@ func (o *UpdateOptions) Complete() error {

// AddFlags for update options
func (o *UpdateOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.Namespace, "namespace", "default", "namespace of ob cluster")
cmd.Flags().Int64Var(&o.Resource.Cpu, "cpu", 0, "The cpu of the observer")
cmd.Flags().Int64Var(&o.Resource.MemoryGB, "memory", 0, "The memory of the observer")
cmd.Flags().StringVar(&o.Storage.Data.StorageClass, "data-storage-class", "", "The storage class of the data storage")
cmd.Flags().StringVar(&o.Storage.RedoLog.StorageClass, "redo-log-storage-class", "", "The storage class of the redo log storage")
cmd.Flags().StringVar(&o.Storage.Log.StorageClass, "log-storage-class", "", "The storage class of the log storage")
cmd.Flags().Int64Var(&o.Storage.Data.SizeGB, "data-storage-size", 0, "The size of the data storage")
cmd.Flags().Int64Var(&o.Storage.RedoLog.SizeGB, "redo-log-storage-size", 0, "The size of the redo log storage")
cmd.Flags().Int64Var(&o.Storage.Log.SizeGB, "log-storage-size", 0, "The size of the log storage")
cmd.Flags().StringVar(&o.Namespace, FLAG_NAMESPACE, "default", "namespace of ob cluster")
cmd.Flags().Int64Var(&o.Resource.Cpu, FLAG_OBSERVER_CPU, 0, "The cpu of the observer")
cmd.Flags().Int64Var(&o.Resource.MemoryGB, FLAG_MONITOR_MEMORY, 0, "The memory of the observer")
cmd.Flags().StringVar(&o.Storage.Data.StorageClass, FLAG_DATA_STORAGE_CLASS, "", "The storage class of the data storage")
cmd.Flags().StringVar(&o.Storage.RedoLog.StorageClass, FLAG_REDO_LOG_STORAGE_CLASS, "", "The storage class of the redo log storage")
cmd.Flags().StringVar(&o.Storage.Log.StorageClass, FLAG_LOG_STORAGE_CLASS, "", "The storage class of the log storage")
cmd.Flags().Int64Var(&o.Storage.Data.SizeGB, FLAG_DATA_STORAGE_SIZE, 0, "The size of the data storage")
cmd.Flags().Int64Var(&o.Storage.RedoLog.SizeGB, FLAG_REDO_LOG_STORAGE_SIZE, 0, "The size of the redo log storage")
cmd.Flags().Int64Var(&o.Storage.Log.SizeGB, FLAG_LOG_STORAGE_SIZE, 0, "The size of the log storage")
}
Loading

0 comments on commit 60baa8b

Please sign in to comment.