Class: OpsWalrus::Host
- Inherits:
-
Object
show all
- Includes:
- HostDSL
- Defined in:
- lib/opswalrus/host.rb
Instance Method Summary
collapse
-
#_cleanup_session ⇒ Object
-
#_initialize_session ⇒ Object
returns the temporary bundle root directory.
-
#alias ⇒ Object
-
#clear_ssh_session ⇒ Object
-
#dereference_secret_if_needed(secret_ref) ⇒ Object
secret_ref: SecretRef returns the decrypted value referenced by the supplied SecretRef.
-
#download(remote_path, local_path) ⇒ Object
-
#eql?(other) ⇒ Boolean
-
#execute(*args, input_mapping: nil, ops_prompt_for_sudo_password: false) ⇒ Object
-
#execute_cmd(*args, input_mapping: nil, ops_prompt_for_sudo_password: false) ⇒ Object
Returns a SSHKit::Command.
-
#hash ⇒ Object
-
#host ⇒ Object
-
#ignore? ⇒ Boolean
-
#initialize(ssh_uri, tags = [], props = {}, default_props = {}, hosts_file = nil) ⇒ Host
constructor
ssh_uri is a string of the form: - hostname - user@hostname - hostname:port - user@hostname:port.
-
#parse_ssh_uri! ⇒ Object
-
#set_ops_file_script(ops_file_script) ⇒ Object
-
#set_runtime_env(runtime_env) ⇒ Object
-
#set_ssh_session_connection(sshkit_backend) ⇒ Object
-
#set_ssh_session_tmp_bundle_root_dir(tmp_bundle_root_dir) ⇒ Object
-
#ssh_key ⇒ Object
-
#ssh_password ⇒ Object
-
#ssh_port ⇒ Object
-
#ssh_uri ⇒ Object
-
#ssh_user ⇒ Object
-
#sshkit_host ⇒ Object
-
#summary(verbose = false) ⇒ Object
-
#tag!(*tags) ⇒ Object
-
#tags ⇒ Object
-
#to_h ⇒ Object
-
#to_s ⇒ Object
-
#upload(local_path_or_io, remote_path) ⇒ Object
-
#write_temp_ssh_keys_if_needed(keys) ⇒ Object
keys is an Array ( String | SecretRef ) such that if a key is a String, then it is interpreted as a path to a key file and if the key is a SecretRef, then the secret’s plaintext value is interpreted as an ssh key string, and must thereforce be written to a tempfile so that net-ssh can use it via file reference (since net-ssh only allows the keys field to be an array of file paths).
Methods included from HostDSL
#autoretry, #debug, #desc, #env, #host_prop, #params, #parse_stdout_and_script_return_value, #reboot, #reconnect, #run_ops, #sh, #sh?, #shell, #shell!, #ssh_session, #warn
Constructor Details
#initialize(ssh_uri, tags = [], props = {}, default_props = {}, hosts_file = nil) ⇒ Host
ssh_uri is a string of the form:
-
hostname
-
user@hostname
-
hostname:port
-
user@hostname:port
412
413
414
415
416
417
418
419
420
421
|
# File 'lib/opswalrus/host.rb', line 412
def initialize(ssh_uri, tags = [], props = {}, default_props = {}, hosts_file = nil)
@ssh_uri = ssh_uri
@host = nil
@tags = tags.to_set
@props = props.is_a?(Array) ? {"tags" => props} : props.to_h
@default_props = default_props
@hosts_file = hosts_file
@tmp_ssh_key_files = []
parse_ssh_uri!
end
|
Instance Method Details
#_cleanup_session ⇒ Object
580
581
582
583
584
585
586
587
|
# File 'lib/opswalrus/host.rb', line 580
def _cleanup_session
if @tmp_bundle_root_dir =~ /tmp/ execute(:rm, "-rf", "tmpops.zip", @tmp_bundle_root_dir)
else
execute(:rm, "-rf", "tmpops.zip")
end
end
|
#_initialize_session ⇒ Object
returns the temporary bundle root directory
568
569
570
571
572
573
574
575
576
577
578
|
# File 'lib/opswalrus/host.rb', line 568
def _initialize_session
zip_bundle_path = @runtime_env.zip_bundle_path
upload_success = upload(zip_bundle_path, "tmpops.zip")
raise Error, "Unable to upload ops bundle to remote host" unless upload_success
stdout, _stderr, exit_status = run_ops(:bundle, "unzip tmpops.zip", in_bundle_root_dir: false)
raise Error, "Unable to unzip ops bundle on remote host: #{stdout}" unless exit_status == 0
tmp_bundle_root_dir = stdout.strip
set_ssh_session_tmp_bundle_root_dir(tmp_bundle_root_dir)
end
|
#alias ⇒ Object
450
451
452
|
# File 'lib/opswalrus/host.rb', line 450
def alias
@props["alias"] || @default_props["alias"]
end
|
#clear_ssh_session ⇒ Object
589
590
591
592
593
594
595
596
|
# File 'lib/opswalrus/host.rb', line 589
def clear_ssh_session
@runtime_env = nil
@ops_file_script = nil
@sshkit_backend = nil
@tmp_bundle_root_dir = nil
@tmp_ssh_key_files.each {|tmpfile| tmpfile.close() rescue nil; File.unlink(tmpfile) rescue nil }
@tmp_ssh_key_files = []
end
|
#dereference_secret_if_needed(secret_ref) ⇒ Object
secret_ref: SecretRef returns the decrypted value referenced by the supplied SecretRef
433
434
435
436
437
438
439
440
|
# File 'lib/opswalrus/host.rb', line 433
def dereference_secret_if_needed(secret_ref)
if secret_ref.is_a? SecretRef
raise "Host #{self} not read from hosts file so no secrets can be dereferenced." unless @hosts_file
@hosts_file.read_secret(secret_ref.to_s)
else
secret_ref
end
end
|
#download(remote_path, local_path) ⇒ Object
630
631
632
|
# File 'lib/opswalrus/host.rb', line 630
def download(remote_path, local_path)
@sshkit_backend.download!(remote_path.to_s, local_path.to_s)
end
|
#eql?(other) ⇒ Boolean
482
483
484
|
# File 'lib/opswalrus/host.rb', line 482
def eql?(other)
self.class == other.class && self.hash == other.hash
end
|
#execute(*args, input_mapping: nil, ops_prompt_for_sudo_password: false) ⇒ Object
598
599
600
601
602
603
604
605
606
607
|
# File 'lib/opswalrus/host.rb', line 598
def execute(*args, input_mapping: nil, ops_prompt_for_sudo_password: false)
sudo_password_args = {}
sudo_password_args[:sudo_password] = ssh_password unless ops_prompt_for_sudo_password
sudo_password_args[:ops_sudo_password] = ssh_password if ops_prompt_for_sudo_password
@runtime_env.handle_input(input_mapping, **sudo_password_args, inherit_existing_mappings: false) do |interaction_handler|
App.instance.debug("Host#execute_cmd(#{args.inspect}) with input mappings #{interaction_handler.input_mappings.inspect} given sudo_password_args: #{sudo_password_args.inspect})")
@sshkit_backend.capture(*args, interaction_handler: interaction_handler)
end
end
|
#execute_cmd(*args, input_mapping: nil, ops_prompt_for_sudo_password: false) ⇒ Object
Returns a SSHKit::Command
610
611
612
613
614
615
616
617
618
619
620
621
622
623
|
# File 'lib/opswalrus/host.rb', line 610
def execute_cmd(*args, input_mapping: nil, ops_prompt_for_sudo_password: false)
sudo_password_args = {}
sudo_password_args[:sudo_password] = ssh_password unless ops_prompt_for_sudo_password
sudo_password_args[:ops_sudo_password] = ssh_password if ops_prompt_for_sudo_password
@runtime_env.handle_input(input_mapping, **sudo_password_args, inherit_existing_mappings: false) do |interaction_handler|
App.instance.debug("Host#execute_cmd(#{args.inspect}) with input mappings #{interaction_handler.input_mappings.inspect} given sudo_password_args: #{sudo_password_args.inspect})")
@sshkit_backend.execute_cmd(*args, interaction_handler: interaction_handler)
end
end
|
#hash ⇒ Object
478
479
480
|
# File 'lib/opswalrus/host.rb', line 478
def hash
@ssh_uri.hash
end
|
#host ⇒ Object
446
447
448
|
# File 'lib/opswalrus/host.rb', line 446
def host
@host
end
|
#ignore? ⇒ Boolean
454
455
456
|
# File 'lib/opswalrus/host.rb', line 454
def ignore?
@props["ignore"] || @default_props["ignore"]
end
|
#parse_ssh_uri! ⇒ Object
423
424
425
426
427
428
429
|
# File 'lib/opswalrus/host.rb', line 423
def parse_ssh_uri!
if match = /^\s*((?<user>.*?)@)?(?<host>.*?)(:(?<port>[0-9]+))?\s*$/.match(@ssh_uri)
@host ||= match[:host] if match[:host]
@props["user"] ||= match[:user] if match[:user]
@props["port"] ||= match[:port].to_i if match[:port]
end
end
|
#set_ops_file_script(ops_file_script) ⇒ Object
555
556
557
|
# File 'lib/opswalrus/host.rb', line 555
def set_ops_file_script(ops_file_script)
@ops_file_script = ops_file_script
end
|
#set_runtime_env(runtime_env) ⇒ Object
551
552
553
|
# File 'lib/opswalrus/host.rb', line 551
def set_runtime_env(runtime_env)
@runtime_env = runtime_env
end
|
#set_ssh_session_connection(sshkit_backend) ⇒ Object
559
560
561
|
# File 'lib/opswalrus/host.rb', line 559
def set_ssh_session_connection(sshkit_backend)
@sshkit_backend = sshkit_backend
end
|
#set_ssh_session_tmp_bundle_root_dir(tmp_bundle_root_dir) ⇒ Object
563
564
565
|
# File 'lib/opswalrus/host.rb', line 563
def set_ssh_session_tmp_bundle_root_dir(tmp_bundle_root_dir)
@tmp_bundle_root_dir = tmp_bundle_root_dir
end
|
#ssh_key ⇒ Object
474
475
476
|
# File 'lib/opswalrus/host.rb', line 474
def ssh_key
@props["ssh-key"] || @default_props["ssh-key"]
end
|
#ssh_password ⇒ Object
466
467
468
469
470
471
472
|
# File 'lib/opswalrus/host.rb', line 466
def ssh_password
password = @props["password"] || @default_props["password"]
password ||= begin
@props["password"] = IO::console.getpass("[opswalrus] Please enter ssh password to connect to #{ssh_user}@#{host}:#{ssh_port}: ")
end
dereference_secret_if_needed(password)
end
|
#ssh_port ⇒ Object
458
459
460
|
# File 'lib/opswalrus/host.rb', line 458
def ssh_port
@props["port"] || @default_props["port"] || 22
end
|
#ssh_uri ⇒ Object
442
443
444
|
# File 'lib/opswalrus/host.rb', line 442
def ssh_uri
@ssh_uri
end
|
#ssh_user ⇒ Object
462
463
464
|
# File 'lib/opswalrus/host.rb', line 462
def ssh_user
@props["user"] || @default_props["user"]
end
|
#sshkit_host ⇒ Object
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
|
# File 'lib/opswalrus/host.rb', line 509
def sshkit_host
keys = case ssh_key
when Array
ssh_key
else
[ssh_key]
end
keys = write_temp_ssh_keys_if_needed(keys)
@sshkit_host ||= ::SSHKit::Host.new({
hostname: host,
port: ssh_port,
user: ssh_user || raise("No ssh user specified to connect to #{host}"),
password: ssh_password,
keys: keys
})
end
|
#summary(verbose = false) ⇒ Object
501
502
503
504
505
506
507
|
# File 'lib/opswalrus/host.rb', line 501
def summary(verbose = false)
report = "#{to_s}\n tags: #{tags.sort.join(', ')}"
if verbose
@default_props.merge(@props).reject{|k,v| k == 'tags' }.each {|k,v| report << "\n #{k}: #{v}" }
end
report
end
|
#tag!(*tags) ⇒ Object
490
491
492
493
494
495
|
# File 'lib/opswalrus/host.rb', line 490
def tag!(*tags)
enumerables, scalars = tags.partition {|t| Enumerable === t }
@tags.merge(scalars)
enumerables.each {|enum| @tags.merge(enum) }
@tags
end
|
497
498
499
|
# File 'lib/opswalrus/host.rb', line 497
def tags
@tags
end
|
#to_h ⇒ Object
634
635
636
637
638
639
640
641
642
643
644
|
# File 'lib/opswalrus/host.rb', line 634
def to_h
hash = {}
hash["alias"] = @props["alias"] if @props["alias"]
hash["ignore"] = @props["ignore"] if @props["ignore"]
hash["user"] = @props["user"] if @props["user"]
hash["port"] = @props["port"] if @props["port"]
hash["password"] = @props["password"] if @props["password"]
hash["ssh-key"] = @props["ssh-key"] if @props["ssh-key"]
hash["tags"] = tags.to_a unless tags.empty?
hash
end
|
#to_s ⇒ Object
486
487
488
|
# File 'lib/opswalrus/host.rb', line 486
def to_s
@ssh_uri
end
|
#upload(local_path_or_io, remote_path) ⇒ Object
625
626
627
628
|
# File 'lib/opswalrus/host.rb', line 625
def upload(local_path_or_io, remote_path)
source = local_path_or_io.is_a?(IO) ? local_path_or_io : local_path_or_io.to_s
@sshkit_backend.upload!(source, remote_path.to_s)
end
|
#write_temp_ssh_keys_if_needed(keys) ⇒ Object
keys is an Array ( String | SecretRef ) such that if a key is a String, then it is interpreted as a path to a key file and if the key is a SecretRef, then the secret’s plaintext value is interpreted as an ssh key string, and must thereforce be written to a tempfile so that net-ssh can use it via file reference (since net-ssh only allows the keys field to be an array of file paths).
returns an array of file paths to key files
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
|
# File 'lib/opswalrus/host.rb', line 535
def write_temp_ssh_keys_if_needed(keys)
keys.map do |key_file_path_or_in_memory_key_text|
if key_file_path_or_in_memory_key_text.is_a? SecretRef tempfile = Tempfile.create
@tmp_ssh_key_files << tempfile
raise "Host #{self} not read from hosts file so no secrets can be written." unless @hosts_file
key_file_contents = @hosts_file.read_secret(key_file_path_or_in_memory_key_text.to_s)
tempfile.write(key_file_contents)
tempfile.close tempfile.path
else key_file_path_or_in_memory_key_text
end
end
end
|