Working with analyzers,test-runners, and representers
This commit is contained in:
@@ -49,11 +49,26 @@ class PipelineClient
|
||||
params = {
|
||||
action: "analyze_iteration",
|
||||
track_slug: track_slug,
|
||||
container_version: "v0.0.5",
|
||||
container_version: "a1f5549b6391443f7a05a038fed8dfebacd3db84",
|
||||
exercise_slug: exercise_slug,
|
||||
solution_slug: solution_slug,
|
||||
iteration_folder: iteration_folder
|
||||
}
|
||||
puts "MSG: #{params}"
|
||||
msg = params.to_json
|
||||
send_msg(msg, 10000)
|
||||
end
|
||||
|
||||
def represent(track_slug, exercise_slug, solution_slug, iteration_folder)
|
||||
params = {
|
||||
action: "represent",
|
||||
track_slug: track_slug,
|
||||
container_version: "7dad3dd8b43c89d0ac03b5f67700c6aad52d8cf9",
|
||||
exercise_slug: exercise_slug,
|
||||
solution_slug: solution_slug,
|
||||
iteration_folder: iteration_folder
|
||||
}
|
||||
puts "MSG: #{params}"
|
||||
msg = params.to_json
|
||||
send_msg(msg, 10000)
|
||||
end
|
||||
@@ -62,11 +77,12 @@ class PipelineClient
|
||||
params = {
|
||||
action: "test_solution",
|
||||
track_slug: track_slug,
|
||||
container_version: "v0.0.5",
|
||||
container_version: "b6ea39ccb2dd04e0b047b25c691b17d6e6b44cfb",
|
||||
exercise_slug: exercise_slug,
|
||||
solution_slug: solution_slug,
|
||||
iteration_folder: iteration_folder
|
||||
}
|
||||
puts "MSG: #{params}"
|
||||
msg = params.to_json
|
||||
send_msg(msg, 10000)
|
||||
end
|
||||
|
||||
23
bin/invoke3.rb
Normal file
23
bin/invoke3.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require_relative "./client"
|
||||
|
||||
pipeline = PipelineClient.new
|
||||
|
||||
# return
|
||||
lang = ARGV[0] || "ruby"
|
||||
lang = "ruby"
|
||||
|
||||
r = pipeline.represent(lang, "two-fer", "soln-42", "s3://exercism-dev/iterations/fff07700-e1c3-402d-8937-823aeefb159f")
|
||||
# puts r
|
||||
if r["logs"]
|
||||
r["logs"].each do |log_line|
|
||||
puts "+ #{log_line["cmd"]}"
|
||||
puts log_line["stdout"]
|
||||
puts log_line["stderr"]
|
||||
end
|
||||
end
|
||||
|
||||
puts r["result"]
|
||||
|
||||
pipeline.close_socket
|
||||
@@ -12,8 +12,7 @@ require 'ffi-rzmq'
|
||||
|
||||
require "zeitwerk"
|
||||
loader = Zeitwerk::Loader.for_gem
|
||||
loader.setup # ready!
|
||||
|
||||
loader.setup
|
||||
|
||||
module Pipeline
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ module Pipeline::Rpc
|
||||
@backend_channels[type] = work_channel
|
||||
end
|
||||
|
||||
@notification_port = 5556
|
||||
@notification_port = 5557
|
||||
@notification_socket = NotificationSocket.new(zmq_context, @notification_port)
|
||||
|
||||
end
|
||||
@@ -98,35 +98,35 @@ module Pipeline::Rpc
|
||||
end
|
||||
end
|
||||
|
||||
def analyzer_versions
|
||||
def container_versions
|
||||
{
|
||||
analyzer_spec: {
|
||||
"ruby" => [ "v0.0.3", "v0.0.5" ]
|
||||
static_analyzers: {
|
||||
"ruby" => [
|
||||
"a1f5549b6391443f7a05a038fed8dfebacd3db84",
|
||||
"398007701db580a09f198e806e680f4cdb04b3b4",
|
||||
"dc1c6c4897e63ebeb60ed53ec7423a3f6c33449d"
|
||||
]
|
||||
},
|
||||
representers: {
|
||||
"ruby" => [
|
||||
"7dad3dd8b43c89d0ac03b5f67700c6aad52d8cf9"
|
||||
]
|
||||
},
|
||||
test_runners: {
|
||||
"ruby" => [
|
||||
"b6ea39ccb2dd04e0b047b25c691b17d6e6b44cfb"
|
||||
]
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def emit_current_spec
|
||||
analyzer_spec = analyzer_versions
|
||||
m = {
|
||||
action: "configure",
|
||||
specs: analyzer_spec
|
||||
specs: container_versions
|
||||
}
|
||||
set_temp_credentials(m)
|
||||
# message = ["_", "", m.to_json]
|
||||
puts "TODO"
|
||||
puts m
|
||||
notification_socket.emit_configuration(m)
|
||||
|
||||
# @backend_channels.each do |channel_name,v|
|
||||
# m = {
|
||||
# action: "configure",
|
||||
# channel: channel_name,
|
||||
# spec: analyzer_spec[:analyzer_spec]
|
||||
# }
|
||||
# puts v
|
||||
# puts m
|
||||
# end
|
||||
end
|
||||
|
||||
def respond_with_worker_config(req)
|
||||
@@ -137,7 +137,7 @@ module Pipeline::Rpc
|
||||
end
|
||||
channel = channel.to_sym
|
||||
analyzer_spec = {}
|
||||
analyzer_spec["specs"] = analyzer_versions
|
||||
analyzer_spec["specs"] = container_versions
|
||||
analyzer_spec[:channel] = {
|
||||
channel: channel,
|
||||
workqueue_address: "tcp://#{@public_hostname}:#{@work_channel_ports[channel]}",
|
||||
|
||||
@@ -9,6 +9,11 @@ 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)
|
||||
end
|
||||
|
||||
def invoke
|
||||
s3 = Aws::S3::Client.new(
|
||||
credentials: parse_credentials(request["context"]),
|
||||
@@ -26,7 +31,7 @@ module Pipeline::Rpc::Worker
|
||||
}
|
||||
end
|
||||
|
||||
analysis_run = environment.new_invocation(language_slug, container_version, exercise_slug, solution_slug)
|
||||
analysis_run = setup(language_slug, container_version, exercise_slug, solution_slug)
|
||||
analysis_run.prepare_iteration do |iteration_folder|
|
||||
location_uri = URI(location)
|
||||
bucket = location_uri.host
|
||||
|
||||
@@ -2,8 +2,13 @@ module Pipeline::Rpc::Worker
|
||||
|
||||
class ConfigureAction < WorkerAction
|
||||
|
||||
def initialize(channel, request)
|
||||
@channel = channel
|
||||
@request = request
|
||||
end
|
||||
|
||||
def invoke
|
||||
spec = request["specs"]["analyzer_spec"]
|
||||
spec = request["specs"][@channel]
|
||||
credentials = parse_credentials(request)
|
||||
raise "No spec received" if spec.nil?
|
||||
spec.each do |language_slug, versions|
|
||||
@@ -13,7 +18,7 @@ module Pipeline::Rpc::Worker
|
||||
puts "Already installed #{language_slug}:#{version}"
|
||||
else
|
||||
puts "Installed #{language_slug}"
|
||||
environment.release_analyzer(language_slug, version, credentials)
|
||||
environment.release(@channel, language_slug, version, credentials)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -34,9 +34,8 @@ module Pipeline::Rpc::Worker
|
||||
|
||||
environment.prepare
|
||||
|
||||
action = Pipeline::Rpc::Worker::ConfigureAction.new
|
||||
action = Pipeline::Rpc::Worker::ConfigureAction.new(@channel, msg)
|
||||
action.environment = environment
|
||||
action.request = msg
|
||||
action.invoke
|
||||
|
||||
response_address = msg["channel"]["response_address"]
|
||||
@@ -53,7 +52,7 @@ module Pipeline::Rpc::Worker
|
||||
setup
|
||||
|
||||
@incoming_wrapper = Pipeline::Rpc::Worker::WorkSocketWrapper.new(incoming)
|
||||
@noificationincoming_wrapper = Pipeline::Rpc::Worker::NotificationSocketWrapper.new(@notifications)
|
||||
@noificationincoming_wrapper = Pipeline::Rpc::Worker::NotificationSocketWrapper.new(@notifications, @channel)
|
||||
|
||||
@poller = Pipeline::Rpc::ChannelPoller.new
|
||||
@poller.register(@incoming_wrapper)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
module Pipeline::Rpc::Worker
|
||||
class NotificationSocketWrapper
|
||||
|
||||
attr_reader :socket
|
||||
attr_reader :socket, :channel
|
||||
|
||||
def initialize(socket)
|
||||
def initialize(socket, channel)
|
||||
@socket = socket
|
||||
@channel = channel
|
||||
end
|
||||
|
||||
def recv
|
||||
@@ -15,14 +16,10 @@ module Pipeline::Rpc::Worker
|
||||
request = JSON.parse(msg)
|
||||
action = request["action"]
|
||||
|
||||
puts "HERE #{action}"
|
||||
if action == "configure"
|
||||
a = Pipeline::Rpc::Worker::ConfigureAction.new
|
||||
a = Pipeline::Rpc::Worker::ConfigureAction.new(channel, request)
|
||||
a.request = request
|
||||
a
|
||||
elsif action == "analyze_iteration" || action == "test_solution"
|
||||
a = Pipeline::Rpc::Worker::AnalyzeAction.new(request, return_address)
|
||||
a
|
||||
else
|
||||
puts "HERE ELSE: #{request}"
|
||||
end
|
||||
|
||||
15
lib/pipeline/rpc/worker/represent_action.rb
Normal file
15
lib/pipeline/rpc/worker/represent_action.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
module Pipeline::Rpc::Worker
|
||||
|
||||
class RepresentAction < AnalyzeAction
|
||||
|
||||
def initialize(request, return_address)
|
||||
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)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
15
lib/pipeline/rpc/worker/test_runner_action.rb
Normal file
15
lib/pipeline/rpc/worker/test_runner_action.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
module Pipeline::Rpc::Worker
|
||||
|
||||
class TestRunnerAction < AnalyzeAction
|
||||
|
||||
def initialize(request, return_address)
|
||||
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)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -18,12 +18,12 @@ module Pipeline::Rpc::Worker
|
||||
request = JSON.parse(raw_request)
|
||||
action = request["action"]
|
||||
|
||||
if action == "configure"
|
||||
ConfigureAction.new
|
||||
elsif action == "analyze_iteration" || action == "test_solution"
|
||||
a = AnalyzeAction.new(request, return_address)
|
||||
a.request = request
|
||||
a
|
||||
if action == "analyze_iteration"
|
||||
AnalyzeAction.new(request, return_address)
|
||||
elsif action == "represent"
|
||||
RepresentAction.new(request, return_address)
|
||||
elsif action == "test_solution"
|
||||
TestRunnerAction.new(request, return_address)
|
||||
else
|
||||
puts "HERE ELSE: #{request}"
|
||||
end
|
||||
|
||||
@@ -1,82 +1,17 @@
|
||||
module Pipeline::Runtime
|
||||
class AnalysisRun
|
||||
class AnalysisRun < ContainerRun
|
||||
|
||||
attr_reader :track_dir, :exercise_slug, :runs_dir, :solution_dir,
|
||||
:iteration_folder, :tmp_folder, :current_dir, :img,
|
||||
:runc
|
||||
|
||||
def initialize(track_dir, exercise_slug, solution_slug)
|
||||
@track_dir = track_dir
|
||||
@exercise_slug = exercise_slug
|
||||
@runs_dir = "#{track_dir}/runs"
|
||||
@current_dir = "#{track_dir}/current"
|
||||
@solution_dir = "#{runs_dir}/iteration_#{Time.now.to_i}-#{solution_slug}-#{SecureRandom.hex}"
|
||||
@iteration_folder = "#{solution_dir}/iteration"
|
||||
@tmp_folder = "#{solution_dir}/tmp"
|
||||
@logs = Pipeline::Util::LogCollector.new
|
||||
@img = Pipeline::Util::ImgWrapper.new(@logs)
|
||||
@runc = Pipeline::Util::RuncWrapper.new(@logs)
|
||||
end
|
||||
|
||||
def prepare_iteration
|
||||
FileUtils.mkdir_p iteration_folder
|
||||
FileUtils.mkdir_p tmp_folder
|
||||
|
||||
configurator.setup_for_terminal_access
|
||||
File.write("#{solution_dir}/terminal_config.json", configurator.build.to_json)
|
||||
|
||||
yield iteration_folder
|
||||
end
|
||||
|
||||
def analyze!
|
||||
container_driver = Pipeline::Util::ContainerDriver.new(runc, img, configurator, solution_dir)
|
||||
@result = container_driver.run_analyzer_for(exercise_slug)
|
||||
{
|
||||
exercise_slug: exercise_slug,
|
||||
solution_dir: solution_dir,
|
||||
rootfs_source: rootfs_source,
|
||||
result: result,
|
||||
invocation: @result.report,
|
||||
logs: @logs.inspect
|
||||
}
|
||||
def args
|
||||
["bin/analyze.sh", exercise_slug, "/mnt/exercism-iteration/"]
|
||||
end
|
||||
|
||||
def result
|
||||
File.read("#{iteration_folder}/analysis.json")
|
||||
end
|
||||
|
||||
def success?
|
||||
@result.success?
|
||||
def working_directory
|
||||
"/opt/analyzer"
|
||||
end
|
||||
|
||||
def exit_status
|
||||
@result.exit_status
|
||||
end
|
||||
|
||||
def stdout
|
||||
@result.stdout
|
||||
end
|
||||
|
||||
def stderr
|
||||
@result.stderr
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def configurator
|
||||
@configurator ||= begin
|
||||
configurator = Pipeline::Util::RuncConfigurator.new
|
||||
configurator.seed_from_env
|
||||
configurator.rootfs = rootfs_source
|
||||
configurator
|
||||
end
|
||||
end
|
||||
|
||||
def rootfs_source
|
||||
@rootfs_source ||= begin
|
||||
release_folder = File.readlink(current_dir)
|
||||
"#{release_folder}/rootfs"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
91
lib/pipeline/runtime/container_run.rb
Normal file
91
lib/pipeline/runtime/container_run.rb
Normal file
@@ -0,0 +1,91 @@
|
||||
module Pipeline::Runtime
|
||||
class ContainerRun
|
||||
|
||||
attr_reader :track_dir, :exercise_slug, :runs_dir, :solution_dir,
|
||||
:iteration_folder, :tmp_folder, :current_dir, :img,
|
||||
:runc
|
||||
|
||||
def initialize(track_dir, exercise_slug, solution_slug)
|
||||
@track_dir = track_dir
|
||||
@exercise_slug = exercise_slug
|
||||
@runs_dir = "#{track_dir}/runs"
|
||||
@current_dir = "#{track_dir}/current"
|
||||
@solution_dir = "#{runs_dir}/iteration_#{Time.now.to_i}-#{solution_slug}-#{SecureRandom.hex}"
|
||||
@iteration_folder = "#{solution_dir}/iteration"
|
||||
@tmp_folder = "#{solution_dir}/tmp"
|
||||
@logs = Pipeline::Util::LogCollector.new
|
||||
@img = Pipeline::Util::ImgWrapper.new(@logs)
|
||||
@runc = Pipeline::Util::RuncWrapper.new(@logs)
|
||||
end
|
||||
|
||||
def prepare_iteration
|
||||
FileUtils.mkdir_p iteration_folder
|
||||
FileUtils.mkdir_p tmp_folder
|
||||
|
||||
configurator.setup_for_terminal_access
|
||||
File.write("#{solution_dir}/terminal_config.json", configurator.build.to_json)
|
||||
|
||||
yield iteration_folder
|
||||
end
|
||||
|
||||
def analyze!
|
||||
container_driver = Pipeline::Util::ContainerDriver.new(runc, img, configurator, solution_dir)
|
||||
@result = container_driver.invoke(working_directory, args)
|
||||
puts @logs.inspect
|
||||
{
|
||||
exercise_slug: exercise_slug,
|
||||
solution_dir: solution_dir,
|
||||
rootfs_source: rootfs_source,
|
||||
result: result,
|
||||
invocation: @result.report,
|
||||
logs: @logs.inspect
|
||||
}
|
||||
end
|
||||
|
||||
def working_directory
|
||||
raise "Working directory was not defined"
|
||||
end
|
||||
|
||||
def args
|
||||
raise "args were not defined"
|
||||
end
|
||||
|
||||
def result
|
||||
raise "No result handler defined"
|
||||
end
|
||||
|
||||
def success?
|
||||
@result.success?
|
||||
end
|
||||
|
||||
def exit_status
|
||||
@result.exit_status
|
||||
end
|
||||
|
||||
def stdout
|
||||
@result.stdout
|
||||
end
|
||||
|
||||
def stderr
|
||||
@result.stderr
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def configurator
|
||||
@configurator ||= begin
|
||||
configurator = Pipeline::Util::RuncConfigurator.new
|
||||
configurator.seed_from_env
|
||||
configurator.rootfs = rootfs_source
|
||||
configurator
|
||||
end
|
||||
end
|
||||
|
||||
def rootfs_source
|
||||
@rootfs_source ||= begin
|
||||
release_folder = File.readlink(current_dir)
|
||||
"#{release_folder}/rootfs"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
17
lib/pipeline/runtime/represent_run.rb
Normal file
17
lib/pipeline/runtime/represent_run.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
module Pipeline::Runtime
|
||||
class RepresentRun < ContainerRun
|
||||
|
||||
def args
|
||||
["bin/generate.sh", exercise_slug, "/mnt/exercism-iteration/"]
|
||||
end
|
||||
|
||||
def result
|
||||
File.read("#{iteration_folder}/representation.txt")
|
||||
end
|
||||
|
||||
def working_directory
|
||||
"/opt/representer"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -17,18 +17,24 @@ module Pipeline::Runtime
|
||||
File.exist? current_dir
|
||||
end
|
||||
|
||||
def available?(track_slug, version)
|
||||
puts "-- CHECK #{version} -----"
|
||||
puts container_repo.list_images
|
||||
puts "-------------------------"
|
||||
true
|
||||
def release(channel, language_slug, version, credentials)
|
||||
container_slug = case channel
|
||||
when "static_analyzers"
|
||||
"#{language_slug}-analyzer"
|
||||
when "test_runners"
|
||||
"#{language_slug}-test-runner"
|
||||
when "representers"
|
||||
"#{language_slug}-representer"
|
||||
# when "static_analyzers"
|
||||
# container_slug = "#{language_slug}-analyzer"
|
||||
else
|
||||
raise "Unknown channel: #{channel}"
|
||||
end
|
||||
container_repo = Pipeline::ContainerRepo.new(container_slug, credentials)
|
||||
release_container(language_slug, version, container_repo)
|
||||
end
|
||||
|
||||
def container_repo
|
||||
@container_repo ||= Pipeline::ContainerRepo.new("#{track_slug}-analyzer-dev", credentials)
|
||||
end
|
||||
|
||||
def release_analyzer(track_slug, version, credentials)
|
||||
def release_container(track_slug, version, container_repo)
|
||||
track_dir = "#{env_base}/#{track_slug}/#{version}"
|
||||
release_dir = "#{track_dir}/releases/#{Time.now.to_i}_release"
|
||||
current_dir = "#{track_dir}/current"
|
||||
@@ -42,7 +48,6 @@ module Pipeline::Runtime
|
||||
configurator.seed_from_env
|
||||
|
||||
container_driver = Pipeline::Util::ContainerDriver.new(runc, img, configurator, release_dir)
|
||||
|
||||
user,password = container_repo.create_login_token
|
||||
img.reset_hub_login
|
||||
img.login("AWS", password, container_repo.repository_url)
|
||||
@@ -65,6 +70,11 @@ module Pipeline::Runtime
|
||||
FileUtils.symlink(release_dir, current_dir, force: true)
|
||||
end
|
||||
|
||||
def track_dir(track_slug, version)
|
||||
container_slug = "#{track_slug}/#{version}"
|
||||
"#{env_base}/#{container_slug}"
|
||||
end
|
||||
|
||||
def new_invocation(track_slug, version, exercise_slug, solution_slug)
|
||||
container_slug = "#{track_slug}/#{version}"
|
||||
puts "AnalysisRun: #{container_slug} #{exercise_slug} #{solution_slug}"
|
||||
|
||||
17
lib/pipeline/runtime/test_run.rb
Normal file
17
lib/pipeline/runtime/test_run.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
module Pipeline::Runtime
|
||||
class TestRun < ContainerRun
|
||||
|
||||
def args
|
||||
["bin/run.sh", exercise_slug, "/mnt/exercism-iteration/", "/mnt/exercism-iteration/"]
|
||||
end
|
||||
|
||||
def result
|
||||
File.read("#{iteration_folder}/results.json")
|
||||
end
|
||||
|
||||
def working_directory
|
||||
"/opt/test-runner"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -45,6 +45,13 @@ module Pipeline::Util
|
||||
run_analyzer
|
||||
end
|
||||
|
||||
def invoke(container_work_dir, args)
|
||||
configurator.setup_invocation_args(container_work_dir, args)
|
||||
File.write("#{workdir}/invocation_config.json", configurator.build.to_json)
|
||||
FileUtils.symlink("#{workdir}/invocation_config.json", "#{workdir}/config.json", force: true)
|
||||
run_analyzer
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
module Pipeline::Util
|
||||
class RuncConfigurator
|
||||
attr_accessor :uid_id, :gid_id, :invocation_args, :interactive, :rootfs
|
||||
attr_accessor :uid_id, :gid_id, :invocation_args, :interactive, :rootfs, :working_directory
|
||||
|
||||
def initialize
|
||||
@rootfs = "./rootfs"
|
||||
@working_directory = "/opt/analyzer"
|
||||
end
|
||||
|
||||
def seed_from_env
|
||||
@@ -18,6 +19,12 @@ module Pipeline::Util
|
||||
@invocation_args = ["bin/analyze.sh", track_slug, "/mnt/exercism-iteration/"]
|
||||
end
|
||||
|
||||
def setup_invocation_args(working_directory, args)
|
||||
@interactive = false
|
||||
@working_directory = working_directory
|
||||
@invocation_args = args
|
||||
end
|
||||
|
||||
def setup_for_terminal_access
|
||||
@interactive = true
|
||||
@invocation_args = ["/bin/sh"]
|
||||
@@ -42,7 +49,7 @@ module Pipeline::Util
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"TERM=xterm"
|
||||
],
|
||||
"cwd": "/opt/analyzer",
|
||||
"cwd": "#{working_directory}",
|
||||
"rlimits": [
|
||||
{
|
||||
"type": "RLIMIT_NOFILE",
|
||||
|
||||
Reference in New Issue
Block a user