bolt 2.29.0 → 2.33.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bolt might be problematic. Click here for more details.

Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/Puppetfile +15 -14
  3. data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +1 -1
  4. data/bolt-modules/boltlib/lib/puppet/functions/facts.rb +6 -0
  5. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +2 -2
  6. data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +1 -1
  7. data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +1 -1
  8. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +1 -1
  9. data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +1 -1
  10. data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +1 -1
  11. data/bolt-modules/boltlib/lib/puppet/functions/write_file.rb +2 -2
  12. data/bolt-modules/out/lib/puppet/functions/out/message.rb +44 -1
  13. data/bolt-modules/prompt/lib/puppet/functions/prompt.rb +3 -0
  14. data/guides/logging.txt +18 -0
  15. data/guides/module.txt +19 -0
  16. data/guides/modulepath.txt +25 -0
  17. data/lib/bolt/bolt_option_parser.rb +48 -9
  18. data/lib/bolt/catalog.rb +1 -1
  19. data/lib/bolt/cli.rb +154 -116
  20. data/lib/bolt/config.rb +13 -1
  21. data/lib/bolt/config/modulepath.rb +30 -0
  22. data/lib/bolt/config/options.rb +32 -13
  23. data/lib/bolt/config/transport/options.rb +2 -2
  24. data/lib/bolt/error.rb +4 -0
  25. data/lib/bolt/executor.rb +13 -13
  26. data/lib/bolt/inventory.rb +10 -9
  27. data/lib/bolt/module_installer.rb +198 -0
  28. data/lib/bolt/{puppetfile → module_installer}/installer.rb +3 -2
  29. data/lib/bolt/module_installer/puppetfile.rb +117 -0
  30. data/lib/bolt/module_installer/puppetfile/forge_module.rb +54 -0
  31. data/lib/bolt/module_installer/puppetfile/git_module.rb +37 -0
  32. data/lib/bolt/module_installer/puppetfile/module.rb +26 -0
  33. data/lib/bolt/module_installer/resolver.rb +76 -0
  34. data/lib/bolt/module_installer/specs.rb +93 -0
  35. data/lib/bolt/module_installer/specs/forge_spec.rb +85 -0
  36. data/lib/bolt/module_installer/specs/git_spec.rb +179 -0
  37. data/lib/bolt/outputter.rb +2 -45
  38. data/lib/bolt/outputter/human.rb +78 -18
  39. data/lib/bolt/outputter/json.rb +22 -7
  40. data/lib/bolt/outputter/logger.rb +2 -2
  41. data/lib/bolt/pal.rb +55 -45
  42. data/lib/bolt/pal/yaml_plan.rb +4 -2
  43. data/lib/bolt/pal/yaml_plan/evaluator.rb +23 -1
  44. data/lib/bolt/pal/yaml_plan/loader.rb +14 -9
  45. data/lib/bolt/plugin.rb +1 -1
  46. data/lib/bolt/plugin/module.rb +1 -1
  47. data/lib/bolt/project.rb +32 -21
  48. data/lib/bolt/project_migrator.rb +80 -0
  49. data/lib/bolt/project_migrator/base.rb +39 -0
  50. data/lib/bolt/project_migrator/config.rb +67 -0
  51. data/lib/bolt/project_migrator/inventory.rb +67 -0
  52. data/lib/bolt/project_migrator/modules.rb +200 -0
  53. data/lib/bolt/result.rb +23 -11
  54. data/lib/bolt/shell/bash.rb +15 -9
  55. data/lib/bolt/shell/powershell.rb +11 -6
  56. data/lib/bolt/transport/base.rb +18 -18
  57. data/lib/bolt/transport/docker.rb +23 -6
  58. data/lib/bolt/transport/orch.rb +23 -14
  59. data/lib/bolt/transport/remote.rb +2 -2
  60. data/lib/bolt/transport/simple.rb +6 -6
  61. data/lib/bolt/transport/ssh/connection.rb +1 -1
  62. data/lib/bolt/util.rb +22 -0
  63. data/lib/bolt/version.rb +1 -1
  64. data/lib/bolt_server/acl.rb +2 -2
  65. data/lib/bolt_server/base_config.rb +3 -3
  66. data/lib/bolt_server/schemas/partials/task.json +17 -2
  67. data/lib/bolt_server/transport_app.rb +92 -12
  68. data/lib/bolt_spec/bolt_context.rb +4 -2
  69. data/lib/bolt_spec/plans.rb +1 -1
  70. data/lib/bolt_spec/plans/action_stubs/command_stub.rb +1 -1
  71. data/lib/bolt_spec/plans/action_stubs/script_stub.rb +1 -1
  72. data/lib/bolt_spec/plans/mock_executor.rb +6 -6
  73. data/lib/bolt_spec/run.rb +1 -1
  74. metadata +29 -10
  75. data/lib/bolt/project_migrate.rb +0 -138
  76. data/lib/bolt/puppetfile.rb +0 -160
  77. data/lib/bolt/puppetfile/module.rb +0 -89
  78. data/lib/bolt_server/pe/pal.rb +0 -67
  79. data/modules/secure_env_vars/plans/init.pp +0 -20
@@ -21,14 +21,16 @@ module Bolt
21
21
  ['shell']
22
22
  end
23
23
 
24
- def run_command(command, options = {})
24
+ def run_command(command, options = {}, position = [])
25
25
  running_as(options[:run_as]) do
26
26
  output = execute(command, environment: options[:env_vars], sudoable: true)
27
27
  Bolt::Result.for_command(target,
28
28
  output.stdout.string,
29
29
  output.stderr.string,
30
30
  output.exit_code,
31
- 'command', command)
31
+ 'command',
32
+ command,
33
+ position)
32
34
  end
33
35
  end
34
36
 
@@ -71,7 +73,7 @@ module Bolt
71
73
  end
72
74
  end
73
75
 
74
- def run_script(script, arguments, options = {})
76
+ def run_script(script, arguments, options = {}, position = [])
75
77
  # unpack any Sensitive data
76
78
  arguments = unwrap_sensitive_args(arguments)
77
79
 
@@ -84,12 +86,14 @@ module Bolt
84
86
  output.stdout.string,
85
87
  output.stderr.string,
86
88
  output.exit_code,
87
- 'script', script)
89
+ 'script',
90
+ script,
91
+ position)
88
92
  end
89
93
  end
90
94
  end
91
95
 
92
- def run_task(task, arguments, options = {})
96
+ def run_task(task, arguments, options = {}, position = [])
93
97
  implementation = select_implementation(target, task)
94
98
  executable = implementation['path']
95
99
  input_method = implementation['input_method']
@@ -143,12 +147,13 @@ module Bolt
143
147
 
144
148
  execute_options[:stdin] = stdin
145
149
  execute_options[:sudoable] = true if run_as
146
- output = execute(remote_task_path, execute_options)
150
+ output = execute(remote_task_path, **execute_options)
147
151
  end
148
152
  Bolt::Result.for_task(target, output.stdout.string,
149
153
  output.stderr.string,
150
154
  output.exit_code,
151
- task.name)
155
+ task.name,
156
+ position)
152
157
  end
153
158
  end
154
159
 
@@ -202,13 +207,14 @@ module Bolt
202
207
  end
203
208
 
204
209
  def handle_sudo_errors(err)
205
- if err =~ /^#{conn.user} is not in the sudoers file\./
210
+ case err
211
+ when /^#{conn.user} is not in the sudoers file\./
206
212
  @logger.trace { err }
207
213
  raise Bolt::Node::EscalateError.new(
208
214
  "User #{conn.user} does not have sudo permission on #{target}",
209
215
  'SUDO_DENIED'
210
216
  )
211
- elsif err =~ /^Sorry, try again\./
217
+ when /^Sorry, try again\./
212
218
  @logger.trace { err }
213
219
  raise Bolt::Node::EscalateError.new(
214
220
  "Sudo password for user #{conn.user} not recognized on #{target}",
@@ -174,7 +174,7 @@ module Bolt
174
174
  Bolt::Result.for_download(target, source, destination, download)
175
175
  end
176
176
 
177
- def run_command(command, options = {})
177
+ def run_command(command, options = {}, position = [])
178
178
  command = [*env_declarations(options[:env_vars]), command].join("\r\n") if options[:env_vars]
179
179
 
180
180
  output = execute(command)
@@ -182,10 +182,12 @@ module Bolt
182
182
  output.stdout.string,
183
183
  output.stderr.string,
184
184
  output.exit_code,
185
- 'command', command)
185
+ 'command',
186
+ command,
187
+ position)
186
188
  end
187
189
 
