github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/provider/azure/utils.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package azure 5 6 import ( 7 "math/rand" 8 "net/http" 9 "time" 10 11 "github.com/Azure/azure-sdk-for-go/Godeps/_workspace/src/github.com/Azure/go-autorest/autorest" 12 "github.com/Azure/azure-sdk-for-go/Godeps/_workspace/src/github.com/Azure/go-autorest/autorest/to" 13 "github.com/juju/retry" 14 "github.com/juju/utils" 15 "github.com/juju/utils/clock" 16 ) 17 18 const ( 19 retryDelay = 5 * time.Second 20 maxRetryDelay = 1 * time.Minute 21 maxRetryDuration = 5 * time.Minute 22 ) 23 24 func toTagsPtr(tags map[string]string) *map[string]*string { 25 stringPtrMap := to.StringMapPtr(tags) 26 return &stringPtrMap 27 } 28 29 func toTags(tags *map[string]*string) map[string]string { 30 if tags == nil { 31 return nil 32 } 33 return to.StringMap(*tags) 34 } 35 36 // randomAdminPassword returns a random administrator password for 37 // Windows machines. 38 func randomAdminPassword() string { 39 // We want at least one each of lower-alpha, upper-alpha, and digit. 40 // Allocate 16 of each (randomly), and then the remaining characters 41 // will be randomly chosen from the full set. 42 validRunes := append(utils.LowerAlpha, utils.Digits...) 43 validRunes = append(validRunes, utils.UpperAlpha...) 44 45 lowerAlpha := utils.RandomString(16, utils.LowerAlpha) 46 upperAlpha := utils.RandomString(16, utils.UpperAlpha) 47 digits := utils.RandomString(16, utils.Digits) 48 mixed := utils.RandomString(16, validRunes) 49 password := []rune(lowerAlpha + upperAlpha + digits + mixed) 50 for i := len(password) - 1; i >= 1; i-- { 51 j := rand.Intn(i + 1) 52 password[i], password[j] = password[j], password[i] 53 } 54 return string(password) 55 } 56 57 // callAPIFunc is a function type that should wrap any any 58 // Azure Resource Manager API calls. 59 type callAPIFunc func(func() (autorest.Response, error)) error 60 61 // backoffAPIRequestCaller is a type whose "call" method can 62 // be used as a callAPIFunc. 63 type backoffAPIRequestCaller struct { 64 clock clock.Clock 65 } 66 67 // call will call the supplied function, with exponential backoff 68 // as long as the request returns an http.StatusTooManyRequests 69 // status. 70 func (c backoffAPIRequestCaller) call(f func() (autorest.Response, error)) error { 71 var resp *http.Response 72 return retry.Call(retry.CallArgs{ 73 Func: func() error { 74 autorestResp, err := f() 75 resp = autorestResp.Response 76 return err 77 }, 78 IsFatalError: func(err error) bool { 79 return resp == nil || !autorest.ResponseHasStatusCode(resp, http.StatusTooManyRequests) 80 }, 81 NotifyFunc: func(err error, attempt int) { 82 logger.Debugf("attempt %d: %v", attempt, err) 83 }, 84 Attempts: -1, 85 Delay: retryDelay, 86 MaxDelay: maxRetryDelay, 87 MaxDuration: maxRetryDuration, 88 BackoffFunc: retry.DoubleDelay, 89 Clock: c.clock, 90 }) 91 }