@@ -20,6 +20,7 @@ import (
2020 "github.com/ucloud/ucloud-sdk-go/ucloud/response"
2121
2222 "github.com/ucloud/ucloud-cli/model"
23+ "github.com/ucloud/ucloud-cli/ux"
2324)
2425
2526//ConfigPath 配置文件路径
@@ -263,59 +264,162 @@ var RegionLabel = map[string]string{
263264 "afr-nigeria" : "Lagos" ,
264265}
265266
266- //Poll 轮询
267- func Poll (describeFunc func (string , string , string , string ) (interface {}, error )) func (string , string , string , string , []string ) chan bool {
268- stateFields := []string {"State" , "Status" }
269- return func (resourceID , projectID , region , zone string , targetState []string ) chan bool {
270- w := waiter.StateWaiter {
271- Pending : []string {"pending" },
272- Target : []string {"avaliable" },
273- Refresh : func () (interface {}, string , error ) {
274- inst , err := describeFunc (resourceID , projectID , region , zone )
275- if err != nil {
276- return nil , "" , err
277- }
267+ //Poller 轮询器
268+ type Poller struct {
269+ stateFields []string
270+ DescribeFunc func (string , string , string , string ) (interface {}, error )
271+ Out io.Writer
272+ Timeout time.Duration
273+ SdescribeFunc func (string ) (interface {}, error )
274+ }
275+
276+ //Spoll 简化版
277+ func (p * Poller ) Spoll (resourceID , pollText string , targetStates []string ) {
278+ w := waiter.StateWaiter {
279+ Pending : []string {"pending" },
280+ Target : []string {"avaliable" },
281+ Refresh : func () (interface {}, string , error ) {
282+ inst , err := p .SdescribeFunc (resourceID )
283+ if err != nil {
284+ return nil , "" , err
285+ }
278286
279- if inst == nil {
280- return nil , "pending" , nil
287+ if inst == nil {
288+ return nil , "pending" , nil
289+ }
290+ instValue := reflect .ValueOf (inst )
291+ instValue = reflect .Indirect (instValue )
292+ instType := instValue .Type ()
293+ if instValue .Kind () != reflect .Struct {
294+ return nil , "" , fmt .Errorf ("Instance is not struct" )
295+ }
296+ state := ""
297+ for i := 0 ; i < instValue .NumField (); i ++ {
298+ for _ , sf := range p .stateFields {
299+ if instType .Field (i ).Name == sf {
300+ state = instValue .Field (i ).String ()
301+ }
281302 }
282- instValue := reflect .ValueOf (inst )
283- instValue = reflect .Indirect (instValue )
284- instType := instValue .Type ()
285- if instValue .Kind () != reflect .Struct {
286- return nil , "" , fmt .Errorf ("Instance is not struct" )
303+ }
304+ if state != "" {
305+ for _ , t := range targetStates {
306+ if t == state {
307+ return inst , "avaliable" , nil
308+ }
287309 }
288- state := ""
289- for i := 0 ; i < instValue .NumField (); i ++ {
290- for _ , sf := range stateFields {
291- if instType .Field (i ).Name == sf {
292- state = instValue .Field (i ).String ()
293- }
310+ }
311+ return nil , "pending" , nil
312+
313+ },
314+ Timeout : p .Timeout ,
315+ }
316+
317+ done := make (chan bool )
318+ go func () {
319+ if resp , err := w .Wait (); err != nil {
320+ log .Error (err )
321+ if _ , ok := err .(* waiter.TimeoutError ); ok {
322+ done <- false
323+ return
324+ }
325+ } else {
326+ log .Infof ("%#v" , resp )
327+ }
328+ done <- true
329+ }()
330+
331+ spinner := ux .NewDotSpinner (p .Out )
332+ spinner .Start (pollText )
333+ ret := <- done
334+ if ret {
335+ spinner .Stop ()
336+ } else {
337+ spinner .Timeout ()
338+ }
339+ }
340+
341+ //Poll function
342+ func (p * Poller ) Poll (resourceID , projectID , region , zone , pollText string , targetState []string ) {
343+ w := waiter.StateWaiter {
344+ Pending : []string {"pending" },
345+ Target : []string {"avaliable" },
346+ Refresh : func () (interface {}, string , error ) {
347+ inst , err := p .DescribeFunc (resourceID , projectID , region , zone )
348+ if err != nil {
349+ return nil , "" , err
350+ }
351+
352+ if inst == nil {
353+ return nil , "pending" , nil
354+ }
355+ instValue := reflect .ValueOf (inst )
356+ instValue = reflect .Indirect (instValue )
357+ instType := instValue .Type ()
358+ if instValue .Kind () != reflect .Struct {
359+ return nil , "" , fmt .Errorf ("Instance is not struct" )
360+ }
361+ state := ""
362+ for i := 0 ; i < instValue .NumField (); i ++ {
363+ for _ , sf := range p .stateFields {
364+ if instType .Field (i ).Name == sf {
365+ state = instValue .Field (i ).String ()
294366 }
295367 }
296- if state != "" {
297- for _ , t := range targetState {
298- if t == state {
299- return inst , "avaliable" , nil
300- }
368+ }
369+ if state != "" {
370+ for _ , t := range targetState {
371+ if t == state {
372+ return inst , "avaliable" , nil
301373 }
302374 }
303- return nil , "pending" , nil
375+ }
376+ return nil , "pending" , nil
304377
305- },
306- Timeout : 5 * time . Minute ,
307- }
378+ },
379+ Timeout : p . Timeout ,
380+ }
308381
309- done := make (chan bool )
310- go func () {
311- if resp , err := w .Wait (); err != nil {
312- log .Error (err )
313- } else {
314- log .Infof ("%#v" , resp )
382+ done := make (chan bool )
383+ go func () {
384+ if resp , err := w .Wait (); err != nil {
385+ log .Error (err )
386+ if _ , ok := err .(* waiter.TimeoutError ); ok {
387+ done <- false
388+ return
315389 }
316- done <- true
317- }()
318- return done
390+ } else {
391+ log .Infof ("%#v" , resp )
392+ }
393+ done <- true
394+ }()
395+
396+ spinner := ux .NewDotSpinner (p .Out )
397+ spinner .Start (pollText )
398+ ret := <- done
399+ if ret {
400+ spinner .Stop ()
401+ } else {
402+ spinner .Timeout ()
403+ }
404+ }
405+
406+ //NewSpoller simple
407+ func NewSpoller (describeFunc func (string ) (interface {}, error ), out io.Writer ) * Poller {
408+ return & Poller {
409+ SdescribeFunc : describeFunc ,
410+ Out : out ,
411+ stateFields : []string {"State" , "Status" },
412+ Timeout : 10 * time .Minute ,
413+ }
414+ }
415+
416+ //NewPoller 轮询
417+ func NewPoller (describeFunc func (string , string , string , string ) (interface {}, error ), out io.Writer ) * Poller {
418+ return & Poller {
419+ DescribeFunc : describeFunc ,
420+ Out : out ,
421+ stateFields : []string {"State" , "Status" },
422+ Timeout : 10 * time .Minute ,
319423 }
320424}
321425
0 commit comments