188
- def run_script(script, arguments, options = {})
190
+ def run_script(script, arguments, options = {}, position = [])
189
191
  # unpack any Sensitive data
190
192
  arguments = unwrap_sensitive_args(arguments)
191
193
  with_tmpdir do |dir|
@@ -204,11 +206,13 @@ module Bolt
204
206
  output.stdout.string,
205
207
  output.stderr.string,
206
208
  output.exit_code,
207
- 'script', script)
209
+ 'script',
210
+ script,
211
+ position)
208
212
  end
209
213
  end
210
214
 
211
- def run_task(task, arguments, _options = {})
215
+ def run_task(task, arguments, _options = {}, position = [])
212
216
  implementation = select_implementation(target, task)
213
217
  executable = implementation['path']
214
218
  input_method = implementation['input_method']
@@ -259,7 +263,8 @@ module Bolt
259
263
  Bolt::Result.for_task(target, output.stdout.string,
260
264
  output.stderr.string,
261
265
  output.exit_code,
262
- task.name)
266
+ task.name,
267
+ position)
263
268
  end
264
269
  end
265
270
 
@@ -43,13 +43,13 @@ module Bolt
43
43
  @logger = Bolt::Logger.logger(self)
44
44
  end
45
45
 
46
- def with_events(target, callback, action)
46
+ def with_events(target, callback, action, position)
47
47
  callback&.call(type: :node_start, target: target)
48
48
 
49
49
  result = begin
50
50
  yield
51
51
  rescue StandardError, NotImplementedError => e
52
- Bolt::Result.from_exception(target, e, action: action)
52
+ Bolt::Result.from_exception(target, e, action: action, position: position)
53
53
  end
54
54
 
55
55
  callback&.call(type: :node_result, result: result)
@@ -100,12 +100,12 @@ module Bolt
100
100
  # The default implementation only supports batches of size 1 and will fail otherwise.
101
101
  #
102
102
  # Transports may override this method to implement their own batch processing.
103
- def batch_task(targets, task, arguments, options = {}, &callback)
103
+ def batch_task(targets, task, arguments, options = {}, position = [], &callback)
104
104
  assert_batch_size_one("batch_task()", targets)
105
105
  target = targets.first
106
- with_events(target, callback, 'task') do
106
+ with_events(target, callback, 'task', position) do
107
107
  @logger.debug { "Running task '#{task.name}' on #{target.safe_name}" }
108
- run_task(target, task, arguments, options)
108
+ run_task(target, task, arguments, options, position)
109
109
  end
110
110
  end
111
111
 
@@ -114,14 +114,14 @@ module Bolt
114
114
  # The default implementation only supports batches of size 1 and will fail otherwise.
115
115
  #
116
116
  # Transports may override this method to implment their own batch processing.
117
- def batch_task_with(targets, task, target_mapping, options = {}, &callback)
117
+ def batch_task_with(targets, task, target_mapping, options = {}, position = [], &callback)
118
118
  assert_batch_size_one("batch_task_with()", targets)
119
119
  target = targets.first
120
120
  arguments = target_mapping[target]
121
121
 
122
- with_events(target, callback, 'task') do
122
+ with_events(target, callback, 'task', position) do
123
123
  @logger.debug { "Running task '#{task.name}' on #{target.safe_name} with '#{arguments.to_json}'" }
124
- run_task(target, task, arguments, options)
124
+ run_task(target, task, arguments, options, position)
125
125
  end
126
126
  end
127
127
 
@@ -130,12 +130,12 @@ module Bolt
130
130
  # The default implementation only supports batches of size 1 and will fail otherwise.
131
131
  #
132
132
  # Transports may override this method to implement their own batch processing.
133
- def batch_command(targets, command, options = {}, &callback)
133
+ def batch_command(targets, command, options = {}, position = [], &callback)
134
134
  assert_batch_size_one("batch_command()", targets)
135
135
  target = targets.first
136
- with_events(target, callback, 'command') do
136
+ with_events(target, callback, 'command', position) do
137
137
  @logger.debug("Running command '#{command}' on #{target.safe_name}")
138
- run_command(target, command, options)
138
+ run_command(target, command, options, position)
139
139
  end
140
140
  end
141
141
 
@@ -144,12 +144,12 @@ module Bolt
144
144
  # The default implementation only supports batches of size 1 and will fail otherwise.
145
145
  #
146
146
  # Transports may override this method to implement their own batch processing.
