elastic-mapreduce 0.0.1

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 (60) hide show
  1. data/CHANGELOG +51 -0
  2. data/Gemfile +13 -0
  3. data/Gemfile.lock +16 -0
  4. data/LICENSE.txt +393 -0
  5. data/NOTICE.txt +26 -0
  6. data/README +1007 -0
  7. data/Rakefile +35 -0
  8. data/VERSION +1 -0
  9. data/bin/elastic-mapreduce +27 -0
  10. data/cacert.pem +280 -0
  11. data/elastic-mapreduce.gemspec +104 -0
  12. data/lib/amazon/aws/exceptions.rb +211 -0
  13. data/lib/amazon/coral/awsquery.rb +128 -0
  14. data/lib/amazon/coral/awsquerychainhelper.rb +92 -0
  15. data/lib/amazon/coral/awsqueryhandler.rb +170 -0
  16. data/lib/amazon/coral/awsqueryurihandler.rb +34 -0
  17. data/lib/amazon/coral/call.rb +68 -0
  18. data/lib/amazon/coral/dispatcher.rb +33 -0
  19. data/lib/amazon/coral/ec2client.rb +91 -0
  20. data/lib/amazon/coral/elasticmapreduceclient.rb +198 -0
  21. data/lib/amazon/coral/handler.rb +20 -0
  22. data/lib/amazon/coral/httpdelegationhelper.rb +27 -0
  23. data/lib/amazon/coral/httpdestinationhandler.rb +36 -0
  24. data/lib/amazon/coral/httphandler.rb +124 -0
  25. data/lib/amazon/coral/identityhandler.rb +32 -0
  26. data/lib/amazon/coral/job.rb +25 -0
  27. data/lib/amazon/coral/logfactory.rb +35 -0
  28. data/lib/amazon/coral/option.rb +70 -0
  29. data/lib/amazon/coral/orchestrator.rb +49 -0
  30. data/lib/amazon/coral/querystringmap.rb +93 -0
  31. data/lib/amazon/coral/service.rb +130 -0
  32. data/lib/amazon/coral/simplelog.rb +98 -0
  33. data/lib/amazon/coral/urlencoding.rb +19 -0
  34. data/lib/amazon/coral/v0signaturehandler.rb +33 -0
  35. data/lib/amazon/coral/v0signaturehelper.rb +83 -0
  36. data/lib/amazon/coral/v1signaturehandler.rb +32 -0
  37. data/lib/amazon/coral/v1signaturehelper.rb +58 -0
  38. data/lib/amazon/coral/v2signaturehandler.rb +46 -0
  39. data/lib/amazon/coral/v2signaturehelper.rb +76 -0
  40. data/lib/amazon/retry_delegator.rb +66 -0
  41. data/lib/amazon/stderr_logger.rb +23 -0
  42. data/lib/client.rb +117 -0
  43. data/lib/commands.rb +1690 -0
  44. data/lib/credentials.rb +86 -0
  45. data/lib/ec2_client_wrapper.rb +73 -0
  46. data/lib/json/lexer.rb +294 -0
  47. data/lib/json/objects.rb +200 -0
  48. data/lib/json.rb +58 -0
  49. data/lib/simple_executor.rb +11 -0
  50. data/lib/simple_logger.rb +38 -0
  51. data/lib/uuidtools/version.rb +32 -0
  52. data/lib/uuidtools.rb +655 -0
  53. data/run_tests.rb +8 -0
  54. data/samples/freebase/code/freebase_jobflow.json +44 -0
  55. data/samples/similarity/lastfm_jobflow.json +78 -0
  56. data/samples/wordSplitter.py +18 -0
  57. data/tests/commands_test.rb +587 -0
  58. data/tests/credentials.json +7 -0
  59. data/tests/example.json +14 -0
  60. metadata +154 -0
