aboisvert_aws 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/History.txt +329 -0
  2. data/Manifest.txt +61 -0
  3. data/README.txt +163 -0
  4. data/Rakefile +130 -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 +1343 -0
  13. data/lib/awsbase/support.rb +35 -0
  14. data/lib/awsbase/version.rb +9 -0
  15. data/lib/ec2/right_ec2.rb +541 -0
  16. data/lib/ec2/right_ec2_ebs.rb +481 -0
  17. data/lib/ec2/right_ec2_images.rb +444 -0
  18. data/lib/ec2/right_ec2_instances.rb +788 -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 +184 -0
  22. data/lib/ec2/right_ec2_security_groups.rb +491 -0
  23. data/lib/ec2/right_ec2_spot_instances.rb +422 -0
  24. data/lib/ec2/right_ec2_tags.rb +139 -0
  25. data/lib/ec2/right_ec2_vpc.rb +590 -0
  26. data/lib/ec2/right_ec2_vpc2.rb +381 -0
  27. data/lib/ec2/right_ec2_windows_mobility.rb +84 -0
  28. data/lib/elb/right_elb_interface.rb +573 -0
  29. data/lib/emr/right_emr_interface.rb +727 -0
  30. data/lib/iam/right_iam_access_keys.rb +71 -0
  31. data/lib/iam/right_iam_groups.rb +195 -0
  32. data/lib/iam/right_iam_interface.rb +341 -0
  33. data/lib/iam/right_iam_mfa_devices.rb +67 -0
  34. data/lib/iam/right_iam_users.rb +251 -0
  35. data/lib/rds/right_rds_interface.rb +1384 -0
  36. data/lib/right_aws.rb +86 -0
  37. data/lib/route_53/right_route_53_interface.rb +640 -0
  38. data/lib/s3/right_s3.rb +1138 -0
  39. data/lib/s3/right_s3_interface.rb +1278 -0
  40. data/lib/sdb/active_sdb.rb +1107 -0
  41. data/lib/sdb/right_sdb_interface.rb +762 -0
  42. data/lib/sns/right_sns_interface.rb +286 -0
  43. data/lib/sqs/right_sqs.rb +387 -0
  44. data/lib/sqs/right_sqs_gen2.rb +342 -0
  45. data/lib/sqs/right_sqs_gen2_interface.rb +523 -0
  46. data/lib/sqs/right_sqs_interface.rb +593 -0
  47. data/right_aws.gemspec +90 -0
  48. data/test/README.mdown +39 -0
  49. data/test/acf/test_helper.rb +2 -0
  50. data/test/acf/test_right_acf.rb +138 -0
  51. data/test/awsbase/test_helper.rb +2 -0
  52. data/test/awsbase/test_right_awsbase.rb +11 -0
  53. data/test/ec2/test_helper.rb +2 -0
  54. data/test/ec2/test_right_ec2.rb +107 -0
  55. data/test/elb/test_helper.rb +2 -0
  56. data/test/elb/test_right_elb.rb +43 -0
  57. data/test/http_connection.rb +87 -0
  58. data/test/rds/test_helper.rb +2 -0
  59. data/test/rds/test_right_rds.rb +120 -0
  60. data/test/route_53/fixtures/a_record.xml +18 -0
  61. data/test/route_53/fixtures/alias_record.xml +18 -0
  62. data/test/route_53/test_helper.rb +2 -0
  63. data/test/route_53/test_right_route_53.rb +141 -0
  64. data/test/s3/test_helper.rb +2 -0
  65. data/test/s3/test_right_s3.rb +528 -0
  66. data/test/s3/test_right_s3_stubbed.rb +97 -0
  67. data/test/sdb/test_active_sdb.rb +357 -0
  68. data/test/sdb/test_batch_put_attributes.rb +54 -0
  69. data/test/sdb/test_helper.rb +3 -0
  70. data/test/sdb/test_right_sdb.rb +253 -0
  71. data/test/sns/test_helper.rb +2 -0
  72. data/test/sns/test_right_sns.rb +153 -0
  73. data/test/sqs/test_helper.rb +2 -0
  74. data/test/sqs/test_right_sqs.rb +285 -0
  75. data/test/sqs/test_right_sqs_gen2.rb +264 -0
  76. data/test/test_credentials.rb +37 -0
  77. data/test/ts_right_aws.rb +15 -0
  78. metadata +257 -0
