]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/hashicorp/terraform/helper/resource/wait.go
Initial transfer of provider code
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / helper / resource / wait.go
1 package resource
2
3 import (
4 "sync"
5 "time"
6 )
7
8 // Retry is a basic wrapper around StateChangeConf that will just retry
9 // a function until it no longer returns an error.
10 func Retry(timeout time.Duration, f RetryFunc) error {
11 // These are used to pull the error out of the function; need a mutex to
12 // avoid a data race.
13 var resultErr error
14 var resultErrMu sync.Mutex
15
16 c := &StateChangeConf{
17 Pending: []string{"retryableerror"},
18 Target: []string{"success"},
19 Timeout: timeout,
20 MinTimeout: 500 * time.Millisecond,
21 Refresh: func() (interface{}, string, error) {
22 rerr := f()
23
24 resultErrMu.Lock()
25 defer resultErrMu.Unlock()
26
27 if rerr == nil {
28 resultErr = nil
29 return 42, "success", nil
30 }
31
32 resultErr = rerr.Err
33
34 if rerr.Retryable {
35 return 42, "retryableerror", nil
36 }
37 return nil, "quit", rerr.Err
38 },
39 }
40
41 _, waitErr := c.WaitForState()
42
43 // Need to acquire the lock here to be able to avoid race using resultErr as
44 // the return value
45 resultErrMu.Lock()
46 defer resultErrMu.Unlock()
47
48 // resultErr may be nil because the wait timed out and resultErr was never
49 // set; this is still an error
50 if resultErr == nil {
51 return waitErr
52 }
53 // resultErr takes precedence over waitErr if both are set because it is
54 // more likely to be useful
55 return resultErr
56 }
57
58 // RetryFunc is the function retried until it succeeds.
59 type RetryFunc func() *RetryError
60
61 // RetryError is the required return type of RetryFunc. It forces client code
62 // to choose whether or not a given error is retryable.
63 type RetryError struct {
64 Err error
65 Retryable bool
66 }
67
68 // RetryableError is a helper to create a RetryError that's retryable from a
69 // given error.
70 func RetryableError(err error) *RetryError {
71 if err == nil {
72 return nil
73 }
74 return &RetryError{Err: err, Retryable: true}
75 }
76
77 // NonRetryableError is a helper to create a RetryError that's _not)_ retryable
78 // from a given error.
79 func NonRetryableError(err error) *RetryError {
80 if err == nil {
81 return nil
82 }
83 return &RetryError{Err: err, Retryable: false}
84 }