66 "errors"
77 "log"
88 "reflect"
9+ "regexp"
910 "strconv"
1011 "strings"
1112 "time"
@@ -17,6 +18,7 @@ import (
1718)
1819
1920var (
21+ MaxRetries uint = 6
2022 FiveMinutes time.Duration = 5 * time .Minute
2123 TwoHours time.Duration = 120 * time .Minute
2224 DefaultTimeout = & schema.ResourceTimeout {
@@ -136,14 +138,29 @@ func LoadBalancerResourceGet(s BaseCrud, workReq *baremetal.WorkRequest) (id str
136138 return id , false , nil
137139}
138140
141+ func exponentialBackoffSleep (retryNum uint ) {
142+ secondsToSleep := 1 << retryNum
143+ log .Printf ("[DEBUG] Got a retriable error. Waiting %d seconds and trying again..." , secondsToSleep )
144+ time .Sleep (time .Duration (secondsToSleep ) * time .Second )
145+ }
146+
147+ func isRetriableError (error string ) bool {
148+ //all errors are retriable except 400, 401, 412, and 409 with code InvalidatedRetryToken
149+ lowerCaseError := strings .ToLower (error )
150+ statusMatch , _ := regexp .MatchString ("status\\ s*:\\ s*4(0[01]|12)" , lowerCaseError )
151+ codeMatch , _ := regexp .MatchString ("code\\ s*:\\ s*invalidatedretrytoken" , lowerCaseError )
152+ return ! statusMatch && ! codeMatch
153+ }
154+
139155func CreateResource (d * schema.ResourceData , sync ResourceCreator ) (e error ) {
156+ return createResourceWithRetry (d , sync , 1 )
157+ }
158+
159+ func createResourceWithRetry (d * schema.ResourceData , sync ResourceCreator , retryNum uint ) (e error ) {
140160 if e = sync .Create (); e != nil {
141- // Check for conflicts and retry
142- // This happens with concurrent volume attachments, etc
143- if strings .Contains (strings .ToLower (e .Error ()), "try again later" ) {
144- log .Println ("[DEBUG] Resource creation conflicts with other resources. Waiting 10 seconds and trying again..." )
145- time .Sleep (10 * time .Second )
146- e = CreateResource (d , sync )
161+ if isRetriableError (e .Error ()) && retryNum <= MaxRetries {
162+ exponentialBackoffSleep (retryNum )
163+ e = createResourceWithRetry (d , sync , retryNum + 1 )
147164 }
148165 return e
149166 }
@@ -166,8 +183,18 @@ func CreateResource(d *schema.ResourceData, sync ResourceCreator) (e error) {
166183}
167184
168185func ReadResource (sync ResourceReader ) (e error ) {
186+ return readResourceWithRetry (sync , 1 )
187+ }
188+
189+ func readResourceWithRetry (sync ResourceReader , retryNum uint ) (e error ) {
169190 if e = sync .Get (); e != nil {
170191 handleMissingResourceError (sync , & e )
192+ if e != nil {
193+ if isRetriableError (e .Error ()) && retryNum <= MaxRetries {
194+ exponentialBackoffSleep (retryNum )
195+ e = readResourceWithRetry (sync , retryNum + 1 )
196+ }
197+ }
171198 return
172199 }
173200
@@ -188,8 +215,16 @@ func ReadResource(sync ResourceReader) (e error) {
188215}
189216
190217func UpdateResource (d * schema.ResourceData , sync ResourceUpdater ) (e error ) {
218+ return updateResourceWithRetry (d , sync , 1 )
219+ }
220+
221+ func updateResourceWithRetry (d * schema.ResourceData , sync ResourceUpdater , retryNum uint ) (e error ) {
191222 d .Partial (true )
192223 if e = sync .Update (); e != nil {
224+ if isRetriableError (e .Error ()) && retryNum <= MaxRetries {
225+ exponentialBackoffSleep (retryNum )
226+ e = updateResourceWithRetry (d , sync , retryNum + 1 )
227+ }
193228 return
194229 }
195230 d .Partial (false )
@@ -203,9 +238,17 @@ func UpdateResource(d *schema.ResourceData, sync ResourceUpdater) (e error) {
203238// () -> Pending -> Deleted.
204239// Finally, sets the ResourceData state to empty.
205240func DeleteResource (d * schema.ResourceData , sync ResourceDeleter ) (e error ) {
241+ return deleteResourceWithRetry (d , sync , 1 )
242+ }
243+
244+ func deleteResourceWithRetry (d * schema.ResourceData , sync ResourceDeleter , retryNum uint ) (e error ) {
206245 if e = sync .Delete (); e != nil {
207246 handleMissingResourceError (sync , & e )
208247 if e != nil {
248+ if isRetriableError (e .Error ()) && retryNum <= MaxRetries {
249+ exponentialBackoffSleep (retryNum )
250+ e = deleteResourceWithRetry (d , sync , retryNum + 1 )
251+ }
209252 return
210253 }
211254 }
0 commit comments