Class: Rush::SshTunnel

Inherits:
Object
  • Object
show all
Defined in:
lib/rush/ssh_tunnel.rb

Overview

Internal class for managing an ssh tunnel, across which relatively insecure HTTP commands can be sent by Rush::Connection::Remote.

Defined Under Namespace

Classes: NoPortSelectedYet, SshFailed

Instance Method Summary collapse

Constructor Details

#initialize(real_host) ⇒ SshTunnel

Returns a new instance of SshTunnel.



4
5
6
# File 'lib/rush/ssh_tunnel.rb', line 4

def initialize(real_host)
	@real_host = real_host
end

Instance Method Details

#configObject



115
116
117
# File 'lib/rush/ssh_tunnel.rb', line 115

def config
	@config ||= Rush::Config.new
end

#display(msg) ⇒ Object



119
120
121
# File 'lib/rush/ssh_tunnel.rb', line 119

def display(msg)
	puts msg
end

#ensure_tunnel(options = {}) ⇒ Object



16
17
18
19
20
21
22
23
24
# File 'lib/rush/ssh_tunnel.rb', line 16

def ensure_tunnel(options={})
	return if @port and tunnel_alive?

	@port = config.tunnels[@real_host]

	if !@port or !tunnel_alive?
		setup_everything(options)
	end
end

#establish_tunnel(options = {}) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/rush/ssh_tunnel.rb', line 51

def establish_tunnel(options={})
	display "Establishing ssh tunnel"
	@port = next_available_port

	make_ssh_tunnel(options)

	tunnels = config.tunnels
	tunnels[@real_host] = @port
	config.save_tunnels tunnels

	sleep 0.5
end

#hostObject



8
9
10
# File 'lib/rush/ssh_tunnel.rb', line 8

def host
	'localhost'
end

#launch_rushdObject



46
47
48
49
# File 'lib/rush/ssh_tunnel.rb', line 46

def launch_rushd
	display "Launching rushd"
	ssh("if [ `ps aux | grep rushd | grep -v grep | wc -l` -ge 1 ]; then exit; fi; rushd > /dev/null 2>&1 &")
end

#make_ssh_tunnel(options = {}) ⇒ Object

Raises:



87
88
89
# File 'lib/rush/ssh_tunnel.rb', line 87

def make_ssh_tunnel(options={})
	raise SshFailed unless system(ssh_tunnel_command(options))
end

#next_available_portObject



111
112
113
# File 'lib/rush/ssh_tunnel.rb', line 111

def next_available_port
	(config.tunnels.values.max || Rush::Config::DefaultPort) + 1
end

#portObject



12
13
14
# File 'lib/rush/ssh_tunnel.rb', line 12

def port
	@port
end

#push_credentialsObject



33
34
35
36
37
# File 'lib/rush/ssh_tunnel.rb', line 33

def push_credentials
	display "Pushing credentials"
	config.ensure_credentials_exist
	ssh_append_to_credentials(config.credentials_file.contents.strip)
end

#setup_everything(options = {}) ⇒ Object



26
27
28
29
30
31
# File 'lib/rush/ssh_tunnel.rb', line 26

def setup_everything(options={})
	display "Connecting to #{@real_host}..."
	push_credentials
	launch_rushd
	establish_tunnel(options)
end

#ssh(command) ⇒ Object

Raises:



83
84
85
# File 'lib/rush/ssh_tunnel.rb', line 83

def ssh(command)
	raise SshFailed unless system("ssh #{@real_host} '#{command}'")
end

#ssh_append_to_credentials(string) ⇒ Object



39
40
41
42
43
44
# File 'lib/rush/ssh_tunnel.rb', line 39

def ssh_append_to_credentials(string)
	# the following horror is exactly why rush is needed
	passwords_file = "~/.rush/passwords"
	string = "'#{string}'"
	ssh "M=`grep #{string} #{passwords_file} 2>/dev/null | wc -l`; if [ $M = 0 ]; then mkdir -p .rush; chmod 700 .rush; echo #{string} >> #{passwords_file}; chmod 600 #{passwords_file}; fi"
end

#ssh_stall_command(options = {}) ⇒ Object



97
98
99
100
101
102
103
104
105
# File 'lib/rush/ssh_tunnel.rb', line 97

def ssh_stall_command(options={})
	if options[:timeout] == :infinite
		"while [ 1 ]; do sleep 1000; done"
	elsif options[:timeout].to_i > 10
		"sleep #{options[:timeout].to_i}"
	else
		"sleep 9000"
	end
end

#ssh_tunnel_command(options = {}) ⇒ Object



107
108
109
# File 'lib/rush/ssh_tunnel.rb', line 107

def ssh_tunnel_command(options={})
	ssh_tunnel_command_without_stall + ' "' + ssh_stall_command(options) + '"'
end

#ssh_tunnel_command_without_stallObject

Raises:



91
92
93
94
95
# File 'lib/rush/ssh_tunnel.rb', line 91

def ssh_tunnel_command_without_stall
	options = tunnel_options
	raise NoPortSelectedYet unless options[:local_port]
	"ssh -f -L #{options[:local_port]}:127.0.0.1:#{options[:remote_port]} #{options[:ssh_host]}"
end

#tunnel_alive?Boolean

Returns:

  • (Boolean)


72
73
74
# File 'lib/rush/ssh_tunnel.rb', line 72

def tunnel_alive?
	`#{tunnel_count_command}`.to_i > 0
end

#tunnel_count_commandObject



76
77
78
# File 'lib/rush/ssh_tunnel.rb', line 76

def tunnel_count_command
	"ps x | grep '#{ssh_tunnel_command_without_stall}' | grep -v grep | wc -l"
end

#tunnel_optionsObject



64
65
66
67
68
69
70
# File 'lib/rush/ssh_tunnel.rb', line 64

def tunnel_options
	{
		:local_port => @port,
		:remote_port => Rush::Config::DefaultPort,
		:ssh_host => @real_host,
	}
end