Class: Bcome::Ssh::Driver
- Inherits:
-
Object
- Object
- Bcome::Ssh::Driver
- Defined in:
- lib/objects/ssh/driver.rb
Constant Summary collapse
- DEFAULT_TIMEOUT_IN_SECONDS =
5
- PROXY_CONNECT_PREFIX =
'-o StrictHostKeyChecking=no -W %h:%p'.freeze
- PROXY_SSH_PREFIX =
'-o UserKnownHostsFile=/dev/null -o "ProxyCommand ssh -W %h:%p'.freeze
Instance Attribute Summary collapse
-
#bootstrap_settings ⇒ Object
readonly
Returns the value of attribute bootstrap_settings.
-
#config ⇒ Object
readonly
Returns the value of attribute config.
Instance Method Summary collapse
- #bastion_host_user ⇒ Object
- #bootstrap? ⇒ Boolean
- #bootstrap_proxy_connection_string ⇒ Object
- #bootstrap_rsync_command(local_path, remote_path) ⇒ Object
- #bootstrap_ssh_command ⇒ Object
- #close_ssh_connection ⇒ Object
- #do_ssh ⇒ Object
- #fallback_local_user ⇒ Object
- #get(remote_path, local_path) ⇒ Object
- #get_overriden_local_user ⇒ Object
- #has_bootstrap_settings? ⇒ Boolean
- #has_open_ssh_con? ⇒ Boolean
- #has_proxy? ⇒ Boolean
-
#initialize(config, context_node) ⇒ Driver
constructor
A new instance of Driver.
- #key_specified_at_node_level? ⇒ Boolean
- #local_port_forward(start_port, end_port) ⇒ Object
- #net_ssh_params(verbose = false) ⇒ Object
- #node_host_or_ip ⇒ Object
- #node_level_ssh_key ⇒ Object
- #node_level_ssh_key_connection_string ⇒ Object
- #overriden_local_user ⇒ Object
- #ping ⇒ Object
- #pretty_config_details ⇒ Object
- #proxy ⇒ Object
- #proxy_config_value ⇒ Object
- #proxy_connection_string ⇒ Object
- #put(local_path, remote_path) ⇒ Object
- #rsync(local_path, remote_path) ⇒ Object
- #rsync_command(local_path, remote_path) ⇒ Object
- #scp ⇒ Object
- #ssh_command(as_pseudo_tty = false) ⇒ Object
- #ssh_connect!(_verbose = false) ⇒ Object
- #ssh_connection(_bootstrap = false) ⇒ Object
- #ssh_keys ⇒ Object
- #timeout_in_seconds ⇒ Object
- #user ⇒ Object
Constructor Details
#initialize(config, context_node) ⇒ Driver
Returns a new instance of Driver.
9 10 11 12 13 14 |
# File 'lib/objects/ssh/driver.rb', line 9 def initialize(config, context_node) @config = config @context_node = context_node @proxy_data = @config[:proxy] ? ::Bcome::Ssh::ProxyData.new(@config[:proxy], @context_node) : nil @bootstrap_settings = @config[:bootstrap_settings] ? ::Bcome::Ssh::Bootstrap.new(@config[:bootstrap_settings]) : nil end |
Instance Attribute Details
#bootstrap_settings ⇒ Object (readonly)
Returns the value of attribute bootstrap_settings.
3 4 5 |
# File 'lib/objects/ssh/driver.rb', line 3 def bootstrap_settings @bootstrap_settings end |
#config ⇒ Object (readonly)
Returns the value of attribute config.
3 4 5 |
# File 'lib/objects/ssh/driver.rb', line 3 def config @config end |
Instance Method Details
#bastion_host_user ⇒ Object
74 75 76 |
# File 'lib/objects/ssh/driver.rb', line 74 def bastion_host_user bootstrap? && @bootstrap_settings.bastion_host_user ? @bootstrap_settings.bastion_host_user : @proxy_data.bastion_host_user ? @proxy_data.bastion_host_user : user end |
#bootstrap? ⇒ Boolean
16 17 18 |
# File 'lib/objects/ssh/driver.rb', line 16 def bootstrap? @context_node.bootstrap? && has_bootstrap_settings? end |
#bootstrap_proxy_connection_string ⇒ Object
65 66 67 |
# File 'lib/objects/ssh/driver.rb', line 65 def bootstrap_proxy_connection_string "ssh -i #{@bootstrap_settings.ssh_key_path} -o StrictHostKeyChecking=no -W %h:%p #{@bootstrap_settings.bastion_host_user}@#{@proxy_data.host}" end |
#bootstrap_rsync_command(local_path, remote_path) ⇒ Object
191 192 193 194 195 196 197 |
# File 'lib/objects/ssh/driver.rb', line 191 def bootstrap_rsync_command(local_path, remote_path) if has_proxy? "rsync -av -e \"ssh -i #{@bootstrap_settings.ssh_key_path} -A #{bastion_host_user}@#{@proxy_data.host} ssh -o StrictHostKeyChecking=no\" #{local_path} #{user}@#{@context_node.internal_ip_address}:#{remote_path}" else "rsync -i #{@bootstrap_settings.ssh_key_path} -av #{local_path} #{user}@#{@context_node.public_ip_address}:#{remote_path}" end end |
#bootstrap_ssh_command ⇒ Object
121 122 123 124 125 126 127 |
# File 'lib/objects/ssh/driver.rb', line 121 def bootstrap_ssh_command if has_proxy? "ssh -i #{@bootstrap_settings.ssh_key_path} -t #{bastion_host_user}@#{@proxy_data.host} ssh -t #{user}@#{@context_node.internal_ip_address}" else "ssh -i #{@bootstrap_settings.ssh_key_path} #{user}@#{@context_node.public_ip_address}" end end |
#close_ssh_connection ⇒ Object
247 248 249 250 251 |
# File 'lib/objects/ssh/driver.rb', line 247 def close_ssh_connection return unless @connection @connection.close unless @connection.closed? @connection = nil end |
#do_ssh ⇒ Object
69 70 71 72 |
# File 'lib/objects/ssh/driver.rb', line 69 def do_ssh cmd = ssh_command @context_node.execute_local(cmd) end |
#fallback_local_user ⇒ Object
151 152 153 |
# File 'lib/objects/ssh/driver.rb', line 151 def fallback_local_user @fallback_local_user ||= ::Bcome::System::Local.instance.local_user end |
#get(remote_path, local_path) ⇒ Object
234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/objects/ssh/driver.rb', line 234 def get(remote_path, local_path) raise Bcome::Exception::MissingParamsForScp, "'get' requires a local_path and a remote_path" if local_path.to_s.empty? || remote_path.to_s.empty? puts "\n(#{@context_node.namespace})\s".namespace + "Downloading #{remote_path} to #{local_path}\n".informational begin scp.download!(remote_path, local_path, recursive: true) do |_ch, name, sent, total| puts "#{name}: #{sent}/#{total}".progress end rescue Exception => e # scp just throws generic exceptions :-/ puts e..error end end |
#get_overriden_local_user ⇒ Object
147 148 149 |
# File 'lib/objects/ssh/driver.rb', line 147 def get_overriden_local_user ::Bcome::Node::Factory.instance.local_data[:ssh_user] end |
#has_bootstrap_settings? ⇒ Boolean
20 21 22 |
# File 'lib/objects/ssh/driver.rb', line 20 def has_bootstrap_settings? !@bootstrap_settings.nil? end |
#has_open_ssh_con? ⇒ Boolean
257 258 259 |
# File 'lib/objects/ssh/driver.rb', line 257 def has_open_ssh_con? !@connection.nil? && !@connection.closed? end |
#has_proxy? ⇒ Boolean
52 53 54 55 |
# File 'lib/objects/ssh/driver.rb', line 52 def has_proxy? return false if proxy_config_value && proxy_config_value == -1 !@config[:proxy].nil? end |
#key_specified_at_node_level? ⇒ Boolean
92 93 94 |
# File 'lib/objects/ssh/driver.rb', line 92 def key_specified_at_node_level? !node_level_ssh_key.nil? end |
#local_port_forward(start_port, end_port) ⇒ Object
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/objects/ssh/driver.rb', line 100 def local_port_forward(start_port, end_port) if has_proxy? if bootstrap? tunnel_command = "ssh -N -L #{start_port}:#{@context_node.internal_ip_address}:#{end_port} -i #{@bootstrap_settings.ssh_key_path} #{bastion_host_user}@#{@proxy_data.host}" else tunnel_command = "ssh -N -L #{start_port}:#{@context_node.internal_ip_address}:#{end_port} #{bastion_host_user}@#{@proxy_data.host}" end else if bootstrap? tunnel_command = "ssh -i #{@bootstrap_settings.ssh_key_path} -N -L #{start_port}:#{@context_node.public_ip_address}:#{end_port}" else tunnel_command = "ssh -N -L #{start_port}:#{@context_node.public_ip_address}:#{end_port}" end end tunnel = ::Bcome::Ssh::Tunnel::LocalPortForward.new(tunnel_command) tunnel.open! return tunnel end |
#net_ssh_params(verbose = false) ⇒ Object
159 160 161 162 163 164 165 166 |
# File 'lib/objects/ssh/driver.rb', line 159 def net_ssh_params(verbose = false) raise Bcome::Exception::InvalidSshConfig, "Missing ssh keys for #{@context_node.namespace}" unless ssh_keys params = { keys: ssh_keys, paranoid: false } params[:proxy] = proxy if has_proxy? params[:timeout] = timeout_in_seconds params[:verbose] = :debug if verbose params end |
#node_host_or_ip ⇒ Object
155 156 157 |
# File 'lib/objects/ssh/driver.rb', line 155 def node_host_or_ip has_proxy? ? @context_node.internal_ip_address : @context_node.public_ip_address end |
#node_level_ssh_key ⇒ Object
96 97 98 |
# File 'lib/objects/ssh/driver.rb', line 96 def node_level_ssh_key return (@config[:ssh_keys]) ? @config[:ssh_keys].first : nil end |
#node_level_ssh_key_connection_string ⇒ Object
88 89 90 |
# File 'lib/objects/ssh/driver.rb', line 88 def node_level_ssh_key_connection_string key_specified_at_node_level? ? "-i #{node_level_ssh_key}\s" : "" end |
#overriden_local_user ⇒ Object
143 144 145 |
# File 'lib/objects/ssh/driver.rb', line 143 def overriden_local_user @overriden_local_user ||= get_overriden_local_user end |
#ping ⇒ Object
209 210 211 212 213 214 |
# File 'lib/objects/ssh/driver.rb', line 209 def ping ssh_connect! return { success: true } rescue Exception => e return { success: false, error: e } end |
#pretty_config_details ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/objects/ssh/driver.rb', line 24 def pretty_config_details config = { user: user, ssh_keys: ssh_keys, timeout: timeout_in_seconds } if has_proxy? config[:host_or_ip] = @context_node.internal_ip_address config[:proxy] = { bastion_host: @proxy_data.host, bastion_host_user: bastion_host_user } else config[:host_or_ip] = @context_node.public_ip_address end config end |
#proxy ⇒ Object
46 47 48 49 50 |
# File 'lib/objects/ssh/driver.rb', line 46 def proxy return nil unless has_proxy? connection_string = bootstrap? ? bootstrap_proxy_connection_string : proxy_connection_string ::Net::SSH::Proxy::Command.new(connection_string) end |
#proxy_config_value ⇒ Object
57 58 59 |
# File 'lib/objects/ssh/driver.rb', line 57 def proxy_config_value @config[:proxy] end |
#proxy_connection_string ⇒ Object
61 62 63 |
# File 'lib/objects/ssh/driver.rb', line 61 def proxy_connection_string "ssh #{PROXY_CONNECT_PREFIX} #{bastion_host_user}@#{@proxy_data.host}" end |
#put(local_path, remote_path) ⇒ Object
220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/objects/ssh/driver.rb', line 220 def put(local_path, remote_path) raise Bcome::Exception::MissingParamsForScp, "'put' requires a local_path and a remote_path" if local_path.to_s.empty? || remote_path.to_s.empty? puts "\n(#{@context_node.namespace})\s".namespace + "Uploading #{local_path} to #{remote_path}\n".informational begin scp.upload!(local_path, remote_path, recursive: true) do |_ch, name, sent, total| puts "#{name}: #{sent}/#{total}".progress end rescue Exception => e # scp just throws generic exceptions :-/ puts e..error end nil end |
#rsync(local_path, remote_path) ⇒ Object
176 177 178 179 180 |
# File 'lib/objects/ssh/driver.rb', line 176 def rsync(local_path, remote_path) raise Bcome::Exception::MissingParamsForRsync, "'rsync' requires a local_path and a remote_path" if local_path.to_s.empty? || remote_path.to_s.empty? command = rsync_command(local_path, remote_path) @context_node.execute_local(command) end |
#rsync_command(local_path, remote_path) ⇒ Object
182 183 184 185 186 187 188 189 |
# File 'lib/objects/ssh/driver.rb', line 182 def rsync_command(local_path, remote_path) return bootstrap_rsync_command(local_path, remote_path) if bootstrap? && @bootstrap_settings.ssh_key_path if has_proxy? "rsync -av -e \"ssh -A #{bastion_host_user}@#{@proxy_data.host} ssh -o StrictHostKeyChecking=no\" #{local_path} #{user}@#{@context_node.internal_ip_address}:#{remote_path}" else "rsync -av #{local_path} #{user}@#{@context_node.public_ip_address}:#{remote_path}" end end |
#scp ⇒ Object
216 217 218 |
# File 'lib/objects/ssh/driver.rb', line 216 def scp ssh_connection.scp end |
#ssh_command(as_pseudo_tty = false) ⇒ Object
78 79 80 81 82 83 84 85 86 |
# File 'lib/objects/ssh/driver.rb', line 78 def ssh_command(as_pseudo_tty = false) return bootstrap_ssh_command if bootstrap? && @bootstrap_settings.ssh_key_path if has_proxy? "#{as_pseudo_tty ? "ssh -t" : "ssh"} #{PROXY_SSH_PREFIX} #{bastion_host_user}@#{@proxy_data.host}\" #{node_level_ssh_key_connection_string}#{user}@#{@context_node.internal_ip_address}" else "#{as_pseudo_tty ? "ssh -t" : "ssh"} #{node_level_ssh_key_connection_string}#{user}@#{@context_node.public_ip_address}" end end |
#ssh_connect!(_verbose = false) ⇒ Object
199 200 201 202 203 204 205 206 207 |
# File 'lib/objects/ssh/driver.rb', line 199 def ssh_connect!(_verbose = false) @connection = nil begin @connection = ::Net::SSH.start(node_host_or_ip, user, net_ssh_params) rescue Net::SSH::Proxy::ConnectError, Net::SSH::ConnectionTimeout, Errno::EPIPE => e raise Bcome::Exception::CouldNotInitiateSshConnection, @context_node.namespace + "\s-\s#{e.}" end @connection end |
#ssh_connection(_bootstrap = false) ⇒ Object
253 254 255 |
# File 'lib/objects/ssh/driver.rb', line 253 def ssh_connection(_bootstrap = false) has_open_ssh_con? ? @connection : ssh_connect! end |
#ssh_keys ⇒ Object
168 169 170 171 172 173 174 |
# File 'lib/objects/ssh/driver.rb', line 168 def ssh_keys if bootstrap? [@bootstrap_settings.ssh_key_path] else @config[:ssh_keys] end end |
#timeout_in_seconds ⇒ Object
42 43 44 |
# File 'lib/objects/ssh/driver.rb', line 42 def timeout_in_seconds @config[:timeout_in_seconds] ||= Bcome::Ssh::Driver::DEFAULT_TIMEOUT_IN_SECONDS end |
#user ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/objects/ssh/driver.rb', line 129 def user # If we're in bootstrapping mode and have a bootstrap user set, return it return @bootstrap_settings.user if (bootstrap? && @bootstrap_settings.user) # If we have a user explcitly set in the config, then return it return @config[:user] if @config[:user] # If the local user has explicitly overriden their user, return that return overriden_local_user if overriden_local_user # Else fall back to whichever local user is using bcome fallback_local_user end |