class TrainPlugins::WinRM::Transport

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

SUPPORTED_WINRM_SHELL_TYPES
SUPPORTED_WINRM_TRANSPORTS

ref: github.com/winrb/winrm#transports

WINRM_ELEVATED_SPEC_VERSION
WINRM_FS_SPEC_VERSION

Public Class Methods

new(opts) click to toggle source
Calls superclass method
# File lib/train-winrm/transport.rb, line 78
def initialize(opts)
  super(opts)
  load_needed_dependencies!
end

Public Instance Methods

connection(state = nil, &block) click to toggle source

(see Base#connection)

# File lib/train-winrm/transport.rb, line 84
def connection(state = nil, &block)
  opts = merge_options(options, state || {})
  validate_options(opts)
  conn_opts = connection_options(opts)

  if @connection && @connection_options == conn_opts
    reuse_connection(&block)
  else
    create_new_connection(conn_opts, &block)
  end
end

Private Instance Methods

connection_options(opts) 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/train-winrm/transport.rb, line 130
def connection_options(opts)
  {
    logger: logger,
    transport: opts[:winrm_transport].to_sym,
    disable_sspi: opts[:winrm_disable_sspi],
    basic_auth_only: opts[:winrm_basic_auth_only],
    hostname: opts[:host],
    endpoint: opts[:endpoint],
    user: opts[:user],
    password: opts[:password],
    rdp_port: opts[:rdp_port],
    connection_retries: opts[:connection_retries],
    connection_retry_sleep: opts[:connection_retry_sleep],
    max_wait_until_ready: opts[:max_wait_until_ready],
    no_ssl_peer_verification: opts[:self_signed],
    realm: opts[:kerberos_realm],
    service: opts[:kerberos_service],
    ca_trust_file: opts[:ca_trust_file],
    ssl_peer_fingerprint: opts[:ssl_peer_fingerprint],
    winrm_shell_type: opts[:winrm_shell_type],
  }
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 [WinRM::Connection] a WinRM Connection instance @api private

# File lib/train-winrm/transport.rb, line 159
def create_new_connection(options, &block)
  if @connection
    logger.debug("[WinRM] shutting previous connection #{@connection}")
    @connection.close
  end

  @connection_options = options
  @connection = Connection.new(options, &block)
end
load_dependency(gem_name, spec_version) click to toggle source
# File lib/train-winrm/transport.rb, line 182
def load_dependency(gem_name, spec_version)
  gem gem_name, spec_version
  first_load = require gem_name
  load_winrm_transport!(gem_name)

  if first_load
    logger.debug("#{gem_name} library loaded")
  else
    logger.debug("#{gem_name} previously loaded")
  end
rescue LoadError => e
  logger.fatal(
    "The `#{gem_name}' gem is missing and must" \
    " be installed or cannot be properly activated. Run" \
    " `gem install #{gem_name}  --version '#{spec_version}'`" \
    " or add the following to your Gemfile if you are using Bundler:" \
    " `gem '#{gem_name}', '#{spec_version}'`."
  )
  raise Train::UserError,
    "Could not load or activate #{gem_name} (#{e.message})"
end
load_needed_dependencies!() click to toggle source

(see Base#load_needed_dependencies!)

# File lib/train-winrm/transport.rb, line 170
def load_needed_dependencies!
  spec_version = WINRM_FS_SPEC_VERSION.dup
  logger.debug("winrm-fs requested," \
    " loading WinRM::FS gem (#{spec_version})")
  load_dependency("winrm-fs", spec_version)

  spec_version = WINRM_ELEVATED_SPEC_VERSION.dup
  logger.debug("winrm-elevated requested," \
    " loading WinRM-elevated gem (#{spec_version})")
  load_dependency("winrm-elevated", spec_version)
end
load_winrm_transport!(gem_name) click to toggle source

Load WinRM::Transport code.

@api private

# File lib/train-winrm/transport.rb, line 207
def load_winrm_transport!(gem_name)
  silence_warnings { require gem_name }
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/train-winrm/transport.rb, line 215
def reuse_connection
  logger.debug("[WinRM] reusing existing connection #{@connection}")
  yield @connection if block_given?
  @connection
end
silence_warnings() { || ... } click to toggle source
# File lib/train-winrm/transport.rb, line 221
def silence_warnings
  old_verbose = $VERBOSE
  $VERBOSE = nil
  yield
ensure
  $VERBOSE = old_verbose
end
validate_options(opts) click to toggle source
Calls superclass method
# File lib/train-winrm/transport.rb, line 98
def validate_options(opts)
  super(opts)

  # set scheme and port based on ssl activation
  scheme = opts[:ssl] ? "https" : "http"
  port = opts[:port]
  port = (opts[:ssl] ? 5986 : 5985) if port.nil?
  winrm_transport = opts[:winrm_transport].to_sym
  unless SUPPORTED_WINRM_TRANSPORTS.include?(winrm_transport)
    raise Train::ClientError, "Unsupported transport type: #{winrm_transport.inspect}"
  end

  winrm_shell_type = opts[:winrm_shell_type].to_sym
  unless SUPPORTED_WINRM_SHELL_TYPES.include?(winrm_shell_type)
    raise Train::ClientError, "Unsupported winrm shell type: #{winrm_shell_type.inspect}"
  end

  # remove leading '/'
  path = (opts[:path] || "").sub(%r{^/+}, "")

  opts[:endpoint] = "#{scheme}://#{opts[:host]}:#{port}/#{path}"
end