bolt 2.22.0 → 2.26.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 +1 -1
- data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +2 -1
- data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +1 -1
- data/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb +12 -6
- data/bolt-modules/dir/lib/puppet/functions/dir/children.rb +1 -1
- data/bolt-modules/out/lib/puppet/functions/out/message.rb +1 -1
- data/exe/bolt +1 -0
- data/guides/inventory.txt +19 -0
- data/guides/project.txt +22 -0
- data/lib/bolt/analytics.rb +8 -8
- data/lib/bolt/applicator.rb +6 -6
- data/lib/bolt/bolt_option_parser.rb +47 -24
- data/lib/bolt/catalog.rb +4 -2
- data/lib/bolt/cli.rb +97 -78
- data/lib/bolt/config.rb +46 -24
- data/lib/bolt/config/options.rb +9 -6
- data/lib/bolt/executor.rb +10 -8
- data/lib/bolt/inventory.rb +8 -1
- data/lib/bolt/inventory/group.rb +4 -4
- data/lib/bolt/inventory/inventory.rb +1 -1
- data/lib/bolt/inventory/target.rb +1 -1
- data/lib/bolt/logger.rb +12 -6
- data/lib/bolt/outputter.rb +56 -0
- data/lib/bolt/outputter/human.rb +10 -9
- data/lib/bolt/outputter/json.rb +11 -4
- data/lib/bolt/outputter/logger.rb +3 -3
- data/lib/bolt/outputter/rainbow.rb +15 -0
- data/lib/bolt/pal.rb +9 -19
- data/lib/bolt/pal/yaml_plan/evaluator.rb +2 -2
- data/lib/bolt/pal/yaml_plan/transpiler.rb +11 -3
- data/lib/bolt/plugin/prompt.rb +3 -3
- data/lib/bolt/plugin/puppetdb.rb +1 -1
- data/lib/bolt/project.rb +32 -19
- data/lib/bolt/project_migrate.rb +138 -0
- data/lib/bolt/puppetdb/client.rb +1 -1
- data/lib/bolt/puppetdb/config.rb +1 -1
- data/lib/bolt/r10k_log_proxy.rb +1 -1
- data/lib/bolt/rerun.rb +1 -1
- data/lib/bolt/result.rb +8 -0
- data/lib/bolt/shell.rb +1 -1
- data/lib/bolt/shell/bash.rb +7 -7
- data/lib/bolt/task.rb +1 -1
- data/lib/bolt/transport/base.rb +1 -1
- data/lib/bolt/transport/docker/connection.rb +10 -10
- data/lib/bolt/transport/local/connection.rb +3 -3
- data/lib/bolt/transport/orch.rb +3 -3
- data/lib/bolt/transport/ssh.rb +1 -1
- data/lib/bolt/transport/ssh/connection.rb +6 -6
- data/lib/bolt/transport/ssh/exec_connection.rb +5 -5
- data/lib/bolt/transport/winrm.rb +1 -1
- data/lib/bolt/transport/winrm/connection.rb +9 -9
- data/lib/bolt/util.rb +2 -2
- data/lib/bolt/util/puppet_log_level.rb +4 -3
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/base_config.rb +1 -1
- data/lib/bolt_server/file_cache.rb +1 -1
- data/lib/bolt_server/pe/pal.rb +1 -1
- data/lib/bolt_server/transport_app.rb +76 -0
- data/lib/bolt_spec/plans.rb +1 -1
- data/lib/bolt_spec/plans/action_stubs.rb +1 -1
- data/lib/bolt_spec/run.rb +3 -0
- data/libexec/apply_catalog.rb +2 -2
- data/libexec/bolt_catalog +1 -1
- data/libexec/custom_facts.rb +1 -1
- data/libexec/query_resources.rb +1 -1
- metadata +9 -12
@@ -7,7 +7,7 @@ module Bolt
|
|
7
7
|
class YamlPlan
|
8
8
|
class Evaluator
|
9
9
|
def initialize(analytics = Bolt::Analytics::NoopClient.new)
|
10
|
-
@logger =
|
10
|
+
@logger = Bolt::Logger.logger(self)
|
11
11
|
@analytics = analytics
|
12
12
|
@evaluator = Puppet::Pops::Parser::EvaluatingParser.new
|
13
13
|
end
|
@@ -109,7 +109,7 @@ module Bolt
|
|
109
109
|
end
|
110
110
|
|
111
111
|
def message_step(scope, step)
|
112
|
-
scope.call_function('out::message', step['message'])
|
112
|
+
scope.call_function('out::message', [step['message']])
|
113
113
|
end
|
114
114
|
|
115
115
|
def generate_manifest(resources)
|
@@ -21,10 +21,18 @@ module Bolt
|
|
21
21
|
validate_path
|
22
22
|
|
23
23
|
plan_object = parse_plan
|
24
|
+
param_descriptions = plan_object.parameters.map do |param|
|
25
|
+
str = String.new("# @param #{param.name}")
|
26
|
+
str << " #{param.description}" if param.description
|
27
|
+
str
|
28
|
+
end.join("\n")
|
24
29
|
|
25
|
-
plan_string = String.new(
|
26
|
-
|
27
|
-
|
30
|
+
plan_string = String.new('')
|
31
|
+
plan_string << "# #{plan_object.description}\n" if plan_object.description
|
32
|
+
plan_string << "# WARNING: This is an autogenerated plan. It may not behave as expected.\n"
|
33
|
+
plan_string << "#{param_descriptions}\n" unless param_descriptions.empty?
|
34
|
+
|
35
|
+
plan_string << "plan #{plan_object.name}("
|
28
36
|
# Parameters are Bolt::PAL::YamlPlan::Parameter
|
29
37
|
plan_object.parameters&.each_with_index do |param, i|
|
30
38
|
plan_string << param.transpile
|
data/lib/bolt/plugin/prompt.rb
CHANGED
@@ -18,9 +18,9 @@ module Bolt
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def resolve_reference(opts)
|
21
|
-
|
22
|
-
value =
|
23
|
-
|
21
|
+
$stderr.print("#{opts['message']}: ")
|
22
|
+
value = $stdin.noecho(&:gets).to_s.chomp
|
23
|
+
$stderr.puts
|
24
24
|
|
25
25
|
value
|
26
26
|
end
|
data/lib/bolt/plugin/puppetdb.rb
CHANGED
@@ -19,7 +19,7 @@ module Bolt
|
|
19
19
|
def initialize(config:, context:)
|
20
20
|
pdb_config = Bolt::PuppetDB::Config.load_config(config, context.boltdir)
|
21
21
|
@puppetdb_client = Bolt::PuppetDB::Client.new(pdb_config)
|
22
|
-
@logger =
|
22
|
+
@logger = Bolt::Logger.logger(self)
|
23
23
|
end
|
24
24
|
|
25
25
|
def name
|
data/lib/bolt/project.rb
CHANGED
@@ -17,35 +17,37 @@ module Bolt
|
|
17
17
|
}.freeze
|
18
18
|
|
19
19
|
attr_reader :path, :data, :config_file, :inventory_file, :modulepath, :hiera_config,
|
20
|
-
:puppetfile, :rerunfile, :type, :resource_types, :
|
20
|
+
:puppetfile, :rerunfile, :type, :resource_types, :logs, :project_file,
|
21
21
|
:deprecations, :downloads, :plans_path
|
22
22
|
|
23
|
-
def self.default_project
|
24
|
-
create_project(File.expand_path(File.join('~', '.puppetlabs', 'bolt')), 'user')
|
23
|
+
def self.default_project(logs = [])
|
24
|
+
create_project(File.expand_path(File.join('~', '.puppetlabs', 'bolt')), 'user', logs)
|
25
25
|
# If homedir isn't defined use the system config path
|
26
26
|
rescue ArgumentError
|
27
|
-
create_project(Bolt::Config.system_path, 'system')
|
27
|
+
create_project(Bolt::Config.system_path, 'system', logs)
|
28
28
|
end
|
29
29
|
|
30
30
|
# Search recursively up the directory hierarchy for the Project. Look for a
|
31
31
|
# directory called Boltdir or a file called bolt.yaml (for a control repo
|
32
32
|
# type Project). Otherwise, repeat the check on each directory up the
|
33
33
|
# hierarchy, falling back to the default if we reach the root.
|
34
|
-
def self.find_boltdir(dir)
|
34
|
+
def self.find_boltdir(dir, logs = [])
|
35
35
|
dir = Pathname.new(dir)
|
36
36
|
|
37
37
|
if (dir + BOLTDIR_NAME).directory?
|
38
|
-
create_project(dir + BOLTDIR_NAME, 'embedded')
|
38
|
+
create_project(dir + BOLTDIR_NAME, 'embedded', logs)
|
39
39
|
elsif (dir + 'bolt.yaml').file? || (dir + 'bolt-project.yaml').file?
|
40
|
-
create_project(dir, 'local')
|
40
|
+
create_project(dir, 'local', logs)
|
41
41
|
elsif dir.root?
|
42
|
-
default_project
|
42
|
+
default_project(logs)
|
43
43
|
else
|
44
|
-
|
44
|
+
logs << { debug: "Did not detect Boltdir, bolt.yaml, or bolt-project.yaml at '#{dir}'. "\
|
45
|
+
"This directory won't be loaded as a project." }
|
46
|
+
find_boltdir(dir.parent, logs)
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
|
-
def self.create_project(path, type = 'option')
|
50
|
+
def self.create_project(path, type = 'option', logs = [])
|
49
51
|
fullpath = Pathname.new(path).expand_path
|
50
52
|
|
51
53
|
if !Bolt::Util.windows? && type != 'environment' && fullpath.world_writable?
|
@@ -58,15 +60,18 @@ module Bolt
|
|
58
60
|
|
59
61
|
project_file = File.join(fullpath, 'bolt-project.yaml')
|
60
62
|
data = Bolt::Util.read_optional_yaml_hash(File.expand_path(project_file), 'project')
|
61
|
-
|
63
|
+
default = type =~ /user|system/ ? 'default ' : ''
|
64
|
+
exist = File.exist?(File.expand_path(project_file))
|
65
|
+
logs << { info: "Loaded #{default}project from '#{fullpath}'" } if exist
|
66
|
+
new(data, path, type, logs)
|
62
67
|
end
|
63
68
|
|
64
|
-
def initialize(raw_data, path, type = 'option')
|
69
|
+
def initialize(raw_data, path, type = 'option', logs = [])
|
65
70
|
@path = Pathname.new(path).expand_path
|
66
71
|
|
67
72
|
@project_file = @path + 'bolt-project.yaml'
|
68
73
|
|
69
|
-
@
|
74
|
+
@logs = logs
|
70
75
|
@deprecations = []
|
71
76
|
if (@path + 'bolt.yaml').file? && project_file?
|
72
77
|
msg = "Project-level configuration in bolt.yaml is deprecated if using bolt-project.yaml. "\
|
@@ -88,7 +93,7 @@ module Bolt
|
|
88
93
|
tc = Bolt::Config::INVENTORY_OPTIONS.keys & raw_data.keys
|
89
94
|
if tc.any?
|
90
95
|
msg = "Transport configuration isn't supported in bolt-project.yaml. Ignoring keys #{tc}"
|
91
|
-
@
|
96
|
+
@logs << { warn: msg }
|
92
97
|
end
|
93
98
|
|
94
99
|
@data = raw_data.reject { |k, _| Bolt::Config::INVENTORY_OPTIONS.include?(k) }
|
@@ -98,7 +103,7 @@ module Bolt
|
|
98
103
|
@config_file = if (Bolt::Config::BOLT_OPTIONS & @data.keys).any?
|
99
104
|
if (@path + 'bolt.yaml').file?
|
100
105
|
msg = "bolt-project.yaml contains valid config keys, bolt.yaml will be ignored"
|
101
|
-
@
|
106
|
+
@logs << { warn: msg }
|
102
107
|
end
|
103
108
|
@project_file
|
104
109
|
else
|
@@ -114,7 +119,9 @@ module Bolt
|
|
114
119
|
# This API is used to prepend the project as a module to Puppet's internal
|
115
120
|
# module_references list. CHANGE AT YOUR OWN RISK
|
116
121
|
def to_h
|
117
|
-
{ path: @path.to_s,
|
122
|
+
{ path: @path.to_s,
|
123
|
+
name: name,
|
124
|
+
load_as_module?: load_as_module? }
|
118
125
|
end
|
119
126
|
|
120
127
|
def eql?(other)
|
@@ -126,6 +133,10 @@ module Bolt
|
|
126
133
|
@project_file.file?
|
127
134
|
end
|
128
135
|
|
136
|
+
def load_as_module?
|
137
|
+
!name.nil?
|
138
|
+
end
|
139
|
+
|
129
140
|
def name
|
130
141
|
@data['name']
|
131
142
|
end
|
@@ -141,15 +152,17 @@ module Bolt
|
|
141
152
|
def validate
|
142
153
|
if name
|
143
154
|
if name !~ Bolt::Module::MODULE_NAME_REGEX
|
144
|
-
raise Bolt::ValidationError,
|
145
|
-
|
155
|
+
raise Bolt::ValidationError, <<~ERROR_STRING
|
156
|
+
Invalid project name '#{name}' in bolt-project.yaml; project name must begin with a lowercase letter
|
157
|
+
and can include lowercase letters, numbers, and underscores.
|
158
|
+
ERROR_STRING
|
146
159
|
elsif Dir.children(Bolt::PAL::BOLTLIB_PATH).include?(name)
|
147
160
|
raise Bolt::ValidationError, "The project '#{name}' will not be loaded. The project name conflicts "\
|
148
161
|
"with a built-in Bolt module of the same name."
|
149
162
|
end
|
150
163
|
else
|
151
164
|
message = "No project name is specified in bolt-project.yaml. Project-level content will not be available."
|
152
|
-
@
|
165
|
+
@logs << { warn: message }
|
153
166
|
end
|
154
167
|
|
155
168
|
%w[tasks plans].each do |conf|
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bolt
|
4
|
+
class ProjectMigrate
|
5
|
+
attr_reader :path, :project_file, :backup_dir, :outputter, :inventory_file, :config_file
|
6
|
+
|
7
|
+
# This init mostly makes testing easier
|
8
|
+
def initialize(path, outputter, configured_inventory = nil)
|
9
|
+
@path = Pathname.new(path).expand_path
|
10
|
+
@project_file = @path + 'bolt-project.yaml'
|
11
|
+
@config_file = @path + 'bolt.yaml'
|
12
|
+
@backup_dir = @path + '.bolt-bak'
|
13
|
+
@inventory_file = configured_inventory || @path + 'inventory.yaml'
|
14
|
+
@outputter = outputter
|
15
|
+
end
|
16
|
+
|
17
|
+
def migrate_project
|
18
|
+
inv_ok = inventory_1_to_2(inventory_file, outputter) if inventory_file.file?
|
19
|
+
config_ok = bolt_yaml_to_bolt_project(inventory_file, outputter)
|
20
|
+
inv_ok && config_ok ? 0 : 1
|
21
|
+
end
|
22
|
+
|
23
|
+
# This could be made public and used elsewhere if the need arises
|
24
|
+
private def backup_file(origin_path)
|
25
|
+
unless File.exist?(origin_path)
|
26
|
+
outputter.print_message "Could not find file #{origin_path}, skipping backup."
|
27
|
+
return
|
28
|
+
end
|
29
|
+
|
30
|
+
date = Time.new.strftime("%Y%m%d_%H%M%S%L")
|
31
|
+
FileUtils.mkdir_p(backup_dir)
|
32
|
+
|
33
|
+
filename = File.basename(origin_path)
|
34
|
+
backup_path = File.join(backup_dir, "#{filename}.#{date}.bak")
|
35
|
+
|
36
|
+
outputter.print_message "Backing up #{filename} from #{origin_path} to #{backup_path}"
|
37
|
+
|
38
|
+
begin
|
39
|
+
FileUtils.cp(origin_path, backup_path)
|
40
|
+
rescue StandardError => e
|
41
|
+
raise Bolt::FileError.new("#{e.message}; unable to create backup of #{filename}.", origin_path)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private def bolt_yaml_to_bolt_project(inventory_file, outputter)
|
46
|
+
# If bolt-project.yaml already exists
|
47
|
+
if project_file.file?
|
48
|
+
outputter.print_message "bolt-project.yaml already exists in Bolt "\
|
49
|
+
"project at #{path}. Skipping project file update."
|
50
|
+
|
51
|
+
# If bolt.yaml doesn't exist
|
52
|
+
elsif !config_file.file?
|
53
|
+
outputter.print_message "Could not find bolt.yaml in project at "\
|
54
|
+
"#{path}. Skipping project file update."
|
55
|
+
|
56
|
+
else
|
57
|
+
config_data = Bolt::Util.read_optional_yaml_hash(config_file, 'config')
|
58
|
+
transport_data, project_data = config_data.partition do |k, _|
|
59
|
+
Bolt::Config::INVENTORY_OPTIONS.keys.include?(k)
|
60
|
+
end.map(&:to_h)
|
61
|
+
|
62
|
+
if transport_data.any?
|
63
|
+
if File.exist?(inventory_file)
|
64
|
+
inventory_data = Bolt::Util.read_yaml_hash(inventory_file, 'inventory')
|
65
|
+
merged = Bolt::Util.deep_merge(transport_data, inventory_data['config'] || {})
|
66
|
+
inventory_data['config'] = merged
|
67
|
+
backup_file(inventory_file)
|
68
|
+
else
|
69
|
+
FileUtils.touch(inventory_file)
|
70
|
+
inventory_data = { 'config' => transport_data }
|
71
|
+
end
|
72
|
+
|
73
|
+
backup_file(config_file)
|
74
|
+
|
75
|
+
begin
|
76
|
+
outputter.print_message "Moving transportation configuration options "\
|
77
|
+
"'#{transport_data.keys.join(', ')}' from bolt.yaml to inventory.yaml"
|
78
|
+
File.write(inventory_file, inventory_data.to_yaml)
|
79
|
+
File.write(config_file, project_data.to_yaml)
|
80
|
+
rescue StandardError => e
|
81
|
+
raise Bolt::FileError.new("#{e.message}; unable to write inventory.", inventory_file)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
outputter.print_message "Renaming bolt.yaml to bolt-project.yaml"
|
86
|
+
FileUtils.mv(config_file, project_file)
|
87
|
+
outputter.print_message "Successfully updated project. Please add a "\
|
88
|
+
"'name' key to bolt-project.yaml to use project-level tasks and plans. "\
|
89
|
+
"Learn more about projects by running 'bolt guide project'."
|
90
|
+
# If nothing errored, this succeeded
|
91
|
+
true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private def inventory_1_to_2(inventory_file, outputter)
|
96
|
+
data = Bolt::Util.read_yaml_hash(inventory_file, 'inventory')
|
97
|
+
data.delete('version') if data['version'] != 2
|
98
|
+
migrated = migrate_group(data)
|
99
|
+
|
100
|
+
ok = if migrated
|
101
|
+
backup_file(inventory_file)
|
102
|
+
File.write(inventory_file, data.to_yaml)
|
103
|
+
end
|
104
|
+
|
105
|
+
result = if migrated && ok
|
106
|
+
"Successfully migrated Bolt inventory to the latest version."
|
107
|
+
elsif !migrated
|
108
|
+
"Bolt inventory is already on the latest version. Skipping inventory update."
|
109
|
+
else
|
110
|
+
"Could not migrate Bolt inventory to the latest version. See "\
|
111
|
+
"https://puppet.com/docs/bolt/latest/inventory_file_v2.html to manually update."
|
112
|
+
end
|
113
|
+
outputter.print_message(result)
|
114
|
+
ok
|
115
|
+
end
|
116
|
+
|
117
|
+
# Walks an inventory hash and replaces all 'nodes' keys with 'targets' keys
|
118
|
+
# and all 'name' keys nested in a 'targets' hash with 'uri' keys. Data is
|
119
|
+
# modified in place.
|
120
|
+
private def migrate_group(group)
|
121
|
+
migrated = false
|
122
|
+
if group.key?('nodes')
|
123
|
+
migrated = true
|
124
|
+
targets = group['nodes'].map do |target|
|
125
|
+
target['uri'] = target.delete('name') if target.is_a?(Hash)
|
126
|
+
target
|
127
|
+
end
|
128
|
+
group.delete('nodes')
|
129
|
+
group['targets'] = targets
|
130
|
+
end
|
131
|
+
(group['groups'] || []).each do |subgroup|
|
132
|
+
migrated_group = migrate_group(subgroup)
|
133
|
+
migrated ||= migrated_group
|
134
|
+
end
|
135
|
+
migrated
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
data/lib/bolt/puppetdb/client.rb
CHANGED
data/lib/bolt/puppetdb/config.rb
CHANGED
@@ -35,7 +35,7 @@ module Bolt
|
|
35
35
|
begin
|
36
36
|
config = JSON.parse(File.read(filepath)) if filepath
|
37
37
|
rescue StandardError => e
|
38
|
-
|
38
|
+
Bolt::Logger.logger(self).error("Could not load puppetdb.conf from #{filepath}: #{e.message}")
|
39
39
|
end
|
40
40
|
|
41
41
|
config = config.fetch('puppetdb', {})
|
data/lib/bolt/r10k_log_proxy.rb
CHANGED
data/lib/bolt/rerun.rb
CHANGED
data/lib/bolt/result.rb
CHANGED
@@ -65,6 +65,10 @@ module Bolt
|
|
65
65
|
'msg' => msg,
|
66
66
|
'details' => { 'exit_code' => exit_code } }
|
67
67
|
end
|
68
|
+
|
69
|
+
if value.key?('_sensitive')
|
70
|
+
value['_sensitive'] = Puppet::Pops::Types::PSensitiveType::Sensitive.new(value['_sensitive'])
|
71
|
+
end
|
68
72
|
new(target, value: value, action: 'task', object: task)
|
69
73
|
end
|
70
74
|
|
@@ -205,5 +209,9 @@ module Bolt
|
|
205
209
|
|
206
210
|
end
|
207
211
|
end
|
212
|
+
|
213
|
+
def sensitive
|
214
|
+
value['_sensitive']
|
215
|
+
end
|
208
216
|
end
|
209
217
|
end
|
data/lib/bolt/shell.rb
CHANGED
data/lib/bolt/shell/bash.rb
CHANGED
@@ -103,7 +103,7 @@ module Bolt
|
|
103
103
|
" using '#{execute_options[:interpreter]}' interpreter"
|
104
104
|
end
|
105
105
|
# log the arguments with sensitive data redacted, do NOT log unwrapped_arguments
|
106
|
-
logger.
|
106
|
+
logger.trace("Running '#{executable}' with #{arguments.to_json}#{interpreter_debug}")
|
107
107
|
# unpack any Sensitive data
|
108
108
|
arguments = unwrap_sensitive_args(arguments)
|
109
109
|
|
@@ -203,13 +203,13 @@ module Bolt
|
|
203
203
|
|
204
204
|
def handle_sudo_errors(err)
|
205
205
|
if err =~ /^#{conn.user} is not in the sudoers file\./
|
206
|
-
@logger.
|
206
|
+
@logger.trace { err }
|
207
207
|
raise Bolt::Node::EscalateError.new(
|
208
208
|
"User #{conn.user} does not have sudo permission on #{target}",
|
209
209
|
'SUDO_DENIED'
|
210
210
|
)
|
211
211
|
elsif err =~ /^Sorry, try again\./
|
212
|
-
@logger.
|
212
|
+
@logger.trace { err }
|
213
213
|
raise Bolt::Node::EscalateError.new(
|
214
214
|
"Sudo password for user #{conn.user} not recognized on #{target}",
|
215
215
|
'BAD_PASSWORD'
|
@@ -351,7 +351,7 @@ module Bolt
|
|
351
351
|
|
352
352
|
command_str = [sudo_str, env_decl, command_str].compact.join(' ')
|
353
353
|
|
354
|
-
@logger.
|
354
|
+
@logger.trace { "Executing `#{command_str}`" }
|
355
355
|
|
356
356
|
in_buffer = if !use_sudo && options[:stdin]
|
357
357
|
String.new(options[:stdin], encoding: 'binary')
|
@@ -431,16 +431,16 @@ module Bolt
|
|
431
431
|
result_output.exit_code = t.value.respond_to?(:exitstatus) ? t.value.exitstatus : t.value
|
432
432
|
|
433
433
|
if result_output.exit_code == 0
|
434
|
-
@logger.
|
434
|
+
@logger.trace { "Command `#{command_str}` returned successfully" }
|
435
435
|
else
|
436
|
-
@logger.
|
436
|
+
@logger.trace { "Command #{command_str} failed with exit code #{result_output.exit_code}" }
|
437
437
|
end
|
438
438
|
result_output
|
439
439
|
rescue StandardError
|
440
440
|
# Ensure we close stdin and kill the child process
|
441
441
|
inp&.close
|
442
442
|
t&.terminate if t&.alive?
|
443
|
-
@logger.
|
443
|
+
@logger.trace { "Command aborted" }
|
444
444
|
raise
|
445
445
|
end
|
446
446
|
|