Class: Knife::Server::SSH
- Inherits:
-
Object
- Object
- Knife::Server::SSH
- Defined in:
- lib/knife/server/ssh.rb
Overview
Communicates with an SSH node.
Constant Summary collapse
- DEFAULT_OPTIONS =
{ :user => "root", :port => "22" }.freeze
- USER_SWITCH_COMMAND =
%{sudo USER=root HOME="$(getent passwd root | cut -d : -f 6)"}.freeze
Instance Method Summary collapse
- #exec!(cmd) ⇒ Object
-
#exec_ssh(wrapper, content) ⇒ Object
rubocop:disable Metrics/MethodLength.
- #full_cmd(cmd) ⇒ Object
-
#initialize(params) ⇒ SSH
constructor
A new instance of SSH.
-
#run_script(content) ⇒ Object
runs a script on the target host by passing it to the stdin of a sh process.
- #ssh_session(session, cmd, result) ⇒ Object
Constructor Details
#initialize(params) ⇒ SSH
Returns a new instance of SSH.
30 31 32 33 34 35 36 |
# File 'lib/knife/server/ssh.rb', line 30 def initialize(params) = DEFAULT_OPTIONS.merge(params) @host = .delete(:host) @user = .delete(:user) @options = end |
Instance Method Details
#exec!(cmd) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/knife/server/ssh.rb', line 38 def exec!(cmd) result = "" exit_code = nil Net::SSH.start(@host, @user, @options) do |session| exit_code = ssh_session(session, full_cmd(cmd), result) end if exit_code != 0 raise "SSH exited with code #{exit_code} for [#{full_cmd(cmd)}]" end result end |
#exec_ssh(wrapper, content) ⇒ Object
rubocop:disable Metrics/MethodLength
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/knife/server/ssh.rb', line 109 def exec_ssh(wrapper, content) # rubocop:disable Metrics/MethodLength result = "" exit_status = nil Net::SSH.start(@host, @user, @options) do |ssh| ssh.open_channel do |ch| ch.on_open_failed do |_, _, desc| raise "Connection Error to #{ip}: #{desc}" end ch.exec(wrapper) do |channel, _, _| # spit out the shell script and close stdin so sh can do its magic channel.send_data(content) channel.eof! # then we just wait for sweet, sweet output channel.on_data do |_, data| result << data end channel.on_request("exit-status") do |_, data| exit_status = data.read_long end end ch.wait end ssh.loop end [result, exit_status] end |
#full_cmd(cmd) ⇒ Object
50 51 52 53 54 55 56 |
# File 'lib/knife/server/ssh.rb', line 50 def full_cmd(cmd) if @user == "root" cmd else [USER_SWITCH_COMMAND, %{bash -c '#{cmd}'}].join(" ") end end |
#run_script(content) ⇒ Object
runs a script on the target host by passing it to the stdin of a sh process. returns stdout and the exit status. does not care about stderr.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/knife/server/ssh.rb', line 86 def run_script(content) user_switch = "" unless @user == "root" user_switch = USER_SWITCH_COMMAND end wrapper = <<-EOF if [ -e /dev/fd/0 ] then #{user_switch} /bin/sh /dev/fd/0 elif [ -e /dev/stdin ] then #{user_switch} /bin/sh /dev/stdin else echo "Cannot find method of communicating with the shell via stdin" exit 1 fi EOF exec_ssh(wrapper, content) end |
#ssh_session(session, cmd, result) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/knife/server/ssh.rb', line 58 def ssh_session(session, cmd, result) exit_code = nil session.open_channel do |channel| channel.request_pty channel.exec(cmd) do |_ch, _success| channel.on_data do |_ch, data| result << data end channel.on_extended_data do |_ch, _type, data| result << data end channel.on_request("exit-status") do |_ch, data| exit_code = data.read_long end end end session.loop exit_code end |