bolt 2.5.0 → 2.6.0
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.
- checksums.yaml +4 -4
- data/Puppetfile +2 -1
- data/lib/bolt/executor.rb +1 -2
- data/lib/bolt/pal/yaml_plan/evaluator.rb +22 -14
- data/lib/bolt/pal/yaml_plan/step.rb +11 -4
- data/lib/bolt/pal/yaml_plan/step/command.rb +2 -2
- data/lib/bolt/pal/yaml_plan/step/resources.rb +3 -3
- data/lib/bolt/pal/yaml_plan/step/script.rb +2 -2
- data/lib/bolt/pal/yaml_plan/step/task.rb +2 -2
- data/lib/bolt/pal/yaml_plan/step/upload.rb +2 -2
- data/lib/bolt/plugin.rb +2 -1
- data/lib/bolt/shell.rb +1 -0
- data/lib/bolt/shell/powershell.rb +263 -0
- data/lib/bolt/shell/powershell/snippets.rb +273 -0
- data/lib/bolt/transport/local/connection.rb +11 -1
- data/lib/bolt/transport/winrm.rb +1 -118
- data/lib/bolt/transport/winrm/connection.rb +27 -78
- data/lib/bolt/version.rb +1 -1
- metadata +18 -4
- data/lib/bolt/transport/local_windows.rb +0 -189
- data/lib/bolt/transport/powershell.rb +0 -337
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ca1602020625348ee5ba03e246feeb9263ca10fdcda10e13bba36eb674dcdfba
|
4
|
+
data.tar.gz: bdde3554a2406f427f57d02f2e0063e592b7ceba235656c406e9f1ece3899c75
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13bcc53364488a1f37ebc19821c6429bcbcc055a543f9b581352b03c403793579290af88be0b92416506c3ddd9f23e775c7d9b9a6d2369aed3c38b0ef162da8f
|
7
|
+
data.tar.gz: ea09c6b92cc08d1cd893c136775070df2f6d79097663c58a96212bfdcf23984fe39fd5690d706f4802a61cd384bfe8139e446914506938605ba6d4771f272d63
|
data/Puppetfile
CHANGED
@@ -30,10 +30,11 @@ mod 'puppetlabs-ruby_task_helper', '0.5.1'
|
|
30
30
|
mod 'puppetlabs-ruby_plugin_helper', '0.1.0'
|
31
31
|
|
32
32
|
# Plugin modules
|
33
|
+
mod 'puppetlabs-aws_inventory', '0.5.0'
|
33
34
|
mod 'puppetlabs-azure_inventory', '0.3.0'
|
35
|
+
mod 'puppetlabs-gcloud_inventory', '0.1.0'
|
34
36
|
mod 'puppetlabs-terraform', '0.5.0'
|
35
37
|
mod 'puppetlabs-vault', '0.3.0'
|
36
|
-
mod 'puppetlabs-aws_inventory', '0.5.0'
|
37
38
|
mod 'puppetlabs-yaml', '0.2.0'
|
38
39
|
|
39
40
|
# If we don't list these modules explicitly, r10k will purge them
|
data/lib/bolt/executor.rb
CHANGED
@@ -15,7 +15,6 @@ require 'bolt/transport/ssh'
|
|
15
15
|
require 'bolt/transport/winrm'
|
16
16
|
require 'bolt/transport/orch'
|
17
17
|
require 'bolt/transport/local'
|
18
|
-
require 'bolt/transport/local_windows'
|
19
18
|
require 'bolt/transport/docker'
|
20
19
|
require 'bolt/transport/remote'
|
21
20
|
|
@@ -24,7 +23,7 @@ module Bolt
|
|
24
23
|
ssh: Bolt::Transport::SSH,
|
25
24
|
winrm: Bolt::Transport::WinRM,
|
26
25
|
pcp: Bolt::Transport::Orch,
|
27
|
-
local: Bolt::
|
26
|
+
local: Bolt::Transport::Local,
|
28
27
|
docker: Bolt::Transport::Docker,
|
29
28
|
remote: Bolt::Transport::Remote
|
30
29
|
}.freeze
|
@@ -24,14 +24,14 @@ module Bolt
|
|
24
24
|
|
25
25
|
def task_step(scope, step)
|
26
26
|
task = step['task']
|
27
|
-
|
27
|
+
targets = step['targets'] || step['target']
|
28
28
|
description = step['description']
|
29
29
|
params = step['parameters'] || {}
|
30
30
|
|
31
31
|
args = if description
|
32
|
-
[task,
|
32
|
+
[task, targets, description, params]
|
33
33
|
else
|
34
|
-
[task,
|
34
|
+
[task, targets, params]
|
35
35
|
end
|
36
36
|
|
37
37
|
scope.call_function('run_task', args)
|
@@ -48,15 +48,15 @@ module Bolt
|
|
48
48
|
|
49
49
|
def script_step(scope, step)
|
50
50
|
script = step['script']
|
51
|
-
|
51
|
+
targets = step['targets'] || step['target']
|
52
52
|
description = step['description']
|
53
53
|
arguments = step['arguments'] || []
|
54
54
|
|
55
55
|
options = { 'arguments' => arguments }
|
56
56
|
args = if description
|
57
|
-
[script,
|
57
|
+
[script, targets, description, options]
|
58
58
|
else
|
59
|
-
[script,
|
59
|
+
[script, targets, options]
|
60
60
|
end
|
61
61
|
|
62
62
|
scope.call_function('run_script', args)
|
@@ -64,10 +64,10 @@ module Bolt
|
|
64
64
|
|
65
65
|
def command_step(scope, step)
|
66
66
|
command = step['command']
|
67
|
-
|
67
|
+
targets = step['targets'] || step['target']
|
68
68
|
description = step['description']
|
69
69
|
|
70
|
-
args = [command,
|
70
|
+
args = [command, targets]
|
71
71
|
args << description if description
|
72
72
|
scope.call_function('run_command', args)
|
73
73
|
end
|
@@ -75,10 +75,10 @@ module Bolt
|
|
75
75
|
def upload_step(scope, step)
|
76
76
|
source = step['source']
|
77
77
|
destination = step['destination']
|
78
|
-
|
78
|
+
targets = step['targets'] || step['target']
|
79
79
|
description = step['description']
|
80
80
|
|
81
|
-
args = [source, destination,
|
81
|
+
args = [source, destination, targets]
|
82
82
|
args << description if description
|
83
83
|
scope.call_function('upload_file', args)
|
84
84
|
end
|
@@ -88,11 +88,13 @@ module Bolt
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def resources_step(scope, step)
|
91
|
+
targets = step['targets'] || step['target']
|
92
|
+
|
91
93
|
# TODO: Only call apply_prep when needed
|
92
|
-
scope.call_function('apply_prep',
|
94
|
+
scope.call_function('apply_prep', targets)
|
93
95
|
manifest = generate_manifest(step['resources'])
|
94
96
|
|
95
|
-
apply_manifest(scope,
|
97
|
+
apply_manifest(scope, targets, manifest)
|
96
98
|
end
|
97
99
|
|
98
100
|
def generate_manifest(resources)
|
@@ -127,16 +129,22 @@ module Bolt
|
|
127
129
|
MANIFEST
|
128
130
|
end
|
129
131
|
|
130
|
-
def apply_manifest(scope,
|
132
|
+
def apply_manifest(scope, targets, manifest)
|
131
133
|
ast = @evaluator.parse_string(manifest)
|
132
134
|
apply_block = ast.body.body
|
133
135
|
applicator = Puppet.lookup(:apply_executor)
|
134
|
-
applicator.apply([
|
136
|
+
applicator.apply([targets], apply_block, scope)
|
135
137
|
end
|
136
138
|
|
137
139
|
# This is the method that Puppet calls to evaluate the plan. The name
|
138
140
|
# makes more sense for .pp plans.
|
139
141
|
def evaluate_block_with_bindings(closure_scope, args_hash, plan)
|
142
|
+
if plan.steps.any? { |step| step.body.key?('target') }
|
143
|
+
msg = "The 'target' parameter for YAML plan steps is deprecated and will be removed "\
|
144
|
+
"in a future version of Bolt. Use the 'targets' parameter instead."
|
145
|
+
@logger.warn(msg)
|
146
|
+
end
|
147
|
+
|
140
148
|
plan_result = closure_scope.with_local_scope(args_hash) do |scope|
|
141
149
|
plan.steps.each do |step|
|
142
150
|
step_result = dispatch_step(scope, step)
|
@@ -6,13 +6,12 @@ module Bolt
|
|
6
6
|
class PAL
|
7
7
|
class YamlPlan
|
8
8
|
class Step
|
9
|
-
attr_reader :name, :type, :body, :
|
9
|
+
attr_reader :name, :type, :body, :targets
|
10
10
|
|
11
11
|
def self.allowed_keys
|
12
|
-
Set['name', 'description', 'target']
|
12
|
+
Set['name', 'description', 'target', 'targets']
|
13
13
|
end
|
14
14
|
|
15
|
-
COMMON_STEP_KEYS = %w[name description target].freeze
|
16
15
|
STEP_KEYS = %w[command script task plan source destination eval resources].freeze
|
17
16
|
|
18
17
|
def self.create(step_body, step_number)
|
@@ -38,7 +37,7 @@ module Bolt
|
|
38
37
|
def initialize(step_body)
|
39
38
|
@name = step_body['name']
|
40
39
|
@description = step_body['description']
|
41
|
-
@
|
40
|
+
@targets = step_body['targets'] || step_body['target']
|
42
41
|
@body = step_body
|
43
42
|
end
|
44
43
|
|
@@ -82,6 +81,14 @@ module Bolt
|
|
82
81
|
|
83
82
|
# Ensure all required keys are present
|
84
83
|
missing_keys = required_keys - body.keys
|
84
|
+
|
85
|
+
# Handle cases where steps with a required 'targets' key are using the deprecated
|
86
|
+
# 'target' key instead.
|
87
|
+
# TODO: Remove this when 'target' is removed
|
88
|
+
if body.include?('target')
|
89
|
+
missing_keys -= ['targets']
|
90
|
+
end
|
91
|
+
|
85
92
|
if missing_keys.any?
|
86
93
|
error_message = "The #{step_type.inspect} step requires: #{missing_keys.to_a.inspect} key(s)"
|
87
94
|
err = step_error(error_message, body['name'], step_number)
|
@@ -10,7 +10,7 @@ module Bolt
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.required_keys
|
13
|
-
Set['
|
13
|
+
Set['targets']
|
14
14
|
end
|
15
15
|
|
16
16
|
def initialize(step_body)
|
@@ -23,7 +23,7 @@ module Bolt
|
|
23
23
|
code << "$#{@name} = " if @name
|
24
24
|
|
25
25
|
fn = 'run_command'
|
26
|
-
args = [@command, @
|
26
|
+
args = [@command, @targets]
|
27
27
|
args << @description if @description
|
28
28
|
|
29
29
|
code << function_call(fn, args)
|
@@ -10,7 +10,7 @@ module Bolt
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.required_keys
|
13
|
-
Set['
|
13
|
+
Set['targets']
|
14
14
|
end
|
15
15
|
|
16
16
|
def initialize(step_body)
|
@@ -68,14 +68,14 @@ module Bolt
|
|
68
68
|
|
69
69
|
code.print " "
|
70
70
|
fn = 'apply_prep'
|
71
|
-
args = [@
|
71
|
+
args = [@targets]
|
72
72
|
code << function_call(fn, args)
|
73
73
|
code.print "\n"
|
74
74
|
|
75
75
|
code.print " "
|
76
76
|
code.print "$#{@name} = " if @name
|
77
77
|
|
78
|
-
code.puts "apply(#{Bolt::Util.to_code(@
|
78
|
+
code.puts "apply(#{Bolt::Util.to_code(@targets)}) {"
|
79
79
|
|
80
80
|
declarations = @normalized_resources.map do |resource|
|
81
81
|
type = resource['type'].is_a?(EvaluableString) ? resource['type'].value : resource['type']
|
@@ -10,7 +10,7 @@ module Bolt
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.required_keys
|
13
|
-
Set['
|
13
|
+
Set['targets']
|
14
14
|
end
|
15
15
|
|
16
16
|
def initialize(step_body)
|
@@ -28,7 +28,7 @@ module Bolt
|
|
28
28
|
options['arguments'] = @arguments unless @arguments.empty?
|
29
29
|
|
30
30
|
fn = 'run_script'
|
31
|
-
args = [@script, @
|
31
|
+
args = [@script, @targets]
|
32
32
|
args << @description if @description
|
33
33
|
args << options unless options.empty?
|
34
34
|
|
@@ -10,7 +10,7 @@ module Bolt
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.required_keys
|
13
|
-
Set['
|
13
|
+
Set['targets']
|
14
14
|
end
|
15
15
|
|
16
16
|
def initialize(step_body)
|
@@ -24,7 +24,7 @@ module Bolt
|
|
24
24
|
code << "$#{@name} = " if @name
|
25
25
|
|
26
26
|
fn = 'run_task'
|
27
|
-
args = [@task, @
|
27
|
+
args = [@task, @targets]
|
28
28
|
args << @description if @description
|
29
29
|
args << @parameters unless @parameters.empty?
|
30
30
|
|
@@ -10,7 +10,7 @@ module Bolt
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.required_keys
|
13
|
-
Set['
|
13
|
+
Set['destination', 'source', 'targets']
|
14
14
|
end
|
15
15
|
|
16
16
|
def initialize(step_body)
|
@@ -24,7 +24,7 @@ module Bolt
|
|
24
24
|
code << "$#{@name} = " if @name
|
25
25
|
|
26
26
|
fn = 'upload_file'
|
27
|
-
args = [@source, @destination, @
|
27
|
+
args = [@source, @destination, @targets]
|
28
28
|
args << @description if @description
|
29
29
|
|
30
30
|
code << function_call(fn, args)
|
data/lib/bolt/plugin.rb
CHANGED
@@ -143,7 +143,8 @@ module Bolt
|
|
143
143
|
end
|
144
144
|
|
145
145
|
RUBY_PLUGINS = %w[task pkcs7 prompt env_var].freeze
|
146
|
-
BUILTIN_PLUGINS = %w[task terraform pkcs7 prompt vault aws_inventory puppetdb azure_inventory
|
146
|
+
BUILTIN_PLUGINS = %w[task terraform pkcs7 prompt vault aws_inventory puppetdb azure_inventory
|
147
|
+
yaml env_var gcloud_inventory].freeze
|
147
148
|
DEFAULT_PLUGIN_HOOKS = { 'puppet_library' => { 'plugin' => 'puppet_agent', 'stop_service' => true } }.freeze
|
148
149
|
|
149
150
|
attr_reader :pal, :plugin_context
|
data/lib/bolt/shell.rb
CHANGED
@@ -0,0 +1,263 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/shell/powershell/snippets'
|
4
|
+
|
5
|
+
module Bolt
|
6
|
+
class Shell
|
7
|
+
class Powershell < Shell
|
8
|
+
DEFAULT_EXTENSIONS = Set.new(%w[.ps1 .rb .pp])
|
9
|
+
PS_ARGS = %w[-NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass -File].freeze
|
10
|
+
|
11
|
+
def initialize(target, conn)
|
12
|
+
super
|
13
|
+
|
14
|
+
extensions = [target.options['extensions'] || []].flatten.map { |ext| ext[0] != '.' ? '.' + ext : ext }
|
15
|
+
extensions += target.options['interpreters'].keys if target.options['interpreters']
|
16
|
+
@extensions = DEFAULT_EXTENSIONS + extensions
|
17
|
+
end
|
18
|
+
|
19
|
+
def provided_features
|
20
|
+
['powershell']
|
21
|
+
end
|
22
|
+
|
23
|
+
def default_input_method(executable)
|
24
|
+
powershell_file?(executable) ? 'powershell' : 'both'
|
25
|
+
end
|
26
|
+
|
27
|
+
def powershell_file?(path)
|
28
|
+
File.extname(path).downcase == '.ps1'
|
29
|
+
end
|
30
|
+
|
31
|
+
def validate_extensions(ext)
|
32
|
+
unless @extensions.include?(ext)
|
33
|
+
raise Bolt::Node::FileError.new("File extension #{ext} is not enabled, "\
|
34
|
+
"to run it please add to 'winrm: extensions'", 'FILETYPE_ERROR')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def process_from_extension(path)
|
39
|
+
case Pathname(path).extname.downcase
|
40
|
+
when '.rb'
|
41
|
+
[
|
42
|
+
'ruby.exe',
|
43
|
+
%W[-S "#{path}"]
|
44
|
+
]
|
45
|
+
when '.ps1'
|
46
|
+
[
|
47
|
+
'powershell.exe',
|
48
|
+
[*PS_ARGS, path]
|
49
|
+
]
|
50
|
+
when '.pp'
|
51
|
+
[
|
52
|
+
'puppet.bat',
|
53
|
+
%W[apply "#{path}"]
|
54
|
+
]
|
55
|
+
else
|
56
|
+
# Run the script via cmd, letting Windows extension handling determine how
|
57
|
+
[
|
58
|
+
'cmd.exe',
|
59
|
+
%W[/c "#{path}"]
|
60
|
+
]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def escape_arguments(arguments)
|
65
|
+
arguments.map do |arg|
|
66
|
+
if arg =~ / /
|
67
|
+
"\"#{arg}\""
|
68
|
+
else
|
69
|
+
arg
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def set_env(arg, val)
|
75
|
+
"[Environment]::SetEnvironmentVariable('#{arg}', @'\n#{val}\n'@)"
|
76
|
+
end
|
77
|
+
|
78
|
+
def quote_string(string)
|
79
|
+
"'" + string.gsub("'", "''") + "'"
|
80
|
+
end
|
81
|
+
|
82
|
+
def write_executable(dir, file, filename = nil)
|
83
|
+
filename ||= File.basename(file)
|
84
|
+
validate_extensions(File.extname(filename))
|
85
|
+
destination = "#{dir}\\#{filename}"
|
86
|
+
conn.copy_file(file, destination)
|
87
|
+
destination
|
88
|
+
end
|
89
|
+
|
90
|
+
def execute_process(path, arguments, stdin = nil)
|
91
|
+
quoted_args = arguments.map { |arg| quote_string(arg) }.join(' ')
|
92
|
+
|
93
|
+
quoted_path = if path =~ /^'.*'$/ || path =~ /^".*"$/
|
94
|
+
path
|
95
|
+
else
|
96
|
+
quote_string(path)
|
97
|
+
end
|
98
|
+
exec_cmd =
|
99
|
+
if stdin.nil?
|
100
|
+
"& #{quoted_path} #{quoted_args}"
|
101
|
+
else
|
102
|
+
<<~STR
|
103
|
+
$command_stdin = @'
|
104
|
+
#{stdin}
|
105
|
+
'@
|
106
|
+
|
107
|
+
$command_stdin | & #{quoted_path} #{quoted_args}
|
108
|
+
STR
|
109
|
+
end
|
110
|
+
Snippets.execute_process(exec_cmd)
|
111
|
+
end
|
112
|
+
|
113
|
+
def mkdirs(dirs)
|
114
|
+
mkdir_command = "mkdir -Force #{dirs.uniq.sort.join(',')}"
|
115
|
+
result = execute(mkdir_command)
|
116
|
+
if result.exit_code != 0
|
117
|
+
message = "Could not create directories: #{result.stderr.string}"
|
118
|
+
raise Bolt::Node::FileError.new(message, 'MKDIR_ERROR')
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def make_tempdir
|
123
|
+
find_parent = target.options['tmpdir'] ? "\"#{target.options['tmpdir']}\"" : '[System.IO.Path]::GetTempPath()'
|
124
|
+
result = execute(Snippets.make_tempdir(find_parent))
|
125
|
+
if result.exit_code != 0
|
126
|
+
raise Bolt::Node::FileError.new("Could not make tempdir: #{result.stderr.string}", 'TEMPDIR_ERROR')
|
127
|
+
end
|
128
|
+
result.stdout.string.chomp
|
129
|
+
end
|
130
|
+
|
131
|
+
def rmdir(dir)
|
132
|
+
execute(Snippets.rmdir(dir))
|
133
|
+
end
|
134
|
+
|
135
|
+
def with_tempdir
|
136
|
+
dir = make_tempdir
|
137
|
+
yield dir
|
138
|
+
ensure
|
139
|
+
rmdir(dir)
|
140
|
+
end
|
141
|
+
|
142
|
+
def run_ps_task(task_path, arguments, input_method)
|
143
|
+
# NOTE: cannot redirect STDIN to a .ps1 script inside of PowerShell
|
144
|
+
# must create new powershell.exe process like other interpreters
|
145
|
+
# fortunately, using PS with stdin input_method should never happen
|
146
|
+
if input_method == 'powershell'
|
147
|
+
Snippets.ps_task(task_path, arguments)
|
148
|
+
else
|
149
|
+
Snippets.try_catch(task_path)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def upload(source, destination, _options = {})
|
154
|
+
conn.copy_file(source, destination)
|
155
|
+
Bolt::Result.for_upload(target, source, destination)
|
156
|
+
end
|
157
|
+
|
158
|
+
def run_command(command, _options = {})
|
159
|
+
output = execute(command)
|
160
|
+
Bolt::Result.for_command(target,
|
161
|
+
output.stdout.string,
|
162
|
+
output.stderr.string,
|
163
|
+
output.exit_code,
|
164
|
+
'command', command)
|
165
|
+
end
|
166
|
+
|
167
|
+
def run_script(script, arguments, _options = {})
|
168
|
+
# unpack any Sensitive data
|
169
|
+
arguments = unwrap_sensitive_args(arguments)
|
170
|
+
with_tempdir do |dir|
|
171
|
+
script_path = write_executable(dir, script)
|
172
|
+
command = if powershell_file?(script_path)
|
173
|
+
Snippets.run_script(arguments, script_path)
|
174
|
+
else
|
175
|
+
path, args = *process_from_extension(script_path)
|
176
|
+
args += escape_arguments(arguments)
|
177
|
+
execute_process(path, args)
|
178
|
+
end
|
179
|
+
output = execute(command)
|
180
|
+
Bolt::Result.for_command(target,
|
181
|
+
output.stdout.string,
|
182
|
+
output.stderr.string,
|
183
|
+
output.exit_code,
|
184
|
+
'script', script)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def run_task(task, arguments, _options = {})
|
189
|
+
implementation = select_implementation(target, task)
|
190
|
+
executable = implementation['path']
|
191
|
+
input_method = implementation['input_method']
|
192
|
+
extra_files = implementation['files']
|
193
|
+
input_method ||= powershell_file?(executable) ? 'powershell' : 'both'
|
194
|
+
|
195
|
+
# unpack any Sensitive data
|
196
|
+
arguments = unwrap_sensitive_args(arguments)
|
197
|
+
with_tempdir do |dir|
|
198
|
+
if extra_files.empty?
|
199
|
+
task_dir = dir
|
200
|
+
else
|
201
|
+
# TODO: optimize upload of directories
|
202
|
+
arguments['_installdir'] = dir
|
203
|
+
task_dir = File.join(dir, task.tasks_dir)
|
204
|
+
mkdirs([task_dir] + extra_files.map { |file| File.join(dir, File.dirname(file['name'])) })
|
205
|
+
extra_files.each do |file|
|
206
|
+
conn.copy_file(file['path'], File.join(dir, file['name']))
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
task_path = write_executable(task_dir, executable)
|
211
|
+
|
212
|
+
if Bolt::Task::STDIN_METHODS.include?(input_method)
|
213
|
+
stdin = JSON.dump(arguments)
|
214
|
+
end
|
215
|
+
|
216
|
+
command = if powershell_file?(task_path) && stdin.nil?
|
217
|
+
run_ps_task(task_path, arguments, input_method)
|
218
|
+
else
|
219
|
+
if (interpreter = select_interpreter(task_path, target.options['interpreters']))
|
220
|
+
path = interpreter
|
221
|
+
args = [task_path]
|
222
|
+
else
|
223
|
+
path, args = *process_from_extension(task_path)
|
224
|
+
end
|
225
|
+
execute_process(path, args, stdin)
|
226
|
+
end
|
227
|
+
|
228
|
+
env_assignments = if Bolt::Task::ENVIRONMENT_METHODS.include?(input_method)
|
229
|
+
envify_params(arguments).map do |(arg, val)|
|
230
|
+
set_env(arg, val)
|
231
|
+
end
|
232
|
+
else
|
233
|
+
[]
|
234
|
+
end
|
235
|
+
|
236
|
+
output = execute([Snippets.shell_init, *env_assignments, command].join("\n"))
|
237
|
+
|
238
|
+
Bolt::Result.for_task(target, output.stdout.string,
|
239
|
+
output.stderr.string,
|
240
|
+
output.exit_code,
|
241
|
+
task.name)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def execute(command)
|
246
|
+
inp, out, err, t = conn.execute(command)
|
247
|
+
|
248
|
+
result = Bolt::Node::Output.new
|
249
|
+
inp.close
|
250
|
+
out.binmode
|
251
|
+
err.binmode
|
252
|
+
stdout = Thread.new { result.stdout << out.read }
|
253
|
+
stderr = Thread.new { result.stderr << err.read }
|
254
|
+
|
255
|
+
stdout.join
|
256
|
+
stderr.join
|
257
|
+
result.exit_code = t.value.respond_to?(:exitstatus) ? t.value.exitstatus : t.value
|
258
|
+
|
259
|
+
result
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|