elasticity 0.6 → 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.mediawiki CHANGED
@@ -54,7 +54,29 @@ Some combinations of the options will be rejected by Amazon and some once-valid
54
54
 
55
55
  == AddJobFlowSteps ==
56
56
 
57
- ''(not yet supported)''
57
+ AddJobFlowSteps adds the specified steps to the specified job flow.
58
+
59
+ <pre>
60
+ emr = Elasticity::EMR.new(ENV["AWS_ACCESS_KEY_ID"], ENV["AWS_SECRET_KEY"])
61
+ jobflow_id = emr.run_job_flow(...)
62
+ emr.add_jobflow_steps(jobflow_id, {
63
+ :steps => [
64
+ {
65
+ :action_on_failure => "TERMINATE_JOB_FLOW",
66
+ :hadoop_jar_step => {
67
+ :args => [
68
+ "s3://elasticmapreduce/libs/pig/pig-script",
69
+ "--base-path",
70
+ "s3://elasticmapreduce/libs/pig/",
71
+ "--install-pig"
72
+ ],
73
+ :jar => "s3://elasticmapreduce/libs/script-runner/script-runner.jar"
74
+ },
75
+ :name => "Setup Pig"
76
+ }
77
+ ]
78
+ })
79
+ </pre>
58
80
 
59
81
  == DescribeJobFlows ==
60
82
 
@@ -119,9 +141,9 @@ RunJobFlow creates and starts a new job flow. Specifying the arguments to RunJo
119
141
  :hadoop_jar_step => {
120
142
  :args => [
121
143
  "s3://elasticmapreduce/libs/pig/pig-script",
122
- "--base-path",
123
- "s3://elasticmapreduce/libs/pig/",
124
- "--install-pig"
144
+ "--base-path",
145
+ "s3://elasticmapreduce/libs/pig/",
146
+ "--install-pig"
125
147
  ],
126
148
  :jar => "s3://elasticmapreduce/libs/script-runner/script-runner.jar"
127
149
  },
@@ -132,13 +154,13 @@ RunJobFlow creates and starts a new job flow. Specifying the arguments to RunJo
132
154
  :hadoop_jar_step => {
133
155
  :args => [
134
156
  "s3://elasticmapreduce/libs/pig/pig-script",
135
- "--run-pig-script",
136
- "--args",
137
- "-p",
138
- "INPUT=s3n://elasticmapreduce/samples/pig-apache/input",
139
- "-p",
140
- "OUTPUT=s3n://slif-elasticity/pig-apache/output/2011-04-19",
141
- "s3n://elasticmapreduce/samples/pig-apache/do-reports.pig"
157
+ "--run-pig-script",
158
+ "--args",
159
+ "-p",
160
+ "INPUT=s3n://elasticmapreduce/samples/pig-apache/input",
161
+ "-p",
162
+ "OUTPUT=s3n://slif-elasticity/pig-apache/output/2011-04-19",
163
+ "s3n://elasticmapreduce/samples/pig-apache/do-reports.pig"
142
164
  ],
143
165
  :jar => "s3://elasticmapreduce/libs/script-runner/script-runner.jar"
144
166
  },
data/lib/elasticity.rb CHANGED
@@ -6,6 +6,7 @@ require 'nokogiri'
6
6
  require 'elasticity/aws_request'
7
7
  require 'elasticity/emr'
8
8
  require 'elasticity/job_flow'
9
+ require 'elasticity/job_flow_step'
9
10
 
10
11
  module Elasticity
11
12
  end
@@ -20,20 +20,19 @@ module Elasticity
20
20
  # not all of these options are required (or valid!) at once. Please see the
21
21
  # EMR docs for details although even then you're going to need to experiment :)
22
22
  #
23
- # instance_group_config = {
24
- # :bid_price => 5,
25
- # :instance_count => 1,
26
- # :instance_role => "TASK",
27
- # :market => "SPOT",
28
- # :name => "Go Canucks Go!"
29
- # :type => "m1.small",
30
- # }
23
+ # instance_group_config = {
24
+ # :bid_price => 5,
25
+ # :instance_count => 1,
26
+ # :instance_role => "TASK",
27
+ # :market => "SPOT",
28
+ # :name => "Go Canucks Go!"
29
+ # :type => "m1.small",
30
+ # }
31
31
  #