147
- def batch_script(targets, script, arguments, options = {}, &callback)
147
+ def batch_script(targets, script, arguments, options = {}, position = [], &callback)
148
148
  assert_batch_size_one("batch_script()", targets)
149
149
  target = targets.first
150
- with_events(target, callback, 'script') do
150
+ with_events(target, callback, 'script', position) do
151
151
  @logger.debug { "Running script '#{script}' on #{target.safe_name}" }
152
- run_script(target, script, arguments, options)
152
+ run_script(target, script, arguments, options, position)
153
153
  end
154
154
  end
155
155
 
@@ -158,10 +158,10 @@ module Bolt
158
158
  # The default implementation only supports batches of size 1 and will fail otherwise.
159
159
  #
160
160
  # Transports may override this method to implement their own batch processing.
161
- def batch_upload(targets, source, destination, options = {}, &callback)
161
+ def batch_upload(targets, source, destination, options = {}, position = [], &callback)
162
162
  assert_batch_size_one("batch_upload()", targets)
163
163
  target = targets.first
164
- with_events(target, callback, 'upload') do
164
+ with_events(target, callback, 'upload', position) do
165
165
  @logger.debug { "Uploading: '#{source}' to #{destination} on #{target.safe_name}" }
166
166
  upload(target, source, destination, options)
167
167
  end
@@ -173,12 +173,12 @@ module Bolt
173
173
  # The default implementation only supports batches of size 1 and will fail otherwise.
174
174
  #
175
175
  # Transports may override this method to implement their own batch processing.
176
- def batch_download(targets, source, destination, options = {}, &callback)
176
+ def batch_download(targets, source, destination, options = {}, position = [], &callback)
177
177
  require 'erb'
178
178
 
179
179
  assert_batch_size_one("batch_download()", targets)
180
180
  target = targets.first
181
- with_events(target, callback, 'download') do
181
+ with_events(target, callback, 'download', position) do
182
182
  escaped_name = ERB::Util.url_encode(target.safe_name)
183
183
  target_destination = File.expand_path(escaped_name, destination)
184
184
  @logger.debug { "Downloading: '#{source}' on #{target.safe_name} to #{target_destination}" }
@@ -46,7 +46,7 @@ module Bolt
46
46
  end
47
47
  end
48
48
 
49
- def run_command(target, command, options = {})
49
+ def run_command(target, command, options = {}, position = [])
50
50
  execute_options = {}
51
51
  execute_options[:tty] = target.options['tty']
52
52
  execute_options[:environment] = options[:env_vars]
@@ -58,11 +58,17 @@ module Bolt
58
58
  end
59
59
  with_connection(target) do |conn|
60
60
  stdout, stderr, exitcode = conn.execute(*Shellwords.split(command), execute_options)
61
- Bolt::Result.for_command(target, stdout, stderr, exitcode, 'command', command)
61
+ Bolt::Result.for_command(target,
62
+ stdout,
63
+ stderr,
64
+ exitcode,
65
+ 'command',
66
+ command,
67
+ position)
62
68
  end
63
69
  end
64
70
 
65
- def run_script(target, script, arguments, options = {})
71
+ def run_script(target, script, arguments, options = {}, position = [])
66
72
  # unpack any Sensitive data
67
73
  arguments = unwrap_sensitive_args(arguments)
68
74
  execute_options = {}
@@ -72,12 +78,18 @@ module Bolt
72
78
  conn.with_remote_tmpdir do |dir|
73
79
  remote_path = conn.write_remote_executable(dir, script)
74
80
  stdout, stderr, exitcode = conn.execute(remote_path, *arguments, execute_options)
75
- Bolt::Result.for_command(target, stdout, stderr, exitcode, 'script', script)
81
+ Bolt::Result.for_command(target,
82
+ stdout,
83
+ stderr,
84
+ exitcode,
85
+ 'script',
86
+ script,
87
+ position)
76
88
  end
77
89
  end
78
90
  end
79
91
 
80
- def run_task(target, task, arguments, _options = {})
92
+ def run_task(target, task, arguments, _options = {}, position = [])
81
93
  implementation = task.select_implementation(target, provided_features)
82
94
  executable = implementation['path']
83
95
  input_method = implementation['input_method']
@@ -113,7 +125,12 @@ module Bolt
113
125
  end
114
126
 
