Copy execution environment to Poseidon on create and update
When creating or updating an execution environment, an API call to Poseidon is made with the necessary information to create the corresponding Nomad job. If runner management is configured, his will display a warning (currently in the same color as if it were a success) in the UI, if the API call fails. The environment is saved even if it fails. If runner management is not configured, this warning will not be created.
This commit is contained in:

committed by
Sebastian Serth

parent
b762c73ddd
commit
90fac7b94c
@ -5,10 +5,13 @@ module CommonBehavior
|
||||
@object = options[:object]
|
||||
respond_to do |format|
|
||||
if @object.save
|
||||
yield if block_given?
|
||||
notice = t('shared.object_created', model: @object.class.model_name.human)
|
||||
if block_given?
|
||||
result = yield
|
||||
notice = result if result.present?
|
||||
end
|
||||
path = options[:path].try(:call) || @object
|
||||
respond_with_valid_object(format, notice: t('shared.object_created', model: @object.class.model_name.human),
|
||||
path: path, status: :created)
|
||||
respond_with_valid_object(format, notice: notice, path: path, status: :created)
|
||||
else
|
||||
respond_with_invalid_object(format, template: :new)
|
||||
end
|
||||
@ -42,9 +45,13 @@ path: path, status: :created)
|
||||
@object = options[:object]
|
||||
respond_to do |format|
|
||||
if @object.update(options[:params])
|
||||
notice = t('shared.object_updated', model: @object.class.model_name.human)
|
||||
if block_given?
|
||||
result = yield
|
||||
notice = result if result.present?
|
||||
end
|
||||
path = options[:path] || @object
|
||||
respond_with_valid_object(format, notice: t('shared.object_updated', model: @object.class.model_name.human),
|
||||
path: path, status: :ok)
|
||||
respond_with_valid_object(format, notice: notice, path: path, status: :ok)
|
||||
else
|
||||
respond_with_invalid_object(format, template: :edit)
|
||||
end
|
||||
|
@ -3,6 +3,8 @@
|
||||
class ExecutionEnvironmentsController < ApplicationController
|
||||
include CommonBehavior
|
||||
|
||||
RUNNER_MANAGEMENT_PRESENT = CodeOcean::Config.new(:code_ocean).read[:runner_management].present?
|
||||
|
||||
before_action :set_docker_images, only: %i[create edit new update]
|
||||
before_action :set_execution_environment, only: MEMBER_ACTIONS + %i[execute_command shell statistics]
|
||||
before_action :set_testing_framework_adapters, only: %i[create edit new update]
|
||||
@ -15,7 +17,9 @@ class ExecutionEnvironmentsController < ApplicationController
|
||||
def create
|
||||
@execution_environment = ExecutionEnvironment.new(execution_environment_params)
|
||||
authorize!
|
||||
create_and_respond(object: @execution_environment)
|
||||
create_and_respond(object: @execution_environment) do
|
||||
copy_execution_environment_to_poseidon
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@ -105,7 +109,7 @@ class ExecutionEnvironmentsController < ApplicationController
|
||||
|
||||
def execution_environment_params
|
||||
if params[:execution_environment].present?
|
||||
params[:execution_environment].permit(:docker_image, :exposed_ports, :editor_mode, :file_extension, :file_type_id, :help, :indent_size, :memory_limit, :name, :network_enabled, :permitted_execution_time, :pool_size, :run_command, :test_command, :testing_framework).merge(
|
||||
params[:execution_environment].permit(:docker_image, :exposed_ports, :editor_mode, :file_extension, :file_type_id, :help, :indent_size, :memory_limit, :cpu_limit, :name, :network_enabled, :permitted_execution_time, :pool_size, :run_command, :test_command, :testing_framework).merge(
|
||||
user_id: current_user.id, user_type: current_user.class.name
|
||||
)
|
||||
end
|
||||
@ -155,6 +159,15 @@ class ExecutionEnvironmentsController < ApplicationController
|
||||
end
|
||||
|
||||
def update
|
||||
update_and_respond(object: @execution_environment, params: execution_environment_params)
|
||||
update_and_respond(object: @execution_environment, params: execution_environment_params) do
|
||||
copy_execution_environment_to_poseidon
|
||||
end
|
||||
end
|
||||
|
||||
def copy_execution_environment_to_poseidon
|
||||
unless RUNNER_MANAGEMENT_PRESENT && @execution_environment.copy_to_poseidon
|
||||
t('execution_environments.form.errors.not_synced_to_poseidon')
|
||||
end
|
||||
end
|
||||
private :copy_execution_environment_to_poseidon
|
||||
end
|
||||
|
@ -7,6 +7,10 @@ class ExecutionEnvironment < ApplicationRecord
|
||||
include DefaultValues
|
||||
|
||||
VALIDATION_COMMAND = 'whoami'
|
||||
RUNNER_MANAGEMENT_PRESENT = CodeOcean::Config.new(:code_ocean).read[:runner_management].present?
|
||||
BASE_URL = CodeOcean::Config.new(:code_ocean).read[:runner_management][:url] if RUNNER_MANAGEMENT_PRESENT
|
||||
HEADERS = {'Content-Type' => 'application/json'}.freeze
|
||||
DEFAULT_CPU_LIMIT = 20
|
||||
|
||||
after_initialize :set_default_values
|
||||
|
||||
@ -26,6 +30,8 @@ class ExecutionEnvironment < ApplicationRecord
|
||||
validates :permitted_execution_time, numericality: {only_integer: true}, presence: true
|
||||
validates :pool_size, numericality: {only_integer: true}, presence: true
|
||||
validates :run_command, presence: true
|
||||
validates :cpu_limit, presence: true, numericality: {greater_than: 0, only_integer: true}
|
||||
validates :exposed_ports, format: {with: /\A(([[:digit:]]{1,5},)*([[:digit:]]{1,5}))?\z/}
|
||||
|
||||
def set_default_values
|
||||
set_default_values_if_present(permitted_execution_time: 60, pool_size: 0)
|
||||
@ -36,6 +42,33 @@ class ExecutionEnvironment < ApplicationRecord
|
||||
name
|
||||
end
|
||||
|
||||
def copy_to_poseidon
|
||||
return false unless RUNNER_MANAGEMENT_PRESENT
|
||||
|
||||
url = "#{BASE_URL}/execution-environments/#{id}"
|
||||
response = Faraday.put(url, to_json, HEADERS)
|
||||
return true if [201, 204].include? response.status
|
||||
|
||||
Rails.logger.warn("Could not create execution environment in Poseidon, got response: #{response.as_json}")
|
||||
false
|
||||
end
|
||||
|
||||
def to_json(*_args)
|
||||
{
|
||||
id: id,
|
||||
image: docker_image,
|
||||
prewarmingPoolSize: pool_size,
|
||||
cpuLimit: cpu_limit,
|
||||
memoryLimit: memory_limit,
|
||||
networkAccess: network_enabled,
|
||||
exposedPorts: exposed_ports_list,
|
||||
}.to_json
|
||||
end
|
||||
|
||||
def exposed_ports_list
|
||||
(exposed_ports || '').split(',').map(&:to_i)
|
||||
end
|
||||
|
||||
def valid_test_setup?
|
||||
if test_command? ^ testing_framework?
|
||||
errors.add(:test_command,
|
||||
|
@ -15,11 +15,14 @@
|
||||
.help-block.form-text == t('.hints.docker_image')
|
||||
.form-group
|
||||
= f.label(:exposed_ports)
|
||||
= f.text_field(:exposed_ports, class: 'form-control', placeholder: '3000, 4000')
|
||||
= f.text_field(:exposed_ports, class: 'form-control', placeholder: '3000,4000', pattern: '^((\d{1,5},)*(\d{1,5}))?$')
|
||||
.help-block.form-text == t('.hints.exposed_ports')
|
||||
.form-group
|
||||
= f.label(:memory_limit)
|
||||
= f.number_field(:memory_limit, class: 'form-control', min: DockerClient::MINIMUM_MEMORY_LIMIT, value: f.object.memory_limit || DockerClient::DEFAULT_MEMORY_LIMIT)
|
||||
.form-group
|
||||
= f.label(:cpu_limit)
|
||||
= f.number_field(:cpu_limit, class: 'form-control', min: 1, step: 1, value: ExecutionEnvironment::DEFAULT_CPU_LIMIT)
|
||||
.form-check.mb-3
|
||||
label.form-check-label
|
||||
= f.check_box(:network_enabled, class: 'form-check-input')
|
||||
|
@ -5,7 +5,7 @@ h1
|
||||
= row(label: 'execution_environment.name', value: @execution_environment.name)
|
||||
= row(label: 'execution_environment.user', value: link_to_if(policy(@execution_environment.author).show?, @execution_environment.author, @execution_environment.author))
|
||||
= row(label: 'execution_environment.file_type', value: @execution_environment.file_type.present? ? link_to(@execution_environment.file_type, @execution_environment.file_type) : nil)
|
||||
- [:docker_image, :exposed_ports, :memory_limit, :network_enabled, :permitted_execution_time, :pool_size].each do |attribute|
|
||||
- [:docker_image, :exposed_ports, :memory_limit, :cpu_limit, :network_enabled, :permitted_execution_time, :pool_size].each do |attribute|
|
||||
= row(label: "execution_environment.#{attribute}", value: @execution_environment.send(attribute))
|
||||
- [:run_command, :test_command].each do |attribute|
|
||||
= row(label: "execution_environment.#{attribute}") do
|
||||
|
Reference in New Issue
Block a user