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: cli: tenant management #577

Merged
merged 9 commits into from
Sep 30, 2024
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
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
Loading