Skip to content

Commit

Permalink
Naïve SSHAdapter implementation using Net/SSH
Browse files Browse the repository at this point in the history
  • Loading branch information
Nu-hin committed Dec 20, 2024
1 parent debca29 commit 248c572
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 4 deletions.
1 change: 1 addition & 0 deletions lib/remote_ruby/connection_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ def open(_code)
require 'remote_ruby/connection_adapter/caching_adapter'
require 'remote_ruby/connection_adapter/tmp_file_adapter'
require 'remote_ruby/connection_adapter/ssh_tmp_file_adapter'
require 'remote_ruby/connection_adapter/ssh_adapter'
73 changes: 73 additions & 0 deletions lib/remote_ruby/connection_adapter/ssh_adapter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
require 'net/ssh'

module RemoteRuby
class SSHAdapter < ConnectionAdapter
attr_reader :host, :user, :config, :working_dir

def initialize(host:, user: nil, working_dir: nil)
super
@host = host
@working_dir = working_dir
@config = Net::SSH.configuration_for(@host, true)
@user = user || @config[:user]
end

def open(code)
Net::SSH.start(host, user, config) do |ssh|
# ssh.exec!('f=$(mktemp) && cat > $f && echo $f')

fname = ''
code_channel = ssh.open_channel do |channel|
channel.exec('f=$(mktemp remote_ruby.rb.XXXXXX) && cat > $f && echo $f') do |ch, success|
raise 'Could not execute command' unless success

ch.on_data do |_, data|
fname << data
end

ch.send_data(code)
ch.eof!
end
end

code_channel.wait

stdout_r, stdout_w = IO.pipe
stderr_r, stderr_w = IO.pipe
stdin_r, stdin_w = IO.pipe

execution_channel = ssh.open_channel do |channel|
channel.exec("cd #{working_dir} && ruby #{fname}") do |ch, success|
raise 'Could not execute command' unless success

ssh.listen_to(stdin_r) do |io|
data = io.read_nonblock(4096)
ch.send_data(data)
rescue EOFError
ch.eof!
end

ch.on_data do |_, data|
stdout_w << data
end

ch.on_extended_data do |_, _, data|
stderr_w << data
end

ch.on_close do |_|
stdout_w.close
stderr_w.close
end
end
end

Thread.new { yield stdin_w, stdout_r, stderr_r }

execution_channel.wait

ssh.exec!("rm #{fname}")
end
end
end
end
2 changes: 1 addition & 1 deletion lib/remote_ruby/execution_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def initialize(**params)
@cache_dir = params.delete(:cache_dir) || File.join(Dir.pwd, 'cache')
@out_stream = params.delete(:out_stream) || $stdout
@err_stream = params.delete(:err_stream) || $stderr
@adapter_klass = params.delete(:adapter) || ::RemoteRuby::SSHTmpFileAdapter
@adapter_klass = params.delete(:adapter) || ::RemoteRuby::SSHAdapter
@out_prefix = params.delete(:out_prefix) || nil
@cache_prefix = params.delete(:cache_prefix) || '[CACHE] '
@params = params
Expand Down
1 change: 1 addition & 0 deletions remote_ruby.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Gem::Specification.new do |spec|

spec.add_dependency 'base64', '~> 0.2'
spec.add_dependency 'method_source', '~> 1.1'
spec.add_dependency 'net-ssh', '~> 7.3'
spec.add_dependency 'parser', '~> 3.0'
spec.add_dependency 'unparser', '~> 0.6'
end
5 changes: 2 additions & 3 deletions spec/integration/ssh_stdin_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
type: :integration do
let(:context) do
RemoteRuby::ExecutionContext.new(
adapter: RemoteRuby::SSHStdinAdapter,
server: ssh_host,
adapter: RemoteRuby::SSHAdapter,
host: ssh_host,
user: ssh_user,
key_file: ssh_key_file,
working_dir: ssh_workdir
)
end
Expand Down

0 comments on commit 248c572

Please sign in to comment.