dustMason-right_aws 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. data/History.txt +305 -0
  2. data/Manifest.txt +60 -0
  3. data/README.txt +165 -0
  4. data/Rakefile +112 -0
  5. data/lib/acf/right_acf_interface.rb +549 -0
  6. data/lib/acf/right_acf_invalidations.rb +144 -0
  7. data/lib/acf/right_acf_origin_access_identities.rb +230 -0
  8. data/lib/acf/right_acf_streaming_interface.rb +229 -0
  9. data/lib/acw/right_acw_interface.rb +248 -0
  10. data/lib/as/right_as_interface.rb +698 -0
  11. data/lib/awsbase/benchmark_fix.rb +39 -0
  12. data/lib/awsbase/right_awsbase.rb +1174 -0
  13. data/lib/awsbase/support.rb +35 -0
  14. data/lib/awsbase/version.rb +9 -0
  15. data/lib/ec2/right_ec2.rb +458 -0
  16. data/lib/ec2/right_ec2_ebs.rb +465 -0
  17. data/lib/ec2/right_ec2_images.rb +413 -0
  18. data/lib/ec2/right_ec2_instances.rb +785 -0
  19. data/lib/ec2/right_ec2_monitoring.rb +70 -0
  20. data/lib/ec2/right_ec2_placement_groups.rb +108 -0
  21. data/lib/ec2/right_ec2_reserved_instances.rb +174 -0
  22. data/lib/ec2/right_ec2_security_groups.rb +396 -0
  23. data/lib/ec2/right_ec2_spot_instances.rb +425 -0
  24. data/lib/ec2/right_ec2_tags.rb +139 -0
  25. data/lib/ec2/right_ec2_vpc.rb +583 -0
  26. data/lib/ec2/right_ec2_windows_mobility.rb +84 -0
  27. data/lib/elb/right_elb_interface.rb +571 -0
  28. data/lib/iam/right_iam_access_keys.rb +71 -0
  29. data/lib/iam/right_iam_groups.rb +195 -0
  30. data/lib/iam/right_iam_interface.rb +341 -0
  31. data/lib/iam/right_iam_mfa_devices.rb +67 -0
  32. data/lib/iam/right_iam_users.rb +251 -0
  33. data/lib/rds/right_rds_interface.rb +1309 -0
  34. data/lib/right_aws.rb +88 -0
  35. data/lib/route_53/right_route_53_interface.rb +630 -0
  36. data/lib/s3/right_s3.rb +1123 -0
  37. data/lib/s3/right_s3_interface.rb +1198 -0
  38. data/lib/sdb/active_sdb.rb +1107 -0
  39. data/lib/sdb/right_sdb_interface.rb +753 -0
  40. data/lib/sns/right_sns.rb +205 -0
  41. data/lib/sns/right_sns_interface.rb +343 -0
  42. data/lib/sqs/right_sqs.rb +387 -0
  43. data/lib/sqs/right_sqs_gen2.rb +342 -0
  44. data/lib/sqs/right_sqs_gen2_interface.rb +523 -0
  45. data/lib/sqs/right_sqs_interface.rb +593 -0
  46. data/right_aws.gemspec +91 -0
  47. data/test/acf/test_helper.rb +2 -0
  48. data/test/acf/test_right_acf.rb +138 -0
  49. data/test/awsbase/test_helper.rb +2 -0
  50. data/test/awsbase/test_right_awsbase.rb +12 -0
  51. data/test/ec2/test_helper.rb +2 -0
  52. data/test/ec2/test_right_ec2.rb +108 -0
  53. data/test/http_connection.rb +87 -0
  54. data/test/rds/test_helper.rb +2 -0
  55. data/test/rds/test_right_rds.rb +120 -0
  56. data/test/s3/test_helper.rb +2 -0
  57. data/test/s3/test_right_s3.rb +421 -0
  58. data/test/s3/test_right_s3_stubbed.rb +97 -0
  59. data/test/sdb/test_active_sdb.rb +357 -0
  60. data/test/sdb/test_batch_put_attributes.rb +54 -0
  61. data/test/sdb/test_helper.rb +3 -0
  62. data/test/sdb/test_right_sdb.rb +253 -0
  63. data/test/sns/test_helper.rb +2 -0
  64. data/test/sns/test_right_sns.rb +73 -0
  65. data/test/sqs/test_helper.rb +2 -0
  66. data/test/sqs/test_right_sqs.rb +285 -0
  67. data/test/sqs/test_right_sqs_gen2.rb +264 -0
  68. data/test/test_credentials.rb +37 -0
  69. data/test/ts_right_aws.rb +14 -0
  70. metadata +244 -0
