Skip to content

Commit 1cbc80f

Browse files
committed
optimize & bugfix
1 parent 9fb928e commit 1cbc80f

10 files changed

Lines changed: 218 additions & 106 deletions

File tree

cmd/completion.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ import (
3030
func NewCmdCompletion() *cobra.Command {
3131
var completionCmd = &cobra.Command{
3232
Use: "completion",
33-
Short: "Turn on auto completion according to the prompt",
34-
Long: "Turn on auto completion according to the prompt",
33+
Short: "Print the description of how to enable auto completion",
34+
Long: "Print the description of how to enable auto completion",
3535
Run: func(cmd *cobra.Command, args []string) {
3636
shell, ok := os.LookupEnv("SHELL")
3737
if ok {

cmd/configure.go

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
package cmd
1616

1717
import (
18-
"fmt"
1918
"reflect"
20-
"strings"
19+
20+
"github.com/ucloud/ucloud-cli/ux"
2121

2222
"github.com/spf13/cobra"
2323

@@ -46,16 +46,12 @@ func NewCmdInit() *cobra.Command {
4646
Run: func(cmd *cobra.Command, args []string) {
4747
Cxt.Println(configDesc)
4848
if len(config.PrivateKey) != 0 && len(config.PublicKey) != 0 {
49-
Cxt.Printf("Your have already configured public-key and private-key. Do you want to overwrite it? (y/n):")
50-
var overwrite string
51-
_, err := fmt.Scanf("%s\n", &overwrite)
49+
confirm, err := ux.Prompt("Your have already configured public-key and private-key. Do you want to overwrite it? (y/n):")
5250
if err != nil {
5351
Cxt.Println(err)
5452
return
5553
}
56-
overwrite = strings.Trim(overwrite, " ")
57-
overwrite = strings.ToLower(overwrite)
58-
if overwrite != "yes" && overwrite != "y" {
54+
if confirm {
5955
printHello()
6056
return
6157
}
@@ -110,6 +106,43 @@ func NewCmdConfig() *cobra.Command {
110106
Long: `Configure UCloud CLI options such as private-key,public-key,default region and default project-id.`,
111107
Example: "ucloud config list; ucloud config --region cn-bj2",
112108
Run: func(cmd *cobra.Command, args []string) {
109+
if cfg.Region != "" || cfg.Zone != "" {
110+
regionMap, err := fetchRegion()
111+
if err != nil {
112+
HandleError(err)
113+
return
114+
}
115+
116+
region := cfg.Region
117+
if region == "" {
118+
region = config.Region
119+
}
120+
121+
zones, ok := regionMap[region]
122+
if !ok {
123+
Cxt.Printf("Error, region[%s] not exist! See 'ucloud region'\n", region)
124+
return
125+
}
126+
127+
zone := cfg.Zone
128+
if zone == "" {
129+
zone = config.Zone
130+
}
131+
132+
if zone != "" {
133+
zoneExist := false
134+
for _, zone := range zones {
135+
if zone == cfg.Zone {
136+
zoneExist = true
137+
}
138+
}
139+
if !zoneExist {
140+
Cxt.Printf("Error, zone[%s] not exist in region[%s]! See 'ucloud config list' and 'ucloud region'\n", zone, region)
141+
return
142+
}
143+
}
144+
}
145+
113146
tmpCfgVal := reflect.ValueOf(cfg)
114147
configVal := reflect.ValueOf(config).Elem()
115148
changed := false

cmd/globalssh.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/spf13/cobra"
2121

2222
. "github.com/ucloud/ucloud-cli/base"
23+
sdk "github.com/ucloud/ucloud-sdk-go/ucloud"
2324
)
2425

2526
//NewCmdGssh ucloud gssh
@@ -102,7 +103,7 @@ func NewCmdGsshList() *cobra.Command {
102103
func NewCmdGsshArea() *cobra.Command {
103104
req := BizClient.NewDescribeGlobalSSHAreaRequest()
104105
cmd := &cobra.Command{
105-
Use: "area",
106+
Use: "location",
106107
Short: "List SSH server locations and covered areas",
107108
Long: "List SSH server locations and covered areas",
108109
Run: func(cmd *cobra.Command, args []string) {
@@ -175,7 +176,7 @@ func NewCmdGsshCreate() *cobra.Command {
175176
},
176177
}
177178
cmd.Flags().SortFlags = false
178-
req.AreaCode = cmd.Flags().String("area", "", "Required. Location of the source server. See 'ucloud gssh area'")
179+
req.AreaCode = cmd.Flags().String("location", "", "Required. Location of the source server. See 'ucloud gssh location'")
179180
req.TargetIP = cmd.Flags().String("target-ip", "", "Required. IP of the source server. Required")
180181
req.Region = cmd.Flags().String("region", "", "Optional. Assign region")
181182
req.ProjectId = cmd.Flags().String("project-id", ConfigInstance.ProjectID, "Optional. Assign project-id")
@@ -184,9 +185,9 @@ func NewCmdGsshCreate() *cobra.Command {
184185
req.ChargeType = cmd.Flags().String("charge-type", "Month", "Optional.'Year',pay yearly;'Month',pay monthly;'Dynamic', pay hourly(requires access)")
185186
req.Quantity = cmd.Flags().Int("quantity", 1, "Optional. The duration of the instance. N years/months.")
186187
req.CouponId = cmd.Flags().String("coupon-id", "", "Optional. Coupon ID, The Coupon can deduct part of the payment,see DescribeCoupon or https://accountv2.ucloud.cn")
187-
cmd.MarkFlagRequired("area")
188+
cmd.MarkFlagRequired("location")
188189
cmd.MarkFlagRequired("target-ip")
189-
cmd.Flags().SetFlagValues("area", "LosAngeles", "Singapore", "HongKong", "Tokyo", "Washington", "Frankfurt")
190+
cmd.Flags().SetFlagValues("location", "LosAngeles", "Singapore", "HongKong", "Tokyo", "Washington", "Frankfurt")
190191
cmd.Flags().SetFlagValues("charge-type", "Month", "Year", "Dynamic", "Trial")
191192
return cmd
192193
}
@@ -224,18 +225,18 @@ func NewCmdGsshDelete() *cobra.Command {
224225
func NewCmdGsshModify() *cobra.Command {
225226
var gsshModifyPortReq = BizClient.NewModifyGlobalSSHPortRequest()
226227
var gsshModifyRemarkReq = BizClient.NewModifyGlobalSSHRemarkRequest()
227-
var region, project string
228+
region := ConfigInstance.Region
229+
project := ConfigInstance.ProjectID
228230
var cmd = &cobra.Command{
229231
Use: "update",
230232
Short: "Update GlobalSSH instance",
231233
Long: "Update GlobalSSH instance, including port and remark attribute",
232234
Example: "ucloud gssh update --id uga-xxx --port 22",
233235
Run: func(cmd *cobra.Command, args []string) {
234-
*gsshModifyPortReq.Region = region
235-
*gsshModifyPortReq.ProjectId = project
236-
*gsshModifyRemarkReq.Region = region
237-
*gsshModifyRemarkReq.ProjectId = project
238-
236+
gsshModifyPortReq.Region = sdk.String(region)
237+
gsshModifyPortReq.ProjectId = sdk.String(project)
238+
gsshModifyRemarkReq.Region = sdk.String(region)
239+
gsshModifyRemarkReq.ProjectId = sdk.String(project)
239240
if *gsshModifyPortReq.Port == 0 && *gsshModifyRemarkReq.Remark == "" {
240241
Cxt.Println("port or remark required")
241242
}
@@ -269,6 +270,6 @@ func NewCmdGsshModify() *cobra.Command {
269270
cmd.Flags().StringVar(&project, "project-id", ConfigInstance.ProjectID, "Optional. Assign project-id")
270271
gsshModifyPortReq.Port = cmd.Flags().Int("port", 0, "Optional. Port of SSH service.")
271272
gsshModifyRemarkReq.Remark = cmd.Flags().String("remark", "", "Optional. Remark of your GlobalSSH.")
272-
cmd.MarkFlagRequired("id")
273+
cmd.MarkFlagRequired("resource-id")
273274
return cmd
274275
}

cmd/image.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func NewCmdUImageList() *cobra.Command {
7575
list = append(list, row)
7676
}
7777
}
78-
PrintTable(list, []string{"ImageName", "ImageID", "BasicImage", "ExtensibleFeature", "CreationTime", "State"})
78+
PrintTable(list, []string{"ImageName", "ImageID", "BasicImage", "ExtensibleFeature", "CreationTime"})
7979
}
8080
},
8181
}
@@ -87,5 +87,6 @@ func NewCmdUImageList() *cobra.Command {
8787
req.ImageId = cmd.Flags().String("image-id", "", "iamge id such as 'uimage-xxx'")
8888
req.Offset = cmd.Flags().Int("offset", 0, "offset default 0")
8989
req.Limit = cmd.Flags().Int("limit", 500, "max count")
90+
cmd.Flags().SetFlagValues("image-type", "Base", "Business", "Custom")
9091
return cmd
9192
}

cmd/region.go

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,31 @@ func NewCmdRegion() *cobra.Command {
3535
Long: "List all region and zone",
3636
Example: "ucloud region",
3737
Run: func(cmd *cobra.Command, args []string) {
38-
if err := listRegion(); err != nil {
39-
Cxt.PrintErr(err)
38+
regionMap, err := fetchRegion()
39+
if err != nil {
40+
HandleError(err)
41+
return
42+
}
43+
regionList := make([]RegionTable, 0)
44+
for region, zones := range regionMap {
45+
regionList = append(regionList, RegionTable{region, strings.Join(zones, ", ")})
46+
}
47+
if global.json {
48+
PrintJSON(regionList)
49+
} else {
50+
PrintTableS(regionList)
4051
}
4152
},
4253
}
4354
return cmd
4455
}
4556

57+
//RegionTable 为显示region表格创建的类型
58+
type RegionTable struct {
59+
Region string
60+
Zones string
61+
}
62+
4663
func getDefaultRegion() (string, string, error) {
4764
req := &uaccount.GetRegionRequest{}
4865
resp, err := BizClient.GetRegion(req)
@@ -60,35 +77,17 @@ func getDefaultRegion() (string, string, error) {
6077
return "", "", fmt.Errorf("No default region")
6178
}
6279

63-
//RegionTable 为显示region表格创建的类型
64-
type RegionTable struct {
65-
Region string
66-
Zones string
67-
}
68-
69-
func listRegion() error {
80+
func fetchRegion() (map[string][]string, error) {
7081
req := &uaccount.GetRegionRequest{}
7182
resp, err := BizClient.GetRegion(req)
7283
if err != nil {
73-
return err
74-
}
75-
if resp.RetCode != 0 {
76-
return fmt.Errorf("Something wrong. RetCode:%d, Message:%s", resp.RetCode, resp.Message)
84+
return nil, err
7785
}
78-
regionList := make([]RegionTable, 0)
7986
regionMap := make(map[string][]string)
8087
for _, region := range resp.Regions {
8188
regionMap[region.Region] = append(regionMap[region.Region], region.Zone)
8289
}
83-
for region, zones := range regionMap {
84-
regionList = append(regionList, RegionTable{region, strings.Join(zones, ", ")})
85-
}
86-
if global.json {
87-
PrintJSON(regionList)
88-
} else {
89-
PrintTable(regionList, []string{"Region", "Zones"})
90-
}
91-
return err
90+
return regionMap, nil
9291
}
9392

9493
func getDefaultProject() (string, string, error) {

cmd/root.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,8 @@ Examples:
8989
{{.Example}}{{end}}{{if .HasAvailableSubCommands}}
9090
9191
Commands:{{range .Commands}}{{if .IsAvailableCommand}}
92-
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
93-
94-
Flags:
92+
{{rpad .Name .NamePadding }} {{.Short}}{{end}}
93+
{{end}}{{end}}{{if .HasAvailableLocalFlags}}Flags:
9594
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
9695
9796
Global Flags:

cmd/uhost.go

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ func NewCmdUHostCreate() *cobra.Command {
135135
Run: func(cmd *cobra.Command, args []string) {
136136
*req.Memory *= 1024
137137
req.LoginMode = sdk.String("Password")
138+
images := strings.SplitN(*req.ImageId, "/", 2)
139+
if len(images) >= 2 {
140+
*req.ImageId = images[0]
141+
}
138142
resp, err := BizClient.CreateUHostInstance(req)
139143
if err != nil {
140144
HandleError(err)
@@ -181,7 +185,7 @@ func NewCmdUHostCreate() *cobra.Command {
181185
req.Disks[1].Type = flags.String("data-disk-type", "LOCAL_NORMAL", "Optional. Enumeration value. 'LOCAL_NORMAL', Ordinary local disk; 'CLOUD_NORMAL', Ordinary cloud disk; 'LOCAL_SSD',local ssd disk; 'CLOUD_SSD',cloud ssd disk; 'EXCLUSIVE_LOCAL_DISK',big data. The disk only supports a limited combination.")
182186
req.Disks[1].Size = flags.String("data-disk-size", "20", "Optional. Disk size. Unit GB")
183187
req.Disks[1].BackupType = flags.String("data-disk-backup-type", "NONE", "Optional. Enumeration value, 'NONE' or 'DATAARK'. DataArk supports real-time backup, which can restore the disk back to any moment within the last 12 hours. (Normal Local Disk and Normal Cloud Disk Only)")
184-
req.NetworkId = flags.String("network-id", "", "Optional. Network ID (no need to fill in the case of VPC2.0). In the case of VPC1.0, if not filled in, we will choose the basic network; if it is filled in, we will choose the subnet. See DescribeSubnet.")
188+
req.NetworkId = flags.String("network-id", "", "Optional. Network ID (no need to fill in the case of VPC2.0). In the case of VPC1.0, if not filled in, we will choose the basic network; if it is filled in, we will choose the subnet. See 'ucloud subnet list'.")
185189
req.SecurityGroupId = flags.String("firewall-id", "", "Optional. Firewall Id, default: Web recommended firewall. see 'ucloud firewall list'.")
186190
req.Tag = flags.String("ugroup", "Default", "Optional. Business group")
187191
req.CouponId = flags.String("coupon-id", "", "Optional. Coupon ID, The Coupon can deduct part of the payment,see DescribeCoupon or https://accountv2.ucloud.cn")
@@ -215,11 +219,15 @@ func NewCmdUHostCreate() *cobra.Command {
215219
}
216220
req.Zone = sdk.String(zone)
217221
req.ImageType = sdk.String("Base")
222+
req.Limit = sdk.Int(1000)
218223
result := make([]string, 0)
219224
resp, err := BizClient.DescribeImage(req)
220225
if err == nil {
221226
for _, image := range resp.ImageSet {
222-
result = append(result, image.ImageId)
227+
if image.State == "Available" {
228+
imageName := strings.Replace(image.ImageName, " ", "-", -1)
229+
result = append(result, fmt.Sprintf("%s/%s", image.ImageId, imageName))
230+
}
223231
}
224232
}
225233
return result
@@ -387,21 +395,29 @@ func NewCmdUHostPoweroff() *cobra.Command {
387395
req := BizClient.NewPoweroffUHostInstanceRequest()
388396
cmd := &cobra.Command{
389397
Use: "poweroff",
390-
Short: "Analog power off Uhost instnace. Danger! this operation may affect data integrity or cause file system corruption",
391-
Long: "Analog power off Uhost instnace. Danger! this operation may affect data integrity or cause file system corruption",
398+
Short: "Analog power off Uhost instnace",
399+
Long: "Analog power off Uhost instnace",
392400
Run: func(cmd *cobra.Command, args []string) {
393-
resp, err := BizClient.PoweroffUHostInstance(req)
401+
sure, err := ux.Prompt("Danger, it may affect data integrity. Are you sure you want to poweroff this host? (y/n):")
394402
if err != nil {
395-
HandleError(err)
396-
} else {
397-
Cxt.Printf("UHost:[%v] is power off\n", resp.UhostId)
403+
Cxt.Println(err)
404+
return
405+
}
406+
if sure {
407+
resp, err := BizClient.PoweroffUHostInstance(req)
408+
if err != nil {
409+
HandleError(err)
410+
} else {
411+
Cxt.Printf("UHost:[%v] is power off\n", resp.UhostId)
412+
}
398413
}
399414
},
400415
}
401416
req.ProjectId = cmd.Flags().String("project-id", ConfigInstance.ProjectID, "Assign project-id")
402417
req.Region = cmd.Flags().String("region", ConfigInstance.Region, "Assign region")
403418
req.Zone = cmd.Flags().String("zone", "", "Assign availability zone")
404419
req.UHostId = cmd.Flags().String("resource-id", "", "ResourceID of the uhost instance( or UHostId)")
420+
cmd.MarkFlagRequired("resource-id")
405421
return cmd
406422
}
407423

@@ -410,8 +426,8 @@ func NewCmdUHostScale() *cobra.Command {
410426
req := BizClient.NewResizeUHostInstanceRequest()
411427
cmd := &cobra.Command{
412428
Use: "scale",
413-
Short: "Scale uhost instance,such as cpu core count, memory size, system disk size and data disk size",
414-
Long: "Scale uhost instance,such as cpu core count, memory size, system disk size and data disk size",
429+
Short: "Scale uhost instance,such as cpu core count, memory size and disk size",
430+
Long: "Scale uhost instance,such as cpu core count, memory size and disk size",
415431
Run: func(cmd *cobra.Command, args []string) {
416432
if *req.CPU == 0 {
417433
req.CPU = nil
@@ -427,6 +443,27 @@ func NewCmdUHostScale() *cobra.Command {
427443
if *req.BootDiskSpace == 0 {
428444
req.BootDiskSpace = nil
429445
}
446+
host, err := describeUHostByID(*req.UHostId, *req.ProjectId, *req.Region, *req.Zone)
447+
if err != nil {
448+
Cxt.Println(err)
449+
return
450+
}
451+
if host.State == "Running" {
452+
agreeClose, err := ux.Prompt("Scale uhost must be after stop it. Do you want to stop this host? (y/n):")
453+
if err != nil {
454+
Cxt.Println(err)
455+
return
456+
}
457+
if agreeClose {
458+
_req := BizClient.NewStopUHostInstanceRequest()
459+
_req.ProjectId = req.ProjectId
460+
_req.Region = req.Region
461+
_req.Zone = req.Zone
462+
_req.UHostId = req.UHostId
463+
stopUhostIns(_req)
464+
}
465+
}
466+
430467
resp, err := BizClient.ResizeUHostInstance(req)
431468
if err != nil {
432469
HandleError(err)

ux/prompt.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package ux
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/ucloud/ucloud-cli/base"
8+
)
9+
10+
// Prompt confirm
11+
func Prompt(text string) (bool, error) {
12+
base.Cxt.Printf(text)
13+
var agreeClose string
14+
_, err := fmt.Scanf("%s\n", &agreeClose)
15+
if err != nil {
16+
return false, err
17+
}
18+
agreeClose = strings.Trim(agreeClose, " ")
19+
agreeClose = strings.ToLower(agreeClose)
20+
21+
if agreeClose == "y" || agreeClose == "yes" {
22+
return true, nil
23+
}
24+
return false, nil
25+
}

0 commit comments

Comments
 (0)