Refactoring main invocation path to return error codes

This commit is contained in:
Charles Care
2019-10-18 19:12:31 +01:00
parent 3524af3550
commit 80c267e397
6 changed files with 212 additions and 33 deletions

View File

@@ -9,9 +9,8 @@ module Pipeline::Rpc::Worker
@return_address = return_address
end
def setup(track_slug, version, exercise_slug, solution_slug)
track_dir = environment.track_dir(track_slug, version)
Pipeline::Runtime::AnalysisRun.new(track_dir, exercise_slug, solution_slug)
def setup_container_run(track_dir, exercise_slug, job_slug)
Pipeline::Runtime::AnalysisRun.new(track_dir, exercise_slug, job_slug)
end
def prepare_folder(iteration_folder)

View File

@@ -2,50 +2,93 @@ module Pipeline::Rpc::Worker
class ContainerAction < WorkerAction
attr_reader :reader, :return_address, :s3
attr_reader :reader, :return_address, :s3, :track_slug, :container_version
def initialize(request, return_address)
@request = request
@return_address = return_address
end
def setup(track_slug, version, exercise_slug, job_slug)
track_dir = environment.track_dir(track_slug, version)
Pipeline::Runtime::AnalysisRun.new(track_dir, exercise_slug, job_slug)
end
def invoke
@s3 = Aws::S3::Client.new(
credentials: parse_credentials(request["context"]),
region: "eu-west-1")
language_slug = request["track_slug"]
exercise_slug = request["exercise_slug"]
job_slug = request["id"]
container_version = request["container_version"]
@track_slug = request["track_slug"]
@exercise_slug = request["exercise_slug"]
@job_slug = request["id"]
@container_version = request["container_version"]
unless environment.released?(language_slug, container_version)
return {
error: "Container #{language_slug}:#{container_version} isn't available"
check_container
setup_run unless @error
prepare_input unless @error
run_container unless @error
response = {return_address: return_address}
if @error
response[:msg_type] = :error_response
response.merge(@error)
else
response[:msg_type] = :response
response[:return_address] = return_address
response.merge(@result)
end
end
def check_container
unless environment.released?(track_slug, container_version)
@error = {
status_code: 404,
error: "Container #{track_slug}:#{container_version} isn't available"
}
end
end
def setup_run
track_dir = environment.track_dir(track_slug, container_version)
analysis_run = setup(language_slug, container_version, exercise_slug, job_slug)
analysis_run.prepare_iteration do |iteration_folder|
prepare_folder(iteration_folder)
end
begin
result = analysis_run.analyze!
result["return_address"] = return_address
result['msg_type'] = 'response'
result
@analysis_run = setup_container_run(track_dir, @exercise_slug, @job_slug)
rescue => e
puts e
ensure
puts "DONE"
@error = {
status_code: 500,
error: "Failure setting up job",
detail: e
}
end
end
def prepare_input
begin
@analysis_run.prepare_iteration do |iteration_folder|
prepare_folder(iteration_folder)
end
rescue => e
@error = {
status_code: 500,
error: "Failure preparing input",
detail: e
}
end
end
def run_container
begin
@result = @analysis_run.analyze!
rescue => e
@error = {
status_code: 500,
error: "Error from container",
detail: e
}
end
end
def setup_container_run(track_dir, exercise_slug, job_slug)
raise "Please create run command"
end
def prepare_folder(iteration_folder)
raise "Please prepare input"
end

View File

@@ -6,9 +6,8 @@ module Pipeline::Rpc::Worker
super(request, return_address)
end
def setup(track_slug, version, exercise_slug, solution_slug)
track_dir = environment.track_dir(track_slug, version)
Pipeline::Runtime::RepresentRun.new(track_dir, exercise_slug, solution_slug)
def setup_container_run(track_dir, exercise_slug, job_slug)
Pipeline::Runtime::RepresentRun.new(track_dir, exercise_slug, job_slug)
end
end

View File

@@ -6,9 +6,8 @@ module Pipeline::Rpc::Worker
super(request, return_address)
end
def setup(track_slug, version, exercise_slug, solution_slug)
track_dir = environment.track_dir(track_slug, version)
Pipeline::Runtime::TestRun.new(track_dir, exercise_slug, solution_slug)
def setup_container_run(track_dir, exercise_slug, job_slug)
Pipeline::Runtime::TestRun.new(track_dir, exercise_slug, job_slug)
end
end

View File

@@ -0,0 +1,108 @@
require 'test_helper'
class Pipeline::Rpc::Worker::WorkerActionTest < Minitest::Test
def setup
@credentials = {
"access_key_id" => "ACCESS_KEY_ID",
"secret_access_key" => "SECRET_KEY",
"session_token" => "SESSION",
}
@request = {
"context" => { "credentials" => @credentials },
"track_slug" => "demo",
"exercise_slug" => "my-exercise",
"id" => "my-input-id",
"container_version" => "abcdef"
}
@return_address = "_return_address"
@environment = mock()
@action = Pipeline::Rpc::Worker::ContainerAction.new(@request, @return_address)
@action.environment = @environment
end
def test_prepare_folder_raises
error = assert_raises do
@action.prepare_folder("/tmp/my_folder")
end
assert_equal "Please prepare input", error.message
end
def test_setup_container_run
error = assert_raises do
@action.setup_container_run("/tmp/my_folder", "foo", "bar")
end
assert_equal "Please create run command", error.message
end
def test_invoke_when_correct_container_is_not_released
@environment.expects(:released?).with("demo", "abcdef").returns(false)
result = @action.invoke
assert_equal 404, result[:status_code]
assert_equal "Container demo:abcdef isn't available", result[:error]
assert_equal :error_response, result[:msg_type]
end
def test_invoke_when_set_fails
@environment.expects(:released?).with("demo", "abcdef").returns(true)
@environment.expects(:track_dir).with("demo", "abcdef").returns("/tmp/foobar")
@action.expects(:setup_container_run).raises("Ouch! Couldn't setup job")
result = @action.invoke
assert_equal 500, result[:status_code]
assert_equal "Failure setting up job", result[:error]
assert_equal :error_response, result[:msg_type]
end
def test_invoke_when_prepare_iteration_fails
@environment.expects(:released?).with("demo", "abcdef").returns(true)
@environment.expects(:track_dir).with("demo", "abcdef").returns("/tmp/foobar")
@stub_job_invoker = mock()
@stub_job_invoker.expects(:prepare_iteration).raises("Ouch! Couldn't prepare input")
@stub_job_invoker.expects(:analyze!).never
@action.expects(:setup_container_run).with("/tmp/foobar", "my-exercise", "my-input-id").returns @stub_job_invoker
result = @action.invoke
assert_equal 500, result[:status_code]
assert_equal "Failure preparing input", result[:error]
assert_equal :error_response, result[:msg_type]
end
def test_invoke_when_container_errors
@environment.expects(:released?).with("demo", "abcdef").returns(true)
@environment.expects(:track_dir).with("demo", "abcdef").returns("/tmp/foobar")
@stub_job_invoker = mock()
@stub_job_invoker.expects(:prepare_iteration)
@stub_job_invoker.expects(:analyze!).raises("Container error")
@action.expects(:setup_container_run).with("/tmp/foobar", "my-exercise", "my-input-id").returns @stub_job_invoker
result = @action.invoke
assert_equal 500, result[:status_code]
assert_equal "Error from container", result[:error]
assert_equal :error_response, result[:msg_type]
end
def test_invoke
@invocation_result = { a: 1, b: 2 }
@environment.expects(:released?).with("demo", "abcdef").returns(true)
@environment.expects(:track_dir).with("demo", "abcdef").returns("/tmp/foobar")
@stub_job_invoker = mock()
@stub_job_invoker.expects(:prepare_iteration)
@stub_job_invoker.expects(:analyze!).returns(@invocation_result)
@action.expects(:setup_container_run).with("/tmp/foobar", "my-exercise", "my-input-id").returns @stub_job_invoker
result = @action.invoke
assert_equal 1, result[:a]
assert_equal 2, result[:b]
assert_equal :response, result[:msg_type]
end
end

View File

@@ -0,0 +1,31 @@
require 'test_helper'
require 'json'
class Pipeline::Rpc::Worker::WorkerActionTest < Minitest::Test
def setup
@action = Pipeline::Rpc::Worker::WorkerAction.new
end
def test_invoke_does_nothing
@action.invoke
end
def test_parse_credentials
@credentials = {
"access_key_id" => "ACCESS_KEY_ID",
"secret_access_key" => "SECRET_KEY",
"session_token" => "SESSION",
}
@request = {
"credentials" => @credentials
}
credentials = @action.parse_credentials(@request)
assert_equal Aws::Credentials, credentials.class
assert_equal "ACCESS_KEY_ID", credentials.access_key_id
assert_equal "SECRET_KEY", credentials.secret_access_key
assert_equal "SESSION", credentials.session_token
end
end