shaft 0.6 → 0.7

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.
Files changed (4) hide show
  1. data/README.md +14 -12
  2. data/bin/shaft +54 -27
  3. data/lib/shaft/version.rb +1 -1
  4. metadata +3 -2
data/README.md CHANGED
@@ -38,22 +38,24 @@ files.
38
38
 
39
39
  ## Configuration
40
40
 
41
- Each SSH tunnel you want to have configured needs to be defined
42
- in YAML format and stored in `~/.shaft/name.yml`, where `name`
43
- is the tunnel name that would be used for `shaft`.
41
+ The SSH tunnels configuration Shaft will use are all stored in
42
+ a single YAML file under `~/.shaft`.
44
43
 
45
- An example configuration would be:
44
+ Each tunnel is represented by a key defining its name, followed
45
+ by an object describing all of the required parameters.
46
46
 
47
- port: 22
48
- username: user
49
- host: remote-host
50
- bind:
51
- client-port: 9999
52
- host: host
53
- host-port: 8888
47
+ An example configuration would be:
54
48
 
49
+ foobar:
50
+ port: 22
51
+ username: user
52
+ host: remote-host
53
+ bind:
54
+ client-port: 9999
55
+ host: host
56
+ host-port: 8888
55
57
 
56
- Starting the tunnel defined in this example would be equivalent
58
+ Calling Shaft with `$ shaft start foobar` would be equivalent
57
59
  to running:
58
60
 
59
61
  $ ssh -N -p 22 user@remote-host -L 9999:host:8888
data/bin/shaft CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- SHAFT_DIR = File.join(Dir.home, ".shaft")
3
+ SHAFT_CONFIG = File.join(Dir.home, ".shaft")
4
+ SHAFT_ACTIVE = File.join(Dir.home, ".shaft.active")
4
5
 
5
6
  require 'rubygems'
6
7
  require 'thor'
@@ -10,11 +11,11 @@ class ShaftCLI < Thor
10
11
  include Thor::Actions
11
12
 
12
13
  map "-h" => :help
13
- map "-l" => :list
14
+ map "-l" => :active
14
15
 
15
- desc "list", "Lists active tunnels"
16
+ desc "active", "Lists active tunnels"
16
17
  method_options %w( short -s ) => :boolean
17
- def list
18
+ def active
18
19
  active = get_active
19
20
  unless active.empty?
20
21
  if options[:short]
@@ -31,7 +32,7 @@ class ShaftCLI < Thor
31
32
  desc "all", "Lists all available tunnels"
32
33
  def all
33
34
  say "Listing all available tunnels:"
34
- tunnels = Dir["#{SHAFT_DIR}/*.yml"].map { |f| File.basename(f, ".yml") }
35
+ tunnels = get_config.keys
35
36
  print_in_columns tunnels
36
37
  end
37
38
 
@@ -42,14 +43,20 @@ class ShaftCLI < Thor
42
43
  if active.has_key? name
43
44
  say "Error: tunnel '#{name}' already active!"
44
45
  else
45
- c = read_yaml("#{name}.yml")
46
+ c = get_tunnel(name)
46
47
  unless c.nil?
47
48
  begin
48
49
  port = c['port']
49
50
  bind = "#{c['bind']['client-port']}:#{c['bind']['host']}:#{c['bind']['host-port']}"
50
51
  host = "#{c['username']}@#{c['host']}"
51
52
  rescue NoMethodError
52
- error "Tunnel file for '#{name}' appears to be invalid!"
53
+ error "Tunnel configuration for '#{name}' appears to be invalid!"
54
+ return
55
+ end
56
+
57
+ used = local_port_used?(c['bind']['client-port'])
58
+ if used
59
+ error "Local port #{port} is used by:\n#{used}"
53
60
  return
54
61
  end
55
62
 
@@ -61,7 +68,7 @@ class ShaftCLI < Thor
61
68
  active[name] = pid
62
69
  set_active(active)
63
70
  else
64
- error "Tunnel '#{name}' file not found!"
71
+ error "Tunnel '#{name}' not found!"
65
72
  end
66
73
  end
67
74
  end
@@ -70,19 +77,25 @@ class ShaftCLI < Thor
70
77
  method_options :name => :string
71
78
  def stop(name)
72
79
  active = get_active
73
- if active.has_key? name
80
+ if active.has_key?(name)
74
81
  say "Stopping tunnel '#{name}' at pid #{active[name]}..."
75
82
  begin
76
83
  Process.kill "INT", active[name]
77
- say "Stopped."
78
84
  rescue Errno::ESRCH
79
85
  say "Tunnel wasn't active (zombie shaft item)."
80
86
  end
81
87
 
82
- #TODO verify killing?
88
+ # verify killing
89
+ tunnel = get_tunnel(name)
90
+ if local_port_used?(tunnel['bind']['client-port'])
91
+ error "Could not stop tunnel process!"
92
+ else
93
+ say "Stopped."
83
94
 
84
- active.delete(name)
85
- set_active(active)
95
+ # set as inactive
96
+ active.delete(name)
97
+ set_active(active)
98
+ end
86
99
  else
87
100
  error "Tunnel '#{name}' does not seem to be active!"
88
101
  end
@@ -95,28 +108,42 @@ class ShaftCLI < Thor
95
108
  end
96
109
 
97
110
  private
98
- def read_yaml(filename)
99
- path = File.join(SHAFT_DIR, filename)
100
- YAML::load(File.open(path)) if File.exist?(path)
111
+ def get_config
112
+ @config ||= read_yaml(SHAFT_CONFIG)
101
113
  end
102
114
 
103
115
  def get_active
104
- active = read_yaml(".active")
105
- if active.nil?
106
- active = {}
107
- set_active(active)
108
- end
109
- active
116
+ @active ||= read_yaml(SHAFT_ACTIVE)
117
+ end
118
+
119
+ def get_tunnel(name)
120
+ get_config[name] || nil
110
121
  end
111
122
 
112
123
  def set_active(active)
113
- unless File.exist?(SHAFT_DIR) and File.directory?(SHAFT_DIR)
114
- Dir.mkdir(SHAFT_DIR)
124
+ File.open(SHAFT_ACTIVE, 'w') { |out|
125
+ YAML.dump(active, out)
126
+ }
127
+ end
128
+
129
+ def read_yaml(file)
130
+ if File.directory?(SHAFT_CONFIG)
131
+ error "Shaft v0.7 and up uses a single-file config.\nConsult the Readme at http://git.io/Zs3viQ ."
132
+ {}
133
+ elsif File.exists?(file)
134
+ YAML::load(File.open(file))
135
+ else
136
+ {}
115
137
  end
138
+ end
116
139
 
117
- File.open(File.join(SHAFT_DIR, '.active'), 'w') { |f|
118
- f.write(active.to_yaml)
119
- }
140
+ def local_port_used?(port)
141
+ usage = `lsof -n -i4TCP:#{port} | grep LISTEN`
142
+ if usage.length > 0
143
+ usage
144
+ else
145
+ false
146
+ end
120
147
  end
121
148
 
122
149
  end
@@ -1,3 +1,3 @@
1
1
  module Shaft
2
- VERSION = "0.6"
2
+ VERSION = "0.7"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shaft
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.6'
4
+ version: '0.7'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-04 00:00:00.000000000 Z
12
+ date: 2013-01-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -69,3 +69,4 @@ signing_key:
69
69
  specification_version: 3
70
70
  summary: An SSH tunnel assistant for the command line.
71
71
  test_files: []
72
+ has_rdoc: