bolt 2.34.0 → 2.40.1
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/applyresult.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/catch_errors.rb +1 -3
- data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +17 -6
- data/bolt-modules/boltlib/lib/puppet/functions/parallelize.rb +56 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +24 -6
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +27 -8
- data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +21 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +18 -1
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +24 -6
- data/lib/bolt/analytics.rb +27 -8
- data/lib/bolt/apply_result.rb +3 -3
- data/lib/bolt/bolt_option_parser.rb +45 -18
- data/lib/bolt/cli.rb +98 -116
- data/lib/bolt/config.rb +184 -80
- data/lib/bolt/config/options.rb +148 -87
- data/lib/bolt/config/transport/base.rb +10 -19
- data/lib/bolt/config/transport/local.rb +1 -7
- data/lib/bolt/config/transport/options.rb +12 -69
- data/lib/bolt/config/transport/ssh.rb +8 -19
- data/lib/bolt/error.rb +24 -0
- data/lib/bolt/executor.rb +92 -18
- data/lib/bolt/inventory.rb +25 -0
- data/lib/bolt/inventory/group.rb +0 -8
- data/lib/bolt/inventory/options.rb +130 -0
- data/lib/bolt/inventory/target.rb +10 -11
- data/lib/bolt/module_installer.rb +21 -13
- data/lib/bolt/module_installer/resolver.rb +1 -1
- data/lib/bolt/outputter.rb +19 -5
- data/lib/bolt/outputter/human.rb +22 -3
- data/lib/bolt/outputter/json.rb +1 -1
- data/lib/bolt/outputter/logger.rb +1 -1
- data/lib/bolt/outputter/rainbow.rb +13 -2
- data/lib/bolt/pal.rb +18 -6
- data/lib/bolt/pal/yaml_plan.rb +7 -0
- data/lib/bolt/plugin.rb +41 -12
- data/lib/bolt/plugin/cache.rb +76 -0
- data/lib/bolt/plugin/module.rb +4 -4
- data/lib/bolt/plugin/puppetdb.rb +1 -1
- data/lib/bolt/project.rb +59 -40
- data/lib/bolt/project_manager.rb +201 -0
- data/lib/bolt/{project_migrator/config.rb → project_manager/config_migrator.rb} +49 -4
- data/lib/bolt/{project_migrator/inventory.rb → project_manager/inventory_migrator.rb} +3 -3
- data/lib/bolt/{project_migrator/base.rb → project_manager/migrator.rb} +2 -2
- data/lib/bolt/{project_migrator/modules.rb → project_manager/module_migrator.rb} +5 -3
- data/lib/bolt/puppetdb/client.rb +11 -2
- data/lib/bolt/puppetdb/config.rb +4 -3
- data/lib/bolt/rerun.rb +1 -5
- data/lib/bolt/shell/bash.rb +8 -2
- data/lib/bolt/shell/powershell.rb +21 -3
- data/lib/bolt/target.rb +4 -0
- data/lib/bolt/task/run.rb +1 -1
- data/lib/bolt/transport/local.rb +13 -0
- data/lib/bolt/transport/orch.rb +0 -5
- data/lib/bolt/transport/orch/connection.rb +10 -3
- data/lib/bolt/transport/ssh/exec_connection.rb +6 -2
- data/lib/bolt/util.rb +36 -7
- data/lib/bolt/validator.rb +227 -0
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt/yarn.rb +23 -0
- data/lib/bolt_server/base_config.rb +3 -1
- data/lib/bolt_server/config.rb +3 -1
- data/lib/bolt_server/plugin.rb +13 -0
- data/lib/bolt_server/plugin/puppet_connect_data.rb +37 -0
- data/lib/bolt_server/schemas/connect-data.json +22 -0
- data/lib/bolt_server/schemas/partials/task.json +2 -2
- data/lib/bolt_server/transport_app.rb +82 -23
- data/lib/bolt_spec/plans/mock_executor.rb +4 -1
- data/libexec/apply_catalog.rb +1 -1
- data/libexec/custom_facts.rb +1 -1
- data/libexec/query_resources.rb +1 -1
- metadata +22 -14
- data/lib/bolt/project_migrator.rb +0 -80
@@ -0,0 +1,201 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/project_manager/config_migrator'
|
4
|
+
require 'bolt/project_manager/inventory_migrator'
|
5
|
+
require 'bolt/project_manager/module_migrator'
|
6
|
+
|
7
|
+
module Bolt
|
8
|
+
class ProjectManager
|
9
|
+
INVENTORY_TEMPLATE = <<~INVENTORY
|
10
|
+
# This is an example inventory.yaml
|
11
|
+
# To read more about inventory files, see https://pup.pt/bolt-inventory
|
12
|
+
#
|
13
|
+
# groups:
|
14
|
+
# - name: linux
|
15
|
+
# targets:
|
16
|
+
# - target1.example.com
|
17
|
+
# - target2.example.com
|
18
|
+
# config:
|
19
|
+
# transport: ssh
|
20
|
+
# ssh:
|
21
|
+
# private-key: /path/to/private_key.pem
|
22
|
+
# - name: windows
|
23
|
+
# targets:
|
24
|
+
# - name: win1
|
25
|
+
# uri: target3.example.com
|
26
|
+
# - name: win2
|
27
|
+
# uri: target4.example.com
|
28
|
+
# config:
|
29
|
+
# transport: winrm
|
30
|
+
# config:
|
31
|
+
# ssh:
|
32
|
+
# host-key-check: false
|
33
|
+
# winrm:
|
34
|
+
# user: Administrator
|
35
|
+
# password: Bolt!
|
36
|
+
# ssl: false
|
37
|
+
INVENTORY
|
38
|
+
|
39
|
+
def initialize(config, outputter, pal)
|
40
|
+
@config = config
|
41
|
+
@outputter = outputter
|
42
|
+
@pal = pal
|
43
|
+
end
|
44
|
+
|
45
|
+
# Creates a new project at the specified directory.
|
46
|
+
#
|
47
|
+
def create(path, name, modules)
|
48
|
+
require 'bolt/module_installer'
|
49
|
+
|
50
|
+
project = Pathname.new(File.expand_path(path))
|
51
|
+
old_config = project + 'bolt.yaml'
|
52
|
+
config = project + 'bolt-project.yaml'
|
53
|
+
puppetfile = project + 'Puppetfile'
|
54
|
+
moduledir = project + '.modules'
|
55
|
+
inventoryfile = project + 'inventory.yaml'
|
56
|
+
project_name = name || File.basename(project)
|
57
|
+
|
58
|
+
if config.exist?
|
59
|
+
if modules
|
60
|
+
command = Bolt::Util.powershell? ? 'Add-BoltModule -Module' : 'bolt module add'
|
61
|
+
raise Bolt::Error.new(
|
62
|
+
"Found existing project directory with #{config.basename} at #{project}, "\
|
63
|
+
"unable to initialize project with modules. To add modules to the project, "\
|
64
|
+
"run '#{command} <module>' instead.",
|
65
|
+
'bolt/existing-project-error'
|
66
|
+
)
|
67
|
+
else
|
68
|
+
raise Bolt::Error.new(
|
69
|
+
"Found existing project directory with #{config.basename} at #{project}, "\
|
70
|
+
"unable to initialize project.",
|
71
|
+
'bolt/existing-project-error'
|
72
|
+
)
|
73
|
+
end
|
74
|
+
elsif old_config.exist?
|
75
|
+
command = Bolt::Util.powershell? ? 'Update-BoltProject' : 'bolt project migrate'
|
76
|
+
raise Bolt::Error.new(
|
77
|
+
"Found existing project directory with #{old_config.basename} at #{project}, "\
|
78
|
+
"unable to initialize project. #{old_config.basename} is deprecated. To "\
|
79
|
+
"update the project to current best practices, run '#{command}'.",
|
80
|
+
'bolt/existing-project-error'
|
81
|
+
)
|
82
|
+
elsif modules && puppetfile.exist?
|
83
|
+
raise Bolt::Error.new(
|
84
|
+
"Found existing Puppetfile at #{puppetfile}, unable to initialize project "\
|
85
|
+
"with modules.",
|
86
|
+
'bolt/existing-puppetfile-error'
|
87
|
+
)
|
88
|
+
elsif project_name !~ Bolt::Module::MODULE_NAME_REGEX
|
89
|
+
if name
|
90
|
+
raise Bolt::ValidationError,
|
91
|
+
"The provided project name '#{project_name}' is invalid; project name must "\
|
92
|
+
"begin with a lowercase letter and can include lowercase letters, "\
|
93
|
+
"numbers, and underscores."
|
94
|
+
else
|
95
|
+
command = Bolt::Util.powershell? ? 'New-BoltProject -Name' : 'bolt project init'
|
96
|
+
raise Bolt::ValidationError,
|
97
|
+
"The current directory name '#{project_name}' is an invalid project name. "\
|
98
|
+
"Please specify a name using '#{command} <name>'."
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# If modules were specified, resolve and install first. We want to error
|
103
|
+
# early here and not initialize the project if the modules cannot be
|
104
|
+
# resolved and installed.
|
105
|
+
if modules
|
106
|
+
@outputter.start_spin
|
107
|
+
Bolt::ModuleInstaller.new(@outputter, @pal).install(modules, puppetfile, moduledir)
|
108
|
+
@outputter.stop_spin
|
109
|
+
end
|
110
|
+
|
111
|
+
data = { 'name' => project_name }
|
112
|
+
data['modules'] = modules || []
|
113
|
+
|
114
|
+
begin
|
115
|
+
File.write(config.to_path, data.to_yaml)
|
116
|
+
rescue StandardError => e
|
117
|
+
raise Bolt::FileError.new("Could not create bolt-project.yaml at #{project}: #{e.message}", nil)
|
118
|
+
end
|
119
|
+
|
120
|
+
unless inventoryfile.exist?
|
121
|
+
begin
|
122
|
+
File.write(inventoryfile.to_path, INVENTORY_TEMPLATE)
|
123
|
+
rescue StandardError => e
|
124
|
+
raise Bolt::FileError.new("Could not create inventory.yaml at #{project}: #{e.message}", nil)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
@outputter.print_message("Successfully created Bolt project at #{project}")
|
129
|
+
|
130
|
+
0
|
131
|
+
end
|
132
|
+
|
133
|
+
# Migrates a project to use the latest file versions and best practices.
|
134
|
+
#
|
135
|
+
def migrate
|
136
|
+
unless $stdin.tty?
|
137
|
+
raise Bolt::Error.new(
|
138
|
+
"stdin is not a tty, unable to migrate project",
|
139
|
+
'bolt/stdin-not-a-tty-error'
|
140
|
+
)
|
141
|
+
end
|
142
|
+
|
143
|
+
@outputter.print_message("Migrating project #{@config.project.path}\n\n")
|
144
|
+
|
145
|
+
@outputter.print_action_step(
|
146
|
+
"Migrating a Bolt project may make irreversible changes to the project's "\
|
147
|
+
"configuration and inventory files. Before continuing, make sure the "\
|
148
|
+
"project has a backup or uses a version control system."
|
149
|
+
)
|
150
|
+
|
151
|
+
return 0 unless Bolt::Util.prompt_yes_no("Continue with project migration?", @outputter)
|
152
|
+
|
153
|
+
@outputter.print_message('')
|
154
|
+
|
155
|
+
ok = migrate_inventory && migrate_config && migrate_modules
|
156
|
+
|
157
|
+
if ok
|
158
|
+
@outputter.print_message("Project successfully migrated")
|
159
|
+
else
|
160
|
+
@outputter.print_error("Project could not be migrated completely")
|
161
|
+
end
|
162
|
+
|
163
|
+
ok ? 0 : 1
|
164
|
+
end
|
165
|
+
|
166
|
+
# Migrates the project-level configuration file to the latest version.
|
167
|
+
#
|
168
|
+
private def migrate_config
|
169
|
+
migrator = ConfigMigrator.new(@outputter)
|
170
|
+
|
171
|
+
migrator.migrate(
|
172
|
+
@config.project.config_file,
|
173
|
+
@config.project.project_file,
|
174
|
+
@config.inventoryfile || @config.project.inventory_file,
|
175
|
+
@config.project.backup_dir
|
176
|
+
)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Migrates the inventory file to the latest version.
|
180
|
+
#
|
181
|
+
private def migrate_inventory
|
182
|
+
migrator = InventoryMigrator.new(@outputter)
|
183
|
+
|
184
|
+
migrator.migrate(
|
185
|
+
@config.inventoryfile || @config.project.inventory_file,
|
186
|
+
@config.project.backup_dir
|
187
|
+
)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Migrates the project's modules to use current best practices.
|
191
|
+
#
|
192
|
+
private def migrate_modules
|
193
|
+
migrator = ModuleMigrator.new(@outputter)
|
194
|
+
|
195
|
+
migrator.migrate(
|
196
|
+
@config.project,
|
197
|
+
@config.modulepath
|
198
|
+
)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -1,12 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'bolt/
|
3
|
+
require 'bolt/project_manager/migrator'
|
4
4
|
|
5
5
|
module Bolt
|
6
|
-
class
|
7
|
-
class
|
6
|
+
class ProjectManager
|
7
|
+
class ConfigMigrator < Migrator
|
8
8
|
def migrate(config_file, project_file, inventory_file, backup_dir)
|
9
|
-
bolt_yaml_to_bolt_project(config_file, project_file, inventory_file, backup_dir)
|
9
|
+
bolt_yaml_to_bolt_project(config_file, project_file, inventory_file, backup_dir) &&
|
10
|
+
update_options(project_file)
|
10
11
|
end
|
11
12
|
|
12
13
|
private def bolt_yaml_to_bolt_project(config_file, project_file, inventory_file, backup_dir)
|
@@ -63,6 +64,50 @@ module Bolt
|
|
63
64
|
|
64
65
|
true
|
65
66
|
end
|
67
|
+
|
68
|
+
private def update_options(project_file)
|
69
|
+
return true unless File.exist?(project_file)
|
70
|
+
|
71
|
+
@outputter.print_message("Updating project configuration options\n\n")
|
72
|
+
data = Bolt::Util.read_yaml_hash(project_file, 'config')
|
73
|
+
modified = false
|
74
|
+
|
75
|
+
# Keys to update. The first element is the old key, while the second is
|
76
|
+
# the key update it to.
|
77
|
+
to_update = [
|
78
|
+
%w[apply_settings apply-settings],
|
79
|
+
%w[puppetfile module-install],
|
80
|
+
%w[plugin_hooks plugin-hooks]
|
81
|
+
]
|
82
|
+
|
83
|
+
to_update.each do |old, new|
|
84
|
+
next unless data.key?(old)
|
85
|
+
|
86
|
+
if data.key?(new)
|
87
|
+
@outputter.print_action_step("Removing deprecated option '#{old}'")
|
88
|
+
data.delete(old)
|
89
|
+
else
|
90
|
+
@outputter.print_action_step("Updating deprecated option '#{old}' to '#{new}'")
|
91
|
+
data[new] = data.delete(old)
|
92
|
+
end
|
93
|
+
|
94
|
+
modified = true
|
95
|
+
end
|
96
|
+
|
97
|
+
if modified
|
98
|
+
begin
|
99
|
+
File.write(project_file, data.to_yaml)
|
100
|
+
rescue StandardError => e
|
101
|
+
raise Bolt::FileError.new("#{e.message}; unable to write config.", project_file)
|
102
|
+
end
|
103
|
+
|
104
|
+
@outputter.print_action_step("Successfully updated project configuration #{project_file}")
|
105
|
+
else
|
106
|
+
@outputter.print_action_step("Project configuration is up to date, nothing to do.")
|
107
|
+
end
|
108
|
+
|
109
|
+
true
|
110
|
+
end
|
66
111
|
end
|
67
112
|
end
|
68
113
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'bolt/
|
3
|
+
require 'bolt/project_manager/migrator'
|
4
4
|
|
5
5
|
module Bolt
|
6
|
-
class
|
7
|
-
class
|
6
|
+
class ProjectManager
|
7
|
+
class InventoryMigrator < Migrator
|
8
8
|
def migrate(inventory_file, backup_dir)
|
9
9
|
inventory1to2(inventory_file, backup_dir)
|
10
10
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'bolt/
|
3
|
+
require 'bolt/project_manager/migrator'
|
4
4
|
|
5
5
|
module Bolt
|
6
|
-
class
|
7
|
-
class
|
6
|
+
class ProjectManager
|
7
|
+
class ModuleMigrator < Migrator
|
8
8
|
def migrate(project, configured_modulepath)
|
9
9
|
return true unless project.modules.nil?
|
10
10
|
|
@@ -61,6 +61,7 @@ module Bolt
|
|
61
61
|
# Create specs to resolve from
|
62
62
|
specs = Bolt::ModuleInstaller::Specs.new(modules.map(&:to_hash))
|
63
63
|
|
64
|
+
@outputter.start_spin
|
64
65
|
# Attempt to resolve dependencies
|
65
66
|
begin
|
66
67
|
@outputter.print_message('')
|
@@ -72,6 +73,7 @@ module Bolt
|
|
72
73
|
end
|
73
74
|
|
74
75
|
migrate_managed_modules(puppetfile, puppetfile_path, managed_moduledir)
|
76
|
+
@outputter.stop_spin
|
75
77
|
|
76
78
|
# Move remaining modules to 'modules'
|
77
79
|
consolidate_modules(modulepath)
|
data/lib/bolt/puppetdb/client.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require 'json'
|
4
4
|
require 'logging'
|
5
|
-
require 'uri'
|
6
5
|
|
7
6
|
module Bolt
|
8
7
|
module PuppetDB
|
@@ -19,6 +18,7 @@ module Bolt
|
|
19
18
|
def query_certnames(query)
|
20
19
|
return [] unless query
|
21
20
|
|
21
|
+
@logger.debug("Querying certnames")
|
22
22
|
results = make_query(query)
|
23
23
|
|
24
24
|
if results&.first && !results.first&.key?('certname')
|
@@ -35,6 +35,8 @@ module Bolt
|
|
35
35
|
certnames.uniq!
|
36
36
|
name_query = certnames.map { |c| ["=", "certname", c] }
|
37
37
|
name_query.insert(0, "or")
|
38
|
+
|
39
|
+
@logger.debug("Querying certnames")
|
38
40
|
result = make_query(name_query, 'inventory')
|
39
41
|
|
40
42
|
result&.each_with_object({}) do |node, coll|
|
@@ -53,6 +55,8 @@ module Bolt
|
|
53
55
|
facts_query.insert(0, "or")
|
54
56
|
|
55
57
|
query = ['and', name_query, facts_query]
|
58
|
+
|
59
|
+
@logger.debug("Querying certnames")
|
56
60
|
result = make_query(query, 'fact-contents')
|
57
61
|
result.map! { |h| h.delete_if { |k, _v| %w[environment name].include?(k) } }
|
58
62
|
result.group_by { |c| c['certname'] }
|
@@ -64,11 +68,13 @@ module Bolt
|
|
64
68
|
url += "/#{path}" if path
|
65
69
|
|
66
70
|
begin
|
71
|
+
@logger.debug("Sending PuppetDB query to #{url}")
|
67
72
|
response = http_client.post(url, body: body, header: headers)
|
68
73
|
rescue StandardError => e
|
69
74
|
raise Bolt::PuppetDBFailoverError, "Failed to query PuppetDB: #{e}"
|
70
75
|
end
|
71
76
|
|
77
|
+
@logger.debug("Got response code #{response.code} from PuppetDB")
|
72
78
|
if response.code != 200
|
73
79
|
msg = "Failed to query PuppetDB: #{response.body}"
|
74
80
|
if response.code == 400
|
@@ -93,6 +99,7 @@ module Bolt
|
|
93
99
|
return @http if @http
|
94
100
|
# lazy-load expensive gem code
|
95
101
|
require 'httpclient'
|
102
|
+
@logger.trace("Creating HTTP Client")
|
96
103
|
@http = HTTPClient.new
|
97
104
|
@http.ssl_config.set_client_cert_file(@config.cert, @config.key) if @config.cert
|
98
105
|
@http.ssl_config.add_trust_ca(@config.cacert)
|
@@ -108,13 +115,15 @@ module Bolt
|
|
108
115
|
end
|
109
116
|
|
110
117
|
def uri
|
118
|
+
require 'addressable/uri'
|
119
|
+
|
111
120
|
@current_url ||= (@config.server_urls - @bad_urls).first
|
112
121
|
unless @current_url
|
113
122
|
msg = "Failed to connect to all PuppetDB server_urls: #{@config.server_urls.to_a.join(', ')}."
|
114
123
|
raise Bolt::PuppetDBError, msg
|
115
124
|
end
|
116
125
|
|
117
|
-
uri = URI.parse(@current_url)
|
126
|
+
uri = Addressable::URI.parse(@current_url)
|
118
127
|
uri.port ||= 8081
|
119
128
|
uri
|
120
129
|
end
|
data/lib/bolt/puppetdb/config.rb
CHANGED
@@ -18,8 +18,7 @@ module Bolt
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.default_windows_config
|
21
|
-
|
22
|
-
File.expand_path(File.join(Dir::COMMON_APPDATA, 'PuppetLabs/client-tools/puppetdb.conf'))
|
21
|
+
File.expand_path(File.join(ENV['ALLUSERSPROFILE'], 'PuppetLabs/client-tools/puppetdb.conf'))
|
23
22
|
end
|
24
23
|
|
25
24
|
def self.load_config(options, project_path = nil)
|
@@ -89,6 +88,8 @@ module Bolt
|
|
89
88
|
|
90
89
|
def uri
|
91
90
|
return @uri if @uri
|
91
|
+
require 'addressable/uri'
|
92
|
+
|
92
93
|
uri = case @settings['server_urls']
|
93
94
|
when String
|
94
95
|
@settings['server_urls']
|
@@ -100,7 +101,7 @@ module Bolt
|
|
100
101
|
raise Bolt::PuppetDBError, "server_urls must be a string or array"
|
101
102
|
end
|
102
103
|
|
103
|
-
@uri = URI.parse(uri)
|
104
|
+
@uri = Addressable::URI.parse(uri)
|
104
105
|
@uri.port ||= 8081
|
105
106
|
@uri
|
106
107
|
end
|
data/lib/bolt/rerun.rb
CHANGED
@@ -12,15 +12,11 @@ module Bolt
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def data
|
15
|
-
@data ||=
|
15
|
+
@data ||= Bolt::Util.read_json_file(@path, 'rerun')
|
16
16
|
unless @data.is_a?(Array) && @data.all? { |r| r['target'] && r['status'] }
|
17
17
|
raise Bolt::FileError.new("Missing data in rerun file: #{@path}", @path)
|
18
18
|
end
|
19
19
|
@data
|
20
|
-
rescue JSON::ParserError
|
21
|
-
raise Bolt::FileError.new("Could not parse rerun file: #{@path}", @path)
|
22
|
-
rescue IOError, SystemCallError
|
23
|
-
raise Bolt::FileError.new("Could not read rerun file: #{@path}", @path)
|
24
20
|
end
|
25
21
|
|
26
22
|
def get_targets(filter)
|
data/lib/bolt/shell/bash.rb
CHANGED
@@ -199,7 +199,7 @@ module Bolt
|
|
199
199
|
lines = buffer.split(/(?<=\n)/)
|
200
200
|
# handle_sudo will return the line if it is not a sudo prompt or error
|
201
201
|
lines.map! { |line| handle_sudo(inp, line, stdin) }
|
202
|
-
lines.join
|
202
|
+
lines.join
|
203
203
|
# If stream has reached EOF, no password prompt is expected
|
204
204
|
# return an empty string
|
205
205
|
rescue EOFError
|
@@ -436,8 +436,14 @@ module Bolt
|
|
436
436
|
result_output.stderr << read_streams[err]
|
437
437
|
result_output.exit_code = t.value.respond_to?(:exitstatus) ? t.value.exitstatus : t.value
|
438
438
|
|
439
|
-
|
439
|
+
case result_output.exit_code
|
440
|
+
when 0
|
440
441
|
@logger.trace { "Command `#{command_str}` returned successfully" }
|
442
|
+
when 126
|
443
|
+
msg = "\n\nThis may be caused by the default tmpdir being mounted "\
|
444
|
+
"using 'noexec'. See http://pup.pt/task-failure for details and workarounds."
|
445
|
+
result_output.stderr << msg
|
446
|
+
@logger.trace { "Command #{command_str} failed with exit code #{result_output.exit_code}" }
|
441
447
|
else
|
442
448
|
@logger.trace { "Command #{command_str} failed with exit code #{result_output.exit_code}" }
|
443
449
|
end
|