Narnach-simple_gate 0.5.2 → 0.5.3

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.rdoc CHANGED
@@ -50,6 +50,13 @@ connection.
50
50
 
51
51
  == Recent changes
52
52
 
53
+ === Version 0.5.3
54
+
55
+ * Added yardoc documentation to all classes.
56
+ * SimpleGate#through raises an error when no gates are chosen
57
+ * SimpleGate#through uses local variables instead of instance variables
58
+ * ServerDefinition#options is created on the fly
59
+
53
60
  === Version 0.5.2
54
61
 
55
62
  * Added -V verbose flag to gate_cp
@@ -1,25 +1,33 @@
1
1
  class Router
2
- # Graph of server connections.
3
- # It's a Hash of Arrays, which contains strings. Keys are server names with
4
- # a connection to other servers. Each of these servers is a string in the
5
- # associated Array.
6
- # An example graph with three servers 'foo', 'bar' and 'baz'.
2
+ # Graph of server connections.
3
+ attr_accessor :paths
4
+
5
+ # Create a new Router for a network of interconnected servers.
6
+ # An example connections graph with three servers 'foo', 'bar' and 'baz':
7
7
  #
8
8
  # router = Router.new
9
+ # # Define a graph: foo -> bar -> baz
9
10
  # router.paths = {
10
11
  # 'foo' => %w[bar],
11
- # 'bar' => ['baz']
12
+ # 'bar' => %w[baz]
12
13
  # }
13
14
  # router.find('foo', 'baz') #=> ['foo', 'bar', 'baz']
14
- attr_accessor :paths
15
-
15
+ # @param [Hash] paths Graph of server connections.
16
+ # It's a Hash of Arrays, which contains strings. Keys are server
17
+ # names with a connection to other servers. Each of these servers is a
18
+ # string in the associated Array.
16
19
  def initialize(paths={})
17
20
  @paths = paths
18
21
  end
19
22
 
20
- # A simple pathfinder. Returns a route as Array or nil.
23
+ # A simple recursive pathfinder.
21
24
  # Uses a very naieve depth-first recursive full-graph search to
22
25
  # find the shortest route.
26
+ # @param [String] start The node to start searching from for +target+.
27
+ # @param [String] target The node to look for. Once it is found, return the shortest route to it.
28
+ # @param [Array] current_route Internal variable that holds the route so far. Helps in preventing cyclic routes from being checked an infinite amount of times.
29
+ # @return [Array] The sequence of nodes that connect +start+ to +target+.
30
+ # @return [nil] When no route was found.
23
31
  def find(start, target, current_route = [])
24
32
  return [target] if start == target
25
33
  return nil unless paths.has_key?(start)
@@ -1,57 +1,72 @@
1
1
  require 'yaml'
2
2
  class ServerDefinition
3
- attr_accessor :host, :user, :options, :port, :password
4
-
3
+ attr_accessor :host, :user, :port, :password, :auth_methods
4
+
5
+ # Create a new ServerDefinition.
6
+ #
7
+ # @param [String] host Name of server.
8
+ # @param [Hash] options Override the server's own configuration.
9
+ # @option options [Integer] port (22) Server port
10
+ # @option options [String] user SSH user
11
+ # @option options [String] password SSH password
5
12
  def initialize(host, options = {})
6
- @options = {:port => 22}.merge(options)
7
13
  self.host = host
8
- self.user = @options[:user]
9
- self.password = @options[:password]
10
- self.port = @options[:port]
11
- end
12
-
13
- def user=(user)
14
- options[:user] = user
15
- @user=user
16
- end
17
-
18
- def port=(port)
19
- options[:port] = port
20
- @port=port
14
+ self.user = options[:user]
15
+ self.password = options[:password]
16
+ self.port = options[:port] || 22
17
+ self.auth_methods = options[:auth_methods] || %w[password keyboard-interactive]
21
18
  end
22
19
 
23
- def password=(password)
24
- options[:password] = password
25
- @password=password
20
+ # SSH options
21
+ # @return [Hash]
22
+ def options
23
+ {
24
+ :user => user,
25
+ :password => password,
26
+ :port => port,
27
+ :auth_methods => auth_methods
28
+ }
26
29
  end
27
30
 
31
+ # Yield connection information.
32
+ # @yieldparam [String] host SSH host
33
+ # @yieldparam [String] user SSH user
34
+ # @yieldparam [Hash] options SSH connection options
35
+ # @see ServerDefinition#initialize
36
+ # @see ServerDefinition#ssh_options
28
37
  def connection_info(&block)
29
- block.call(host, user, options.merge(ssh_options))
38
+ block.call(host, user, options)
30
39
  end
31
-
32
- def ssh_options
33
- {
34
- :auth_methods => %w[password keyboard-interactive]
35
- }
36
- end
37
-
40
+
41
+ # Represent server definition as URL-like string
42
+ # @return [String]
38
43
  def to_s
39
44
  "#{user}:#{'*' * password.to_s.size}@#{host}:#{port}"
40
45
  end
41
-
46
+
47
+ # Factory method that uses pre-defined server configurations.
48
+ # @return [ServerDefinition]
42
49
  def self.lookup(server)
43
50
  server = servers[server]
44
- new(server['address'],{
51
+ new(server['address'],{
45
52
  :user => server['username'],
46
- :password => server['password'],
53
+ :password => server['password'],
47
54
  :port => server['port']
48
55
  })
49
56
  end
50
-
57
+
58
+ # Factory method that chooses between a lookup and parse.
59
+ # @param [String] server Server name or ssh string
60
+ # @return [ServerDefinition]
61
+ # @see ServerDefinition.lookup
62
+ # @see ServerDefinition.parse
51
63
  def self.find(server)
52
64
  servers.has_key?(server) ? lookup(server) : parse(server)
53
65
  end
54
-
66
+
67
+ # Factory method that parses a connection string.
68
+ # @param [String] ssh_string String formatted as "user:password@host:port"
69
+ # @return [ServerDefinition]
55
70
  def self.parse(ssh_string)
56
71
  user, password, host, port = ssh_string.match /\A(.*?):(.*?)@(.*?):(\d*?)\Z/
57
72
  new(host, :user => user, :password => password, :port => port)
@@ -76,6 +91,7 @@ class ServerDefinition
76
91
  #
77
92
  # Since the parsed Hash of servers is cached, a value can be stored and
78
93
  # the configuration file ignored if desired.
94
+ # @return [Hash] Server name to server configuration pairs.
79
95
  def servers
80
96
  @servers ||= YAML.load_file(File.expand_path('~/.servers.yml'))
81
97
  end
data/lib/simple_gate.rb CHANGED
@@ -5,19 +5,26 @@ require 'activesupport'
5
5
  require 'simple_gate/server_definition'
6
6
 
7
7
  class SimpleGate
8
+ # Initialize a new SimpleGate
9
+ # @param [Hash] options Hash with options to configure SimpleGate. Defaults to set :verbose to false.
8
10
  def initialize(options={})
9
11
  @options = {
10
12
  :verbose => false
11
13
  }.merge(options)
12
14
  end
13
15
 
16
+ # Is the verbose option turned on?
14
17
  def verbose?
15
18
  @options[:verbose]
16
19
  end
17
20
 
18
- # Connect through a list of gateways to the real server.
19
- # Treats the last 'gateway' as the real server and the others as gateways.
20
- def through_to(*gateways) # :yields: ssh session
21
+ # Connect through a list of gateways to a target server.
22
+ # Treats the last 'gateway' as the target server and the others as gateways.
23
+ #
24
+ # @param [Array] *gateways A list of gateway server names that can be found using ServerDefinition.find(). Should have at least one server name.
25
+ # @yieldparam [Net::SSH::Connection::Session] session SSH Session to the target server.
26
+ # @raise [ArgumentError] When no gateways are chosen.
27
+ def through_to(*gateways)
21
28
  gateways = gateways.flatten
22
29
  raise ArgumentError.new("No target chosen") if gateways.size == 0
23
30
  target = ServerDefinition.find(gateways.pop)
@@ -39,19 +46,27 @@ class SimpleGate
39
46
  nil
40
47
  end
41
48
 
49
+ # Establish a series of gateways and yields the last one created.
50
+ # Will automatically shut down gateway connections when the block closes.
51
+ #
42
52
  # Most of the code was taken from Capistrano and then changed to work
43
53
  # outside of Capistrano.
54
+ #
55
+ # @param [Array] *gateways A list of gateway server names that can be found using ServerDefinition.find(). Should have at least one server name.
56
+ # @yieldparam [Net::SSH::Gateway] gateway Gateway object of the last tunnel endpoint.
57
+ # @raise [ArgumentError] When no gateways are chosen.
44
58
  def through(*gateways)
45
59
  Thread.abort_on_exception = true
46
- @open_connections ||= []
47
- @gateways = gateways.flatten.collect { |g| ServerDefinition.find(g) }
48
- tunnel = @gateways[0].connection_info do |host, user, connect_options|
49
- STDERR.puts "Setting up tunnel #{@gateways[0]}" if verbose?
60
+ open_connections = []
61
+ gateways = gateways.flatten.collect { |g| ServerDefinition.find(g) }
62
+ raise ArgumentError.new("No target chosen") if gateways.size == 0
63
+ tunnel = gateways[0].connection_info do |host, user, connect_options|
64
+ STDERR.puts "Setting up tunnel #{gateways[0]}" if verbose?
50
65
  gw = Net::SSH::Gateway.new(host, user, connect_options)
51
- @open_connections << gw
66
+ open_connections << gw
52
67
  gw
53
68
  end
54
- @gateway = (@gateways[1..-1]).inject(tunnel) do |tunnel, destination|
69
+ gateway = (gateways[1..-1]).inject(tunnel) do |tunnel, destination|
55
70
  STDERR.puts "Connecting to #{destination}" if verbose?
56
71
  tunnel_port = tunnel.open(destination.host, (destination.port || 22))
57
72
  localhost_options = {:user => destination.user, :port => tunnel_port, :password => destination.password}
@@ -59,13 +74,13 @@ class SimpleGate
59
74
  local_host.connection_info do |host, user, connect_options|
60
75
  STDERR.puts "Connecting using local info #{local_host}" if verbose?
61
76
  gw = Net::SSH::Gateway.new(host, user, connect_options)
62
- @open_connections << gw
77
+ open_connections << gw
63
78
  gw
64
79
  end
65
80
  end
66
- yield(@gateway)
81
+ yield(gateway)
67
82
  ensure
68
- while g = @open_connections.pop
83
+ while g = open_connections.pop
69
84
  g.shutdown!
70
85
  end
71
86
  end
data/simple_gate.gemspec CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
3
3
  s.name = 'simple_gate'
4
4
  s.summary = "SimpleGate makes it possible to use net/ssh/gateway's capabilities in a simple to use way."
5
5
  s.description = s.summary
6
- s.version = '0.5.2'
7
- s.date = '2009-04-18'
6
+ s.version = '0.5.3'
7
+ s.date = '2009-05-16'
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Wes Oldenbeuving"]
10
10
  s.email = "narnach@gmail.com"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: Narnach-simple_gate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wes Oldenbeuving
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-18 00:00:00 -07:00
12
+ date: 2009-05-16 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15