123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- // +build codegen
- package api
- import (
- "bytes"
- "encoding/json"
- "fmt"
- "os"
- "sort"
- "strings"
- "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 waiterTmpls = template.Must(template.New("waiterTmpls").Parse(`
- {{ define "docstring" -}}
- // WaitUntil{{ .Name }} uses the {{ .Operation.API.NiceName }} API operation
- // {{ .OperationName }} to wait for a condition to be met before returning.
- // If the condition is not meet within the max attempt window an error will
- // be returned.
- {{- end }}
- {{ define "waiter" }}
- {{ template "docstring" . }}
- func (c *{{ .Operation.API.StructName }}) WaitUntil{{ .Name }}(input {{ .Operation.InputRef.GoType }}) error {
- waiterCfg := 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: waiterCfg,
- }
- return w.Wait()
- }
- {{- end }}
- {{ define "waiter interface" }}
- WaitUntil{{ .Name }}({{ .Operation.InputRef.GoTypeWithPkgName }}) error
- {{- end }}
- `))
- // InterfaceSignature returns a string representing the Waiter's interface
- // function signature.
- func (w *Waiter) InterfaceSignature() string {
- var buf bytes.Buffer
- if err := waiterTmpls.ExecuteTemplate(&buf, "waiter interface", w); err != nil {
- panic(err)
- }
- return strings.TrimSpace(buf.String())
- }
- // GoCode returns the generated Go code for an individual waiter.
- func (w *Waiter) GoCode() string {
- var buf bytes.Buffer
- if err := waiterTmpls.ExecuteTemplate(&buf, "waiter", w); err != nil {
- panic(err)
- }
- return buf.String()
- }
|