Add interactive mode

This commit is contained in:
Patrick Lühne 2020-05-25 18:13:28 +02:00
parent aa17fe4e00
commit bbdda36e4c
Signed by: patrick
GPG Key ID: 05F3611E97A70ABF
2 changed files with 67 additions and 9 deletions

View File

@ -1,17 +1,21 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
require "base64" require "base64"
require "io/console"
require "optparse" require "optparse"
require "socket" require "socket"
usage_output = "USAGE:\n github-fast-env SCRIPT_PATH [options]" usage_output = "USAGE:\n github-fast-env SCRIPT_PATH [options]"
$options = {:verbose => false} $options = {:verbose => false, :interactive => false}
OptionParser.new do |options| OptionParser.new do |options|
options.banner = usage_output options.banner = usage_output
options.on("-v", "--verbose", "Show verbose output") do options.on("-v", "--verbose", "Show verbose output") do
$options[:verbose] = true $options[:verbose] = true
end end
options.on("-i", "--interactive", "Run an interactive session using a pseudoterminal") do
$options[:interactive] = true
end
end.parse! end.parse!
if not ARGV or ARGV.empty? if not ARGV or ARGV.empty?
@ -34,9 +38,13 @@ control_socket_path = "/tmp/github-fast-envd.sock"
$control_socket = UNIXSocket.new(control_socket_path) $control_socket = UNIXSocket.new(control_socket_path)
$original_stdin = $stdin.dup
$original_stdout = $stdout.dup
$origianl_stderr = $stderr.dup
def log(level, message) def log(level, message)
if level == "error" or $options[:verbose] if level == "error" or $options[:verbose]
$stderr.puts "[github-fast-env] #{level}: #{message}" $origianl_stderr.puts "[github-fast-env] #{level}: #{message}"
end end
end end
@ -89,7 +97,12 @@ end
log "info", "connected to control socket" log "info", "connected to control socket"
encoded_script_path = Base64.encode64(script_path).delete("\n") encoded_script_path = Base64.encode64(script_path).delete("\n")
$control_socket.puts "new v1 named-pipes #{encoded_script_path}"
if $options[:interactive]
$control_socket.puts "new v1 pseudoterminal #{encoded_script_path}"
else
$control_socket.puts "new v1 named-pipes #{encoded_script_path}"
end
pipes = {"stdin" => nil, "stdout" => nil, "stderr" => nil} pipes = {"stdin" => nil, "stdout" => nil, "stderr" => nil}
@ -115,10 +128,27 @@ while true
pipes["stderr"] = File::open("#{pipe_base_path}.stderr", "r") pipes["stderr"] = File::open("#{pipe_base_path}.stderr", "r")
pipes["stderr"].sync = true pipes["stderr"].sync = true
read_ios = [$control_socket, $stdin, pipes["stdout"], pipes["stderr"]]
log "info", "connected via named pipes" log "info", "connected via named pipes"
elsif command == "pseudoterminal" elsif command == "pseudoterminal"
log "error", "not yet implemented" if arguments.empty?
exit 1 log "error", "malformed response"
exit 1
end
pseudoterminal_path = Base64.decode64(arguments[0])
log "info", "connecting to pseudoterminal at #{pseudoterminal_path}"
pseudoterminal_io = File::open(pseudoterminal_path, File::RDWR | File::NOCTTY)
pipes["stdin"] = pseudoterminal_io
pipes["stdout"] = pseudoterminal_io
read_ios = [$control_socket, $stdin, pipes["stdout"]]
log "info", "connected via pseudoterminal"
else else
log "error", "malformed response" log "error", "malformed response"
exit 1 exit 1
@ -128,8 +158,6 @@ end
log "info", "ready" log "info", "ready"
$control_socket.puts "ready" $control_socket.puts "ready"
read_ios = [$control_socket, $stdin, pipes["stdout"], pipes["stderr"]]
exit_code = "unknown" exit_code = "unknown"
while read_ios.include?($control_socket) or read_ios.include?(pipes["stdout"]) or read_ios.include?(pipes["stderr"]) while read_ios.include?($control_socket) or read_ios.include?(pipes["stdout"]) or read_ios.include?(pipes["stderr"])
@ -165,7 +193,7 @@ while read_ios.include?($control_socket) or read_ios.include?(pipes["stdout"]) o
log "warn", "received input from unknown stream" log "warn", "received input from unknown stream"
end end
rescue EOFError rescue EOFError
log "trace", "closing stream" log "trace", "closing stream #{ready_read_io}"
ready_read_io.close ready_read_io.close
end end
end end

View File

@ -1,6 +1,7 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
require "base64" require "base64"
require "io/console"
require "socket" require "socket"
#require "/data/github/current/config/environment" #require "/data/github/current/config/environment"
@ -116,6 +117,35 @@ def set_up_named_pipes(control_socket, connection_id)
$stderr.reopen(stderr) $stderr.reopen(stderr)
end end
def set_up_pseudoterminal(control_socket)
require "pty"
master, client = PTY.open
master.raw!
File.chmod 0600, client.path
client_path = Base64.encode64(client.path).delete("\n")
client.close
control_socket.puts "pseudoterminal #{client_path}"
$stderr.puts " set up pseudoterminal"
control_socket.puts "ready"
response = control_socket.readline.strip
if response != "ready"
raise ClientError.new "invalid command"
Kernel.exit!
end
$stdin.reopen(master)
$stdout.reopen(master)
$stderr.reopen(master)
end
while true while true
control_socket = control_server.accept control_socket = control_server.accept
$stderr.puts "- new connection" $stderr.puts "- new connection"
@ -157,7 +187,7 @@ while true
if mode == "named-pipes" if mode == "named-pipes"
set_up_named_pipes(control_socket, connection_id) set_up_named_pipes(control_socket, connection_id)
else else
raise ClientError.new "not yet implemented" set_up_pseudoterminal(control_socket)
end end
original_stderr.puts " executing script " + script_path original_stderr.puts " executing script " + script_path