diff --git a/internal/cli/cluster/create.go b/internal/cli/cluster/create.go index 31ff07787..7164d4764 100644 --- a/internal/cli/cluster/create.go +++ b/internal/cli/cluster/create.go @@ -340,7 +340,7 @@ func (o *CreateOptions) AddFlags(cmd *cobra.Command) { // 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") + zoneFlags.StringToStringVarP(&o.Zones, FLAG_ZONES, "z", map[string]string{"z1": "1"}, "The zones of the cluster, e.g. '--zones=='") cmd.Flags().AddFlagSet(zoneFlags) } @@ -351,7 +351,7 @@ func (o *CreateOptions) AddBaseFlags(cmd *cobra.Command) { baseFlags.StringVar(&o.Namespace, FLAG_NAMESPACE, DEFAULT_NAMESPACE, "The namespace of the cluster") baseFlags.Int64Var(&o.ClusterId, FLAG_CLUSTER_ID, DEFAULT_ID, "The id of the cluster") baseFlags.StringVarP(&o.RootPassword, FLAG_ROOT_PASSWORD, "p", "", "The root password of the cluster") - baseFlags.StringVar(&o.Mode, FLAG_MODE, "", "The mode of the cluster") + baseFlags.StringVar(&o.Mode, FLAG_MODE, DEFAULT_MODE, "The mode of the cluster") } // AddObserverFlags adds the observer-related flags to the command. diff --git a/internal/cli/cluster/enter.go b/internal/cli/cluster/enter.go index 4fd21c39e..3383b15a8 100644 --- a/internal/cli/cluster/enter.go +++ b/internal/cli/cluster/enter.go @@ -80,6 +80,7 @@ const ( DEFAULT_MONITOR_CPU = 1 DEFAULT_MONITOR_MEMORY = 1 DEFAULT_NAME = "test" + DEFAULT_MODE = "service" // Default values for Parameter flag DEFAULT_MIN_FULL_RESOURCE_POOL_MEMORY = "2147483648" diff --git a/internal/cli/cluster/scale.go b/internal/cli/cluster/scale.go index c6de02db2..ad8350cac 100644 --- a/internal/cli/cluster/scale.go +++ b/internal/cli/cluster/scale.go @@ -165,8 +165,8 @@ func (o *ScaleOptions) Validate() error { return nil } -// Add Flags for scale options +// AddFlags for scale options func (o *ScaleOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&o.Namespace, FLAG_NAMESPACE, DEFAULT_NAMESPACE, "namespace of ob cluster") - cmd.Flags().StringToStringVar(&o.Zones, FLAG_ZONES, nil, "zone of ob cluster") + cmd.Flags().StringToStringVar(&o.Zones, FLAG_ZONES, nil, "The zone of the cluster, e.g. '--zones==', set replicas to 0 to delete the zone, only one operation of adding, deleting or modifying is allowd at a time.") } diff --git a/internal/cli/cluster/show.go b/internal/cli/cluster/show.go index a80ebe6a8..7b6331a74 100644 --- a/internal/cli/cluster/show.go +++ b/internal/cli/cluster/show.go @@ -29,5 +29,5 @@ func NewShowOptions() *ShowOptions { // AddFlags add basic flags for cluster management func (o *ShowOptions) AddFlags(cmd *cobra.Command) { - cmd.Flags().StringVar(&o.Namespace, FLAG_NAMESPACE, DEFAULT_NAMESPACE, "namespace of ob cluster") + cmd.Flags().StringVar(&o.Namespace, FLAG_NAMESPACE, DEFAULT_NAMESPACE, "namespace of the ob cluster") } diff --git a/internal/cli/cluster/update.go b/internal/cli/cluster/update.go index 46389ad66..a68c821ec 100644 --- a/internal/cli/cluster/update.go +++ b/internal/cli/cluster/update.go @@ -114,10 +114,10 @@ func (o *UpdateOptions) Complete() error { expandStorageSize.DataStorage = apiresource.NewQuantity(o.Storage.Data.SizeGB*constant.GB, apiresource.BinarySI) } if o.Storage.RedoLog.SizeGB != 0 { - expandStorageSize.DataStorage = apiresource.NewQuantity(o.Storage.RedoLog.SizeGB*constant.GB, apiresource.BinarySI) + expandStorageSize.RedoLogStorage = apiresource.NewQuantity(o.Storage.RedoLog.SizeGB*constant.GB, apiresource.BinarySI) } if o.Storage.Log.SizeGB != 0 { - expandStorageSize.DataStorage = apiresource.NewQuantity(o.Storage.Log.SizeGB*constant.GB, apiresource.BinarySI) + expandStorageSize.LogStorage = apiresource.NewQuantity(o.Storage.Log.SizeGB*constant.GB, apiresource.BinarySI) } o.ModifyConfig = &v1alpha1.ModifyOBServersConfig{ExpandStorageSize: expandStorageSize} default: diff --git a/internal/cli/cmd/cluster/show.go b/internal/cli/cmd/cluster/show.go index dcce9a6d0..beefc86b4 100644 --- a/internal/cli/cmd/cluster/show.go +++ b/internal/cli/cmd/cluster/show.go @@ -47,14 +47,16 @@ func NewShowCmd() *cobra.Command { if len(obcluster.Status.OBZoneStatus) > 0 { tbLog.Println("ZONE \t STATUS") for _, zone := range obcluster.Status.OBZoneStatus { - tbLog.Printf("%s \t %s \n\n", zone.Zone, zone.Status) + tbLog.Printf("%s \t %s \n", zone.Zone, zone.Status) } + tbLog.Println() } if len(obcluster.Status.Parameters) > 0 { tbLog.Println("KEY \t VALUE") for _, Parameter := range obcluster.Status.Parameters { - tbLog.Printf("%s \t %s \n\n", Parameter.Name, Parameter.Value) + tbLog.Printf("%s \t %s \n", Parameter.Name, Parameter.Value) } + tbLog.Println() } if len(obclusterOperationList.Items) > 0 { @@ -63,7 +65,7 @@ func NewShowCmd() *cobra.Command { }) tbLog.Println("OPERATION TYPE \t TTLDAYS \t STATUS \t CREATETIME") for _, op := range obclusterOperationList.Items { - tbLog.Printf("%s \t %d \t %s \t %s\n", op.Spec.Type, op.Spec.TTLDays, op.Status.Status, op.CreationTimestamp) + tbLog.Printf("%s \t %d \t %s \t %s \n", op.Spec.Type, op.Spec.TTLDays, op.Status.Status, op.CreationTimestamp) } } else { logger.Printf("No OBClusterOperations found in %s", obcluster.Spec.ClusterName) diff --git a/internal/cli/cmd/tenant/show.go b/internal/cli/cmd/tenant/show.go index 584b62747..8d99ff6e5 100644 --- a/internal/cli/cmd/tenant/show.go +++ b/internal/cli/cmd/tenant/show.go @@ -51,8 +51,9 @@ func NewShowCmd() *cobra.Command { if len(obtenant.Status.Pools) > 0 { tbLog.Println("ZONELIST \t UNITNUM \t PRIORITY") for _, pool := range obtenant.Status.Pools { - tbLog.Printf("%s \t %d \t %d\n\n", pool.ZoneList, pool.UnitNumber, pool.Priority) + tbLog.Printf("%s \t %d \t %d \n", pool.ZoneList, pool.UnitNumber, pool.Priority) } + tbLog.Println() } if len(obtenantOperationList.Items) > 0 { sort.Slice(obtenantOperationList.Items, func(i, j int) bool { @@ -60,7 +61,7 @@ func NewShowCmd() *cobra.Command { }) tbLog.Println("OPERATION TYPE \t STATUS \t CREATETIME") for _, op := range obtenantOperationList.Items { - tbLog.Printf("%s \t %s \t %s\n", op.Spec.Type, op.Status.Status, op.CreationTimestamp) + tbLog.Printf("%s \t %s \t %s \n", op.Spec.Type, op.Status.Status, op.CreationTimestamp) } } else { logger.Printf("No OBTenantOperations found in %s", obtenant.Spec.TenantName) diff --git a/internal/cli/demo/prompt.go b/internal/cli/demo/prompt.go index 7c1387c86..ef1627037 100644 --- a/internal/cli/demo/prompt.go +++ b/internal/cli/demo/prompt.go @@ -130,7 +130,7 @@ func (pf *PromptFactory) CreatePrompt(promptType string) any { } case tenant.FLAG_TENANT_NAME_IN_K8S: return &promptui.Prompt{ - Label: "Please input the tenant resource name, press `enter` to use the default name `demo-tenant`: ", + Label: "Please input the tenant resource name, press `enter` to use the default name `t1`: ", Templates: pf.promptTepl, Validate: func(input string) error { if !utils.CheckResourceName(input) { @@ -143,7 +143,7 @@ func (pf *PromptFactory) CreatePrompt(promptType string) any { } case tenant.FLAG_TENANT_NAME: return &promptui.Prompt{ - Label: "Please input the tenant name, press `enter` to use the default name `demo_tenant`: ", + Label: "Please input the tenant name, press `enter` to use the default name `t1`: ", Templates: pf.promptTepl, Validate: func(input string) error { if !utils.CheckTenantName(input) { diff --git a/internal/cli/tenant/activate.go b/internal/cli/tenant/activate.go index 1e3a46c65..89ad95068 100644 --- a/internal/cli/tenant/activate.go +++ b/internal/cli/tenant/activate.go @@ -54,5 +54,5 @@ func GetActivateOperation(o *ActivateOptions) *v1alpha1.OBTenantOperation { // AddFlags add basic flags for tenant management func (o *ActivateOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&o.Namespace, FLAG_NAMESPACE, DEFAULT_NAMESPACE, "namespace of ob tenant") - cmd.Flags().BoolVarP(&o.force, FLAG_FORCE, "f", DEFAULT_FORCE_FLAG, "force operation") + cmd.Flags().BoolVarP(&o.force, FLAG_FORCE, "f", DEFAULT_FORCE_FLAG, "If the operation is a force operation") } diff --git a/internal/cli/tenant/create.go b/internal/cli/tenant/create.go index 3a78681d7..e6e0d5588 100644 --- a/internal/cli/tenant/create.go +++ b/internal/cli/tenant/create.go @@ -107,9 +107,21 @@ func (o *CreateOptions) Complete() error { if o.RootPassword == "" { o.RootPassword = utils.GenerateRandomPassword(8, 32) } + if o.TenantName == "" { + o.TenantName = o.Name + } if o.Timestamp != "" { o.Source.Restore.Until.Timestamp = &o.Timestamp } + if o.RestoreType != "" { + o.RestoreType = strings.ToUpper(o.RestoreType) + } + if o.RestoreType == "NFS" && o.Source.Restore.BakDataSource == "" { + o.Source.Restore.BakDataSource = fmt.Sprintf("%s/%s", "backup", o.From) + } + if o.RestoreType == "NFS" && o.Source.Restore.ArchiveSource == "" { + o.Source.Restore.ArchiveSource = fmt.Sprintf("%s/%s", "archive", o.From) + } return nil } @@ -118,7 +130,7 @@ func (o *CreateOptions) Validate() error { return errors.New("namespace is not specified") } if o.ClusterName == "" { - return errors.New("cluster name is not specified") + return errors.New("cluster is not specified") } if o.TenantName == "" { return errors.New("tenant name is not specified") @@ -129,9 +141,6 @@ func (o *CreateOptions) Validate() error { if !utils.CheckTenantName(o.TenantName) { return fmt.Errorf("invalid tenant name: %s, the first letter must be a letter or an underscore and cannot contain -", o.TenantName) } - if o.Source != nil && o.Source.Tenant != nil && o.TenantRole == "PRIMARY" { - return fmt.Errorf("invalid tenant role") - } if o.Restore && o.RestoreType != "OSS" && o.RestoreType != "NFS" { return errors.New("Restore Type not supported") } @@ -179,7 +188,7 @@ func CreateOBTenant(ctx context.Context, p *CreateOptions) (*v1alpha1.OBTenant, if kubeerrors.IsNotFound(err) { return nil, fmt.Errorf("primary tenant not found") } - return nil, fmt.Errorf(err.Error()) + return nil, err } if existing.Status.TenantRole != apiconst.TenantRolePrimary { return nil, fmt.Errorf("the target tenant is not primary tenant") @@ -187,7 +196,7 @@ func CreateOBTenant(ctx context.Context, p *CreateOptions) (*v1alpha1.OBTenant, // Match root password rootSecret, err := k8sclient.ClientSet.CoreV1().Secrets(existing.Namespace).Get(ctx, existing.Status.Credentials.Root, v1.GetOptions{}) if err != nil { - return nil, fmt.Errorf(err.Error()) + return nil, err } if pwd, ok := rootSecret.Data["password"]; ok { if p.RootPassword != string(pwd) { @@ -196,7 +205,7 @@ func CreateOBTenant(ctx context.Context, p *CreateOptions) (*v1alpha1.OBTenant, if t.Spec.Credentials.Root != "" { err = utils.CreatePasswordSecret(ctx, nn.Namespace, t.Spec.Credentials.Root, p.RootPassword) if err != nil { - return nil, fmt.Errorf(err.Error()) + return nil, err } } } @@ -396,7 +405,7 @@ func (o *CreateOptions) AddBaseFlags(cmd *cobra.Command) { baseFlags.StringVarP(&o.RootPassword, FLAG_ROOTPASSWD, "p", "", "The root password of the primary tenant, if not specified, generate a random password") baseFlags.StringVarP(&o.Charset, FLAG_CHARSET, "c", DEFAULT_CHARSET, "The charset used in ob tenant") baseFlags.StringVar(&o.ConnectWhiteList, FLAG_CONNECT_WHITE_LIST, DEFAULT_CONNECT_WHITE_LIST, "The connect white list used in ob tenant") - baseFlags.StringVar(&o.From, FLAG_FROM, "", "restore from data source") + baseFlags.StringVar(&o.From, FLAG_FROM, "", "The source tenant to create a standby tenant or restore the tenant") } // AddPoolFlags add pool-related flags @@ -422,14 +431,14 @@ func (o *CreateOptions) AddUnitFlags(cmd *cobra.Command) { // AddRestoreFlags add restore flags func (o *CreateOptions) AddRestoreFlags(cmd *cobra.Command) { restoreFlags := pflag.NewFlagSet(FLAGSET_RESTORE, pflag.ContinueOnError) - restoreFlags.BoolVarP(&o.Restore, FLAG_RESTORE, "r", DEFAULT_RESTORE_FLAG, "Restore from backup files") + restoreFlags.BoolVarP(&o.Restore, FLAG_RESTORE, "r", DEFAULT_RESTORE_FLAG, "Restore from backup files, set to true to restore a tenant, also need the `from` flag to specify the source tenant") restoreFlags.StringVar(&o.RestoreType, FLAG_RESTORE_TYPE, DEFAULT_RESTORE_TYPE, "The type of restore source, support OSS or NFS") - restoreFlags.StringVar(&o.Source.Restore.ArchiveSource, FLAG_ARCHIVE_SOURCE, DEFAULT_ARCHIVE_SOURCE, "The archive source of restore") + restoreFlags.StringVar(&o.Source.Restore.ArchiveSource, FLAG_ARCHIVE_SOURCE, "", "The archive source of restore") restoreFlags.StringVar(&o.Source.Restore.BakEncryptionPassword, FLAG_BAK_ENCRYPTION_PASS, "", "The backup encryption password of obtenant") - restoreFlags.StringVar(&o.Source.Restore.BakDataSource, FLAG_BAK_DATA_SOURCE, DEFAULT_BAK_DATA_SOURCE, "The bak data source of restore") + restoreFlags.StringVar(&o.Source.Restore.BakDataSource, FLAG_BAK_DATA_SOURCE, "", "The bak data source of restore") restoreFlags.StringVar(&o.Source.Restore.OSSAccessID, FLAG_OSS_ACCESS_ID, "", "The oss access id of restore") restoreFlags.StringVar(&o.Source.Restore.OSSAccessKey, FLAG_OSS_ACCESS_KEY, "", "The oss access key of restore") restoreFlags.BoolVar(&o.Source.Restore.Until.Unlimited, FLAG_UNLIMITED, DEFAULT_UNLIMITED_FLAG, "time limited for restore") - restoreFlags.StringVar(&o.Timestamp, FLAG_UNTIL_TIMESTAMP, "", "timestamp for obtenant restore") + restoreFlags.StringVar(&o.Timestamp, FLAG_UNTIL_TIMESTAMP, "", "Timestamp for obtenant restore") cmd.Flags().AddFlagSet(restoreFlags) } diff --git a/internal/cli/tenant/enter.go b/internal/cli/tenant/enter.go index d8814dea6..9ceffe257 100644 --- a/internal/cli/tenant/enter.go +++ b/internal/cli/tenant/enter.go @@ -44,7 +44,7 @@ const ( // restore flags FLAG_RESTORE = "restore" - FLAG_RESTORE_TYPE = "type" + FLAG_RESTORE_TYPE = "restore-type" FLAG_ARCHIVE_SOURCE = "archive-source" FLAG_BAK_ENCRYPTION_PASS = "bak-encryption-password" FLAG_BAK_DATA_SOURCE = "bak-data-source" @@ -69,8 +69,6 @@ const ( DEFAULT_MEMORY_SIZE = "2Gi" DEFAULT_LOG_DISK_SIZE = "4Gi" DEFAULT_RESTORE_TYPE = "OSS" - DEFAULT_ARCHIVE_SOURCE = "demo_tenant/log_archive_custom" - DEFAULT_BAK_DATA_SOURCE = "demo_tenant/data_backup_custom_enc" // Default values for bool flags DEFAULT_UNLIMITED_FLAG = true @@ -78,8 +76,8 @@ const ( DEFAULT_RESTORE_FLAG = false // Default Tenant name for demo cmd - DEFAULT_TENANT_NAME_IN_K8S = "demo-tenant" - DEFAULT_TENANT_NAME = "demo_tenant" + DEFAULT_TENANT_NAME_IN_K8S = "t1" + DEFAULT_TENANT_NAME = "t1" ) // using in `demo` command, tenant resource name in k8s diff --git a/internal/cli/tenant/replaylog.go b/internal/cli/tenant/replaylog.go index 4e676b090..a2247ae7c 100644 --- a/internal/cli/tenant/replaylog.go +++ b/internal/cli/tenant/replaylog.go @@ -73,7 +73,7 @@ func (o *ReplayLogOptions) Validate() error { // AddFlags add basic flags for tenant management func (o *ReplayLogOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&o.Namespace, FLAG_NAMESPACE, DEFAULT_NAMESPACE, "The namespace of OBTenant") - cmd.Flags().BoolVarP(&o.force, FLAG_FORCE, "f", DEFAULT_FORCE_FLAG, "force operation") + cmd.Flags().BoolVarP(&o.force, FLAG_FORCE, "f", DEFAULT_FORCE_FLAG, "If the operation is a force operation") cmd.Flags().StringVar(&o.RestoreUntilOptions.Timestamp, FLAG_UNTIL_TIMESTAMP, "", "timestamp for OBTenant restore,example: 2024-02-23 17:47:00") cmd.Flags().BoolVar(&o.RestoreUntilOptions.Unlimited, FLAG_UNLIMITED, DEFAULT_UNLIMITED_FLAG, "time limit for OBTenant restore") } diff --git a/internal/cli/tenant/scale.go b/internal/cli/tenant/scale.go index 976ef00c7..2a9f2a544 100644 --- a/internal/cli/tenant/scale.go +++ b/internal/cli/tenant/scale.go @@ -119,7 +119,7 @@ func (o *ScaleOptions) Validate() error { func (o *ScaleOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&o.Namespace, FLAG_NAMESPACE, DEFAULT_NAMESPACE, "namespace of OBTenant") cmd.Flags().IntVar(&o.UnitNumber, FLAG_UNIT_NUMBER, DEFAULT_UNIT_NUMBER, "unit-number of pools") - cmd.Flags().BoolVarP(&o.force, FLAG_FORCE, "f", DEFAULT_FORCE_FLAG, "force operation") + cmd.Flags().BoolVarP(&o.force, FLAG_FORCE, "f", DEFAULT_FORCE_FLAG, "If the operation is a force operation") o.AddUnitFlags(cmd) } diff --git a/internal/cli/tenant/switchover.go b/internal/cli/tenant/switchover.go index 35387232e..e7e4d7ddb 100644 --- a/internal/cli/tenant/switchover.go +++ b/internal/cli/tenant/switchover.go @@ -63,5 +63,5 @@ func GetSwitchOverOperation(o *SwitchOverOptions) *v1alpha1.OBTenantOperation { // AddFlags add basic flags for tenant management func (o *SwitchOverOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&o.Namespace, FLAG_NAMESPACE, DEFAULT_NAMESPACE, "namespace of ob tenant") - cmd.Flags().BoolVarP(&o.force, FLAG_FORCE, "f", DEFAULT_FORCE_FLAG, "force operation") + cmd.Flags().BoolVarP(&o.force, FLAG_FORCE, "f", DEFAULT_FORCE_FLAG, "If the operation is a force operation") } diff --git a/internal/cli/tenant/update.go b/internal/cli/tenant/update.go index ac96a1dcf..8fb16064c 100644 --- a/internal/cli/tenant/update.go +++ b/internal/cli/tenant/update.go @@ -18,7 +18,6 @@ import ( "fmt" "github.com/spf13/cobra" - "github.com/spf13/pflag" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" @@ -53,7 +52,14 @@ func NewUpdateOptions() *UpdateOptions { ModifyResourcePools: make([]v1alpha1.ResourcePoolSpec, 0), AddResourcePools: make([]v1alpha1.ResourcePoolSpec, 0), DeleteResourcePools: make([]string, 0), - UnitConfig: ¶m.UnitConfig{}, + UnitConfig: ¶m.UnitConfig{ + CPUCount: "1", + MemorySize: "2Gi", + MaxIops: 1024, + MinIops: 1024, + IopsWeight: 1, + LogDiskSize: "4Gi", + }, } } @@ -196,19 +202,6 @@ func (o *UpdateOptions) Validate() error { func (o *UpdateOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&o.Namespace, FLAG_NAMESPACE, DEFAULT_NAMESPACE, "The namespace of OBTenant") cmd.Flags().StringVar(&o.ConnectWhiteList, FLAG_CONNECT_WHITE_LIST, "", "The connect white list of ob tenant") - cmd.Flags().StringToStringVar(&o.ZonePriority, FLAG_ZONE_PRIORITY, nil, "zone priority config of OBTenant") - cmd.Flags().BoolVarP(&o.force, FLAG_FORCE, "f", DEFAULT_FORCE_FLAG, "force operation") - o.AddUnitFlags(cmd) -} - -// AddUnitFlags add unit-resource-related flags -func (o *UpdateOptions) AddUnitFlags(cmd *cobra.Command) { - unitFlags := pflag.NewFlagSet(FLAGSET_UNIT, pflag.ContinueOnError) - unitFlags.Int64Var(&o.UnitConfig.MaxIops, FLAG_MAX_IOPS, DEFAULT_MAX_IOPS, "The max iops of unit") - unitFlags.Int64Var(&o.UnitConfig.MinIops, FLAG_MIN_IOPS, DEFAULT_MIN_IOPS, "The min iops of unit") - unitFlags.IntVar(&o.UnitConfig.IopsWeight, FLAG_IOPS_WEIGHT, DEFAULT_IOPS_WEIGHT, "The iops weight of unit") - unitFlags.StringVar(&o.UnitConfig.CPUCount, FLAG_CPU_COUNT, DEFAULT_CPU_COUNT, "The cpu count of unit") - unitFlags.StringVar(&o.UnitConfig.MemorySize, FLAG_MEMORY_SIZE, DEFAULT_MEMORY_SIZE, "The memory size of unit") - unitFlags.StringVar(&o.UnitConfig.LogDiskSize, FLAG_LOG_DISK_SIZE, DEFAULT_LOG_DISK_SIZE, "The log disk size of unit") - cmd.Flags().AddFlagSet(unitFlags) + cmd.Flags().StringToStringVar(&o.ZonePriority, FLAG_ZONE_PRIORITY, nil, "The zone priority config of OBTenant, e.g. --priority==, set priority to 0 to delete zone from the unit pool") + cmd.Flags().BoolVarP(&o.force, FLAG_FORCE, "f", DEFAULT_FORCE_FLAG, "If the operation is a force operation") } diff --git a/internal/cli/tenant/upgrade.go b/internal/cli/tenant/upgrade.go index 462d84d49..2c0ae1b03 100644 --- a/internal/cli/tenant/upgrade.go +++ b/internal/cli/tenant/upgrade.go @@ -52,5 +52,5 @@ func GetUpgradeOperation(o *UpgradeOptions) *v1alpha1.OBTenantOperation { // AddFlags add basic flags for tenant management func (o *UpgradeOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&o.Namespace, FLAG_NAMESPACE, DEFAULT_NAMESPACE, "The namespace of the tenant") - cmd.Flags().BoolVarP(&o.force, FLAG_FORCE, "f", DEFAULT_FORCE_FLAG, "force operation") + cmd.Flags().BoolVarP(&o.force, FLAG_FORCE, "f", DEFAULT_FORCE_FLAG, "If the operation is a force operation") } diff --git a/internal/cli/utils/validator.go b/internal/cli/utils/validator.go index ba75f1203..31cb75798 100644 --- a/internal/cli/utils/validator.go +++ b/internal/cli/utils/validator.go @@ -25,7 +25,7 @@ const ( // CheckResourceName checks resource name in k8s func CheckResourceName(name string) bool { - regex := `[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*` + regex := `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` re := regexp.MustCompile(regex) return re.MatchString(name) } @@ -64,7 +64,7 @@ func CheckPassword(password string) bool { // CheckTenantName check Tenant name when creating tenant func CheckTenantName(name string) bool { - regex := `^[_a-zA-Z][^-]*$` + regex := `^[_a-zA-Z][^-\n]*$` re := regexp.MustCompile(regex) return re.MatchString(name) } diff --git a/internal/cli/utils/validator_test.go b/internal/cli/utils/validator_test.go new file mode 100644 index 000000000..f0a17bbf2 --- /dev/null +++ b/internal/cli/utils/validator_test.go @@ -0,0 +1,105 @@ +/* +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 utils_test + +import ( + "testing" + + "github.com/oceanbase/ob-operator/internal/cli/utils" +) + +func TestCheckResourceName(t *testing.T) { + tests := []struct { + name string + input string + expected bool + }{ + // test valid names + {"validAlphanumeric", "example", true}, + {"validWithDash", "example-test", true}, + {"validWithDot", "example.com", true}, + {"validWithMultipleLabels", "sub.example.com", true}, + + // test invalid names + {"invalidWithUppercase", "Example", false}, + {"invalidWithUnderscore", "example_test", false}, + {"invalidWithSpace", "example test", false}, + {"invalidWithSpecialChar", "example@domain", false}, + {"invalidWithLeadingDash", "-example", false}, + {"invalidWithTrailingDash", "example-", false}, + {"invalidWithConsecutiveDashes", "example--com", true}, + {"invalidWithOnlyDot", ".", false}, + {"invalidEmptyString", "", false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if result := utils.CheckResourceName(tt.input); result != tt.expected { + t.Errorf("CheckResourceName(%q) = %v, want %v", tt.input, result, tt.expected) + } + }) + } +} + +func TestCheckTenantName(t *testing.T) { + tests := []struct { + name string + input string + expected bool + }{ + {"validTenantName", "example", true}, + {"tenantNameWithUnderscore", "example_name", true}, + {"tenantNameWithHyphen", "example-name", false}, // it is not allowed to contain a '-' character + + {"emptyTenantName", "", false}, + {"tenantNameStartingWithHyphen", "-exmple", false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if result := utils.CheckTenantName(tt.input); result != tt.expected { + t.Errorf("CheckTenantName(%q) = %v, want %v", tt.input, result, tt.expected) + } + }) + } +} + +func TestCheckPassword(t *testing.T) { + tests := []struct { + name string + input string + expected bool + }{ + {"validPassword", "Aa1?Aa1?", true}, // valid password + + {"noEnoughlength", "Aa1?", false}, // at least two uppercase, lowercase, number and special char + {"noUppercase", "aa11??", false}, + {"noLowercase", "AA11??", false}, + {"noNumber", "AAaa!!", false}, + {"noSpecialChar", "AAaa11", false}, + {"emptyPassword", "", false}, + {"onlySpecialChar", "????", false}, + {"onlyNumber", "1111", false}, + {"onlyLowercase", "aaaa", false}, + {"onlyUppercase", "AAAA", false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if result := utils.CheckPassword(tt.input); result != tt.expected { + t.Errorf("CheckPassword(%q) = %v, want %v", tt.input, result, tt.expected) + } + }) + } +}