class Fulmar::Infrastructure::Service::SSHConfigService

Adds entries to the ssh config and checks for existing ones

Constants

DEFAULT_CONFIG_FILE
DEFAULT_KNOWN_HOSTS_FILE

Attributes

config_file[RW]
known_host_file[RW]
quiet[RW]

Public Class Methods

new(config, config_file = DEFAULT_CONFIG_FILE, known_hosts_file = DEFAULT_KNOWN_HOSTS_FILE) click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 16
def initialize(config, config_file = DEFAULT_CONFIG_FILE, known_hosts_file = DEFAULT_KNOWN_HOSTS_FILE)
  @config = config
  @config_file = config_file
  @known_hosts_file = known_hosts_file
  @quiet = false
end

Public Instance Methods

add_host(hostname, ssh_config = {}) click to toggle source

Adds a host to the ssh config file

# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 90
def add_host(hostname, ssh_config = {})
  puts "Adding host #{hostname}..." if @config[:debug]
  config_file = File.open(@config_file, 'a')

  unless ssh_config[:IdentityFile].blank? || ssh_config[:IdentityFile][0, 1] == '/'
    ssh_config[:IdentityFile] = @config.base_path + '/' + ssh_config[:IdentityFile]
  end

  config_file.puts host_entry(hostname, ssh_config)

  config_file.close
end
add_hosts() click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 42
def add_hosts
  backup_file
  @config.hosts.values.each do |data|
    unless config_valid?(data)
      puts "Skipping #{data[:hostname]}, config not sufficient." if @config[:debug]
      next
    end
    edit_host(data[:hostname], data[:ssh_config])
  end
  show_diff
end
backup_file() click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 103
def backup_file
  backup_filename = "#{@config_file}.bak"
  FileUtils.cp @config_file, backup_filename
end
changed?() click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 23
def changed?
  File.read(@config_file) != File.read("#{@config_file}.bak")
end
diff(type = :color) click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 27
def diff(type = :color)
  before = File.read("#{@config_file}.bak")
  after = File.read(@config_file)
  Diffy::Diff.new(before, after, context: 3).to_s(type)
end
edit_host(hostname, ssh_config) click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 65
def edit_host(hostname, ssh_config)
  data = read_file
  new_data = block_before(data.clone, hostname) +
             host_entry(hostname, ssh_config) +
             block_after(data, hostname)

  File.open(@config_file, 'w') do |file|
    file.puts new_data.join("\n")
  end
end
host_exists?(hostname) click to toggle source

Parses the users ssh config for an existing hostname

# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 77
def host_exists?(hostname)
  config_file = File.open(@config_file, 'r')
  while (line = config_file.gets)
    if /\s*Host #{Regexp.escape(hostname)}\s*$/ =~ line
      config_file.close
      return true
    end
  end
  config_file.close
  false
end
remove_known_host(hostname) click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 54
def remove_known_host(hostname)
  input_file = File.open(@known_hosts_file, 'r')
  output_file = File.open(@known_hosts_file + '.temp', 'w')
  while (line = input_file.gets)
    output_file.puts(line) unless /^\[?#{Regexp.escape(hostname)}(?:\]:\d+)?[ ,]/ =~ line
  end
  input_file.close
  output_file.close
  FileUtils.mv(@known_hosts_file + '.temp', @known_hosts_file)
end
show_diff() click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 33
def show_diff
  return if @quiet || !changed?
  puts 'You ssh host configuration changed: '
  puts '--------------- DIFF ---------------'
  puts diff
  puts '--------------- /DIFF --------------'
  puts 'You can revert these changes by running "fulmar revert:ssh_config"'
end

Protected Instance Methods

block_after(data, hostname) click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 165
def block_after(data, hostname)
  data = data.drop_while { |i| !/^Host\s#{Regexp.escape(hostname)}$/.match(i.strip) }
  return [] if data.empty?
  data.shift

  after = []
  cache = []
  write = false
  data.each do |line|
    if line.strip[0] == '#'
      cache << line
    else
      write = true if /^Host\s/ =~ line.strip
      if write
        after += cache
        after << line
      end
      cache = []
    end
  end
  remove_trailing_newlines(after)
end
block_before(data, hostname) click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 149
def block_before(data, hostname)
  cache = []
  before = []
  data.each do |line|
    if line.strip[0] == '#'
      cache << line
    else
      return remove_trailing_newlines(before) if /^Host\s#{Regexp.escape(hostname)}$/ =~ line.strip
      before += cache
      cache = []
      before << line
    end
  end
  remove_trailing_newlines(before)
end
config_valid?(host_config) click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 140
def config_valid?(host_config)
  (!host_config[:hostname].blank? && !host_config[:ssh_config].nil?)
end
escape_value(key, value) click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 124
def escape_value(key, value)
  value = value.to_s
  value = "\"#{value.gsub('"', '\\"')}\"" if value.include?(' ') && key.to_s != 'ProxyCommand'
  value
end
host_entry(hostname, ssh_config = {}) click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 110
def host_entry(hostname, ssh_config = {})
  unless ssh_config[:IdentityFile].blank? || ssh_config[:IdentityFile][0, 1] == '/'
    ssh_config[:IdentityFile] = @config.base_path + '/' + ssh_config[:IdentityFile]
  end

  entry = [
    '', # Add some space between this and the second last entry
    "Host #{hostname}"
  ]
  ssh_config.keys.each { |key| entry << "    #{key} #{escape_value(key, ssh_config[key])}" }
  entry << ''
  entry
end
read_file() click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 130
def read_file
  config_file_data = []
  File.open(@config_file, 'r') do |file|
    until file.eof?
      config_file_data << file.gets.chomp
    end
  end
  config_file_data
end
remove_trailing_newlines(data) click to toggle source
# File lib/fulmar/infrastructure/service/ssh_config_service.rb, line 144
def remove_trailing_newlines(data)
  data.pop while !data.empty? && data.last.strip.empty?
  data
end