bolt 3.23.1 → 3.24.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/lib/bolt/application.rb +17 -10
- data/lib/bolt/config/transport/lxd.rb +9 -0
- data/lib/bolt/inventory/inventory.rb +30 -11
- data/lib/bolt/outputter/human.rb +2 -1
- data/lib/bolt/outputter/json.rb +3 -1
- data/lib/bolt/outputter/rainbow.rb +2 -1
- data/lib/bolt/transport/orch/connection.rb +2 -1
- data/lib/bolt/transport/winrm/connection.rb +18 -11
- data/lib/bolt/version.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ad3bbc9413aac278feeac8a7e31173bd065f0029fb211d7e1906c4803a4c390
|
4
|
+
data.tar.gz: 387d3a07844139eb29a1db06d1792acfdad6a09eab2b5576a9c4d34fdffdaca8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83c1685fc238f049dad5cf841ea55f37c57a1aa59d66ef420d754b78d7b0ba8cca4533accb2cfbe53915587f1832beb7cbf956501486de63e135933b57f5fa98
|
7
|
+
data.tar.gz: c6900fde1fd9234a603171c79c2f2b3a22b2d2661797b94bf0afd2050f4ef5cc32844562734d3e41bd94464806e1efaabaac346d6887773f547c801c33cc3d6f
|
data/Puppetfile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
forge
|
3
|
+
forge 'https://forge.puppetlabs.com'
|
4
4
|
|
5
5
|
moduledir File.join(File.dirname(__FILE__), 'modules')
|
6
6
|
|
@@ -26,7 +26,7 @@ mod 'puppetlabs-package', '2.2.0'
|
|
26
26
|
mod 'puppetlabs-powershell_task_helper', '0.1.0'
|
27
27
|
mod 'puppetlabs-puppet_conf', '1.3.0'
|
28
28
|
mod 'puppetlabs-python_task_helper', '0.5.0'
|
29
|
-
mod 'puppetlabs-reboot', '4.
|
29
|
+
mod 'puppetlabs-reboot', '4.2.0'
|
30
30
|
mod 'puppetlabs-ruby_task_helper', '0.6.1'
|
31
31
|
mod 'puppetlabs-ruby_plugin_helper', '0.2.0'
|
32
32
|
mod 'puppetlabs-stdlib', '8.2.0'
|
data/lib/bolt/application.rb
CHANGED
@@ -49,7 +49,7 @@ module Bolt
|
|
49
49
|
code
|
50
50
|
end
|
51
51
|
|
52
|
-
targets = inventory.get_targets(targets)
|
52
|
+
targets = inventory.get_targets(targets, ext_glob: true)
|
53
53
|
|
54
54
|
Puppet[:tasks] = false
|
55
55
|
ast = pal.parse_manifest(manifest_code, manifest)
|
@@ -90,7 +90,7 @@ module Bolt
|
|
90
90
|
# @return [Bolt::ResultSet]
|
91
91
|
#
|
92
92
|
def run_command(command, targets, env_vars: nil)
|
93
|
-
targets = inventory.get_targets(targets)
|
93
|
+
targets = inventory.get_targets(targets, ext_glob: true)
|
94
94
|
|
95
95
|
with_benchmark do
|
96
96
|
executor.run_command(targets, command, env_vars: env_vars)
|
@@ -106,7 +106,7 @@ module Bolt
|
|
106
106
|
#
|
107
107
|
def download_file(source, destination, targets)
|
108
108
|
destination = File.expand_path(destination, Dir.pwd)
|
109
|
-
targets = inventory.get_targets(targets)
|
109
|
+
targets = inventory.get_targets(targets, ext_glob: true)
|
110
110
|
|
111
111
|
with_benchmark do
|
112
112
|
executor.download_file(targets, source, destination)
|
@@ -122,7 +122,7 @@ module Bolt
|
|
122
122
|
#
|
123
123
|
def upload_file(source, destination, targets)
|
124
124
|
source = find_file(source)
|
125
|
-
targets = inventory.get_targets(targets)
|
125
|
+
targets = inventory.get_targets(targets, ext_glob: true)
|
126
126
|
|
127
127
|
Bolt::Util.validate_file('source file', source, true)
|
128
128
|
|
@@ -225,7 +225,7 @@ module Bolt
|
|
225
225
|
|
226
226
|
with_benchmark do
|
227
227
|
pal.lookup(key,
|
228
|
-
inventory.get_targets(targets),
|
228
|
+
inventory.get_targets(targets, ext_glob: true),
|
229
229
|
inventory,
|
230
230
|
executor,
|
231
231
|
plan_vars: vars)
|
@@ -351,6 +351,7 @@ module Bolt
|
|
351
351
|
# @return [Bolt::PlanResult]
|
352
352
|
#
|
353
353
|
def run_plan(plan, targets, params: {})
|
354
|
+
plan_params = pal.get_plan_info(plan)['parameters']
|
354
355
|
if targets && targets.any?
|
355
356
|
if params['nodes'] || params['targets']
|
356
357
|
key = params.include?('nodes') ? 'nodes' : 'targets'
|
@@ -360,7 +361,6 @@ module Bolt
|
|
360
361
|
"in the JSON data passed in the --params option"
|
361
362
|
end
|
362
363
|
|
363
|
-
plan_params = pal.get_plan_info(plan)['parameters']
|
364
364
|
target_param = plan_params.dig('targets', 'type') =~ /TargetSpec/
|
365
365
|
node_param = plan_params.include?('nodes')
|
366
366
|
|
@@ -375,13 +375,17 @@ module Bolt
|
|
375
375
|
end
|
376
376
|
end
|
377
377
|
|
378
|
-
|
378
|
+
sensitive_params = params.keys.select { |param| plan_params.dig(param, 'sensitive') }
|
379
|
+
|
380
|
+
plan_context = { plan_name: plan, params: params, sensitive: sensitive_params }
|
379
381
|
|
380
382
|
executor.start_plan(plan_context)
|
381
383
|
result = pal.run_plan(plan, params, executor, inventory, plugins.puppetdb_client)
|
382
384
|
executor.finish_plan(result)
|
383
385
|
|
384
386
|
result
|
387
|
+
rescue Bolt::Error => e
|
388
|
+
Bolt::PlanResult.new(e, 'failure')
|
385
389
|
end
|
386
390
|
|
387
391
|
# Show plan information.
|
@@ -620,7 +624,10 @@ module Bolt
|
|
620
624
|
Bolt::Util.validate_file('script', script)
|
621
625
|
|
622
626
|
with_benchmark do
|
623
|
-
executor.run_script(inventory.get_targets(targets
|
627
|
+
executor.run_script(inventory.get_targets(targets, ext_glob: true),
|
628
|
+
script,
|
629
|
+
arguments,
|
630
|
+
env_vars: env_vars)
|
624
631
|
end
|
625
632
|
end
|
626
633
|
|
@@ -676,7 +683,7 @@ module Bolt
|
|
676
683
|
# @return [Bolt::ResultSet]
|
677
684
|
#
|
678
685
|
def run_task(task, targets, params: {})
|
679
|
-
targets = inventory.get_targets(targets)
|
686
|
+
targets = inventory.get_targets(targets, ext_glob: true)
|
680
687
|
|
681
688
|
with_benchmark do
|
682
689
|
pal.run_task(task, targets, params, executor, inventory)
|
@@ -775,7 +782,7 @@ module Bolt
|
|
775
782
|
# Retrieve the known group and target names. This needs to be done before
|
776
783
|
# updating targets, as that will add adhoc targets to the inventory.
|
777
784
|
known_names = inventory.target_names
|
778
|
-
targets = inventory.get_targets(targets)
|
785
|
+
targets = inventory.get_targets(targets, ext_glob: true)
|
779
786
|
|
780
787
|
inventory_targets, adhoc_targets = targets.partition do |target|
|
781
788
|
known_names.include?(target.name)
|
@@ -9,6 +9,7 @@ module Bolt
|
|
9
9
|
class LXD < Base
|
10
10
|
OPTIONS = %w[
|
11
11
|
cleanup
|
12
|
+
interpreters
|
12
13
|
remote
|
13
14
|
tmpdir
|
14
15
|
].concat(RUN_AS_OPTIONS).sort.freeze
|
@@ -17,6 +18,14 @@ module Bolt
|
|
17
18
|
'cleanup' => true,
|
18
19
|
'remote' => 'local'
|
19
20
|
}.freeze
|
21
|
+
|
22
|
+
private def validate
|
23
|
+
super
|
24
|
+
|
25
|
+
if @config['interpreters']
|
26
|
+
@config['interpreters'] = normalize_interpreters(@config['interpreters'])
|
27
|
+
end
|
28
|
+
end
|
20
29
|
end
|
21
30
|
end
|
22
31
|
end
|
@@ -8,6 +8,12 @@ module Bolt
|
|
8
8
|
class Inventory
|
9
9
|
attr_reader :plugins, :source, :targets, :transport
|
10
10
|
|
11
|
+
# Getting targets from the inventory using '--targets' supports extended glob pattern
|
12
|
+
# matching. In this case, use the extended regex so Bolt only uses commas outside
|
13
|
+
# brackets and braces as delimiters.
|
14
|
+
EXTENDED_TARGET_REGEX = /[[:space:],]+(?=[^\]}]*(?:[\[{]|$))/.freeze
|
15
|
+
TARGET_REGEX = /[[:space:],]+/.freeze
|
16
|
+
|
11
17
|
class WildcardError < Bolt::Error
|
12
18
|
def initialize(target)
|
13
19
|
super("Found 0 targets matching wildcard pattern #{target}", 'bolt.inventory/wildcard-error')
|
@@ -85,8 +91,8 @@ module Bolt
|
|
85
91
|
# alias for analytics
|
86
92
|
alias node_names target_names
|
87
93
|
|
88
|
-
def get_targets(targets)
|
89
|
-
target_array = expand_targets(targets)
|
94
|
+
def get_targets(targets, ext_glob: false)
|
95
|
+
target_array = expand_targets(targets, ext_glob: ext_glob)
|
90
96
|
if target_array.is_a? Array
|
91
97
|
target_array.flatten.uniq(&:name)
|
92
98
|
else
|
@@ -107,20 +113,31 @@ module Bolt
|
|
107
113
|
groups.group_collect(target_name)
|
108
114
|
end
|
109
115
|
|
116
|
+
# Does a target match the glob-style wildcard?
|
117
|
+
# Ignore case; use extended globs ({a,b}) when running from the CLI.
|
118
|
+
def match_wildcard?(wildcard, target_name, ext_glob: false)
|
119
|
+
if ext_glob
|
120
|
+
File.fnmatch(wildcard, target_name, File::FNM_CASEFOLD | File::FNM_EXTGLOB)
|
121
|
+
else
|
122
|
+
regexp = Regexp.new("^#{Regexp.escape(wildcard).gsub('\*', '.*?')}$", Regexp::IGNORECASE)
|
123
|
+
target_name =~ regexp
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
110
127
|
# If target is a group name, expand it to the members of that group.
|
111
128
|
# Else match against targets in inventory by name or alias.
|
112
129
|
# If a wildcard string, error if no matches are found.
|
113
130
|
# Else fall back to [target] if no matches are found.
|
114
|
-
def resolve_name(target)
|
131
|
+
def resolve_name(target, ext_glob: false)
|
115
132
|
if (group = group_lookup[target])
|
116
133
|
group.all_targets
|
117
134
|
else
|
118
135
|
# Try to wildcard match targets in inventory
|
119
136
|
# Ignore case because hostnames are generally case-insensitive
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
137
|
+
targets = groups.all_targets.select { |targ| match_wildcard?(target, targ, ext_glob: ext_glob) }
|
138
|
+
targets += groups.target_aliases
|
139
|
+
.select { |tgt_alias, _| match_wildcard?(target, tgt_alias, ext_glob: ext_glob) }
|
140
|
+
.values
|
124
141
|
|
125
142
|
if targets.empty?
|
126
143
|
raise(WildcardError, target) if target.include?('*')
|
@@ -132,16 +149,18 @@ module Bolt
|
|
132
149
|
end
|
133
150
|
private :resolve_name
|
134
151
|
|
135
|
-
def expand_targets(targets)
|
152
|
+
def expand_targets(targets, ext_glob: false)
|
136
153
|
case targets
|
137
154
|
when Bolt::Target
|
138
155
|
targets
|
139
156
|
when Array
|
140
|
-
targets.map { |tish| expand_targets(tish) }
|
157
|
+
targets.map { |tish| expand_targets(tish, ext_glob: ext_glob) }
|
141
158
|
when String
|
142
159
|
# Expand a comma-separated list
|
143
|
-
|
144
|
-
|
160
|
+
# Regex magic below is required to workaround `{foo,bar}` glob syntax
|
161
|
+
regex = ext_glob ? EXTENDED_TARGET_REGEX : TARGET_REGEX
|
162
|
+
targets.split(regex).reject(&:empty?).map do |name|
|
163
|
+
ts = resolve_name(name, ext_glob: ext_glob)
|
145
164
|
ts.map do |t|
|
146
165
|
# If the target doesn't exist, evaluate it from the inventory.
|
147
166
|
# Then return a Bolt::Target.
|
data/lib/bolt/outputter/human.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative '../../bolt/container_result'
|
4
4
|
require_relative '../../bolt/pal'
|
5
|
+
require_relative '../../bolt/util/format'
|
5
6
|
|
6
7
|
module Bolt
|
7
8
|
class Outputter
|
@@ -890,7 +891,7 @@ module Bolt
|
|
890
891
|
end
|
891
892
|
|
892
893
|
def print_message(message)
|
893
|
-
@stream.puts(message)
|
894
|
+
@stream.puts(Bolt::Util::Format.stringify(message))
|
894
895
|
end
|
895
896
|
|
896
897
|
def print_error(message)
|
data/lib/bolt/outputter/json.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative '../../bolt/util/format'
|
4
|
+
|
3
5
|
module Bolt
|
4
6
|
class Outputter
|
5
7
|
class JSON < Bolt::Outputter
|
@@ -190,7 +192,7 @@ module Bolt
|
|
190
192
|
end
|
191
193
|
|
192
194
|
def print_message(message)
|
193
|
-
$stderr.puts(message)
|
195
|
+
$stderr.puts(Bolt::Util::Format.stringify(message))
|
194
196
|
end
|
195
197
|
alias print_error print_message
|
196
198
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../../bolt/pal'
|
4
|
+
require_relative '../../bolt/util/format'
|
4
5
|
|
5
6
|
module Bolt
|
6
7
|
class Outputter
|
@@ -110,7 +111,7 @@ module Bolt
|
|
110
111
|
end
|
111
112
|
|
112
113
|
def print_message(message)
|
113
|
-
@stream.puts colorize(:rainbow, message)
|
114
|
+
@stream.puts colorize(:rainbow, Bolt::Util::Format.stringify(message))
|
114
115
|
end
|
115
116
|
end
|
116
117
|
end
|
@@ -6,7 +6,7 @@ module Bolt
|
|
6
6
|
class Connection
|
7
7
|
attr_reader :logger, :key
|
8
8
|
|
9
|
-
CONTEXT_KEYS = Set.new(%i[plan_name description params]).freeze
|
9
|
+
CONTEXT_KEYS = Set.new(%i[plan_name description params sensitive]).freeze
|
10
10
|
|
11
11
|
def self.get_key(opts)
|
12
12
|
[
|
@@ -46,6 +46,7 @@ module Bolt
|
|
46
46
|
if plan_context
|
47
47
|
begin
|
48
48
|
opts = plan_context.select { |k, _| CONTEXT_KEYS.include? k }
|
49
|
+
opts[:params] = opts[:params].reject { |k, _| plan_context[:sensitive].include?(k) }
|
49
50
|
@client.command.plan_start(opts)['name']
|
50
51
|
rescue OrchestratorClient::ApiError => e
|
51
52
|
if e.code == '404'
|
@@ -53,9 +53,11 @@ module Bolt
|
|
53
53
|
@connection = ::WinRM::Connection.new(options)
|
54
54
|
@connection.logger = @transport_logger
|
55
55
|
|
56
|
-
@
|
57
|
-
|
58
|
-
|
56
|
+
@connection.shell(:powershell) do |session|
|
57
|
+
session.run('$PSVersionTable.PSVersion')
|
58
|
+
end
|
59
|
+
|
60
|
+
@logger.trace { "Opened connection" }
|
59
61
|
end
|
60
62
|
rescue Timeout::Error
|
61
63
|
# If we're using the default port with SSL, a timeout probably means the
|
@@ -95,9 +97,8 @@ module Bolt
|
|
95
97
|
end
|
96
98
|
|
97
99
|
def disconnect
|
98
|
-
@session&.close
|
99
100
|
@client&.disconnect!
|
100
|
-
@logger.trace { "Closed
|
101
|
+
@logger.trace { "Closed connection" }
|
101
102
|
end
|
102
103
|
|
103
104
|
def execute(command)
|
@@ -116,12 +117,18 @@ module Bolt
|
|
116
117
|
# propagate to the main thread via the shell, there's no chance
|
117
118
|
# they will be unhandled, so the default stack trace is unneeded.
|
118
119
|
Thread.current.report_on_exception = false
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
120
|
+
|
121
|
+
# Open a new shell instance for each command executed. PowerShell is
|
122
|
+
# unable to unload any DLLs loaded when running a PowerShell script
|
123
|
+
# or task from the same shell instance they were loaded in, which
|
124
|
+
# prevents Bolt from cleaning up the temp directory successfully.
|
125
|
+
# Using a new PowerShell instance avoids this limitation.
|
126
|
+
@connection.shell(:powershell) do |session|
|
127
|
+
result = session.run(command)
|
128
|
+
out_wr << result.stdout
|
129
|
+
err_wr << result.stderr
|
130
|
+
result.exitcode
|
131
|
+
end
|
125
132
|
ensure
|
126
133
|
# Close the streams to avoid the caller deadlocking
|
127
134
|
out_wr.close
|
data/lib/bolt/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bolt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.24.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Puppet
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-06-
|
11
|
+
date: 2022-06-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -163,6 +163,9 @@ dependencies:
|
|
163
163
|
- - ">="
|
164
164
|
- !ruby/object:Gem::Version
|
165
165
|
version: '4.0'
|
166
|
+
- - "<"
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '7.0'
|
166
169
|
type: :runtime
|
167
170
|
prerelease: false
|
168
171
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -170,6 +173,9 @@ dependencies:
|
|
170
173
|
- - ">="
|
171
174
|
- !ruby/object:Gem::Version
|
172
175
|
version: '4.0'
|
176
|
+
- - "<"
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '7.0'
|
173
179
|
- !ruby/object:Gem::Dependency
|
174
180
|
name: net-ssh-krb
|
175
181
|
requirement: !ruby/object:Gem::Requirement
|