forked from aws/aws-sdk-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
waiters.go
137 lines (120 loc) · 2.96 KB
/
waiters.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package api
import (
"bytes"
"encoding/json"
"fmt"
"os"
"sort"
"text/template"
)
// A Waiter is an individual waiter definition.
type Waiter struct {
Name string
Delay int
MaxAttempts int
OperationName string `json:"operation"`
Operation *Operation
Acceptors []WaitAcceptor
}
// A WaitAcceptor is an individual wait acceptor definition.
type WaitAcceptor struct {
Expected interface{}
Matcher string
State string
Argument string
}
// WaitersGoCode generates and returns Go code for each of the waiters of
// this API.
func (a *API) WaitersGoCode() string {
var buf bytes.Buffer
fmt.Fprintf(&buf, "import (\n\t%q\n)",
"github.com/aws/aws-sdk-go/private/waiter")
for _, w := range a.Waiters {
buf.WriteString(w.GoCode())
}
return buf.String()
}
// used for unmarshaling from the waiter JSON file
type waiterDefinitions struct {
*API
Waiters map[string]Waiter
}
// AttachWaiters reads a file of waiter definitions, and adds those to the API.
// Will panic if an error occurs.
func (a *API) AttachWaiters(filename string) {
p := waiterDefinitions{API: a}
f, err := os.Open(filename)
defer f.Close()
if err != nil {
panic(err)
}
err = json.NewDecoder(f).Decode(&p)
if err != nil {
panic(err)
}
p.setup()
}
func (p *waiterDefinitions) setup() {
p.API.Waiters = []Waiter{}
i, keys := 0, make([]string, len(p.Waiters))
for k := range p.Waiters {
keys[i] = k
i++
}
sort.Strings(keys)
for _, n := range keys {
e := p.Waiters[n]
n = p.ExportableName(n)
e.Name = n
e.OperationName = p.ExportableName(e.OperationName)
e.Operation = p.API.Operations[e.OperationName]
if e.Operation == nil {
panic("unknown operation " + e.OperationName + " for waiter " + n)
}
p.API.Waiters = append(p.API.Waiters, e)
}
}
// ExpectedString returns the string that was expected by the WaitAcceptor
func (a *WaitAcceptor) ExpectedString() string {
switch a.Expected.(type) {
case string:
return fmt.Sprintf("%q", a.Expected)
default:
return fmt.Sprintf("%v", a.Expected)
}
}
var tplWaiter = template.Must(template.New("waiter").Parse(`
var waiter{{ .Name }} *waiter.Config
func (c *{{ .Operation.API.StructName }}) WaitUntil{{ .Name }}(input {{ .Operation.InputRef.GoType }}) error {
if waiter{{ .Name }} == nil {
waiter{{ .Name }} = &waiter.Config{
Operation: "{{ .OperationName }}",
Delay: {{ .Delay }},
MaxAttempts: {{ .MaxAttempts }},
Acceptors: []waiter.WaitAcceptor{
{{ range $_, $a := .Acceptors }}waiter.WaitAcceptor{
State: "{{ .State }}",
Matcher: "{{ .Matcher }}",
Argument: "{{ .Argument }}",
Expected: {{ .ExpectedString }},
},
{{ end }}
},
}
}
w := waiter.Waiter{
Client: c,
Input: input,
Config: waiter{{ .Name }},
}
return w.Wait()
}
`))
// GoCode returns the generated Go code for an individual waiter.
func (w *Waiter) GoCode() string {
var buf bytes.Buffer
if err := tplWaiter.Execute(&buf, w); err != nil {
panic(err)
}
return buf.String()
}