openwferu-sqs 0.9.8
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.
- data/lib/openwfe/util/sqs.rb +581 -0
- metadata +46 -0
@@ -0,0 +1,581 @@
|
|
1
|
+
#
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2007, John Mettraux, OpenWFE.org
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# . Redistributions of source code must retain the above copyright notice, this
|
10
|
+
# list of conditions and the following disclaimer.
|
11
|
+
#
|
12
|
+
# . Redistributions in binary form must reproduce the above copyright notice,
|
13
|
+
# this list of conditions and the following disclaimer in the documentation
|
14
|
+
# and/or other materials provided with the distribution.
|
15
|
+
#
|
16
|
+
# . Neither the name of the "OpenWFE" nor the names of its contributors may be
|
17
|
+
# used to endorse or promote products derived from this software without
|
18
|
+
# specific prior written permission.
|
19
|
+
#
|
20
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
21
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
23
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
24
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
25
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
26
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
27
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
28
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
29
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
30
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
31
|
+
#++
|
32
|
+
#
|
33
|
+
# $Id$
|
34
|
+
#
|
35
|
+
|
36
|
+
#
|
37
|
+
# Made in Japan
|
38
|
+
#
|
39
|
+
# John dot Mettraux at OpenWFE dot org
|
40
|
+
#
|
41
|
+
|
42
|
+
require 'base64'
|
43
|
+
require 'cgi'
|
44
|
+
require 'net/https'
|
45
|
+
require 'rexml/document'
|
46
|
+
require 'time'
|
47
|
+
require 'pp'
|
48
|
+
|
49
|
+
|
50
|
+
module SQS
|
51
|
+
|
52
|
+
#
|
53
|
+
# An SQS message (after its creation).
|
54
|
+
#
|
55
|
+
class Message
|
56
|
+
|
57
|
+
attr_reader :queue, :message_id, :message_body
|
58
|
+
|
59
|
+
def initialize (queue, xml_element)
|
60
|
+
|
61
|
+
@queue = queue
|
62
|
+
@message_id = SQS::get_element_text(xml_element, "MessageId")
|
63
|
+
@message_body = SQS::get_element_text(xml_element, "MessageBody")
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Connects to the queue service and deletes this message in its queue.
|
68
|
+
#
|
69
|
+
def delete
|
70
|
+
@queue.queue_service.delete_message(@queue, @message_id)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# An SQS queue (gathering all the necessary info about it
|
76
|
+
# in a single class).
|
77
|
+
#
|
78
|
+
class Queue
|
79
|
+
|
80
|
+
attr_reader :queue_service, :host, :path, :name
|
81
|
+
|
82
|
+
def initialize (queue_service, xml_element)
|
83
|
+
|
84
|
+
@queue_service = queue_service
|
85
|
+
|
86
|
+
s = xml_element.text.to_s
|
87
|
+
m = Regexp.compile('^http://(.*)(/.*)(/.*$)').match(s)
|
88
|
+
@host = m[1]
|
89
|
+
@name = m[3][1..-1]
|
90
|
+
@path = m[2] + m[3]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class QueueService
|
95
|
+
|
96
|
+
AWS_VERSION = "2006-04-01"
|
97
|
+
DEFAULT_QUEUE_HOST = "queue.amazonaws.com"
|
98
|
+
|
99
|
+
def initialize (queue_host=nil)
|
100
|
+
|
101
|
+
@queue_host = queue_host
|
102
|
+
@queue_host = DEFAULT_QUEUE_HOST unless @queue_host
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# Lists the queues for the active AWS account.
|
107
|
+
# If 'prefix' is given, only queues whose name begin with that
|
108
|
+
# prefix will be returned.
|
109
|
+
#
|
110
|
+
def list_queues (prefix=nil)
|
111
|
+
|
112
|
+
queues = []
|
113
|
+
|
114
|
+
path = "/"
|
115
|
+
path = "#{path}?QueueNamePrefix=#{prefix}" if prefix
|
116
|
+
|
117
|
+
doc = do_action :get, @queue_host, path
|
118
|
+
|
119
|
+
doc.elements.each("//QueueUrl") do |e|
|
120
|
+
queues << Queue.new(self, e)
|
121
|
+
end
|
122
|
+
|
123
|
+
return queues
|
124
|
+
end
|
125
|
+
|
126
|
+
#
|
127
|
+
# Creates a queue.
|
128
|
+
#
|
129
|
+
# If the queue name doesn't comply with SQS requirements for it,
|
130
|
+
# an error will be raised.
|
131
|
+
#
|
132
|
+
def create_queue (queue_name)
|
133
|
+
|
134
|
+
doc = do_action :post, @queue_host, "/?QueueName=#{queue_name}"
|
135
|
+
|
136
|
+
doc.elements.each("//QueueUrl") do |e|
|
137
|
+
return e.text.to_s
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
#
|
142
|
+
# Given some content ('text/plain' content), send it as a message to
|
143
|
+
# a queue.
|
144
|
+
# Returns the SQS message id (a String).
|
145
|
+
#
|
146
|
+
# The queue might be a queue name (String) or a Queue instance.
|
147
|
+
#
|
148
|
+
def put_message (queue, content)
|
149
|
+
|
150
|
+
queue = resolve_queue(queue)
|
151
|
+
|
152
|
+
doc = do_action :put, queue.host, "#{queue.path}/back", content
|
153
|
+
|
154
|
+
#puts doc.to_s
|
155
|
+
|
156
|
+
#status_code = SQS::get_element_text(doc, '//StatusCode')
|
157
|
+
#message_id = SQS::get_element_text(doc, '//MessageId')
|
158
|
+
#request_id = SQS::get_element_text(doc, '//RequestId')
|
159
|
+
#{ :status_code => status_code,
|
160
|
+
# :message_id => message_id,
|
161
|
+
# :request_id => request_id }
|
162
|
+
|
163
|
+
SQS::get_element_text(doc, '//MessageId')
|
164
|
+
end
|
165
|
+
|
166
|
+
alias :send_message :put_message
|
167
|
+
|
168
|
+
#
|
169
|
+
# Retrieves a bunch of messages from a queue. Returns a list of
|
170
|
+
# Message instances.
|
171
|
+
#
|
172
|
+
# There are actually two optional params that this method understands :
|
173
|
+
#
|
174
|
+
# - :timeout the duration in seconds of the message visibility in the
|
175
|
+
# queue
|
176
|
+
# - :count the max number of message to be returned by this call
|
177
|
+
#
|
178
|
+
# The queue might be a queue name (String) or a Queue instance.
|
179
|
+
#
|
180
|
+
def get_messages (queue, params={})
|
181
|
+
|
182
|
+
queue = resolve_queue(queue)
|
183
|
+
|
184
|
+
path = "#{queue.path}/front"
|
185
|
+
|
186
|
+
path += "?" if params.size > 0
|
187
|
+
|
188
|
+
timeout = params[:timeout]
|
189
|
+
count = params[:count]
|
190
|
+
|
191
|
+
path += "VisibilityTimeout=#{timeout}" if timeout
|
192
|
+
path += "&" if timeout and count
|
193
|
+
path += "NumberOfMessages=#{count}" if count
|
194
|
+
|
195
|
+
doc = do_action :get, queue.host, path
|
196
|
+
|
197
|
+
messages = []
|
198
|
+
|
199
|
+
doc.elements.each("//Message") do |me|
|
200
|
+
messages << Message.new(queue, me)
|
201
|
+
end
|
202
|
+
|
203
|
+
messages
|
204
|
+
end
|
205
|
+
|
206
|
+
#
|
207
|
+
# Retrieves a single message from a queue. Returns an instance of
|
208
|
+
# Message.
|
209
|
+
#
|
210
|
+
# The queue might be a queue name (String) or a Queue instance.
|
211
|
+
#
|
212
|
+
def get_message (queue, message_id)
|
213
|
+
|
214
|
+
queue = resolve_queue(queue)
|
215
|
+
|
216
|
+
path = "#{queue.path}/#{message_id}"
|
217
|
+
|
218
|
+
begin
|
219
|
+
doc = do_action :get, queue.host, path
|
220
|
+
Message.new(queue, doc.root.elements[1])
|
221
|
+
rescue Exception => e
|
222
|
+
#puts e.message
|
223
|
+
return nil if e.message.match "^404 .*$"
|
224
|
+
raise e
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
#
|
229
|
+
# Deletes a given message.
|
230
|
+
#
|
231
|
+
# The queue might be a queue name (String) or a Queue instance.
|
232
|
+
#
|
233
|
+
def delete_message (queue, message_id)
|
234
|
+
|
235
|
+
queue = resolve_queue(queue)
|
236
|
+
|
237
|
+
path = "#{queue.path}/#{message_id}"
|
238
|
+
#path = "#{queue.path}/#{CGI::escape(message_id)}"
|
239
|
+
|
240
|
+
doc = do_action :delete, queue.host, path
|
241
|
+
|
242
|
+
SQS::get_element_text(doc, "//StatusCode") == "Success"
|
243
|
+
end
|
244
|
+
|
245
|
+
#
|
246
|
+
# Use with care !
|
247
|
+
#
|
248
|
+
# Attempts at deleting all the messages in a queue.
|
249
|
+
# Returns the total count of messages deleted.
|
250
|
+
#
|
251
|
+
# A call on this method might take a certain time, as it has
|
252
|
+
# to delete each message individually. AWS will perhaps
|
253
|
+
# add a proper 'flush_queue' method later.
|
254
|
+
#
|
255
|
+
# The queue might be a queue name (String) or a Queue instance.
|
256
|
+
#
|
257
|
+
def flush_queue (queue)
|
258
|
+
|
259
|
+
count = 0
|
260
|
+
|
261
|
+
while true
|
262
|
+
|
263
|
+
l = get_messages(queue, :timeout => 0, :count => 255)
|
264
|
+
break if l.length < 1
|
265
|
+
|
266
|
+
l.each do |m|
|
267
|
+
m.delete
|
268
|
+
count += 1
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
return count
|
273
|
+
end
|
274
|
+
|
275
|
+
#
|
276
|
+
# Deletes the queue. Returns true if the delete was successful.
|
277
|
+
# You can empty a queue by called the method #flush_queue
|
278
|
+
#
|
279
|
+
# If 'force' is set to true, a flush will be performed on the
|
280
|
+
# queue before the actual delete operation. It should ensure
|
281
|
+
# a successful removal of the queue.
|
282
|
+
#
|
283
|
+
def delete_queue (queue, force=false)
|
284
|
+
|
285
|
+
queue = resolve_queue(queue)
|
286
|
+
|
287
|
+
flush_queue(queue) if force
|
288
|
+
|
289
|
+
begin
|
290
|
+
|
291
|
+
doc = do_action :delete, @queue_host, queue.path
|
292
|
+
|
293
|
+
rescue Exception => e
|
294
|
+
|
295
|
+
return false if e.message.match "^400 .*$"
|
296
|
+
end
|
297
|
+
|
298
|
+
SQS::get_element_text(doc, "//StatusCode") == "Success"
|
299
|
+
end
|
300
|
+
|
301
|
+
#
|
302
|
+
# Given a queue name, a Queue instance is returned.
|
303
|
+
#
|
304
|
+
def get_queue (queue_name)
|
305
|
+
|
306
|
+
l = list_queues(queue_name)
|
307
|
+
|
308
|
+
l.each do |q|
|
309
|
+
return q if q.name == queue_name
|
310
|
+
end
|
311
|
+
|
312
|
+
#return nil
|
313
|
+
raise "found no queue named '#{queue_name}'"
|
314
|
+
end
|
315
|
+
|
316
|
+
protected
|
317
|
+
|
318
|
+
#
|
319
|
+
# 'queue' might be a Queue instance or a queue name.
|
320
|
+
# If it's a Queue instance, it is immediately returned,
|
321
|
+
# else the Queue instance is looked up and returned.
|
322
|
+
#
|
323
|
+
def resolve_queue (queue)
|
324
|
+
return queue if queue.kind_of? Queue
|
325
|
+
return get_queue(queue.to_s)
|
326
|
+
end
|
327
|
+
|
328
|
+
#
|
329
|
+
# The actual http request/response job is done here.
|
330
|
+
#
|
331
|
+
def do_action (action, host, path, content=nil)
|
332
|
+
|
333
|
+
#puts "___path : #{path}"
|
334
|
+
|
335
|
+
doc = nil
|
336
|
+
|
337
|
+
http = Net::HTTP.new(host)
|
338
|
+
http.start do
|
339
|
+
|
340
|
+
date = Time.now.httpdate
|
341
|
+
|
342
|
+
req = if action == :get
|
343
|
+
Net::HTTP::Get.new(path)
|
344
|
+
elsif action == :post
|
345
|
+
Net::HTTP::Post.new(path)
|
346
|
+
elsif action == :put
|
347
|
+
Net::HTTP::Put.new(path)
|
348
|
+
else #action == :delete
|
349
|
+
Net::HTTP::Delete.new(path)
|
350
|
+
end
|
351
|
+
|
352
|
+
req['AWS-Version'] = AWS_VERSION
|
353
|
+
req['Date'] = date
|
354
|
+
req['Content-type'] = 'text/plain'
|
355
|
+
|
356
|
+
if action == :put or action == :post
|
357
|
+
req.body = content
|
358
|
+
req['Content-length'] = content.length.to_s if content
|
359
|
+
end
|
360
|
+
|
361
|
+
req['Authorization'] = generate_auth_header(
|
362
|
+
action, path, date, "text/plain")
|
363
|
+
|
364
|
+
#req.each_header do |k, v|
|
365
|
+
# puts " - '#{k}' => '#{v}'"
|
366
|
+
#end
|
367
|
+
|
368
|
+
res = http.request(req)
|
369
|
+
|
370
|
+
case res
|
371
|
+
when Net::HTTPSuccess, Net::HTTPRedirection
|
372
|
+
doc = REXML::Document.new(res.read_body)
|
373
|
+
else
|
374
|
+
res.error!
|
375
|
+
end
|
376
|
+
end
|
377
|
+
raise_errors(doc)
|
378
|
+
return doc
|
379
|
+
end
|
380
|
+
|
381
|
+
#
|
382
|
+
# Scans the SQS XML reply for potential errors and raises an
|
383
|
+
# error if he encounters one.
|
384
|
+
#
|
385
|
+
def raise_errors (doc)
|
386
|
+
|
387
|
+
doc.elements.each("//Error") do |e|
|
388
|
+
|
389
|
+
code = get_element_text(e, "Code")
|
390
|
+
return unless code
|
391
|
+
|
392
|
+
message = get_element_text(e, "Message")
|
393
|
+
raise "SQS::#{code} : #{m.text.to_s}"
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
#
|
398
|
+
# Generates the 'AWS x:y" authorization header value.
|
399
|
+
#
|
400
|
+
def generate_auth_header (action, path, date, content_type)
|
401
|
+
|
402
|
+
s = ""
|
403
|
+
s << action.to_s.upcase
|
404
|
+
s << "\n"
|
405
|
+
|
406
|
+
#s << Base64.encode64(Digest::MD5.digest(content)).strip \
|
407
|
+
# if content
|
408
|
+
#
|
409
|
+
# documented but not necessary (not working)
|
410
|
+
s << "\n"
|
411
|
+
|
412
|
+
s << content_type
|
413
|
+
s << "\n"
|
414
|
+
|
415
|
+
s << date
|
416
|
+
s << "\n"
|
417
|
+
|
418
|
+
i = path.index '?'
|
419
|
+
path = path[0..i-1] if i
|
420
|
+
s << path
|
421
|
+
|
422
|
+
#puts ">>>#{s}<<<"
|
423
|
+
|
424
|
+
digest = OpenSSL::Digest::Digest.new 'sha1'
|
425
|
+
|
426
|
+
key = ENV['AMAZON_SECRET_ACCESS_KEY']
|
427
|
+
|
428
|
+
raise "No $AMAZON_SECRET_ACCESS_KEY env variable found" \
|
429
|
+
unless key
|
430
|
+
|
431
|
+
sig = OpenSSL::HMAC.digest(digest, key, s)
|
432
|
+
sig = Base64.encode64(sig).strip
|
433
|
+
|
434
|
+
"AWS #{ENV['AMAZON_ACCESS_KEY_ID']}:#{sig}"
|
435
|
+
end
|
436
|
+
|
437
|
+
end
|
438
|
+
|
439
|
+
#
|
440
|
+
# A convenience method for returning the text of a sub element,
|
441
|
+
# maybe there is something better in REXML, but I haven't found out
|
442
|
+
# yet.
|
443
|
+
#
|
444
|
+
def SQS.get_element_text (parent_elt, elt_name)
|
445
|
+
e = parent_elt.elements[elt_name]
|
446
|
+
return nil unless e
|
447
|
+
return e.text.to_s
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
|
452
|
+
#
|
453
|
+
# running directly...
|
454
|
+
|
455
|
+
if $0 == __FILE__
|
456
|
+
|
457
|
+
if ENV['AMAZON_ACCESS_KEY_ID'] == nil or ENV['AMAZON_SECRET_ACCESS_KEY'] == nil
|
458
|
+
|
459
|
+
puts
|
460
|
+
puts "env variables $AMAZON_ACCESS_KEY_ID and $AMAZON_SECRET_ACCESS_KEY are not set"
|
461
|
+
puts
|
462
|
+
exit 1
|
463
|
+
end
|
464
|
+
|
465
|
+
ACTIONS = {
|
466
|
+
:list_queues => :list_queues,
|
467
|
+
:lq => :list_queues,
|
468
|
+
:create_queue => :create_queue,
|
469
|
+
:cq => :create_queue,
|
470
|
+
:delete_queue => :delete_queue,
|
471
|
+
:dq => :delete_queue,
|
472
|
+
:flush_queue => :flush_queue,
|
473
|
+
:fq => :flush_queue,
|
474
|
+
:get_message => :get_message,
|
475
|
+
:gm => :get_message,
|
476
|
+
:delete_message => :delete_message,
|
477
|
+
:dm => :delete_message,
|
478
|
+
:puts_message => :put_message,
|
479
|
+
:pm => :put_message
|
480
|
+
}
|
481
|
+
|
482
|
+
b64 = false
|
483
|
+
queue_host = nil
|
484
|
+
|
485
|
+
require 'optparse'
|
486
|
+
|
487
|
+
opts = OptionParser.new
|
488
|
+
|
489
|
+
opts.banner = "Usage: sqs.rb [options] {action} [queue_name] [message_id]"
|
490
|
+
opts.separator("")
|
491
|
+
opts.separator(" known actions are :")
|
492
|
+
opts.separator("")
|
493
|
+
|
494
|
+
keys = ACTIONS.keys.collect { |k| k.to_s }.sort
|
495
|
+
keys.each { |k| opts.separator(" - '#{k}' (#{ACTIONS[k.intern]})") }
|
496
|
+
|
497
|
+
opts.separator("")
|
498
|
+
opts.separator(" options are :")
|
499
|
+
opts.separator("")
|
500
|
+
|
501
|
+
opts.on("-H", "--host", "AWS queue host") do |host|
|
502
|
+
queue_host = host
|
503
|
+
end
|
504
|
+
|
505
|
+
opts.on("-h", "--help", "displays this help / usage") do
|
506
|
+
STDERR.puts "\n#{opts.to_s}\n"
|
507
|
+
exit 0
|
508
|
+
end
|
509
|
+
|
510
|
+
opts.on("-b", "--base64", "encode/decode messages with base64") do
|
511
|
+
b64 = true
|
512
|
+
end
|
513
|
+
|
514
|
+
argv = opts.parse(ARGV)
|
515
|
+
|
516
|
+
if argv.length < 1
|
517
|
+
STDERR.puts "\n#{opts.to_s}\n"
|
518
|
+
exit 0
|
519
|
+
end
|
520
|
+
|
521
|
+
a = argv[0]
|
522
|
+
queue_name = argv[1]
|
523
|
+
message_id = argv[2]
|
524
|
+
|
525
|
+
action = ACTIONS[a.intern]
|
526
|
+
|
527
|
+
unless action
|
528
|
+
STDERR.puts "unknown action '#{a}'"
|
529
|
+
exit 1
|
530
|
+
end
|
531
|
+
|
532
|
+
qs = SQS::QueueService.new
|
533
|
+
|
534
|
+
STDERR.puts "#{action.to_s}..."
|
535
|
+
|
536
|
+
#
|
537
|
+
# just do it
|
538
|
+
|
539
|
+
case action
|
540
|
+
when :list_queues, :create_queue, :delete_queue, :flush_queue
|
541
|
+
|
542
|
+
pp qs.send(action, queue_name)
|
543
|
+
|
544
|
+
when :get_message
|
545
|
+
|
546
|
+
if message_id
|
547
|
+
m = qs.get_message(queue_name, message_id)
|
548
|
+
body = m.message_body
|
549
|
+
body = Base64.decode64(body) if b64
|
550
|
+
puts body
|
551
|
+
else
|
552
|
+
pp qs.get_messages(queue_name, :timeout => 0, :count => 255)
|
553
|
+
end
|
554
|
+
|
555
|
+
when :delete_message
|
556
|
+
|
557
|
+
raise "argument 'message_id' is missing" unless message_id
|
558
|
+
pp qs.delete_message(queue_name, message_id)
|
559
|
+
|
560
|
+
when :put_message
|
561
|
+
|
562
|
+
message = argv[2]
|
563
|
+
|
564
|
+
unless message
|
565
|
+
message = ""
|
566
|
+
while true
|
567
|
+
s = STDIN.gets()
|
568
|
+
break if s == nil
|
569
|
+
message += s[0..-2]
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
message = Base64.encode64(message).strip if b64
|
574
|
+
|
575
|
+
pp qs.put_message(queue_name, message)
|
576
|
+
else
|
577
|
+
|
578
|
+
STDERR.puts "not yet implemented..."
|
579
|
+
end
|
580
|
+
|
581
|
+
end
|
metadata
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0
|
3
|
+
specification_version: 1
|
4
|
+
name: openwferu-sqs
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.9.8
|
7
|
+
date: 2007-04-05 00:00:00 +09:00
|
8
|
+
summary: Accessing Amazon SQS over its REST API
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: john at openwfe dot org
|
12
|
+
homepage: http://openwferu.rubyforge.org/scheduler.html
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: openwferu-sqs
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- John Mettraux
|
31
|
+
files:
|
32
|
+
- lib/openwfe/util/sqs.rb
|
33
|
+
test_files: []
|
34
|
+
|
35
|
+
rdoc_options: []
|
36
|
+
|
37
|
+
extra_rdoc_files: []
|
38
|
+
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
requirements: []
|
44
|
+
|
45
|
+
dependencies: []
|
46
|
+
|