@@ -0,0 +1,205 @@
1
+ #
2
+ # Copyright (c) 2007-2008 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ module RightAws
25
+
26
+ #
27
+ # = RightAws::Sns -- RightScale's Amazon SNS interface
28
+ # The RightAws::Sns class provides a complete interface to Amazon's Simple
29
+ # Notification Service.
30
+ # For explanations of the semantics
31
+ # of each call, please refer to Amazon's documentation at
32
+ # http://docs.amazonwebservices.com/sns/2010-03-31/api/
33
+ #
34
+ # Error handling: all operations raise an RightAws::AwsError in case
35
+ # of problems. Note that transient errors are automatically retried.
36
+ #
37
+ # sns = RightAws::Sns.new(aws_access_key_id, aws_secret_access_key)
38
+ # topics = sns.topics #=> [<Sns::Topic>, <Sns::Topic>]
39
+ # topic1 = sns.create_topic('bananas') #=> <Sns::Topic>
40
+ # topic1.subscribe('email', 'john@example.com') #=> true
41
+ # ...
42
+ # topic1.send_message('Some content', 'An optional subject')
43
+ #
44
+ # Params is a hash:
45
+ #
46
+ # {:server => 'sns.us-east-1.amazonaws.com' # Amazon service host: 'sns.us-east-1.amazonaws.com' (default)
47
+ # :port => 443 # Amazon service port: 80 or 443 (default)
48
+ # :multi_thread => true|false # Multi-threaded (connection per each thread): true or false (default)
49
+ # :signature_version => '0' # The signature version : '0' or '1'(default)
50
+ # :logger => Logger Object} # Logger instance: logs to STDOUT if omitted }
51
+ #
52
+ class Sns
53
+ attr_reader :interface
54
+
55
+ def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
56
+ @interface = SnsInterface.new(aws_access_key_id, aws_secret_access_key, params)
57
+ end
58
+
59
+ # Retrieves a list of topics.
60
+ # Returns an +array+ of +Topic+ instances.
61
+ #
62
+ # RightAws::Sns.topics #=> array of topics
63
+ #
64
+ def topics
65
+ @interface.list_topics.map do |arn|
66
+ Topic.new(self, arn)
67
+ end
68
+ end
69
+
70
+ # Returns Topic instance by ARN.
71
+ def topic(arn)
72
+ Topic.new(self, arn)
73
+ end
74
+
75
+ # Creates a new topic.
76
+ def create_topic(name)
77
+ @interface.create_topic(self, name)
78
+ end
79
+
80
+ class Topic
81
+ attr_reader :arn, :sns
82
+
83
+ # Creates new Topic instance.
84
+ # Does not create a topic at Amazon.
85
+ #
86
+ # topic = RightAws::Sns::Topic.new(sns, 'arn%3Aaws%3Asns%3Aus-east-1%3A123456789012%3AMy-Topic')
87
+ #
88
+ def initialize(sns, arn)
89
+ @sns = sns
90
+ @arn = arn
91
+ end
92
+
93
+ # Deletes queue.
94
+ # Queue must be empty or +force+ must be set to +true+.
95
+ # Returns +true+.
96
+ #
97
+ # queue.delete(true) #=> true
98
+ #
99
+ def delete
100
+ @sns.interface.delete_topic(arn)
101
+ end
102
+ alias_method :destroy, :delete
103
+
104
+ # Sends new message to topic.
105
+ # Returns new Message instance that has been sent to topic.
106
+ def send_message(body, subject = nil)
107
+ @sns.interface.send_message(arn, body, subject)
108
+ end
109
+ alias_method :push, :send_message
110
+
111
+ # Returns the AWS account ID of the topic's owner
112
+ def owner
113
+ topic_attributes['Owner']
114
+ end
115
+
116
+ # Returns the JSON serialization of the topic's access control policy
117
+ def policy
118
+ unless !topic_attributes['Policy'] || topic_attributes['Policy'].length == 0
119
+ JSON.parse(topic_attributes['Policy'])
120
+ end
121
+ end
122
+
123
+ # Returns the human-readable name used in the "From" field for
124
+ # notifications to email and email-json endpoints
125
+ def display_name
126
+ topic_attributes['DisplayName']
127
+ end
128
+
129
+ # Sets the display name
130
+ def display_name=(value)
131
+ set_topic_attribute('DisplayName', value)
132
+ end
133
+
134
+ # Returns a hash in the format:
135
+ # { :set => [<Sns::Member>, <Sns::Member>, <Sns::Member>], :next => '123' }
136
+ #
137
+ # Accepts an optional next_token telling where to start from
138
+ def subscriptions(next_token = nil)
139
+ @sns.interface.list_subscriptions_by_topic(arn, next_token)
140
+ end
141
+
142
+ # Returns a <Member> object
143
+ def subscribe(protocol, end_point)
144
+ raise StandardError, "Protocol (#{protocol}) is not valid" unless ['http', 'https', 'email', 'email-json', 'sqs']
145
+ @sns.interface.subscribe_to_topic(arn, protocol, end_point)
146
+ end
147
+
148
+ # Gives another AWS account holder access to set actions within your account
149
+ def add_permission(label, account_ids, actions)
150
+ account_ids = [account_ids.to_s] unless account_ids.kind_of?(Array)
151
+ actions = [actions.to_s] unless actions.kind_of?(Array)
152
+ @sns.interface.add_permissions(arn, label, account_ids, actions)
153
+ end
154
+
155
+ # Removes permission from another AWS account holder
156
+ def remove_permission(label)
157
+ @sns.interface.remove_permissions(arn, label)
158
+ end
159
+
160
+ # Confirms a subscription (if you don't have the <Sns::Member> object)
161
+ def confirm_subscription(token, authenticate_on_unsubscribe = false)
162
+ member = Member.new
163
+ member.sns_interface = @sns.interface
164
+ member.topic_arn = arn
165
+ member.token = token
166
+
167
+ member.confirm(authenticate_on_unsubscribe)
168
+ end
169
+
170
+ private
171
+ def set_topic_attribute(name, value)
172
+ if @sns.interface.set_topic_attributes(arn, name, value)
173
+ @topic_attributes ||= {}
174
+ @topic_attributes[name] = value
175
+ end
176
+ end
177
+
178
+ def topic_attributes
179
+ @topic_attributes ||= @sns.interface.get_topic_attributes(arn)
180
+ end
181
+ end
182
+
183
+
184
+ class Message
185
+ attr_reader :topic, :id, :body, :subject
186
+
187
+ def initialize(topic, id = nil, body = nil, subject = nil)
188
+ @topic = topic
189
+ @id = id
190
+ @body = body
191
+ @subject = subject
192
+ end
193
+ end
194
+
195
+ class Member
196
+ attr_accessor :sns_interface, :topic_arn, :token
197
+
198
+ def confirm(authenticate_on_unsubscribe = false)
199
+ sns_interface.confirm_subscription(topic_arn, token, authenticate_on_unsubscribe)
200
+ end
201
+ end
202
+
203
+ end
204
+
205
+ end
@@ -0,0 +1,343 @@
1
+ #
2
+ # Copyright (c) 2007-2008 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ module RightAws
25
+
26
+ #
27
+ # Right::Aws::SnsInterface - RightScale's low-level Amazon SNS interface
28
+ #
29
+
30
+ class SnsInterface < RightAwsBase
31
+ include RightAwsBaseInterface
32
+
33
+ API_VERSION = "2010-03-31"
34
+ DEFAULT_HOST = "sns.us-east-1.amazonaws.com"
35
+ DEFAULT_PORT = 443
36
+ DEFAULT_PROTOCOL = 'https'
37
+ REQUEST_TTL = 30
38
+ DEFAULT_VISIBILITY_TIMEOUT = 30
39
+
40
+
41
+ @@bench = AwsBenchmarkingBlock.new
42
+ def self.bench_xml
43
+ @@bench.xml
44
+ end
45
+ def self.bench_sns
46
+ @@bench.service
47
+ end
48
+
49
+ @@api = API_VERSION
50
+ def self.api
51
+ @@api
52
+ end
53
+
54
+ # Creates a new SnsInterface instance. This instance is limited to
55
+ # operations on SNS objects created with Amazon's 2008-01-01 API version. This
56
+ # interface will not work on objects created with prior API versions. See
57
+ # Amazon's article "Migrating to Amazon SNS API version 2008-01-01" at:
58
+ # http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1148
59
+ #
60
+ # sqs = RightAws::SnsInterface.new('1E3GDYEOGFJPIT75KDT40','hgTHt68JY07JKUY08ftHYtERkjgtfERn57DFE379', {:multi_thread => true, :logger => Logger.new('/tmp/x.log')})
61
+ #
62
+ # Params is a hash:
63
+ #
64
+ # {:server => 'sns.us-east-1.amazonaws.com' # Amazon service host: 'sns.us-east-1.amazonaws.com' (default)
65
+ # :port => 443 # Amazon service port: 80 or 443 (default)
66
+ # :multi_thread => true|false # Multi-threaded (connection per each thread): true or false (default)
67
+ # :signature_version => '0' # The signature version : '0', '1' or '2'(default)
68
+ # :logger => Logger Object} # Logger instance: logs to STDOUT if omitted }
69
+ #
70
+ def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
71
+ init({ :name => 'SNS',
72
+ :default_host => ENV['SNS_URL'] ? URI.parse(ENV['SNS_URL']).host : DEFAULT_HOST,
73
+ :default_port => ENV['SNS_URL'] ? URI.parse(ENV['SNS_URL']).port : DEFAULT_PORT,
74
+ :default_protocol => ENV['SNS_URL'] ? URI.parse(ENV['SNS_URL']).scheme : DEFAULT_PROTOCOL },
75
+ aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'],
76
+ aws_secret_access_key || ENV['AWS_SECRET_ACCESS_KEY'],
77
+ params)
78
+ end
79
+
80
+
81
+ #-----------------------------------------------------------------
82
+ # Requests
83
+ #-----------------------------------------------------------------
84
+
85
+ # Generates a request hash for the query API
86
+ def generate_request(action, param={}) # :nodoc:
87
+ # For operation requests on a topic, the queue URI will be a parameter,
88
+ # so we first extract it from the call parameters. Next we remove any
89
+ # parameters with no value or with symbolic keys. We add the header
90
+ # fields required in all requests, and then the headers passed in as
91
+ # params. We sort the header fields alphabetically and then generate the
92
+ # signature before URL escaping the resulting query and sending it.
93
+ service = param[:queue_url] ? URI(param[:queue_url]).path : '/'
94
+ param.each{ |key, value| param.delete(key) if (value.nil? || key.is_a?(Symbol)) }
95
+ service_hash = { "Action" => action,
96
+ "Expires" => (Time.now + REQUEST_TTL).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
97
+ "AWSAccessKeyId" => @aws_access_key_id,
98
+ "Version" => API_VERSION }
99
+ service_hash.update(param)
100
+ service_params = signed_service_params(@aws_secret_access_key, service_hash, :get, @params[:server], service)
101
+ request = Net::HTTP::Get.new("#{AwsUtils.URLencode(service)}?#{service_params}")
102
+ # prepare output hash
103
+ { :request => request,
104
+ :server => @params[:server],
105
+ :port => @params[:port],
106
+ :protocol => @params[:protocol] }
107
+ end
108
+
109
+ def generate_post_request(action, param={}) # :nodoc:
110
+ service = param[:queue_url] ? URI(param[:queue_url]).path : '/'
111
+ message = param[:message] # extract message body if nesessary
112
+ param.each{ |key, value| param.delete(key) if (value.nil? || key.is_a?(Symbol)) }
113
+ service_hash = { "Action" => action,
114
+ "Expires" => (Time.now + REQUEST_TTL).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
115
+ "AWSAccessKeyId" => @aws_access_key_id,
116
+ "MessageBody" => message,
117
+ "Version" => API_VERSION }
118
+ service_hash.update(param)
119
+ #
120
+ service_params = signed_service_params(@aws_secret_access_key, service_hash, :post, @params[:server], service)
121
+ request = Net::HTTP::Post.new(AwsUtils::URLencode(service))
122
+ request['Content-Type'] = 'application/x-www-form-urlencoded'
123
+ request.body = service_params
124
+ # prepare output hash
125
+ { :request => request,
126
+ :server => @params[:server],
127
+ :port => @params[:port],
128
+ :protocol => @params[:protocol] }
129
+ end
130
+
131
+
132
+ # Sends request to Amazon and parses the response
133
+ # Raises AwsError if any banana happened
134
+ def request_info(request, parser) # :nodoc:
135
+ request_info_impl(:sqs_connection, @@bench, request, parser)
136
+ end
137
+
138
+ # Creates a new topic, returning the new Topic object.
139
+ #
140
+ # sqs.create_topic('my_awesome_queue') #=> 'https://queue.amazonaws.com/ZZ7XXXYYYBINS/my_awesome_queue'
141
+ #
142
+ def create_topic(sns, topic_name)
143
+ req_hash = generate_request('CreateTopic', 'Name' => topic_name)
144
+ arn = request_info(req_hash, SnsCreateTopicParser.new(:logger => @logger))
145
+ Sns::Topic.new(sns, arn)
146
+ rescue
147
+ on_exception
148
+ end
149
+
150
+ # Lists all topics owned by this user
151
+ # Topic creation is an eventual operation and created topics may not show up in immediately subsequent list_topic calls.
152
+ #
153
+ # sns.list_queues() #=> ['ZZ7XXXYYYBINS','ZZ7XXXYYYBINS']
154
+ #
155
+ def list_topics
156
+ req_hash = generate_request('ListTopics')
157
+ request_info(req_hash, SnsListTopicsParser.new(:logger => @logger))
158
+ rescue
159
+ on_exception
160
+ end
161
+
162
+ # Deletes topic. Any messages in the topic are permanently lost.
163
+ # Returns +true+ or an exception.
164
+ # Deletion is eventual.
165
+ #
166
+ # sqs.delete_queue('arn:aws:sns:us-east-1:464646271962:test') #=> true
167
+ #
168
+ def delete_topic(topic_arn)
169
+ req_hash = generate_request('DeleteTopic', 'TopicArn' => topic_arn)
170
+ request_info(req_hash, SnsStatusParser.new(:logger => @logger))
171
+ rescue
172
+ on_exception
173
+ end
174
+
175
+ # Sends a new message to a topic. Body size is limited to 8 KB.
176
+ # If successful, this call returns true
177
+ #
178
+ # sns.send_message('arn:aws:sns:us-east-1:464646271962:test', 'body', 'message 1') #=> true
179
+ #
180
+ # On failure, send_message raises an exception.
181
+ #
182
+ def send_message(topic_arn, body, subject = nil)
183
+ params = { 'TopicArn' => topic_arn, 'Message' => body }
184
+ params.merge!({ 'Subject' => subject }) unless !subject || subject.length == 0
185
+ req_hash = generate_post_request('Publish', params)
186
+ request_info(req_hash, SnsStatusParser.new(:logger => @logger))
187
+ rescue
188
+ on_exception
189
+ end
190
+
191
+ # Same as send_message
192
+ alias_method :push_message, :send_message
193
+
194
+ # Retrieves the topic attribute(s). Returns a hash of attribute(s) or an exception.
195
+ def get_topic_attributes(topic_arn)
196
+ req_hash = generate_request('GetTopicAttributes', 'TopicArn' => topic_arn)
197
+ request_info(req_hash, SnsGetTopicAttributesParser.new(:logger => @logger))
198
+ rescue
199
+ on_exception
200
+ end
201
+
202
+ # Retrieves the topic subscribers(s). Returns a hash containing a :set of members and the :next token
203
+ def list_subscriptions_by_topic(topic_arn, next_token = nil)
204
+ params = { 'TopicArn' => topic_arn }
205
+ params.merge!({ 'NextToken' => next_token }) unless !next_token
206
+ req_hash = generate_request('ListSubscriptionsByTopic', params)
207
+ request_info(req_hash, SnsListSubscriptionsByTopicParser.new(:logger => @logger))
208
+ rescue
209
+ on_exception
210
+ end
211
+
212
+ # Subscribe a new endpoint to a topic
213
+ def subscribe_to_topic(topic_arn, protocol, end_point)
214
+ req_hash = generate_request('Subscribe', 'TopicArn' => topic_arn, 'Protocol' => protocol, 'Endpoint' => end_point)
215
+ token = request_info(req_hash, SnsSubscribeParser.new(:logger => @logger))
216
+ if token == 'pending confirmation'
217
+ true
218
+ else
219
+ member = Sns::Member.new
220
+ member.topic_arn = topic_arn
221
+ member.token = token
222
+ member.sns_interface = self
223
+ member
224
+ end
225
+ end
226
+
227
+ # Add permissions to a topic.
228
+ #
229
+ # sns.add_permissions('arn:aws:sns:us-east-1:464646271962:test',
230
+ # 'testLabel', ['125074342641','125074342642'],
231
+ # ['Publish','Subscribe']) #=> true
232
+ #
233
+ # +permissions+ is a hash of: AccountId => ActionName
234
+ # (valid ActionNames: * | Publish | Subscribe | Unsubscribe | GetTopicAttributes | SetTopicAttributes | ConfirmSubscription )
235
+ def add_permissions(topic_arn, label, grantees, actions)
236
+ params = {}
237
+ # add each member
238
+ grantees.each_with_index { |awsid,i| params.merge!("AWSAccountId.member.#{i + 1}" => awsid) }
239
+ # add each action
240
+ actions.each_with_index { |action,i| params.merge!("ActionName.member.#{i + 1}" => action) }
241
+ # standard params
242
+ params.merge!('Label' => label,
243
+ 'TopicArn' => topic_arn )
244
+ req_hash = generate_request('AddPermission', params)
245
+ request_info(req_hash, SnsStatusParser.new(:logger => @logger))
246
+ rescue
247
+ on_exception
248
+ end
249
+
250
+ # Revoke any permissions in the topic policy that matches the +label+ parameter.
251
+ #
252
+ # sns.remove_permissions('arn:aws:sns:us-east-1:464646271962:test',
253
+ # 'testLabel') # => true
254
+ #
255
+ def remove_permissions(topic_arn, label)
256
+ req_hash = generate_request('RemovePermission',
257
+ 'Label' => label,
258
+ 'TopicArn' => topic_arn )
259
+ request_info(req_hash, SnsStatusParser.new(:logger => @logger))
260
+ rescue
261
+ on_exception
262
+ end
263
+
264
+ # Sets a topic attribute. Returns +true+ or an exception.
265
+ #
266
+ # sns.set_queue_attributes('arn:aws:sns:us-east-1:464646271962:test', "DisplayName", "Wendy's Widgets") #=> true
267
+ #
268
+ def set_topic_attributes(topic_arn, attribute, value)
269
+ req_hash = generate_request('SetTopicAttributes',
270
+ 'AttributeName' => attribute,
271
+ 'AttributeValue' => value,
272
+ 'TopicArn' => topic_arn)
273
+ request_info(req_hash, SnsStatusParser.new(:logger => @logger))
274
+ rescue
275
+ on_exception
276
+ end
277
+
278
+ #-----------------------------------------------------------------
279
+ # PARSERS: Status Response Parser
280
+ #-----------------------------------------------------------------
281
+
282
+ class SnsStatusParser < RightAWSParser # :nodoc:
283
+ def tagend(name)
284
+ if name == 'ResponseMetadata'
285
+ @result = true
286
+ end
287
+ end
288
+ end
289
+
290
+ #-----------------------------------------------------------------
291
+ # PARSERS: Queue
292
+ #-----------------------------------------------------------------
293
+
294
+ class SnsCreateTopicParser < RightAWSParser # :nodoc:
295
+ def tagend(name)
296
+ @result = @text if name == 'TopicArn'
297
+ end
298
+ end
299
+
300
+ class SnsListTopicsParser < RightAWSParser # :nodoc:
301
+ def reset
302
+ @result = []
303
+ end
304
+ def tagend(name)
305
+ @result << @text if name == 'TopicArn'
306
+ end
307
+ end
308
+
309
+ class SnsGetTopicAttributesParser < RightAWSParser # :nodoc:
310
+ def reset
311
+ @result = {}
312
+ end
313
+ def tagend(name)
314
+ case name
315
+ when 'key' then @current_attribute = @text
316
+ when 'value' then @result[@current_attribute] = @text
317
+ end
318
+ end
319
+ end
320
+
321
+ class SnsListSubscriptionsByTopicParser < RightAWSParser # :nodoc:
322
+ def reset
323
+ @result = {}
324
+ end
325
+ def tagend(name)
326
+ case name
327
+ when 'member' then
328
+ @result[:set] ||= []
329
+ @result[:set] << Sns::Member.parse(@text)
330
+ when 'NextToken' then @result[:next] = @text
331
+ end
332
+ end
333
+ end
334
+
335
+ class SnsSubscribeParser < RightAWSParser # :nodoc:
336
+ def tagend(name)
337
+ @result = @text if name == 'SubscriptionArn'
338
+ end
339
+ end
340
+
341
+ end
342
+
343
+ end