bolt 3.29.0 → 3.30.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b5a8936e9789e8d1a722b5cc76cedf594a8f09709352b95ed6e423f0d7ddc6e
4
- data.tar.gz: ef052d1f831ba328d6949a1f33ec617f933f2f28e862d23264ed1dfd9b43b0a6
3
+ metadata.gz: 80dd0d96ead6ae1cddc50bfd8381ea7cdce56a521afa475108589066dcd75f39
4
+ data.tar.gz: bee19d728cf36384d22e1c69eff95e05c58bc08b9186c6542ca3bc07effcb8d6
5
5
  SHA512:
6
- metadata.gz: f1eeec5f42a0f82a751d5eaa834a42e66d26080a0250e680d4c6328e7fb3a2048f13093d65dc6a7d55220963d8178cbaee7744643f17dd82af44d92b3187c3a6
7
- data.tar.gz: 6cd501114d6efc60a26df945e528b03a610018c287a9e03b722f15da5a37680655df1dc953702922e0c306376adcb9e536b30f6aedb1b24a4efe9e97fc3da504
6
+ metadata.gz: a3a05e9ee13b0e24f951268f0d27d5e6ba5d26df4f21f96f0f1f2c6fe37df5db83bab32114d5ebc2cfebe806ee0fde992c1e8a69d254f960ce7e1a79f31300fb
7
+ data.tar.gz: 5b3a8b35ddde08c7c89c1b97421b987e37cfdc973cb08a5ae1dcc36cbbefd6c4b3d81db058406d490958fc0718b8cec23d9536b68f2e5af023990e0f43506b78
@@ -6,7 +6,7 @@ Puppet::Functions.create_function(:'ctrl::do_until') do
6
6
  # @param block The code block to repeat.
7
7
  # @option options [Numeric] limit The number of times to repeat the block.
8
8
  # @option options [Numeric] interval The number of seconds to wait before repeating the block.
9
- # @return [nil]
9
+ # @return The value of the code block's last iteration
10
10
  # @example Run a task until it succeeds
11
11
  # ctrl::do_until() || {
12
12
  # run_task('test', $target, '_catch_errors' => true).ok()
@@ -284,6 +284,9 @@ module Bolt
284
284
  'catalog' => Puppet::Pops::Types::PSensitiveType::Sensitive.new(catalog),
285
285
  'plugins' => Puppet::Pops::Types::PSensitiveType::Sensitive.new(plugins),
286
286
  'apply_settings' => @apply_settings,
287
+ # This should just be boltlib and modules dirs shipped with bolt packages
288
+ # The apply_catalog task uses them to load core types if they exist
289
+ 'bolt_builtin_content' => @modulepath - @plugin_dirs,
287
290
  '_task' => catalog_apply_task.name,
288
291
  '_noop' => options[:noop]
289
292
  }
@@ -11,7 +11,9 @@ module Bolt
11
11
  cleanup
12
12
  interpreters
13
13
  remote
14
+ shell-command
14
15
  tmpdir
16
+ tty
15
17
  ].concat(RUN_AS_OPTIONS).sort.freeze
16
18
 
17
19
  DEFAULTS = {
@@ -332,7 +332,7 @@ module Bolt
332
332
  },
333
333
  "shell-command" => {
334
334
  type: String,
335
- description: "A shell command to wrap any Docker exec commands in, such as `bash -lc`.",
335
+ description: "A shell command to wrap any exec commands in, such as `bash -lc`.",
336
336
  _plugin: true,
337
337
  _example: "bash -lc"
338
338
  },
