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  }