taketo 0.0.10 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/Gemfile +1 -1
  2. data/Gemfile.lock +14 -30
  3. data/README.md +4 -0
  4. data/Rakefile +4 -8
  5. data/VERSION +1 -1
  6. data/bin/taketo +5 -5
  7. data/lib/taketo/config_printer_visitor.rb +6 -22
  8. data/lib/taketo/config_traverser.rb +4 -33
  9. data/lib/taketo/config_validator.rb +1 -1
  10. data/lib/taketo/config_visitor.rb +15 -1
  11. data/lib/taketo/constructs/base_construct.rb +30 -6
  12. data/lib/taketo/constructs/config.rb +5 -0
  13. data/lib/taketo/constructs/environment.rb +6 -3
  14. data/lib/taketo/constructs/project.rb +3 -3
  15. data/lib/taketo/constructs/server.rb +3 -4
  16. data/lib/taketo/constructs.rb +6 -1
  17. data/lib/taketo/destination_resolver.rb +37 -52
  18. data/lib/taketo/dsl.rb +6 -3
  19. data/lib/taketo/printer.rb +29 -0
  20. data/lib/taketo/ssh_config_generator_visitor.rb +8 -22
  21. data/spec/acceptance/command_spec.rb +20 -0
  22. data/spec/acceptance/config_dsl_spec.rb +277 -0
  23. data/spec/acceptance/config_validation_spec.rb +109 -0
  24. data/spec/acceptance/connect_to_server_spec.rb +60 -0
  25. data/spec/acceptance/error_handling_spec.rb +31 -0
  26. data/spec/acceptance/generate_ssh_config_spec.rb +44 -0
  27. data/spec/acceptance/help_spec.rb +74 -0
  28. data/spec/acceptance/location_spec.rb +21 -0
  29. data/spec/acceptance_spec_helper.rb +71 -0
  30. data/spec/lib/taketo/config_traverser_spec.rb +20 -33
  31. data/spec/lib/taketo/config_validator_spec.rb +4 -4
  32. data/spec/lib/taketo/config_visitor_spec.rb +0 -4
  33. data/spec/lib/taketo/constructs/base_construct_spec.rb +37 -5
  34. data/spec/lib/taketo/constructs/environment_spec.rb +1 -1
  35. data/spec/lib/taketo/constructs/project_spec.rb +0 -6
  36. data/spec/lib/taketo/constructs/server_spec.rb +1 -3
  37. data/spec/lib/taketo/destination_resolver_spec.rb +21 -54
  38. data/spec/lib/taketo/dsl_spec.rb +46 -44
  39. data/spec/spec_helper.rb +1 -1
  40. data/spec/support/helpers/construct_spec_helper.rb +29 -0
  41. metadata +94 -82
  42. data/features/commands.feature +0 -36
  43. data/features/config.feature +0 -177
  44. data/features/config_validation.feature +0 -43
  45. data/features/connect_to_server.feature +0 -87
  46. data/features/default_server_config.feature +0 -41
  47. data/features/error_handling.feature +0 -29
  48. data/features/generate_ssh_config.feature +0 -44
  49. data/features/help.feature +0 -76
  50. data/features/step_definitions/main_steps.rb +0 -16
  51. data/features/support/env.rb +0 -14
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source :rubygems
3
3
  group :development do
4
4
  gem "rspec", "~> 2.11"
5
5
  gem "rake", "~> 0.9"
6
- gem "aruba", "~> 0.4"
7
6
  gem 'simplecov', '~> 0.6', :require => false
7
+ gem 'open4', '~> 1.3'
8
8
  end
9
9
 
data/Gemfile.lock CHANGED
@@ -1,44 +1,28 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- aruba (0.4.11)
5
- childprocess (>= 0.2.3)
6
- cucumber (>= 1.1.1)
7
- ffi (>= 1.0.11)
8
- rspec (>= 2.7.0)
9
- builder (3.0.0)
10
- childprocess (0.3.2)
11
- ffi (~> 1.0.6)
12
- cucumber (1.2.1)
13
- builder (>= 2.1.2)
14
- diff-lcs (>= 1.1.3)
15
- gherkin (~> 2.11.0)
16
- json (>= 1.4.6)
17
4
  diff-lcs (1.1.3)
18
- ffi (1.0.11)
19
- gherkin (2.11.0)
20
- json (>= 1.4.6)
21
- json (1.7.3)
22
- multi_json (1.3.6)
23
- rake (0.9.2.2)
24
- rspec (2.11.0)
25
- rspec-core (~> 2.11.0)
26
- rspec-expectations (~> 2.11.0)
27
- rspec-mocks (~> 2.11.0)
28
- rspec-core (2.11.1)
29
- rspec-expectations (2.11.3)
5
+ multi_json (1.3.7)
6
+ open4 (1.3.0)
7
+ rake (0.9.5)
8
+ rspec (2.12.0)
9
+ rspec-core (~> 2.12.0)
10
+ rspec-expectations (~> 2.12.0)
11
+ rspec-mocks (~> 2.12.0)
12
+ rspec-core (2.12.0)
13
+ rspec-expectations (2.12.0)
30
14
  diff-lcs (~> 1.1.3)
31
- rspec-mocks (2.11.3)
32
- simplecov (0.6.4)
15
+ rspec-mocks (2.12.0)
16
+ simplecov (0.7.1)
33
17
  multi_json (~> 1.0)
34
- simplecov-html (~> 0.5.3)
35
- simplecov-html (0.5.3)
18
+ simplecov-html (~> 0.7.1)
19
+ simplecov-html (0.7.1)
36
20
 
37
21
  PLATFORMS
38
22
  ruby
39
23
 
40
24
  DEPENDENCIES
41
- aruba (~> 0.4)
25
+ open4 (~> 1.3)
42
26
  rake (~> 0.9)
43
27
  rspec (~> 2.11)
44
28
  simplecov (~> 0.6)
data/README.md CHANGED
@@ -144,6 +144,10 @@ An SSH config file can be generated from taketo config. To do so, run ```taketo
144
144
  The Changelog:
145
145
  --------------
146
146
 
147
+ ### v0.1.0 (04.12.2012) ###
148
+ * Servers can now be outside projects and environments (userful for standalone servers)
149
+ * SSH config is being generated both for hostnames and global aliases
150
+
147
151
  ### v0.0.10 (17.11.2012) ###
148
152
  * Add ability to generate ssh config
149
153
 
data/Rakefile CHANGED
@@ -12,22 +12,18 @@ end
12
12
 
13
13
  require 'rake'
14
14
  require 'rspec/core/rake_task'
15
- require 'cucumber'
16
- require 'cucumber/rake/task'
17
15
 
18
16
  RSpec::Core::RakeTask.new do |t|
19
17
  t.pattern = 'spec/lib/**/*_spec.rb'
20
18
  end
21
19
 
22
- RSpec::Core::RakeTask.new do |t|
20
+ RSpec::Core::RakeTask.new(:integration_spec) do |t|
23
21
  t.pattern = 'spec/integration/**/*_spec.rb'
24
- t.name = :integration_spec
25
22
  end
26
23
 
27
- Cucumber::Rake::Task.new(:features) do |t|
28
- t.cucumber_opts = "features --tags ~@wip --format pretty -x"
29
- t.fork = false
24
+ RSpec::Core::RakeTask.new(:acceptance_spec) do |t|
25
+ t.pattern = 'spec/acceptance/**/*_spec.rb'
30
26
  end
31
27
 
32
- task :default => [:spec, :features]
28
+ task :default => [:spec, :acceptance_spec]
33
29
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.10
1
+ 0.1.0
data/bin/taketo CHANGED
@@ -1,9 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- if ENV["TAKETO_DEV"]
4
- $:.unshift(File.expand_path('../../lib', __FILE__))
5
- end
6
-
7
3
  require 'rubygems'
8
4
 
9
5
  require 'taketo'
@@ -121,6 +117,10 @@ rescue SystemExit
121
117
  # Do nothing
122
118
  rescue Exception => e
123
119
  STDERR.puts "An error occurred: #{e.message}"
124
- raise if options && options[:debug]
120
+ if options && options[:debug]
121
+ STDERR.puts e.backtrace
122
+ raise
123
+ end
124
+ exit 1
125
125
  end
126
126
 
@@ -1,16 +1,14 @@
1
1
  require 'taketo/config_visitor'
2
+ require 'taketo/printer'
2
3
 
3
4
  module Taketo
4
5
  class ConfigPrinterVisitor < ConfigVisitor
5
- def initialize
6
- @indent_level = 0
7
- @result = ""
8
- end
6
+ include Printer
9
7
 
10
8
  visit Config do |config|
11
9
  indent(0) do
12
10
  if config.has_projects?
13
- put "Default destination: #{config.default_destination}" if config.default_destination
11
+ put_optional "Default destination:", config.default_destination
14
12
  else
15
13
  put "There are no projects yet..."
16
14
  end
@@ -37,9 +35,9 @@ module Taketo
37
35
  put "Server: #{server.name}"
38
36
  indent do
39
37
  put "Host: #{server.host}"
40
- put "Port: #{server.port}" if server.port
41
- put "User: #{server.username}" if server.username
42
- put "Default location: #{server.default_location}" if server.default_location
38
+ put_optional "Port:", server.port
39
+ put_optional "User:", server.username
40
+ put_optional "Default location:", server.default_location
43
41
  put "Default command: #{server.default_command}"
44
42
  put "Environment: " + server.environment_variables.map { |n, v| "#{n}=#{v}" }.join(" ")
45
43
  put "Commands:" if server.has_commands?
@@ -50,20 +48,6 @@ module Taketo
50
48
  visit Command do |command|
51
49
  indent(4) { put command.name.to_s + (" - " + command.description if command.description).to_s }
52
50
  end
53
-
54
- def result
55
- @result.chomp
56
- end
57
-
58
- def indent(level = nil)
59
- @first_indent ||= level || @indent_level
60
- level ? @indent_level = level - @first_indent : @indent_level += 1
61
- yield
62
- end
63
-
64
- def put(str = nil)
65
- @result += (" " * @indent_level + str.to_s).rstrip.chomp + "\n"
66
- end
67
51
  end
68
52
  end
69
53
 
@@ -3,53 +3,24 @@ require 'forwardable'
3
3
 
4
4
  module Taketo
5
5
  class ConfigTraverser
6
- LEVELS = { :config => 1, :project => 2, :environment => 3, :server => 4, :command => 5 }.freeze
7
- PLURALS = { :config => :configs, :project => :projects, :environment => :environments, :server => :servers, :command => :commands }.freeze
8
-
9
- class NodeWithPath < SimpleDelegator
10
- extend Forwardable
11
- def_delegators :__getobj__, :class, :ancestors, :== # avoid ancestry tree troubles
12
-
13
- attr_reader :path
14
-
15
- def initialize(node, path_string)
16
- super(node)
17
- @path = path_string.freeze
18
- end
19
- end
20
-
21
6
  def initialize(root)
22
7
  @root = root
23
8
  end
24
9
 
25
10
  def visit_depth_first(visitor)
26
- parents = []
27
- path_stack = [wrap_node_with_path(parents, @root)]
11
+ path_stack = [@root]
28
12
 
29
13
  while path_stack.any?
30
14
  node = path_stack.pop
31
15
  visitor.visit(node)
32
16
 
33
- next_level_node_type = LEVELS.respond_to?(:key) ? LEVELS.key(LEVELS[node.node_type] + 1) : LEVELS.index(LEVELS[node.node_type] + 1)
34
- if next_level_node_type && node.has_nodes?(PLURALS[next_level_node_type])
35
- parents << node
36
- node.nodes(PLURALS[next_level_node_type]).reverse_each do |n|
37
- n = wrap_node_with_path(parents, n)
38
- path_stack.push(n)
17
+ node.class.node_types.each do |node_type|
18
+ node.nodes(node_type).reverse_each do |n|
19
+ path_stack.push(n)
39
20
  end
40
21
  end
41
22
  end
42
23
  end
43
-
44
- private
45
-
46
- def wrap_node_with_path(parents, node)
47
- NodeWithPath.new(node, path(parents, node))
48
- end
49
-
50
- def path(parents, node)
51
- parents.map(&:name).reject(&:nil?).concat([node.name]).join(":")
52
- end
53
24
  end
54
25
  end
55
26
 
@@ -10,7 +10,7 @@ module Taketo
10
10
  end
11
11
 
12
12
  visit Config do |c|
13
- raise ConfigError, "There are no projects. Add some to your config (~/.taketo.rc.rb by default)" unless c.has_projects?
13
+ raise ConfigError, "There are no servers. Add some to your config (~/.taketo.rc.rb by default)" unless c.has_servers?
14
14
  end
15
15
 
16
16
  visit Project do |p|
@@ -21,8 +21,22 @@ module Taketo
21
21
  next unless respond_to?(method_name)
22
22
  return send(method_name, obj)
23
23
  end
24
+ end
25
+ end
26
+
27
+ def SimpleCollector(*types)
28
+ Class.new(ConfigVisitor) do
29
+ attr_reader :result
24
30
 
25
- raise "Don't know how to visit #{obj.class}"
31
+ def initialize
32
+ @result = []
33
+ end
34
+
35
+ types.each do |t|
36
+ visit t do |n|
37
+ @result << n
38
+ end
39
+ end
26
40
  end
27
41
  end
28
42
  end
@@ -4,14 +4,17 @@ require 'taketo/associated_nodes'
4
4
  module Taketo
5
5
  module Constructs
6
6
  class BaseConstruct
7
-
8
7
  include AssociatedNodes
9
- attr_reader :name, :default_server_config
8
+
9
+ attr_accessor :parent
10
+ attr_reader :name
11
+ attr_writer :default_server_config
10
12
 
11
13
  def initialize(name)
12
14
  super
13
15
  @name = name
14
16
  @default_server_config = proc {}
17
+ @parent = NullConstruct
15
18
  end
16
19
 
17
20
  def node_type
@@ -22,19 +25,40 @@ module Taketo
22
25
  ##
23
26
  # Override in subclasses if needed
24
27
  def parent=(parent)
25
- @default_server_config = parent.default_server_config
28
+ @parent = parent
26
29
  end
27
30
 
28
- def default_server_config=(config)
29
- default = @default_server_config
30
- @default_server_config = proc { instance_eval(&default); instance_eval(&config) }
31
+ def parents
32
+ result = []
33
+ p = parent
34
+ while p != NullConstruct
35
+ result << p
36
+ p = p.parent
37
+ end
38
+ result
39
+ end
40
+
41
+ def path
42
+ parents.reverse_each.map(&:name).concat([self.name]).reject(&:nil?).join(":")
43
+ end
44
+
45
+ def default_server_config
46
+ parent_default_server_config = parent.default_server_config
47
+ own_default_server_config = @default_server_config
48
+ proc { instance_eval(&parent_default_server_config); instance_eval(&own_default_server_config)}
31
49
  end
32
50
 
33
51
  def qualified_name
34
52
  "#{node_type} #{self.name}"
35
53
  end
54
+ end
36
55
 
56
+ class NullConstructClass
57
+ def default_server_config; proc {}; end
37
58
  end
59
+
60
+ NullConstruct = NullConstructClass.new
61
+
38
62
  end
39
63
  end
40
64
 
@@ -5,12 +5,17 @@ module Taketo
5
5
  module Constructs
6
6
  class Config < BaseConstruct
7
7
  has_nodes :projects, :project
8
+ has_nodes :servers, :server
8
9
 
9
10
  attr_accessor :default_destination
10
11
 
11
12
  def initialize(*args)
12
13
  super(nil)
13
14
  end
15
+
16
+ def has_servers?
17
+ has_nodes?(:servers) || projects.any?(&:has_servers?)
18
+ end
14
19
  end
15
20
  end
16
21
  end
@@ -1,4 +1,5 @@
1
1
  require 'taketo/constructs/base_construct'
2
+ require 'taketo/constructs/project'
2
3
  require 'taketo/support'
3
4
 
4
5
  module Taketo
@@ -6,14 +7,16 @@ module Taketo
6
7
  class Environment < BaseConstruct
7
8
  has_nodes :servers, :server
8
9
 
9
- attr_accessor :project
10
-
11
10
  def initialize(name)
12
11
  super(name)
13
12
  end
14
13
 
15
14
  def project_name
16
- @project.name if defined? @project
15
+ if parent.is_a?(Project)
16
+ parent.name
17
+ else
18
+ ""
19
+ end
17
20
  end
18
21
  end
19
22
  end
@@ -5,10 +5,10 @@ module Taketo
5
5
  module Constructs
6
6
  class Project < BaseConstruct
7
7
  has_nodes :environments, :environment
8
+ has_nodes :servers, :server
8
9
 
9
- def append_environment(environment)
10
- environment.project = self
11
- super
10
+ def has_servers?
11
+ has_nodes?(:servers) || environments.any?(&:has_servers?)
12
12
  end
13
13
  end
14
14
  end
@@ -6,7 +6,7 @@ module Taketo
6
6
  module Constructs
7
7
  class Server < BaseConstruct
8
8
  attr_reader :environment_variables
9
- attr_accessor :host, :port, :username, :default_location, :default_command, :environment, :global_alias, :identity_file
9
+ attr_accessor :host, :port, :username, :default_location, :default_command, :global_alias, :identity_file
10
10
 
11
11
  has_nodes :commands, :command
12
12
 
@@ -19,10 +19,9 @@ module Taketo
19
19
  @environment_variables.merge!(env_variables)
20
20
  end
21
21
 
22
- def parent=(environment)
23
- env(:RAILS_ENV => environment.name.to_s)
24
- @environment = environment
22
+ def parent=(parent)
25
23
  super
24
+ env(:RAILS_ENV => parent.name.to_s) if parent.is_a?(Environment)
26
25
  end
27
26
 
28
27
  def default_command
@@ -3,4 +3,9 @@ module Taketo
3
3
  end
4
4
  end
5
5
 
6
- Dir.glob(File.expand_path('../constructs/*.rb', __FILE__)).each { |c| require c }
6
+ require 'taketo/constructs/base_construct'
7
+ require 'taketo/constructs/config'
8
+ require 'taketo/constructs/project'
9
+ require 'taketo/constructs/environment'
10
+ require 'taketo/constructs/server'
11
+ require 'taketo/constructs/command'
@@ -1,81 +1,66 @@
1
+ require 'taketo/config_visitor'
2
+ require 'taketo/config_traverser'
3
+
1
4
  module Taketo
2
5
  class AmbiguousDestinationError < StandardError; end
3
6
  class NonExistentDestinationError < StandardError; end
4
7
 
5
8
  class DestinationResolver
6
- class Path
7
- PATH = [[:project, :projects], [:environment, :environments], [:server, :servers]].freeze
8
-
9
- class PathNode < Struct.new(:name, :singular, :plural); end
10
-
11
- def initialize(names)
12
- names = names.split(":").map(&:to_sym)
13
- @path = PATH.each_with_index.map { |n, i| PathNode.new(names[i], *n) }
14
- end
15
-
16
- def specified
17
- @path.reject { |n| n.name.nil? }
18
- end
19
-
20
- def unspecified
21
- @path - specified
22
- end
23
- end
24
-
25
9
  def initialize(config, path)
26
10
  @config = config
27
11
  if String(path).empty? && !String(config.default_destination).empty?
28
12
  path = config.default_destination
29
13
  end
30
- @path_str = path.dup
31
- @path = Path.new(path)
14
+ @path = path
15
+ @traverser = ConfigTraverser.new(@config)
32
16
  end
33
17
 
34
- def resolve
35
- resolve_by_global_alias || resolve_by_path
36
- end
37
-
38
- def get_node(node = @config, remaining_path = @path.specified)
39
- handling_failure do
40
- return node if remaining_path.empty?
41
- next_in_path = remaining_path.shift
42
- node = node.find(next_in_path.singular, next_in_path.name)
43
- get_node(node, remaining_path)
18
+ def servers
19
+ @servers ||= begin
20
+ collector = SimpleCollector(Taketo::Constructs::Server).new
21
+ @traverser.visit_depth_first(collector)
22
+ collector.result
44
23
  end
45
24
  end
46
25
 
47
- private
26
+ def resolve
27
+ resolve_by_global_alias || resolve_by_path
28
+ end
48
29
 
49
30
  def resolve_by_global_alias
50
- aliases_and_servers = Hash[servers_with_aliases]
51
- aliases_and_servers[@path_str.to_sym] unless String(@path_str).empty?
31
+ unless @path.to_s.empty?
32
+ servers.select(&:global_alias).detect { |s| s.global_alias == @path.to_sym }
33
+ end
52
34
  end
53
35
 
54
36
  def resolve_by_path
55
- node = get_node
56
- get_only_server(node)
37
+ matching_servers = servers.select { |s| s.path =~ /^#@path/ }
38
+ disambiguate(matching_servers)
57
39
  end
58
40
 
59
- def get_only_server(node, remaining_path = @path.unspecified)
60
- return node if remaining_path.empty?
61
- next_in_path = remaining_path.shift
62
- nested_nodes = node.nodes(next_in_path.plural)
63
- if nested_nodes.one?
64
- node = nested_nodes.first
65
- get_only_server(node, remaining_path)
66
- else
67
- raise AmbiguousDestinationError, "There are multiple #{next_in_path.plural} for #{node.node_type} #{node.name}: #{nested_nodes.map(&:name).join(", ")}"
68
- end
41
+ def get_node
42
+ matching_nodes = nodes.select { |n| n.path == @path }
43
+ disambiguate(matching_nodes)
69
44
  end
70
45
 
71
- def handling_failure(message = nil)
72
- yield
73
- rescue KeyError, NonExistentDestinationError
74
- raise NonExistentDestinationError, message || $!.message
46
+ def nodes
47
+ @nodes ||= begin
48
+ collector = SimpleCollector(Taketo::Constructs::BaseConstruct).new
49
+ @traverser.visit_depth_first(collector)
50
+ collector.result
51
+ end
75
52
  end
76
53
 
77
- def servers_with_aliases
78
- @config.nodes(:projects).map { |p| p.nodes(:environments).map { |e| e.nodes(:servers).reject { |s| s.global_alias.nil? }.map { |s| [s.global_alias, s] } } }.flatten(2)
54
+ def disambiguate(results)
55
+ case results.length
56
+ when 0
57
+ raise NonExistentDestinationError, "Can't find server for path #@path"
58
+ when 1
59
+ results.first
60
+ else
61
+ raise AmbiguousDestinationError,
62
+ "There are multiple possible destinations: #{results.map(&:path).join(", ")}"
63
+ end
79
64
  end
80
65
  end
81
66
  end
data/lib/taketo/dsl.rb CHANGED
@@ -6,9 +6,12 @@ module Taketo
6
6
  class ConfigError < StandardError; end
7
7
 
8
8
  class << self
9
- def define_scope(scope, parent_scope, options = {}, &block)
9
+ def define_scope(scope, *args, &block)
10
+ options = args.last.is_a?(Hash) ? args.pop : {}
11
+ parent_scopes = args
12
+
10
13
  define_method scope do |*args, &blk|
11
- ensure_nesting_allowed!(scope, parent_scope)
14
+ ensure_nesting_allowed!(scope, parent_scopes)
12
15
  name = args.shift || options[:default_name] or raise(ArgumentError, "Name not specified")
13
16
 
14
17
  scope_object = current_scope_object.find(scope, name) { @factory.create(scope, name) }
@@ -54,7 +57,7 @@ module Taketo
54
57
  define_scope :project, :config
55
58
  define_scope :environment, :project
56
59
 
57
- define_scope :server, :environment, :default_name => :default do |s|
60
+ define_scope :server, :environment, :project, :config, :default_name => :default do |s|
58
61
  instance_eval(&s.default_server_config)
59
62
  end
60
63
 
@@ -0,0 +1,29 @@
1
+ module Taketo
2
+ module Printer
3
+ def initialize
4
+ @indent_level = 0
5
+ @print_result = ""
6
+ end
7
+
8
+ def result
9
+ @print_result.chomp
10
+ end
11
+
12
+ private
13
+
14
+ def indent(level = nil)
15
+ @first_indent ||= level || @indent_level
16
+ level ? @indent_level = level - @first_indent : @indent_level += 1
17
+ yield
18
+ end
19
+
20
+ def put(str = nil)
21
+ @print_result += (" " * @indent_level + str.to_s).rstrip.chomp + "\n"
22
+ end
23
+
24
+ def put_optional(str, value)
25
+ put "#{str} #{value}" if value
26
+ end
27
+ end
28
+ end
29
+
@@ -1,36 +1,22 @@
1
1
  require 'taketo/config_visitor'
2
+ require 'taketo/printer'
2
3
 
3
4
  module Taketo
4
5
  class SSHConfigGeneratorVisitor < ConfigVisitor
5
- def initialize
6
- @result = ""
7
- end
6
+ include Printer
8
7
 
9
8
  visit Server do |server|
10
- put "Host #{server.global_alias || server.host}"
9
+ put_server(server, server.global_alias) unless server.global_alias.to_s.empty?
10
+ put_server(server, server.host)
11
+ end
12
+
13
+ def put_server(server, host)
14
+ put "Host #{host}"
11
15
  put "Hostname #{server.host}"
12
16
  put_optional "Port", server.port
13
17
  put_optional "User", server.username
14
18
  put_optional "IdentityFile", server.identity_file
15
19
  put
16
20
  end
17
-
18
- visit Object do |_|
19
- # catch all
20
- end
21
-
22
- def result
23
- @result.chomp
24
- end
25
-
26
- private
27
-
28
- def put(str = "")
29
- @result += str + "\n"
30
- end
31
-
32
- def put_optional(str, value)
33
- put "#{str} #{value}" if value
34
- end
35
21
  end
36
22
  end