elasticity 1.2.2 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (25) hide show
  1. data/{README.mediawiki → README.md} +34 -32
  2. data/elasticity.gemspec +0 -2
  3. data/lib/elasticity/aws_request.rb +11 -4
  4. data/lib/elasticity/emr.rb +12 -5
  5. data/lib/elasticity/job_flow.rb +31 -21
  6. data/lib/elasticity/job_flow_step.rb +22 -19
  7. data/lib/elasticity/version.rb +1 -1
  8. data/spec/fixtures/vcr_cassettes/add_instance_groups/one_group_successful.yml +2 -2
  9. data/spec/fixtures/vcr_cassettes/add_instance_groups/one_group_unsuccessful.yml +1 -1
  10. data/spec/fixtures/vcr_cassettes/add_jobflow_steps/add_multiple_steps.yml +3 -3
  11. data/spec/fixtures/vcr_cassettes/describe_jobflows/all_jobflows.yml +2 -2
  12. data/spec/fixtures/vcr_cassettes/direct/terminate_jobflow.yml +1 -1
  13. data/spec/fixtures/vcr_cassettes/hive_job/hive_ads.yml +1 -1
  14. data/spec/fixtures/vcr_cassettes/modify_instance_groups/set_instances_to_3.yml +2 -2
  15. data/spec/fixtures/vcr_cassettes/pig_job/apache_log_reports.yml +2 -2
  16. data/spec/fixtures/vcr_cassettes/pig_job/apache_log_reports_with_bootstrap.yml +1 -1
  17. data/spec/fixtures/vcr_cassettes/run_jobflow/word_count.yml +1 -1
  18. data/spec/fixtures/vcr_cassettes/set_termination_protection/nonexistent_job_flows.yml +2 -2
  19. data/spec/fixtures/vcr_cassettes/set_termination_protection/protect_multiple_job_flows.yml +2 -2
  20. data/spec/fixtures/vcr_cassettes/terminate_jobflows/one_jobflow.yml +1 -1
  21. data/spec/lib/elasticity/aws_request_spec.rb +48 -2
  22. data/spec/lib/elasticity/emr_spec.rb +9 -1
  23. data/spec/lib/elasticity/job_flow_spec.rb +69 -1
  24. data/spec/lib/elasticity/job_flow_step_spec.rb +15 -1
  25. metadata +6 -6
@@ -1,10 +1,14 @@
1
1
  Elasticity provides programmatic access to Amazon's Elastic Map Reduce service. The aim is to conveniently wrap the API operations in a manner that makes working with EMR job flows from Ruby more productive and more enjoyable, without having to understand the nuts and bolts of the EMR REST API. At the very least, using Elasticity allows you to easily experiment with the EMR API :)
2
2
 
