Class: ChefApply::TargetHost
- Inherits:
-
Object
- Object
- ChefApply::TargetHost
- Defined in:
- lib/chef_apply/target_host.rb
Defined Under Namespace
Classes: ChefNotInstalled, ConnectionFailure, RemoteExecutionFailed, UnsupportedTargetOS
Constant Summary collapse
- SSH_CONFIG_OVERRIDE_KEYS =
These values may exist in .ssh/config but will be ignored by train in favor of its defaults unless we specify them explicitly. See #apply_ssh_config
[:user, :port, :proxy]
- MANIFEST_PATHS =
{ # TODO - use a proper method to query the win installation path - # currently we're assuming the default, but this can be customized # at install time. # A working approach is below - but it runs very slowly in testing # on a virtualbox windows vm: # (over winrm) Get-WmiObject Win32_Product | Where {$_.Name -match 'Chef Client'} windows: "c:\\opscode\\chef\\version-manifest.json", linux: "/opt/chef/version-manifest.json" }
Instance Attribute Summary collapse
-
#backend ⇒ Object
readonly
Returns the value of attribute backend.
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#reporter ⇒ Object
readonly
Returns the value of attribute reporter.
-
#transport_type ⇒ Object
readonly
Returns the value of attribute transport_type.
Class Method Summary collapse
Instance Method Summary collapse
- #apply_ssh_config(config, opts_in) ⇒ Object
- #architecture ⇒ Object
- #base_os ⇒ Object
- #connect! ⇒ Object
- #connection_config(host_url, opts_in, logger) ⇒ Object
- #get_chef_version_manifest ⇒ Object
- #hostname ⇒ Object
-
#initialize(host_url, opts = {}, logger = nil) ⇒ TargetHost
constructor
A new instance of TargetHost.
-
#installed_chef_version ⇒ Object
Returns the installed chef version as a Gem::Version, or raised ChefNotInstalled if chef client version manifest can’t be found.
- #platform ⇒ Object
- #run_command(command, sudo_as_user = false) ⇒ Object
- #run_command!(command, sudo_as_user = false) ⇒ Object
- #upload_file(local_path, remote_path) ⇒ Object
-
#user ⇒ Object
Returns the user being used to connect.
- #version ⇒ Object
Constructor Details
#initialize(host_url, opts = {}, logger = nil) ⇒ TargetHost
Returns a new instance of TargetHost.
36 37 38 39 40 41 |
# File 'lib/chef_apply/target_host.rb', line 36 def initialize(host_url, opts = {}, logger = nil) @config = connection_config(host_url, opts, logger) @transport_type = Train.validate_backend(@config) apply_ssh_config(@config, opts) if @transport_type == "ssh" @train_connection = Train.create(@transport_type, config) end |
Instance Attribute Details
#backend ⇒ Object (readonly)
Returns the value of attribute backend.
23 24 25 |
# File 'lib/chef_apply/target_host.rb', line 23 def backend @backend end |
#config ⇒ Object (readonly)
Returns the value of attribute config.
23 24 25 |
# File 'lib/chef_apply/target_host.rb', line 23 def config @config end |
#reporter ⇒ Object (readonly)
Returns the value of attribute reporter.
23 24 25 |
# File 'lib/chef_apply/target_host.rb', line 23 def reporter @reporter end |
#transport_type ⇒ Object (readonly)
Returns the value of attribute transport_type.
23 24 25 |
# File 'lib/chef_apply/target_host.rb', line 23 def transport_type @transport_type end |
Class Method Details
.instance_for_url(target, opts = {}) ⇒ Object
29 30 31 32 33 34 |
# File 'lib/chef_apply/target_host.rb', line 29 def self.instance_for_url(target, opts = {}) opts = { target: @url } target_host = new(target, opts) target_host.connect! target_host end |
Instance Method Details
#apply_ssh_config(config, opts_in) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/chef_apply/target_host.rb', line 67 def apply_ssh_config(config, opts_in) # If we don't provide certain options, they will be defaulted # within train - in the case of ssh, this will prevent the .ssh/config # values from being picked up. # Here we'll modify the returned @config to specify # values that we get out of .ssh/config if present and if they haven't # been explicitly given. host_cfg = ssh_config_for_host(config[:host]) SSH_CONFIG_OVERRIDE_KEYS.each do |key| if host_cfg.has_key?(key) && opts_in[key].nil? config[key] = host_cfg[key] end end end |
#architecture ⇒ Object
106 107 108 |
# File 'lib/chef_apply/target_host.rb', line 106 def architecture platform.arch end |
#base_os ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/chef_apply/target_host.rb', line 114 def base_os if platform.family == "windows" :windows elsif platform.linux? :linux else # TODO - this seems like it shouldn't happen here, when # all the caller is doing is asking about the OS raise ChefApply::TargetHost::UnsupportedTargetOS.new(platform.name) end end |
#connect! ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/chef_apply/target_host.rb', line 82 def connect! return unless @backend.nil? @backend = train_connection.connection @backend.wait_until_ready rescue Train::UserError => e raise ConnectionFailure.new(e, config) rescue Train::Error => e # These are typically wrapper errors for other problems, # so we'll prefer to use e.cause over e if available. raise ConnectionFailure.new(e.cause || e, config) end |
#connection_config(host_url, opts_in, logger) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/chef_apply/target_host.rb', line 43 def connection_config(host_url, opts_in, logger) connection_opts = { target: host_url, sudo: opts_in[:sudo] === false ? false : true, www_form_encoded_password: true, key_files: opts_in[:identity_file], non_interactive: true, # Prevent long delays due to retries on auth failure. # This does reduce the number of attempts we'll make for transient conditions as well, but # train does not currently exposes these as separate controls. Ideally I'd like to see a 'retry_on_auth_failure' option. connection_retries: 2, connection_retry_sleep: 0.15, logger: ChefApply::Log } if opts_in.has_key? :ssl connection_opts[:ssl] = opts_in[:ssl] connection_opts[:self_signed] = (opts_in[:ssl_verify] === false ? true : false) end [:sudo_password, :sudo, :sudo_command, :password, :user].each do |key| connection_opts[key] = opts_in[key] if opts_in.has_key? key end Train.target_config(connection_opts) end |
#get_chef_version_manifest ⇒ Object
175 176 177 178 179 180 |
# File 'lib/chef_apply/target_host.rb', line 175 def get_chef_version_manifest path = MANIFEST_PATHS[base_os()] manifest = backend.file(path) return :not_found unless manifest.file? JSON.parse(manifest.content) end |
#hostname ⇒ Object
102 103 104 |
# File 'lib/chef_apply/target_host.rb', line 102 def hostname config[:host] end |
#installed_chef_version ⇒ Object
Returns the installed chef version as a Gem::Version, or raised ChefNotInstalled if chef client version manifest can’t be found.
152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/chef_apply/target_host.rb', line 152 def installed_chef_version return @installed_chef_version if @installed_chef_version # Note: In the case of a very old version of chef (that has no manifest - pre 12.0?) # this will report as not installed. manifest = get_chef_version_manifest() raise ChefNotInstalled.new if manifest == :not_found # We'll split the version here because unstable builds (where we currently # install from) are in the form "Major.Minor.Build+HASH" which is not a valid # version string. @installed_chef_version = Gem::Version.new(manifest["build_version"].split("+")[0]) end |
#platform ⇒ Object
126 127 128 |
# File 'lib/chef_apply/target_host.rb', line 126 def platform backend.platform end |
#run_command(command, sudo_as_user = false) ⇒ Object
138 139 140 141 142 143 |
# File 'lib/chef_apply/target_host.rb', line 138 def run_command(command, sudo_as_user = false) if config[:sudo] && sudo_as_user && base_os == :linux command = "-u #{config[:user]} #{command}" end backend.run_command command end |
#run_command!(command, sudo_as_user = false) ⇒ Object
130 131 132 133 134 135 136 |
# File 'lib/chef_apply/target_host.rb', line 130 def run_command!(command, sudo_as_user = false) result = run_command(command, sudo_as_user) if result.exit_status != 0 raise RemoteExecutionFailed.new(@config[:host], command, result) end result end |
#upload_file(local_path, remote_path) ⇒ Object
145 146 147 |
# File 'lib/chef_apply/target_host.rb', line 145 def upload_file(local_path, remote_path) backend.upload(local_path, remote_path) end |
#user ⇒ Object
Returns the user being used to connect. Defaults to train’s default user if not specified defaulted in .ssh/config (for ssh connections), as set up in ‘#apply_ssh_config’.
96 97 98 99 100 |
# File 'lib/chef_apply/target_host.rb', line 96 def user return config[:user] unless config[:user].nil? require "train/transports/ssh" Train::Transports::SSH.[:user][:default] end |
#version ⇒ Object
110 111 112 |
# File 'lib/chef_apply/target_host.rb', line 110 def version platform.release end |