1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
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.action do |global_options,options,args|
exec_ssh(:ssh, options, args)
end
end
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.action do |global_options,options,args|
exec_ssh(:mosh, options, args)
end
end
protected
#
# allow for ssh overrides of all commands that use ssh_connect
#
def connect_options(options)
connect_options = {:ssh_options=>{}}
if options[:port]
connect_options[:ssh_options][:port] = options[:port]
end
if options[:ip]
connect_options[:ssh_options][:host_name] = options[:ip]
end
return connect_options
end
def ssh_config_help_message
puts ""
puts "Are 'too many authentication failures' getting you down?"
puts "Then we have the solution for you! Add something like this to your ~/.ssh/config file:"
puts " Host *.#{manager.provider.domain}"
puts " IdentityFile ~/.ssh/id_rsa"
puts " IdentitiesOnly=yes"
puts "(replace `id_rsa` with the actual private key filename that you use for this provider)"
end
private
def exec_ssh(cmd, cli_options, args)
node = get_node_from_args(args, :include_disabled => true)
port = node.ssh.port
options = [
"-o 'HostName=#{node.ip_address}'",
# "-o 'HostKeyAlias=#{node.name}'", << oddly incompatible with ports in known_hosts file, so we must not use this or non-standard ports break.
"-o 'GlobalKnownHostsFile=#{path(:known_hosts)}'",
"-o 'UserKnownHostsFile=/dev/null'"
]
if node.vagrant?
options << "-i #{vagrant_ssh_key_file}" # use the universal vagrant insecure key
options << "-o IdentitiesOnly=yes" # force the use of the insecure vagrant key
options << "-o 'StrictHostKeyChecking=no'" # blindly accept host key and don't save it (since userknownhostsfile is /dev/null)
else
options << "-o 'StrictHostKeyChecking=yes'"
end
username = 'root'
if LeapCli.log_level >= 3
options << "-vv"
elsif LeapCli.log_level >= 2
options << "-v"
end
if cli_options[:port]
port = cli_options[:port]
end
if cli_options[:ssh]
options << cli_options[:ssh]
end
ssh = "ssh -l #{username} -p #{port} #{options.join(' ')}"
if cmd == :ssh
command = "#{ssh} #{node.domain.full}"
elsif cmd == :mosh
command = "MOSH_TITLE_NOPREFIX=1 mosh --ssh \"#{ssh}\" #{node.domain.full}"
end
log 2, command
# exec the shell command in a subprocess
pid = fork { exec "#{command}" }
# 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
end
end
end; end
|