Skip to content

Commit 9fb928e

Browse files
committed
polling and async complete
1 parent 90505bd commit 9fb928e

12 files changed

Lines changed: 411 additions & 126 deletions

File tree

ansi/code.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Reference https://github.com/sindresorhus/ansi-escapes
2+
package ansi
3+
4+
import (
5+
"fmt"
6+
)
7+
8+
const ESC = "\x1b["
9+
const OSC = "\x1b]"
10+
const BEL = "\x07"
11+
const SEP = ";"
12+
13+
var CursorLeft = fmt.Sprintf("%sG", ESC)
14+
var EraseDown = fmt.Sprintf("%sJ", ESC)
15+
16+
func CursorUp(count int) string {
17+
return fmt.Sprintf("%s%dA", ESC, count)
18+
}

base/client.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package base
2+
3+
import (
4+
"github.com/ucloud/ucloud-sdk-go/services/pathx"
5+
"github.com/ucloud/ucloud-sdk-go/services/uaccount"
6+
"github.com/ucloud/ucloud-sdk-go/services/uhost"
7+
"github.com/ucloud/ucloud-sdk-go/services/ulb"
8+
"github.com/ucloud/ucloud-sdk-go/services/unet"
9+
"github.com/ucloud/ucloud-sdk-go/services/vpc"
10+
"github.com/ucloud/ucloud-sdk-go/ucloud"
11+
"github.com/ucloud/ucloud-sdk-go/ucloud/auth"
12+
)
13+
14+
//Client aggregate client for business
15+
type Client struct {
16+
uaccount.UAccountClient
17+
uhost.UHostClient
18+
unet.UNetClient
19+
ulb.ULBClient
20+
vpc.VPCClient
21+
pathx.PathXClient
22+
}
23+
24+
// NewClient will return a aggregate client
25+
func NewClient(config *ucloud.Config, credential *auth.Credential) *Client {
26+
return &Client{
27+
*uaccount.NewClient(config, credential),
28+
*uhost.NewClient(config, credential),
29+
*unet.NewClient(config, credential),
30+
*ulb.NewClient(config, credential),
31+
*vpc.NewClient(config, credential),
32+
*pathx.NewClient(config, credential),
33+
}
34+
}

base/config.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ import (
88
"strings"
99
"time"
1010

11-
"github.com/ucloud/ucloud-sdk-go/sdk"
12-
"github.com/ucloud/ucloud-sdk-go/sdk/auth"
13-
service "github.com/ucloud/ucloud-sdk-go/services"
1411
"github.com/ucloud/ucloud-sdk-go/services/uaccount"
12+
sdk "github.com/ucloud/ucloud-sdk-go/ucloud"
13+
"github.com/ucloud/ucloud-sdk-go/ucloud/auth"
1514
)
1615

1716
const configFile = "config.json"
@@ -204,5 +203,5 @@ func init() {
204203
SdkClient = sdk.NewClient(ClientConfig, Credential)
205204

206205
//bizClient 用于调用业务接口
207-
BizClient = service.NewClient(ClientConfig, Credential)
206+
BizClient = NewClient(ClientConfig, Credential)
208207
}

base/cli.go renamed to base/util.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@ import (
1313
"time"
1414
"unicode"
1515

16-
"github.com/ucloud/ucloud-sdk-go/sdk"
17-
uerr "github.com/ucloud/ucloud-sdk-go/sdk/error"
18-
"github.com/ucloud/ucloud-sdk-go/sdk/response"
19-
service "github.com/ucloud/ucloud-sdk-go/services"
16+
sdk "github.com/ucloud/ucloud-sdk-go/ucloud"
17+
uerr "github.com/ucloud/ucloud-sdk-go/ucloud/error"
18+
"github.com/ucloud/ucloud-sdk-go/ucloud/response"
2019

2120
"github.com/ucloud/ucloud-cli/model"
2221
)
@@ -34,7 +33,7 @@ var Cxt = model.GetContext(os.Stdout)
3433
var SdkClient *sdk.Client
3534

3635
//BizClient 用于调用业务接口
37-
var BizClient *service.Client
36+
var BizClient *Client
3837

