require 'spec_helper' describe Elasticity::EMR do describe "#add_instance_groups" do describe "integration happy path" do context "when properly specified" do use_vcr_cassette "add_instance_groups/one_group_successful", :record => :none it "should add the instance groups" do emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) instance_group_config = { :instance_count => 1, :instance_role => "TASK", :instance_type => "m1.small", :market => "ON_DEMAND", :name => "Go Canucks Go!" } instance_group_ids = emr.add_instance_groups("j-OALI7TZTQMHX", [instance_group_config]) instance_group_ids.should == ["ig-2GOVEN6HVJZID"] end end context "when improperly specified" do use_vcr_cassette "add_instance_groups/one_group_unsuccessful", :record => :none it "should add the instance groups" do emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) instance_group_config = { :bid_price => 0, :instance_count => 1, :instance_role => "TASK", :instance_type => "m1.small", :market => "ON_DEMAND", :name => "Go Canucks Go!" } lambda { emr.add_instance_groups("j-19WDDS68ZUENP", [instance_group_config]) }.should raise_error(ArgumentError, "Task instance group already exists in the job flow, cannot add more task groups") end end end describe "unit tests" do context "when multiple instance groups are specified" do before do @add_instance_groups_xml = <<-ADD_GROUPS j-OALI7TZTQMHX ig-1 ig-2 ig-3 ADD_GROUPS end it "should iterate over them and send the correct params to AWS" do instance_group_configs = [ {:instance_type=>"m1.small", :instance_role=>"CORE", :market=>"ON_DEMAND", :instance_count=>1, :name=>"Go Canucks Go!", :bid_price=>0}, {:instance_type=>"m1.small", :instance_role=>"CORE", :market=>"ON_DEMAND", :instance_count=>1, :name=>"Go Canucks Go!", :bid_price=>0}, ] aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).with({ "Operation" => "AddInstanceGroups", "InstanceGroups.member.1.Name"=>"Go Canucks Go!", "InstanceGroups.member.1.InstanceRole"=>"CORE", "InstanceGroups.member.1.InstanceCount"=>1, "InstanceGroups.member.1.BidPrice"=>0, "InstanceGroups.member.1.InstanceType"=>"m1.small", "InstanceGroups.member.1.Market"=>"ON_DEMAND", "InstanceGroups.member.2.Name"=>"Go Canucks Go!", "InstanceGroups.member.2.InstanceRole"=>"CORE", "InstanceGroups.member.2.InstanceCount"=>1, "InstanceGroups.member.2.BidPrice"=>0, "InstanceGroups.member.2.InstanceType"=>"m1.small", "InstanceGroups.member.2.Market"=>"ON_DEMAND", "JobFlowId"=>"j-19WDDS68ZUENP" }) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") emr.add_instance_groups("j-19WDDS68ZUENP", instance_group_configs) end it "should return an array of the instance groups created" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).and_return(@add_instance_groups_xml) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") emr.add_instance_groups("", []).should == ["ig-1", "ig-2", "ig-3"] end end context "when a block is provided" do it "should yield the XML result" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).and_return("AWS XML") Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") xml_result = nil emr.add_instance_groups("", []) do |xml| xml_result = xml end xml_result.should == "AWS XML" end end end end describe "#add_jobflow_steps" do describe "integration happy path" do use_vcr_cassette "add_jobflow_steps/add_multiple_steps", :record => :none before do @setup_pig_step = { :action_on_failure => "TERMINATE_JOB_FLOW", :hadoop_jar_step => { :args => [ "s3://elasticmapreduce/libs/pig/pig-script", "--base-path", "s3://elasticmapreduce/libs/pig/", "--install-pig" ], :jar => "s3://elasticmapreduce/libs/script-runner/script-runner.jar" }, :name => "Setup Pig" } @emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) @jobflow_id = @emr.run_job_flow({ :name => "Elasticity Test Flow (EMR Pig Script)", :instances => { :ec2_key_name => "sharethrough-dev", :instance_count => 2, :master_instance_type => "m1.small", :slave_instance_type => "m1.small", }, :steps => [@setup_pig_step] }) end it "should add a job flow step to the specified job flow" do @emr.add_jobflow_steps(@jobflow_id, { :steps => [ @setup_pig_step.merge(:name => "Setup Pig 2"), @setup_pig_step.merge(:name => "Setup Pig 3") ] }) jobflow = @emr.describe_jobflows.select { |jf| jf.jobflow_id = @jobflow_id }.first jobflow.steps.map(&:name).should == ["Setup Pig", "Setup Pig 2", "Setup Pig 3"] end end describe "unit tests" do it "should add the specified steps to the job flow" do aws_request = Elasticity::AwsRequest.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) aws_request.should_receive(:aws_emr_request).with({ "Operation" => "AddJobFlowSteps", "JobFlowId" => "j-1", "Steps.member.1.Name" => "Step 1", "Steps.member.1.ActionOnFailure" => "TERMINATE_JOB_FLOW", "Steps.member.1.HadoopJarStep.Jar" => "jar1", "Steps.member.1.HadoopJarStep.Args.member.1" => "arg1-1", "Steps.member.1.HadoopJarStep.Args.member.2" => "arg1-2", "Steps.member.2.Name" => "Step 2", "Steps.member.2.ActionOnFailure" => "CONTINUE", "Steps.member.2.HadoopJarStep.Jar" => "jar2", "Steps.member.2.HadoopJarStep.Args.member.1" => "arg2-1", "Steps.member.2.HadoopJarStep.Args.member.2" => "arg2-2", }) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) emr.add_jobflow_steps("j-1", { :steps => [ { :action_on_failure => "TERMINATE_JOB_FLOW", :name => "Step 1", :hadoop_jar_step => { :args => ["arg1-1", "arg1-2"], :jar => "jar1", } }, { :action_on_failure => "CONTINUE", :name => "Step 2", :hadoop_jar_step => { :args => ["arg2-1", "arg2-2"], :jar => "jar2", } } ] }) end context "when there is an error" do before do @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" @error_xml = <<-ERROR #{@error_message} ERROR end it "should raise an ArgumentError with the error message" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") @exception = RestClient::BadRequest.new @exception.should_receive(:http_body).and_return(@error_xml) aws_request.should_receive(:aws_emr_request).and_raise(@exception) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") lambda { emr.add_jobflow_steps("", {}) }.should raise_error(ArgumentError, @error_message) end end context "when a block is given" do it "should yield the XML result" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).and_return("xml_response") Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") xml_result = nil emr.add_jobflow_steps("", {}) do |xml| xml_result = xml end xml_result.should == "xml_response" end end end end describe "#describe_jobflows" do describe "integration happy path" do use_vcr_cassette "describe_jobflows/all_jobflows", :record => :none it "should return the names of all running job flows" do emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) jobflows = emr.describe_jobflows jobflows.map(&:name).should == ["WM+RS", "Interactive Audience Hive Test", "Audience (Hive)", "Audience Reporting"] jobflows.map(&:jobflow_id).should == ["j-1MZ5TVWFJRSKN", "j-38EU2XZQP9KJ4", "j-2TDCVGEEHOFI9", "j-NKKQ429D858I"] jobflows.map(&:state).should == ["TERMINATED", "TERMINATED", "TERMINATED", "TERMINATED"] end end describe "unit tests" do before do @describe_jobflows_xml = <<-JOBFLOWS TERMINATED j-p Pig Job TERMINATED j-h Hive Job JOBFLOWS end it "should return the names of all running job flows" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).with({"Operation" => "DescribeJobFlows"}).and_return(@describe_jobflows_xml) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") jobflows = emr.describe_jobflows jobflows.map(&:name).should == ["Pig Job", "Hive Job"] end it "should accept additional parameters" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).with({"Operation" => "DescribeJobFlows","CreatedBefore" => "2011-10-04"}).and_return(@describe_jobflows_xml) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") emr.describe_jobflows(:CreatedBefore => "2011-10-04") end context "when a block is provided" do it "should yield the XML result" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).and_return("describe!") Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") xml_result = nil emr.describe_jobflows do |xml| xml_result = xml end xml_result.should == "describe!" end end end end describe "#describe_jobflow" do before do @describe_jobflows_xml = <<-JOBFLOWS TERMINATED j-3UN6WX5RRO2AG The One Job Flow JOBFLOWS end it "should ask AWS about the specified job flow" do aws_request = Elasticity::AwsRequest.new("","") aws_request.should_receive(:aws_emr_request).with({ "Operation" => "DescribeJobFlows", "JobFlowIds.member.1" => "j-3UN6WX5RRO2AG" }) Elasticity::AwsRequest.stub(:new).and_return(aws_request) emr = Elasticity::EMR.new("", "") emr.describe_jobflow("j-3UN6WX5RRO2AG") end context "when the job flow ID exists" do it "should return a JobFlow" do aws_request = Elasticity::AwsRequest.new("","") aws_request.stub(:aws_emr_request).with({ "Operation" => "DescribeJobFlows", "JobFlowIds.member.1" => "j-3UN6WX5RRO2AG" }).and_return(@describe_jobflows_xml) Elasticity::AwsRequest.stub(:new).and_return(aws_request) emr = Elasticity::EMR.new("", "") jobflow = emr.describe_jobflow("j-3UN6WX5RRO2AG") jobflow.jobflow_id.should == "j-3UN6WX5RRO2AG" end end context "when there is an error" do before do @error_xml = <<-ERROR Specified job flow ID not valid ERROR end it "should raise an ArgumentError with the error message" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") @exception = RestClient::BadRequest.new @exception.should_receive(:http_body).and_return(@error_xml) aws_request.should_receive(:aws_emr_request).and_raise(@exception) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") lambda { emr.describe_jobflow("bad_jobflow_id") }.should raise_error(ArgumentError, "Specified job flow ID not valid") end end context "when a block is provided" do it "should yield to the block" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).and_return("describe!") Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") xml_result = nil emr.describe_jobflow("_") do |xml| xml_result = xml end xml_result.should == "describe!" end end end describe "#modify_instance_groups" do describe "integration happy path" do context "when the instance group exists" do use_vcr_cassette "modify_instance_groups/set_instances_to_3", :record => :none it "should terminate the specified jobflow" do emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) instance_group_config = {"ig-2T1HNUO61BG3O" => 2} emr.modify_instance_groups(instance_group_config) end end end describe "unit tests" do context "when the instance group exists" do it "should modify the specified instance group" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).with({ "Operation" => "ModifyInstanceGroups", "InstanceGroups.member.1.InstanceGroupId" => "ig-1", "InstanceGroups.member.1.InstanceCount" => 2 }) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") emr.modify_instance_groups({"ig-1" => 2}) end end context "when a block is given" do it "should yield the XML result" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).and_return("xml result!") Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") xml_result = nil emr.modify_instance_groups({"ig-1" => 2}) do |xml| xml_result = xml end xml_result.should == "xml result!" end end context "when there is an error" do before do @error_message = "1 validation error detected: Value null at 'instanceGroups.1.member.instanceCount' failed to satisfy constraint: Member must not be null" @error_xml = <<-ERROR #{@error_message} ERROR end it "should raise an ArgumentError with the error message" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") @exception = RestClient::BadRequest.new @exception.should_receive(:http_body).and_return(@error_xml) aws_request.should_receive(:aws_emr_request).and_raise(@exception) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") lambda { emr.modify_instance_groups({"ig-1" => 2}) }.should raise_error(ArgumentError, @error_message) end end end end describe "#run_jobflow" do describe "integration happy path" do context "when the job flow is properly specified" do use_vcr_cassette "run_jobflow/word_count", :record => :none it "should start the specified job flow" do emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) jobflow_id = emr.run_job_flow({ :name => "Elasticity Test Flow (EMR Pig Script)", :instances => { :ec2_key_name => "sharethrough-dev", :hadoop_version => "0.20", :instance_count => 2, :master_instance_type => "m1.small", :placement => { :availability_zone => "us-east-1a" }, :slave_instance_type => "m1.small", }, :steps => [ { :action_on_failure => "TERMINATE_JOB_FLOW", :hadoop_jar_step => { :args => [ "s3://elasticmapreduce/libs/pig/pig-script", "--base-path", "s3://elasticmapreduce/libs/pig/", "--install-pig" ], :jar => "s3://elasticmapreduce/libs/script-runner/script-runner.jar" }, :name => "Setup Pig" }, { :action_on_failure => "TERMINATE_JOB_FLOW", :hadoop_jar_step => { :args => [ "s3://elasticmapreduce/libs/pig/pig-script", "--run-pig-script", "--args", "-p", "INPUT=s3n://elasticmapreduce/samples/pig-apache/input", "-p", "OUTPUT=s3n://slif-elasticity/pig-apache/output/2011-04-19", "s3n://elasticmapreduce/samples/pig-apache/do-reports.pig" ], :jar => "s3://elasticmapreduce/libs/script-runner/script-runner.jar" }, :name => "Run Pig Script" } ] }) jobflow_id.should == "j-G6N5HA528AD4" end end end describe "unit tests" do it "should return the job flow ID of the new job" do run_jobflow_response = <<-RESPONSE j-N500G8Y8U7ZQ a6dddf4c-6a49-11e0-b6c0-e9580d1f7304 RESPONSE aws_request = Elasticity::AwsRequest.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) aws_request.should_receive(:aws_emr_request).and_return(run_jobflow_response) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) jobflow_id = emr.run_job_flow({}) jobflow_id.should == "j-N500G8Y8U7ZQ" end it "should run the specified job flow" do aws_request = Elasticity::AwsRequest.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) aws_request.should_receive(:aws_emr_request).with({ "Operation" => "RunJobFlow", "Name" => "Job flow name", "Instances.MasterInstanceType" => "m1.small", "Instances.Placement.AvailabilityZone" => "us-east-1a", "Steps.member.1.Name" => "Streaming Job", "Steps.member.1.ActionOnFailure" => "TERMINATE_JOB_FLOW", "Steps.member.1.HadoopJarStep.Jar" => "/home/hadoop/contrib/streaming/hadoop-streaming.jar", "Steps.member.1.HadoopJarStep.Args.member.1" => "-input", "Steps.member.1.HadoopJarStep.Args.member.2" => "s3n://elasticmapreduce/samples/wordcount/input" }) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) emr.run_job_flow({ :name => "Job flow name", :instances => { :master_instance_type => "m1.small", :placement => { :availability_zone => "us-east-1a" } }, :steps => [ { :action_on_failure => "TERMINATE_JOB_FLOW", :name => "Streaming Job", :hadoop_jar_step => { :args => ["-input", "s3n://elasticmapreduce/samples/wordcount/input"], :jar => "/home/hadoop/contrib/streaming/hadoop-streaming.jar", } } ] }) end context "when there is an error" do before do @error_message = "1 validation error detected: Value null at 'instanceGroups.1.member.instanceCount' failed to satisfy constraint: Member must not be null" @error_xml = <<-ERROR #{@error_message} ERROR end it "should raise an ArgumentError with the error message" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") @exception = RestClient::BadRequest.new @exception.should_receive(:http_body).and_return(@error_xml) aws_request.should_receive(:aws_emr_request).and_raise(@exception) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") lambda { emr.run_job_flow({}) }.should raise_error(ArgumentError, @error_message) end end context "when a block is given" do it "should yield the XML result" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).and_return("jobflow_id!") Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") xml_result = nil emr.run_job_flow({}) do |xml| xml_result = xml end xml_result.should == "jobflow_id!" end end end end describe "#terminate_jobflows" do describe "integration happy path" do context "when the job flow exists" do use_vcr_cassette "terminate_jobflows/one_jobflow", :record => :none it "should terminate the specified jobflow" do emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) emr.terminate_jobflows("j-1MZ5TVWFJRSKN") end end end describe "unit tests" do context "when the jobflow exists" do before do @terminate_jobflows_xml = <<-RESPONSE 2690d7eb-ed86-11dd-9877-6fad448a8419 RESPONSE end it "should terminate the specific jobflow" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).with({ "Operation" => "TerminateJobFlows", "JobFlowIds.member.1" => "j-1" }).and_return(@terminate_jobflows_xml) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") emr.terminate_jobflows("j-1") end end context "when the jobflow does not exist" do it "should raise an ArgumentError" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).and_raise(RestClient::BadRequest) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") lambda { emr.terminate_jobflows("invalid_jobflow_id") }.should raise_error(ArgumentError) end end context "when a block is given" do it "should yield the XML result" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).and_return("terminated!") Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") xml_result = nil emr.terminate_jobflows("j-1") do |xml| xml_result = xml end xml_result.should == "terminated!" end end end end describe "#set_termination_protection" do describe "integration happy path" do context "when protecting multiple job flows" do use_vcr_cassette "set_termination_protection/protect_multiple_job_flows", :record => :none it "should protect the specified job flows" do emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) emr.set_termination_protection(["j-1B4D1XP0C0A35", "j-1YG2MYL0HVYS5"], true) end end context "when specifying a job flow that doesn't exist" do use_vcr_cassette "set_termination_protection/nonexistent_job_flows", :record => :none it "should have an error" do emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) lambda { emr.set_termination_protection(["j-1B4D1XP0C0A35", "j-2"], true) }.should raise_error(ArgumentError, "Specified job flow ID not valid") end end end describe "unit tests" do it "should enable protection on the specified job flows" do aws_request = Elasticity::AwsRequest.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) aws_request.should_receive(:aws_emr_request).with({ "Operation" => "SetTerminationProtection", "JobFlowIds.member.1" => "jobflow1", "JobFlowIds.member.2" => "jobflow2", "TerminationProtected" => true }) emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) emr.set_termination_protection(["jobflow1", "jobflow2"], true) end it "should disable protection on the specified job flows" do aws_request = Elasticity::AwsRequest.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) aws_request.should_receive(:aws_emr_request).with({ "Operation" => "SetTerminationProtection", "JobFlowIds.member.1" => "jobflow1", "JobFlowIds.member.2" => "jobflow2", "TerminationProtected" => false }) emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) emr.set_termination_protection(["jobflow1", "jobflow2"], false) end it "should enable protection when not specified" do aws_request = Elasticity::AwsRequest.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) aws_request.should_receive(:aws_emr_request).with({ "Operation" => "SetTerminationProtection", "JobFlowIds.member.1" => "jobflow1", "JobFlowIds.member.2" => "jobflow2", "TerminationProtected" => true }) emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) emr.set_termination_protection(["jobflow1", "jobflow2"]) end context "when a block is given" do before do @xml_response = <<-RESPONSE 755ebe8a-6923-11e0-a9c2-c126f1bb4493 RESPONSE end it "should yield the XML result" do aws_request = Elasticity::AwsRequest.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) aws_request.should_receive(:aws_emr_request).and_return(@xml_response) emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) xml = nil emr.set_termination_protection([]) do |aws_response| xml = aws_response end xml.should == @xml_response end end end end describe "#direct" do describe "integration happy path" do use_vcr_cassette "direct/terminate_jobflow", :record => :none it "should terminate the specified jobflow" do emr = Elasticity::EMR.new(AWS_ACCESS_KEY_ID, AWS_SECRET_KEY) params = { "Operation" => "TerminateJobFlows", "JobFlowIds.member.1" => "j-1MZ5TVWFJRSKN" } emr.direct(params) end end describe "unit tests" do before do @terminate_jobflows_xml = <<-RESPONSE 2690d7eb-ed86-11dd-9877-6fad448a8419 RESPONSE end it "should pass through directly to the request" do aws_request = Elasticity::AwsRequest.new("aws_access_key_id", "aws_secret_key") aws_request.should_receive(:aws_emr_request).with({ "Operation" => "TerminateJobFlows", "JobFlowIds.member.1" => "j-1" }).and_return(@terminate_jobflows_xml) Elasticity::AwsRequest.should_receive(:new).and_return(aws_request) emr = Elasticity::EMR.new("aws_access_key_id", "aws_secret_key") params = { "Operation" => "TerminateJobFlows", "JobFlowIds.member.1" => "j-1" } emr.direct(params).should == @terminate_jobflows_xml end end end describe ".convert_ruby_to_aws" do it "should convert the params" do add_jobflow_steps_params = { :job_flow_id => "j-1", :steps => [ { :action_on_failure => "CONTINUE", :name => "First New Job Step", :hadoop_jar_step => { :args => ["arg1", "arg2", "arg3",], :jar => "first_step.jar", :main_class => "first_class.jar" } }, { :action_on_failure => "CANCEL_AND_WAIT", :name => "Second New Job Step", :hadoop_jar_step => { :args => ["arg4", "arg5", "arg6",], :jar => "second_step.jar", :main_class => "second_class.jar" } } ] } expected_result = { "JobFlowId" => "j-1", "Steps.member.1.Name" => "First New Job Step", "Steps.member.1.ActionOnFailure" => "CONTINUE", "Steps.member.1.HadoopJarStep.Jar" => "first_step.jar", "Steps.member.1.HadoopJarStep.MainClass" => "first_class.jar", "Steps.member.1.HadoopJarStep.Args.member.1" => "arg1", "Steps.member.1.HadoopJarStep.Args.member.2" => "arg2", "Steps.member.1.HadoopJarStep.Args.member.3" => "arg3", "Steps.member.2.Name" => "Second New Job Step", "Steps.member.2.ActionOnFailure" => "CANCEL_AND_WAIT", "Steps.member.2.HadoopJarStep.Jar" => "second_step.jar", "Steps.member.2.HadoopJarStep.MainClass" => "second_class.jar", "Steps.member.2.HadoopJarStep.Args.member.1" => "arg4", "Steps.member.2.HadoopJarStep.Args.member.2" => "arg5", "Steps.member.2.HadoopJarStep.Args.member.3" => "arg6" } Elasticity::EMR.send(:convert_ruby_to_aws, add_jobflow_steps_params).should == expected_result end end end