elasticity 0.6 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ 5Qfe256L223VIXoy352nfzUW5uqVPMyvV25k/iazxtfFfSHXsR/0NRDfDOrh
115
+ yTTnH5NDejL+bXZfzWlt5kwsL8ZkSUb72C3bonRz8Tae2v5FsoOVOVyZo42M
116
+ vde2ZrJvc5H7hV6W6kE6QikEU1j0onr2+sNj1xivSBhIGC/k1SXI+5snhrO3
117
+ +cQkj/WQ3N/GRSAtVofUklNY6tuRY+ue7dZE4Ojdo/XuPd/Jq266FBR3ZRNW
118
+ +sKYLl+IJ32P7g+V2a/2Ykyy2ClJY4kozliPxiZ5+9z4jSSzS8t/lhzEAAtA
119
+ EEQlOZn9WpKs9qPdXfNdr8QB7b9CQRd276fBC6tJaPiiON4/XUQcXlCHJ1uO
120
+ VzARjwWTjYSVNY1XGxVVV3OHshZ1OjrUjZKCiHSzfUfQAAdKNb2Sb2bb3ada
121
+ 6ToIZ3eqttIYThLll5EJFfc8vpvBfGEj17Ckf5NRMAbjyXj13p9Nzcf1kiPT
122
+ xYqDZB75dnFntPaKvDDaOs0Q9ybJkD55PmzFYoqXPa3Ya1oUjk2LGx2I2bfa
123
+ tfvJ3f2CPZxrVuoCRmql+dSIDNiLir16pXC2hLPSuI0O92av/rCmnkvnm5qU
124
+ rSChGxmoCZE/rIlAUFjTudxYDybjYW66tJ/dHCJOABxUOIQ5UbY+3M/XK5OD
125
+ ux/zN7J3G1MA2Z9XALKrxfo2caxDbsEUUPzhWP3VTPwiQzFNaFox8Zf5npiS
126
+ V5D4YywT4+lvYpi0aJbEnXy6VNmbO+7PGzeqI/5Q3siWUbBPVrs9RuSTVQwR
127
+ JXWgsOXsd3kSOxOrj/hHRXPZsj6wZbqWVSv744NPdMjccp+wO3bLGC/KYI7J
128
+ HPOkvuPlmPFd4nFTjnmcT8XVaq6VbXSf0riTubkVI7Qv8gILANRa7kQO3RsL
129
+ ubWLB5djO8CLhblO94LLLEnJFUCLF7FY4quRISmZQboax9Ag/dGQsFjUW7WK
130
+ UBBKPT4yPCRb8nIPS14clwYpHFeqEKSEg5+YGVXIoM9ujxGBPrEFPhSBwpYT
131
+ C+DD3HKfsDt2yxhThSDFU61kZ47JHDOGjhlfqvCmHPM4VaiLWg9XMGzDtHZz
132
+ TCFt5hMiMXMMCrm1uzNixjdT2OG7KF3mG1jDMGJUIbPIOFukP6oQl3OCokH+
133
+ qd+Re4wqZFRhCFQh9Lk7LgJUob0xn1GFDPrEB/rEGPh4BgpbTiyAD3PLfcLu
134
+ 2C1jzUhAiTkmc0zmmMwxw6IKYVespctVsdxA8PbqUNGmPqEyM4exkFu7O2Nm
135
+ /HKFaruuyEAuKoV69KhCZpDxNUifqwrr+XaJzzV1XeebjCpkVOG1qUKopIT4
136
+ UoUQM6qQQZ9YQZ+4Ah+aQGHLiQXwYW65T9gdu2V8GQnmmMwxT+ubOeaHHswx
137
+ L0UV6v38U/GpCoRi9eaYQur3GCoxcxgKubW7M2LGL1PYEJCe7j6XVSBlo8UU
138
+ MoOMtUH6YwplqAKtL8B6J91nRCEjCkMgChGKJ1FIVOfZmkIGfOIFfGIMezwD
139
+ hS3nBmAP7FSgVuj2q2UdCDeIe+heZHhp5tHI7tbuztJMv7hHU4t9XKnjrIYi
140
+ VneJGWSsDdLnUWPtZiXfreOW3mlJDPgw4HN14COn+PgCH8CADwM+DPg4WgQM
141
+ fCgChS3nFoBPK59rFhswr4Jc9uaAD+2LDDXPPBzZ3drdWZ7pv4yE1EONvC72
142
+ tVorYsiHWWScLdJnGYl0X1G1XAsUxEaOIR+GfK6OfMQUH9OKs1BKAbY2nCEf
143
+ hnwcLQJGPhSBwpZzA8gHi7KCKl3QqMha5eaQD+2LDDHPPBbZ3drdWZ7pF/lI
144
+ pXoR98VaIy20IwZ8mEHG2SD9AZ8sRF2pyxczhUyN4R6Ge0LAPVCIKe4RU5id
145
+ tMFwD8M9jhaB4x7PQGHLuQHcA0WEVLnYU0Wl/3SDuIfuRYaYZh6L7G7t7izN
146
+ 9P3Fp/esa6hV60jPGT1ywIdZZHwt0mc1oF6uK1QyraKYQXmGfBjyuTry4VOY
147
+ jyny4R2miCEfhnwY8gkc+VAEClvODSCfUqdTxArUdCDc3IlJ1O8xxDTzWGB3
148
+ a3dnaaZf4JNrgG6m0K8XSpj2gJpr4R5mkHE2SJ+4R++gXuFJq8htHTDcw3DP
149
+ FXEP0u0D0FIC9od7tNf1KjGa/ZkmCNIhr2+eeCGdU7mPFYYWq0MqSc562t17
150
+ tlsTgaN3j9a795yNtBzZckrgA0Ra6fVobBIDSJTeSHK/tFxomfgHacIZH1e4
151
+ 8dcVDmKABSAIosLgF+nxlbil/ddJAIyoxJ3cyCBaUt35QgfrpuShKF5zcnP9
152
+ 59b1H/+m0mREc5eWbZUauvZPao0u13W9rTfaOn3Pydl6NV/TvS8qBTqlnFrX
153
+ furpTEU9QY3f45E5W/4c2vHzt0lnFnQvQ222VYL4fuZJpNp+J3+M96nJrUgW
154
+ lVxa2ZRlEC8k8h7pOzA8T5LNRHG8Px+JOJynnv9sOUdnLDElKMdmrI2EY/OO
155
+ 80yH5x4pBY/uMglixWermKuVe1KpXEbXwf+7eaCVI3OmiIbSSFbcSeJuevzF
156
+ HLhGJf2bDIIxGE/Gq/f+bGo+rpccyUdWHCRO+O3izmDtFXlhLuI0IzwX+h2z
157
+ YPsIjuMWfDTvIj4gHcu7Njr4gp/e6Zd7hO4MfvrlQ1C+3ykLablf0ABtkYng
158
+ CZGoeIUXErElnIVGNjowr4gOKSMXSpKa5dudIl+JDCeDosbJOJcb68FkPMxN
159
+ l/ajm0PECYCDCocgB+Ufw9kbydFNDv4w3oz/zqbGn6X120b2bmMKwucnI3wu
160
+ QPjEsJrlRnUsRo9+wTKjX+6AfsFy1OgXLIdFv5CxiAL9QtRg9Evc6Ze7KZmK
161
+ 9JbwXCjlRV7NtG9oOcVpLzKUr9fe6YNbuzsDSn7pA9wRM5rcRHy+x5ciRx8w
162
+ i4yvRfqD7pkm7ld7fFPLiLTmyJZTsOUUnwNzNrqGKQxiiq5hio8euuZliaHr
163
+ 20fX5DVHDF0TjUJC19ZYRABdW2owdB1vdE0xG9lybgBdw6xQALVCOd8H/JUW
164
+ K1wRXdO+yBCxzLH0wa3dnWEZ3+i6revNPta0ZjaDI4aumUXG2SJ97lZQn3AG
165
+ 92G+UFVVBq8ZvL46vAYp4HX+a1ThNUghED14DSCD13cArwG8Hrz21uXywJri
166
+ +YOF1BQKXBFMMyy9feUyWJpi6rHl3ACWxnpOxEKuLtfUavfmsDTtiwwRuRzL
167
+ Fdza3Rly8YulsxVcBU/pfjWHUMSgNDPIOBukPyjdruTkdFWROv10nyFphqSv
168
+ iKShDuUUFnzv+9c//SUxeE+sl+YisXB8+4yd/7ZSPE4B5Gfn/05rr53/n6kl
169
+ PYKHVhDEKAXlABF8aZkw3xaJkTH6PwbJ/ULyS9VTs3s/raDaq41urg6snIpq
170
+ MYVW1LHIluMVO7z36n0Aqnq1UVH3BwDnsfYHAacbfPTMiyA+bfY7vMb31Bwv
171
+ V4XQ9mEbJgLiYAgvvg97GIV92KcZYhA7Th3zshaF+t1x6khATi2CYHacek+E
172
+ 7hG6MzTguyA3Kmf6pUym0VFk2kJgwePTqHiFV15oSzgrN9zowLwiOhi5DtJV
173
+ GSpPulKkrdUYPEbm/WFkBK69DxvKPCdhayM2judG7NVifZsAHOgIpiB2Kq5E
174
+ BYA7SskpwPsB4DutAwDgSEcoRbpAQZbfszBUYmUPI4PfDH7fAfymjkS2HK/I
175
+ gQOF35tusHBt+M0XCkq9CJ5z6adsaPBbMgQZ8lC4Tfh9miEGATQcDT4O9vEF
176
+ ND79INCCTx7ToHuE7gxo+IbfadTvIUGXS0iIThm0qHiFV1ZoSzgrM9zowLwi
177
+ OvD7GcvVeqXcbkud6JRBg8DnR+rrA3CrEJpE/kgcEniGwCOEwKGiA5GEC/+V
178
+ 0M5F4P5QsB1LgXLk1HV23Bc77mu3xw08Zsd9nQiO6YOELScWy36ZW+4T5mzk
179
+ OLUN9T6OOc1dpdpXgYBvz7U03uYT0340zpgbw1czOZ7Sbmag6n63QMFk/MKZ
180
+ n9PAdrfOJorkl4/Q71GhearRjFuY89litfwRTryydil8TXMsaEUhaHmwc5rW
181
+ rWitupAtCNeuqkfNsRkR4NhONI1QFpt7J7hu7e4Myfsu8y+pAmy3sp10S4vM
182
+ uYfMIt2NY2iR/rglrdARhHqr2Mm2apHhliLHLLEq+M6/L8/9QBJ3pLgVEvhU
183
+ nUeM/4kn0GT8j2v4ow6laAKFLScWUIq55T5hjP9h/M9N8T+3FbQ8+B+kdIR0
184
+ M199qsMrrc6KM/9DbRphoG2KBNet3Z2hbd+VJPN6M6Pks6iilSNT/oJZpLtx
185
+ DC3SH//TaKa1Wj5XzGtam/E/J/I/rPzF+fwP8L/7Jmz+B6TwwYPAGf8TbaDJ
186
+ +B/X8EceSlEECltOLKAUc8t9whj/w/if2+J/bipoHed/CmJNKKYFJKdzPKN/
187
+ LmYZIYLtY/mtW7s7A9u+t7fJQhooSrEitOtixOgfZpFxtkh/9E//uZ5rKGqm
188
+ 064rjP5h9M916R8hJQgpLMeR/rFVF4IsgsLon231Gf1zz/QPXaCw5cQCSTG3
189
+ 3CeM0T+M/rkh+ufWgtZx+qcmAFCQn+W21G8y+udilhEW2PbIb93a3RnY9k3/
190
+ dDK9giDmpLJYj8w5sswi3Y1jaJH+6B9cE1X4XG1UgNKL/TmyjP+JG/+DUlgi
191
+ Xu2P/7EfPmFVc5qYdF5zoLaaowmPnJO1tBMr7u629qq4e6zi5sHIh1MQOmcJ
192
+ BMU12UjDhoEh0UlHgclwMluPBsT9V1v/eR5qpe3PhnfJ5c/lerz8MVhcAGV9
193
+ Ew4B+Osk0W5YuCXRFyzEItVdNDcBmpuoTp1FPJUsXqYTdrm7IKLqEh4Z1MBQ
194
+ c3a9XM3eEuXvjvxxV8QRM918YMvxCOVQCbIE8mdQhke/RgaAspHQaeNcrvOk
195
+ qsqViqzsKYGsDKEk4Bd8kyWQTzTEc+HQYSsGKcH7HC2PpMQ+CCWQYq8UiYl7
196
+ hO4MkvneItRCrQrIdxqdSkeOEkkQCa/wStNtCWel6hsdmFdEh6h4ytdy7UqJ
197
+ V0vtQmR4ChQ1nuJ4AWRF4qAMYln/+PZZELtkegRYED6Fjp4ecjy0frQOhAVB
198
+ KQGTkQqaBZl/XyPBFtWwRTWuy7ewqIYu7thyvEKG91EtZ6JtuxvhoPM7g8UW
199
+ 4rCFOGwhzu7vbCHOJQOdHYECDnQCOpLlOIN1eVoRF556HZivpgtCeAebj2SL
200
+ VhxIt00r0hlikAQK9j4f0CvLD5RA8cj03SN0ZwSKX1qx2xa0p6rc0njqSr/X
201
+ YxXDdgov2GtLOAv6bnRgThEdVhFVUE/JNLKwm09Hp/pRbGjFj4PNscwpCqMV
202
+ I0griineZ22lS9OKH2dC+qQVP1oHRCvyglP3LlBakdxhGsRCwiIXk6+zNzP5
203
+ at+ZHM6mq8V4kPxU6uPCl5bnUBEcNRT3wMF/ZovR0HLoE8C9g8f9L6b66tMX
204
+ sufIU8zNS6wT+1LE+i9tToALCaM/5u9UajjCqPQwfv1amL+I4YfBoG7sLUHi
205
+ b2zJBYowa8vxipCBHtv+0Q0OgkU9Ti6UxaJckPLVYk2qh8YtINHiFnjllrkF
206
+ WjsMDEZhhfw5D0YRNwjs1HaK6d49QncGo3xzC1JazLaVfFqVYMS4hdCdwjP3
207
+ tSWclf9udGBOER1uAQt1HTVqOKPWEGDcgp8lSyIHgcApIuMWIsktQJ/ndl2a
208
+ W/BaJ308tn60DmjjFuBTQAiaW3gdf48a97hmyRoH+69QVi3ZvZ+2bMl5cSGt
209
+ WyrusZrNO4gB5PaMPracswLHRsKZkPsD0rCFS7sXgvJna+nSyY2o1y69XIDa
210
+ s7UzRkvnKd9mI3PCDdbjyejHv6l0GF1s/dSnJitjQP59ud6PLp/67NUfxUql
211
+ QKWU0aif3noPIa2tsqJw3BdXXSQYf0TJQIMxyceQx86cIBZXyRhUmo1avlXv
212
+ FkIjQHl7cRW66cVVtIYYJAEKzlxHAlK8EuzutKOYxD1Cd8b1+CVAS51iXct0
213
+ GuV6JxM5AjRkp7jARmYvkL7RgTlFdAhQpGYq+b6qPSuy0mMEqB8CVOIsCpRt
214
+ 2YwW/ynpULZmejuR9FO4/NMbE4P3xHppLhILJ3KcQYXaSvE8+eOHCt1p7UWF
215
+ fgKQE9dZYT6Fg+RCV19mQiLecpVAjBRlpGjiHkhR6pBkyzkrhGwk+MbhTjeC
216
+ c9jMNXE4fC6g6nMFFDvPWnibnLDBYzyydlndIg4/zRCDgByOeZGE3neVmE8/
217
+ CHg/x9H50D1CdwY5/OJwBHni5Wq5KGpaJzJAPCpeQRXbz0oRNzowr4gOEIe8
218
+ ILVVscu3ir1cZIC4yMcFiUOJ2CZS7MVIUJJiicZXi/Utg3E5Jfg9RSw4MI59
219
+ llLaaR0gGD+8KuGyYPznyh5NBsUZFL8bKE4RkGw5ZwWQjYQzoThOCfjaUDzD
220
+ 52CvAbIgjU+C4nsA9RDxCA+N0cUB9SA6gJrWnIKDDtDR4AzogAPf2XN0TnOP
221
+ 0J1BB9+AWq/2yuVc4ymba9KeEHwaoPaFHnBsvuNtiiRInCyHCR0ggw7fwhIA
222
+ 1nd/iCMFHSylSMgX/UGHrdYBQAciXyITgbOiJCjoYIxGS8uuGGxgsOGzze3D
223
+ BspgZMvxCh5CwLDB6kbxWDAVAGxoZIuCks7zTVB+Cq+SABgBY8S/3OoHvFPs
224
+ MBi8YWkgOdblE298uEFwnyq8J0L3CDG8QYc3UEnUixosyw3aXdPX+H4XDafw
225
+ SgttCWelhhsdmFNE5/tdr/nUes71CuVeuRmZz3fW+XbxAOAflQQEkUM8+3YX
226
+ JQAuWvECoxSAEQLgjlKiRyGjQ1F2p3UAANyWbxVrCfLb3ddWTQa/GfxO3AP8
227
+ pg5FtpyzQsdGgm/47XQjOdnoVTeyipVSr9GuaVlQxeEdPiobcIReLr+RNRLf
228
+ +04zxCCghqOB4Jxt6wtqfPpBcIePes+D7hG6M6jhF39DnefTsI7Vcj/NRwaA
229
+ R8UrqGL7WanhRgfmFdEB4Ijv10GxUFKBWA2klJ9/l1CcMB2eS/D4jDXlOxKY
230
+ S4TiEnpaezrdJVQpK1cLadSuNGkLvhZmiawxXQ//Wv5PsEtD4kRMSRxEiMMo
231
+ TGIKM2Lqe9AQUhinBBAtYkqwVwIe3dh2JNR+tQ6QmIJBElPVd+ucgIRlaoyZ
232
+ YsxU4k6YKbpYZMs5K3ZsJJzDTAlWToquzUzV05WSpPf1ZrXYC42YgrIEAJZu
233
+ l5g6wQ4DwhuCfVbgOcSU7QYBVljzngfdI3RneMP3whBRb9UqZb5bzOtPUSKm
234
+ IuEVVKH9rNRwowPziugQUzqANb2llkslRY0QL2XnAFAI1SPOOtF1RwLziBjx
235
+ UqhQ76g1sdgp90u0tQ6+iKlEYRYsNyXHjJviAYcg46Yixk3hFC+nkFd8vTI3
236
+ RXIgPsX75aa+WgfITWEQIDc1dEII46UYL5W4E16KLg7ZcjziRvArpkg3gsfC
237
+ 9CDqHCjdXE4T5X5brTVCI6ZEhBEPwY1WSDjNEAMCHFYNjTN2LH36gRQ44Dg8
238
+ CbpH6M4Ah19iqoMafT2dzzYz7XqUeKlIOIVXSmhLOCst3OjAnCI6vJTcx7IM
239
+ O/XnfLsWKV7KXjIVKi8FYQqfx0ttJDCPiBEvheVsP1eVG3K+V2xHj5eCME7E
240
+ lGgV1IFKqJU4GTHljhzYDrBCtBZN2UpB4JQCOJmY2mkdADFF5Mv2kXRykLv5
241
+ lMSKnYTBaCmnza3TUtRRyJZzVtTYSPBNS+GPdA7wV6alMOhoRQ3U64X0c3jr
242
+ pQSAEP+CL19IJxK01GmGGATecDRQzvgO/ukHKDC84T0FukfozvCGX1rqWe0/
243
+ V7NIKWcytFVDgqelIuIUdKH9rKRwo0MIToFv3yl87uPTYbHWroswU8C0VG3w
244
+ lXSkOEFvieNFTgh1uxLPkLcrXEAd8BbZD6K0JMRWSkAeZcMPBdmd1gEgb2iv
245
+ 8FNIHA8YebMatgx7b9rcOvamjkO2HK+4IQWKvZ1usFMO8ZrYO1PvZjqSLPO9
246
+ HAgNegMeCQNTHNxmDdvT7DAIlOFYF3Q+v/tCGZ9uEFy5Tu850D1CDHpT4QyY
247
+ aytV1G5Wq0CgrY4QPPaOild4pYS2hLPSwo0OzCuig71xrt/q8s+ox2uRQd7x
248
+ OkOG/J9owW9Ww/Yc7P2ZctnXH5I50wIkA3Pza8tcrif2c5EYtJwTWGdWSc43
249
+ MlbGh4APvyZmKyEwGAgK5MSRCEnkMAEny1jg0EB+wXDwgng8sMLU5n67w+9S
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