bolt 2.8.0 → 2.12.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 -2
- data/bolt-modules/boltlib/lib/puppet/datatypes/applyresult.rb +2 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/resourceinstance.rb +27 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +2 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/resultset.rb +2 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/target.rb +4 -3
- data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +61 -0
- data/bolt-modules/boltlib/lib/puppet/functions/set_resources.rb +122 -0
- data/bolt-modules/boltlib/types/planresult.pp +12 -1
- data/bolt-modules/file/lib/puppet/functions/file/exists.rb +3 -1
- data/bolt-modules/file/lib/puppet/functions/file/join.rb +1 -1
- data/bolt-modules/file/lib/puppet/functions/file/read.rb +2 -1
- data/bolt-modules/file/lib/puppet/functions/file/readable.rb +3 -1
- data/bolt-modules/file/lib/puppet/functions/file/write.rb +3 -1
- data/lib/bolt/analytics.rb +21 -2
- data/lib/bolt/applicator.rb +3 -1
- data/lib/bolt/apply_result.rb +1 -1
- data/lib/bolt/apply_target.rb +3 -2
- data/lib/bolt/bolt_option_parser.rb +18 -8
- data/lib/bolt/cli.rb +35 -5
- data/lib/bolt/config.rb +45 -13
- data/lib/bolt/config/transport/docker.rb +2 -0
- data/lib/bolt/config/transport/local.rb +2 -0
- data/lib/bolt/config/transport/orch.rb +2 -0
- data/lib/bolt/config/transport/remote.rb +2 -0
- data/lib/bolt/config/transport/ssh.rb +50 -1
- data/lib/bolt/config/transport/winrm.rb +2 -0
- data/lib/bolt/inventory.rb +2 -1
- data/lib/bolt/inventory/group.rb +1 -0
- data/lib/bolt/inventory/inventory.rb +5 -0
- data/lib/bolt/inventory/target.rb +17 -1
- data/lib/bolt/node/output.rb +1 -1
- data/lib/bolt/outputter/human.rb +5 -4
- data/lib/bolt/outputter/json.rb +1 -1
- data/lib/bolt/pal.rb +4 -1
- data/lib/bolt/pal/yaml_plan.rb +1 -0
- data/lib/bolt/plugin.rb +13 -7
- data/lib/bolt/plugin/puppetdb.rb +5 -2
- data/lib/bolt/project.rb +25 -7
- data/lib/bolt/puppetdb/config.rb +14 -26
- data/lib/bolt/rerun.rb +1 -1
- data/lib/bolt/resource_instance.rb +126 -0
- data/lib/bolt/result.rb +46 -23
- data/lib/bolt/result_set.rb +2 -5
- data/lib/bolt/shell/bash.rb +1 -1
- data/lib/bolt/shell/powershell.rb +12 -4
- data/lib/bolt/target.rb +12 -1
- data/lib/bolt/transport/ssh.rb +6 -2
- data/lib/bolt/transport/ssh/connection.rb +4 -0
- data/lib/bolt/transport/ssh/exec_connection.rb +110 -0
- data/lib/bolt/transport/winrm/connection.rb +6 -2
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/pe/pal.rb +1 -38
- data/lib/bolt_server/transport_app.rb +7 -7
- data/lib/bolt_spec/bolt_context.rb +1 -4
- data/lib/bolt_spec/plans/mock_executor.rb +1 -0
- data/lib/bolt_spec/run.rb +2 -5
- metadata +6 -2
data/lib/bolt/result.rb
CHANGED
@@ -40,18 +40,23 @@ module Bolt
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def self.for_task(target, stdout, stderr, exit_code, task)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
43
|
+
stdout.force_encoding('utf-8') unless stdout.encoding == Encoding::UTF_8
|
44
|
+
value = if stdout.valid_encoding?
|
45
|
+
parse_hash(stdout) || { '_output' => stdout }
|
46
|
+
else
|
47
|
+
{ '_error' => { 'kind' => 'puppetlabs.tasks/task-error',
|
48
|
+
'issue_code' => 'TASK_ERROR',
|
49
|
+
'msg' => 'The task result contained invalid UTF-8 on stdout',
|
50
|
+
'details' => {} } }
|
51
|
+
end
|
52
|
+
|
52
53
|
if exit_code != 0 && value['_error'].nil?
|
53
54
|
msg = if stdout.empty?
|
54
|
-
|
55
|
+
if stderr.empty?
|
56
|
+
"The task failed with exit code #{exit_code} and no output"
|
57
|
+
else
|
58
|
+
"The task failed with exit code #{exit_code} and no stdout, but stderr contained:\n#{stderr}"
|
59
|
+
end
|
55
60
|
else
|
56
61
|
"The task failed with exit code #{exit_code}"
|
57
62
|
end
|
@@ -63,6 +68,13 @@ module Bolt
|
|
63
68
|
new(target, value: value, action: 'task', object: task)
|
64
69
|
end
|
65
70
|
|
71
|
+
def self.parse_hash(string)
|
72
|
+
value = JSON.parse(string)
|
73
|
+
value if value.is_a? Hash
|
74
|
+
rescue JSON::ParserError
|
75
|
+
nil
|
76
|
+
end
|
77
|
+
|
66
78
|
def self.for_upload(target, source, destination)
|
67
79
|
new(target, message: "Uploaded '#{source}' to '#{target.host}:#{destination}'", action: 'upload', object: source)
|
68
80
|
end
|
@@ -110,18 +122,8 @@ module Bolt
|
|
110
122
|
message && !message.strip.empty?
|
111
123
|
end
|
112
124
|
|
113
|
-
def status_hash
|
114
|
-
{
|
115
|
-
target: @target.name,
|
116
|
-
action: action,
|
117
|
-
object: object,
|
118
|
-
status: status,
|
119
|
-
value: @value
|
120
|
-
}
|
121
|
-
end
|
122
|
-
|
123
125
|
def generic_value
|
124
|
-
|
126
|
+
safe_value.reject { |k, _| %w[_error _output].include? k }
|
125
127
|
end
|
126
128
|
|
127
129
|
def eql?(other)
|
@@ -139,15 +141,36 @@ module Bolt
|
|
139
141
|
end
|
140
142
|
|
141
143
|
def to_json(opts = nil)
|
142
|
-
|
144
|
+
to_data.to_json(opts)
|
143
145
|
end
|
144
146
|
|
145
147
|
def to_s
|
146
148
|
to_json
|
147
149
|
end
|
148
150
|
|
151
|
+
# This is the value with all non-UTF-8 characters removed, suitable for
|
152
|
+
# printing or converting to JSON. It *should* only be possible to have
|
153
|
+
# non-UTF-8 characters in stdout/stderr keys as they are not allowed from
|
154
|
+
# tasks but we scrub the whole thing just in case.
|
155
|
+
def safe_value
|
156
|
+
Bolt::Util.walk_vals(value) do |val|
|
157
|
+
if val.is_a?(String)
|
158
|
+
# Replace invalid bytes with hex codes, ie. \xDE\xAD\xBE\xEF
|
159
|
+
val.scrub { |c| c.bytes.map { |b| "\\x" + b.to_s(16).upcase }.join }
|
160
|
+
else
|
161
|
+
val
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
149
166
|
def to_data
|
150
|
-
|
167
|
+
{
|
168
|
+
"target" => @target.name,
|
169
|
+
"action" => action,
|
170
|
+
"object" => object,
|
171
|
+
"status" => status,
|
172
|
+
"value" => safe_value
|
173
|
+
}
|
151
174
|
end
|
152
175
|
|
153
176
|
def status
|
data/lib/bolt/result_set.rb
CHANGED
@@ -99,17 +99,14 @@ module Bolt
|
|
99
99
|
self.class == other.class && @results == other.results
|
100
100
|
end
|
101
101
|
|
102
|
-
def to_a
|
103
|
-
@results.map(&:status_hash)
|
104
|
-
end
|
105
|
-
|
106
102
|
def to_json(opts = nil)
|
107
|
-
|
103
|
+
to_data.to_json(opts)
|
108
104
|
end
|
109
105
|
|
110
106
|
def to_data
|
111
107
|
@results.map(&:to_data)
|
112
108
|
end
|
109
|
+
alias to_a to_data
|
113
110
|
|
114
111
|
def to_s
|
115
112
|
to_json
|
data/lib/bolt/shell/bash.rb
CHANGED
@@ -353,9 +353,9 @@ module Bolt
|
|
353
353
|
# Chunks of this size will be read in one iteration
|
354
354
|
index = 0
|
355
355
|
timeout = 0.1
|
356
|
+
result_output = Bolt::Node::Output.new
|
356
357
|
|
357
358
|
inp, out, err, t = conn.execute(command_str)
|
358
|
-
result_output = Bolt::Node::Output.new
|
359
359
|
read_streams = { out => String.new,
|
360
360
|
err => String.new }
|
361
361
|
write_stream = in_buffer.empty? ? [] : [inp]
|
@@ -267,10 +267,18 @@ module Bolt
|
|
267
267
|
|
268
268
|
result = Bolt::Node::Output.new
|
269
269
|
inp.close
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
270
|
+
stdout = Thread.new do
|
271
|
+
# Set to binmode to preserve \r\n line endings, but save and restore
|
272
|
+
# the proper encoding so the string isn't later misinterpreted
|
273
|
+
encoding = out.external_encoding
|
274
|
+
out.binmode
|
275
|
+
result.stdout << out.read.force_encoding(encoding)
|
276
|
+
end
|
277
|
+
stderr = Thread.new do
|
278
|
+
encoding = err.external_encoding
|
279
|
+
err.binmode
|
280
|
+
result.stderr << err.read.force_encoding(encoding)
|
281
|
+
end
|
274
282
|
|
275
283
|
stdout.join
|
276
284
|
stderr.join
|
data/lib/bolt/target.rb
CHANGED
@@ -31,7 +31,8 @@ module Bolt
|
|
31
31
|
facts = nil,
|
32
32
|
vars = nil,
|
33
33
|
features = nil,
|
34
|
-
plugin_hooks = nil
|
34
|
+
plugin_hooks = nil,
|
35
|
+
resources = nil)
|
35
36
|
from_asserted_hash('uri' => uri)
|
36
37
|
end
|
37
38
|
# rubocop:enable Lint/UnusedMethodArgument
|
@@ -75,6 +76,16 @@ module Bolt
|
|
75
76
|
inventory_target.target_alias
|
76
77
|
end
|
77
78
|
|
79
|
+
def resources
|
80
|
+
inventory_target.resources
|
81
|
+
end
|
82
|
+
|
83
|
+
# rubocop:disable Naming/AccessorMethodName
|
84
|
+
def set_resource(resource)
|
85
|
+
inventory_target.set_resource(resource)
|
86
|
+
end
|
87
|
+
# rubocop:enable Naming/AccessorMethodName
|
88
|
+
|
78
89
|
def to_h
|
79
90
|
options.to_h.merge(
|
80
91
|
'name' => name,
|
data/lib/bolt/transport/ssh.rb
CHANGED
@@ -16,13 +16,16 @@ module Bolt
|
|
16
16
|
rescue LoadError
|
17
17
|
logger.debug("Authentication method 'gssapi-with-mic' (Kerberos) is not available.")
|
18
18
|
end
|
19
|
-
|
20
19
|
@transport_logger = Logging.logger[Net::SSH]
|
21
20
|
@transport_logger.level = :warn
|
22
21
|
end
|
23
22
|
|
24
23
|
def with_connection(target)
|
25
|
-
conn =
|
24
|
+
conn = if target.transport_config['ssh-command']
|
25
|
+
ExecConnection.new(target)
|
26
|
+
else
|
27
|
+
Connection.new(target, @transport_logger)
|
28
|
+
end
|
26
29
|
conn.connect
|
27
30
|
yield conn
|
28
31
|
ensure
|
@@ -37,3 +40,4 @@ module Bolt
|
|
37
40
|
end
|
38
41
|
|
39
42
|
require 'bolt/transport/ssh/connection'
|
43
|
+
require 'bolt/transport/ssh/exec_connection'
|
@@ -207,6 +207,10 @@ module Bolt
|
|
207
207
|
err_wr.close
|
208
208
|
end
|
209
209
|
[in_wr, out_rd, err_rd, th]
|
210
|
+
rescue Errno::EMFILE => e
|
211
|
+
msg = "#{e.message}. This may be resolved by increasing your user limit "\
|
212
|
+
"with 'ulimit -n 1024'. See https://puppet.com/docs/bolt/latest/bolt_known_issues.html for details."
|
213
|
+
raise Bolt::Error.new(msg, 'bolt/too-many-files')
|
210
214
|
end
|
211
215
|
|
212
216
|
def copy_file(source, destination)
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
|
5
|
+
module Bolt
|
6
|
+
module Transport
|
7
|
+
class SSH < Simple
|
8
|
+
class ExecConnection
|
9
|
+
attr_reader :user, :target
|
10
|
+
|
11
|
+
def initialize(target)
|
12
|
+
raise Bolt::ValidationError, "Target #{target.safe_name} does not have a host" unless target.host
|
13
|
+
|
14
|
+
@target = target
|
15
|
+
ssh_config = Net::SSH::Config.for(target.host)
|
16
|
+
@user = @target.user || ssh_config[:user] || Etc.getlogin
|
17
|
+
@logger = Logging.logger[self]
|
18
|
+
end
|
19
|
+
|
20
|
+
# This is used to verify we can connect to targets with `connected?`
|
21
|
+
def connect
|
22
|
+
cmd = build_ssh_command('exit')
|
23
|
+
_, err, stat = Open3.capture3(*cmd)
|
24
|
+
unless stat.success?
|
25
|
+
raise Bolt::Node::ConnectError.new(
|
26
|
+
"Failed to connect to #{@target.safe_name}: #{err}",
|
27
|
+
'CONNECT_ERROR'
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def disconnect; end
|
33
|
+
|
34
|
+
def shell
|
35
|
+
Bolt::Shell::Bash.new(@target, self)
|
36
|
+
end
|
37
|
+
|
38
|
+
def userhost
|
39
|
+
"#{@user}@#{@target.host}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def ssh_opts
|
43
|
+
cmd = []
|
44
|
+
# BatchMode is SSH's noninteractive option: if key authentication
|
45
|
+
# fails it will error out instead of falling back to password prompt
|
46
|
+
cmd += %w[-o BatchMode=yes]
|
47
|
+
cmd += %W[-o Port=#{@target.port}] if @target.port
|
48
|
+
|
49
|
+
if @target.transport_config.key?('host-key-check')
|
50
|
+
hkc = @target.transport_config['host-key-check'] ? 'yes' : 'no'
|
51
|
+
cmd += %W[-o StrictHostKeyChecking=#{hkc}]
|
52
|
+
end
|
53
|
+
|
54
|
+
if (key = target.transport_config['private-key'])
|
55
|
+
cmd += ['-i', key]
|
56
|
+
end
|
57
|
+
cmd
|
58
|
+
end
|
59
|
+
|
60
|
+
def build_ssh_command(command)
|
61
|
+
ssh_conf = @target.transport_config['ssh-command']
|
62
|
+
ssh_cmd = Array(ssh_conf)
|
63
|
+
ssh_cmd += ssh_opts
|
64
|
+
ssh_cmd << userhost
|
65
|
+
ssh_cmd << command
|
66
|
+
end
|
67
|
+
|
68
|
+
def copy_file(source, dest)
|
69
|
+
@logger.debug { "Uploading #{source}, to #{userhost}:#{dest}" } unless source.is_a?(StringIO)
|
70
|
+
|
71
|
+
cp_conf = @target.transport_config['copy-command'] || ["scp", "-r"]
|
72
|
+
cp_cmd = Array(cp_conf)
|
73
|
+
cp_cmd += ssh_opts
|
74
|
+
|
75
|
+
_, err, stat = if source.is_a?(StringIO)
|
76
|
+
Tempfile.create(File.basename(dest)) do |f|
|
77
|
+
f.write(source.read)
|
78
|
+
f.close
|
79
|
+
cp_cmd << f.path
|
80
|
+
cp_cmd << "#{userhost}:#{Shellwords.escape(dest)}"
|
81
|
+
Open3.capture3(*cp_cmd)
|
82
|
+
end
|
83
|
+
else
|
84
|
+
cp_cmd << source
|
85
|
+
cp_cmd << "#{userhost}:#{Shellwords.escape(dest)}"
|
86
|
+
Open3.capture3(*cp_cmd)
|
87
|
+
end
|
88
|
+
|
89
|
+
if stat.success?
|
90
|
+
@logger.debug "Successfully uploaded #{source} to #{dest}"
|
91
|
+
else
|
92
|
+
message = "Could not copy file to #{dest}: #{err}"
|
93
|
+
raise Bolt::Node::FileError.new(message, 'COPY_ERROR')
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def execute(command)
|
98
|
+
cmd_array = build_ssh_command(command)
|
99
|
+
Open3.popen3(*cmd_array)
|
100
|
+
end
|
101
|
+
|
102
|
+
# This is used by the Bash shell to decide whether to `cd` before
|
103
|
+
# executing commands as a run-as user
|
104
|
+
def reset_cwd?
|
105
|
+
true
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -108,8 +108,8 @@ module Bolt
|
|
108
108
|
# it will fail if the shell attempts to provide stdin
|
109
109
|
inp.close
|
110
110
|
|
111
|
-
out_rd, out_wr = IO.pipe
|
112
|
-
err_rd, err_wr = IO.pipe
|
111
|
+
out_rd, out_wr = IO.pipe('UTF-8')
|
112
|
+
err_rd, err_wr = IO.pipe('UTF-8')
|
113
113
|
th = Thread.new do
|
114
114
|
result = @session.run(command)
|
115
115
|
out_wr << result.stdout
|
@@ -120,6 +120,10 @@ module Bolt
|
|
120
120
|
end
|
121
121
|
|
122
122
|
[inp, out_rd, err_rd, th]
|
123
|
+
rescue Errno::EMFILE => e
|
124
|
+
msg = "#{e.message}. This may be resolved by increasing your user limit "\
|
125
|
+
"with 'ulimit -n 1024'. See https://puppet.com/docs/bolt/latest/bolt_known_issues.html for details."
|
126
|
+
raise Bolt::Error.new(msg, 'bolt/too-many-files')
|
123
127
|
rescue StandardError
|
124
128
|
@logger.debug { "Command aborted" }
|
125
129
|
raise
|
data/lib/bolt/version.rb
CHANGED
data/lib/bolt_server/pe/pal.rb
CHANGED
@@ -51,50 +51,13 @@ module BoltServer
|
|
51
51
|
basemodulepath = plan_executor_config['basemodulepath'] || "#{codedir}/modules:/opt/puppetlabs/puppet/modules"
|
52
52
|
|
53
53
|
with_pe_pal_init_settings(codedir, environmentpath, basemodulepath) do
|
54
|
-
modulepath_dirs = []
|
55
|
-
modulepath_setting_from_bolt = nil
|
56
54
|
environment = Puppet.lookup(:environments).get!(environment_name)
|
57
|
-
path_to_env = environment.configuration.path_to_env
|
58
|
-
|
59
|
-
# In the instance where the environment is "production" but no production dir
|
60
|
-
# exists, the lookup will succeed, but the configuration will be mostly empty.
|
61
|
-
# For other environments the lookup will fail, but for production we don't
|
62
|
-
# want cryptic messages sent to the user about combining `nil` with a string.
|
63
|
-
# Thus if we do get here and `path_to_env` is empty, just assume it's the
|
64
|
-
# default production environment and continue.
|
65
|
-
#
|
66
|
-
# This should hopefully match puppet's behavior for the default 'production'
|
67
|
-
# environment: _technically_ that environment always exists, but if the dir
|
68
|
-
# isn't there it won't find the module and fail with "plan not found" rather
|
69
|
-
# than "environment doesn't exist"
|
70
|
-
if path_to_env
|
71
|
-
bolt_yaml = File.join(environment.configuration.path_to_env, 'bolt.yaml')
|
72
|
-
modulepath_setting_from_bolt = Bolt::Util.read_optional_yaml_hash(bolt_yaml, 'config')['modulepath']
|
73
|
-
end
|
74
|
-
|
75
|
-
# If we loaded a bolt.yaml in the environment root and it contained a modulepath setting:
|
76
|
-
# we will use that modulepath rather than the one loaded through puppet. modulepath will
|
77
|
-
# be the _only_ setting that will work from bolt.yaml in plans in PE.
|
78
|
-
if modulepath_setting_from_bolt
|
79
|
-
modulepath_setting_from_bolt.split(File::PATH_SEPARATOR).each do |path|
|
80
|
-
if Pathname.new(path).absolute? && File.exist?(path)
|
81
|
-
modulepath_dirs << path
|
82
|
-
elsif File.exist?(File.join(path_to_env, path))
|
83
|
-
modulepath_dirs << File.join(path_to_env, path)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
# Append the basemodulepath to include "built-in" modules.
|
88
|
-
modulepath_dirs.concat(basemodulepath.split(File::PATH_SEPARATOR))
|
89
|
-
else
|
90
|
-
modulepath_dirs = environment.modulepath
|
91
|
-
end
|
92
|
-
|
93
55
|
# A new modulepath is created from scratch (rather than using super's @modulepath)
|
94
56
|
# so that we can have full control over all the entries in modulepath. In the future
|
95
57
|
# it's likely we will need to preceed _both_ Bolt::PAL::BOLTLIB_PATH _and_
|
96
58
|
# Bolt::PAL::MODULES_PATH which would be more complex if we tried to use @modulepath since
|
97
59
|
# we need to append our modulepaths and exclude modules shiped in bolt gem code
|
60
|
+
modulepath_dirs = environment.modulepath
|
98
61
|
@original_modulepath = modulepath_dirs
|
99
62
|
@modulepath = [PE_BOLTLIB_PATH, Bolt::PAL::BOLTLIB_PATH, *modulepath_dirs]
|
100
63
|
end
|
@@ -57,8 +57,8 @@ module BoltServer
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def scrub_stack_trace(result)
|
60
|
-
if result.dig(
|
61
|
-
result[
|
60
|
+
if result.dig('value', '_error', 'details', 'stack_trace')
|
61
|
+
result['value']['_error']['details'].reject! { |k| k == 'stack_trace' }
|
62
62
|
end
|
63
63
|
result
|
64
64
|
end
|
@@ -87,14 +87,14 @@ module BoltServer
|
|
87
87
|
# If the `result_set` contains only one item, it will be returned
|
88
88
|
# as a single result object. Set `aggregate` to treat it as a set
|
89
89
|
# of results with length 1 instead.
|
90
|
-
def
|
90
|
+
def result_set_to_data(result_set, aggregate: false)
|
91
91
|
scrubbed_results = result_set.map do |result|
|
92
|
-
scrub_stack_trace(result.
|
92
|
+
scrub_stack_trace(result.to_data)
|
93
93
|
end
|
94
94
|
|
95
95
|
if aggregate || scrubbed_results.length > 1
|
96
96
|
# For actions that act on multiple targets, construct a status hash for the aggregate result
|
97
|
-
all_succeeded = scrubbed_results.all? { |r| r[
|
97
|
+
all_succeeded = scrubbed_results.all? { |r| r['status'] == 'success' }
|
98
98
|
{
|
99
99
|
status: all_succeeded ? 'success' : 'failure',
|
100
100
|
result: scrubbed_results
|
@@ -297,7 +297,7 @@ module BoltServer
|
|
297
297
|
return [400, error.to_json] unless error.nil?
|
298
298
|
|
299
299
|
aggregate = body['target'].nil?
|
300
|
-
[200,
|
300
|
+
[200, result_set_to_data(result_set, aggregate: aggregate).to_json]
|
301
301
|
end
|
302
302
|
|
303
303
|
def make_winrm_target(target_hash)
|
@@ -337,7 +337,7 @@ module BoltServer
|
|
337
337
|
return [400, error.to_json] if error
|
338
338
|
|
339
339
|
aggregate = body['target'].nil?
|
340
|
-
[200,
|
340
|
+
[200, result_set_to_data(result_set, aggregate: aggregate).to_json]
|
341
341
|
end
|
342
342
|
|
343
343
|
# Fetches the metadata for a single plan
|