~juju-qa/ubuntu/yakkety/juju/2.0-rc3-again

« back to all changes in this revision

Viewing changes to src/launchpad.net/goamz/exp/sns/sns.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-04-24 22:34:47 UTC
  • Revision ID: package-import@ubuntu.com-20130424223447-f0qdji7ubnyo0s71
Tags: upstream-1.10.0.1
ImportĀ upstreamĀ versionĀ 1.10.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// goamz - Go packages to interact with the Amazon Web Services.
 
3
//
 
4
//   https://wiki.ubuntu.com/goamz
 
5
//
 
6
// Copyright (c) 2011 Memeo Inc.
 
7
//
 
8
// Written by Prudhvi Krishna Surapaneni <me@prudhvi.net>
 
9
 
 
10
// This package is in an experimental state, and does not currently
 
11
// follow conventions and style of the rest of goamz or common
 
12
// Go conventions. It must be polished before it's considered a
 
13
// first-class package in goamz.
 
14
package sns
 
15
 
 
16
// BUG(niemeyer): Package needs significant clean up.
 
17
 
 
18
// BUG(niemeyer): Topic values in responses are not being initialized
 
19
// properly, since they're supposed to reference *SNS.
 
20
 
 
21
// BUG(niemeyer): Package needs documentation.
 
22
 
 
23
// BUG(niemeyer): Message.Message should be "Payload []byte"
 
24
 
 
25
// BUG(niemeyer): Message.SNS must be dropped.
 
26
 
 
27
import (
 
28
        "encoding/xml"
 
29
        "errors"
 
30
        "launchpad.net/goamz/aws"
 
31
        "net/http"
 
32
        "net/url"
 
33
        "strconv"
 
34
        "time"
 
35
)
 
36
 
 
37
// The SNS type encapsulates operation with an SNS region.
 
38
type SNS struct {
 
39
        aws.Auth
 
40
        aws.Region
 
41
        private byte // Reserve the right of using private data.
 
42
}
 
43
 
 
44
type Topic struct {
 
45
        SNS      *SNS
 
46
        TopicArn string
 
47
}
 
48
 
 
49
func New(auth aws.Auth, region aws.Region) *SNS {
 
50
        return &SNS{auth, region, 0}
 
51
}
 
52
 
 
53
type Message struct {
 
54
        SNS     *SNS
 
55
        Topic   *Topic
 
56
        Message [8192]byte
 
57
        Subject string
 
58
}
 
59
 
 
60
type Subscription struct {
 
61
        Endpoint        string
 
62
        Owner           string
 
63
        Protocol        string
 
64
        SubscriptionArn string
 
65
        TopicArn        string
 
66
}
 
67
 
 
68
func (topic *Topic) Message(message [8192]byte, subject string) *Message {
 
69
        return &Message{topic.SNS, topic, message, subject}
 
70
}
 
71
 
 
72
type ResponseMetadata struct {
 
73
        RequestId string  `xml:"ResponseMetadata>RequestId"`
 
74
        BoxUsage  float64 `xml:"ResponseMetadata>BoxUsage"`
 
75
}
 
76
 
 
77
type ListTopicsResp struct {
 
78
        Topics    []Topic `xml:"ListTopicsResult>Topics>member"`
 
79
        NextToken string
 
80
        ResponseMetadata
 
81
}
 
82
 
 
83
type CreateTopicResp struct {
 
84
        Topic Topic `xml:"CreateTopicResult"`
 
85
        ResponseMetadata
 
86
}
 
87
 
 
88
type DeleteTopicResp struct {
 
89
        ResponseMetadata
 
90
}
 
91
 
 
92
type ListSubscriptionsResp struct {
 
93
        Subscriptions []Subscription `xml:"ListSubscriptionsResult>Subscriptions>member"`
 
94
        NextToken     string
 
95
        ResponseMetadata
 
96
}
 
97
 
 
98
type AttributeEntry struct {
 
99
        Key   string `xml:"key"`
 
100
        Value string `xml:"value"`
 
101
}
 
102
 
 
103
type GetTopicAttributesResp struct {
 
104
        Attributes []AttributeEntry `xml:"GetTopicAttributesResult>Attributes>entry"`
 
105
        ResponseMetadata
 
106
}
 
107
 
 
108
func makeParams(action string) map[string]string {
 
109
        params := make(map[string]string)
 
110
        params["Action"] = action
 
111
        return params
 
112
}
 
113
 
 
114
// ListTopics
 
115
//
 
116
// See http://goo.gl/lfrMK for more details.
 
117
func (sns *SNS) ListTopics(NextToken *string) (resp *ListTopicsResp, err error) {
 
118
        resp = &ListTopicsResp{}
 
119
        params := makeParams("ListTopics")
 
120
        if NextToken != nil {
 
121
                params["NextToken"] = *NextToken
 
122
        }
 
123
        err = sns.query(nil, nil, params, resp)
 
124
        return
 
125
}
 
126
 
 
127
// CreateTopic
 
128
//
 
129
// See http://goo.gl/m9aAt for more details.
 
130
func (sns *SNS) CreateTopic(Name string) (resp *CreateTopicResp, err error) {
 
131
        resp = &CreateTopicResp{}
 
132
        params := makeParams("CreateTopic")
 
133
        params["Name"] = Name
 
134
        err = sns.query(nil, nil, params, resp)
 
135
        return
 
136
}
 
137
 
 
138
// DeleteTopic
 
139
//
 
140
// See http://goo.gl/OXNcY for more details.
 
141
func (sns *SNS) DeleteTopic(topic Topic) (resp *DeleteTopicResp, err error) {
 
142
        resp = &DeleteTopicResp{}
 
143
        params := makeParams("DeleteTopic")
 
144
        params["TopicArn"] = topic.TopicArn
 
145
        err = sns.query(nil, nil, params, resp)
 
146
        return
 
147
}
 
148
 
 
149
// Delete
 
150
//
 
151
// Helper function for deleting a topic
 
152
func (topic *Topic) Delete() (resp *DeleteTopicResp, err error) {
 
153
        return topic.SNS.DeleteTopic(*topic)
 
154
}
 
155
 
 
156
// ListSubscriptions
 
157
//
 
158
// See http://goo.gl/k3aGn for more details.
 
159
func (sns *SNS) ListSubscriptions(NextToken *string) (resp *ListSubscriptionsResp, err error) {
 
160
        resp = &ListSubscriptionsResp{}
 
161
        params := makeParams("ListSubscriptions")
 
162
        if NextToken != nil {
 
163
                params["NextToken"] = *NextToken
 
164
        }
 
165
        err = sns.query(nil, nil, params, resp)
 
166
        return
 
167
}
 
168
 
 
169
// GetTopicAttributes
 
170
//
 
171
// See http://goo.gl/WXRoX for more details.
 
172
func (sns *SNS) GetTopicAttributes(TopicArn string) (resp *GetTopicAttributesResp, err error) {
 
173
        resp = &GetTopicAttributesResp{}
 
174
        params := makeParams("GetTopicAttributes")
 
175
        params["TopicArn"] = TopicArn
 
176
        err = sns.query(nil, nil, params, resp)
 
177
        return
 
178
}
 
179
 
 
180
type PublishOpt struct {
 
181
        Message          string
 
182
        MessageStructure string
 
183
        Subject          string
 
184
        TopicArn         string
 
185
}
 
186
 
 
187
type PublishResp struct {
 
188
        MessageId string `xml:"PublishResult>MessageId"`
 
189
        ResponseMetadata
 
190
}
 
191
 
 
192
// Publish
 
193
//
 
194
// See http://goo.gl/AY2D8 for more details.
 
195
func (sns *SNS) Publish(options *PublishOpt) (resp *PublishResp, err error) {
 
196
        resp = &PublishResp{}
 
197
        params := makeParams("Publish")
 
198
 
 
199
        if options.Subject != "" {
 
200
                params["Subject"] = options.Subject
 
201
        }
 
202
 
 
203
        if options.MessageStructure != "" {
 
204
                params["MessageStructure"] = options.MessageStructure
 
205
        }
 
206
 
 
207
        if options.Message != "" {
 
208
                params["Message"] = options.Message
 
209
        }
 
210
 
 
211
        if options.TopicArn != "" {
 
212
                params["TopicArn"] = options.TopicArn
 
213
        }
 
214
 
 
215
        err = sns.query(nil, nil, params, resp)
 
216
        return
 
217
}
 
218
 
 
219
type SetTopicAttributesResponse struct {
 
220
        ResponseMetadata
 
221
}
 
222
 
 
223
// SetTopicAttributes
 
224
//
 
