Class: Remotus::HostPool

Inherits:
Object
  • Object
show all
Defined in:
lib/remotus/host_pool.rb

Overview

Class representing a remote connection pool (SSH or WinRM) for a single host

Constant Summary collapse

DEFAULT_EXPIRATION_SECONDS =

Number of seconds to wait for a connection from the pool by default

600
DEFAULT_POOL_SIZE =

Default size of the connection pool

2

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(host, size: DEFAULT_POOL_SIZE, timeout: DEFAULT_EXPIRATION_SECONDS, port: nil, proto: nil, **metadata) ⇒ HostPool

Creates a host pool for a specific host

Parameters:

  • host (String)

    hostname

  • size (Integer) (defaults to: DEFAULT_POOL_SIZE)

    number of connections in the pool (optional)

  • timeout (Integer) (defaults to: DEFAULT_EXPIRATION_SECONDS)

    amount of time to wait for a connection from the pool (optional)

  • port (Integer) (defaults to: nil)

    port to use for the connection

  • proto (Symbol) (defaults to: nil)

    protocol to use for the connection (:winrm, :ssh), must be specified if port is specified

  • metadata (Hash)

    metadata for this connection. Useful for providing additional information to various authentication stores should be specified using snake_case symbol keys. If keys are not snake_case, they will be converted.

    To connect to a host via IP, the following metadata entry can be provided to the host pool:

    :ip
    

    To configure a connection gateway, the following metadata entries can be provided to the host pool:

    :gateway_host (required to use gateway)
    :gateway_port
    :gateway_metadata
    :gateway_ip
    

    These function similarly to the host, port, host_pool metadata, and ip fields.

Raises:



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/remotus/host_pool.rb', line 56

def initialize(host, size: DEFAULT_POOL_SIZE, timeout: DEFAULT_EXPIRATION_SECONDS, port: nil, proto: nil, **)
  Remotus.logger.debug { "Creating host pool for #{host}" }

  # Update metadata information and generate the necessary accessor methods
  @metadata = 
  

  @host = host
  @proto = proto || Remotus.host_type(host)

  raise Remotus::HostTypeDeterminationError, "Could not determine whether to use SSH or WinRM for #{host}" unless @proto

  connection_class = Object.const_get("Remotus::#{@proto.capitalize}Connection")
  port ||= connection_class::REMOTE_PORT

  @pool = ConnectionPool.new(size: size, timeout: timeout) { connection_class.new(host, port, host_pool: self) }
  @size = size.to_i
  @timeout = timeout.to_i
  @expiration_time = Time.now + timeout
end

Instance Attribute Details

#expiration_timeTime (readonly)

Returns when the host pool will expire.

Returns:

  • (Time)

    when the host pool will expire



14
15
16
# File 'lib/remotus/host_pool.rb', line 14

def expiration_time
  @expiration_time
end

#hostString (readonly)

Returns host pool remote host.

Returns:

  • (String)

    host pool remote host



26
27
28
# File 'lib/remotus/host_pool.rb', line 26

def host
  @host
end

#protoSymbol (readonly)

Returns host pool protocol (:ssh or :winrm).

Returns:

  • (Symbol)

    host pool protocol (:ssh or :winrm)



23
24
25
# File 'lib/remotus/host_pool.rb', line 23

def proto
  @proto
end

#sizeInteger (readonly)

Returns size of the host connection pool.

Returns:

  • (Integer)

    size of the host connection pool



17
18
19
# File 'lib/remotus/host_pool.rb', line 17

def size
  @size
end

#timeoutInteger (readonly)

Returns Number of seconds to wait for a connection from the pool.

Returns:

  • (Integer)

    Number of seconds to wait for a connection from the pool



20
21
22
# File 'lib/remotus/host_pool.rb', line 20

def timeout
  @timeout
end

Instance Method Details

#[](key) ⇒ Object

Gets HostPool metadata at key

Parameters:

  • key (Object)

    metadata key

Returns:

  • (Object)

    metadata value



215
216
217
# File 'lib/remotus/host_pool.rb', line 215

def [](key)
  @metadata[key]
end

#[]=(key, value) ⇒ Object

Sets HostPool metadata value at key

Parameters:

  • key (Object)

    metadata key

  • value (Object)

    new metadata value



225
226
227
228
# File 'lib/remotus/host_pool.rb', line 225

