From 45e94cc3dbd716c9dc6e380dbd94adf9aa15b28e Mon Sep 17 00:00:00 2001 From: Matt Wrock Date: Sat, 3 Sep 2016 10:31:12 -0700 Subject: [PATCH] port winrm transport to winrm v2 gems --- chef-provisioning.gemspec | 2 +- .../convergence_strategy/install_msi.rb | 8 +-- lib/chef/provisioning/transport/winrm.rb | 65 ++++++++----------- 3 files changed, 31 insertions(+), 44 deletions(-) diff --git a/chef-provisioning.gemspec b/chef-provisioning.gemspec index a0a2e486..37f1983f 100644 --- a/chef-provisioning.gemspec +++ b/chef-provisioning.gemspec @@ -19,7 +19,7 @@ Gem::Specification.new do |s| s.add_dependency 'net-ssh-gateway', '~> 1.2.0' s.add_dependency 'inifile', '>= 2.0.2' s.add_dependency 'cheffish', '~> 4.0' - s.add_dependency 'winrm', '~> 1.3' + s.add_dependency 'winrm-fs', '~> 1.0' s.add_dependency "mixlib-install", "~> 1.0" s.add_development_dependency 'chef', '~> 12.1', "!= 12.4.0" # 12.4.0 is incompatible. diff --git a/lib/chef/provisioning/convergence_strategy/install_msi.rb b/lib/chef/provisioning/convergence_strategy/install_msi.rb index 4fdedad1..ced32a61 100644 --- a/lib/chef/provisioning/convergence_strategy/install_msi.rb +++ b/lib/chef/provisioning/convergence_strategy/install_msi.rb @@ -41,8 +41,7 @@ def setup_convergence(action_handler, machine) action_handler.open_stream(machine.node['name']) do |stdout| action_handler.open_stream(machine.node['name']) do |stderr| - machine.execute(action_handler, "powershell.exe -ExecutionPolicy Unrestricted -NoProfile \"& \"\"#{convergence_options[:install_script_path]}\"\"\"", - :raw => true, + machine.execute(action_handler, "& \"#{convergence_options[:install_script_path]}\"", :stream_stdout => stdout, :stream_stderr => stderr) end @@ -54,10 +53,11 @@ def converge(action_handler, machine) action_handler.open_stream(machine.node['name']) do |stdout| action_handler.open_stream(machine.node['name']) do |stderr| - command_line = "chef-client" + # We just installed chef in this shell so refresh PATH from System.Environment + command_line = "$env:path = [System.Environment]::GetEnvironmentVariable('PATH', 'MACHINE');" + command_line << "chef-client" command_line << " -l #{config[:log_level].to_s}" if config[:log_level] machine.execute(action_handler, command_line, - :raw => true, :stream_stdout => stdout, :stream_stderr => stderr, :timeout => @chef_client_timeout) diff --git a/lib/chef/provisioning/transport/winrm.rb b/lib/chef/provisioning/transport/winrm.rb index 270b8b60..f2d7ac7b 100644 --- a/lib/chef/provisioning/transport/winrm.rb +++ b/lib/chef/provisioning/transport/winrm.rb @@ -22,27 +22,24 @@ class WinRM < Chef::Provisioning::Transport # The actual connection is made as ::WinRM::WinRMWebService.new(endpoint, type, options) # def initialize(endpoint, type, options, global_config) - @endpoint = endpoint - @type = type @options = options + @options[:endpoint] = endpoint + @options[:transport] = type + + # WinRM v2 switched from :pass to :password + # we accept either to avoid having to update every driver + @options[:password] = @options[:password] || @options[:pass] + @config = global_config end - attr_reader :endpoint - attr_reader :type attr_reader :options attr_reader :config def execute(command, execute_options = {}) output = with_execute_timeout(execute_options) do - session.set_timeout(execute_timeout(execute_options)) - command_executor = ::WinRM::CommandExecutor.new(session) block = Proc.new { |stdout, stderr| stream_chunk(execute_options, stdout, stderr) } - if execute_options[:raw] - command_executor.run_cmd(command, &block) - else - command_executor.run_powershell_script(command, &block) - end + session.run(command, &block) end WinRMResult.new(command, execute_options, config, output) end @@ -57,25 +54,13 @@ def read_file(path) end def write_file(path, content) - execute("New-Item -Type Directory -Force -Path #{escape(::File.dirname(path))}").error! - chunk_size = options[:chunk_size] || 1024 - # TODO if we could marshal this data directly, we wouldn't have to base64 or do this godawful slow stuff :( - index = 0 - execute(" -$ByteArray = [System.Convert]::FromBase64String(#{escape(Base64.encode64(content[index..index+chunk_size-1]))}) -$file = [System.IO.File]::Open(#{escape(path)}, 'Create', 'Write') -$file.Write($ByteArray, 0, $ByteArray.Length) -$file.Close -").error! - index += chunk_size - while index < content.length - execute(" -$ByteArray = [System.Convert]::FromBase64String(#{escape(Base64.encode64(content[index..index+chunk_size-1]))}) -$file = [System.IO.File]::Open(#{escape(path)}, 'Append', 'Write') -$file.Write($ByteArray, 0, $ByteArray.Length) -$file.Close -").error! - index += chunk_size + file = Tempfile.new('provisioning-upload') + begin + file.write(content) + file.close + file_transporter.upload(file.path, path) + ensure + file.unlink end end @@ -114,9 +99,15 @@ def make_url_available_to_remote(local_url) def session @session ||= begin - require 'kconv' # Really, people? *sigh* require 'winrm' - ::WinRM::WinRMWebService.new(endpoint, type, options) + ::WinRM::Connection.new(options).shell(:powershell) + end + end + + def file_transporter + @file_transporter ||= begin + require 'winrm-fs' + ::WinRM::FS::Core::FileTransporter.new(session) end end @@ -125,13 +116,9 @@ def initialize(command, options, config, output) @command = command @options = options @config = config - @exitstatus = output[:exitcode] - @stdout = '' - @stderr = '' - output[:data].each do |data| - @stdout << data[:stdout] if data[:stdout] - @stderr << data[:stderr] if data[:stderr] - end + @exitstatus = output.exitcode + @stdout = output.stdout + @stderr = output.stderr end attr_reader :stdout