bolt 2.27.0 → 2.32.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.

Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/Puppetfile +13 -12
  3. data/bolt-modules/boltlib/lib/puppet/functions/write_file.rb +2 -2
  4. data/bolt-modules/out/lib/puppet/functions/out/message.rb +44 -1
  5. data/bolt-modules/prompt/lib/puppet/functions/prompt.rb +3 -0
  6. data/guides/module.txt +19 -0
  7. data/guides/modulepath.txt +25 -0
  8. data/lib/bolt/applicator.rb +14 -14
  9. data/lib/bolt/bolt_option_parser.rb +74 -22
  10. data/lib/bolt/catalog.rb +1 -1
  11. data/lib/bolt/cli.rb +178 -127
  12. data/lib/bolt/config.rb +13 -1
  13. data/lib/bolt/config/modulepath.rb +30 -0
  14. data/lib/bolt/config/options.rb +38 -9
  15. data/lib/bolt/config/transport/options.rb +1 -1
  16. data/lib/bolt/executor.rb +1 -1
  17. data/lib/bolt/inventory.rb +11 -10
  18. data/lib/bolt/logger.rb +26 -19
  19. data/lib/bolt/module_installer.rb +197 -0
  20. data/lib/bolt/{puppetfile → module_installer}/installer.rb +3 -2
  21. data/lib/bolt/module_installer/puppetfile.rb +117 -0
  22. data/lib/bolt/module_installer/puppetfile/forge_module.rb +54 -0
  23. data/lib/bolt/module_installer/puppetfile/git_module.rb +37 -0
  24. data/lib/bolt/module_installer/puppetfile/module.rb +26 -0
  25. data/lib/bolt/module_installer/resolver.rb +76 -0
  26. data/lib/bolt/module_installer/specs.rb +93 -0
  27. data/lib/bolt/module_installer/specs/forge_spec.rb +84 -0
  28. data/lib/bolt/module_installer/specs/git_spec.rb +178 -0
  29. data/lib/bolt/outputter.rb +2 -45
  30. data/lib/bolt/outputter/human.rb +78 -18
  31. data/lib/bolt/outputter/json.rb +22 -7
  32. data/lib/bolt/outputter/logger.rb +2 -2
  33. data/lib/bolt/pal.rb +29 -25
  34. data/lib/bolt/plugin.rb +1 -1
  35. data/lib/bolt/plugin/module.rb +1 -1
  36. data/lib/bolt/project.rb +32 -22
  37. data/lib/bolt/project_migrator.rb +80 -0
  38. data/lib/bolt/project_migrator/base.rb +39 -0
  39. data/lib/bolt/project_migrator/config.rb +67 -0
  40. data/lib/bolt/project_migrator/inventory.rb +67 -0
  41. data/lib/bolt/project_migrator/modules.rb +200 -0
  42. data/lib/bolt/shell/bash.rb +4 -3
  43. data/lib/bolt/transport/base.rb +4 -4
  44. data/lib/bolt/transport/ssh/connection.rb +1 -1
  45. data/lib/bolt/util.rb +51 -10
  46. data/lib/bolt/version.rb +1 -1
  47. data/lib/bolt_server/acl.rb +2 -2
  48. data/lib/bolt_server/base_config.rb +3 -3
  49. data/lib/bolt_server/file_cache.rb +11 -11
  50. data/lib/bolt_server/schemas/partials/task.json +17 -2
  51. data/lib/bolt_server/transport_app.rb +93 -13
  52. data/lib/bolt_spec/bolt_context.rb +8 -6
  53. data/lib/bolt_spec/plans.rb +1 -1
  54. data/lib/bolt_spec/plans/mock_executor.rb +1 -1
  55. data/lib/bolt_spec/run.rb +1 -1
  56. metadata +30 -11
  57. data/lib/bolt/project_migrate.rb +0 -138
  58. data/lib/bolt/puppetfile.rb +0 -160
  59. data/lib/bolt/puppetfile/module.rb +0 -66
  60. data/lib/bolt_server/pe/pal.rb +0 -67
@@ -105,7 +105,7 @@ module BoltSpec
105
105
 
106
106
  # Set the things
107
107
  Puppet[:tasks] = true