@@ -0,0 +1,198 @@
1
+ #
2
+ # Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+
4
+ require 'amazon/coral/dispatcher'
5
+ require 'amazon/coral/call'
6
+ require 'amazon/coral/service'
7
+
8
+ module Amazon
9
+ module Coral
10
+
11
+ # Client interface for calling ElasticMapReduce.
12
+ #
13
+ # The client supports two mechanisms to invoke each remote service call: a simple approach
14
+ # which directly calls the remote service, or a Call based mechanism that allows you to
15
+ # control aspects of the outgoing request such as request-id and identity attributes.
16
+ #
17
+ # Each instance of a client interface is backed by an Orchestrator object which manages
18
+ # the processing of each request to the remote service.
19
+ # Clients can be instantiated with a custom orchestrator or with presets corresponding to
20
+ # particular protocols. Inputs and return values to the direct service-call methods and
21
+ # the Call.call methods are hashes.
22
+ class ElasticMapReduceClient
23
+ # Construct a new client. Takes an orchestrator through which to process requests.
24
+ # See additional constructors below to use pre-configured orchestrators for specific protocols.
25
+ #
26
+ # [orchestrator]
27
+ # The Orchestrator is responsible for actually making the remote service call. Clients
28
+ # construct requests, hand them off to the orchestrator, and receive responses in return.
29
+ def initialize(orchestrator)
30
+ @addJobFlowStepsDispatcher = Dispatcher.new(orchestrator, 'ElasticMapReduce', 'AddJobFlowSteps')
31
+ @addInstanceGroupsDispatcher = Dispatcher.new(orchestrator, 'ElasticMapReduce', 'AddInstanceGroups')
32
+ @terminateJobFlowsDispatcher = Dispatcher.new(orchestrator, 'ElasticMapReduce', 'TerminateJobFlows')
33
+ @setTerminationProtectionDispatcher = Dispatcher.new(orchestrator, 'ElasticMapReduce', 'SetTerminationProtection')
34
+ @describeJobFlowsDispatcher = Dispatcher.new(orchestrator, 'ElasticMapReduce', 'DescribeJobFlows')
35
+ @runJobFlowDispatcher = Dispatcher.new(orchestrator, 'ElasticMapReduce', 'RunJobFlow')
36
+ @modifyInstanceGroupsDispatcher = Dispatcher.new(orchestrator, 'ElasticMapReduce', 'ModifyInstanceGroups')
37
+ end
38
+
39
+
40
+ # Instantiates a call object to invoke the AddJobFlowSteps operation:
41
+ #
42
+ # Example usage:
43
+ # my_call = my_client.newAddJobFlowStepsCall
44
+ # # set identity information if needed
45
+ # my_call.identity[:aws_access_key] = my_access_key
46
+ # my_call.identity[:aws_secret_key] = my_secret_key
47
+ # # make the remote call
48
+ # my_call.call(my_input)
49
+ # # retrieve the request-id returned by the server
50
+ # my_request_id = my_call.request_id
51
+ def newAddJobFlowStepsCall
52
+ Call.new(@addJobFlowStepsDispatcher)
53
+ end
54
+
55
+ # Instantiates a call object to invoke the AddInstanceGroups operation:
56
+ #
57
+ # Example usage:
58
+ # my_call = my_client.newAddInstanceGroupsCall
59
+ # # set identity information if needed
60
+ # my_call.identity[:aws_access_key] = my_access_key
61
+ # my_call.identity[:aws_secret_key] = my_secret_key
62
+ # # make the remote call
63
+ # my_call.call(my_input)
64
+ # # retrieve the request-id returned by the server
65
+ # my_request_id = my_call.request_id
66
+ def newAddInstanceGroupsCall
67
+ Call.new(@addInstanceGroupsDispatcher)
68
+ end
69
+
70
+ # Instantiates a call object to invoke the TerminateJobFlows operation:
71
+ #
72
+ # Example usage:
73
+ # my_call = my_client.newTerminateJobFlowsCall
74
+ # # set identity information if needed
75
+ # my_call.identity[:aws_access_key] = my_access_key
76
+ # my_call.identity[:aws_secret_key] = my_secret_key
77
+ # # make the remote call
78
+ # my_call.call(my_input)
79
+ # # retrieve the request-id returned by the server
80
+ # my_request_id = my_call.request_id
81
+ def newTerminateJobFlowsCall
82
+ Call.new(@terminateJobFlowsDispatcher)
83
+ end
84
+
85
+ # Instantiates a call object to invoke the SetTerminationProtection operation:
86
+ def newSetTerminationProtectionCall
87
+ Call.new(@setTerminationProtectionDispatcher)
88
+ end
89
+
90
+ # Instantiates a call object to invoke the DescribeJobFlows operation:
91
+ #
92
+ # Example usage:
93
+ # my_call = my_client.newDescribeJobFlowsCall
94
+ # # set identity information if needed
95
+ # my_call.identity[:aws_access_key] = my_access_key
96
+ # my_call.identity[:aws_secret_key] = my_secret_key
97
+ # # make the remote call
98
+ # my_output = my_call.call(my_input)
99
+ # # retrieve the request-id returned by the server
100
+ # my_request_id = my_call.request_id
101
+ def newDescribeJobFlowsCall
102
+ Call.new(@describeJobFlowsDispatcher)
103
+ end
104
+
105
+ # Instantiates a call object to invoke the RunJobFlow operation:
106
+ #
107
+ # Example usage:
108
+ # my_call = my_client.newRunJobFlowCall
109
+ # # set identity information if needed
110
+ # my_call.identity[:aws_access_key] = my_access_key
111
+ # my_call.identity[:aws_secret_key] = my_secret_key
112
+ # # make the remote call
113
+ # my_output = my_call.call(my_input)
114
+ # # retrieve the request-id returned by the server
115
+ # my_request_id = my_call.request_id
116
+ def newRunJobFlowCall
117
+ Call.new(@runJobFlowDispatcher)
118
+ end
119
+
120
+ def newModifyInstanceGroupsCall
121
+ Call.new(@modifyInstanceGroupsDispatcher)
122
+ end
123
+
124
+
125
+ # Shorthand method to invoke the AddJobFlowSteps operation:
126
+ #
127
+ # Example usage:
128
+ # my_client.AddJobFlowSteps(my_input)
129
+ def AddJobFlowSteps(input = {})
130
+ newAddJobFlowStepsCall.call(input)
131
+ end
132
+
133
+ # Shorthand method to invoke the AddInstanceGroups operation:
134
+ #
135
+ # Example usage:
136
+ # my_client.AddInstanceGroups(my_input)
137
+ def AddInstanceGroups(input = {})
138
+ newAddInstanceGroupsCall.call(input)
139
+ end
140
+
141
+ # Shorthand method to invoke the TerminateJobFlows operation:
142
+ #
143
+ # Example usage:
144
+ # my_client.TerminateJobFlows(my_input)
145
+ def TerminateJobFlows(input = {})
146
+ newTerminateJobFlowsCall.call(input)
147
+ end
148
+
149
+ # Shorthand method to invoke the SetTerminationProtection operation:
150
+ def SetTerminationProtection(input = {})
151
+ newSetTerminationProtectionCall.call(input)
152
+ end
153
+
154
+ # Shorthand method to invoke the DescribeJobFlows operation:
155
+ #
156
+ # Example usage:
157
+ # my_output = my_client.DescribeJobFlows(my_input)
158
+ def DescribeJobFlows(input = {})
159
+ newDescribeJobFlowsCall.call(input)
160
+ end
161
+
162
+ # Shorthand method to invoke the RunJobFlow operation:
163
+ #
164
+ # Example usage:
165
+ # my_output = my_client.RunJobFlow(my_input)
166
+ def RunJobFlow(input = {})
167
+ newRunJobFlowCall.call(input)
168
+ end
169
+
170
+
171
+ def ModifyInstanceGroups(input = {})
172
+ newModifyInstanceGroupsCall.call(input)
173
+ end
174
+
175
+
176
+ # Instantiates the client with an orchestrator configured for use with AWS/QUERY.
177
+ # Use of this constructor is deprecated in favor of using the AwsQuery class:
178
+ # client = ElasticMapReduceClient.new(AwsQuery.new_orchestrator(args))
179
+ def ElasticMapReduceClient.new_aws_query(args)
180
+ require 'amazon/coral/awsquery'
181
+ ElasticMapReduceClient.new(AwsQuery.new_orchestrator(args))
182
+ end
183
+
184
+ end
185
+
186
+ # allow running from the command line
187
+ Service.new(:service => 'ElasticMapReduce', :operations => [
188
+ 'AddJobFlowSteps',
189
+ 'AddInstanceGroups',
190
+ 'TerminateJobFlows',
191
+ 'SetTerminationProtection',
192
+ 'DescribeJobFlows',
193
+ 'RunJobFlow',
194
+ 'ModifyInstanceGroups'
195
+ ]).main if caller.empty?
196
+ end
197
+ end
198
+
@@ -0,0 +1,20 @@
1
+ #
2
+ # Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+
4
+ module Amazon
5
+ module Coral
6
+
7
+ class Handler
8
+
9
+ # Operate on the specified Job on the "outbound" side of the execution
10
+ def before(job)
11
+ end
12
+
13
+ # Operation on the specified Job on the "inbound" side of the execution
14
+ def after(job)
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ #
2
+ # Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+
4
+ module Amazon
5
+ module Coral
6
+
7
+ class HttpDelegationHelper
8
+ def self.add_delegation_token(delegate_identity, request_identity)
9
+ token = ""
10
+ first = true
11
+
12
+ delegate_identity.each do |k,v|
13
+ if(first)
14
+ first = false
15
+ else
16
+ token << ';'
17
+ end
18
+
19
+ token << "#{k}=#{v}"
20
+ end
21
+
22
+ request_identity[:http_delegation] = token if(token.length > 0)
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,36 @@
1
+ # Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+
3
+ require 'uri'
4
+ require 'amazon/coral/handler'
5
+ require 'amazon/coral/logfactory'
6
+
7
+ module Amazon
8
+ module Coral
9
+
10
+ # Attaches the specified endpoint URI to the outgoing request.
11
+ class HttpDestinationHandler < Handler
12
+
13
+ # Initialize an HttpDestinationHandler with the specified endpoint
14
+ # URI.
15
+ def initialize(endpoint)
16
+ @log = LogFactory.getLog('Amazon::Coral::HttpDestinationHandler')
17
+
18
+ @uri = case endpoint
19
+ when URI
20
+ endpoint
21
+ else
22
+ URI.parse(endpoint)
23
+ end
24
+ @uri.path = '/' if @uri.path.nil? || @uri.path.empty?
25
+ end
26
+
27
+ def before(job)
28
+ job.request[:http_verb] = 'GET'
29
+ job.request[:http_uri] = @uri.clone
30
+
31
+ @log.debug "Initial request URI #{@uri}"
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,124 @@
1
+ #
2
+ # Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+
4
+ require 'uri'
5
+ require 'net/http'
6
+ require 'net/https'
7
+ require 'amazon/coral/handler'
8
+ require 'amazon/coral/logfactory'
9
+
10
+ module Amazon
11
+ module Coral
12
+
13
+ # Executes HTTP requests via the Net::HTTP library. Supports HTTP,
14
+ # HTTPS and client X509 certificates.
15
+ class HttpHandler < Handler
16
+
17
+ # Instantiate a new HttpHandler with the specified arguments. Possible arguments include:
18
+ # [:verbose]
19
+ # If true, the handler will output the URI it is requesting to STDOUT.
20
+ # This may be useful for debugging purposes.
21
+ # [:ca_file]
22
+ # This parameter's value points to a valid .pem certificate file to enable the
23
+ # client to validate server certificates when using SSL.
24
+ # If this parameter is not specified, the client operates in insecure mode and does not
25
+ # validate that server certificates come from a trusted source.
26
+ # [:timeout]
27
+ # This value (in seconds) will be used for every socket operation during the request.
28
+ # Note that since a request can involve many socket operations, calls that timeout may
29
+ # actually take more time than this value. If unspecified, defaults to 5.0 seconds.
30
+ # A value of zero will result in an infinite timeout.
31
+ # [:connect_timeout]
32
+ # This value (in seconds) will be used as the timeout for opening a connection to the
33
+ # service. If unspecified, defaults to 5.0 seconds. A value of zero will result in
34
+ # an infinite timeout.
35
+ def initialize(args = {})
36
+ @log = LogFactory.getLog('Amazon::Coral::HttpHandler')
37
+
38
+ @verbose = args[:verbose]
39
+ @ca_file = args[:ca_file]
40
+ @connect_timeout = args[:connect_timeout]
41
+ @timeout = args[:timeout]
42
+
43
+ @connect_timeout = 5.0 if @connect_timeout.nil?
44
+ @timeout = 5.0 if @timeout.nil?
45
+
46
+ raise ArgumentError, "connect_timeout must be non-negative" if @connect_timeout < 0
47
+ raise ArgumentError, "timeout must be non-negative" if @timeout < 0
48
+ end
49
+
50
+ def before(job)
51
+ identity = job.request[:identity]
52
+ request_id = job.request[:id]
53
+ uri = job.request[:http_uri]
54
+ verb = job.request[:http_verb]
55
+ query_map = job.request[:http_query_map]
56
+
57
+ verb = 'GET' if verb.nil?
58
+
59
+ headers = {}
60
+ headers['x-amzn-RequestId'] = "#{request_id}"
61
+ headers['x-amzn-Delegation'] = identity[:http_delegation] unless identity[:http_delegation].nil?
62
+ headers['Authorization'] = identity[:http_authorization] unless identity[:http_authorization].nil?
63
+ headers['Host'] = job.request[:http_host] unless job.request[:http_host].nil?
64
+ headers['User-Agent'] = 'ruby-client'
65
+
66
+ result = http_request(uri, headers, verb, query_map, identity[:http_client_x509], identity[:http_client_x509_key])
67
+
68
+ @log.info "Response code: #{result.code}"
69
+
70
+ job.reply[:response] = result
71
+ job.reply[:value] = result.body
72
+ job.reply[:http_status_code] = result.code
73
+ job.reply[:http_status_message] = result.message
74
+ job.reply[:http_content] = nil # TODO: get content-type header
75
+ end
76
+
77
+ private
78
+ def http_request(uri, headers, verb, query_map = nil, cert = nil, key = nil)
79
+ if @verbose then
80
+ puts "Requesting URL:\n#{uri}\nQuery string:\n#{query_map}\nHeaders:\n#{headers}\n"
81
+ end
82
+
83
+ http = Net::HTTP.new(uri.host, uri.port)
84
+ http.read_timeout = @timeout;
85
+ http.open_timeout = @connect_timeout;
86
+
87
+ if(uri.scheme == 'https')
88
+ # enable SSL
89
+ http.use_ssl = true
90
+
91
+ # if we haven't been given CA certificates to check, disable certificate verification (otherwise we'll get repeated warnings to STDOUT)
92
+ if @ca_file.nil?
93
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
94
+ else
95
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
96
+ http.ca_file = @ca_file
97
+ end
98
+
99
+ # negotiate with the client certificate, if one is present
100
+ unless(cert.nil? || key.nil?)
101
+ http.cert = OpenSSL::X509::Certificate.new(cert)
102
+ http.key = OpenSSL::PKey::RSA.new(key)
103
+ end
104
+ end
105
+
106
+ if verb == 'GET'
107
+ request = Net::HTTP::Get.new("#{uri.path}?#{uri.query}", headers)
108
+ elsif verb == 'POST'
109
+ request = Net::HTTP::Post.new("#{uri.path}?#{uri.query}", headers)
110
+ request.set_form_data(query_map)
111
+ else
112
+ raise "Unrecognized http_verb: #{http_verb}"
113
+ end
114
+
115
+ http.start { |http|
116
+ http.request(request)
117
+ }
118
+
119
+ end
120
+
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,32 @@
1
+ #
2
+ # Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+
4
+ require 'amazon/coral/handler'
5
+
6
+ module Amazon
7
+ module Coral
8
+
9
+ # Preloads identity information into request objects. Useful if all
10
+ # requests through a client will utilize the same identity.
11
+ class IdentityHandler < Handler
12
+
13
+ # Instantiates an IdentityHandler with a hash of identity attributes
14
+ # to be contributed to the request's identity. Attributes specified
15
+ # here will not override those explicitly associated with a request.
16
+ def initialize(attributes)
17
+ @attributes = attributes.to_hash
18
+ end
19
+
20
+ def before(job)
21
+ identity = job.request[:identity]
22
+
23
+ # for each shared identity attribute, set it on the request's
24
+ # identity IFF no attribute with that key is already present
25
+ @attributes.each { |k,v|
26
+ identity[k] = v unless identity.has_key?(k)
27
+ }
28
+ end
29
+ end
30
+ end
31
+ end
32
+
@@ -0,0 +1,25 @@
1
+ #
2
+ # Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+
4
+ module Amazon
5
+ module Coral
6
+
7
+ class Job
8
+ def initialize(request)
9
+ @request = request
10
+ @reply = {}
11
+ end
12
+
13
+ # Returns the hash of request attributes
14
+ def request
15
+ @request
16
+ end
17
+
18
+ # Returns the hash of reply attributes
19
+ def reply
20
+ @reply
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ #
2
+ # Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+
4
+ require 'logger'
5
+
6
+ module Amazon
7
+ module Coral
8
+
9
+ # A simple log retrieval interface to allow injection of common logging frameworks.
10
+ class LogFactory
11
+
12
+ @@instance = LogFactory.new
13
+
14
+ # Invokes the singleton LogFactory instance to retrieve a logger for a given key.
15
+ def LogFactory.getLog(key)
16
+ return @@instance.getLog(key)
17
+ end
18
+
19
+ # Specifies a LogFactory instance which will handle log requests.
20
+ # Call this method early in execution prior to instantiating handlers to replace the default no-op log.
21
+ def LogFactory.setInstance(instance)
22
+ @@instance = instance
23
+ end
24
+
25
+ # Default logging implementation which returns a null logger.
26
+ def getLog(key)
27
+ log = Logger.new(nil)
28
+ log.level = Logger::FATAL
29
+ return log
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,70 @@
1
+ # Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+
3
+ module Amazon
4
+ module Coral
5
+
6
+ # A simple library for processing command line arguments.
7
+ class Option
8
+ def initialize(args)
9
+ @long = args[:long]
10
+ @short = args[:short]
11
+ @num_parameters = args[:parameters]
12
+ @description = args[:description]
13
+ end
14
+
15
+ # Returns the long form of this option's name
16
+ def long
17
+ @long
18
+ end
19
+ # Returns the short form of this option's name
20
+ def short
21
+ @short
22
+ end
23
+ # Returns a text description of this option, if present
24
+ def description
25
+ @description
26
+ end
27
+
28
+ # Consume the arguments of this option from the argument vector and store them in the provided hash
29
+ # Returns the incremented counter of current position within the argument vector.
30
+ def consume(argv, i, hash)
31
+ i = i + 1
32
+ hash[@long] = []
33
+ unless @num_parameters.nil?
34
+ @num_parameters.times do
35
+ raise "Option #{@long} requires #{@num_parameters} parameter(s)" if argv.length <= i
36
+ hash[@long] << argv[i]
37
+ i = i + 1
38
+ end
39
+ end
40
+
41
+ return i
42
+ end
43
+
44
+ # Using the provided list of arguments (defined as Option objects), parse the given argument vector.
45
+ def Option.parse(arguments, argv)
46
+ long_map = {}
47
+ short_map = {}
48
+ arguments.each { |p|
49
+ long_map["--#{p.long}"] = p unless p.long.nil?
50
+ short_map["-#{p.short}"] = p unless p.short.nil?
51
+ }
52
+
53
+
54
+ h = {}
55
+ i = 0
56
+ while i < argv.length
57
+ arg = argv[i]
58
+ a = long_map[arg]
59
+ a = short_map[arg] if a.nil?
60
+ raise "Unrecognized argument '#{arg}'" if a.nil?
61
+
62
+ i = a.consume(argv, i, h)
63
+ end
64
+
65
+ return h
66
+ end
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,49 @@
1
+ #
2
+ # Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+
4
+ require 'amazon/coral/job'
5
+ require 'amazon/coral/logfactory'
6
+
7
+ module Amazon
8
+ module Coral
9
+
10
+ # Directs a Job through a Handler chain for processing.
11
+ class Orchestrator
12
+
13
+ # Instantiate an orchestrator with the given list of Handlers.
14
+ def initialize(handlers)
15
+ @log = LogFactory.getLog('Amazon::Coral::Orchestrator')
16
+ @handlers = handlers
17
+
18
+ @log.info "Initialized with handlers: #{handlers}"
19
+ end
20
+
21
+ # Direct the specified request down the Handler chain, invoking first each before method,
22
+ # then in reverse order each after method. If any exceptions are thrown along the way, orchestration
23
+ # will stop immediately.
24
+ def orchestrate(request)
25
+ @log.debug "Processing request #{request}"
26
+
27
+ job = Job.new(request)
28
+
29
+ stack = []
30
+
31
+ @handlers.each { |handler|
32
+ stack << handler
33
+
34
+ @log.debug "Invoking #{handler}.before()"
35
+ handler.before(job)
36
+ }
37
+
38
+ stack.reverse.each { |handler|
39
+ @log.debug "Invoking #{handler}.after()"
40
+ handler.after(job)
41
+ }
42
+
43
+ return job.reply
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end