115
127
  stdout, stderr, exitcode = conn.execute(remote_task_path, execute_options)
116
- Bolt::Result.for_task(target, stdout, stderr, exitcode, task.name)
128
+ Bolt::Result.for_task(target,
129
+ stdout,
130
+ stderr,
131
+ exitcode,
132
+ task.name,
133
+ position)
117
134
  end
118
135
  end
119
136
  end
@@ -53,7 +53,7 @@ module Bolt
53
53
  conn
54
54
  end
55
55
 
56
- def process_run_results(targets, results, task_name)
56
+ def process_run_results(targets, results, task_name, position = [])
57
57
  targets_by_name = Hash[targets.map { |t| t.host || t.name }.zip(targets)]
58
58
  results.map do |node_result|
59
59
  target = targets_by_name[node_result['name']]
@@ -63,25 +63,31 @@ module Bolt
63
63
  # If it's finished or already has a proper error simply pass it to the
64
64
  # the result otherwise make sure an error is generated
65
65
  if state == 'finished' || (result && result['_error'])
66
+ if result['_error']
67
+ file_line = %w[file line].zip(position).to_h.compact
68
+ result['_error']['details'].merge!(file_line) unless result['_error']['details']['file']
69
+ end
70
+
66
71
  Bolt::Result.new(target, value: result, action: 'task', object: task_name)
67
72
  elsif state == 'skipped'
73
+ details = %w[file line].zip(position).to_h.compact
68
74
  Bolt::Result.new(
69
75
  target,
70
76
  value: { '_error' => {
71
77
  'kind' => 'puppetlabs.tasks/skipped-node',
72
78
  'msg' => "Target #{target.safe_name} was skipped",
73
- 'details' => {}
79
+ 'details' => details
74
80
  } },
75
81
  action: 'task', object: task_name
76
82
  )
77
83
  else
78
84
  # Make a generic error with a unkown exit_code
79
- Bolt::Result.for_task(target, result.to_json, '', 'unknown', task_name)
85
+ Bolt::Result.for_task(target, result.to_json, '', 'unknown', task_name, position)
80
86
  end
81
87
  end
82
88
  end
83
89
 
84
- def batch_command(targets, command, options = {}, &callback)
90
+ def batch_command(targets, command, options = {}, position = [], &callback)
85
91
  if options[:env_vars] && !options[:env_vars].empty?
86
92
  raise NotImplementedError, "pcp transport does not support setting environment variables"
87
93
  end
@@ -93,6 +99,7 @@ module Bolt
93
99
  BOLT_COMMAND_TASK,
94
100
  params,
95
101
  options,
102
+ position,
96
103
  &callback)
97
104
  callback ||= proc {}
98
105
  results.map! { |result| unwrap_bolt_result(result.target, result, 'command', command) }
@@ -101,7 +108,7 @@ module Bolt
101
108
  end
102
109
  end
103
110
 
104
- def batch_script(targets, script, arguments, options = {}, &callback)
111
+ def batch_script(targets, script, arguments, options = {}, position = [], &callback)
105
112
  if options[:env_vars] && !options[:env_vars].empty?
106
113
  raise NotImplementedError, "pcp transport does not support setting environment variables"
107
114
  end
@@ -114,7 +121,7 @@ module Bolt
114
121
  'name' => Pathname(script).basename.to_s
115
122
  }
116
123
  callback ||= proc {}
117
- results = run_task_job(targets, BOLT_SCRIPT_TASK, params, options, &callback)
124
+ results = run_task_job(targets, BOLT_SCRIPT_TASK, params, options, position, &callback)
118
125
  results.map! { |result| unwrap_bolt_result(result.target, result, 'script', script) }
119
126
  results.each do |result|
120
127
  callback.call(type: :node_result, result: result)
@@ -155,7 +162,7 @@ module Bolt
155
162
  output&.close
156
163
  end
157
164
 
158
- def batch_upload(targets, source, destination, options = {}, &callback)
165
+ def batch_upload(targets, source, destination, options = {}, position = [], &callback)
159
166
  stat = File.stat(source)
160
167
  content = if stat.directory?
161
168
  pack(source)
@@ -171,7 +178,7 @@ module Bolt
171
178
  'directory' => stat.directory?
172
179
  }
173
180
  callback ||= proc {}
174
- results = run_task_job(targets, BOLT_UPLOAD_TASK, params, options, &callback)
181
+ results = run_task_job(targets, BOLT_UPLOAD_TASK, params, options, position, &callback)
175
182
  results.map! do |result|