3
- '''BACKLOG''': Have a look at the [https://www.pivotaltracker.com/projects/272429 backlog] to see where this is headed.
3
+ **BACKLOG**: Have a look at the [backlog](https://www.pivotaltracker.com/projects/272429) to see where this is headed.
4
4
 
5
- '''CREDITS''': AWS signing was used from [http://www.rightscale.com/ RightScale's] amazing [https://github.com/rightscale/right_aws right_aws gem] which works extraordinarily well! If you need access to any AWS service (EC2, S3, etc.), have a look. Used camelize from ActiveSupport as well, thank you \Rails :)
5
+ **CREDITS**: AWS signing was used from [RightScale's](http://www.rightscale.com/) amazing [right_aws gem](https://github.com/rightscale/right_aws) which works extraordinarily well! If you need access to any AWS service (EC2, S3, etc.), have a look. Used camelize from ActiveSupport as well, thank you \Rails :)
6
6
 
7
- = Installation and Usage =
7
+ **CONTRIBUTIONS**:
8
+
9
+ + [Wouter Broekhof](https://github.com/wouter/) - HTTPS and AWS region support, additional params to describe_jobflows.
10
+
11
+ # Installation and Usage
8
12
 
9
13
  <pre>
10
14
  gem install elasticity
@@ -12,7 +16,7 @@ Elasticity provides programmatic access to Amazon's Elastic Map Reduce service.
12
16
 
13
17
  All you have to do is <code>require 'elasticity'</code> and you're all set!
14
18
 
15
- = Simplified API Reference =
19
+ # Simplified API Reference
16
20
 
17
21
  Elasticity currently provides simplified access to launching Hive and Pig job flows, specifying several default values that you may optionally override:
18
22
 
@@ -28,7 +32,7 @@ Elasticity currently provides simplified access to launching Hive and Pig job fl
28
32
 
29
33
  These are all accessible from HiveJob and PigJob. See the PigJob description for an example.
30
34
 
31
- === Bootstrap Actions ===
35
+ ### Bootstrap Actions
32
36
 
33
37
  You can also configure Hadoop options with add_hadoop_bootstrap_action().
34
38
 
@@ -38,7 +42,7 @@ You can also configure Hadoop options with add_hadoop_bootstrap_action().
38
42
  ...
39
43
  </pre>
40
44
 
41
- == Hive ==
45
+ ## Hive
42
46
 
43
47
  HiveJob allows you to quickly launch Hive jobs without having to understand the ins and outs of the EMR API. Specify only the Hive script location and (optionally) variables to make available to the Hive script.
44
48
 
@@ -52,7 +56,7 @@ HiveJob allows you to quickly launch Hive jobs without having to understand the
52
56
  > "j-129V5AQFMKO1C"
53
57
  </pre>
54
58
 
55
- == Pig ==
59
+ ## Pig
56
60
 
57
61
  Like HiveJob, PigJob allows you to quickly launch Pig jobs :)
58
62
 
@@ -68,9 +72,9 @@ Like HiveJob, PigJob allows you to quickly launch Pig jobs :)
68
72
  > "j-16PZ24OED71C6"
69
73
  </pre>
70
74
 
71
- === PARALLEL ===
75
+ ### PARALLEL
72
76
 
73
- Given the importance of specifying a reasonable value for [http://pig.apache.org/docs/r0.8.1/cookbook.html#Use+the+Parallel+Features PARALLEL] (the number of parallel reducers), Elasticity calculates and passes through a reasonable default up with every invocation in the form of a script variable called E_PARALLELS. This default value is based off of the formula in the Pig Cookbook and the number of reducers AWS configures per instance.
77
+ Given the importance of specifying a reasonable value for [the number of parallel reducers](http://pig.apache.org/docs/r0.8.1/cookbook.html#Use+the+Parallel+Features PARALLEL), Elasticity calculates and passes through a reasonable default up with every invocation in the form of a script variable called E_PARALLELS. This default value is based off of the formula in the Pig Cookbook and the number of reducers AWS configures per instance.
74
78
 
75
79
  For example, if you had 8 instances in total and your slaves were m1.xlarge, the value is 26 (as shown below).
76
80
 
@@ -92,21 +96,21 @@ Use this as you would any other Pig variable.
92
96
  ...
93
97
  </pre>
94
98
 
95
- = Amazon API Reference =
99
+ # Amazon API Reference
96
100
 
97
101
  Elasticity wraps all of the EMR API calls. Please see the Amazon guide for details on these operations because the default values aren't obvious (e.g. the meaning of <code>DescribeJobFlows</code> without parameters).
98
102
 
99
103
  You may opt for "direct" access to the API where you specify the params and Elasticity takes care of the signing for you, responding with the XML from Amazon. Direct access is described below the API catalog.
100
104
 
101
- In addition to the [http://aws.amazon.com/elasticmapreduce/ AWS EMR subsite], there are three primary resources of reference information for EMR:
105
+ In addition to the [AWS EMR subsite](http://aws.amazon.com/elasticmapreduce/), there are three primary resources of reference information for EMR:
102
106
 
103
- * [http://docs.amazonwebservices.com/ElasticMapReduce/latest/GettingStartedGuide/ Amazon EMR Getting Started Guide]
104
- * [http://docs.amazonwebservices.com/ElasticMapReduce/latest/DeveloperGuide/ Amazon EMR Developer Guide]
105
- * [http://docs.amazonwebservices.com/ElasticMapReduce/latest/API/ Amazon EMR API Reference]
107
+ * [Amazon EMR Getting Started Guide](http://docs.amazonwebservices.com/ElasticMapReduce/latest/GettingStartedGuide/)
108
+ * [Amazon EMR Developer Guide](http://docs.amazonwebservices.com/ElasticMapReduce/latest/DeveloperGuide/)
109
+ * [Amazon EMR API Reference](http://docs.amazonwebservices.com/ElasticMapReduce/latest/API/)
106
110
 
107
- Unfortunately, the documentation is sometimes incorrect and sometimes missing. E.g. the allowable values for AddInstanceGroups are present in the [http://awsdocs.s3.amazonaws.com/ElasticMapReduce/20090331/emr-api-20090331.pdf PDF] version of the API reference but not in the [http://docs.amazonwebservices.com/ElasticMapReduce/latest/API/ HTML] version. Elasticity implements the API as specified in the PDF reference as that is the most complete description I could find.
111
+ Unfortunately, the documentation is sometimes incorrect and sometimes missing. E.g. the allowable values for AddInstanceGroups are present in the [PDF](http://awsdocs.s3.amazonaws.com/ElasticMapReduce/20090331/emr-api-20090331.pdf) version of the API reference but not in the [HTML](http://docs.amazonwebservices.com/ElasticMapReduce/latest/API/) version. Elasticity implements the API as specified in the PDF reference as that is the most complete description I could find.
108
112
 
109
- == AddInstanceGroups ==
113
+ ## AddInstanceGroups
110
114
 
111
115
  AddInstanceGroups adds a group of instances to an existing job flow. The available instance configuration options are listed in the EMR API reference. They've been converted to be more Ruby-like in the wrappers, as shown in the example below.
112
116
 
@@ -132,7 +136,7 @@ Some combinations of the options will be rejected by Amazon and some once-valid
132
136
  > Task instance group already exists in the job flow, cannot add more task groups
133
137
  </pre>
134
138
 
135
- == AddJobFlowSteps ==
139
+ ## AddJobFlowSteps
136
140
 
137
141
  AddJobFlowSteps adds the specified steps to the specified job flow.
138
142
 
@@ -158,7 +162,7 @@ AddJobFlowSteps adds the specified steps to the specified job flow.
158
162
  })
159
163
  </pre>
160
164
 
161
- == DescribeJobFlows ==
165
+ ## DescribeJobFlows
162
166
 
163
167
  DescribeJobFlows returns detailed information as to the state of all jobs. Currently this is wrapped in an <code>Elasticity::JobFlow</code> that contains the <code>name</code>, <code>jobflow_id</code> and <code>state</code>.
164
168
 
@@ -170,7 +174,7 @@ DescribeJobFlows returns detailed information as to the state of all jobs. Curr
170
174
  > ["Hive Test", "Pig Test", "Interactive Hadoop", "Interactive Hive"]
171
175
  </pre>
172
176
 
173
- == ModifyInstanceGroups ==
177
+ ## ModifyInstanceGroups
174
178
 
175
179
  A job flow contains several "instance groups" of various types. These instances are where the work for your EMR task occurs. After a job flow has been created, you can find these instance groups in the AWS web UI by clicking on a job flow and then clicking on the "Instance Groups" tab.
176
180
 
@@ -197,7 +201,7 @@ Or if you attempt to increase the instance count of the MASTER instance group:
197
201
  > ArgumentError: A master instance group may not be modified
198
202
  </pre>
199
203
 
200
- == RunJobFlow ==
204
+ ## RunJobFlow
201
205
 
202
206
  RunJobFlow creates and starts a new job flow. Specifying the arguments to RunJobFlow is a bit of a hot mess at the moment, requiring you to understand the EMR syntax as well as the data structure for specifying jobs. Here's a beefy example:
203
207
 
@@ -252,9 +256,9 @@ RunJobFlow creates and starts a new job flow. Specifying the arguments to RunJo
252
256
  > "j-129V5AQFMKO1C"
253
257
  </pre>
254
258
 
255
- Currently Elasticity doesn't do much to ease this pain although this is what I would like to focus on in coming releases. Feel free to ship ideas my way. In the meantime, have a look at the EMR API [http://awsdocs.s3.amazonaws.com/ElasticMapReduce/20090331/emr-api-20090331.pdf PDF] under the RunJobFlow action and riff off of the example here.
259
+ Currently Elasticity doesn't do much to ease this pain although this is what I would like to focus on in coming releases. Feel free to ship ideas my way. In the meantime, have a look at the EMR API [PDF](http://awsdocs.s3.amazonaws.com/ElasticMapReduce/20090331/emr-api-20090331.pdf) under the RunJobFlow action and riff off of the example here.
256
260
 
257
- == SetTerminationProtection ==
261
+ ## SetTerminationProtection
258
262
 
259
263
  Enable or disable "termination protection" on the specified job flows. Termination protection prevents a job flow from from being terminated by any user-initiated action.
260
264
 
@@ -269,7 +273,7 @@ To disable termination protection, specify false as the second parameter.
269
273
  emr.set_termination_protection(["j-1B4D1XP0C0A35", "j-1YG2MYL0HVYS5"], false)
270
274
  </pre>
271
275
 
272
- == TerminateJobFlows ==
276
+ ## TerminateJobFlows
273
277
 
274
278
  Terminate the specified job flow. When the job flow '''exists''', you will receive no output. This is because Amazon does not return anything other than a 200 when you terminate a job flow :) You'll want to continuously poll with DescribeJobFlows to see when the job was actually terminated.
275
279
 
@@ -287,7 +291,7 @@ When the job flow '''doesn't exist''':
287
291
  > ArgumentError: Job flow 'no-flow' does not exist.
288
292
  </pre>
289
293
 
290
- = Direct Response Access =
294
+ # Direct Response Access
291
295
 
292
296
  If you're fine with Elasticity's invocation wrapping and would prefer to get at the resulting XML rather than the wrapped response, throw a block our way and we'll yield the result. This still saves you the trouble of having to create the params and sign the request yet gives you direct access to the response XML for your parsing pleasure.
293
297
 
@@ -295,12 +299,12 @@ If you're fine with Elasticity's invocation wrapping and would prefer to get at
295
299
  emr = Elasticity::EMR.new(ENV["AWS_ACCESS_KEY_ID"], ENV["AWS_SECRET_KEY"])
296
300
  emr.describe_jobflows{|xml| puts xml[0..77]}
297
301
 
298
- > <DescribeJobFlowsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/200
302
+ > &lt;DescribeJobFlowsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/200...
299
303
  </pre>
300
304
 
301
- = Direct Request/Response Access =
305
+ # Direct Request/Response Access
302
306
 
303
- If you're chomping at the bit to initiate some EMR functionality that isn't wrapped (or isn't wrapped in a way you prefer :) feel free to access the AWS EMR API directly by using <code>EMR.direct()</code>. You can find the allowed values in Amazon's EMR API [http://docs.amazonwebservices.com/ElasticMapReduce/latest/DeveloperGuide/index.html developer documentation].
307
+ If you're chomping at the bit to initiate some EMR functionality that isn't wrapped (or isn't wrapped in a way you prefer :) feel free to access the AWS EMR API directly by using <code>EMR.direct()</code>. You can find the allowed values in Amazon's EMR API [developer documentation](http://docs.amazonwebservices.com/ElasticMapReduce/latest/DeveloperGuide/index.html).
304
308
 
305
309
  <pre>
306
310
  emr = Elasticity::EMR.new(ENV["AWS_ACCESS_KEY_ID"], ENV["AWS_SECRET_KEY"])
@@ -308,10 +312,10 @@ If you're chomping at the bit to initiate some EMR functionality that isn't wrap
308
312
  result_xml = emr.direct(params)
309
313
  result_xml[0..78]
310
314
 
311
- > <DescribeJobFlowsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009
315
+ > &lt;DescribeJobFlowsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009...
312
316
  </pre>
313
317
 
314
- = License =
318
+ # License
315
319
 
316
320
  <pre>
317
321
  Copyright 2011 Robert Slifka
@@ -327,6 +331,4 @@ If you're chomping at the bit to initiate some EMR functionality that isn't wrap
327
331
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
328
332
  See the License for the specific language governing permissions and
329
333
  limitations under the License.
330
- </pre>
331
-
332
- <!-- __NOTOC__ -->
334
+ </pre>
data/elasticity.gemspec CHANGED
@@ -11,8 +11,6 @@ Gem::Specification.new do |s|
11
11
  s.summary = %q{Programmatic access to Amazon's Elastic Map Reduce service.}
12
12
  s.description = %q{Programmatic access to Amazon's Elastic Map Reduce service.}
13
13
 
14
- s.rubyforge_project = "elasticity"
15
-
16
14
  s.add_dependency("rest-client")
17
15
  s.add_dependency("nokogiri")
18
16
 
@@ -2,14 +2,21 @@ module Elasticity
2
2
 
3
3
  class AwsRequest
4
4
 
5
- def initialize(aws_access_key_id, aws_secret_access_key)
5
+ # Supported values for options:
6
+ # :region - AWS region (e.g. us-west-1)
7
+ # :secure - true or false, default true.
8
+ def initialize(aws_access_key_id, aws_secret_access_key, options = {})
6
9
  @access_key = aws_access_key_id
7
10
  @secret_key = aws_secret_access_key
11
+ @options = {:secure => true}.merge(options)
8
12
  end
9
13
 
10
14
  def aws_emr_request(params)
11
- signed_params = sign_params(params, "GET", "elasticmapreduce.amazonaws.com", "/")
12
- signed_request = "http://elasticmapreduce.amazonaws.com?#{signed_params}"
15
+ host = @options[:region] ? "elasticmapreduce.#{@options[:region]}.amazonaws.com" : "elasticmapreduce.amazonaws.com"
16
+ protocol = @options[:secure] ? "https" : "http"
17
+
18
+ signed_params = sign_params(params, "GET", host, "/")
19
+ signed_request = "#{protocol}://#{host}?#{signed_params}"
13
20
  RestClient.get signed_request
14
21
  end
15
22
 
@@ -45,4 +52,4 @@ module Elasticity
45
52
 
46
53
  end
47
54
 
48
- end
55
+ end
@@ -2,13 +2,20 @@ module Elasticity
2
2
 
3
3
  class EMR
4
4
 
5
- def initialize(aws_access_key_id, aws_secret_access_key)
6
- @aws_request = Elasticity::AwsRequest.new(aws_access_key_id, aws_secret_access_key)
5
+ def initialize(aws_access_key_id, aws_secret_access_key, options = {})
6
+ @aws_request = Elasticity::AwsRequest.new(aws_access_key_id, aws_secret_access_key, options)
7
7
  end
8
8
 
9
9
  # Lists all jobflows in all states.
10
- def describe_jobflows
11
- aws_result = @aws_request.aws_emr_request(EMR.convert_ruby_to_aws(:operation => "DescribeJobFlows"))
10
+ #
11
+ # To override this behaviour, pass additional filters as specified in the AWS
12
+ # documentation - http://docs.amazonwebservices.com/ElasticMapReduce/latest/API/index.html?API_DescribeJobFlows.html.
13
+ #
14
+ # describe_jobflows(:CreatedBefore => "2011-10-04")
15
+ def describe_jobflows(params = {})
16
+ aws_result = @aws_request.aws_emr_request(EMR.convert_ruby_to_aws(
17
+ params.merge({:operation => "DescribeJobFlows"}))
18
+ )
12
19
  xml_doc = Nokogiri::XML(aws_result)
13
20
  xml_doc.remove_namespaces!
14
21
  yield aws_result if block_given?
@@ -31,7 +38,7 @@ module Elasticity
31
38
  #
32
39
  # add_instance_groups takes an array of {}. Returns an array of the instance IDs
33
40
  # that were created by the specified configs.
34
- #
41
+ #
35
42
  # ["ig-2GOVEN6HVJZID", "ig-1DU9M2UQMM051", "ig-3DZRW4Y2X4S", ...]
36
43
  def add_instance_groups(jobflow_id, instance_group_configs)
37
44
  params = {
@@ -6,34 +6,44 @@ module Elasticity
6
6
  attr_accessor :jobflow_id
7
7
  attr_accessor :state
8
8
  attr_accessor :steps
9
+ attr_accessor :created_at
10
+ attr_accessor :started_at
11
+ attr_accessor :ready_at
12
+ attr_accessor :instance_count
13
+ attr_accessor :master_instance_type
14
+ attr_accessor :slave_instance_type
9
15
 
10
16
  def initialize
11
17
  @steps = []
12
18
  end
13
19
 
14
- class << self
15
-
16
- # Create a jobflow from an AWS <member> (Nokogiri::XML::Element):
17
- # /DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows/member
18
- def from_member_element(xml_element)
19
- jobflow = JobFlow.new
20
- jobflow.name = xml_element.xpath("./Name").text
21
- jobflow.jobflow_id = xml_element.xpath("./JobFlowId").text
22
- jobflow.state = xml_element.xpath("./ExecutionStatusDetail/State").text
23
- jobflow.steps = JobFlowStep.from_members_nodeset(xml_element.xpath("./Steps/member"))
24
- jobflow
25
- end
20
+ # Create a jobflow from an AWS <member> (Nokogiri::XML::Element):
21
+ # /DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows/member
22
+ def self.from_member_element(xml_element)
23
+ jobflow = JobFlow.new
24
+ jobflow.name = xml_element.xpath("./Name").text.strip
25
+ jobflow.jobflow_id = xml_element.xpath("./JobFlowId").text.strip
26
+ jobflow.state = xml_element.xpath("./ExecutionStatusDetail/State").text.strip
27
+ jobflow.steps = JobFlowStep.from_members_nodeset(xml_element.xpath("./Steps/member"))
28
+ jobflow.created_at = Time.parse(xml_element.xpath("./ExecutionStatusDetail/CreationDateTime").text.strip)
29
+ started_at = xml_element.xpath("./ExecutionStatusDetail/StartDateTime").text.strip
30
+ jobflow.started_at = (started_at == "") ? (nil) : (Time.parse(started_at))
31
+ ready_at = xml_element.xpath("./ExecutionStatusDetail/ReadyDateTime").text.strip
32
+ jobflow.ready_at = (ready_at == "") ? (nil) : (Time.parse(ready_at))
33
+ jobflow.instance_count = xml_element.xpath("./Instances/InstanceCount").text.strip
34
+ jobflow.master_instance_type = xml_element.xpath("./Instances/MasterInstanceType").text.strip
35
+ jobflow.slave_instance_type = xml_element.xpath("./Instances/SlaveInstanceType").text.strip
36
+ jobflow
37
+ end
26
38
 
27
- # Create JobFlows from a collection of AWS <member> nodes (Nokogiri::XML::NodeSet):
28
- # /DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows
29
- def from_members_nodeset(members_nodeset)
30
- jobflows = []
31
- members_nodeset.each do |member|
32
- jobflows << from_member_element(member)
33
- end
34
- jobflows
39
+ # Create JobFlows from a collection of AWS <member> nodes (Nokogiri::XML::NodeSet):
40
+ # /DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows
41
+ def self.from_members_nodeset(members_nodeset)
42
+ jobflows = []
43
+ members_nodeset.each do |member|
44
+ jobflows << from_member_element(member)
35
45
  end
36
-
46
+ jobflows
37
47
  end
38
48
 
39
49
  end
@@ -4,29 +4,32 @@ module Elasticity
4
4
 
5
5
  attr_accessor :name
6
6
  attr_accessor :state
7
+ attr_accessor :started_at
8
+ attr_accessor :ended_at
7
9
 
8
- class << self
9
-
10
- # Create a job flow from an AWS <member> (Nokogiri::XML::Element):
11
- # /DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows/member/Steps/member
12
- def from_member_element(xml_element)
13
- job_flow_step = JobFlowStep.new
14
- job_flow_step.name = xml_element.xpath("./StepConfig/Name").text
15
- job_flow_step.state = xml_element.xpath("./ExecutionStatusDetail/State").text
16
- job_flow_step
17
- end
10
+ # Create a job flow from an AWS <member> (Nokogiri::XML::Element):
11
+ # /DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows/member/Steps/member
12
+ def self.from_member_element(xml_element)
13
+ job_flow_step = JobFlowStep.new
14
+ job_flow_step.name = xml_element.xpath("./StepConfig/Name").text.strip
15
+ job_flow_step.state = xml_element.xpath("./ExecutionStatusDetail/State").text.strip
16
+ started_at = xml_element.xpath("./ExecutionStatusDetail/StartDateTime").text.strip
17
+ job_flow_step.started_at = (started_at == "") ? (nil) : (Time.parse(started_at))
18
+ ended_at = xml_element.xpath("./ExecutionStatusDetail/EndDateTime").text.strip
19
+ job_flow_step.ended_at = (ended_at == "") ? (nil) : (Time.parse(ended_at))
20
+ job_flow_step
21
+ end
18
22
 
19
- # Create JobFlowSteps from a collection of AWS <member> nodes (Nokogiri::XML::NodeSet):
20
- # /DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows/member/Steps/member
21
- def from_members_nodeset(members_nodeset)
22
- jobflow_steps = []
23
- members_nodeset.each do |member|
24
- jobflow_steps << from_member_element(member)
25
- end
26
- jobflow_steps
23
+ # Create JobFlowSteps from a collection of AWS <member> nodes (Nokogiri::XML::NodeSet):
24
+ # /DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows/member/Steps/member
25
+ def self.from_members_nodeset(members_nodeset)
26
+ jobflow_steps = []
27
+ members_nodeset.each do |member|
28
+ jobflow_steps << from_member_element(member)
27
29
  end
30
+ jobflow_steps
28
31
  end
29
32
 
30
33
  end
31
34
 
32
- end
35
+ end
@@ -1,3 +1,3 @@
1
1
  module Elasticity
2
- VERSION = "1.2.2"
2
+ VERSION = "1.2.3"
3
3
  end
@@ -2,8 +2,8 @@
2
2
  - !ruby/struct:VCR::HTTPInteraction
3
3
  request: !ruby/struct:VCR::Request
4
4
  method: :get
5
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?AWSAccessKeyId=AKIAI7HEMMNKGT6VFFSA&InstanceGroups.member.1.InstanceCount=1&InstanceGroups.member.1.InstanceRole=TASK&InstanceGroups.member.1.InstanceType=m1.small&InstanceGroups.member.1.Market=ON_DEMAND&InstanceGroups.member.1.Name=Go%20Canucks%20Go!&JobFlowId=j-OALI7TZTQMHX&Operation=AddInstanceGroups/
6
- body:
5
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?AWSAccessKeyId=\S+&InstanceGroups.member.1.InstanceCount=1&InstanceGroups.member.1.InstanceRole=TASK&InstanceGroups.member.1.InstanceType=m1.small&InstanceGroups.member.1.Market=ON_DEMAND&InstanceGroups.member.1.Name=Go%20Canucks%20Go!&JobFlowId=j-OALI7TZTQMHX&Operation=AddInstanceGroups/
6
+ body:
7
7
  headers:
8
8
  accept:
9
9
  - "*/*; q=0.5, application/xml"
@@ -2,7 +2,7 @@
2
2
  - !ruby/struct:VCR::HTTPInteraction
3
3
  request: !ruby/struct:VCR::Request
4
4
  method: :get
5
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?AWSAccessKeyId=AKIAI7HEMMNKGT6VFFSA&InstanceGroups.member.1.BidPrice=0&InstanceGroups.member.1.InstanceCount=1&InstanceGroups.member.1.InstanceRole=TASK&InstanceGroups.member.1.InstanceType=m1.small&InstanceGroups.member.1.Market=ON_DEMAND&InstanceGroups.member.1.Name=Go%20Canucks%20Go!&JobFlowId=j-19WDDS68ZUENP&Operation=AddInstanceGroups/
5
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?AWSAccessKeyId=\S+&InstanceGroups.member.1.BidPrice=0&InstanceGroups.member.1.InstanceCount=1&InstanceGroups.member.1.InstanceRole=TASK&InstanceGroups.member.1.InstanceType=m1.small&InstanceGroups.member.1.Market=ON_DEMAND&InstanceGroups.member.1.Name=Go%20Canucks%20Go!&JobFlowId=j-19WDDS68ZUENP&Operation=AddInstanceGroups/
6
6
  body:
7
7
  headers:
8
8
  accept:
@@ -2,7 +2,7 @@
2
2
  - !ruby/struct:VCR::HTTPInteraction
3
3
  request: !ruby/struct:VCR::Request
4
4
  method: :get
5
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?.*Operation=RunJobFlow/
5
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?.*Operation=RunJobFlow/
6
6
  body:
7
7
  headers:
8
8
  accept:
@@ -36,7 +36,7 @@
36
36
  - !ruby/struct:VCR::HTTPInteraction
37
37
  request: !ruby/struct:VCR::Request
38
38
  method: :get
39
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?.*Operation=AddJobFlowSteps/
39
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?.*Operation=AddJobFlowSteps/
40
40
  body:
41
41
  headers:
42
42
  accept:
@@ -67,7 +67,7 @@
67
67
  - !ruby/struct:VCR::HTTPInteraction
68
68
  request: !ruby/struct:VCR::Request
69
69
  method: :get
70
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?.*Operation=DescribeJobFlows/
70
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?.*Operation=DescribeJobFlows/
71
71
  body:
72
72
  headers:
73
73
  accept:
@@ -2,8 +2,8 @@
2
2
  - !ruby/struct:VCR::HTTPInteraction
3
3
  request: !ruby/struct:VCR::Request
4
4
  method: :get
5
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?AWSAccessKeyId=AKIAI7HEMMNKGT6VFFSA&Operation=DescribeJobFlows/
6
- body:
5
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?AWSAccessKeyId=\S+&Operation=DescribeJobFlows/
6
+ body:
7
7
  headers:
8
8
  accept:
9
9
  - "*/*; q=0.5, application/xml"
@@ -2,7 +2,7 @@
2
2
  - !ruby/struct:VCR::HTTPInteraction
3
3
  request: !ruby/struct:VCR::Request
4
4
  method: :get
5
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?AWSAccessKeyId=AKIAI7HEMMNKGT6VFFSA&JobFlowIds.member.1=j-1MZ5TVWFJRSKN&Operation=TerminateJobFlows/
5
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?AWSAccessKeyId=\S+&JobFlowIds.member.1=j-1MZ5TVWFJRSKN&Operation=TerminateJobFlows/
6
6
  body:
7
7
  headers:
8
8
  accept:
@@ -2,7 +2,7 @@
2
2
  - !ruby/struct:VCR::HTTPInteraction
3
3
  request: !ruby/struct:VCR::Request
4
4
  method: :get
5
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?AWSAccessKeyId=AKIAI7HEMMNKGT6VFFSA&Instances\.Ec2KeyName=sharethrough_dev&Instances\.HadoopVersion=0\.20&Instances\.InstanceCount=2&Instances\.MasterInstanceType=m1\.small&Instances\.SlaveInstanceType=m1\.small&Name=Elasticity%20Hive%20Job&Operation=RunJobFlow&.*&Steps\.member\.1\.ActionOnFailure=TERMINATE_JOB_FLOW&Steps\.member\.1\.HadoopJarStep\.Args\.member\.1=s3:\/\/elasticmapreduce\/libs\/hive\/hive-script&Steps\.member\.1\.HadoopJarStep\.Args\.member\.2=--base-path&Steps\.member\.1\.HadoopJarStep\.Args\.member\.3=s3:\/\/elasticmapreduce\/libs\/hive\/&Steps\.member\.1\.HadoopJarStep\.Args\.member\.4=--install-hive&Steps\.member\.1\.HadoopJarStep\.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner\.jar&Steps\.member\.1\.Name=Setup%20Hive&Steps\.member\.2\.ActionOnFailure=TERMINATE_JOB_FLOW&Steps\.member\.2\.HadoopJarStep\.Args\.member\.1=s3:\/\/elasticmapreduce\/libs\/hive\/hive-script&Steps\.member\.2\.HadoopJarStep\.Args\.member\.10=-d&Steps\.member\.2\.HadoopJarStep\.Args\.member\.11=LIBS=s3n:\/\/elasticmapreduce\/samples\/hive-ads\/libs&Steps\.member\.2\.HadoopJarStep\.Args\.member\.2=--run-hive-script&Steps\.member\.2\.HadoopJarStep\.Args\.member\.3=--args&Steps\.member\.2\.HadoopJarStep\.Args\.member\.4=-f&Steps\.member\.2\.HadoopJarStep\.Args\.member\.5=s3n:\/\/elasticmapreduce\/samples\/hive-ads\/libs\/model-build\.q&Steps\.member\.2\.HadoopJarStep\.Args\.member\.6=-d&Steps\.member\.2\.HadoopJarStep\.Args\.member\.7=INPUT=s3n:\/\/elasticmapreduce\/samples\/hive-ads\/tables&Steps\.member\.2\.HadoopJarStep\.Args\.member\.8=-d&Steps\.member\.2\.HadoopJarStep\.Args\.member\.9=OUTPUT=s3n:\/\/slif-elasticity\/hive-ads\/output\/2011-04-19&Steps\.member\.2\.HadoopJarStep\.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner\.jar&Steps\.member\.2\.Name=Run%20Hive%20Script/
5
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?AWSAccessKeyId=\S+&Instances\.Ec2KeyName=sharethrough_dev&Instances\.HadoopVersion=0\.20&Instances\.InstanceCount=2&Instances\.MasterInstanceType=m1\.small&Instances\.SlaveInstanceType=m1\.small&Name=Elasticity%20Hive%20Job&Operation=RunJobFlow&.*&Steps\.member\.1\.ActionOnFailure=TERMINATE_JOB_FLOW&Steps\.member\.1\.HadoopJarStep\.Args\.member\.1=s3:\/\/elasticmapreduce\/libs\/hive\/hive-script&Steps\.member\.1\.HadoopJarStep\.Args\.member\.2=--base-path&Steps\.member\.1\.HadoopJarStep\.Args\.member\.3=s3:\/\/elasticmapreduce\/libs\/hive\/&Steps\.member\.1\.HadoopJarStep\.Args\.member\.4=--install-hive&Steps\.member\.1\.HadoopJarStep\.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner\.jar&Steps\.member\.1\.Name=Setup%20Hive&Steps\.member\.2\.ActionOnFailure=TERMINATE_JOB_FLOW&Steps\.member\.2\.HadoopJarStep\.Args\.member\.1=s3:\/\/elasticmapreduce\/libs\/hive\/hive-script&Steps\.member\.2\.HadoopJarStep\.Args\.member\.10=-d&Steps\.member\.2\.HadoopJarStep\.Args\.member\.11=LIBS=s3n:\/\/elasticmapreduce\/samples\/hive-ads\/libs&Steps\.member\.2\.HadoopJarStep\.Args\.member\.2=--run-hive-script&Steps\.member\.2\.HadoopJarStep\.Args\.member\.3=--args&Steps\.member\.2\.HadoopJarStep\.Args\.member\.4=-f&Steps\.member\.2\.HadoopJarStep\.Args\.member\.5=s3n:\/\/elasticmapreduce\/samples\/hive-ads\/libs\/model-build\.q&Steps\.member\.2\.HadoopJarStep\.Args\.member\.6=-d&Steps\.member\.2\.HadoopJarStep\.Args\.member\.7=INPUT=s3n:\/\/elasticmapreduce\/samples\/hive-ads\/tables&Steps\.member\.2\.HadoopJarStep\.Args\.member\.8=-d&Steps\.member\.2\.HadoopJarStep\.Args\.member\.9=OUTPUT=s3n:\/\/slif-elasticity\/hive-ads\/output\/2011-04-19&Steps\.member\.2\.HadoopJarStep\.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner\.jar&Steps\.member\.2\.Name=Run%20Hive%20Script/
6
6
  body:
7
7
  headers:
8
8
  accept:
@@ -2,8 +2,8 @@
2
2
  - !ruby/struct:VCR::HTTPInteraction
3
3
  request: !ruby/struct:VCR::Request
4
4
  method: :get
5
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?AWSAccessKeyId=AKIAI7HEMMNKGT6VFFSA&InstanceGroups.member.1.InstanceCount=2&InstanceGroups.member.1.InstanceGroupId=ig-2T1HNUO61BG3O&Operation=ModifyInstanceGroups/
6
- body:
5
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?AWSAccessKeyId=\S+&InstanceGroups.member.1.InstanceCount=2&InstanceGroups.member.1.InstanceGroupId=ig-2T1HNUO61BG3O&Operation=ModifyInstanceGroups/
6
+ body:
7
7
  headers:
8
8
  accept:
9
9
  - "*/*; q=0.5, application/xml"
@@ -2,8 +2,8 @@
2
2
  - !ruby/struct:VCR::HTTPInteraction
3
3
  request: !ruby/struct:VCR::Request
4
4
  method: :get
5
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?AWSAccessKeyId=AKIAI7HEMMNKGT6VFFSA&Instances.Ec2KeyName=sharethrough_dev&Instances.HadoopVersion=0.20&Instances.InstanceCount=2&Instances.MasterInstanceType=m1.small&Instances.SlaveInstanceType=m1.small&LogUri=s3n:\/\/slif-elasticity\/pig-apache\/logs&Name=Elasticity%20Pig%20Job&Operation=RunJobFlow&.*&Steps.member.1.ActionOnFailure=TERMINATE_JOB_FLOW&Steps.member.1.HadoopJarStep.Args.member.1=s3:\/\/elasticmapreduce\/libs\/pig\/pig-script&Steps.member.1.HadoopJarStep.Args.member.2=--base-path&Steps.member.1.HadoopJarStep.Args.member.3=s3:\/\/elasticmapreduce\/libs\/pig\/&Steps.member.1.HadoopJarStep.Args.member.4=--install-pig&Steps.member.1.HadoopJarStep.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner.jar&Steps.member.1.Name=Setup%20Pig&Steps.member.2.ActionOnFailure=TERMINATE_JOB_FLOW&Steps.member.2.HadoopJarStep.Args.member.1=s3:\/\/elasticmapreduce\/libs\/pig\/pig-script&Steps.member.2.HadoopJarStep.Args.member.10=s3n:\/\/elasticmapreduce\/samples\/pig-apache\/do-reports.pig&Steps.member.2.HadoopJarStep.Args.member.2=--run-pig-script&Steps.member.2.HadoopJarStep.Args.member.3=--args&Steps.member.2.HadoopJarStep.Args.member.4=-p&Steps.member.2.HadoopJarStep.Args.member.5=INPUT=s3n:\/\/elasticmapreduce\/samples\/pig-apache\/input&Steps.member.2.HadoopJarStep.Args.member.6=-p&Steps.member.2.HadoopJarStep.Args.member.7=OUTPUT=s3n:\/\/slif-elasticity\/pig-apache\/output\/2011-05-04&Steps.member.2.HadoopJarStep.Args.member.8=-p&Steps.member.2.HadoopJarStep.Args.member.9=E_PARALLELS=1&Steps.member.2.HadoopJarStep.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner.jar&Steps.member.2.Name=Run%20Pig%20Script/
6
- body:
5
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?AWSAccessKeyId=\S+&Instances.Ec2KeyName=sharethrough_dev&Instances.HadoopVersion=0.20&Instances.InstanceCount=2&Instances.MasterInstanceType=m1.small&Instances.SlaveInstanceType=m1.small&LogUri=s3n:\/\/slif-elasticity\/pig-apache\/logs&Name=Elasticity%20Pig%20Job&Operation=RunJobFlow&.*&Steps.member.1.ActionOnFailure=TERMINATE_JOB_FLOW&Steps.member.1.HadoopJarStep.Args.member.1=s3:\/\/elasticmapreduce\/libs\/pig\/pig-script&Steps.member.1.HadoopJarStep.Args.member.2=--base-path&Steps.member.1.HadoopJarStep.Args.member.3=s3:\/\/elasticmapreduce\/libs\/pig\/&Steps.member.1.HadoopJarStep.Args.member.4=--install-pig&Steps.member.1.HadoopJarStep.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner.jar&Steps.member.1.Name=Setup%20Pig&Steps.member.2.ActionOnFailure=TERMINATE_JOB_FLOW&Steps.member.2.HadoopJarStep.Args.member.1=s3:\/\/elasticmapreduce\/libs\/pig\/pig-script&Steps.member.2.HadoopJarStep.Args.member.10=s3n:\/\/elasticmapreduce\/samples\/pig-apache\/do-reports.pig&Steps.member.2.HadoopJarStep.Args.member.2=--run-pig-script&Steps.member.2.HadoopJarStep.Args.member.3=--args&Steps.member.2.HadoopJarStep.Args.member.4=-p&Steps.member.2.HadoopJarStep.Args.member.5=INPUT=s3n:\/\/elasticmapreduce\/samples\/pig-apache\/input&Steps.member.2.HadoopJarStep.Args.member.6=-p&Steps.member.2.HadoopJarStep.Args.member.7=OUTPUT=s3n:\/\/slif-elasticity\/pig-apache\/output\/2011-05-04&Steps.member.2.HadoopJarStep.Args.member.8=-p&Steps.member.2.HadoopJarStep.Args.member.9=E_PARALLELS=1&Steps.member.2.HadoopJarStep.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner.jar&Steps.member.2.Name=Run%20Pig%20Script/
6
+ body:
7
7
  headers:
8
8
  accept:
9
9
  - "*/*; q=0.5, application/xml"
@@ -2,7 +2,7 @@
2
2
  - !ruby/struct:VCR::HTTPInteraction
3
3
  request: !ruby/struct:VCR::Request
4
4
  method: :get
5
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?AWSAccessKeyId=AKIAI7HEMMNKGT6VFFSA&BootstrapActions.member.1.Name=Elasticity%20Bootstrap%20Action%20\(Configure%20Hadoop\)&BootstrapActions.member.1.ScriptBootstrapAction.Args.member.1=-m&BootstrapActions.member.1.ScriptBootstrapAction.Args.member.2=mapred.job.reuse.jvm.num.tasks=120&BootstrapActions.member.1.ScriptBootstrapAction.Path=s3n:\/\/elasticmapreduce\/bootstrap-actions\/configure-hadoop&Instances.Ec2KeyName=sharethrough_dev&Instances.HadoopVersion=0.20&Instances.InstanceCount=2&Instances.MasterInstanceType=m1.small&Instances.SlaveInstanceType=m1.small&Name=Elasticity%20Pig%20Job&Operation=RunJobFlow&.*&Steps.member.1.ActionOnFailure=TERMINATE_JOB_FLOW&Steps.member.1.HadoopJarStep.Args.member.1=s3:\/\/elasticmapreduce\/libs\/pig\/pig-script&Steps.member.1.HadoopJarStep.Args.member.2=--base-path&Steps.member.1.HadoopJarStep.Args.member.3=s3:\/\/elasticmapreduce\/libs\/pig\/&Steps.member.1.HadoopJarStep.Args.member.4=--install-pig&Steps.member.1.HadoopJarStep.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner.jar&Steps.member.1.Name=Setup%20Pig&Steps.member.2.ActionOnFailure=TERMINATE_JOB_FLOW&Steps.member.2.HadoopJarStep.Args.member.1=s3:\/\/elasticmapreduce\/libs\/pig\/pig-script&Steps.member.2.HadoopJarStep.Args.member.10=s3n:\/\/elasticmapreduce\/samples\/pig-apache\/do-reports.pig&Steps.member.2.HadoopJarStep.Args.member.2=--run-pig-script&Steps.member.2.HadoopJarStep.Args.member.3=--args&Steps.member.2.HadoopJarStep.Args.member.4=-p&Steps.member.2.HadoopJarStep.Args.member.5=INPUT=s3n:\/\/elasticmapreduce\/samples\/pig-apache\/input&Steps.member.2.HadoopJarStep.Args.member.6=-p&Steps.member.2.HadoopJarStep.Args.member.7=OUTPUT=s3n:\/\/slif-elasticity\/pig-apache\/output\/2011-05-10&Steps.member.2.HadoopJarStep.Args.member.8=-p&Steps.member.2.HadoopJarStep.Args.member.9=E_PARALLELS=1&Steps.member.2.HadoopJarStep.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner.jar&Steps.member.2.Name=Run%20Pig%20Script/
5
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?AWSAccessKeyId=\S+&BootstrapActions.member.1.Name=Elasticity%20Bootstrap%20Action%20\(Configure%20Hadoop\)&BootstrapActions.member.1.ScriptBootstrapAction.Args.member.1=-m&BootstrapActions.member.1.ScriptBootstrapAction.Args.member.2=mapred.job.reuse.jvm.num.tasks=120&BootstrapActions.member.1.ScriptBootstrapAction.Path=s3n:\/\/elasticmapreduce\/bootstrap-actions\/configure-hadoop&Instances.Ec2KeyName=sharethrough_dev&Instances.HadoopVersion=0.20&Instances.InstanceCount=2&Instances.MasterInstanceType=m1.small&Instances.SlaveInstanceType=m1.small&Name=Elasticity%20Pig%20Job&Operation=RunJobFlow&.*&Steps.member.1.ActionOnFailure=TERMINATE_JOB_FLOW&Steps.member.1.HadoopJarStep.Args.member.1=s3:\/\/elasticmapreduce\/libs\/pig\/pig-script&Steps.member.1.HadoopJarStep.Args.member.2=--base-path&Steps.member.1.HadoopJarStep.Args.member.3=s3:\/\/elasticmapreduce\/libs\/pig\/&Steps.member.1.HadoopJarStep.Args.member.4=--install-pig&Steps.member.1.HadoopJarStep.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner.jar&Steps.member.1.Name=Setup%20Pig&Steps.member.2.ActionOnFailure=TERMINATE_JOB_FLOW&Steps.member.2.HadoopJarStep.Args.member.1=s3:\/\/elasticmapreduce\/libs\/pig\/pig-script&Steps.member.2.HadoopJarStep.Args.member.10=s3n:\/\/elasticmapreduce\/samples\/pig-apache\/do-reports.pig&Steps.member.2.HadoopJarStep.Args.member.2=--run-pig-script&Steps.member.2.HadoopJarStep.Args.member.3=--args&Steps.member.2.HadoopJarStep.Args.member.4=-p&Steps.member.2.HadoopJarStep.Args.member.5=INPUT=s3n:\/\/elasticmapreduce\/samples\/pig-apache\/input&Steps.member.2.HadoopJarStep.Args.member.6=-p&Steps.member.2.HadoopJarStep.Args.member.7=OUTPUT=s3n:\/\/slif-elasticity\/pig-apache\/output\/2011-05-10&Steps.member.2.HadoopJarStep.Args.member.8=-p&Steps.member.2.HadoopJarStep.Args.member.9=E_PARALLELS=1&Steps.member.2.HadoopJarStep.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner.jar&Steps.member.2.Name=Run%20Pig%20Script/
6
6
  body:
7
7
  headers:
8
8
  accept:
@@ -2,7 +2,7 @@
2
2
  - !ruby/struct:VCR::HTTPInteraction
3
3
  request: !ruby/struct:VCR::Request
4
4
  method: :get
5
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?AWSAccessKeyId=AKIAI7HEMMNKGT6VFFSA&Instances\.Ec2KeyName=sharethrough-dev&Instances\.HadoopVersion=0\.20&Instances\.InstanceCount=2&Instances\.MasterInstanceType=m1\.small&Instances\.Placement\.AvailabilityZone=us-east-1a&Instances\.SlaveInstanceType=m1\.small&Name=Elasticity%20Test%20Flow%20\(EMR%20Pig%20Script\)&Operation=RunJobFlow&.*&Steps\.member\.1\.ActionOnFailure=TERMINATE_JOB_FLOW&Steps\.member\.1\.HadoopJarStep\.Args\.member\.1=s3:\/\/elasticmapreduce\/libs\/pig\/pig-script&Steps\.member\.1\.HadoopJarStep\.Args\.member\.2=--base-path&Steps\.member\.1\.HadoopJarStep\.Args\.member\.3=s3:\/\/elasticmapreduce\/libs\/pig\/&Steps\.member\.1\.HadoopJarStep\.Args\.member\.4=--install-pig&Steps\.member\.1\.HadoopJarStep\.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner\.jar&Steps\.member\.1\.Name=Setup%20Pig&Steps\.member\.2\.ActionOnFailure=TERMINATE_JOB_FLOW&Steps\.member\.2\.HadoopJarStep\.Args\.member\.1=s3:\/\/elasticmapreduce\/libs\/pig\/pig-script&Steps\.member\.2\.HadoopJarStep\.Args\.member\.2=--run-pig-script&Steps\.member\.2\.HadoopJarStep\.Args\.member\.3=--args&Steps\.member\.2\.HadoopJarStep\.Args\.member\.4=-p&Steps\.member\.2\.HadoopJarStep\.Args\.member\.5=INPUT=s3n:\/\/elasticmapreduce\/samples\/pig-apache\/input&Steps\.member\.2\.HadoopJarStep\.Args\.member\.6=-p&Steps\.member\.2\.HadoopJarStep\.Args\.member\.7=OUTPUT=s3n:\/\/slif-elasticity\/pig-apache\/output\/2011-04-19&Steps\.member\.2\.HadoopJarStep\.Args\.member\.8=s3n:\/\/elasticmapreduce\/samples\/pig-apache\/do-reports\.pig&Steps\.member\.2\.HadoopJarStep\.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner\.jar&Steps\.member\.2\.Name=Run%20Pig%20Script/
5
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?AWSAccessKeyId=\S+&Instances\.Ec2KeyName=sharethrough-dev&Instances\.HadoopVersion=0\.20&Instances\.InstanceCount=2&Instances\.MasterInstanceType=m1\.small&Instances\.Placement\.AvailabilityZone=us-east-1a&Instances\.SlaveInstanceType=m1\.small&Name=Elasticity%20Test%20Flow%20\(EMR%20Pig%20Script\)&Operation=RunJobFlow&.*&Steps\.member\.1\.ActionOnFailure=TERMINATE_JOB_FLOW&Steps\.member\.1\.HadoopJarStep\.Args\.member\.1=s3:\/\/elasticmapreduce\/libs\/pig\/pig-script&Steps\.member\.1\.HadoopJarStep\.Args\.member\.2=--base-path&Steps\.member\.1\.HadoopJarStep\.Args\.member\.3=s3:\/\/elasticmapreduce\/libs\/pig\/&Steps\.member\.1\.HadoopJarStep\.Args\.member\.4=--install-pig&Steps\.member\.1\.HadoopJarStep\.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner\.jar&Steps\.member\.1\.Name=Setup%20Pig&Steps\.member\.2\.ActionOnFailure=TERMINATE_JOB_FLOW&Steps\.member\.2\.HadoopJarStep\.Args\.member\.1=s3:\/\/elasticmapreduce\/libs\/pig\/pig-script&Steps\.member\.2\.HadoopJarStep\.Args\.member\.2=--run-pig-script&Steps\.member\.2\.HadoopJarStep\.Args\.member\.3=--args&Steps\.member\.2\.HadoopJarStep\.Args\.member\.4=-p&Steps\.member\.2\.HadoopJarStep\.Args\.member\.5=INPUT=s3n:\/\/elasticmapreduce\/samples\/pig-apache\/input&Steps\.member\.2\.HadoopJarStep\.Args\.member\.6=-p&Steps\.member\.2\.HadoopJarStep\.Args\.member\.7=OUTPUT=s3n:\/\/slif-elasticity\/pig-apache\/output\/2011-04-19&Steps\.member\.2\.HadoopJarStep\.Args\.member\.8=s3n:\/\/elasticmapreduce\/samples\/pig-apache\/do-reports\.pig&Steps\.member\.2\.HadoopJarStep\.Jar=s3:\/\/elasticmapreduce\/libs\/script-runner\/script-runner\.jar&Steps\.member\.2\.Name=Run%20Pig%20Script/
6
6
  body:
7
7
  headers:
8
8
  accept:
@@ -2,8 +2,8 @@
2
2
  - !ruby/struct:VCR::HTTPInteraction
3
3
  request: !ruby/struct:VCR::Request
4
4
  method: :get
5
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?AWSAccessKeyId=AKIAI7HEMMNKGT6VFFSA&JobFlowIds.member.1=j-1B4D1XP0C0A35&JobFlowIds.member.2=j-2&Operation=SetTerminationProtection.*&TerminationProtected=true/
6
- body:
5
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?AWSAccessKeyId=\S+&JobFlowIds.member.1=j-1B4D1XP0C0A35&JobFlowIds.member.2=j-2&Operation=SetTerminationProtection.*&TerminationProtected=true/
6
+ body:
7
7
  headers:
8
8
  accept:
9
9
  - "*/*; q=0.5, application/xml"
@@ -2,8 +2,8 @@
2
2
  - !ruby/struct:VCR::HTTPInteraction
3
3
  request: !ruby/struct:VCR::Request
4
4
  method: :get
5
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?AWSAccessKeyId=AKIAI7HEMMNKGT6VFFSA&JobFlowIds.member.1=j-1B4D1XP0C0A35&JobFlowIds.member.2=j-1YG2MYL0HVYS5&Operation=SetTerminationProtection&.*TerminationProtected=true/
6
- body:
5
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?AWSAccessKeyId=\S+&JobFlowIds.member.1=j-1B4D1XP0C0A35&JobFlowIds.member.2=j-1YG2MYL0HVYS5&Operation=SetTerminationProtection&.*TerminationProtected=true/
6
+ body:
7
7
  headers:
8
8
  accept:
9
9
  - "*/*; q=0.5, application/xml"
@@ -2,7 +2,7 @@
2
2
  - !ruby/struct:VCR::HTTPInteraction
3
3
  request: !ruby/struct:VCR::Request
4
4
  method: :get
5
- uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?AWSAccessKeyId=AKIAI7HEMMNKGT6VFFSA&JobFlowIds.member.1=j-1MZ5TVWFJRSKN&Operation=TerminateJobFlows/
5
+ uri: !ruby/regexp /^https:\/\/elasticmapreduce.amazonaws.com\/\?AWSAccessKeyId=\S+&JobFlowIds.member.1=j-1MZ5TVWFJRSKN&Operation=TerminateJobFlows/
6
6
  body:
7
7
  headers:
8
8
  accept:
@@ -15,7 +15,7 @@ describe Elasticity::AwsRequest do
15
15
 
16
16
  describe "#sign_params" do
17
17
  before do
18
- Time.should_receive(:now).and_return(Time.at(1302461096))
18
+ Time.stub(:now).and_return(Time.at(1302461096))
19
19
  end
20
20
  it "should sign according to Amazon's rules" do
21
21
  request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_access_key")
@@ -24,4 +24,50 @@ describe Elasticity::AwsRequest do
24
24
  end
25
25
  end
26
26
 
27
- end
27
+ describe "#aws_emr_request" do
28
+ before do
29
+ Time.stub(:now).and_return(Time.at(1302461096))
30
+ end
31
+
32
+ describe "options" do
33
+
34
+ describe "region" do
35
+ context "when :region is specified" do
36
+ it "should request against that region" do
37
+ request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_access_key",
38
+ :region => "eu-west-1")
39
+ RestClient.should_receive(:get).with(/elasticmapreduce\.eu\-west\-1\.amazonaws\.com/)
40
+ request.aws_emr_request({})
41
+ end
42
+ end
43
+ context "when :region is not specified" do
44
+ it "should use the default request url" do
45
+ request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_access_key")
46
+ RestClient.should_receive(:get).with(/elasticmapreduce\.amazonaws\.com/)
47
+ request.aws_emr_request({})
48
+ end
49
+ end
50
+ end
51
+
52
+ describe ":secure" do
53
+ context "when :secure is specified" do
54
+ it "should use the value to determine the request type" do
55
+ request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_access_key",
56
+ :secure => false)
57
+ RestClient.should_receive(:get).with(/^http:/)
58
+ request.aws_emr_request({})
59
+ end
60
+ end
61
+ context "when :secure is not specified" do
62
+ it "should default to secure connection" do
63
+ request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_access_key")
64
+ RestClient.should_receive(:get).with(/^https:/)
65
+ request.aws_emr_request({})
66
+ end
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+
73
+ end
@@ -293,6 +293,14 @@ describe Elasticity::EMR do
293
293
  jobflows.map(&:name).should == ["Pig Job", "Hive Job"]
294
294
  end
295
295
 
296
+ it "should accept additional parameters" do
297
+ aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key")
298
+ aws_request.should_receive(:aws_emr_request).with({"Operation" => "DescribeJobFlows","CreatedBefore" => "2011-10-04"}).and_return(@describe_jobflows_xml)
299
+ Elasticity::AwsRequest.should_receive(:new).and_return(aws_request)
300
+ emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key")
301
+ emr.describe_jobflows(:CreatedBefore => "2011-10-04")
302
+ end
303
+
296
304
  context "when a block is provided" do
297
305
  it "should yield the XML result" do
298
306
  aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key")
@@ -783,4 +791,4 @@ describe Elasticity::EMR do
783
791
  end
784
792
  end
785
793
 
786
- end
794
+ end
@@ -11,6 +11,15 @@ describe Elasticity::JobFlow do
11
11
  <JobFlowId>j-p</JobFlowId>
12
12
  <Name>Pig Job</Name>
13
13
  <ExecutionStatusDetail>
14
+ <CreationDateTime>
15
+ 2011-10-04T21:49:16Z
16
+ </CreationDateTime>
17
+ <StartDateTime>
18
+ 2011-10-04T21:49:17Z
19
+ </StartDateTime>
20
+ <ReadyDateTime>
21
+ 2011-10-04T21:49:18Z
22
+ </ReadyDateTime>
14
23
  <State>TERMINATED</State>
15
24
  </ExecutionStatusDetail>
16
25
  <Steps>
@@ -31,13 +40,60 @@ describe Elasticity::JobFlow do
31
40
  </ExecutionStatusDetail>
32
41
  </member>
33
42
  </Steps>
43
+ <Instances>
44
+ <Placement>
45
+ <AvailabilityZone>
46
+ eu-west-1a
47
+ </AvailabilityZone>
48
+ </Placement>
49
+ <SlaveInstanceType>
50
+ m1.small
51
+ </SlaveInstanceType>
52
+ <MasterInstanceType>
53
+ m1.small
54
+ </MasterInstanceType>
55
+ <Ec2KeyName>
56
+ myec2keyname
57
+ </Ec2KeyName>
58
+ <InstanceCount>
59
+ 4
60
+ </InstanceCount>
61
+ </Instances>
34
62
  </member>
35
63
  <member>
36
64
  <JobFlowId>j-h</JobFlowId>
37
65
  <Name>Hive Job</Name>
38
66
  <ExecutionStatusDetail>
67
+ <CreationDateTime>
68
+ 2011-10-04T22:49:16Z
69
+ </CreationDateTime>
70
+ <StartDateTime>
71
+
72
+ </StartDateTime>
73
+ <ReadyDateTime>
74
+
75
+ </ReadyDateTime>
39
76
  <State>TERMINATED</State>
40
77
  </ExecutionStatusDetail>
78
+ <Instances>
79
+ <Placement>
80
+ <AvailabilityZone>
81
+ eu-west-1b
82
+ </AvailabilityZone>
83
+ </Placement>
84
+ <SlaveInstanceType>
85
+ c1.medium
86
+ </SlaveInstanceType>
87
+ <MasterInstanceType>
88
+ c1.medium
89
+ </MasterInstanceType>
90
+ <Ec2KeyName>
91
+ myec2keyname
92
+ </Ec2KeyName>
93
+ <InstanceCount>
94
+ 2
95
+ </InstanceCount>
96
+ </Instances>
41
97
  </member>
42
98
  </JobFlows>
43
99
  </DescribeJobFlowsResult>
@@ -56,6 +112,12 @@ describe Elasticity::JobFlow do
56
112
  jobflow.state.should == "TERMINATED"
57
113
  jobflow.steps.map(&:name).should == ["Setup Hive", "Run Hive Script"]
58
114
  jobflow.steps.map(&:state).should == ["FAILED", "PENDING"]
115
+ jobflow.created_at.should == Time.parse("2011-10-04T21:49:16Z")
116
+ jobflow.started_at.should == Time.parse("2011-10-04T21:49:17Z")
117
+ jobflow.ready_at.should == Time.parse("2011-10-04T21:49:18Z")
118
+ jobflow.master_instance_type.should == "m1.small"
119
+ jobflow.slave_instance_type.should == "m1.small"
120
+ jobflow.instance_count.should == "4"
59
121
  end
60
122
  end
61
123
 
@@ -65,7 +127,13 @@ describe Elasticity::JobFlow do
65
127
  jobflow.map(&:name).should == ["Pig Job", "Hive Job"]
66
128
  jobflow.map(&:jobflow_id).should == ["j-p", "j-h"]
67
129
  jobflow.map(&:state).should == ["TERMINATED", "TERMINATED"]
130
+ jobflow.map(&:created_at).should == [Time.parse("2011-10-04T21:49:16Z"), Time.parse("2011-10-04T22:49:16Z")]
131
+ jobflow.map(&:started_at).should == [Time.parse("2011-10-04T21:49:17Z"), nil]
132
+ jobflow.map(&:ready_at).should == [Time.parse("2011-10-04T21:49:18Z"), nil]
133
+ jobflow.map(&:master_instance_type).should == ["m1.small","c1.medium"]
134
+ jobflow.map(&:slave_instance_type).should == ["m1.small", "c1.medium"]
135
+ jobflow.map(&:instance_count).should == ["4","2"]
68
136
  end
69
137
  end
70
138
 
71
- end
139
+ end
@@ -20,6 +20,12 @@ describe Elasticity::JobFlowStep do
20
20
  </StepConfig>
21
21
  <ExecutionStatusDetail>
22
22
  <State>FAILED</State>
23
+ <StartDateTime>
24
+ 2011-10-04T21:49:16Z
25
+ </StartDateTime>
26
+ <EndDateTime>
27
+ 2011-10-04T21:51:16Z
28
+ </EndDateTime>
23
29
  </ExecutionStatusDetail>
24
30
  </member>
25
31
  <member>
@@ -28,6 +34,10 @@ describe Elasticity::JobFlowStep do
28
34
  </StepConfig>
29
35
  <ExecutionStatusDetail>
30
36
  <State>PENDING</State>
37
+ <StartDateTime>
38
+ </StartDateTime>
39
+ <EndDateTime>
40
+ </EndDateTime>
31
41
  </ExecutionStatusDetail>
32
42
  </member>
33
43
  </Steps>
@@ -46,6 +56,8 @@ describe Elasticity::JobFlowStep do
46
56
  jobflow_step = Elasticity::JobFlowStep.from_member_element(@members_nodeset[0])
47
57
  jobflow_step.name.should == "Setup Hive"
48
58
  jobflow_step.state.should == "FAILED"
59
+ jobflow_step.started_at.should == Time.parse("2011-10-04T21:49:16Z")
60
+ jobflow_step.ended_at.should == Time.parse("2011-10-04T21:51:16Z")
49
61
  end
50
62
  end
51
63
 
@@ -54,8 +66,10 @@ describe Elasticity::JobFlowStep do
54
66
  jobflow_steps = Elasticity::JobFlowStep.from_members_nodeset(@members_nodeset)
55
67
  jobflow_steps.map(&:name).should == ["Setup Hive", "Run Hive Script"]
56
68
  jobflow_steps.map(&:state).should == ["FAILED", "PENDING"]
69
+ jobflow_steps.map(&:started_at).should == [Time.parse("2011-10-04T21:49:16Z"), nil]
70
+ jobflow_steps.map(&:ended_at).should == [Time.parse("2011-10-04T21:51:16Z"), nil]
57
71
  end
58
72
  end
59
73
 
60
74
 
61
- end
75
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elasticity
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 2
9
- - 2
10
- version: 1.2.2
9
+ - 3
10
+ version: 1.2.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Robert Slifka
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-10 00:00:00 -07:00
18
+ date: 2011-10-09 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -166,7 +166,7 @@ files:
166
166
  - Gemfile
167
167
  - HISTORY.mediawiki
168
168
  - LICENSE
169
- - README.mediawiki
169
+ - README.md
170
170
  - Rakefile
171
171
  - elasticity.gemspec
172
172
  - lib/elasticity.rb
@@ -227,7 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
227
227
  version: "0"
228
228
  requirements: []
229
229
 
230
- rubyforge_project: elasticity
230
+ rubyforge_project:
231
231
  rubygems_version: 1.4.1
232
232
  signing_key:
233
233
  specification_version: 3