@@ -0,0 +1,286 @@
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
+ class SnsInterface < RightAwsBase
26
+ include RightAwsBaseInterface
27
+
28
+ DEFAULT_HOST = 'sns.us-east-1.amazonaws.com'
29
+ DEFAULT_PORT = 443
30
+ DEFAULT_PROTOCOL = 'https'
31
+ DEFAULT_SERVICE = '/'
32
+ REQUEST_TTL = 30
33
+
34
+ # Apparently boilerplate stuff
35
+ @@bench = AwsBenchmarkingBlock.new
36
+ def self.bench_xml
37
+ @@bench.xml
38
+ end
39
+ def self.bench_service
40
+ @@bench.service
41
+ end
42
+
43
+ def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
44
+ if params[:region]
45
+ server = "sns.#{params[:region]}.amazonaws.com"
46
+ params.delete(:region)
47
+ else
48
+ server = DEFAULT_HOST
49
+ end
50
+ init({ :name => 'SNS',
51
+ :default_host => ENV['SNS_URL'] ? URI.parse(ENV['SNS_URL']).host : server,
52
+ :default_port => ENV['SNS_URL'] ? URI.parse(ENV['SNS_URL']).port : DEFAULT_PORT,
53
+ :default_service => ENV['SNS_URL'] ? URI.parse(ENV['SNS_URL']).path : DEFAULT_SERVICE,
54
+ :default_protocol => ENV['SNS_URL'] ? URI.parse(ENV['SNS_URL']).scheme : DEFAULT_PROTOCOL},
55
+ aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'],
56
+ aws_secret_access_key || ENV['AWS_SECRET_ACCESS_KEY'],
57
+ params)
58
+ end
59
+
60
+ # TODO: RJG - Seems like generate_request and generate_rest_request could be in a sub class?
61
+ # Generates a request hash for the sns API
62
+ def generate_request(action, params={}) # :nodoc:
63
+ # Sometimes we need to use queue uri (delete queue etc)
64
+ # In that case we will use Symbol key: 'param[:queue_url]'
65
+ service = params[:sns_url] ? URI(params[:sns_url]).path : '/'
66
+ # remove unset(=optional) and symbolyc keys
67
+ params.each{ |key, value| params.delete(key) if (value.nil? || key.is_a?(Symbol)) }
68
+ # prepare output hash
69
+ service_hash = { "Action" => action,
70
+ "Expires" => (Time.now + REQUEST_TTL).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
71
+ "AWSAccessKeyId" => @aws_access_key_id }
72
+ #"Version" => API_VERSION }
73
+ service_hash.update(params)
74
+ service_params = signed_service_params(@aws_secret_access_key, service_hash, :get, @params[:server], service)
75
+ request = Net::HTTP::Get.new("#{AwsUtils::URLencode(service)}?#{service_params}")
76
+ # prepare output hash
77
+ { :request => request,
78
+ :server => @params[:server],
79
+ :port => @params[:port],
80
+ :protocol => @params[:protocol] }
81
+ end
82
+
83
+ # Generates a request hash for the REST API
84
+ def generate_rest_request(method, param) # :nodoc:
85
+ sns_uri = param[:sns_url] ? URI(param[:sns_url]).path : '/'
86
+ message = param[:message] # extract message body if nesessary
87
+ # remove unset(=optional) and symbolyc keys
88
+ param.each{ |key, value| param.delete(key) if (value.nil? || key.is_a?(Symbol)) }
89
+ # created request
90
+ param_to_str = param.to_a.collect{|key,val| key.to_s + "=" + CGI::escape(val.to_s) }.join("&")
91
+ param_to_str = "?#{param_to_str}" unless param_to_str.right_blank?
92
+ request = "Net::HTTP::#{method.capitalize}".right_constantize.new("#{sns_uri}#{param_to_str}")
93
+ request.body = message if message
94
+ # set main headers
95
+ request['content-md5'] = ''
96
+ request['Content-Type'] = 'text/plain'
97
+ request['Date'] = Time.now.httpdate
98
+ # generate authorization string
99
+ auth_string = "#{method.upcase}\n#{request['content-md5']}\n#{request['Content-Type']}\n#{request['Date']}\n#{CGI::unescape(sns_uri)}"
100
+ signature = AwsUtils::sign(@aws_secret_access_key, auth_string)
101
+ # set other headers
102
+ request['Authorization'] = "AWS #{@aws_access_key_id}:#{signature}"
103
+ #request['AWS-Version'] = API_VERSION
104
+ # prepare output hash
105
+ { :request => request,
106
+ :server => @params[:server],
107
+ :port => @params[:port],
108
+ :protocol => @params[:protocol] }
109
+ end
110
+
111
+ # Sends request to Amazon and parses the response
112
+ # Raises AwsError if any banana happened
113
+ def request_info(request, parser) # :nodoc:
114
+ request_info_impl(:sns_connection, @@bench, request, parser)
115
+ end
116
+
117
+ def create_topic(topic_name)
118
+ req_hash = generate_request('CreateTopic', 'Name' => topic_name)
119
+ request_info(req_hash, SnsCreateTopicParser.new)
120
+ end
121
+
122
+ def list_topics()
123
+ req_hash = generate_request('ListTopics')
124
+ request_info(req_hash, SnsListTopicsParser.new)
125
+ end
126
+
127
+ def delete_topic(topic_arn)
128
+ req_hash = generate_request('DeleteTopic', 'TopicArn' => topic_arn)
129
+ request_info(req_hash, RightHttp2xxParser.new)
130
+ end
131
+
132
+ def subscribe(topic_arn, protocol, endpoint)
133
+ req_hash = generate_request('Subscribe', 'TopicArn' => topic_arn, 'Protocol' => protocol, 'Endpoint' => endpoint)
134
+ request_info(req_hash, SnsSubscribeParser.new)
135
+ end
136
+
137
+ def unsubscribe(subscription_arn)
138
+ req_hash = generate_request('Unsubscribe', 'SubscriptionArn' => subscription_arn)
139
+ request_info(req_hash, RightHttp2xxParser.new)
140
+ end
141
+
142
+ def publish(topic_arn, message, subject)
143
+ req_hash = generate_request('Publish', 'TopicArn' => topic_arn, 'Message' => message, 'Subject' => subject)
144
+ request_info(req_hash, SnsPublishParser.new)
145
+ end
146
+
147
+ def set_topic_attribute(topic_arn, attribute_name, attribute_value)
148
+ if attribute_name != 'Policy' && attribute_name != 'DisplayName'
149
+ raise(ArgumentError, "The only values accepted for the attribute_name parameter are (Policy, DisplayName)")
150
+ end
151
+ req_hash = generate_request('SetTopicAttributes', 'TopicArn' => topic_arn, 'AttributeName' => attribute_name, 'AttributeValue' => attribute_value)
152
+ request_info(req_hash, RightHttp2xxParser.new)
153
+ end
154
+
155
+ def get_topic_attributes(topic_arn)
156
+ req_hash = generate_request('GetTopicAttributes', 'TopicArn' => topic_arn)
157
+ request_info(req_hash, SnsGetTopicAttributesParser.new)
158
+ end
159
+
160
+ # Calls either the ListSubscriptions or ListSubscriptionsByTopic depending on whether or not the topic_arn parameter is provided.
161
+ def list_subscriptions(topic_arn = nil)
162
+ req_hash = topic_arn ? generate_request('ListSubscriptionsByTopic', 'TopicArn' => topic_arn) : generate_request('ListSubscriptions')
163
+ request_info(req_hash, SnsListSubscriptionsParser.new)
164
+ end
165
+
166
+ def confirm_subscription(topic_arn, token, authenticate_on_unsubscribe=false)
167
+ req_hash = generate_request('ConfirmSubscription', 'AuthenticateOnUnsubscribe' => authenticate_on_unsubscribe.to_s, 'Token' => token, 'TopicArn' => topic_arn)
168
+ request_info(req_hash, SnsConfirmSubscriptionParser.new)
169
+ end
170
+
171
+ def add_permission(topic_arn, label, acct_action_hash_ary)
172
+ n_hash = {
173
+ 'TopicArn' => topic_arn,
174
+ 'Label' => label
175
+ }
176
+
177
+ acct_action_hash_ary.each_with_index do |hash_val, idx|
178
+ n_hash["AWSAccountId.member.#{idx+1}"] = hash_val[:aws_account_id]
179
+ n_hash["ActionName.member.#{idx+1}"] = hash_val[:action]
180
+ end
181
+
182
+ req_hash = generate_request('AddPermission', n_hash)
183
+ request_info(req_hash, RightHttp2xxParser.new)
184
+ end
185
+
186
+ def remove_permission(topic_arn, label)
187
+ req_hash = generate_request('RemovePermission', 'TopicArn' => topic_arn, 'Label' => label)
188
+ request_info(req_hash, RightHttp2xxParser.new)
189
+ end
190
+
191
+ class SnsCreateTopicParser < RightAWSParser # :nodoc:
192
+ def reset
193
+ @result = ''
194
+ @request_id = ''
195
+ end
196
+ def tagend(name)
197
+ case name
198
+ when 'RequestId' then @result_id = @text
199
+ when 'TopicArn' then @result = @text
200
+ end
201
+ end
202
+ end
203
+
204
+ class SnsListTopicsParser < RightAWSParser # :nodoc:
205
+ def reset
206
+ @result = []
207
+ @request_id = ''
208
+ end
209
+ def tagstart(name, attributes)
210
+ @current_key = {} if name == 'member'
211
+ end
212
+ def tagend(name)
213
+ case name
214
+ when 'RequestId' then @result_id = @text
215
+ when 'TopicArn' then @current_key[:arn] = @text
216
+ when 'member' then @result << @current_key
217
+ end
218
+ end
219
+ end
220
+
221
+ class SnsSubscribeParser < RightAWSParser # :nodoc:
222
+ def reset
223
+ @result = ''
224
+ end
225
+ def tagend(name)
226
+ case name
227
+ when 'SubscriptionArn' then @result = @text
228
+ end
229
+ end
230
+ end
231
+
232
+ class SnsPublishParser < RightAWSParser # :nodoc:
233
+ def reset
234
+ @result = ''
235
+ end
236
+ def tagend(name)
237
+ case name
238
+ when 'MessageId' then @result = @text
239
+ end
240
+ end
241
+ end
242
+
243
+ class SnsGetTopicAttributesParser < RightAWSParser # :nodoc:
244
+ def reset
245
+ @result = {}
246
+ end
247
+ def tagend(name)
248
+ case name
249
+ when 'key' then @current_attr = @text
250
+ when 'value' then @result[@current_attr] = @text
251
+ end
252
+ end
253
+ end
254
+
255
+ class SnsListSubscriptionsParser < RightAWSParser # :nodoc:
256
+ def reset
257
+ @result = []
258
+ end
259
+ def tagstart(name, attributes)
260
+ @current_key = {} if name == 'member'
261
+ end
262
+ def tagend(name)
263
+ case name
264
+ when 'TopicArn' then @current_key[:topic_arn] = @text
265
+ when 'Protocol' then @current_key[:protocol] = @text
266
+ when 'SubscriptionArn' then @current_key[:subscription_arn] = @text
267
+ when 'Owner' then @current_key[:owner] = @text
268
+ when 'Endpoint' then @current_key[:endpoint] = @text
269
+ when 'member' then @result << @current_key
270
+ end
271
+ end
272
+ end
273
+
274
+ class SnsConfirmSubscriptionParser < RightAWSParser # :nodoc:
275
+ def reset
276
+ @result = ''
277
+ end
278
+ def tagend(name)
279
+ case name
280
+ when 'SubscriptionArn' then @result = @text
281
+ end
282
+ end
283
+ end
284
+
285
+ end
286
+ end
@@ -0,0 +1,387 @@
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::Sqs -- RightScale's Amazon SQS interface
28
+ # The RightAws::Sqs class provides a complete interface to Amazon's Simple
29
+ # Queue Service.
30
+ # For explanations of the semantics
31
+ # of each call, please refer to Amazon's documentation at
32
+ # http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=31
33
+ #
34
+ # Error handling: all operations raise an RightAws::AwsError in case
35
+ # of problems. Note that transient errors are automatically retried.
36
+ #
37
+ # sqs = RightAws::Sqs.new(aws_access_key_id, aws_secret_access_key)
38
+ # queue1 = sqs.queue('my_awesome_queue')
39
+ # ...
40
+ # queue2 = RightAws::Sqs::Queue.create(sqs, 'my_cool_queue', true)
41
+ # puts queue2.size
42
+ # ...
43
+ # message1 = queue2.receive
44
+ # message1.visibility = 0
45
+ # puts message1
46
+ # ...
47
+ # queue2.clear(true)
48
+ # queue2.send_message('Ola-la!')
49
+ # message2 = queue2.pop
50
+ # ...
51
+ # grantee1 = RightAws::Sqs::Grantee.create(queue2,'one_cool_guy@email.address')
52
+ # grantee1.grant('FULLCONTROL')
53
+ # grantee1.drop
54
+ # ...
55
+ # grantee2 = queue.grantees('another_cool_guy@email.address')
56
+ # grantee2.revoke('SENDMESSAGE')
57
+ #
58
+ # Params is a hash:
59
+ #
60
+ # {:server => 'queue.amazonaws.com' # Amazon service host: 'queue.amazonaws.com' (default)
61
+ # :port => 443 # Amazon service port: 80 or 443 (default)
62
+ # :signature_version => '0' # The signature version : '0' or '1'(default)
63
+ # :logger => Logger Object} # Logger instance: logs to STDOUT if omitted }
64
+ #
65
+ class Sqs
66
+ attr_reader :interface
67
+
68
+ def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
69
+ @interface = SqsInterface.new(aws_access_key_id, aws_secret_access_key, params)
70
+ end
71
+
72
+ # Retrieves a list of queues.
73
+ # Returns an +array+ of +Queue+ instances.
74
+ #
75
+ # RightAws::Sqs.queues #=> array of queues
76
+ #
77
+ def queues(prefix=nil)
78
+ @interface.list_queues(prefix).map do |url|
79
+ Queue.new(self, url)
80
+ end
81
+ end
82
+
83
+ # Returns Queue instance by queue name.
84
+ # If the queue does not exist at Amazon SQS and +create+ is true, the method creates it.
85
+ #
86
+ # RightAws::Sqs.queue('my_awesome_queue') #=> #<RightAws::Sqs::Queue:0xb7b626e4 ... >
87
+ #
88
+ def queue(queue_name, create=true, visibility=nil)
89
+ url = @interface.queue_url_by_name(queue_name)
90
+ url = (create ? @interface.create_queue(queue_name, visibility) : nil) unless url
91
+ url ? Queue.new(self, url) : nil
92
+ end
93
+
94
+
95
+ class Queue
96
+ attr_reader :name, :url, :sqs
97
+
98
+ # Returns Queue instance by queue name.
99
+ # If the queue does not exist at Amazon SQS and +create+ is true, the method creates it.
100
+ #
101
+ # RightAws::Sqs::Queue.create(sqs, 'my_awesome_queue') #=> #<RightAws::Sqs::Queue:0xb7b626e4 ... >
102
+ #
103
+ def self.create(sqs, url_or_name, create=true, visibility=nil)
104
+ sqs.queue(url_or_name, create, visibility)
105
+ end
106
+
107
+ # Creates new Queue instance.
108
+ # Does not create a queue at Amazon.
109
+ #
110
+ # queue = RightAws::Sqs::Queue.new(sqs, 'my_awesome_queue')
111
+ #
112
+ def initialize(sqs, url_or_name)
113
+ @sqs = sqs
114
+ @url = @sqs.interface.queue_url_by_name(url_or_name)
115
+ @name = @sqs.interface.queue_name_by_url(@url)
116
+ end
117
+
118
+ # Retrieves queue size.
119
+ #
120
+ # queue.size #=> 1
121
+ #
122
+ def size
123
+ @sqs.interface.get_queue_length(@url)
124
+ end
125
+
126
+ # Clears queue.
127
+ # Deletes only the visible messages unless +force+ is +true+.
128
+ #
129
+ # queue.clear(true) #=> true
130
+ #
131
+ # P.S. when <tt>force==true</tt> the queue deletes then creates again. This is
132
+ # the quickest method to clear a big queue or a queue with 'locked' messages. All queue
133
+ # attributes are restored. But there is no way to restore grantees' permissions to
134
+ # this queue. If you have no grantees except 'root' then you have no problems.
135
+ # Otherwise, it's better to use <tt>queue.clear(false)</tt>.
136
+ #
137
+ # PS This function is no longer supported. Amazon has changed the SQS semantics to require at least 60 seconds between
138
+ # queue deletion and creation. Hence this method will fail with an exception.
139
+ #
140
+ def clear(force=false)
141
+ ## if force
142
+ ## @sqs.interface.force_clear_queue(@url)
143
+ ## else
144
+ @sqs.interface.clear_queue(@url)
145
+ ## end
146
+ end
147
+
148
+ # Deletes queue.
149
+ # Queue must be empty or +force+ must be set to +true+.
150
+ # Returns +true+.
151
+ #
152
+ # queue.delete(true) #=> true
153
+ #
154
+ def delete(force=false)
155
+ @sqs.interface.delete_queue(@url, force)
156
+ end
157
+
158
+ # Sends new message to queue.
159
+ # Returns new Message instance that has been sent to queue.
160
+ def send_message(message)
161
+ message = message.to_s
162
+ msg = Message.new(self, @sqs.interface.send_message(@url, message), message)
163
+ msg.sent_at = Time.now
164
+ msg
165
+ end
166
+ alias_method :push, :send_message
167
+
168
+ # Retrieves several messages from queue.
169
+ # Returns an array of Message instances.
170
+ #
171
+ # queue.receive_messages(2,10) #=> array of messages
172
+ #
173
+ def receive_messages(number_of_messages=1, visibility=nil)
174
+ list = @sqs.interface.receive_messages(@url, number_of_messages, visibility)
175
+ list.map! do |entry|
176
+ msg = Message.new(self, entry[:id], entry[:body], visibility)
177
+ msg.received_at = Time.now
178
+ msg
179
+ end
180
+ end
181
+
182
+ # Retrieves first accessible message from queue.
183
+ # Returns Message instance or +nil+ it the queue is empty.
184
+ #
185
+ # queue.receive #=> #<RightAws::Sqs::Message:0xb7bf0884 ... >
186
+ #
187
+ def receive(visibility=nil)
188
+ list = receive_messages(1, visibility)
189
+ list.empty? ? nil : list[0]
190
+ end
191
+
192
+ # Peeks message body.
193
+ #
194
+ # queue.peek #=> #<RightAws::Sqs::Message:0xb7bf0884 ... >
195
+ #
196
+ def peek(message_id)
197
+ entry = @sqs.interface.peek_message(@url, message_id)
198
+ msg = Message.new(self, entry[:id], entry[:body])
199
+ msg.received_at = Time.now
200
+ msg
201
+ end
202
+
203
+ # Pops (and deletes) first accessible message from queue.
204
+ # Returns Message instance or +nil+ it the queue is empty.
205
+ #
206
+ # queue.pop #=> #<RightAws::Sqs::Message:0xb7bf0884 ... >
207
+ #
208
+ def pop
209
+ msg = receive
210
+ msg.delete if msg
211
+ msg
212
+ end
213
+
214
+ # Retrieves +VisibilityTimeout+ value for the queue.
215
+ # Returns new timeout value.
216
+ #
217
+ # queue.visibility #=> 30
218
+ #
219
+ def visibility
220
+ @sqs.interface.get_visibility_timeout(@url)
221
+ end
222
+
223
+ # Sets new +VisibilityTimeout+ for the queue.
224
+ # Returns new timeout value.
225
+ #
226
+ # queue.visibility #=> 30
227
+ # queue.visibility = 33
228
+ # queue.visibility #=> 33
229
+ #
230
+ def visibility=(visibility_timeout)
231
+ @sqs.interface.set_visibility_timeout(@url, visibility_timeout)
232
+ visibility_timeout
233
+ end
234
+
235
+ # Sets new queue attribute value.
236
+ # Not all attributes may be changed: +ApproximateNumberOfMessages+ (for example) is a read only attribute.
237
+ # Returns a value to be assigned to attribute.
238
+ #
239
+ # queue.set_attribute('VisibilityTimeout', '100') #=> '100'
240
+ # queue.get_attribute('VisibilityTimeout') #=> '100'
241
+ #
242
+ def set_attribute(attribute, value)
243
+ @sqs.interface.set_queue_attributes(@url, attribute, value)
244
+ value
245
+ end
246
+
247
+ # Retrieves queue attributes.
248
+ # At this moment Amazon supports +VisibilityTimeout+ and +ApproximateNumberOfMessages+ only.
249
+ # If the name of attribute is set, returns its value. Otherwise, returns a hash of attributes.
250
+ #
251
+ # queue.get_attribute('VisibilityTimeout') #=> '100'
252
+ #
253
+ def get_attribute(attribute='All')
254
+ attributes = @sqs.interface.get_queue_attributes(@url, attribute)
255
+ attribute=='All' ? attributes : attributes[attribute]
256
+ end
257
+
258
+ # Retrieves a list of grantees.
259
+ # Returns an +array+ of Grantee instances if the +grantee_email_address+ is unset.
260
+ # Otherwise returns a Grantee instance that points to +grantee_email_address+ or +nil+.
261
+ #
262
+ # grantees = queue.grantees #=> [#<RightAws::Sqs::Grantee:0xb7bf0888 ... >, ...]
263
+ # ...
264
+ # grantee = queue.grantees('cool_guy@email.address') #=> nil | #<RightAws::Sqs::Grantee:0xb7bf0888 ... >
265
+ #
266
+ def grantees(grantee_email_address=nil, permission = nil)
267
+ hash = @sqs.interface.list_grants(@url, grantee_email_address, permission)
268
+ grantees = []
269
+ hash.each do |key, value|
270
+ grantees << Grantee.new(self, grantee_email_address, key, value[:name], value[:perms])
271
+ end
272
+ if grantee_email_address
273
+ grantees.right_blank? ? nil : grantees.shift
274
+ else
275
+ grantees
276
+ end
277
+ end
278
+ end
279
+
280
+
281
+ class Message
282
+ attr_reader :queue, :id, :body, :visibility
283
+ attr_accessor :sent_at, :received_at
284
+
285
+ def initialize(queue, id=nil, body=nil, visibility=nil)
286
+ @queue = queue
287
+ @id = id
288
+ @body = body
289
+ @visibility = visibility
290
+ @sent_at = nil
291
+ @received_at = nil
292
+ end
293
+
294
+ # Returns +Message+ instance body.
295
+ def to_s
296
+ @body
297
+ end
298
+
299
+ # Changes +VisibilityTimeout+ for current message.
300
+ # Returns new +VisibilityTimeout+ value.
301
+ def visibility=(visibility_timeout)
302
+ @queue.sqs.interface.change_message_visibility(@queue.url, @id, visibility_timeout)
303
+ @visibility = visibility_timeout
304
+ end
305
+
306
+ # Removes message from queue.
307
+ # Returns +true+.
308
+ def delete
309
+ @queue.sqs.interface.delete_message(@queue.url, @id)
310
+ end
311
+ end
312
+
313
+
314
+ class Grantee
315
+ attr_accessor :queue, :id, :name, :perms, :email
316
+
317
+ # Creates new Grantee instance.
318
+ # To create new grantee for queue use:
319
+ #
320
+ # grantee = Grantee.new(queue, grantee@email.address)
321
+ # grantee.grant('FULLCONTROL')
322
+ #
323
+ def initialize(queue, email=nil, id=nil, name=nil, perms=[])
324
+ @queue = queue
325
+ @id = id
326
+ @name = name
327
+ @perms = perms
328
+ @email = email
329
+ retrieve unless id
330
+ end
331
+
332
+ # Retrieves security information for grantee identified by email.
333
+ # Returns +nil+ if the named user has no privileges on this queue, or
334
+ # +true+ if perms updated successfully.
335
+ def retrieve # :nodoc:
336
+ @id = nil
337
+ @name = nil
338
+ @perms = []
339
+
340
+ hash = @queue.sqs.interface.list_grants(@queue.url, @email)
341
+ return nil if hash.empty?
342
+
343
+ grantee = hash.shift
344
+ @id = grantee[0]
345
+ @name = grantee[1][:name]
346
+ @perms = grantee[1][:perms]
347
+ true
348
+ end
349
+
350
+ # Adds permissions for grantee.
351
+ # Permission: 'FULLCONTROL' | 'RECEIVEMESSAGE' | 'SENDMESSAGE'.
352
+ # The caller must have set the email instance variable.
353
+ def grant(permission=nil)
354
+ raise "You can't grant permission without defining a grantee email address!" unless @email
355
+ @queue.sqs.interface.add_grant(@queue.url, @email, permission)
356
+ retrieve
357
+ end
358
+
359
+ # Revokes permissions for grantee.
360
+ # Permission: 'FULLCONTROL' | 'RECEIVEMESSAGE' | 'SENDMESSAGE'.
361
+ # Default value is 'FULLCONTROL'.
362
+ # User must have +@email+ or +@id+ set.
363
+ # Returns +true+.
364
+ def revoke(permission='FULLCONTROL')
365
+ @queue.sqs.interface.remove_grant(@queue.url, @email || @id, permission)
366
+ unless @email # if email is unknown - just remove permission from local perms list...
367
+ @perms.delete(permission)
368
+ else # ... else retrieve updated information from Amazon
369
+ retrieve
370
+ end
371
+ true
372
+ end
373
+
374
+ # Revokes all permissions for this grantee.
375
+ # Returns +true+
376
+ def drop
377
+ @perms.each do |permission|
378
+ @queue.sqs.interface.remove_grant(@queue.url, @email || @id, permission)
379
+ end
380
+ retrieve
381
+ true
382
+ end
383
+
384
+ end
385
+
386
+ end
387
+ end