Class: Bolt::Transport::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/bolt/transport/base.rb

Overview

This class provides the default behavior for Transports. A Transport is responsible for uploading files and running commands, scripts, and tasks on Targets.

Bolt executes work on the Transport in “batches”. To do that, it calls the batches() method, which is responsible for dividing the list of Targets into batches according to how it wants to handle them. It will then call Transport#batch_task, or the corresponding method for another operation, passing a list of Targets. The Transport returns a list of Bolt::Result objects, one per Target. Each batch is executed on a separate thread, controlled by the ‘concurrency` setting, so many batches may be running in parallel.

The default batch implementation splits the list of Targets into batches of 1. It then calls run_task(), or a corresponding method for other operations, passing in the single Target.

Most Transport implementations, like the SSH and WinRM transports, don’t need to do their own batching, since they only operate on a single Target at a time. Those Transports can implement the run_task() and related methods, which will automatically handle running many Targets in parallel, and will handle publishing start and finish events for each Target.

Transports that need their own batching, like the Orch transport, can instead override the batches() method to split Targets into sets that can be executed together, and override the batch_task() and related methods to execute a batch of nodes. In that case, those Transports should accept a block argument and call it with a :node_start event for each Target before executing, and a :node_result event for each Target after execution.

Direct Known Subclasses

Local, Orch, SSH, WinRM

Constant Summary collapse

STDIN_METHODS =
%w[both stdin].freeze
ENVIRONMENT_METHODS =
%w[both environment].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeBase

Returns a new instance of Base.



53
54
55
# File 'lib/bolt/transport/base.rb', line 53

def initialize
  @logger = Logging.logger[self]
end

Instance Attribute Details

#loggerObject (readonly)

Returns the value of attribute logger.



42
43
44
# File 'lib/bolt/transport/base.rb', line 42

def logger
  @logger
end

Class Method Details

.optionsObject

Returns options this transport supports

Raises:

  • (NotImplementedError)


45
46
47
# File 'lib/bolt/transport/base.rb', line 45

def self.options
  raise NotImplementedError, "self.options() must be implemented by the transport class"
end

.validate(_options) ⇒ Object

Raises:

  • (NotImplementedError)


49
50
51
# File 'lib/bolt/transport/base.rb', line 49

def self.validate(_options)
  raise NotImplementedError, "self.validate() must be implemented by the transport class"
end

Instance Method Details

#assert_batch_size_one(method, targets) ⇒ Object

Raises an error if more than one target was given in the batch.

The default implementations of batch_* strictly assume the transport is using the default batch size of 1. This method ensures that is the case and raises an error if it’s not.



83
84
85
86
87
88
# File 'lib/bolt/transport/base.rb', line 83

def assert_batch_size_one(method, targets)
  if targets.length > 1
    message = "#{self.class.name} must implement #{method} to support batches (got #{targets.length} nodes)"
    raise NotImplementedError, message
  end
end

#batch_command(targets, command, options = {}, &callback) ⇒ Object

Runs the given command on a batch of nodes.

The default implementation only supports batches of size 1 and will fail otherwise.

Transports may override this method to implement their own batch processing.



109
110
111
112
113
114
115
116
# File 'lib/bolt/transport/base.rb', line 109

def batch_command(targets, command, options = {}, &callback)
  assert_batch_size_one("batch_command()", targets)
  target = targets.first
  with_events(target, callback) do
    @logger.debug("Running command '#{command}' on #{target.uri}")
    run_command(target, command, filter_options(target, options))
  end
end

#batch_script(targets, script, arguments, options = {}, &callback) ⇒ Object

Runs the given script on a batch of nodes.

The default implementation only supports batches of size 1 and will fail otherwise.

Transports may override this method to implement their own batch processing.



123
124
125
126
127
128
129
130
# File 'lib/bolt/transport/base.rb', line 123

def batch_script(targets, script, arguments, options = {}, &callback)
  assert_batch_size_one("batch_script()", targets)
  target = targets.first
  with_events(target, callback) do
    @logger.debug { "Running script '#{script}' on #{target.uri}" }
    run_script(target, script, arguments, filter_options(target, options))
  end
end

#batch_task(targets, task, arguments, options = {}, &callback) ⇒ Object

Runs the given task on a batch of nodes.

The default implementation only supports batches of size 1 and will fail otherwise.

Transports may override this method to implement their own batch processing.



95
96
97
98
99
100
101
102
# File 'lib/bolt/transport/base.rb', line 95

def batch_task(targets, task, arguments, options = {}, &callback)
  assert_batch_size_one("batch_task()", targets)
  target = targets.first
  with_events(target, callback) do
    @logger.debug { "Running task run '#{task}' on #{target.uri}" }
    run_task(target, task, arguments, filter_options(target, options))
  end
end

#batch_upload(targets, source, destination, options = {}, &callback) ⇒ Object

Uploads the given source file to the destination location on a batch of nodes.

The default implementation only supports batches of size 1 and will fail otherwise.

Transports may override this method to implement their own batch processing.



137
138
139
140
141
142
143
144
# File 'lib/bolt/transport/base.rb', line 137

def batch_upload(targets, source, destination, options = {}, &callback)
  assert_batch_size_one("batch_upload()", targets)
  target = targets.first
  with_events(target, callback) do
    @logger.debug { "Uploading: '#{source}' to #{destination} on #{target.uri}" }
    upload(target, source, destination, filter_options(target, options))
  end
end

#batches(targets) ⇒ Object

Split the given list of targets into a list of batches. The default implementation returns single-node batches.

Transports may override this method, and the corresponding batch_* methods, to implement their own batch processing.



151
152
153
# File 'lib/bolt/transport/base.rb', line 151

def batches(targets)
  targets.map { |target| [target] }
end

#filter_options(target, options) ⇒ Object



70
71
72
73
74
75
76
# File 'lib/bolt/transport/base.rb', line 70

def filter_options(target, options)
  if target.options['run-as']
    options.reject { |k, _v| k == '_run_as' }
  else
    options
  end
end

#run_command(*_args) ⇒ Object

Transports should override this method with their own implementation of running a command.

Raises:

  • (NotImplementedError)


156
157
158
# File 'lib/bolt/transport/base.rb', line 156

def run_command(*_args)
  raise NotImplementedError, "run_command() must be implemented by the transport class"
end

#run_script(*_args) ⇒ Object

Transports should override this method with their own implementation of running a script.

Raises:

  • (NotImplementedError)


161
162
163
# File 'lib/bolt/transport/base.rb', line 161

def run_script(*_args)
  raise NotImplementedError, "run_script() must be implemented by the transport class"
end

#run_task(*_args) ⇒ Object

Transports should override this method with their own implementation of running a task.

Raises:

  • (NotImplementedError)


166
167
168
# File 'lib/bolt/transport/base.rb', line 166

def run_task(*_args)
  raise NotImplementedError, "run_task() must be implemented by the transport class"
end

#upload(*_args) ⇒ Object

Transports should override this method with their own implementation of file upload.

Raises:

  • (NotImplementedError)


171
172
173
# File 'lib/bolt/transport/base.rb', line 171

def upload(*_args)
  raise NotImplementedError, "upload() must be implemented by the transport class"
end

#with_events(target, callback) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/bolt/transport/base.rb', line 57

def with_events(target, callback)
  callback&.call(type: :node_start, target: target)

  result = begin
    yield
  rescue StandardError => ex
    Bolt::Result.from_exception(target, ex)
  end

  callback&.call(type: :node_result, result: result)
  result
end