3938
//GetHomePath 获取家目录
4039
func GetHomePath() string {
File renamed without changes.

cmd/eip.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ import (
1919
"strconv"
2020
"time"
2121

22-
"github.com/ucloud/ucloud-sdk-go/sdk"
23-
2422
"github.com/spf13/cobra"
23+
24+
sdk "github.com/ucloud/ucloud-sdk-go/ucloud"
25+
2526
. "github.com/ucloud/ucloud-cli/base"
2627
)
2728

@@ -133,9 +134,9 @@ func NewCmdEIPAllocate() *cobra.Command {
133134
req.Name = cmd.Flags().String("name", "EIP", "Name of your EIP.")
134135
req.Remark = cmd.Flags().String("remark", "", "Remark of your EIP.")
135136
req.CouponId = cmd.Flags().String("coupon-id", "", "Coupon ID, The Coupon can deducte part of the payment")
136-
cmd.Flags().SetFlagValues("line", []string{"BGP", "International"})
137-
cmd.Flags().SetFlagValues("charge-mode", []string{"Bandwidth", "Traffic", "ShareBandwidth"})
138-
cmd.Flags().SetFlagValues("charge-type", []string{"Month", "Year", "Dynamic", "Trial"})
137+
cmd.Flags().SetFlagValues("line", "BGP", "International")
138+
cmd.Flags().SetFlagValues("charge-mode", "Bandwidth", "Traffic", "ShareBandwidth")
139+
cmd.Flags().SetFlagValues("charge-type", "Month", "Year", "Dynamic", "Trial")
139140
cmd.MarkFlagRequired("line")
140141
cmd.MarkFlagRequired("bandwidth")
141142
return cmd

cmd/globalssh.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ func NewCmdGsshCreate() *cobra.Command {
186186
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")
187187
cmd.MarkFlagRequired("area")
188188
cmd.MarkFlagRequired("target-ip")
189-
cmd.Flags().SetFlagValues("area", []string{"LosAngeles", "Singapore", "HongKong", "Tokyo", "Washington", "Frankfurt"})
190-
cmd.Flags().SetFlagValues("charge-type", []string{"Month", "Year", "Dynamic", "Trial"})
189+
cmd.Flags().SetFlagValues("area", "LosAngeles", "Singapore", "HongKong", "Tokyo", "Washington", "Frankfurt")
190+
cmd.Flags().SetFlagValues("charge-type", "Month", "Year", "Dynamic", "Trial")
191191
return cmd
192192
}
193193

cmd/uhost.go

Lines changed: 132 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,17 @@ package cmd
1717
import (
1818
"fmt"
1919
"strings"
20+
"time"
2021

2122
"github.com/spf13/cobra"
2223

23-
"github.com/ucloud/ucloud-sdk-go/sdk"
2424
"github.com/ucloud/ucloud-sdk-go/services/uhost"
25+
sdk "github.com/ucloud/ucloud-sdk-go/ucloud"
26+
"github.com/ucloud/ucloud-sdk-go/ucloud/helpers/waiter"
27+
"github.com/ucloud/ucloud-sdk-go/ucloud/log"
2528

2629
. "github.com/ucloud/ucloud-cli/base"
30+
"github.com/ucloud/ucloud-cli/ux"
2731
)
2832

2933
//NewCmdUHost ucloud uhost
@@ -153,7 +157,6 @@ func NewCmdUHostCreate() *cobra.Command {
153157

154158
req.Disks = make([]uhost.UHostDisk, 2)
155159
req.Disks[0].IsBoot = sdk.Bool(true)
156-
req.Disks[0].Size = sdk.String("20")
157160
req.Disks[1].IsBoot = sdk.Bool(false)
158161

159162
flags := cmd.Flags()
@@ -173,6 +176,7 @@ func NewCmdUHostCreate() *cobra.Command {
173176
req.UHostType = flags.String("type", defaultUhostType, "Optional. Default is 'N2' of which cpu is V4 and sata disk. also support 'N1' means V3 cpu and sata disk;'I2' means V4 cpu and ssd disk;'D1' means big data model;'G1' means GPU type, model for K80;'G2' model for P40; 'G3' model for V100")
174177
req.NetCapability = flags.String("net-capability", "Normal", "Optional. Default is 'Normal', also support 'Super' which will enhance multiple times network capability as before")
175178
req.Disks[0].Type = flags.String("boot-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.")
179+
req.Disks[0].Size = flags.String("boot-disk-size", "20", "Optional. Default 20G. Windows should be bigger than 40G Unit GB")
176180
req.Disks[0].BackupType = flags.String("boot-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)")
177181
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.")
178182
req.Disks[1].Size = flags.String("data-disk-size", "20", "Optional. Disk size. Unit GB")
@@ -182,14 +186,44 @@ func NewCmdUHostCreate() *cobra.Command {
182186
req.Tag = flags.String("ugroup", "Default", "Optional. Business group")
183187
req.CouponId = flags.String("coupon-id", "", "Optional. Coupon ID, The Coupon can deduct part of the payment,see DescribeCoupon or https://accountv2.ucloud.cn")
184188

185-
cmd.Flags().SetFlagValues("charge-type", []string{"Month", "Year", "Dynamic", "Trial"})
186-
cmd.Flags().SetFlagValues("cpu", []string{"1", "2", "4", "8", "12", "16", "24", "32"})
187-
cmd.Flags().SetFlagValues("type", []string{"N2", "N1", "I2", "D1", "G1", "G2", "G3"})
188-
cmd.Flags().SetFlagValues("net-capability", []string{"Normal", "Super"})
189-
cmd.Flags().SetFlagValues("boot-disk-type", []string{"LOCAL_NORMAL", "CLOUD_NORMAL", "LOCAL_SSD", "CLOUD_SSD", "EXCLUSIVE_LOCAL_DISK"})
190-
cmd.Flags().SetFlagValues("boot-disk-backup-type", []string{"NONE", "DATAARK"})
191-
cmd.Flags().SetFlagValues("data-disk-type", []string{"LOCAL_NORMAL", "CLOUD_NORMAL", "LOCAL_SSD", "CLOUD_SSD", "EXCLUSIVE_LOCAL_DISK"})
192-
cmd.Flags().SetFlagValues("data-disk-backup-type", []string{"NONE", "DATAARK"})
189+
cmd.Flags().SetFlagValues("charge-type", "Month", "Year", "Dynamic", "Trial")
190+
cmd.Flags().SetFlagValues("cpu", "1", "2", "4", "8", "12", "16", "24", "32")
191+
cmd.Flags().SetFlagValues("type", "N2", "N1", "I2", "D1", "G1", "G2", "G3")
192+
cmd.Flags().SetFlagValues("net-capability", "Normal", "Super")
193+
cmd.Flags().SetFlagValues("boot-disk-type", "LOCAL_NORMAL", "CLOUD_NORMAL", "LOCAL_SSD", "CLOUD_SSD", "EXCLUSIVE_LOCAL_DISK")
194+
cmd.Flags().SetFlagValues("boot-disk-backup-type", "NONE", "DATAARK")
195+
cmd.Flags().SetFlagValues("data-disk-type", "LOCAL_NORMAL", "CLOUD_NORMAL", "LOCAL_SSD", "CLOUD_SSD", "EXCLUSIVE_LOCAL_DISK")
196+
cmd.Flags().SetFlagValues("data-disk-backup-type", "NONE", "DATAARK")
197+
198+
cmd.Flags().SetFlagValuesFunc("image-id", func() []string {
199+
req := BizClient.NewDescribeImageRequest()
200+
projectID, _ := flags.GetString("project-id")
201+
if projectID == "" {
202+
projectID = ConfigInstance.ProjectID
203+
}
204+
req.ProjectId = sdk.String(projectID)
205+
206+
region, _ := flags.GetString("region")
207+
if region == "" {
208+
region = ConfigInstance.Region
209+
}
210+
req.Region = sdk.String(region)
211+
212+
zone, _ := flags.GetString("zone")
213+
if zone == "" {
214+
zone = ConfigInstance.Zone
215+
}
216+
req.Zone = sdk.String(zone)
217+
req.ImageType = sdk.String("Base")
218+
result := make([]string, 0)
219+
resp, err := BizClient.DescribeImage(req)
220+
if err == nil {
221+
for _, image := range resp.ImageSet {
222+
result = append(result, image.ImageId)
223+
}
224+
}
225+
return result
226+
})
193227

194228
cmd.MarkFlagRequired("cpu")
195229
cmd.MarkFlagRequired("memory")
@@ -220,6 +254,19 @@ func NewCmdUHostDelete() *cobra.Command {
220254
} else {
221255
req.EIPReleased = sdk.String("no")
222256
}
257+
hostIns, err := describeUHostByID(*req.UHostId, *req.ProjectId, *req.Region, *req.Zone)
258+
if err != nil {
259+
HandleError(err)
260+
} else if hostIns != nil {
261+
if hostIns.State == "Running" {
262+
_req := BizClient.NewStopUHostInstanceRequest()
263+
_req.ProjectId = req.ProjectId
264+
_req.Region = req.Region
265+
_req.Zone = req.Zone
266+
_req.UHostId = req.UHostId
267+
stopUhostIns(_req)
268+
}
269+
}
223270
resp, err := BizClient.TerminateUHostInstance(req)
224271
if err != nil {
225272
HandleError(err)
@@ -235,6 +282,8 @@ func NewCmdUHostDelete() *cobra.Command {
235282
req.UHostId = cmd.Flags().String("resource-id", "", "ResourceID of the uhost instance( or UHostId)")
236283
isDestory = cmd.Flags().Bool("destory", false, "false,the uhost instance will be thrown to UHost recycle If you have permission; true,the uhost instance will be deleted directly")
237284
isEipReleased = cmd.Flags().Bool("eip-released", false, "false,Unbind EIP only; true, Unbind EIP and release it")
285+
cmd.Flags().SetFlagValues("destory", "true", "false")
286+
cmd.Flags().SetFlagValues("eip-released", "true", "false")
238287
cmd.MarkFlagRequired("resource-id")
239288

240289
return cmd
@@ -248,12 +297,7 @@ func NewCmdUHostStop() *cobra.Command {
248297
Short: "Shut down uhost instance",
249298
Long: "Shut down uhost instance",
250299
Run: func(cmd *cobra.Command, args []string) {
251-
resp, err := BizClient.StopUHostInstance(req)
252-
if err != nil {
253-
HandleError(err)
254-
} else {
255-
Cxt.Printf("UHost:[%v] is shuting down. Wait a moment\n", resp.UhostId)
256-
}
300+
stopUhostIns(req)
257301
},
258302
}
259303
req.ProjectId = cmd.Flags().String("project-id", ConfigInstance.ProjectID, "Assign project-id")
@@ -265,6 +309,19 @@ func NewCmdUHostStop() *cobra.Command {
265309
return cmd
266310
}
267311

312+
func stopUhostIns(req *uhost.StopUHostInstanceRequest) {
313+
resp, err := BizClient.StopUHostInstance(req)
314+
if err != nil {
315+
HandleError(err)
316+
} else {
317+
text := fmt.Sprintf("UHost:[%v] is shuting down", resp.UhostId)
318+
done := poll(resp.UhostId, *req.ProjectId, *req.Region, *req.Zone, "Stopped")
319+
ux.DotSpinner.Start(text)
320+
<-done
321+
ux.DotSpinner.Stop()
322+
}
323+
}
324+
268325
//NewCmdUHostStart ucloud uhost start
269326
func NewCmdUHostStart() *cobra.Command {
270327
req := BizClient.NewStartUHostInstanceRequest()
@@ -278,7 +335,11 @@ func NewCmdUHostStart() *cobra.Command {
278335
if err != nil {
279336
HandleError(err)
280337
} else {
281-
Cxt.Printf("UHost:[%v] is starting. Wait a moment\n", resp.UhostId)
338+
text := fmt.Sprintf("UHost:[%v] is starting", resp.UhostId)
339+
done := poll(resp.UhostId, *req.ProjectId, *req.Region, *req.Zone, "Running")
340+
ux.DotSpinner.Start(text)
341+
<-done
342+
ux.DotSpinner.Stop()
282343
}
283344
},
284345
}
@@ -304,7 +365,11 @@ func NewCmdUHostReboot() *cobra.Command {
304365
if err != nil {
305366
HandleError(err)
306367
} else {
307-
Cxt.Printf("UHost:[%v] is restarting. Wait a moment\n", resp.UhostId)
368+
text := fmt.Sprintf("UHost:[%v] is restarting", resp.UhostId)
369+
done := poll(resp.UhostId, *req.ProjectId, *req.Region, *req.Zone, "Running")
370+
ux.DotSpinner.Start(text)
371+
<-done
372+
ux.DotSpinner.Stop()
308373
}
309374
},
310375
}
@@ -382,3 +447,52 @@ func NewCmdUHostScale() *cobra.Command {
382447
cmd.MarkFlagRequired("resource-id")
383448
return cmd
384449
}
450+
451+
func poll(uhostID, projectID, region, zone string, targetState string) chan bool {
452+
w := waiter.StateWaiter{
453+
Pending: []string{"pending"},
454+
Target: []string{"avaliable"},
455+
Refresh: func() (interface{}, string, error) {
456+
inst, err := describeUHostByID(uhostID, projectID, region, zone)
457+
if err != nil {
458+
return nil, "", err
459+
}
460+
461+
if inst == nil || inst.State != targetState {
462+
return nil, "pending", nil
463+
}
464+
465+
return inst, "avaliable", nil
466+
},
467+
Timeout: 5 * time.Minute,
468+
}
469+
470+
done := make(chan bool)
471+
go func() {
472+
if resp, err := w.Wait(); err != nil {
473+
log.Error(err)
474+
} else {
475+
log.Infof("%#v", resp)
476+
}
477+
done <- true
478+
}()
479+
return done
480+
}
481+
482+
func describeUHostByID(uhostID, projectID, region, zone string) (*uhost.UHostInstanceSet, error) {
483+
req := BizClient.NewDescribeUHostInstanceRequest()
484+
req.UHostIds = []string{uhostID}
485+
req.ProjectId = &projectID
486+
req.Region = &region
487+
req.Zone = &zone
488+
489+
resp, err := BizClient.DescribeUHostInstance(req)
490+
if err != nil {
491+
return nil, err
492+
}
493+
if len(resp.UHostSet) < 1 {
494+
return nil, nil
495+
}
496+
497+
return &resp.UHostSet[0], nil
498+
}

0 commit comments

Comments
 (0)