Class: Ridley::HostConnector::SSH

Inherits:
Base
  • Object
show all
Defined in:
lib/ridley/host_connector/ssh.rb

Constant Summary collapse

DEFAULT_PORT =
22
EMBEDDED_RUBY_PATH =
'/opt/chef/embedded/bin/ruby'.freeze

Instance Method Summary collapse

Methods included from Logging

logger, #logger, set_logger

Instance Method Details

#bootstrap(host, options = {}) ⇒ HostConnector::Response

Bootstrap a node

Options Hash (options):

  • :ssh (Hash)
    • :user (String) a shell user that will login to each node and perform the bootstrap command on

    • :password (String) the password for the shell user that will perform the bootstrap

    • :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password

    • :timeout (Float) timeout value for SSH bootstrap (5.0)

    • :sudo (Boolean) run as sudo



92
93
94
95
96
97
98
99
# File 'lib/ridley/host_connector/ssh.rb', line 92

def bootstrap(host, options = {})
  options = options.reverse_merge(ssh: Hash.new)
  options[:ssh].reverse_merge!(sudo: true, timeout: 5.0)
  context = BootstrapContext::Unix.new(options)

  log.info "Bootstrapping host: #{host}"
  run(host, context.boot_command, options)
end

#chef_client(host, options = {}) ⇒ HostConnector::Response

Perform a chef client run on a node

Options Hash (options):

  • :ssh (Hash)
    • :user (String) a shell user that will login to each node and perform the bootstrap command on

    • :password (String) the password for the shell user that will perform the bootstrap

    • :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password

    • :timeout (Float) timeout value for SSH bootstrap (5.0)

    • :sudo (Boolean) run as sudo



114
115
116
# File 'lib/ridley/host_connector/ssh.rb', line 114

def chef_client(host, options = {})
  run(host, "chef-client", options)
end

#put_secret(host, secret, options = {}) ⇒ HostConnector::Response

Write your encrypted data bag secret on a node

Options Hash (options):

  • :ssh (Hash)
    • :user (String) a shell user that will login to each node and perform the bootstrap command on

    • :password (String) the password for the shell user that will perform the bootstrap

    • :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password

    • :timeout (Float) timeout value for SSH bootstrap (5.0)

    • :sudo (Boolean) run as sudo



133
134
135
136
# File 'lib/ridley/host_connector/ssh.rb', line 133

def put_secret(host, secret, options = {})
  cmd = "echo '#{secret}' > /etc/chef/encrypted_data_bag_secret; chmod 0600 /etc/chef/encrypted_data_bag_secret"
  run(host, cmd, options)
end

#ruby_script(host, command_lines, options = {}) ⇒ HostConnector::Response

Execute line(s) of Ruby code on a node using Chef’s embedded Ruby

Options Hash (options):

  • :ssh (Hash)
    • :user (String) a shell user that will login to each node and perform the bootstrap command on

    • :password (String) the password for the shell user that will perform the bootstrap

    • :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password

    • :timeout (Float) timeout value for SSH bootstrap (5.0)

    • :sudo (Boolean) run as sudo



153
154
155
# File 'lib/ridley/host_connector/ssh.rb', line 153

def ruby_script(host, command_lines, options = {})
  run(host, "#{EMBEDDED_RUBY_PATH} -e \"#{command_lines.join(';')}\"", options)
end

#run(host, command, options = {}) ⇒ HostConnector::Response

Execute a shell command on a node

Options Hash (options):

  • :ssh (Hash)
    • :user (String) a shell user that will login to each node and perform the bootstrap command on

    • :password (String) the password for the shell user that will perform the bootstrap

    • :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password

    • :timeout (Float) timeout value for SSH bootstrap (5.0)

    • :sudo (Boolean) run as sudo



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/ridley/host_connector/ssh.rb', line 23

def run(host, command, options = {})
  options = options.reverse_merge(ssh: Hash.new)
  options[:ssh].reverse_merge!(port: DEFAULT_PORT, paranoid: false, sudo: false)

  command = "sudo #{command}" if options[:ssh][:sudo]

  Ridley::HostConnector::Response.new(host).tap do |response|
    begin
      log.info "Running SSH command: '#{command}' on: '#{host}' as: '#{options[:ssh][:user]}'"

      defer {
        Net::SSH.start(host, options[:ssh][:user], options[:ssh].slice(*Net::SSH::VALID_OPTIONS)) do |ssh|
          ssh.open_channel do |channel|
            if options[:sudo]
              channel.request_pty do |channel, success|
                unless success
                  raise "Could not aquire pty: A pty is required for running sudo commands."
                end

                channel_exec(channel, command, host, response)
              end
            else
              channel_exec(channel, command, host, response)
            end
          end
          ssh.loop
        end
      }
    rescue Net::SSH::AuthenticationFailed => ex
      response.exit_code = -1
      response.stderr    = "Authentication failure for user #{ex}"
    rescue Net::SSH::ConnectionTimeout, Timeout::Error
      response.exit_code = -1
      response.stderr    = "Connection timed out"
    rescue Errno::EHOSTUNREACH
      response.exit_code = -1
      response.stderr    = "Host unreachable"
    rescue Errno::ECONNREFUSED
      response.exit_code = -1
      response.stderr    = "Connection refused"
    rescue Net::SSH::Exception => ex
      response.exit_code = -1
      response.stderr    = ex.inspect
    end

    case response.exit_code
    when 0
      log.info "Successfully ran SSH command on: '#{host}' as: '#{options[:ssh][:user]}'"
    when -1
      log.info "Failed to run SSH command on: '#{host}' as: '#{options[:ssh][:user]}'"
    else
      log.info "Successfully ran SSH command on: '#{host}' as: '#{options[:ssh][:user]}' but it failed"
    end
  end
end

#uninstall_chef(host, options = {}) ⇒ HostConnector::Response

Uninstall Chef from a node

Options Hash (options):

  • :skip_chef (Boolena) — default: false

    skip removal of the Chef package and the contents of the installation directory. Setting this to true will only remove any data and configurations generated by running Chef client.

  • :ssh (Hash)
    • :user (String) a shell user that will login to each node and perform the bootstrap command on

    • :password (String) the password for the shell user that will perform the bootstrap

    • :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password

    • :timeout (Float) timeout value for SSH bootstrap (5.0)

    • :sudo (Boolean) run as sudo (true)



174
175
176
177
178
179
180
# File 'lib/ridley/host_connector/ssh.rb', line 174

def uninstall_chef(host, options = {})
  options = options.reverse_merge(ssh: Hash.new)
  options[:ssh].reverse_merge!(sudo: true, timeout: 5.0)

  log.info "Uninstalling Chef from host: #{host}"
  run(host, CommandContext::UnixUninstall.command(options), options)
end