elasticity 0.4 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.mediawiki +74 -33
- data/lib/elasticity/emr.rb +48 -1
- data/lib/elasticity/version.rb +1 -1
- data/spec/fixtures/vcr_cassettes/add_instance_groups/one_group_successful.yml +38 -0
- data/spec/fixtures/vcr_cassettes/add_instance_groups/one_group_unsuccessful.yml +35 -0
- data/spec/lib/elasticity/emr_spec.rb +131 -34
- metadata +8 -4
data/README.mediawiki
CHANGED
@@ -1,18 +1,55 @@
|
|
1
|
-
Elasticity provides programmatic access to Amazon's Elastic Map Reduce service.
|
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 enjoyable. At the very least, using Elasticity allows you to easily experiment with the EMR API :)
|
2
2
|
|
3
|
-
|
3
|
+
'''BACKLOG''': Have a look at the backlog [https://www.pivotaltracker.com/projects/272429 here] (Pivotal Tracker).
|
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.
|
6
|
+
|
7
|
+
= Installation and Usage =
|
8
|
+
|
9
|
+
<pre>
|
10
|
+
gem install elasticity
|
11
|
+
</pre>
|
12
|
+
|
13
|
+
All you have to do is <code>require 'elasticity'</code> and you're all set!
|
4
14
|
|
5
|
-
|
15
|
+
= API Reference =
|
16
|
+
|
17
|
+
Elasticity wraps (well, eventually!) 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).
|
6
18
|
|
7
19
|
Alternatively, 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.
|
8
20
|
|
9
|
-
|
21
|
+
In addition to the [http://aws.amazon.com/elasticmapreduce/ AWS EMR subsite], there are three primary resources of reference information for EMR:
|
10
22
|
|
11
|
-
|
23
|
+
* [http://docs.amazonwebservices.com/ElasticMapReduce/latest/GettingStartedGuide/ Amazon EMR Getting Started Guide]
|
24
|
+
* [http://docs.amazonwebservices.com/ElasticMapReduce/latest/DeveloperGuide/ Amazon EMR Developer Guide]
|
25
|
+
* [http://docs.amazonwebservices.com/ElasticMapReduce/latest/API/ Amazon EMR API Reference]
|
26
|
+
|
27
|
+
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.
|
12
28
|
|
13
29
|
== AddInstanceGroups ==
|
14
30
|
|
15
|
-
'
|
31
|
+
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.
|
32
|
+
|
33
|
+
<pre>
|
34
|
+
instance_group_config = {
|
35
|
+
:count => 1,
|
36
|
+
:role => "TASK",
|
37
|
+
:type => "m1.small",
|
38
|
+
:market => "ON_DEMAND",
|
39
|
+
:name => "Go Canucks!"
|
40
|
+
}
|
41
|
+
emr.add_instance_groups("j-26LIXPUNSC0M3", [instance_group_config])
|
42
|
+
|
43
|
+
> ["ig-E7C8MGA2ULQ1"]
|
44
|
+
</pre>
|
45
|
+
|
46
|
+
Some combinations of the options will be rejected by Amazon and some once-valid options will sometimes be rejected if they not relevant to the current state of the job flow (e.g. duplicate addition of TASK groups to the same job flow).
|
47
|
+
|
48
|
+
<pre>
|
49
|
+
emr.add_instance_groups("j-26LIXPUNSC0M3", [instance_group_config])
|
50
|
+
|
51
|
+
> Task instance group already exists in the job flow, cannot add more task groups
|
52
|
+
</pre>
|
16
53
|
|
17
54
|
== AddJobFlowSteps ==
|
18
55
|
|
@@ -23,10 +60,11 @@ Alternatively, you may opt for "direct" access to the API where you specify the
|
|
23
60
|
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>.
|
24
61
|
|
25
62
|
<pre>
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
63
|
+
emr = Elasticity::EMR.new(ENV["aws_access_key_id"], ENV["aws_secret_key"])
|
64
|
+
jobflows = emr.describe_jobflows
|
65
|
+
p jobflows.map(&:name)
|
66
|
+
|
67
|
+
> ["Hive Test", "Pig Test", "Interactive Hadoop", "Interactive Hive"]
|
30
68
|
</pre>
|
31
69
|
|
32
70
|
== ModifyInstanceGroups ==
|
@@ -34,25 +72,26 @@ DescribeJobFlows returns detailed information as to the state of all jobs. Curr
|
|
34
72
|
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.
|
35
73
|
|
36
74
|
<pre>
|
37
|
-
|
38
|
-
|
39
|
-
>
|
75
|
+
emr = Elasticity::EMR.new(ENV["aws_access_key_id"], ENV["aws_secret_key"])
|
76
|
+
emr.modify_instance_groups({"ig-2T1HNUO61BG3O" => 3})
|
40
77
|
</pre>
|
41
78
|
|
42
79
|
If there's an error, you'll receive an ArgumentError containing the message from Amazon. For example if you attempt to modify an instance group that's part of a terminated job flow:
|
43
80
|
|
44
81
|
<pre>
|
45
|
-
|
46
|
-
|
47
|
-
|
82
|
+
emr = Elasticity::EMR.new(ENV["aws_access_key_id"], ENV["aws_secret_key"])
|
83
|
+
emr.modify_instance_groups({"ig-some_terminated_group" => 3})
|
84
|
+
|
85
|
+
> ArgumentError: An instance group may only be modified when the job flow is running or waiting
|
48
86
|
</pre>
|
49
87
|
|
50
88
|
Or if you attempt to increase the instance count of the MASTER instance group:
|
51
89
|
|
52
90
|
<pre>
|
53
|
-
|
54
|
-
|
55
|
-
|
91
|
+
emr = Elasticity::EMR.new(ENV["aws_access_key_id"], ENV["aws_secret_key"])
|
92
|
+
emr.modify_instance_groups({"ig-some_terminated_group" => 3})
|
93
|
+
|
94
|
+
> ArgumentError: A master instance group may not be modified
|
56
95
|
</pre>
|
57
96
|
|
58
97
|
== RunJobFlow ==
|
@@ -64,17 +103,17 @@ Or if you attempt to increase the instance count of the MASTER instance group:
|
|
64
103
|
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.
|
65
104
|
|
66
105
|
<pre>
|
67
|
-
|
68
|
-
|
69
|
-
>
|
106
|
+
emr = Elasticity::EMR.new(ENV["aws_access_key_id"], ENV["aws_secret_key"])
|
107
|
+
emr.terminate_jobflows("j-BOWBV7884XD0")
|
70
108
|
</pre>
|
71
109
|
|
72
110
|
When the job flow '''doesn't exist''':
|
73
111
|
|
74
112
|
<pre>
|
75
|
-
|
76
|
-
|
77
|
-
|
113
|
+
emr = Elasticity::EMR.new(ENV["aws_access_key_id"], ENV["aws_secret_key"])
|
114
|
+
emr.terminate_jobflows("no-flow")
|
115
|
+
|
116
|
+
> ArgumentError: Job flow 'no-flow' does not exist.
|
78
117
|
</pre>
|
79
118
|
|
80
119
|
= Direct Response Access =
|
@@ -82,9 +121,10 @@ When the job flow '''doesn't exist''':
|
|
82
121
|
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.
|
83
122
|
|
84
123
|
<pre>
|
85
|
-
|
86
|
-
|
87
|
-
|
124
|
+
emr = Elasticity::EMR.new(ENV["aws_access_key_id"], ENV["aws_secret_key"])
|
125
|
+
emr.describe_jobflows{|xml| puts xml[0..77]}
|
126
|
+
|
127
|
+
> <DescribeJobFlowsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/200
|
88
128
|
</pre>
|
89
129
|
|
90
130
|
= Direct Request/Response Access =
|
@@ -92,11 +132,12 @@ If you're fine with Elasticity's invocation wrapping and would prefer to get at
|
|
92
132
|
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].
|
93
133
|
|
94
134
|
<pre>
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
135
|
+
emr = Elasticity::EMR.new(ENV["aws_access_key_id"], ENV["aws_secret_key"])
|
136
|
+
params = {"Operation" => "DescribeJobFlows"}
|
137
|
+
result_xml = emr.direct(params)
|
138
|
+
result_xml[0..78]
|
139
|
+
|
140
|
+
> <DescribeJobFlowsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009
|
100
141
|
</pre>
|
101
142
|
|
102
143
|
<!-- __NOTOC__ -->
|
data/lib/elasticity/emr.rb
CHANGED
@@ -15,6 +15,53 @@ module Elasticity
|
|
15
15
|
JobFlow.from_members_nodeset(xml_doc.xpath("/DescribeJobFlowsResponse/DescribeJobFlowsResult/JobFlows/member"))
|
16
16
|
end
|
17
17
|
|
18
|
+
# Adds a new group of instances to the specified jobflow. Elasticity maps a
|
19
|
+
# more Ruby-like syntax to the Amazon options. An exhaustive hash follows although
|
20
|
+
# not all of these options are required (or valid!) at once. Please see the
|
21
|
+
# EMR docs for details although even then you're going to need to experiment :)
|
22
|
+
#
|
23
|
+
# instance_group_config = {
|
24
|
+
# :bid_price => 5,
|
25
|
+
# :count => 1,
|
26
|
+
# :role => "TASK",
|
27
|
+
# :type => "m1.small",
|
28
|
+
# :market => "SPOT",
|
29
|
+
# :name => "Go Canucks Go!"
|
30
|
+
# }
|
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.
|
35
|
+
#
|
36
|
+
# ["ig-2GOVEN6HVJZID", "ig-1DU9M2UQMM051", "ig-3DZRW4Y2X4S", ...]
|
37
|
+
def add_instance_groups(jobflow_id, instance_group_configs)
|
38
|
+
params = {
|
39
|
+
"Operation" => "AddInstanceGroups",
|
40
|
+
"JobFlowId" => jobflow_id
|
41
|
+
}
|
42
|
+
instance_group_configs.each_with_index do |ig_config, index|
|
43
|
+
params.merge!("InstanceGroups.member.#{index+1}.BidPrice" => ig_config[:bid_price]) if ig_config[:bid_price]
|
44
|
+
params.merge!("InstanceGroups.member.#{index+1}.InstanceCount" => ig_config[:count]) if ig_config[:count]
|
45
|
+
params.merge!("InstanceGroups.member.#{index+1}.InstanceRole" => ig_config[:role]) if ig_config[:role]
|
46
|
+
params.merge!("InstanceGroups.member.#{index+1}.InstanceType" => ig_config[:type]) if ig_config[:type]
|
47
|
+
params.merge!("InstanceGroups.member.#{index+1}.Market" => ig_config[:market]) if ig_config[:market]
|
48
|
+
params.merge!("InstanceGroups.member.#{index+1}.Name" => ig_config[:name]) if ig_config[:name]
|
49
|
+
end
|
50
|
+
begin
|
51
|
+
aws_result = @aws_request.aws_emr_request(params)
|
52
|
+
xml_doc = Nokogiri::XML(aws_result)
|
53
|
+
xml_doc.remove_namespaces!
|
54
|
+
instance_group_ids = []
|
55
|
+
xml_doc.xpath("/AddInstanceGroupsResponse/AddInstanceGroupsResult/InstanceGroupIds/member").each do |member|
|
56
|
+
instance_group_ids << member.text
|
57
|
+
end
|
58
|
+
yield aws_result if block_given?
|
59
|
+
instance_group_ids
|
60
|
+
rescue RestClient::BadRequest => e
|
61
|
+
raise ArgumentError, parse_error_response(e.http_body)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
18
65
|
# Set the number of instances in the specified instance groups to the
|
19
66
|
# specified counts. Note that this modifies the *request* count, which
|
20
67
|
# is not the same as the *running* count. I.e. you request instances
|
@@ -22,7 +69,7 @@ module Elasticity
|
|
22
69
|
#
|
23
70
|
# Takes a {} of instance group IDs => desired instance count.
|
24
71
|
#
|
25
|
-
# {"ig-1" => 40, "ig-2" => 5
|
72
|
+
# {"ig-1" => 40, "ig-2" => 5, ...}
|
26
73
|
def modify_instance_groups(instance_group_config)
|
27
74
|
params = {"Operation" => "ModifyInstanceGroups"}
|
28
75
|
instance_group_config.keys.each_with_index do |instance_group, index|
|
data/lib/elasticity/version.rb
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
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:
|
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
|
+
- ddd0d158-67eb-11e0-ba06-2b5c43005be2
|
19
|
+
content-type:
|
20
|
+
- text/xml
|
21
|
+
date:
|
22
|
+
- Sat, 16 Apr 2011 05:39:15 GMT
|
23
|
+
content-length:
|
24
|
+
- "411"
|
25
|
+
body: |
|
26
|
+
<AddInstanceGroupsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31">
|
27
|
+
<AddInstanceGroupsResult>
|
28
|
+
<JobFlowId>j-OALI7TZTQMHX</JobFlowId>
|
29
|
+
<InstanceGroupIds>
|
30
|
+
<member>ig-2GOVEN6HVJZID</member>
|
31
|
+
</InstanceGroupIds>
|
32
|
+
</AddInstanceGroupsResult>
|
33
|
+
<ResponseMetadata>
|
34
|
+
<RequestId>ddd0d158-67eb-11e0-ba06-2b5c43005be2</RequestId>
|
35
|
+
</ResponseMetadata>
|
36
|
+
</AddInstanceGroupsResponse>
|
37
|
+
|
38
|
+
http_version: "1.1"
|
@@ -0,0 +1,35 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
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/
|
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: 400
|
15
|
+
message: Bad Request
|
16
|
+
headers:
|
17
|
+
x-amzn-requestid:
|
18
|
+
- 0c8d744d-67ea-11e0-bf8a-ed57a5465c87
|
19
|
+
content-type:
|
20
|
+
- text/xml
|
21
|
+
date:
|
22
|
+
- Sat, 16 Apr 2011 05:26:15 GMT
|
23
|
+
content-length:
|
24
|
+
- "337"
|
25
|
+
body: |
|
26
|
+
<ErrorResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31">
|
27
|
+
<Error>
|
28
|
+
<Type>Sender</Type>
|
29
|
+
<Code>ValidationError</Code>
|
30
|
+
<Message>Task instance group already exists in the job flow, cannot add more task groups</Message>
|
31
|
+
</Error>
|
32
|
+
<RequestId>0c8d744d-67ea-11e0-bf8a-ed57a5465c87</RequestId>
|
33
|
+
</ErrorResponse>
|
34
|
+
|
35
|
+
http_version: "1.1"
|
@@ -2,6 +2,118 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Elasticity::EMR do
|
4
4
|
|
5
|
+
describe "#add_instance_groups" do
|
6
|
+
|
7
|
+
describe "integration happy path" do
|
8
|
+
|
9
|
+
context "when properly specified" do
|
10
|
+
use_vcr_cassette "add_instance_groups/one_group_successful", :record => :none
|
11
|
+
it "should add the instance groups" do
|
12
|
+
emr = Elasticity::EMR.new(ENV["aws_access_key_id"], ENV["aws_secret_key"])
|
13
|
+
instance_group_config = {
|
14
|
+
:count => 1,
|
15
|
+
:role => "TASK",
|
16
|
+
:type => "m1.small",
|
17
|
+
:market => "ON_DEMAND",
|
18
|
+
:name => "Go Canucks Go!"
|
19
|
+
}
|
20
|
+
instance_group_ids = emr.add_instance_groups("j-OALI7TZTQMHX", [instance_group_config])
|
21
|
+
instance_group_ids.should == ["ig-2GOVEN6HVJZID"]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when improperly specified" do
|
26
|
+
use_vcr_cassette "add_instance_groups/one_group_unsuccessful", :record => :none
|
27
|
+
it "should add the instance groups" do
|
28
|
+
emr = Elasticity::EMR.new(ENV["aws_access_key_id"], ENV["aws_secret_key"])
|
29
|
+
instance_group_config = {
|
30
|
+
:bid_price => 0,
|
31
|
+
:count => 1,
|
32
|
+
:role => "TASK",
|
33
|
+
:type => "m1.small",
|
34
|
+
:market => "ON_DEMAND",
|
35
|
+
:name => "Go Canucks Go!"
|
36
|
+
}
|
37
|
+
lambda {
|
38
|
+
emr.add_instance_groups("j-19WDDS68ZUENP", [instance_group_config])
|
39
|
+
}.should raise_error(ArgumentError, "Task instance group already exists in the job flow, cannot add more task groups")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "unit tests" do
|
46
|
+
|
47
|
+
context "when multiple instance groups are specified" do
|
48
|
+
before do
|
49
|
+
@add_instance_groups_xml = <<-ADD_GROUPS
|
50
|
+
<AddInstanceGroupsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31">
|
51
|
+
<AddInstanceGroupsResult>
|
52
|
+
<JobFlowId>j-OALI7TZTQMHX</JobFlowId>
|
53
|
+
<InstanceGroupIds>
|
54
|
+
<member>ig-1</member>
|
55
|
+
<member>ig-2</member>
|
56
|
+
<member>ig-3</member>
|
57
|
+
</InstanceGroupIds>
|
58
|
+
</AddInstanceGroupsResult>
|
59
|
+
</AddInstanceGroupsResponse>
|
60
|
+
ADD_GROUPS
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should iterate over them and send the correct params to AWS" do
|
64
|
+
instance_group_configs = [
|
65
|
+
{:type=>"m1.small", :role=>"CORE", :market=>"ON_DEMAND", :count=>1, :name=>"Go Canucks Go!", :bid_price=>0},
|
66
|
+
{:type=>"m1.small", :role=>"CORE", :market=>"ON_DEMAND", :count=>1, :name=>"Go Canucks Go!", :bid_price=>0},
|
67
|
+
]
|
68
|
+
aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key")
|
69
|
+
aws_request.should_receive(:aws_emr_request).with({
|
70
|
+
"Operation" => "AddInstanceGroups",
|
71
|
+
"InstanceGroups.member.1.Name"=>"Go Canucks Go!",
|
72
|
+
"InstanceGroups.member.1.InstanceRole"=>"CORE",
|
73
|
+
"InstanceGroups.member.1.InstanceCount"=>1,
|
74
|
+
"InstanceGroups.member.1.BidPrice"=>0,
|
75
|
+
"InstanceGroups.member.1.InstanceType"=>"m1.small",
|
76
|
+
"InstanceGroups.member.1.Market"=>"ON_DEMAND",
|
77
|
+
"InstanceGroups.member.2.Name"=>"Go Canucks Go!",
|
78
|
+
"InstanceGroups.member.2.InstanceRole"=>"CORE",
|
79
|
+
"InstanceGroups.member.2.InstanceCount"=>1,
|
80
|
+
"InstanceGroups.member.2.BidPrice"=>0,
|
81
|
+
"InstanceGroups.member.2.InstanceType"=>"m1.small",
|
82
|
+
"InstanceGroups.member.2.Market"=>"ON_DEMAND",
|
83
|
+
"JobFlowId"=>"j-19WDDS68ZUENP"
|
84
|
+
})
|
85
|
+
Elasticity::AwsRequest.should_receive(:new).and_return(aws_request)
|
86
|
+
emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key")
|
87
|
+
emr.add_instance_groups("j-19WDDS68ZUENP", instance_group_configs)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should return an array of the instance groups created" do
|
91
|
+
aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key")
|
92
|
+
aws_request.should_receive(:aws_emr_request).and_return(@add_instance_groups_xml)
|
93
|
+
Elasticity::AwsRequest.should_receive(:new).and_return(aws_request)
|
94
|
+
emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key")
|
95
|
+
emr.add_instance_groups("", []).should == ["ig-1", "ig-2", "ig-3"]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when a block is provided" do
|
100
|
+
it "should yield the XML result" do
|
101
|
+
aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key")
|
102
|
+
aws_request.should_receive(:aws_emr_request).and_return("AWS XML")
|
103
|
+
Elasticity::AwsRequest.should_receive(:new).and_return(aws_request)
|
104
|
+
emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key")
|
105
|
+
xml_result = nil
|
106
|
+
emr.add_instance_groups("", []) do |xml|
|
107
|
+
xml_result = xml
|
108
|
+
end
|
109
|
+
xml_result.should == "AWS XML"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
5
117
|
describe "#describe_jobflows" do
|
6
118
|
|
7
119
|
describe "integration happy path" do
|
@@ -53,14 +165,14 @@ describe Elasticity::EMR do
|
|
53
165
|
context "when a block is provided" do
|
54
166
|
it "should yield the XML result" do
|
55
167
|
aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key")
|
56
|
-
aws_request.should_receive(:aws_emr_request).
|
168
|
+
aws_request.should_receive(:aws_emr_request).and_return("describe!")
|
57
169
|
Elasticity::AwsRequest.should_receive(:new).and_return(aws_request)
|
58
170
|
emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key")
|
59
171
|
xml_result = nil
|
60
172
|
emr.describe_jobflows do |xml|
|
61
173
|
xml_result = xml
|
62
174
|
end
|
63
|
-
xml_result.should ==
|
175
|
+
xml_result.should == "describe!"
|
64
176
|
end
|
65
177
|
end
|
66
178
|
end
|
@@ -82,7 +194,6 @@ describe Elasticity::EMR do
|
|
82
194
|
describe "unit tests" do
|
83
195
|
|
84
196
|
context "when the jobflow exists" do
|
85
|
-
|
86
197
|
before do
|
87
198
|
@terminate_jobflows_xml = <<-RESPONSE
|
88
199
|
<TerminateJobFlowsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31">
|
@@ -92,7 +203,6 @@ describe Elasticity::EMR do
|
|
92
203
|
</TerminateJobFlowsResponse>
|
93
204
|
RESPONSE
|
94
205
|
end
|
95
|
-
|
96
206
|
it "should terminate the specific jobflow" do
|
97
207
|
aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key")
|
98
208
|
aws_request.should_receive(:aws_emr_request).with({
|
@@ -103,24 +213,6 @@ describe Elasticity::EMR do
|
|
103
213
|
emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key")
|
104
214
|
emr.terminate_jobflows("j-1")
|
105
215
|
end
|
106
|
-
|
107
|
-
context "when a block is given" do
|
108
|
-
it "should yield the XML result" do
|
109
|
-
aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key")
|
110
|
-
aws_request.should_receive(:aws_emr_request).with({
|
111
|
-
"Operation" => "TerminateJobFlows",
|
112
|
-
"JobFlowIds.member.1" => "j-1"
|
113
|
-
}).and_return(@terminate_jobflows_xml)
|
114
|
-
Elasticity::AwsRequest.should_receive(:new).and_return(aws_request)
|
115
|
-
emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key")
|
116
|
-
xml_result = nil
|
117
|
-
emr.terminate_jobflows("j-1") do |xml|
|
118
|
-
xml_result = xml
|
119
|
-
end
|
120
|
-
xml_result.should == @terminate_jobflows_xml
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
216
|
end
|
125
217
|
|
126
218
|
context "when the jobflow does not exist" do
|
@@ -135,6 +227,20 @@ describe Elasticity::EMR do
|
|
135
227
|
end
|
136
228
|
end
|
137
229
|
|
230
|
+
context "when a block is given" do
|
231
|
+
it "should yield the XML result" do
|
232
|
+
aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key")
|
233
|
+
aws_request.should_receive(:aws_emr_request).and_return("terminated!")
|
234
|
+
Elasticity::AwsRequest.should_receive(:new).and_return(aws_request)
|
235
|
+
emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key")
|
236
|
+
xml_result = nil
|
237
|
+
emr.terminate_jobflows("j-1") do |xml|
|
238
|
+
xml_result = xml
|
239
|
+
end
|
240
|
+
xml_result.should == "terminated!"
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
138
244
|
end
|
139
245
|
end
|
140
246
|
|
@@ -168,25 +274,16 @@ describe Elasticity::EMR do
|
|
168
274
|
end
|
169
275
|
|
170
276
|
context "when a block is given" do
|
171
|
-
before do
|
172
|
-
@modify_instance_groups_xml = <<-RESPONSE
|
173
|
-
<ModifyInstanceGroupsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31">
|
174
|
-
<ResponseMetadata>
|
175
|
-
<RequestId>4ef75373-659c-11e0-bdf6-e3d62a364c28</RequestId>
|
176
|
-
</ResponseMetadata>
|
177
|
-
</ModifyInstanceGroupsResponse>
|
178
|
-
RESPONSE
|
179
|
-
end
|
180
277
|
it "should yield the XML result" do
|
181
278
|
aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key")
|
182
|
-
aws_request.should_receive(:aws_emr_request).and_return(
|
279
|
+
aws_request.should_receive(:aws_emr_request).and_return("xml result!")
|
183
280
|
Elasticity::AwsRequest.should_receive(:new).and_return(aws_request)
|
184
281
|
emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key")
|
185
282
|
xml_result = nil
|
186
|
-
emr.modify_instance_groups({"ig-1" => 2})
|
283
|
+
emr.modify_instance_groups({"ig-1" => 2}) do |xml|
|
187
284
|
xml_result = xml
|
188
285
|
end
|
189
|
-
xml_result.should ==
|
286
|
+
xml_result.should == "xml result!"
|
190
287
|
end
|
191
288
|
end
|
192
289
|
|
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:
|
4
|
+
hash: 1
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: "0.
|
8
|
+
- 5
|
9
|
+
version: "0.5"
|
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-
|
17
|
+
date: 2011-04-16 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -128,6 +128,8 @@ files:
|
|
128
128
|
- lib/elasticity/emr.rb
|
129
129
|
- lib/elasticity/job_flow.rb
|
130
130
|
- lib/elasticity/version.rb
|
131
|
+
- spec/fixtures/vcr_cassettes/add_instance_groups/one_group_successful.yml
|
132
|
+
- spec/fixtures/vcr_cassettes/add_instance_groups/one_group_unsuccessful.yml
|
131
133
|
- spec/fixtures/vcr_cassettes/describe_jobflows/all_jobflows.yml
|
132
134
|
- spec/fixtures/vcr_cassettes/direct/terminate_jobflow.yml
|
133
135
|
- spec/fixtures/vcr_cassettes/modify_instance_groups/set_instances_to_3.yml
|
@@ -171,6 +173,8 @@ signing_key:
|
|
171
173
|
specification_version: 3
|
172
174
|
summary: Programmatic access to Amazon's Elastic Map Reduce service.
|
173
175
|
test_files:
|
176
|
+
- spec/fixtures/vcr_cassettes/add_instance_groups/one_group_successful.yml
|
177
|
+
- spec/fixtures/vcr_cassettes/add_instance_groups/one_group_unsuccessful.yml
|
174
178
|
- spec/fixtures/vcr_cassettes/describe_jobflows/all_jobflows.yml
|
175
179
|
- spec/fixtures/vcr_cassettes/direct/terminate_jobflow.yml
|
176
180
|
- spec/fixtures/vcr_cassettes/modify_instance_groups/set_instances_to_3.yml
|