32
- # add_instance_groups takes an array of {}.
33
- #
34
- # Returns an array of the instance IDs that were created by the specified configs.
32
+ # add_instance_groups takes an array of {}. Returns an array of the instance IDs
33
+ # that were created by the specified configs.
35
34
  #
36
- # ["ig-2GOVEN6HVJZID", "ig-1DU9M2UQMM051", "ig-3DZRW4Y2X4S", ...]
35
+ # ["ig-2GOVEN6HVJZID", "ig-1DU9M2UQMM051", "ig-3DZRW4Y2X4S", ...]
37
36
  def add_instance_groups(jobflow_id, instance_group_configs)
38
37
  params = {
39
38
  :operation => "AddInstanceGroups",
@@ -55,6 +54,38 @@ module Elasticity
55
54
  end
56
55
  end
57
56
 
57
+ # Add a step (or steps) to the specified job flow.
58
+ #
59
+ # emr.add_jobflow_step("j-123", {
60
+ # :steps => [
61
+ # {
62
+ # :action_on_failure => "TERMINATE_JOB_FLOW",
63
+ # :hadoop_jar_step => {
64
+ # :args => [
65
+ # "s3://elasticmapreduce/libs/pig/pig-script",
66
+ # "--base-path",
67
+ # "s3://elasticmapreduce/libs/pig/",
68
+ # "--install-pig"
69
+ # ],
70
+ # :jar => "s3://elasticmapreduce/libs/script-runner/script-runner.jar"
71
+ # },
72
+ # :name => "Setup Pig"
73
+ # }
74
+ # ]
75
+ # })
76
+ def add_jobflow_steps(jobflow_id, steps_config)
77
+ params = {
78
+ :operation => "AddJobFlowSteps",
79
+ :job_flow_id => jobflow_id
80
+ }.merge!(steps_config)
81
+ begin
82
+ aws_result = @aws_request.aws_emr_request(EMR.convert_ruby_to_aws(params))
83
+ yield aws_result if block_given?
84
+ rescue RestClient::BadRequest => e
85
+ raise ArgumentError, EMR.parse_error_response(e.http_body)
86
+ end
87
+ end
88
+
58
89
  # Set the number of instances in the specified instance groups to the
59
90
  # specified counts. Note that this modifies the *request* count, which
60
91
  # is not the same as the *running* count. I.e. you request instances
@@ -62,7 +93,7 @@ module Elasticity
62
93
  #
63
94
  # Takes a {} of instance group IDs => desired instance count.
64
95
  #
65
- # {"ig-1" => 40, "ig-2" => 5, ...}
96
+ # {"ig-1" => 40, "ig-2" => 5, ...}
66
97
  def modify_instance_groups(instance_group_config)
67
98
  params = {
68
99
  :operation => "ModifyInstanceGroups",
@@ -76,7 +107,61 @@ module Elasticity
76
107
  end
77
108
  end
78
109
 
79
- # TODO DOCUMENT ME
110
+ # Start a job flow with the specified configuration. This is a very thin
111
+ # wrapper around the AWS API, so in order to use it directly you'll need
112
+ # to have the PDF API reference handy, which can be found here:
113
+ #
114
+ # http://awsdocs.s3.amazonaws.com/ElasticMapReduce/20090331/emr-api-20090331.pdf
115
+ #
116
+ # Here is a sample job flow configuration that should help. This job flow
117
+ # starts by installing Pig then running a Pig script. It is based off of the
118
+ # Pig demo script from Amazon.
119
+ #
120
+ # emr.run_job_flow({
121
+ # :name => "Elasticity Test Flow (EMR Pig Script)",
122
+ # :instances => {
123
+ # :ec2_key_name => "sharethrough-dev",
124
+ # :hadoop_version => "0.20",
125
+ # :instance_count => 2,
126
+ # :master_instance_type => "m1.small",
127
+ # :placement => {
128
+ # :availability_zone => "us-east-1a"
129
+ # },
130
+ # :slave_instance_type => "m1.small",
131
+ # },
132
+ # :steps => [
133
+ # {
134
+ # :action_on_failure => "TERMINATE_JOB_FLOW",
135
+ # :hadoop_jar_step => {
136
+ # :args => [
137
+ # "s3://elasticmapreduce/libs/pig/pig-script",
138
+ # "--base-path",
139
+ # "s3://elasticmapreduce/libs/pig/",
140
+ # "--install-pig"
141
+ # ],
142
+ # :jar => "s3://elasticmapreduce/libs/script-runner/script-runner.jar"
143
+ # },
144
+ # :name => "Setup Pig"
145
+ # },
146
+ # {
147
+ # :action_on_failure => "TERMINATE_JOB_FLOW",
148
+ # :hadoop_jar_step => {
149
+ # :args => [
150
+ # "s3://elasticmapreduce/libs/pig/pig-script",
151
+ # "--run-pig-script",
152
+ # "--args",
153
+ # "-p",
154
+ # "INPUT=s3n://elasticmapreduce/samples/pig-apache/input",
155
+ # "-p",
156
+ # "OUTPUT=s3n://slif-elasticity/pig-apache/output/2011-04-19",
157
+ # "s3n://elasticmapreduce/samples/pig-apache/do-reports.pig"
158
+ # ],
159
+ # :jar => "s3://elasticmapreduce/libs/script-runner/script-runner.jar"
160
+ # },
161
+ # :name => "Run Pig Script"
162
+ # }
163
+ # ]
164
+ # })
80
165
  def run_job_flow(job_flow_config)
81
166
  params = {
82
167
  :operation => "RunJobFlow",
@@ -99,7 +184,7 @@ module Elasticity
99
184
  #
100
185
  # Takes an [] of job flow IDs.
101
186
  #
102
- # ["j-1B4D1XP0C0A35", "j-1YG2MYL0HVYS5", ...]
187
+ # ["j-1B4D1XP0C0A35", "j-1YG2MYL0HVYS5", ...]
103
188
  def set_termination_protection(jobflow_ids, protection_enabled=true)
104
189
  params = {
105
190
  :operation => "SetTerminationProtection",
@@ -5,21 +5,27 @@ module Elasticity
5
5
  attr_accessor :name
6
6
  attr_accessor :jobflow_id
7
7
  attr_accessor :state
8
+ attr_accessor :steps
9
+
10
+ def initialize
11
+ @steps = []
12
+ end
8
13
 
9
14
  class << self
10
15
 
11
16
  # Create a jobflow from an AWS <member> (Nokogiri::XML::Element):
12
- # /DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows/member
17
+ # /DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows/member
13
18
  def from_member_element(xml_element)
14
19
  jobflow = JobFlow.new
15
20
  jobflow.name = xml_element.xpath("./Name").text
16
21
  jobflow.jobflow_id = xml_element.xpath("./JobFlowId").text
17
22
  jobflow.state = xml_element.xpath("./ExecutionStatusDetail/State").text
23
+ jobflow.steps = JobFlowStep.from_members_nodeset(xml_element.xpath("./Steps/member"))
18
24
  jobflow
19
25
  end
20
26
 
21
27
  # Create JobFlows from a collection of AWS <member> nodes (Nokogiri::XML::NodeSet):
22
- # /DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows
28
+ # /DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows
23
29
  def from_members_nodeset(members_nodeset)
24
30
  jobflows = []
25
31
  members_nodeset.each do |member|
@@ -0,0 +1,32 @@
1
+ module Elasticity
2
+
3
+ class JobFlowStep
4
+
5
+ attr_accessor :name
6
+ attr_accessor :state
7
+
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
18
+
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
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -1,3 +1,3 @@
1
1
  module Elasticity
2
- VERSION = "0.6"
2
+ VERSION = "1.0"
3
3
  end
@@ -0,0 +1,252 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?.*Operation=RunJobFlow/
6
+ body:
7
+ headers:
8
+ accept:
9
+ - "*/*; q=0.5, application/xml"
10
+ accept-encoding:
11
+ - gzip, deflate
12
+ response: !ruby/struct:VCR::Response
13
+ status: !ruby/struct:VCR::ResponseStatus
14
+ code: 200
15
+ message: OK
16
+ headers:
17
+ x-amzn-requestid:
18
+ - 71b9eb69-6d61-11e0-9ddc-a168e244afdb
19
+ content-type:
20
+ - text/xml
21
+ date:
22
+ - Sat, 23 Apr 2011 04:23:30 GMT
23
+ content-length:
24
+ - "296"
25
+ body: |
26
+ <RunJobFlowResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31">
27
+ <RunJobFlowResult>
28
+ <JobFlowId>j-F0UCD5851OKV</JobFlowId>
29
+ </RunJobFlowResult>
30
+ <ResponseMetadata>
31
+ <RequestId>71b9eb69-6d61-11e0-9ddc-a168e244afdb</RequestId>
32
+ </ResponseMetadata>
33
+ </RunJobFlowResponse>
34
+
35
+ http_version: "1.1"
36
+ - !ruby/struct:VCR::HTTPInteraction
37
+ request: !ruby/struct:VCR::Request
38
+ method: :get
39
+ uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?.*Operation=AddJobFlowSteps/
40
+ body:
41
+ headers:
42
+ accept:
43
+ - "*/*; q=0.5, application/xml"
44
+ accept-encoding:
45
+ - gzip, deflate
46
+ response: !ruby/struct:VCR::Response
47
+ status: !ruby/struct:VCR::ResponseStatus
48
+ code: 200
49
+ message: OK
50
+ headers:
51
+ x-amzn-requestid:
52
+ - 71e1712c-6d61-11e0-b6c0-e9580d1f7304
53
+ content-type:
54
+ - text/xml
55
+ date:
56
+ - Sat, 23 Apr 2011 04:23:31 GMT
57
+ content-length:
58
+ - "221"
59
+ body: |
60
+ <AddJobFlowStepsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31">
61
+ <ResponseMetadata>
62
+ <RequestId>71e1712c-6d61-11e0-b6c0-e9580d1f7304</RequestId>
63
+ </ResponseMetadata>
64
+ </AddJobFlowStepsResponse>
65
+
66
+ http_version: "1.1"
67
+ - !ruby/struct:VCR::HTTPInteraction
68
+ request: !ruby/struct:VCR::Request
69
+ method: :get
70
+ uri: !ruby/regexp /^http:\/\/elasticmapreduce.amazonaws.com:80\/\?.*Operation=DescribeJobFlows/
71
+ body:
72
+ headers:
73
+ accept:
74
+ - "*/*; q=0.5, application/xml"
75
+ accept-encoding:
76
+ - gzip, deflate
77
+ response: !ruby/struct:VCR::Response
78
+ status: !ruby/struct:VCR::ResponseStatus
79
+ code: 200
80
+ message: OK
81
+ headers:
82
+ x-amzn-requestid:
83
+ - 720bb591-6d61-11e0-8835-2b8f31bf243b
84
+ content-type:
85
+ - text/xml
86
+ date:
87
+ - Sat, 23 Apr 2011 04:23:31 GMT
88
+ content-encoding:
89
+ - gzip
90
+ vary:
91
+ - Accept-Encoding
92
+ transfer-encoding:
93
+ - chunked
94
+ body: !binary |
95
+ H4sIAAAAAAAAAO1dWXPiSrJ+n1/Bnae5D2pq0Up4fINFbGaXWMxLhwC5zRwM
96
+ DEv3eH79LUnGBhlQIRCSoCJ6ek4jVVaqlJmV36eqrIecuRwuxgOzPBvkJ7M/
97
+ y5a5nM+mSzPxn7fJdPnPv7+uVvNUMmlOjOVqPHwz5gtztB6aP4w347+zqfFn
98
+ +WM4e0uOZsMkAkDhAOYw/Pvj3xKJhz2S15OVdYlc3Pzo/JP88Ga+DczF5p/k
99
+ B/U/5nC9Gs+m2spYrZc5c2WMJ1/XyR3ZhWlYN+SMlamP38xHBCDkAM8hrAM+
100
+ hXAKg/5D8ttt2zIs4eajpqdbeqlWeEg6//7SIumhxkNmNlstVwtjnh5ady2T
101
+ W9dqBulNdUZuvHpP6OZylbAeO/EPtdpKNMa/EhoZovnqfx+S9r1/29LLnC93
102
+ NHUP0Odt2dn0Zfxr9wK5VDRGs9m8bCyse9xXrTdgLB6XeM+rTU7Gg2VyaSvG
103
+ LdbTqbnY/dePfxmLh6TV/rvU9OLX8vvPX+of6XE+/mX9j3P6ekjue+BdYRw3
104
+ MJYmNzdWrzS3e/RN1+N4ulwZkwlHWhxu8JDcPw4PjcVsbi5WY3PbTjZtjr4x
105
+ x5g0c7WeW4bjNpjN8NtGWJ/miZGuF+ajrraqpVpaV3+W65mf+Uq9S1Rz3bNr
106
+ UclDJuXtkPZdF3BKW47jiA21ltvnl46q3iFizxtijvRd2B07UgLF2ZUgcyXm
107
+ SpFxJcxcyZ8rOc+39XI2+XFp9PgvLg/a2ZwgC7D+1CE2/nnl6+6SZQDTobmb
108
+ MWoT47e5uaS/z83HN/hj+UYshfT37dp2y8bEGJpv5nS1YxGf3RQWs/XcZUp7
109
+ Y8EF84FN3y3i7uPpr+xsPV09gofk3t8PvLZWvVPSSvXaoXe33Y357zXJ1h1x
110
+ cKub7d8PNXaN9aFhtttUjcVf5uqxXvuZU6vpWu4h+fGL+8YKiRG2ztlXY/qL
111
+ KGIsZ9PvHvup6GxiPlbTGvG1Le2tHw+1sN8qMSsS7mCjVJAh0oppWRK+mm/u
112
+ 2BsG3oh+5mJfBNgfk5jBRNBgsvWWerq5oGcIu6ibxVpRA5TmsrQCEK21uGTu
113
+ hrnabEGGbfxfc7S5qThbL5bWuz50abu5M8N1zMWSWNMj+AHlzay3+W377qpt
114
+ 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
250
+ 9yph3/P4t/8HTfYMqCsnAgA=
251
+
252
+ http_version: "1.1"
@@ -117,6 +117,137 @@ describe Elasticity::EMR do
117
117
 
118
118
  end
119
119
 
120
+ describe "#add_jobflow_steps" do
121
+
122
+ describe "integration happy path" do
123
+ use_vcr_cassette "add_jobflow_steps/add_multiple_steps", :record => :none
124
+
125
+ before do
126
+ @setup_pig_step = {
127
+ :action_on_failure => "TERMINATE_JOB_FLOW",
128
+ :hadoop_jar_step => {
129
+ :args => [
130
+ "s3://elasticmapreduce/libs/pig/pig-script",
131
+ "--base-path",
132
+ "s3://elasticmapreduce/libs/pig/",
133
+ "--install-pig"
134
+ ],
135
+ :jar => "s3://elasticmapreduce/libs/script-runner/script-runner.jar"
136
+ },
137
+ :name => "Setup Pig"
138
+ }
139
+ @emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY)
140
+ @jobflow_id = @emr.run_job_flow({
141
+ :name => "Elasticity Test Flow (EMR Pig Script)",
142
+ :instances => {
143
+ :ec2_key_name => "sharethrough-dev",
144
+ :instance_count => 2,
145
+ :master_instance_type => "m1.small",
146
+ :slave_instance_type => "m1.small",
147
+ },
148
+ :steps => [@setup_pig_step]
149
+ })
150
+ end
151
+
152
+ it "should add a job flow step to the specified job flow" do
153
+ @emr.add_jobflow_steps(@jobflow_id, {
154
+ :steps => [
155
+ @setup_pig_step.merge(:name => "Setup Pig 2"),
156
+ @setup_pig_step.merge(:name => "Setup Pig 3")
157
+ ]
158
+ })
159
+ jobflow = @emr.describe_jobflows.select { |jf| jf.jobflow_id = @jobflow_id }.first
160
+ jobflow.steps.map(&:name).should == ["Setup Pig", "Setup Pig 2", "Setup Pig 3"]
161
+ end
162
+
163
+ end
164
+
165
+ describe "unit tests" do
166
+
167
+ it "should add the specified steps to the job flow" do
168
+ aws_request = Elasticity::AwsRequest.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY)
169
+ aws_request.should_receive(:aws_emr_request).with({
170
+ "Operation" => "AddJobFlowSteps",
171
+ "JobFlowId" => "j-1",
172
+ "Steps.member.1.Name" => "Step 1",
173
+ "Steps.member.1.ActionOnFailure" => "TERMINATE_JOB_FLOW",
174
+ "Steps.member.1.HadoopJarStep.Jar" => "jar1",
175
+ "Steps.member.1.HadoopJarStep.Args.member.1" => "arg1-1",
176
+ "Steps.member.1.HadoopJarStep.Args.member.2" => "arg1-2",
177
+ "Steps.member.2.Name" => "Step 2",
178
+ "Steps.member.2.ActionOnFailure" => "CONTINUE",
179
+ "Steps.member.2.HadoopJarStep.Jar" => "jar2",
180
+ "Steps.member.2.HadoopJarStep.Args.member.1" => "arg2-1",
181
+ "Steps.member.2.HadoopJarStep.Args.member.2" => "arg2-2",
182
+ })
183
+ Elasticity::AwsRequest.should_receive(:new).and_return(aws_request)
184
+ emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY)
185
+ emr.add_jobflow_steps("j-1", {
186
+ :steps => [
187
+ {
188
+ :action_on_failure => "TERMINATE_JOB_FLOW",
189
+ :name => "Step 1",
190
+ :hadoop_jar_step => {
191
+ :args => ["arg1-1", "arg1-2"],
192
+ :jar => "jar1",
193
+ }
194
+ },
195
+ {
196
+ :action_on_failure => "CONTINUE",
197
+ :name => "Step 2",
198
+ :hadoop_jar_step => {
199
+ :args => ["arg2-1", "arg2-2"],
200
+ :jar => "jar2",
201
+ }
202
+ }
203
+ ]
204
+ })
205
+ end
206
+
207
+ context "when there is an error" do
208
+ before do
209
+ @error_message = "2 validation errors detected: Value null at 'steps' failed to satisfy constraint: Member must not be null; Value null at 'jobFlowId' failed to satisfy constraint: Member must not be null"
210
+ @error_xml = <<-ERROR
211
+ <ErrorResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31">
212
+ <Error>
213
+ <Message>#{@error_message}</Message>
214
+ </Error>
215
+ </ErrorResponse>
216
+ ERROR
217
+ end
218
+
219
+ it "should raise an ArgumentError with the error message" do
220
+ aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key")
221
+ @exception = RestClient::BadRequest.new
222
+ @exception.should_receive(:http_body).and_return(@error_xml)
223
+ aws_request.should_receive(:aws_emr_request).and_raise(@exception)
224
+ Elasticity::AwsRequest.should_receive(:new).and_return(aws_request)
225
+ emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key")
226
+ lambda {
227
+ emr.add_jobflow_steps("", {})
228
+ }.should raise_error(ArgumentError, @error_message)
229
+ end
230
+ end
231
+
232
+ context "when a block is given" do
233
+ it "should yield the XML result" do
234
+ aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key")
235
+ aws_request.should_receive(:aws_emr_request).and_return("xml_response")
236
+ Elasticity::AwsRequest.should_receive(:new).and_return(aws_request)
237
+ emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key")
238
+ xml_result = nil
239
+ emr.add_jobflow_steps("", {}) do |xml|
240
+ xml_result = xml
241
+ end
242
+ xml_result.should == "xml_response"
243
+ end
244
+ end
245
+
246
+
247
+ end
248
+
249
+ end
250
+
120
251
  describe "#describe_jobflows" do
121
252
 
122
253
  describe "integration happy path" do
@@ -8,26 +8,44 @@ describe Elasticity::JobFlow do
8
8
  <DescribeJobFlowsResult>
9
9
  <JobFlows>
10
10
  <member>
11
+ <JobFlowId>j-p</JobFlowId>
12
+ <Name>Pig Job</Name>
11
13
  <ExecutionStatusDetail>
12
14
  <State>TERMINATED</State>
13
15
  </ExecutionStatusDetail>
14
- <JobFlowId>j-p</JobFlowId>
15
- <Name>Pig Job</Name>
16
+ <Steps>
17
+ <member>
18
+ <StepConfig>
19
+ <Name>Setup Hive</Name>
20
+ </StepConfig>
21
+ <ExecutionStatusDetail>
22
+ <State>FAILED</State>
23
+ </ExecutionStatusDetail>
24
+ </member>
25
+ <member>
26
+ <StepConfig>
27
+ <Name>Run Hive Script</Name>
28
+ </StepConfig>
29
+ <ExecutionStatusDetail>
30
+ <State>PENDING</State>
31
+ </ExecutionStatusDetail>
32
+ </member>
33
+ </Steps>
16
34
  </member>
17
35
  <member>
36
+ <JobFlowId>j-h</JobFlowId>
37
+ <Name>Hive Job</Name>
18
38
  <ExecutionStatusDetail>
19
39
  <State>TERMINATED</State>
20
40
  </ExecutionStatusDetail>
21
- <JobFlowId>j-h</JobFlowId>
22
- <Name>Hive Job</Name>
23
41
  </member>
24
42
  </JobFlows>
25
43
  </DescribeJobFlowsResult>
26
44
  </DescribeJobFlowsResponse>
27
45
  JOBFLOWS
28
- @describe_jobflows_document = Nokogiri::XML(describe_jobflows_xml)
29
- @describe_jobflows_document.remove_namespaces!
30
- @members_nodeset = @describe_jobflows_document.xpath('/DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows/member')
46
+ describe_jobflows_document = Nokogiri::XML(describe_jobflows_xml)
47
+ describe_jobflows_document.remove_namespaces!
48
+ @members_nodeset = describe_jobflows_document.xpath('/DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows/member')
31
49
  end
32
50
 
33
51
  describe ".from_xml" do
@@ -36,6 +54,8 @@ describe Elasticity::JobFlow do
36
54
  jobflow.name.should == "Pig Job"
37
55
  jobflow.jobflow_id.should == "j-p"
38
56
  jobflow.state.should == "TERMINATED"
57
+ jobflow.steps.map(&:name).should == ["Setup Hive", "Run Hive Script"]
58
+ jobflow.steps.map(&:state).should == ["FAILED", "PENDING"]
39
59
  end
40
60
  end
41
61
 
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe Elasticity::JobFlowStep do
4
+
5
+ before do
6
+ describe_jobflows_xml = <<-JOBFLOWS
7
+ <DescribeJobFlowsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31">
8
+ <DescribeJobFlowsResult>
9
+ <JobFlows>
10
+ <member>
11
+ <JobFlowId>j-p</JobFlowId>
12
+ <Name>Pig Job</Name>
13
+ <ExecutionStatusDetail>
14
+ <State>TERMINATED</State>
15
+ </ExecutionStatusDetail>
16
+ <Steps>
17
+ <member>
18
+ <StepConfig>
19
+ <Name>Setup Hive</Name>
20
+ </StepConfig>
21
+ <ExecutionStatusDetail>
22
+ <State>FAILED</State>
23
+ </ExecutionStatusDetail>
24
+ </member>
25
+ <member>
26
+ <StepConfig>
27
+ <Name>Run Hive Script</Name>
28
+ </StepConfig>
29
+ <ExecutionStatusDetail>
30
+ <State>PENDING</State>
31
+ </ExecutionStatusDetail>
32
+ </member>
33
+ </Steps>
34
+ </member>
35
+ </JobFlows>
36
+ </DescribeJobFlowsResult>
37
+ </DescribeJobFlowsResponse>
38
+ JOBFLOWS
39
+ describe_jobflows_document = Nokogiri::XML(describe_jobflows_xml)
40
+ describe_jobflows_document.remove_namespaces!
41
+ @members_nodeset = describe_jobflows_document.xpath('/DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows/member/Steps/member')
42
+ end
43
+
44
+ describe ".from_xml" do
45
+ it "should return a JobFlowStep with the appropriate fields initialized" do
46
+ jobflow_step = Elasticity::JobFlowStep.from_member_element(@members_nodeset[0])
47
+ jobflow_step.name.should == "Setup Hive"
48
+ jobflow_step.state.should == "FAILED"
49
+ end
50
+ end
51
+
52
+ describe ".from_steps_nodeset" do
53
+ it "should return JobFlowSteps with the appropriate fields initialized" do
54
+ jobflow_steps = Elasticity::JobFlowStep.from_members_nodeset(@members_nodeset)
55
+ jobflow_steps.map(&:name).should == ["Setup Hive", "Run Hive Script"]
56
+ jobflow_steps.map(&:state).should == ["FAILED", "PENDING"]
57
+ end
58
+ end
59
+
60
+
61
+ end
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elasticity
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 15
5
5
  prerelease:
6
6
  segments:
7
+ - 1
7
8
  - 0
8
- - 6
9
- version: "0.6"
9
+ version: "1.0"
10
10
  platform: ruby
11
11
  authors:
12
12
  - Robert Slifka
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-04-18 00:00:00 -07:00
17
+ date: 2011-04-22 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -127,9 +127,11 @@ files:
127
127
  - lib/elasticity/aws_request.rb
128
128
  - lib/elasticity/emr.rb
129
129
  - lib/elasticity/job_flow.rb
130
+ - lib/elasticity/job_flow_step.rb
130
131
  - lib/elasticity/version.rb
131
132
  - spec/fixtures/vcr_cassettes/add_instance_groups/one_group_successful.yml
132
133
  - spec/fixtures/vcr_cassettes/add_instance_groups/one_group_unsuccessful.yml
134
+ - spec/fixtures/vcr_cassettes/add_jobflow_steps/add_multiple_steps.yml
133
135
  - spec/fixtures/vcr_cassettes/describe_jobflows/all_jobflows.yml
134
136
  - spec/fixtures/vcr_cassettes/direct/terminate_jobflow.yml
135
137
  - spec/fixtures/vcr_cassettes/modify_instance_groups/set_instances_to_3.yml
@@ -140,6 +142,7 @@ files:
140
142
  - spec/lib/elasticity/aws_request_spec.rb
141
143
  - spec/lib/elasticity/emr_spec.rb
142
144
  - spec/lib/elasticity/job_flow_spec.rb
145
+ - spec/lib/elasticity/job_flow_step_spec.rb
143
146
  - spec/spec_helper.rb
144
147
  has_rdoc: true
145
148
  homepage: http://www.github.com/rslifka/elasticity
@@ -178,6 +181,7 @@ summary: Programmatic access to Amazon's Elastic Map Reduce service.
178
181
  test_files:
179
182
  - spec/fixtures/vcr_cassettes/add_instance_groups/one_group_successful.yml
180
183
  - spec/fixtures/vcr_cassettes/add_instance_groups/one_group_unsuccessful.yml
184
+ - spec/fixtures/vcr_cassettes/add_jobflow_steps/add_multiple_steps.yml
181
185
  - spec/fixtures/vcr_cassettes/describe_jobflows/all_jobflows.yml
182
186
  - spec/fixtures/vcr_cassettes/direct/terminate_jobflow.yml
183
187
  - spec/fixtures/vcr_cassettes/modify_instance_groups/set_instances_to_3.yml
@@ -188,4 +192,5 @@ test_files:
188
192
  - spec/lib/elasticity/aws_request_spec.rb
189
193
  - spec/lib/elasticity/emr_spec.rb
190
194
  - spec/lib/elasticity/job_flow_spec.rb
195
+ - spec/lib/elasticity/job_flow_step_spec.rb
191
196
  - spec/spec_helper.rb