Module: RHC::SSHHelpers
- Included in:
- Commands::App, Commands::Snapshot, Commands::Ssh, Commands::Sshkey, Commands::Tail, DeploymentHelpers, SCPHelpers, Wizard
- Defined in:
- lib/rhc/ssh_helpers.rb
Defined Under Namespace
Classes: MultipleGearTask
Instance Method Summary collapse
-
#check_ssh_executable!(path) ⇒ Object
return supplied ssh executable, if valid (executable, searches $PATH).
- #exe?(executable) ⇒ Boolean
- #fingerprint_for_default_key ⇒ Object
- #fingerprint_for_local_key(key) ⇒ Object
-
#generate_ssh_key_ruby(type = "RSA", bits = 2048, comment = "OpenShift-Key") ⇒ Object
Public: Generate an SSH key and store it in ~/.ssh/id_rsa.
-
#has_ssh? ⇒ Boolean
return whether or not SSH is installed.
- #restore_snapshot(app, filename, ssh_executable = nil) ⇒ Object
- #run_on_gears(command, gears, opts = {}, &block) ⇒ Object
- #save_snapshot(app, filename, for_deployment = false, ssh_executable = nil) ⇒ Object
- #ssh_command_for_op(operation) ⇒ Object
-
#ssh_key_triple_for(key) ⇒ Object
for an SSH public key specified by ‘key’, return a triple [type, content, comment] which is basically the space-separated list of the SSH public key content.
- #ssh_key_triple_for_default_key ⇒ Object
-
#ssh_keygen_fallback(path) ⇒ Object
For Net::SSH versions (< 2.0.11) that does not have Net::SSH::KeyFactory.load_public_key, we drop to shell to get the key’s fingerprint.
-
#ssh_ruby(host, username, command, compression = false, request_pty = false, &block) ⇒ Object
Public: Run ssh command on remote host.
-
#ssh_send_file_ruby(host, username, command, filename) ⇒ Object
Public: Run ssh command on remote host and pipe the specified file contents to the command input.
-
#ssh_send_url_ruby(host, username, command, content_url) ⇒ Object
Public: Run ssh command on remote host and pipe the specified url contents to the command input.
-
#ssh_version ⇒ Object
check the version of SSH that is installed.
- #table_from_gears(command, groups, opts = {}, &block) ⇒ Object
Instance Method Details
#check_ssh_executable!(path) ⇒ Object
return supplied ssh executable, if valid (executable, searches $PATH). if none was supplied, return installed ssh, if any.
446 447 448 449 450 451 452 453 454 455 456 |
# File 'lib/rhc/ssh_helpers.rb', line 446 def check_ssh_executable!(path) if not path raise RHC::InvalidSSHExecutableException.new("No system SSH available. Please use the --ssh option to specify the path to your SSH executable, or install SSH.") unless has_ssh? 'ssh' else bin_path = path.split(' ').first raise RHC::InvalidSSHExecutableException.new("SSH executable '#{bin_path}' does not exist.") unless File.exist?(bin_path) or exe?(bin_path) raise RHC::InvalidSSHExecutableException.new("SSH executable '#{bin_path}' is not executable.") unless File.executable?(bin_path) or exe?(bin_path) path end end |
#exe?(executable) ⇒ Boolean
376 377 378 379 380 |
# File 'lib/rhc/ssh_helpers.rb', line 376 def exe?(executable) ENV['PATH'].split(File::PATH_SEPARATOR).any? do |directory| File.executable?(File.join(directory, executable.to_s)) end end |
#fingerprint_for_default_key ⇒ Object
407 408 409 |
# File 'lib/rhc/ssh_helpers.rb', line 407 def fingerprint_for_default_key fingerprint_for_local_key(RHC::Config.ssh_pub_key_file_path) end |
#fingerprint_for_local_key(key) ⇒ Object
394 395 396 397 398 399 400 401 402 403 404 405 |
# File 'lib/rhc/ssh_helpers.rb', line 394 def fingerprint_for_local_key(key) Net::SSH::KeyFactory.load_public_key(key).fingerprint rescue NoMethodError, NotImplementedError => e ssh_keygen_fallback key nil rescue OpenSSL::PKey::PKeyError, Net::SSH::Exception => e error e. nil rescue => e debug e. nil end |
#generate_ssh_key_ruby(type = "RSA", bits = 2048, comment = "OpenShift-Key") ⇒ Object
Public: Generate an SSH key and store it in ~/.ssh/id_rsa
type - The String type RSA or DSS. bits - The Integer value for number of bits. comment - The String comment for the key
Examples
generate_ssh_key_ruby
# => /home/user/.ssh/id_rsa.pub
Returns nil on failure or public key location as a String on success
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 |
# File 'lib/rhc/ssh_helpers.rb', line 351 def generate_ssh_key_ruby(type="RSA", bits = 2048, comment = "OpenShift-Key") key = RHC::Vendor::SSHKey.generate(:type => type, :bits => bits, :comment => comment) ssh_dir = RHC::Config.ssh_dir priv_key = RHC::Config.ssh_priv_key_file_path pub_key = RHC::Config.ssh_pub_key_file_path if File.exists?(priv_key) say "SSH key already exists: #{priv_key}. Reusing..." return nil else unless File.exists?(ssh_dir) FileUtils.mkdir_p(ssh_dir) File.chmod(0700, ssh_dir) end File.open(priv_key, 'w') {|f| f.write(key.private_key)} File.chmod(0600, priv_key) File.open(pub_key, 'w') {|f| f.write(key.ssh_public_key)} ssh_add end pub_key end |
#has_ssh? ⇒ Boolean
return whether or not SSH is installed
434 435 436 437 438 439 440 441 442 |
# File 'lib/rhc/ssh_helpers.rb', line 434 def has_ssh? @has_ssh ||= begin @ssh_version = nil ssh_version $?.success? rescue false end end |
#restore_snapshot(app, filename, ssh_executable = nil) ⇒ Object
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
# File 'lib/rhc/ssh_helpers.rb', line 290 def restore_snapshot(app, filename, ssh_executable=nil) include_git = RHC::Helpers.windows? ? true : RHC::TarGz.contains(filename, './*/git') ssh_uri = URI.parse(app.ssh_url) ssh_executable = check_ssh_executable! .ssh ssh_cmd = "cat '#{filename}' | #{ssh_executable} #{ssh_uri.user}@#{ssh_uri.host} 'restore#{include_git ? ' INCLUDE_GIT' : ''}'" ssh_stderr = " 2>/dev/null" debug ssh_cmd say "Restoring from snapshot #{filename} to application '#{app.name}' ... " begin if !RHC::Helpers.windows? status, output = exec(ssh_cmd + (debug? ? '' : ssh_stderr)) if status != 0 debug output raise RHC::SnapshotRestoreException.new "Error in trying to restore snapshot. You can try to restore manually by running:\n#{ssh_cmd}" end else ssh = Net::SSH.start(ssh_uri.host, ssh_uri.user) ssh.open_channel do |channel| channel.exec("restore#{include_git ? ' INCLUDE_GIT' : ''}") do |ch, success| channel.on_data do |ch, data| debug data end channel.on_extended_data do |ch, type, data| debug data end channel.on_close do |ch| debug "Terminating..." end File.open(filename, 'rb') do |file| file.chunk(4096) do |chunk| channel.send_data chunk end end channel.eof! end end ssh.loop end rescue Timeout::Error, Errno::EADDRNOTAVAIL, Errno::EADDRINUSE, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Net::SSH::AuthenticationFailed => e debug e.backtrace raise RHC::SnapshotRestoreException.new "Error in trying to restore snapshot. You can try to restore manually by running:\n#{ssh_cmd}" end success 'done' end |
#run_on_gears(command, gears, opts = {}, &block) ⇒ Object
135 136 137 138 |
# File 'lib/rhc/ssh_helpers.rb', line 135 def run_on_gears(command, gears, opts={}, &block) debug "Executing #{command} on each of #{gears.inspect}" MultipleGearTask.new(command, gears, {:limit => .limit, :always_prefix => .always_prefix, :raw => .raw}.merge(opts)).run(&block) end |
#save_snapshot(app, filename, for_deployment = false, ssh_executable = nil) ⇒ Object
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/rhc/ssh_helpers.rb', line 251 def save_snapshot(app, filename, for_deployment=false, ssh_executable=nil) ssh_uri = URI.parse(app.ssh_url) ssh_executable = check_ssh_executable! ssh_executable snapshot_cmd = for_deployment ? 'gear archive-deployment' : 'snapshot' ssh_cmd = "#{ssh_executable} #{ssh_uri.user}@#{ssh_uri.host} '#{snapshot_cmd}' > #{filename}" ssh_stderr = " 2>/dev/null" debug ssh_cmd say "Pulling down a snapshot of application '#{app.name}' to #{filename} ... " begin if !RHC::Helpers.windows? status, output = exec(ssh_cmd + (debug? ? '' : ssh_stderr)) if status != 0 debug output raise RHC::SnapshotSaveException.new "Error in trying to save snapshot. You can try to save manually by running:\n#{ssh_cmd}" end else Net::SSH.start(ssh_uri.host, ssh_uri.user) do |ssh| File.open(filename, 'wb') do |file| ssh.exec! "snapshot" do |channel, stream, data| if stream == :stdout file.write(data) else debug data end end end end end rescue Timeout::Error, Errno::EADDRNOTAVAIL, Errno::EADDRINUSE, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Net::SSH::AuthenticationFailed => e debug e.backtrace raise RHC::SnapshotSaveException.new "Error in trying to save snapshot. You can try to save manually by running:\n#{ssh_cmd}" end success 'done' end |
#ssh_command_for_op(operation) ⇒ Object
146 147 148 149 150 |
# File 'lib/rhc/ssh_helpers.rb', line 146 def ssh_command_for_op(operation) #case operation raise RHC::OperationNotSupportedException, "The operation #{operation} is not supported." #end end |
#ssh_key_triple_for(key) ⇒ Object
for an SSH public key specified by ‘key’, return a triple
- type, content, comment
-
which is basically the space-separated list of the SSH public key content
414 415 416 417 418 419 420 421 422 |
# File 'lib/rhc/ssh_helpers.rb', line 414 def ssh_key_triple_for(key) begin IO.read(key).chomp.split rescue Errno::ENOENT => e raise ::RHC::KeyFileNotExistentException.new("File '#{key}' does not exist.") rescue Errno::EACCES => e raise ::RHC::KeyFileAccessDeniedException.new("Access denied to '#{key}'.") end end |
#ssh_key_triple_for_default_key ⇒ Object
424 425 426 |
# File 'lib/rhc/ssh_helpers.rb', line 424 def ssh_key_triple_for_default_key ssh_key_triple_for(RHC::Config.ssh_pub_key_file_path) end |
#ssh_keygen_fallback(path) ⇒ Object
For Net::SSH versions (< 2.0.11) that does not have Net::SSH::KeyFactory.load_public_key, we drop to shell to get the key’s fingerprint
385 386 387 388 389 390 391 392 |
# File 'lib/rhc/ssh_helpers.rb', line 385 def ssh_keygen_fallback(path) fingerprint = `ssh-keygen -lf #{path} 2>&1`.split(' ')[1] if $?.exitstatus != 0 error "Unable to compute SSH public key finger print for #{path}" end fingerprint end |
#ssh_ruby(host, username, command, compression = false, request_pty = false, &block) ⇒ Object
Public: Run ssh command on remote host
host - The String of the remote hostname to ssh to. username - The String username of the remote user to ssh as. command - The String command to run on the remote host. compression - Use compression in ssh, set to false if sending files. request_pty - Request for pty, set to false when pipe a file. block - Will yield this block and send the channel if provided.
Examples
ssh_ruby('myapp-t.rhcloud.com',
'109745632b514e9590aa802ec015b074',
'rhcsh tail -f $OPENSHIFT_LOG_DIR/*"')
# => true
Returns true on success
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/rhc/ssh_helpers.rb', line 169 def ssh_ruby(host, username, command, compression=false, request_pty=false, &block) debug "Opening Net::SSH connection to #{host}, #{username}, #{command}" exit_status = 0 = {:compression => compression} [:verbose] = :debug if debug? Net::SSH.start(host, username, ) do |session| #:nocov: channel = session.open_channel do |channel| if request_pty channel.request_pty do |ch, success| say "pty could not be obtained" unless success end end channel.exec(command) do |ch, success| channel.on_data do |ch, data| print data end channel.on_extended_data do |ch, type, data| print data end channel.on_close do |ch| debug "Terminating ... " end channel.on_request("exit-status") do |ch, data| exit_status = data.read_long end yield channel if block_given? channel.eof! end end session.loop #:nocov: end raise RHC::SSHCommandFailed.new(exit_status) if exit_status != 0 rescue Errno::ECONNREFUSED => e debug_error e raise RHC::SSHConnectionRefused.new(host, username) rescue Net::SSH::AuthenticationFailed => e debug_error e raise RHC::SSHAuthenticationFailed.new(host, username) rescue SocketError => e debug_error e raise RHC::ConnectionFailed, "The connection to #{host} failed: #{e.}" end |
#ssh_send_file_ruby(host, username, command, filename) ⇒ Object
Public: Run ssh command on remote host and pipe the specified file contents to the command input
host - The String of the remote hostname to ssh to. username - The String username of the remote user to ssh as. command - The String command to run on the remote host. filename - The String path to file to send.
223 224 225 226 227 228 229 230 231 232 |
# File 'lib/rhc/ssh_helpers.rb', line 223 def ssh_send_file_ruby(host, username, command, filename) filename = File.(filename) ssh_ruby(host, username, command) do |channel| File.open(filename, 'rb') do |file| file.chunk(1024) do |chunk| channel.send_data chunk end end end end |
#ssh_send_url_ruby(host, username, command, content_url) ⇒ Object
Public: Run ssh command on remote host and pipe the specified url contents to the command input
host - The String of the remote hostname to ssh to. username - The String username of the remote user to ssh as. command - The String command to run on the remote host. content_url - The url with the content to pipe to command.
242 243 244 245 246 247 248 249 |
# File 'lib/rhc/ssh_helpers.rb', line 242 def ssh_send_url_ruby(host, username, command, content_url) content_url = URI.parse(URI.encode(content_url.to_s)) ssh_ruby(host, username, command) do |channel| HTTPClient.new.get_content(content_url) do |chunk| channel.send_data chunk end end end |
#ssh_version ⇒ Object
check the version of SSH that is installed
429 430 431 |
# File 'lib/rhc/ssh_helpers.rb', line 429 def ssh_version @ssh_version ||= `ssh -V 2>&1`.strip end |
#table_from_gears(command, groups, opts = {}, &block) ⇒ Object
140 141 142 143 144 |
# File 'lib/rhc/ssh_helpers.rb', line 140 def table_from_gears(command, groups, opts={}, &block) cells = run_on_gears(command, groups, {:as => :table}.merge(opts), &block) cells.each{ |r| r.concat(r.pop.first.split(opts[:split_cells_on])) } if !block_given? && opts[:split_cells_on] say table cells, opts unless .raw end |