108
- RSpec.configuration.module_path = [modulepath, Bolt::PAL::BOLTLIB_PATH].join(File::PATH_SEPARATOR)
108
+ RSpec.configuration.module_path = [modulepath, Bolt::Config::Modulepath::BOLTLIB_PATH].join(File::PATH_SEPARATOR)
109
109
  opts = {
110
110
  bolt_executor: executor,
111
111
  bolt_inventory: inventory,
@@ -142,10 +142,10 @@ module BoltSpec
142
142
  # Override in your tests
143
143
  def config
144
144
  @config ||= begin
145
- conf = Bolt::Config.default
146
- conf.modulepath = [modulepath].flatten
147
- conf
148
- end
145
+ conf = Bolt::Config.default
146
+ conf.modulepath = [modulepath].flatten
147
+ conf
148
+ end
149
149
  end
150
150
 
151
151
  def plugins
@@ -153,7 +153,9 @@ module BoltSpec
153
153
  end
154
154
 
155
155
  def pal
156
- @pal ||= Bolt::PAL.new(config.modulepath, config.hiera_config, config.project.resource_types)
156
+ @pal ||= Bolt::PAL.new(Bolt::Config::Modulepath.new(config.modulepath),
157
+ config.hiera_config,
158
+ config.project.resource_types)
157
159
  end
158
160
 
159
161
  BoltSpec::Plans::MOCKED_ACTIONS.each do |action|
@@ -224,7 +224,7 @@ module BoltSpec
224
224
 
225
225
  def run_plan(name, params)
226
226
  pal = Bolt::PAL.new(
227
- config.modulepath,
227
+ Bolt::Config::Modulepath.new(config.modulepath),
228
228
  config.hiera_config,
229
229
  config.project.resource_types,
230
230
  config.compile_concurrency,
@@ -40,7 +40,7 @@ module BoltSpec
40
40
 
41
41
  def module_file_id(file)
42
42
  modpath = @modulepath.select { |path| file =~ /^#{path}/ }
43
- raise "Could not identify module path containing #{file}: #{modpath}" unless modpath.size == 1
43
+ raise "Could not identify modulepath containing #{file}: #{modpath}" unless modpath.size == 1
44
44
 
45
45
  path = Pathname.new(file)
46
46
  relative = path.relative_path_from(Pathname.new(modpath.first))
@@ -179,7 +179,7 @@ module BoltSpec
179
179
  end
180
180
 
181
181
  def pal
182
- @pal ||= Bolt::PAL.new(config.modulepath,
182
+ @pal ||= Bolt::PAL.new(Bolt::Config::Modulepath.new(config.modulepath),
183
183
  config.hiera_config,
184
184
  config.project.resource_types,
185
185
  config.compile_concurrency)
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: 2.27.0
4
+ version: 2.32.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-08 00:00:00.000000000 Z
11
+ date: 2020-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -182,30 +182,36 @@ dependencies:
182
182
  name: puppet
183
183
  requirement: !ruby/object:Gem::Requirement
184
184
  requirements:
185
- - - '='
185
+ - - ">="
186
186
  - !ruby/object:Gem::Version
187
187
  version: 6.18.0
188
+ - - "<="
189
+ - !ruby/object:Gem::Version
190
+ version: '6.19'
188
191
  type: :runtime
189
192
  prerelease: false
190
193
  version_requirements: !ruby/object:Gem::Requirement
191
194
  requirements:
192
- - - '='
195
+ - - ">="
193
196
  - !ruby/object:Gem::Version
194
197
  version: 6.18.0
198
+ - - "<="
199
+ - !ruby/object:Gem::Version
200
+ version: '6.19'
195
201
  - !ruby/object:Gem::Dependency
196
202
  name: puppetfile-resolver
197
203
  requirement: !ruby/object:Gem::Requirement
198
204
  requirements:
199
205
  - - "~>"
200
206
  - !ruby/object:Gem::Version
201
- version: 0.1.0
207
+ version: '0.4'
202
208
  type: :runtime
203
209
  prerelease: false
204
210
  version_requirements: !ruby/object:Gem::Requirement
205
211
  requirements:
206
212
  - - "~>"
207
213
  - !ruby/object:Gem::Version
208
- version: 0.1.0
214
+ version: '0.4'
209
215
  - !ruby/object:Gem::Dependency
210
216
  name: puppet-resource_api
211
217
  requirement: !ruby/object:Gem::Requirement
@@ -432,6 +438,8 @@ files:
432
438
  - bolt-modules/system/lib/puppet/functions/system/env.rb
433
439
  - exe/bolt
434
440
  - guides/inventory.txt
441
+ - guides/module.txt
442
+ - guides/modulepath.txt
435
443
  - guides/project.txt
436
444
  - lib/bolt.rb
437
445
  - lib/bolt/analytics.rb
@@ -444,6 +452,7 @@ files:
444
452
  - lib/bolt/catalog/logging.rb
445
453
  - lib/bolt/cli.rb
446
454
  - lib/bolt/config.rb
455
+ - lib/bolt/config/modulepath.rb
447
456
  - lib/bolt/config/options.rb
448
457
  - lib/bolt/config/transport/base.rb
449
458
  - lib/bolt/config/transport/docker.rb
@@ -461,6 +470,16 @@ files:
461
470
  - lib/bolt/inventory/target.rb
462
471
  - lib/bolt/logger.rb
463
472
  - lib/bolt/module.rb
473
+ - lib/bolt/module_installer.rb
474
+ - lib/bolt/module_installer/installer.rb
475
+ - lib/bolt/module_installer/puppetfile.rb
476
+ - lib/bolt/module_installer/puppetfile/forge_module.rb
477
+ - lib/bolt/module_installer/puppetfile/git_module.rb
478
+ - lib/bolt/module_installer/puppetfile/module.rb
479
+ - lib/bolt/module_installer/resolver.rb
480
+ - lib/bolt/module_installer/specs.rb
481
+ - lib/bolt/module_installer/specs/forge_spec.rb
482
+ - lib/bolt/module_installer/specs/git_spec.rb
464
483
  - lib/bolt/node/errors.rb
465
484
  - lib/bolt/node/output.rb
466
485
  - lib/bolt/outputter.rb
@@ -494,13 +513,14 @@ files:
494
513
  - lib/bolt/plugin/puppetdb.rb
495
514
  - lib/bolt/plugin/task.rb
496
515
  - lib/bolt/project.rb
497
- - lib/bolt/project_migrate.rb
516
+ - lib/bolt/project_migrator.rb
517
+ - lib/bolt/project_migrator/base.rb
518
+ - lib/bolt/project_migrator/config.rb
519
+ - lib/bolt/project_migrator/inventory.rb
520
+ - lib/bolt/project_migrator/modules.rb
498
521
  - lib/bolt/puppetdb.rb
499
522
  - lib/bolt/puppetdb/client.rb
500
523
  - lib/bolt/puppetdb/config.rb
501
- - lib/bolt/puppetfile.rb
502
- - lib/bolt/puppetfile/installer.rb
503
- - lib/bolt/puppetfile/module.rb
504
524
  - lib/bolt/r10k_log_proxy.rb
505
525
  - lib/bolt/rerun.rb
506
526
  - lib/bolt/resource_instance.rb
@@ -537,7 +557,6 @@ files:
537
557
  - lib/bolt_server/base_config.rb
538
558
  - lib/bolt_server/config.rb
539
559
  - lib/bolt_server/file_cache.rb
540
- - lib/bolt_server/pe/pal.rb
541
560
  - lib/bolt_server/schemas/action-check_node_connections.json
542
561
  - lib/bolt_server/schemas/action-run_command.json
543
562
  - lib/bolt_server/schemas/action-run_script.json
@@ -1,138 +0,0 @@
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
@@ -1,160 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bolt/error'
4
- require 'bolt/puppetfile/module'
5
-
6
- # This class manages the logical contents of a Puppetfile. It includes methods
7
- # for parsing a Puppetfile and its modules, resolving module dependencies,
8
- # and writing a Puppetfile.
9
- #
10
- module Bolt
11
- class Puppetfile
12
- attr_reader :modules
13
-
14
- def initialize(modules = [])
15
- @modules = Set.new
16
- add_modules(modules)
17
- end
18
-
19
- # Loads a Puppetfile and parses its module specifications, returning a
20
- # Bolt::Puppetfile object with the modules set.
21
- #
22
- def self.parse(path)
23
- require 'puppetfile-resolver'
24
- require 'puppetfile-resolver/puppetfile/parser/r10k_eval'
25
-
26
- begin
27
- parsed = ::PuppetfileResolver::Puppetfile::Parser::R10KEval.parse(File.read(path))
28
- rescue StandardError => e
29
- raise Bolt::Error.new(
30
- "Unable to parse Puppetfile #{path}: #{e.message}",
31
- 'bolt/puppetfile-parsing'
32
- )
33
- end
34
-
35
- unless parsed.valid?
36
- raise Bolt::ValidationError,
37
- "Unable to parse Puppetfile #{path}"
38
- end
39
-
40
- modules = parsed.modules.map do |mod|
41
- Bolt::Puppetfile::Module.new(mod.owner, mod.name, mod.version)
42
- end
43
-
44
- new(modules)
45
- end
46
-
47
- # Writes a Puppetfile that includes specifications for each of the
48
- # modules.
49
- #
50
- def write(path, force: false)
51
- if File.exist?(path) && !force
52
- raise Bolt::FileError.new(
53
- "Cannot overwrite existing Puppetfile at #{path}. To forcibly overwrite, "\
54
- "run with the '--force' option.",
55
- path
56
- )
57
- end
58
-
59
- File.open(path, 'w') do |file|
60
- file.puts '# This Puppetfile is managed by Bolt. Do not edit.'
61
- modules.each { |mod| file.puts mod.to_spec }
62
- file.puts
63
- end
64
- rescue SystemCallError => e
65
- raise Bolt::FileError.new(
66
- "#{e.message}: unable to write Puppetfile.",
67
- path
68
- )
69
- end
70
-
71
- # Resolves module dependencies using the puppetfile-resolver library. The
72
- # resolver will return a document model including all module dependencies
73
- # and the latest version that can be installed for each. The document model
74
- # is parsed and turned into a Set of Bolt::Puppetfile::Module objects.
75
- #
76
- def resolve
77
- require 'puppetfile-resolver'
78
-
79
- # Build the document model from the modules.
80
- model = PuppetfileResolver::Puppetfile::Document.new('')
81
-
82
- @modules.each do |mod|
83
- model.add_module(
84
- PuppetfileResolver::Puppetfile::ForgeModule.new(mod.title).tap do |tap|
85
- tap.version = :latest
86
- end
87
- )
88
- end
89
-
90
- # Make sure the Puppetfile model is valid.
91
- unless model.valid?
92
- raise Bolt::ValidationError,
93
- "Unable to resolve dependencies for modules: #{@modules.map(&:title).join(', ')}"
94
- end
95
-
96
- # Create the resolver using the Puppetfile model. nil disables Puppet
97
- # version restrictions.
98
- resolver = PuppetfileResolver::Resolver.new(model, nil)
99
-
100
- # Configure and resolve the dependency graph, catching any errors
101
- # raised by puppetfile-resolver and re-raising them as Bolt errors.
102
- begin
103
- result = resolver.resolve(
104
- cache: nil,
105
- ui: nil,
106
- module_paths: [],
107
- allow_missing_modules: true
108
- )
109
- rescue StandardError => e
110
- raise Bolt::Error.new(e.message, 'bolt/puppetfile-resolver-error')
111
- end
112
-
113
- # Validate that the modules exist.
114
- missing_graph = result.specifications.select do |_name, spec|
115
- spec.instance_of? PuppetfileResolver::Models::MissingModuleSpecification
116
- end
117
-
118
- if missing_graph.any?
119
- titles = model.modules.each_with_object({}) do |mod, acc|
120
- acc[mod.name] = mod.title
121
- end
122
-
123
- names = titles.values_at(*missing_graph.keys)
124
- plural = names.count == 1 ? '' : 's'
125
-
126
- raise Bolt::Error.new(
127
- "Unknown module name#{plural} #{names.join(', ')}",
128
- 'bolt/unknown-modules'
129
- )
130
- end
131
-
132
- # Filter the dependency graph to only include module specifications. This
133
- # will only remove the Puppet version specification, which is not needed.
134
- specs = result.specifications.select do |_name, spec|
135
- spec.instance_of? PuppetfileResolver::Models::ModuleSpecification
136
- end
137
-
138
- @modules = specs.map do |_name, spec|
139
- Bolt::Puppetfile::Module.new(spec.owner, spec.name, spec.version.to_s)
140
- end.to_set
141
- end
142
-
143
- # Adds to the set of modules.
144
- #
145
- def add_modules(modules)
146
- modules.each do |mod|
147
- case mod
148
- when Bolt::Puppetfile::Module
149
- @modules << mod
150
- when Hash
151
- @modules << Bolt::Puppetfile::Module.from_hash(mod)
152
- else
153
- raise Bolt::ValidationError, "Module must be a Bolt::Puppetfile::Module or Hash."
154
- end
155
- end
156
-
157
- @modules
158
- end
159
- end
160
- end