summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorelijah <elijah@riseup.net>2014-12-08 13:14:50 -0800
committerelijah <elijah@riseup.net>2014-12-08 13:14:50 -0800
commitc0c815b62d6ef62764679488de40370b6118c03d (patch)
treec0fdd816214a34dd98d5bf711e5f6d416458a8c0 /lib
parented0d1750e5afa551ec5fda3f3b137e20b1aa8688 (diff)
added `leap tunnel` command.
Diffstat (limited to 'lib')
-rw-r--r--lib/leap_cli/commands/ssh.rb57
1 files changed, 54 insertions, 3 deletions
diff --git a/lib/leap_cli/commands/ssh.rb b/lib/leap_cli/commands/ssh.rb
index a7a0d85..40d205e 100644
--- a/lib/leap_cli/commands/ssh.rb
+++ b/lib/leap_cli/commands/ssh.rb
@@ -3,8 +3,8 @@ module LeapCli; module Commands
desc 'Log in to the specified node with an interactive shell.'
arg_name 'NAME' #, :optional => false, :multiple => false
command :ssh do |c|
- c.flag 'ssh', :desc => "Pass through raw options to ssh (e.g. --ssh '-F ~/sshconfig')"
- c.flag 'port', :desc => 'Override ssh port for remote host'
+ c.flag 'ssh', :desc => "Pass through raw options to ssh (e.g. `--ssh '-F ~/sshconfig'`)."
+ c.flag 'port', :arg_name => 'SSH_PORT', :desc => 'Override default SSH port used when trying to connect to the server. Same as `--ssh "-p SSH_PORT"`.'
c.action do |global_options,options,args|
exec_ssh(:ssh, options, args)
end
@@ -13,11 +13,28 @@ module LeapCli; module Commands
desc 'Log in to the specified node with an interactive shell using mosh (requires node to have mosh.enabled set to true).'
arg_name 'NAME'
command :mosh do |c|
+ c.flag 'ssh', :desc => "Pass through raw options to ssh (e.g. `--ssh '-F ~/sshconfig'`)."
+ c.flag 'port', :arg_name => 'SSH_PORT', :desc => 'Override default SSH port used when trying to connect to the server. Same as `--ssh "-p SSH_PORT"`.'
c.action do |global_options,options,args|
exec_ssh(:mosh, options, args)
end
end
+ desc 'Creates an SSH port forward (tunnel) to the node NAME. REMOTE_PORT is the port on the remote node that the tunnel will connect to. LOCAL_PORT is the optional port on your local machine. For example: `leap tunnel couch1:5984`.'
+ arg_name '[LOCAL_PORT:]NAME:REMOTE_PORT'
+ command :tunnel do |c|
+ c.flag 'ssh', :desc => "Pass through raw options to ssh (e.g. --ssh '-F ~/sshconfig')."
+ c.flag 'port', :arg_name => 'SSH_PORT', :desc => 'Override default SSH port used when trying to connect to the server. Same as `--ssh "-p SSH_PORT"`.'
+ c.action do |global_options,options,args|
+ local_port, node, remote_port = parse_tunnel_arg(args.first)
+ options[:ssh] = [options[:ssh], "-N -L 127.0.0.1:#{local_port}:0.0.0.0:#{remote_port}"].join(' ')
+ log("Forward port localhost:#{local_port} to #{node.name}:#{remote_port}")
+ if is_port_available?(local_port)
+ exec_ssh(:ssh, options, [node.name])
+ end
+ end
+ end
+
protected
#
@@ -44,6 +61,18 @@ module LeapCli; module Commands
puts "(replace `id_rsa` with the actual private key filename that you use for this provider)"
end
+ require 'socket'
+ def is_port_available?(port)
+ TCPServer.open('127.0.0.1', port) {}
+ true
+ rescue Errno::EACCES
+ bail!("You don't have permission to bind to port #{port}.")
+ rescue Errno::EADDRINUSE
+ bail!("Local port #{port} is already in use. Specify LOCAL_PORT to pick another.")
+ rescue Exception => exc
+ bail!(exc.to_s)
+ end
+
private
def exec_ssh(cmd, cli_options, args)
@@ -88,14 +117,36 @@ module LeapCli; module Commands
# exec the shell command in a subprocess
pid = fork { exec "#{command}" }
+ Signal.trap("SIGINT") do
+ Process.kill("KILL", pid)
+ Process.wait(pid)
+ exit(0)
+ end
+
# wait for shell to exit so we can grab the exit status
_, status = Process.waitpid2(pid)
if status.exitstatus == 255
ssh_config_help_message
elsif status.exitstatus != 0
- exit_now! status.exitstatus, status.exitstatus
+ exit(status.exitstatus)
+ end
+ end
+
+ def parse_tunnel_arg(arg)
+ if arg.count(':') == 1
+ node_name, remote = arg.split(':')
+ local = nil
+ elsif arg.count(':') == 2
+ local, node_name, remote = arg.split(':')
+ else
+ bail!('Argument NAME:REMOTE_PORT required.')
end
+ node = get_node_from_args([node_name], :include_disabled => true)
+ remote = remote.to_i
+ local = local || remote
+ local = local.to_i
+ return [local, node, remote]
end
end; end \ No newline at end of file