225
// See http://goo.gl/oVYW7 for more details.
 
226
func (sns *SNS) SetTopicAttributes(AttributeName, AttributeValue, TopicArn string) (resp *SetTopicAttributesResponse, err error) {
 
227
        resp = &SetTopicAttributesResponse{}
 
228
        params := makeParams("SetTopicAttributes")
 
229
 
 
230
        if AttributeName == "" || TopicArn == "" {
 
231
                return nil, errors.New("Invalid Attribute Name or TopicArn")
 
232
        }
 
233
 
 
234
        params["AttributeName"] = AttributeName
 
235
        params["AttributeValue"] = AttributeValue
 
236
        params["TopicArn"] = TopicArn
 
237
 
 
238
        err = sns.query(nil, nil, params, resp)
 
239
        return
 
240
}
 
241
 
 
242
type SubscribeResponse struct {
 
243
        SubscriptionArn string `xml:"SubscribeResult>SubscriptionArn"`
 
244
        ResponseMetadata
 
245
}
 
246
 
 
247
// Subscribe
 
248
//
 
249
// See http://goo.gl/c3iGS for more details.
 
250
func (sns *SNS) Subscribe(Endpoint, Protocol, TopicArn string) (resp *SubscribeResponse, err error) {
 
251
        resp = &SubscribeResponse{}
 
252
        params := makeParams("Subscribe")
 
253
 
 
254
        params["Endpoint"] = Endpoint
 
255
        params["Protocol"] = Protocol
 
256
        params["TopicArn"] = TopicArn
 
257
 
 
258
        err = sns.query(nil, nil, params, resp)
 
259
        return
 
260
}
 
261
 
 
262
type UnsubscribeResponse struct {
 
263
        ResponseMetadata
 
264
}
 
265
 
 
266
// Unsubscribe
 
267
//
 
268
// See http://goo.gl/4l5Ge for more details.
 
269
func (sns *SNS) Unsubscribe(SubscriptionArn string) (resp *UnsubscribeResponse, err error) {
 
270
        resp = &UnsubscribeResponse{}
 
271
        params := makeParams("Unsubscribe")
 
272
 
 
273
        params["SubscriptionArn"] = SubscriptionArn
 
274
 
 
275
        err = sns.query(nil, nil, params, resp)
 
276
        return
 
277
}
 
278
 
 
279
type ConfirmSubscriptionResponse struct {
 
280
        SubscriptionArn string `xml:"ConfirmSubscriptionResult>SubscriptionArn"`
 
281
        ResponseMetadata
 
282
}
 
283
 
 
284
type ConfirmSubscriptionOpt struct {
 
285
        AuthenticateOnUnsubscribe string
 
286
        Token                     string
 
287
        TopicArn                  string
 
288
}
 
289
 
 
290
// ConfirmSubscription
 
291
//
 
292
// See http://goo.gl/3hXzH for more details.
 
293
func (sns *SNS) ConfirmSubscription(options *ConfirmSubscriptionOpt) (resp *ConfirmSubscriptionResponse, err error) {
 
294
        resp = &ConfirmSubscriptionResponse{}
 
295
        params := makeParams("ConfirmSubscription")
 
296
 
 
297
        if options.AuthenticateOnUnsubscribe != "" {
 
298
                params["AuthenticateOnUnsubscribe"] = options.AuthenticateOnUnsubscribe
 
299
        }
 
300
 
 
301
        params["Token"] = options.Token
 
302
        params["TopicArn"] = options.TopicArn
 
303
 
 
304
        err = sns.query(nil, nil, params, resp)
 
305
        return
 
306
}
 
307
 
 
308
type Permission struct {
 
309
        ActionName string
 
310
        AccountId  string
 
311
}
 
312
 
 
313
type AddPermissionResponse struct {
 
314
        ResponseMetadata
 
315
}
 
316
 
 
317
// AddPermission
 
318
//
 
319
// See http://goo.gl/mbY4a for more details.
 
320
func (sns *SNS) AddPermission(permissions []Permission, Label, TopicArn string) (resp *AddPermissionResponse, err error) {
 
321
        resp = &AddPermissionResponse{}
 
322
        params := makeParams("AddPermission")
 
323
 
 
324
        for i, p := range permissions {
 
325
                params["AWSAccountId.member."+strconv.Itoa(i+1)] = p.AccountId
 
326
                params["ActionName.member."+strconv.Itoa(i+1)] = p.ActionName
 
327
        }
 
328
 
 
329
        params["Label"] = Label
 
330
        params["TopicArn"] = TopicArn
 
331
 
 
332
        err = sns.query(nil, nil, params, resp)
 
333
        return
 
334
}
 