176
183
  if result.error_hash
177
184
  result
@@ -200,7 +207,7 @@ module Bolt
200
207
  targets.group_by { |target| Connection.get_key(target.options) }.values
201
208
  end
202
209
 
203
- def run_task_job(targets, task, arguments, options)
210
+ def run_task_job(targets, task, arguments, options, position)
204
211
  targets.each do |target|
205
212
  yield(type: :node_start, target: target) if block_given?
206
213
  end
@@ -210,7 +217,7 @@ module Bolt
210
217
  arguments = unwrap_sensitive_args(arguments)
211
218
  results = get_connection(targets.first.options).run_task(targets, task, arguments, options)
212
219
 
213
- process_run_results(targets, results, task.name)
220
+ process_run_results(targets, results, task.name, position)
214
221
  rescue OrchestratorClient::ApiError => e
215
222
  targets.map do |target|
216
223
  Bolt::Result.new(target, error: e.data)
@@ -222,15 +229,15 @@ module Bolt
222
229
  end
223
230
  end
224
231
 
225
- def batch_task(targets, task, arguments, options = {}, &callback)
232
+ def batch_task(targets, task, arguments, options = {}, position = [], &callback)
226
233
  callback ||= proc {}
227
- results = run_task_job(targets, task, arguments, options, &callback)
234
+ results = run_task_job(targets, task, arguments, options, position, &callback)
228
235
  results.each do |result|
229
236
  callback.call(type: :node_result, result: result)
230
237
  end
231
238
  end
232
239
 
233
- def batch_task_with(_targets, _task, _target_mapping, _options = {})
240
+ def batch_task_with(_targets, _task, _target_mapping, _options = {}, _position = [])
234
241
  raise NotImplementedError, "pcp transport does not support run_task_with()"
235
242
  end
236
243
 
@@ -248,11 +255,13 @@ module Bolt
248
255
  return result
249
256
  end
250
257
 
258
+ # If we get here, there's no error so we don't need the file or line
259
+ # number
251
260
  Bolt::Result.for_command(target,
252
261
  result.value['stdout'],
253
262
  result.value['stderr'],
254
263
  result.value['exit_code'],
255
- action, obj)
264
+ action, obj, [])
256
265
  end
257
266
  end
258
267
  end
@@ -26,14 +26,14 @@ module Bolt
26
26
  end
27
27
 
28
28
  # Cannot batch because arugments differ
29
- def run_task(target, task, arguments, options = {})
29
+ def run_task(target, task, arguments, options = {}, position = [])
30
30
  proxy_target = get_proxy(target)
31
31
  transport = @executor.transport(proxy_target.transport)
32
32
  arguments = arguments.merge('_target' => target.to_h.reject { |_, v| v.nil? })
33
33
 
34
34
  remote_task = task.remote_instance
35
35
 
36
- result = transport.run_task(proxy_target, remote_task, arguments, options)
36
+ result = transport.run_task(proxy_target, remote_task, arguments, options, position)
37
37
  Bolt::Result.new(target, value: result.value, action: 'task', object: task.name)
38
38
  end
39
39
  end
@@ -20,9 +20,9 @@ module Bolt
20
20
  false
21
21
  end
22
22
 
23
- def run_command(target, command, options = {})
23
+ def run_command(target, command, options = {}, position = [])
24
24
  with_connection(target) do |conn|
25
- conn.shell.run_command(command, options)
25
+ conn.shell.run_command(command, options, position)
26
26
  end
27
27
  end
28
28
 
@@ -38,15 +38,15 @@ module Bolt
38
38
  end
39
39
  end
40
40
 
41
- def run_script(target, script, arguments, options = {})
41
+ def run_script(target, script, arguments, options = {}, position = [])
42
42
  with_connection(target) do |conn|
43
- conn.shell.run_script(script, arguments, options)
43
+ conn.shell.run_script(script, arguments, options, position)
44
44
  end
45
45
  end
46
46
 
47
- def run_task(target, task, arguments, options = {})
47
+ def run_task(target, task, arguments, options = {}, position = [])
48
48
  with_connection(target) do |conn|
49
- conn.shell.run_task(task, arguments, options)
49
+ conn.shell.run_task(task, arguments, options, position)
50
50
  end
51
51
  end
52
52
  end