diff --git a/app/controllers/execution_environments_controller.rb b/app/controllers/execution_environments_controller.rb index bd5e96d0..5b966fb1 100644 --- a/app/controllers/execution_environments_controller.rb +++ b/app/controllers/execution_environments_controller.rb @@ -133,12 +133,12 @@ class ExecutionEnvironmentsController < ApplicationController end def set_docker_images - DockerClient.check_availability! - @docker_images = DockerClient.image_tags.sort - rescue DockerClient::Error => e - @docker_images = [] + @docker_images ||= ExecutionEnvironment.pluck(:docker_image) + @docker_images += Runner.strategy_class.available_images + rescue Runner::Error::InternalServerError => e flash[:warning] = e.message - Sentry.capture_exception(e) + ensure + @docker_images = @docker_images.sort.uniq end private :set_docker_images diff --git a/lib/runner/strategy.rb b/lib/runner/strategy.rb index 908be168..418c679e 100644 --- a/lib/runner/strategy.rb +++ b/lib/runner/strategy.rb @@ -9,6 +9,10 @@ class Runner::Strategy raise NotImplementedError end + def self.available_images + raise NotImplementedError + end + def self.sync_environment(_environment) raise NotImplementedError end diff --git a/lib/runner/strategy/docker_container_pool.rb b/lib/runner/strategy/docker_container_pool.rb index 3e0f2e3b..272278a3 100644 --- a/lib/runner/strategy/docker_container_pool.rb +++ b/lib/runner/strategy/docker_container_pool.rb @@ -8,6 +8,13 @@ class Runner::Strategy::DockerContainerPool < Runner::Strategy @config ||= CodeOcean::Config.new(:docker).read(erb: true) end + def self.available_images + DockerClient.check_availability! + DockerClient.image_tags + rescue DockerClient::Error => e + raise Runner::Error::InternalServerError.new(e.message) + end + def self.sync_environment(_environment) # There is no dedicated sync mechanism yet true diff --git a/lib/runner/strategy/poseidon.rb b/lib/runner/strategy/poseidon.rb index 5dc649ff..d3c27bd2 100644 --- a/lib/runner/strategy/poseidon.rb +++ b/lib/runner/strategy/poseidon.rb @@ -13,6 +13,13 @@ class Runner::Strategy::Poseidon < Runner::Strategy @config ||= CodeOcean::Config.new(:code_ocean).read[:runner_management] || {} end + def self.available_images + # Images are pulled when needed for a new execution environment + # and cleaned up automatically if no longer in use. + # Hence, there is no additional image that we need to return + [] + end + def self.headers @headers ||= {'Content-Type' => 'application/json', 'Poseidon-Token' => config[:token]} end diff --git a/spec/controllers/execution_environments_controller_spec.rb b/spec/controllers/execution_environments_controller_spec.rb index 68f4ed45..cfa94fb3 100644 --- a/spec/controllers/execution_environments_controller_spec.rb +++ b/spec/controllers/execution_environments_controller_spec.rb @@ -114,6 +114,7 @@ describe ExecutionEnvironmentsController do let(:docker_images) { [1, 2, 3] } before do + allow(Runner).to receive(:strategy_class).and_return Runner::Strategy::DockerContainerPool allow(DockerClient).to receive(:check_availability!).at_least(:once) allow(DockerClient).to receive(:image_tags).and_return(docker_images) controller.send(:set_docker_images) @@ -126,6 +127,7 @@ describe ExecutionEnvironmentsController do let(:error_message) { 'Docker is unavailable' } before do + allow(Runner).to receive(:strategy_class).and_return Runner::Strategy::DockerContainerPool allow(DockerClient).to receive(:check_availability!).at_least(:once).and_raise(DockerClient::Error.new(error_message)) controller.send(:set_docker_images) end