335
 
 
336
type RemovePermissionResponse struct {
 
337
        ResponseMetadata
 
338
}
 
339
 
 
340
// RemovePermission
 
341
//
 
342
// See http://goo.gl/wGl5j for more details.
 
343
func (sns *SNS) RemovePermission(Label, TopicArn string) (resp *RemovePermissionResponse, err error) {
 
344
        resp = &RemovePermissionResponse{}
 
345
        params := makeParams("RemovePermission")
 
346
 
 
347
        params["Label"] = Label
 
348
        params["TopicArn"] = TopicArn
 
349
 
 
350
        err = sns.query(nil, nil, params, resp)
 
351
        return
 
352
}
 
353
 
 
354
type ListSubscriptionByTopicResponse struct {
 
355
        Subscriptions []Subscription `xml:"ListSubscriptionsByTopicResult>Subscriptions>member"`
 
356
        ResponseMetadata
 
357
}
 
358
 
 
359
type ListSubscriptionByTopicOpt struct {
 
360
        NextToken string
 
361
        TopicArn  string
 
362
}
 
363
 
 
364
// ListSubscriptionByTopic
 
365
//
 
366
// See http://goo.gl/LaVcC for more details.
 
367
func (sns *SNS) ListSubscriptionByTopic(options *ListSubscriptionByTopicOpt) (resp *ListSubscriptionByTopicResponse, err error) {
 
368
        resp = &ListSubscriptionByTopicResponse{}
 
369
        params := makeParams("ListSbubscriptionByTopic")
 
370
 
 
371
        if options.NextToken != "" {
 
372
                params["NextToken"] = options.NextToken
 
373
        }
 
374
 
 
375
        params["TopicArn"] = options.TopicArn
 
376
 
 
377
        err = sns.query(nil, nil, params, resp)
 
378
        return
 
379
}
 
380
 
 
381
type Error struct {
 
382
        StatusCode int
 
383
        Code       string
 
384
        Message    string
 
385
        RequestId  string
 
386
}
 
387
 
 
388
func (err *Error) Error() string {
 
389
        return err.Message
 
390
}
 
391
 
 
392
type xmlErrors struct {
 
393
        RequestId string
 
394
        Errors    []Error `xml:"Errors>Error"`
 
395
}
 
396
 
 
397
func (sns *SNS) query(topic *Topic, message *Message, params map[string]string, resp interface{}) error {
 
398
        params["Timestamp"] = time.Now().UTC().Format(time.RFC3339)
 
399
        u, err := url.Parse(sns.Region.SNSEndpoint)
 
400
        if err != nil {
 
401
                return err
 
402
        }
 
403
 
 
404
        sign(sns.Auth, "GET", "/", params, u.Host)
 
405
        u.RawQuery = multimap(params).Encode()
 
406
        r, err := http.Get(u.String())
 
407
        if err != nil {
 
408
                return err
 
409
        }
 
410
        defer r.Body.Close()
 
411
 
 
412
        //dump, _ := http.DumpResponse(r, true)
 
413
        //println("DUMP:\n", string(dump))
 
414
        //return nil
 
415
 
 
416
        if r.StatusCode != 200 {
 
417
                return buildError(r)
 
418
        }
 
419
        err = xml.NewDecoder(r.Body).Decode(resp)
 
420
        return err
 
421
}
 
422
 
 
423
func buildError(r *http.Response) error {
 
424
        errors := xmlErrors{}
 
425
        xml.NewDecoder(r.Body).Decode(&errors)
 
426
        var err Error
 
427
        if len(errors.Errors) > 0 {
 
428
                err = errors.Errors[0]
 
429
        }
 
430
        err.RequestId = errors.RequestId
 
431
        err.StatusCode = r.StatusCode
 
432
        if err.Message == "" {
 
433
                err.Message = r.Status
 
434
        }
 
435
        return &err
 
436
}
 
437
 
 
438
func multimap(p map[string]string) url.Values {
 
439
        q := make(url.Values, len(p))
 
440
        for k, v := range p {
 
441
                q[k] = []string{v}
 
442
        }
 
443
        return q
 
444
}