def []=(key, value)
  @metadata[key] = value
  
end

#closeObject

Closes all open connections in the pool.



99
100
101
# File 'lib/remotus/host_pool.rb', line 99

def close
  @pool.reload(&:close)
end

#credential(**options) ⇒ Object

Gets the current host credential (if any)

See Also:

  • Auth#credential


193
194
195
# File 'lib/remotus/host_pool.rb', line 193

def credential(**options)
  with { |c| Remotus::Auth.credential(c, **options) }
end

#credential=(credential) ⇒ Object

Sets the current host credential

Parameters:



202
203
204
205
206
# File 'lib/remotus/host_pool.rb', line 202

def credential=(credential)
  # If the credential is a hash, transform it prior to setting it
  credential = Remotus::Auth::Credential.from_hash(credential) unless credential.is_a?(Remotus::Auth::Credential)
  Remotus::Auth.cache[host] = credential
end

#download(remote_path, local_path = nil, **options) ⇒ Object

Downloads file from the remote host



176
177
178
# File 'lib/remotus/host_pool.rb', line 176

def download(remote_path, local_path = nil, **options)
  with { |c| c.download(remote_path, local_path, **options) }
end

#expireObject

Force immediate expiration of the pool



89
90
91
92
# File 'lib/remotus/host_pool.rb', line 89

def expire
  Remotus.logger.debug { "Expiring #{@proto} host pool #{object_id} (#{@host})" }
  @expiration_time = Time.now
end

#expired?Boolean

Whether the pool is currently expired

Returns:

  • (Boolean)

    whether pool is expired



82
83
84
# File 'lib/remotus/host_pool.rb', line 82

def expired?
  Time.now > @expiration_time
end

#file_exist?(remote_path, **options) ⇒ Boolean

Checks if file exists on the remote host



185
186
187
# File 'lib/remotus/host_pool.rb', line 185

def file_exist?(remote_path, **options)
  with { |c| c.file_exist?(remote_path, **options) }
end

#portObject

Gets remote host connection port



129
130
131
132
# File 'lib/remotus/host_pool.rb', line 129

def port
  Remotus.logger.debug { "Getting port from #{@proto} host pool #{object_id} (#{@host})" }
  with(&:port)
end

#port_open?Boolean

Checks if connection port is open on the remote host



139
140
141
142
# File 'lib/remotus/host_pool.rb', line 139

def port_open?
  Remotus.logger.debug { "Checking if port is open from #{@proto} host pool #{object_id} (#{@host})" }
  with(&:port_open?)
end

#run(command, *args, **options) ⇒ Object

Runs command on the remote host



149
150
151
# File 'lib/remotus/host_pool.rb', line 149

def run(command, *args, **options)
  with { |c| c.run(command, *args, **options) }
end

#run_script(local_path, remote_path, *args, **options) ⇒ Object

Runs script on the remote host



158
159
160
# File 'lib/remotus/host_pool.rb', line 158

def run_script(local_path, remote_path, *args, **options)
  with { |c| c.run_script(local_path, remote_path, *args, **options) }
end

#upload(local_path, remote_path, **options) ⇒ Object

Uploads file to the remote host



167
168
169
# File 'lib/remotus/host_pool.rb', line 167

def upload(local_path, remote_path, **options)
  with { |c| c.upload(local_path, remote_path, **options) }
end

#with(**options, &block) ⇒ Object

Provides an SSH or WinRM connection to a given block of code

Examples:

Run a command over SSH or WinRM using a pooled connection

pool.with { |c| c.run("ls") }

Parameters:

  • options (Hash)

    options hash

Options Hash (**options):

  • :timeout (Integer)

    amount of time to wait for a connection if none is available

Returns:

  • (Object)

    return value of the provided block



114
115
116
117
118
119
120
121
122
# File 'lib/remotus/host_pool.rb', line 114

def with(**options, &block)
  # Update expiration time since the pool has been used
  @expiration_time = Time.now + (@timeout + options[:timeout].to_i)
  Remotus.logger.debug { "Updating #{@proto} host pool #{object_id} (#{@host}) expiration time to #{@expiration_time}" }

  # Run the provided block against the connection
  Remotus.logger.debug { "Running block in #{@proto} host pool #{object_id} (#{@host})" }
  @pool.with(options, &block)
end