Class: Chef::Provisioning::Transport::WinRM

Inherits:
Chef::Provisioning::Transport show all
Defined in:
lib/chef/provisioning/transport/winrm.rb

Overview

Transport to handle the WinRM connection protocol.

Defined Under Namespace

Classes: WinRMResult

Constant Summary

Constants inherited from Chef::Provisioning::Transport

DEFAULT_TIMEOUT

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Chef::Provisioning::Transport

#download_file, #upload_file

Constructor Details

#initialize(endpoint, type, options, global_config) ⇒ WinRM

Create a new WinRM transport.

Arguments

  • endpoint: the WinRM endpoint, e.g. 145.14.51.45:5985/wsman.

  • type: the connection type, e.g. :plaintext.

  • options: options hash, including both WinRM options and transport options. For transport options, see the Transport.options definition. WinRM options include :user, :pass, :disable_sspi => true, among others.

  • global_config: an options hash that looks suspiciously similar to Chef::Config, containing at least the key :log_level.

The actual connection is made as ::WinRM::WinRMWebService.new(endpoint, type, options)



26
27
28
29
30
31
32
33
34
35
36
# File 'lib/chef/provisioning/transport/winrm.rb', line 26

def initialize(endpoint, type, options, global_config)
  @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

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



39
40
41
# File 'lib/chef/provisioning/transport/winrm.rb', line 39

def config
  @config
end

#optionsObject (readonly)

Returns the value of attribute options.



38
39
40
# File 'lib/chef/provisioning/transport/winrm.rb', line 38

def options
  @options
end

Instance Method Details

#available?Boolean

Returns:

  • (Boolean)


75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/chef/provisioning/transport/winrm.rb', line 75

def available?
  execute('pwd')
  true
rescue ::WinRM::WinRMAuthorizationError
  Chef::Log.debug("unavailable: winrm authentication error: #{$!.inspect} ")
  disconnect
  false
rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET, ::WinRM::WinRMError, Errno::ECONNABORTED
  Chef::Log.debug("unavailable: network connection failed or broke: #{$!.inspect}")
  disconnect
  false
end

#disconnectObject



67
68
69
# File 'lib/chef/provisioning/transport/winrm.rb', line 67

def disconnect
  #
end

#escape(string) ⇒ Object



71
72
73
# File 'lib/chef/provisioning/transport/winrm.rb', line 71

def escape(string)
  "\"#{string.gsub("\"", "`\"")}\""
end

#execute(command, execute_options = {}) ⇒ Object



41
42
43
44
45
# File 'lib/chef/provisioning/transport/winrm.rb', line 41

def execute(command, execute_options = {})
  block = Proc.new { |stdout, stderr| stream_chunk(execute_options, stdout, stderr) }
  output = session.run(command, &block)
  WinRMResult.new(command, execute_options, config, output)
end

#make_url_available_to_remote(local_url) ⇒ Object



88
89
90
91
92
93
94
95
96
# File 'lib/chef/provisioning/transport/winrm.rb', line 88

def make_url_available_to_remote(local_url)
  uri = URI(local_url)
  uri.scheme = 'http' if uri.scheme == 'chefzero' && uri.host == 'localhost'
  host = Socket.getaddrinfo(uri.host, uri.scheme, nil, :STREAM)[0][3]
  if host == '127.0.0.1' || host == '::1'
    raise 'Unable to converge locally via winrm. Local converge is currently only supported with SSH. You may only converge with winrm against a chef-server.'
  end
  local_url
end

#read_file(path) ⇒ Object



47
48
49
50
51
52
53
54
# File 'lib/chef/provisioning/transport/winrm.rb', line 47

def read_file(path)
  result = execute("[Convert]::ToBase64String((Get-Content #{escape(path)} -Encoding byte -ReadCount 0))")
  if result.exitstatus == 0
    Base64.decode64(result.stdout)
  else
    nil
  end
end

#write_file(path, content) ⇒ Object



56
57
58
59
60
61
62
63
64
65
# File 'lib/chef/provisioning/transport/winrm.rb', line 56

def write_file(path, content)
  file = Tempfile.new('provisioning-upload')
  begin
     file.write(content)
     file.close
     file_manager.upload(file.path, path)
  ensure
     file.unlink
  end
end