@@ -14,6 +14,10 @@ module Bolt
14
14
  EXTENDED_TARGET_REGEX = /[[:space:],]+(?=[^\]}]*(?:[\[{]|$))/.freeze
15
15
  TARGET_REGEX = /[[:space:],]+/.freeze
16
16
 
17
+ # Pattern which looks for indicators that glob-based target name matching
18
+ # should be used.
19
+ GLOB_MATCH_REGEX = /[*?\[\]{}]/.freeze
20
+
17
21
  class WildcardError < Bolt::Error
18
22
  def initialize(target)
19
23
  super("Found 0 targets matching wildcard pattern #{target}", 'bolt.inventory/wildcard-error')
@@ -119,19 +123,36 @@ module Bolt
119
123
  if ext_glob
120
124
  File.fnmatch(wildcard, target_name, File::FNM_CASEFOLD | File::FNM_EXTGLOB)
121
125
  else
122
- regexp = Regexp.new("^#{Regexp.escape(wildcard).gsub('\*', '.*?')}$", Regexp::IGNORECASE)
123
- target_name =~ regexp
126
+ File.fnmatch(wildcard, target_name, File::FNM_CASEFOLD)
124
127
  end
125
128
  end
126
129
 
127
130
  # If target is a group name, expand it to the members of that group.
128
131
  # Else match against groups and targets in inventory by name or alias.
129
- # If a wildcard string, error if no matches are found.
132
+ # Attempt exact matches for groups, targets, and aliases first for speed.
133
+ # If no exact match and the string contains wildcard characters, then check
134
+ # and see if the target string might be a URI, if it parses as a URI with
135
+ # a scheme then return as-is, otherwise look for a wildcard match and
136
+ # error if no matches are found.
130
137
  # Else fall back to [target] if no matches are found.
131
138
  def resolve_name(target, ext_glob: false)
132
139
  if (group = group_lookup[target])
133
140
  group.all_targets.to_a
134
- else
141
+ elsif @targets.key?(target)
142
+ [target]
143
+ elsif (real_target = groups.target_aliases[target])
144
+ [real_target]
145
+ elsif GLOB_MATCH_REGEX.match?(target)
146
+ # URIs and glob wildcards have some overlapping characters. If the target
147
+ # being resolved parses as a valid target URI and has a scheme defined then
148
+ # return it as-is and do not try to do further wildcard matching:
149
+ uri = begin
150
+ Bolt::Inventory::Target.parse_uri(target)
151
+ rescue Bolt::ParseError
152
+ nil
153
+ end
154
+ return [target] if uri&.scheme
155
+
135
156
  targets = []
136
157
 
137
158
  # Find groups that match the glob
@@ -148,12 +169,11 @@ module Bolt
148
169
  .select { |tgt_alias, _| match_wildcard?(target, tgt_alias, ext_glob: ext_glob) }
149
170
  .values
150
171
 
151
- if targets.empty?
152
- raise(WildcardError, target) if target.include?('*')
153
- [target]
154
- else
155
- targets.uniq
156
- end
172
+ raise(WildcardError, target) if targets.empty?
173
+
174
+ targets.uniq
175
+ else # rubocop:disable Lint/DuplicateBranch
176
+ [target]
157
177
  end
158
178
  end
159
179
  private :resolve_name
@@ -34,7 +34,7 @@ module Bolt
34
34
  @name = @uri
35
35
  @safe_name = @uri_obj.omit(:password).to_str.sub(%r{^//}, '')
36
36
  end
37
-
37
+ # handle special localhost target
38
38
  if @name == 'localhost'
39
39
  default = { 'config' => { 'transport' => 'local' } }
40
40
  target_data = Bolt::Util.deep_merge(default, target_data)
@@ -53,6 +53,8 @@ module Bolt
53
53
  @inventory = inventory
54
54
 
55
55
  validate
56
+ # after setting config, apply local defaults when using bundled ruby
57
+ set_local_defaults if transport_config['bundled-ruby']
56
58
  end
57
59
 
58
60
  def set_local_defaults
data/lib/bolt/target.rb CHANGED
@@ -80,10 +80,6 @@ module Bolt
80
80
  inventory_target.resources
81
81
  end
82
82
 
83
- def set_local_defaults
84
- inventory_target.set_local_defaults
85
- end
86
-
87
83
  # rubocop:disable Naming/AccessorMethodName
88
84
  def set_resource(resource)
89
85
  inventory_target.set_resource(resource)
@@ -11,10 +11,6 @@ module Bolt
11
11
  end
12
12
 
13
13
  def with_connection(target)
14
- if target.transport_config['bundled-ruby']
15
- target.set_local_defaults
16
- end
17
-
18
14
  yield Connection.new(target)
19
15
  end
20
16
  end
@@ -57,12 +57,24 @@ module Bolt
57
57
  end
58
58
 
59
59
  def execute(command)
60
- lxc_command = %w[lxc exec]
60
+ lxc_command = %W[lxc exec #{container_id}]
61
+ lxc_command += ['--mode', target.options['tty'].to_s.empty? ? 'non-interactive' : 'interactive']
61
62
  lxc_command += @env_vars if @env_vars
62
- lxc_command += %W[#{container_id} -- sh -c #{Shellwords.shellescape(command)}]
63
+ lxc_command << '--'
64
+
65
+ if target.options['shell-command'].to_s.empty?
66
+ lxc_command += Shellwords.split(command)
67
+ else
68
+ lxc_command += Shellwords.split(target.options['shell-command'])
69
+ lxc_command << command
70
+ end
63
71
 
64
72
  @logger.trace { "Executing: #{lxc_command.join(' ')}" }
65
- Open3.popen3(lxc_command.join(' '))
73
+
74
+ Open3.popen3(*lxc_command)
75
+ rescue StandardError
76
+ @logger.trace { "Command aborted" }
77
+ raise
66
78
  end
67
79
 
68
80
  private def execute_local_command(command)
data/lib/bolt/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bolt
4
- VERSION = '3.29.0'
4
+ VERSION = '3.30.0'
5
5
  end
@@ -52,6 +52,19 @@ begin
52
52
  $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
53
53
  end
54
54
 
55
+ # In the case we are applying on a bolt runner and using bundled-ruby over local transport
56
+ # we will want to load code shipped with bolt. This is last on the load path and therefore
57
+ # explicitly packaged plugins should take precedence
58
+ args['bolt_builtin_content'].each do |builtin_dir|
59
+ next unless Dir.exist?(builtin_dir)
60
+ Dir.foreach(builtin_dir) do |dir|
61
+ unless ['.', '..'].include? dir
62
+ full_path = File.join(builtin_dir, dir, 'lib')
63
+ $LOAD_PATH << full_path unless $LOAD_PATH.include?(full_path)
64
+ end
65
+ end
66
+ end
67
+
55
68
  if (conn_info = args['_target'])
56
69
  unless (type = conn_info['remote-transport'])
57
70
  puts "Cannot execute a catalog for a remote target without knowing it's the remote-transport type."
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.29.0
4
+ version: 3.30.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-17 00:00:00.000000000 Z
11
+ date: 2024-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -366,58 +366,82 @@ dependencies:
366
366
  name: octokit
367
367
  requirement: !ruby/object:Gem::Requirement
368
368
  requirements:
369
- - - "~>"
369
+ - - ">="
370
370
  - !ruby/object:Gem::Version
371
371
  version: '4.0'
372
+ - - "<"
373
+ - !ruby/object:Gem::Version
374
+ version: '9'
372
375
  type: :development
373
376
  prerelease: false
374
377
  version_requirements: !ruby/object:Gem::Requirement
375
378
  requirements:
376
- - - "~>"
379
+ - - ">="
377
380
  - !ruby/object:Gem::Version
378
381
  version: '4.0'
382
+ - - "<"
383
+ - !ruby/object:Gem::Version
384
+ version: '9'
379
385
  - !ruby/object:Gem::Dependency
380
386
  name: puppetlabs_spec_helper
381
387
  requirement: !ruby/object:Gem::Requirement
382
388
  requirements:
383
- - - "~>"
389
+ - - ">="
384
390
  - !ruby/object:Gem::Version
385
391
  version: '5.0'
392
+ - - "<"
393
+ - !ruby/object:Gem::Version
394
+ version: '8'
386
395
  type: :development
387
396
  prerelease: false
388
397
  version_requirements: !ruby/object:Gem::Requirement
389
398
  requirements:
390
- - - "~>"
399
+ - - ">="
391
400
  - !ruby/object:Gem::Version
392
401
  version: '5.0'
402
+ - - "<"
403
+ - !ruby/object:Gem::Version
404
+ version: '8'
393
405
  - !ruby/object:Gem::Dependency
394
406
  name: rake
395
407
  requirement: !ruby/object:Gem::Requirement
396
408
  requirements:
397
- - - "~>"
409
+ - - ">="
398
410
  - !ruby/object:Gem::Version
399
411
  version: '12.0'
412
+ - - "<"
413
+ - !ruby/object:Gem::Version
414
+ version: '14'
400
415
  type: :development
401
416
  prerelease: false
402
417
  version_requirements: !ruby/object:Gem::Requirement
403
418
  requirements:
404
- - - "~>"
419
+ - - ">="
405
420
  - !ruby/object:Gem::Version
406
421
  version: '12.0'
422
+ - - "<"
423
+ - !ruby/object:Gem::Version
424
+ version: '14'
407
425
  - !ruby/object:Gem::Dependency
408
426
  name: rspec
409
427
  requirement: !ruby/object:Gem::Requirement
410
428
  requirements:
411
- - - "~>"
429
+ - - ">="
412
430
  - !ruby/object:Gem::Version
413
431
  version: '3.0'
432
+ - - "<"
433
+ - !ruby/object:Gem::Version
434
+ version: '4'
414
435
  type: :development
415
436
  prerelease: false
416
437
  version_requirements: !ruby/object:Gem::Requirement
417
438
  requirements:
418
- - - "~>"
439
+ - - ">="
419
440
  - !ruby/object:Gem::Version
420
441
  version: '3.0'
442
+ - - "<"
443
+ - !ruby/object:Gem::Version
444
+ version: '4'
421
445
  description: Execute commands remotely over SSH and WinRM
422
446
  email:
423
447
  - puppet@puppet.com