class Kitchen::Transport::Winrm

A Transport which uses WinRM to execute commands and transfer files.

@author Matt Wrock <matt@mattwrock.com> @author Salim Afiune <salim@afiunemaya.com.mx> @author Fletcher Nichol <fnichol@nichol.ca>

Constants

WINRM_ELEVATED_SPEC_VERSION
WINRM_FS_SPEC_VERSION
WINRM_SPEC_VERSION

Public Instance Methods

connection(state, &block) click to toggle source

(see Base#connection)

# File lib/kitchen/transport/winrm.rb, line 70
def connection(state, &block)
  options = connection_options(config.to_hash.merge(state))

  if @connection && @connection_options == options
    reuse_connection(&block)
  else
    create_new_connection(options, &block)
  end
end
finalize_config!(instance) click to toggle source
Calls superclass method Kitchen::Configurable#finalize_config!
# File lib/kitchen/transport/winrm.rb, line 61
def finalize_config!(instance)
  super

  config[:winrm_transport] = config[:winrm_transport].to_sym

  self
end

Private Instance Methods

additional_transport_args(data, transport_type) click to toggle source
# File lib/kitchen/transport/winrm.rb, line 470
def additional_transport_args(data, transport_type)
  opts = {
    disable_sspi: false,
    basic_auth_only: false,
  }

  case transport_type.to_sym
  when :ssl
    if data.key?(:client_cert) && data.key?(:client_key)
      opts[:client_cert] = data[:client_cert]
      opts[:client_key] = data[:client_key]
    end
    opts[:no_ssl_peer_verification] = data.key?(:no_ssl_peer_verification) ? data[:no_ssl_peer_verification] : true
    opts
  when :negotiate
    opts[:no_ssl_peer_verification] = true
    opts
  when :plaintext
    {
      disable_sspi: true,
      basic_auth_only: true,
    }
  else
    {}
  end
end
connection_options(data) click to toggle source

Builds the hash of options needed by the Connection object on construction.

@param data [Hash] merged configuration and mutable state data @return [Hash] hash of connection options @api private

# File lib/kitchen/transport/winrm.rb, line 433
def connection_options(data)
  endpoint = URI::Generic.build(
    scheme: data.fetch(:scheme),
    host: data.fetch(:hostname),
    port: data.fetch(:port),
    path: "/wsman"
  ).to_s

  elevated_password = data[:password]
  elevated_password = data[:elevated_password] if data.key?(:elevated_password)

  opts = {
    instance_name: instance.name,
    kitchen_root: data[:kitchen_root],
    logger: logger,
    endpoint: endpoint,
    user: data[:username],
    password: data[:password],
    rdp_port: data[:rdp_port],
    connection_retries: data[:connection_retries],
    connection_retry_sleep: data[:connection_retry_sleep],
    operation_timeout: data[:operation_timeout],
    receive_timeout: data[:receive_timeout],
    max_wait_until_ready: data[:max_wait_until_ready],
    transport: data[:winrm_transport],
    elevated: data[:elevated],
    elevated_username: data[:elevated_username] || data[:username],
    elevated_password: elevated_password,
  }
  opts.merge!(additional_transport_args(data, opts[:transport]))
  if opts[:transport].to_sym == :ssl && opts.key?(:client_cert) && opts.key?(:client_key)
    opts.delete(:user)
    opts.delete(:password)
  end
  opts
end
create_new_connection(options, &block) click to toggle source

Creates a new WinRM Connection instance and save it for potential future reuse.

@param options [Hash] connection options @return [Ssh::Connection] a WinRM Connection instance @api private

# File lib/kitchen/transport/winrm.rb, line 503
def create_new_connection(options, &block)
  if @connection
    string_to_mask = "[WinRM] shutting previous connection #{@connection}"
    masked_string = Util.mask_values(string_to_mask, %w{password ssh_http_proxy_password})
    logger.debug(masked_string)
    @connection.close
  end

  @connection_options = options
  @connection = Kitchen::Transport::Winrm::Connection.new(options, &block)
end
fail_to_load_gem_message(name, version = nil) click to toggle source
# File lib/kitchen/transport/winrm.rb, line 542
def fail_to_load_gem_message(name, version = nil)
  version_cmd = "--version '#{version}'" if version
  version_file = "', '#{version}"

  "The `#{name}` gem is missing and must" \
    " be installed or cannot be properly activated. Run" \
    " `gem install #{name} #{version_cmd}`" \
    " or add the following to your Gemfile if you are using Bundler:" \
    " `gem '#{name} #{version_file}'`."
end
host_os_windows?() click to toggle source
# File lib/kitchen/transport/winrm.rb, line 553
def host_os_windows?
  case RbConfig::CONFIG["host_os"]
  when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
    true
  else
    false
  end
end
load_needed_dependencies!() click to toggle source

(see Base#load_needed_dependencies!)

# File lib/kitchen/transport/winrm.rb, line 516
def load_needed_dependencies!
  super
  load_with_rescue!("winrm", WINRM_SPEC_VERSION.dup)
  load_with_rescue!("winrm-fs", WINRM_FS_SPEC_VERSION.dup)
  load_with_rescue!("winrm-elevated", WINRM_ELEVATED_SPEC_VERSION.dup) if config[:elevated]
end
load_with_rescue!(gem_name, spec_version) click to toggle source
# File lib/kitchen/transport/winrm.rb, line 523
def load_with_rescue!(gem_name, spec_version)
  logger.debug("#{gem_name} requested," \
    " loading #{gem_name} gem (#{spec_version})")
  attempt_load = false
  gem gem_name, spec_version
  silence_warnings { attempt_load = require gem_name }
  if attempt_load
    logger.debug("#{gem_name} is loaded.")
  else
    logger.debug("#{gem_name} was already loaded.")
  end
rescue LoadError => e
  message = fail_to_load_gem_message(gem_name,
    spec_version)
  logger.fatal(message)
  raise UserError,
    "Could not load or activate #{gem_name}. (#{e.message})"
end
reuse_connection() { |connection| ... } click to toggle source

Return the last saved WinRM connection instance.

@return [Winrm::Connection] a WinRM Connection instance @api private

# File lib/kitchen/transport/winrm.rb, line 566
def reuse_connection
  string_to_mask = "[WinRM] reusing existing connection #{@connection}"
  masked_string = Util.mask_values(string_to_mask, %w{password ssh_http_proxy_password})
  logger.debug(masked_string)
  yield @connection if block_given?
  @connection
end
silence_warnings() { || ... } click to toggle source
# File lib/kitchen/transport/winrm.rb, line 574
def silence_warnings
  old_verbose = $VERBOSE
  $VERBOSE = nil
  yield
ensure
  $VERBOSE = old_verbose
end