github.com/huaweicloud/golangsdk@v0.0.0-20210831081626-d823fe11ceba/util.go (about) 1 package golangsdk 2 3 import ( 4 "fmt" 5 "net/url" 6 "path/filepath" 7 "strings" 8 "time" 9 ) 10 11 // WaitFor polls a predicate function, once per second, up to a timeout limit. 12 // This is useful to wait for a resource to transition to a certain state. 13 // To handle situations when the predicate might hang indefinitely, the 14 // predicate will be prematurely cancelled after the timeout. 15 // Resource packages will wrap this in a more convenient function that's 16 // specific to a certain resource, but it can also be useful on its own. 17 func WaitFor(timeout int, predicate func() (bool, error)) error { 18 type WaitForResult struct { 19 Success bool 20 Error error 21 } 22 23 start := time.Now().Unix() 24 25 for { 26 // If a timeout is set, and that's been exceeded, shut it down. 27 if timeout >= 0 && time.Now().Unix()-start >= int64(timeout) { 28 return fmt.Errorf("A timeout occurred") 29 } 30 31 time.Sleep(5 * time.Second) 32 33 var result WaitForResult 34 ch := make(chan bool, 1) 35 go func() { 36 defer close(ch) 37 satisfied, err := predicate() 38 result.Success = satisfied 39 result.Error = err 40 }() 41 42 select { 43 case <-ch: 44 if result.Error != nil { 45 return result.Error 46 } 47 if result.Success { 48 return nil 49 } 50 // If the predicate has not finished by the timeout, cancel it. 51 case <-time.After(time.Duration(timeout) * time.Second): 52 return fmt.Errorf("A timeout occurred") 53 } 54 } 55 } 56 57 // NormalizeURL is an internal function to be used by provider clients. 58 // 59 // It ensures that each endpoint URL has a closing `/`, as expected by 60 // ServiceClient's methods. 61 func NormalizeURL(url string) string { 62 if !strings.HasSuffix(url, "/") { 63 return url + "/" 64 } 65 return url 66 } 67 68 // NormalizePathURL is used to convert rawPath to a fqdn, using basePath as 69 // a reference in the filesystem, if necessary. basePath is assumed to contain 70 // either '.' when first used, or the file:// type fqdn of the parent resource. 71 // e.g. myFavScript.yaml => file://opt/lib/myFavScript.yaml 72 func NormalizePathURL(basePath, rawPath string) (string, error) { 73 u, err := url.Parse(rawPath) 74 if err != nil { 75 return "", err 76 } 77 // if a scheme is defined, it must be a fqdn already 78 if u.Scheme != "" { 79 return u.String(), nil 80 } 81 // if basePath is a url, then child resources are assumed to be relative to it 82 bu, err := url.Parse(basePath) 83 if err != nil { 84 return "", err 85 } 86 var basePathSys, absPathSys string 87 if bu.Scheme != "" { 88 basePathSys = filepath.FromSlash(bu.Path) 89 absPathSys = filepath.Join(basePathSys, rawPath) 90 bu.Path = filepath.ToSlash(absPathSys) 91 return bu.String(), nil 92 } 93 94 absPathSys = filepath.Join(basePath, rawPath) 95 u.Path = filepath.ToSlash(absPathSys) 96 if err != nil { 97 return "", err 98 } 99 u.Scheme = "file" 100 return u.String(), nil 101 102 }