tbm 0.1.2 → 0.2.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +46 -3
- data/Rakefile +5 -5
- data/bin/tbm +1 -1
- data/lib/TBM/cli.rb +83 -0
- data/lib/TBM/config.rb +41 -0
- data/lib/TBM/config_parser.rb +221 -0
- data/lib/TBM/machine.rb +59 -0
- data/lib/TBM/meta.rb +6 -0
- data/lib/TBM/target.rb +54 -0
- data/lib/TBM/tunnel.rb +26 -0
- data/lib/tbm.rb +7 -4
- data/spec/cli_spec.rb +165 -0
- data/spec/config_spec.rb +348 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/target_spec.rb +40 -0
- metadata +19 -11
- data/lib/tunnel/cli.rb +0 -69
- data/lib/tunnel/config.rb +0 -94
- data/lib/tunnel/meta.rb +0 -5
- data/lib/tunnel/target.rb +0 -24
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
def stub_messages
|
2
|
+
@messages = []
|
3
|
+
$stdout.stub( :write ) { |message| @messages << message }
|
4
|
+
end
|
5
|
+
|
6
|
+
def surpress_messages
|
7
|
+
$stdout.stub( :write )
|
8
|
+
end
|
9
|
+
|
10
|
+
RSpec::Matchers.define :include_match do |expected|
|
11
|
+
match do |actual|
|
12
|
+
!actual.grep( expected ).empty?
|
13
|
+
end
|
14
|
+
end
|
data/spec/target_spec.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'TBM/target'
|
2
|
+
require 'rspec'
|
3
|
+
|
4
|
+
describe TBM::Target do
|
5
|
+
context "with name 'Foo'" do
|
6
|
+
subject { TBM::Target.new( 'Foo','host','user' ) }
|
7
|
+
|
8
|
+
it "should have name 'Foo'" do
|
9
|
+
subject.should have_name( 'Foo' )
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should describe itself as 'Foo'" do
|
13
|
+
subject.to_s.should eq('Foo')
|
14
|
+
end
|
15
|
+
|
16
|
+
context "and aliases 'Bar', 'Baz'" do
|
17
|
+
before do
|
18
|
+
subject.add_alias('Bar')
|
19
|
+
subject.add_alias('Baz')
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should have name 'Foo'" do
|
23
|
+
subject.should have_name( 'Foo' )
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should have name 'Bar'" do
|
27
|
+
subject.should have_name( 'Foo' )
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should have name 'Baz'" do
|
31
|
+
subject.should have_name( 'Foo' )
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should describe itself as 'Foo (Bar, Baz)'" do
|
35
|
+
subject.to_s.should eq('Foo (Bar, Baz)')
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tbm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.0.rc1
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Geoffrey Wiseman
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: net-ssh
|
@@ -36,11 +36,18 @@ executables:
|
|
36
36
|
extensions: []
|
37
37
|
extra_rdoc_files: []
|
38
38
|
files:
|
39
|
+
- lib/TBM/cli.rb
|
40
|
+
- lib/TBM/config.rb
|
41
|
+
- lib/TBM/config_parser.rb
|
42
|
+
- lib/TBM/machine.rb
|
43
|
+
- lib/TBM/meta.rb
|
44
|
+
- lib/TBM/target.rb
|
45
|
+
- lib/TBM/tunnel.rb
|
39
46
|
- lib/tbm.rb
|
40
|
-
-
|
41
|
-
-
|
42
|
-
-
|
43
|
-
-
|
47
|
+
- spec/cli_spec.rb
|
48
|
+
- spec/config_spec.rb
|
49
|
+
- spec/spec_helper.rb
|
50
|
+
- spec/target_spec.rb
|
44
51
|
- bin/tbm
|
45
52
|
- Rakefile
|
46
53
|
- README.md
|
@@ -59,17 +66,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
59
66
|
version: '0'
|
60
67
|
segments:
|
61
68
|
- 0
|
62
|
-
hash:
|
69
|
+
hash: -3696541644893645018
|
63
70
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
71
|
none: false
|
65
72
|
requirements:
|
66
|
-
- - ! '
|
73
|
+
- - ! '>'
|
67
74
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
75
|
+
version: 1.3.1
|
69
76
|
requirements: []
|
70
77
|
rubyforge_project:
|
71
78
|
rubygems_version: 1.8.24
|
72
79
|
signing_key:
|
73
80
|
specification_version: 3
|
74
|
-
summary:
|
81
|
+
summary: Manages SSH Tunnels by creating an SSH connection and forwarding ports based
|
82
|
+
on named targets defined in configuration.
|
75
83
|
test_files: []
|
data/lib/tunnel/cli.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
require 'net/ssh'
|
2
|
-
|
3
|
-
module Tunnel
|
4
|
-
class CommandLineInterface
|
5
|
-
def initialize( config )
|
6
|
-
@config = config
|
7
|
-
@target = nil
|
8
|
-
@cancelled = false
|
9
|
-
end
|
10
|
-
|
11
|
-
def parse
|
12
|
-
if ARGV.size != 1
|
13
|
-
print_targets "SYNTAX: tbm <target>\n\nWhere target is one of:"
|
14
|
-
else
|
15
|
-
target_name = ARGV[0]
|
16
|
-
@target = @config.get_target( target_name )
|
17
|
-
print_targets( "Cannot find target: #{target_name}\n\nThese are the targets currently defined:" ) if @target.nil?
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def print_targets( message )
|
22
|
-
puts message
|
23
|
-
@config.each_target { |target| puts "\t#{target.name}" }
|
24
|
-
end
|
25
|
-
|
26
|
-
|
27
|
-
def valid?
|
28
|
-
!@target.nil?
|
29
|
-
end
|
30
|
-
|
31
|
-
def bore
|
32
|
-
puts "Starting #{APP_NAME} v#{VERSION}"
|
33
|
-
puts
|
34
|
-
|
35
|
-
trap("INT") { @cancelled = true }
|
36
|
-
Net::SSH.start( @target.host, @target.username ) do |session|
|
37
|
-
forward_ports( session )
|
38
|
-
end
|
39
|
-
|
40
|
-
puts "Shutting down the machine."
|
41
|
-
end
|
42
|
-
|
43
|
-
def forward_ports( session )
|
44
|
-
begin
|
45
|
-
puts "Opened connection to #{@target.username}@#{@target.host}:"
|
46
|
-
@target.each_forward do |fwd|
|
47
|
-
remote_server, port = fwd
|
48
|
-
session.forward.local( port, remote_server, port )
|
49
|
-
puts "\tforwarded port #{port} to #{remote_server}:#{port}"
|
50
|
-
end
|
51
|
-
puts "\twaiting for Ctrl-C..."
|
52
|
-
session.loop(0.1) { not @cancelled }
|
53
|
-
puts "\n\tCtrl-C pressed. Exiting."
|
54
|
-
rescue Errno::EACCES
|
55
|
-
@cancelled = true
|
56
|
-
puts "\tCould not open all ports; you may need to sudo if port < 1000."
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.parse_and_run
|
61
|
-
config = Config.new
|
62
|
-
if config.valid?
|
63
|
-
cli = CommandLineInterface.new( config )
|
64
|
-
cli.parse
|
65
|
-
cli.bore if cli.valid?
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
data/lib/tunnel/config.rb
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
require 'etc'
|
2
|
-
require 'yaml'
|
3
|
-
|
4
|
-
module Tunnel
|
5
|
-
class Config
|
6
|
-
CONFIG_FILE = File.expand_path( '~/.tunnels' )
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@valid = nil
|
10
|
-
@targets = []
|
11
|
-
if File.file? CONFIG_FILE
|
12
|
-
config_data = YAML.load_file( CONFIG_FILE )
|
13
|
-
parse config_data if config_data.is_a? Hash
|
14
|
-
else
|
15
|
-
puts "Configure your tunnels in ~/.tunnels in YAML form."
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def valid?
|
20
|
-
@valid
|
21
|
-
end
|
22
|
-
|
23
|
-
def get_target( name )
|
24
|
-
@targets.find { |target| target.has_name?(name) }
|
25
|
-
end
|
26
|
-
|
27
|
-
def each_target( &block )
|
28
|
-
@targets.each { |target| yield target }
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def parse( targets )
|
34
|
-
targets.each_key { |name| parse_target name, targets[name] }
|
35
|
-
@valid = true if @valid.nil? && !@targets.empty?
|
36
|
-
end
|
37
|
-
|
38
|
-
def parse_target( name, config )
|
39
|
-
if config.is_a? Hash
|
40
|
-
target = create_target( name, config )
|
41
|
-
unless target.nil?
|
42
|
-
@targets << target
|
43
|
-
parse_forward( target, config['forward'] )
|
44
|
-
end
|
45
|
-
else
|
46
|
-
puts "Cannot parse target '#{name}' (#{config.class})"
|
47
|
-
@valid = false
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def create_target( name, config )
|
52
|
-
if config.has_key? 'host' then
|
53
|
-
if config.has_key? 'username' then
|
54
|
-
username = config['username']
|
55
|
-
else
|
56
|
-
username = Etc.getlogin
|
57
|
-
end
|
58
|
-
Target.new name, config['host'], username
|
59
|
-
else
|
60
|
-
puts "Cannot parse target '#{name}': no host found."
|
61
|
-
@valid = false
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def parse_forward( target, config )
|
66
|
-
case config
|
67
|
-
when nil
|
68
|
-
puts "Target #{target.name} has no forwards defined."
|
69
|
-
@valid = false
|
70
|
-
when Fixnum
|
71
|
-
target.forward_port( config )
|
72
|
-
when Array
|
73
|
-
config.each { |port| target.forward_port(port) }
|
74
|
-
when Hash
|
75
|
-
config.each_key do |server|
|
76
|
-
server_config = config[ server ]
|
77
|
-
case server_config
|
78
|
-
when Fixnum
|
79
|
-
target.forward_port( server_config, server )
|
80
|
-
when Array
|
81
|
-
server_config.each { |port| target.forward_port( port, server ) }
|
82
|
-
else
|
83
|
-
puts "Not sure how to handle forward from #{target.host} to #{server}: #{server_config.class}"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
else
|
87
|
-
puts "Not sure how to handle forward for '#{target.host}': #{config.class}"
|
88
|
-
@valid = false
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
end
|
93
|
-
|
94
|
-
end
|
data/lib/tunnel/meta.rb
DELETED
data/lib/tunnel/target.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
module Tunnel
|
2
|
-
class Target
|
3
|
-
attr_reader :name, :host, :username
|
4
|
-
|
5
|
-
def initialize( name, host, username )
|
6
|
-
@name = name
|
7
|
-
@host = host
|
8
|
-
@username = username
|
9
|
-
@forwards = []
|
10
|
-
end
|
11
|
-
|
12
|
-
def forward_port( port, server='localhost' )
|
13
|
-
@forwards << [ server, port ]
|
14
|
-
end
|
15
|
-
|
16
|
-
def has_name?( name )
|
17
|
-
@name==name
|
18
|
-
end
|
19
|
-
|
20
|
-
def each_forward( &block )
|
21
|
-
@forwards.each { |fwd| yield fwd }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|