waiters.go 2.9 KB

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