Module: Cirrus::SSH

Extended by:
SSH
Included in:
SSH
Defined in:
lib/cirrus/ssh.rb

Instance Method Summary collapse

Instance Method Details

#add_to_keychain(private_key_path) ⇒ Object

Start ssh-agent and add a key to the keychain TODO: avoid starting if already running



82
83
84
85
86
# File 'lib/cirrus/ssh.rb', line 82

def add_to_keychain(private_key_path)
  puts "Starting ssh-agent, adding keypair private key ..."
  puts `eval $(ssh-agent)`
  puts `ssh-add #{private_key_path}`
end

#bootstrap(host:, username:, private_key_path:, source_path:) ⇒ Object

TODO: better key handling (bootstrap with public key)



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/cirrus/ssh.rb', line 90

def bootstrap(host:, username:, private_key_path:, source_path:)
  return unless source_path

  puts "Bootstrapping instance (#{username}@#{host}) ..."

  add_to_keychain(private_key_path)

  tf = Tempfile.new('boxer-shell')
  tf.write(File.read(source_path))
  tf.rewind

  source_path = tf.path
  dest_path = "/tmp/boxer-shell"

  Cirrus::SCP.connect(host, username) do |scp|
    scp.upload!(source_path, dest_path)
  end
end

#connect(host, username) {|connection| ... } ⇒ Object

Open an SSH connection and yield it

Yields:

  • (connection)


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/cirrus/ssh.rb', line 12

def connect(host, username)
  timeout = 15

  common_connect_opts = {
    auth_methods:          ["publickey"],
    forward_agent:         false,
    port:                  22,
    timeout:               15,
    user_known_hosts_file: [],
    verbose:               :debug
  }

  begin
    connection =
      Timeout.timeout(timeout) do
        begin
          connect_opts = common_connect_opts.dup
          connect_opts[:logger] = Logger.new(StringIO.new)
          Net::SSH.start(host, username, connect_opts)
        end
      end
  rescue Errno::EACCES
    # This happens on connect() for unknown reasons yet...
    raise "eacces"
  rescue Errno::ETIMEDOUT, Timeout::Error
    # This happens if we continued to timeout when attempting to connect.
    if $retry_count < 3
      $retry_count += 1
      retry
    else
      raise "timeout"
    end
  rescue Net::SSH::AuthenticationFailed
    # This happens if authentication failed. We wrap the error in our
    # own exception.
    raise "authentication"
  rescue Net::SSH::Disconnect
    # This happens if the remote server unexpectedly closes the
    # connection. This is usually raised when SSH is running on the
    # other side but can't properly setup a connection. This is
    # usually a server-side issue.
    raise "disconnect"
  rescue Errno::ECONNREFUSED
    # This is raised if we failed to connect the max amount of times
    raise "econnrefused"
  rescue Errno::ECONNRESET
    # This is raised if we failed to connect the max number of times
    # due to an ECONNRESET.
    raise "econnreset"
  rescue Errno::EHOSTDOWN
    # This is raised if we get an ICMP DestinationUnknown error.
    raise "ehostdown"
  rescue Errno::EHOSTUNREACH
    # This is raised if we can't work out how to route traffic.
    raise "ehostunreach"
  rescue Net::SSH::Exception => e
    # This is an internal error in Net::SSH
    raise "internal net ssh error"
  rescue NotImplementedError
    # This is raised if a private key type that Net-SSH doesn't support
    # is used. Show a nicer error.
    raise "unsupported private key type"
  end

  yield connection
end