bolt 2.28.0 → 2.33.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.

Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/Puppetfile +15 -14
  3. data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +1 -1
  4. data/bolt-modules/boltlib/lib/puppet/functions/facts.rb +6 -0
  5. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +2 -2
  6. data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +1 -1
  7. data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +1 -1
  8. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +1 -1
  9. data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +1 -1
  10. data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +1 -1
  11. data/bolt-modules/boltlib/lib/puppet/functions/write_file.rb +2 -2
  12. data/bolt-modules/out/lib/puppet/functions/out/message.rb +44 -1
  13. data/bolt-modules/prompt/lib/puppet/functions/prompt.rb +3 -0
  14. data/guides/logging.txt +18 -0
  15. data/guides/module.txt +19 -0
  16. data/guides/modulepath.txt +25 -0
  17. data/lib/bolt/bolt_option_parser.rb +50 -28
  18. data/lib/bolt/catalog.rb +1 -1
  19. data/lib/bolt/cli.rb +159 -112
  20. data/lib/bolt/config.rb +13 -1
  21. data/lib/bolt/config/modulepath.rb +30 -0
  22. data/lib/bolt/config/options.rb +38 -9
  23. data/lib/bolt/config/transport/options.rb +2 -2
  24. data/lib/bolt/error.rb +4 -0
  25. data/lib/bolt/executor.rb +13 -13
  26. data/lib/bolt/inventory.rb +10 -9
  27. data/lib/bolt/logger.rb +26 -19
  28. data/lib/bolt/module_installer.rb +198 -0
  29. data/lib/bolt/{puppetfile → module_installer}/installer.rb +3 -2
  30. data/lib/bolt/module_installer/puppetfile.rb +117 -0
  31. data/lib/bolt/module_installer/puppetfile/forge_module.rb +54 -0
  32. data/lib/bolt/module_installer/puppetfile/git_module.rb +37 -0
  33. data/lib/bolt/module_installer/puppetfile/module.rb +26 -0
  34. data/lib/bolt/module_installer/resolver.rb +76 -0
  35. data/lib/bolt/module_installer/specs.rb +93 -0
  36. data/lib/bolt/module_installer/specs/forge_spec.rb +84 -0
  37. data/lib/bolt/module_installer/specs/git_spec.rb +178 -0
  38. data/lib/bolt/outputter.rb +2 -45
  39. data/lib/bolt/outputter/human.rb +78 -18
  40. data/lib/bolt/outputter/json.rb +22 -7
  41. data/lib/bolt/outputter/logger.rb +2 -2
  42. data/lib/bolt/pal.rb +55 -45
  43. data/lib/bolt/pal/yaml_plan.rb +4 -2
  44. data/lib/bolt/pal/yaml_plan/evaluator.rb +23 -1
  45. data/lib/bolt/pal/yaml_plan/loader.rb +14 -9
  46. data/lib/bolt/plugin.rb +1 -1
  47. data/lib/bolt/plugin/module.rb +1 -1
  48. data/lib/bolt/project.rb +32 -22
  49. data/lib/bolt/project_migrator.rb +80 -0
  50. data/lib/bolt/project_migrator/base.rb +39 -0
  51. data/lib/bolt/project_migrator/config.rb +67 -0
  52. data/lib/bolt/project_migrator/inventory.rb +67 -0
  53. data/lib/bolt/project_migrator/modules.rb +200 -0
  54. data/lib/bolt/result.rb +23 -11
  55. data/lib/bolt/shell/bash.rb +15 -9
  56. data/lib/bolt/shell/powershell.rb +11 -6
  57. data/lib/bolt/transport/base.rb +18 -18
  58. data/lib/bolt/transport/docker.rb +23 -6
  59. data/lib/bolt/transport/orch.rb +23 -14
  60. data/lib/bolt/transport/remote.rb +2 -2
  61. data/lib/bolt/transport/simple.rb +6 -6
  62. data/lib/bolt/transport/ssh/connection.rb +1 -1
  63. data/lib/bolt/util.rb +41 -0
  64. data/lib/bolt/version.rb +1 -1
  65. data/lib/bolt_server/acl.rb +2 -2
  66. data/lib/bolt_server/base_config.rb +3 -3
  67. data/lib/bolt_server/schemas/partials/task.json +17 -2
  68. data/lib/bolt_server/transport_app.rb +93 -13
  69. data/lib/bolt_spec/bolt_context.rb +4 -2
  70. data/lib/bolt_spec/plans.rb +1 -1
  71. data/lib/bolt_spec/plans/action_stubs/command_stub.rb +1 -1
  72. data/lib/bolt_spec/plans/action_stubs/script_stub.rb +1 -1
  73. data/lib/bolt_spec/plans/mock_executor.rb +6 -6
  74. data/lib/bolt_spec/run.rb +1 -1
  75. metadata +31 -12
  76. data/lib/bolt/project_migrate.rb +0 -138
  77. data/lib/bolt/puppetfile.rb +0 -160
  78. data/lib/bolt/puppetfile/module.rb +0 -66
  79. data/lib/bolt_server/pe/pal.rb +0 -67
  80. data/modules/secure_env_vars/plans/init.pp +0 -20
@@ -13,9 +13,9 @@ module Bolt
13
13
  def handle_event(event)
14
14
  case event[:type]
15
15
  when :step_start
16
- log_step_start(event)
16
+ log_step_start(**event)
17
17
  when :step_finish
18
- log_step_finish(event)
18
+ log_step_finish(**event)
19
19
  when :plan_start
20
20
  log_plan_start(event)
21
21
  when :plan_finish
@@ -5,40 +5,36 @@ require 'bolt/executor'
5
5
  require 'bolt/error'
6
6
  require 'bolt/plan_result'
7
7
  require 'bolt/util'
8
+ require 'bolt/config/modulepath'
8
9
  require 'etc'
9
10
 
10
11
  module Bolt
11
12
  class PAL
12
- BOLTLIB_PATH = File.expand_path('../../bolt-modules', __dir__)
13
- MODULES_PATH = File.expand_path('../../modules', __dir__)
14
-
15
13
  # PALError is used to convert errors from executing puppet code into
16
14
  # Bolt::Errors
17
15
  class PALError < Bolt::Error
18
16
  def self.from_preformatted_error(err)
19
- if err.cause&.is_a? Bolt::Error
20
- err.cause
21
- else
22
- from_error(err)
23
- end
17
+ error = if err.cause.is_a? Bolt::Error
18
+ err.cause
19
+ else
20
+ from_error(err)
21
+ end
22
+
23
+ # Provide the location of an error if it came from a plan
24
+ details = {}
25
+ details[:file] = err.file if defined?(err.file)
26
+ details[:line] = err.line if defined?(err.line)
27
+ details[:column] = err.pos if defined?(err.pos)
28
+
29
+ error.add_filelineno(details)
30
+ error
24
31
  end
25
32
 
26
33
  # Generate a Bolt::Pal::PALError for non-bolt errors
27
34
  def self.from_error(err)
28
35
  # Use the original error message if available
29
36
  message = err.cause ? err.cause.message : err.message
30
-
31
- # Provide the location of an error if it came from a plan
32
- details = if defined?(err.file) && err.file
33
- { file: err.file,
34
- line: err.line,
35
- column: err.pos }.compact
36
- else
37
- {}
38
- end
39
-
40
- e = new(message, details)
41
-
37
+ e = new(message)
42
38
  e.set_backtrace(err.backtrace)
43
39
  e
44
40
  end
@@ -48,16 +44,16 @@ module Bolt
48
44
  end
49
45
  end
50
46
 
51
- attr_reader :modulepath, :user_modulepath
52
-
53
47
  def initialize(modulepath, hiera_config, resource_types, max_compiles = Etc.nprocessors,
54
48
  trusted_external = nil, apply_settings = {}, project = nil)
49
+ unless modulepath.is_a?(Bolt::Config::Modulepath)
50
+ msg = "Type error in PAL: modulepath must be a Bolt::Config::Modulepath"
51
+ raise Bolt::Error.new(msg, "bolt/execution-error")
52
+ end
55
53
  # Nothing works without initialized this global state. Reinitializing
56
54
  # is safe and in practice only happens in tests
57
55
  self.class.load_puppet
58
-
59
- @user_modulepath = modulepath
60
- @modulepath = [BOLTLIB_PATH, *modulepath, MODULES_PATH]
56
+ @modulepath = modulepath
61
57
  @hiera_config = hiera_config
62
58
  @trusted_external = trusted_external
63
59
  @apply_settings = apply_settings
@@ -66,13 +62,21 @@ module Bolt
66
62
  @project = project
67
63
 
68
64
  @logger = Bolt::Logger.logger(self)
69
- if modulepath && !modulepath.empty?
70
- @logger.debug("Loading modules from #{@modulepath.join(File::PATH_SEPARATOR)}")
65
+ unless user_modulepath.empty?
66
+ @logger.debug("Loading modules from #{full_modulepath.join(File::PATH_SEPARATOR)}")
71
67
  end
72
68
 
73
69
  @loaded = false
74
70
  end
75
71
 
72
+ def full_modulepath
73
+ @modulepath.full_modulepath
74
+ end
75
+
76
+ def user_modulepath
77
+ @modulepath.user_modulepath
78
+ end
79
+
76
80
  # Puppet logging is global so this is class method to avoid confusion
77
81
  def self.configure_logging
78
82
  Puppet::Util::Log.destinations.clear
@@ -160,7 +164,7 @@ module Bolt
160
164
  def in_bolt_compiler
161
165
  # TODO: If we always call this inside a bolt_executor we can remove this here
162
166
  setup
163
- r = Puppet::Pal.in_tmp_environment('bolt', modulepath: @modulepath, facts: {}) do |pal|
167
+ r = Puppet::Pal.in_tmp_environment('bolt', modulepath: full_modulepath, facts: {}) do |pal|
164
168
  # Only load the project if it a) exists, b) has a name it can be loaded with
165
169
  Puppet.override(bolt_project: @project,
166
170
  yaml_plan_instantiator: Bolt::PAL::YamlPlan::Loader) do
@@ -215,11 +219,11 @@ module Bolt
215
219
  apply_executor: applicator || Applicator.new(
216
220
  inventory,
217
221
  executor,
218
- @modulepath,
222
+ full_modulepath,
219
223
  # Skip syncing built-in plugins, since we vendor some Puppet 6
220
224
  # versions of "core" types, which are already present on the agent,
221
225
  # but may cause issues on Puppet 5 agents.
222
- @user_modulepath,
226
+ user_modulepath,
223
227
  @project,
224
228
  pdb_client,
225
229
  @hiera_config,
@@ -253,19 +257,24 @@ module Bolt
253
257
 
254
258
  # TODO: PUP-8553 should replace this
255
259
  def with_puppet_settings
256
- Dir.mktmpdir('bolt') do |dir|
257
- cli = []
258
- Puppet::Settings::REQUIRED_APP_SETTINGS.each do |setting|
259
- cli << "--#{setting}" << dir
260
- end
261
- Puppet.settings.send(:clear_everything_for_tests)
262
- Puppet.initialize_settings(cli)
263
- Puppet::GettextConfig.create_default_text_domain
264
- Puppet[:trusted_external_command] = @trusted_external
265
- Puppet.settings[:hiera_config] = @hiera_config
266
- self.class.configure_logging
267
- yield
260
+ dir = Dir.mktmpdir('bolt')
261
+
262
+ cli = []
263
+ Puppet::Settings::REQUIRED_APP_SETTINGS.each do |setting|
264
+ cli << "--#{setting}" << dir
268
265
  end
266
+ Puppet.settings.send(:clear_everything_for_tests)
267
+ Puppet.initialize_settings(cli)
268
+ Puppet::GettextConfig.create_default_text_domain
269
+ Puppet[:trusted_external_command] = @trusted_external
270
+ Puppet.settings[:hiera_config] = @hiera_config
271
+ self.class.configure_logging
272
+ yield
273
+ ensure
274
+ # Delete the tmpdir if it still exists. This check is needed to
275
+ # prevent Bolt from erroring if the tmpdir is somehow deleted
276
+ # before reaching this point.
277
+ FileUtils.remove_entry_secure(dir) if File.exist?(dir)
269
278
  end
270
279
 
271
280
  # Parses a snippet of Puppet manifest code and returns the AST represented
@@ -441,13 +450,14 @@ module Bolt
441
450
  # Returns a mapping of all modules available to the Bolt compiler
442
451
  #
443
452
  # @return [Hash{String => Array<Hash{Symbol => String,nil}>}]
444
- # A hash that associates each directory on the module path with an array
453
+ # A hash that associates each directory on the modulepath with an array
445
454
  # containing a hash of information for each module in that directory.
446
455
  # The information hash provides the name, version, and a string
447
456
  # indicating whether the module belongs to an internal module group.
448
457
  def list_modules
449
- internal_module_groups = { BOLTLIB_PATH => 'Plan Language Modules',
450
- MODULES_PATH => 'Packaged Modules' }
458
+ internal_module_groups = { Bolt::Config::Modulepath::BOLTLIB_PATH => 'Plan Language Modules',
459
+ Bolt::Config::Modulepath::MODULES_PATH => 'Packaged Modules',
460
+ @project.managed_moduledir.to_s => 'Project Dependencies' }
451
461
 
452
462
  in_bolt_compiler do
453
463
  # NOTE: Can replace map+to_h with transform_values when Ruby 2.4
@@ -98,10 +98,12 @@ module Bolt
98
98
  # subclasses this parent class in order to implement its own evaluation
99
99
  # logic.
100
100
  class EvaluableString
101
- attr_reader :value
101
+ attr_reader :file, :line, :value
102
102
 
103
- def initialize(value)
103
+ def initialize(value, file = nil, line = nil)
104
104
  @value = value
105
+ @file = file
106
+ @line = line
105
107
  end
106
108
 
107
109
  def ==(other)
@@ -191,7 +191,11 @@ module Bolt
191
191
  o[key] = evaluate_code_blocks(scope, v)
192
192
  end
193
193
  when EvaluableString
194
- value.evaluate(scope, @evaluator)
194
+ begin
195
+ value.evaluate(scope, @evaluator)
196
+ rescue StandardError => e
197
+ raise format_evaluate_error(e, value)
198
+ end
195
199
  else
196
200
  value
197
201
  end
@@ -203,6 +207,24 @@ module Bolt
203
207
  def evaluate(value, _scope)
204
208
  value
205
209
  end
210
+
211
+ def format_evaluate_error(error, value)
212
+ # The Puppet::PreformattedError includes the line number of the
213
+ # evaluable string that caused the error, while the value includes the
214
+ # line number of the YAML plan that the string began on. To get the
215
+ # actual line number of the error, add these two numbers together.
216
+ line = error.line + value.line
217
+
218
+ # If the evaluable string is not a scalar literal, correct for it
219
+ # being on the same line as the step key.
220
+ line -= 1 if value.is_a?(BareString)
221
+
222
+ Bolt::PlanFailure.new(
223
+ error.basic_message,
224
+ 'bolt/evaluation-error',
225
+ { file: value.file, line: line }
226
+ )
227
+ end
206
228
  end
207
229
  end
208
230
  end
@@ -9,10 +9,15 @@ module Bolt
9
9
  class YamlPlan
10
10
  class Loader
11
11
  class PuppetVisitor < Psych::Visitors::NoAliasRuby
12
- def self.create_visitor
12
+ def initialize(scanner, class_loader, file)
13
+ super(scanner, class_loader)
14
+ @file = file
15
+ end
16
+
17
+ def self.create_visitor(source_ref)
13
18
  class_loader = Psych::ClassLoader::Restricted.new([], [])
14
19
  scanner = Psych::ScalarScanner.new(class_loader)
15
- new(scanner, class_loader)
20
+ new(scanner, class_loader, source_ref)
16
21
  end
17
22
 
18
23
  def deserialize(node)
@@ -23,18 +28,18 @@ module Bolt
23
28
  # @ss is a ScalarScanner, from the base ToRuby visitor class
24
29
  node.value
25
30
  when Psych::Nodes::Scalar::DOUBLE_QUOTED
26
- DoubleQuotedString.new(node.value)
27
- # | style string or > style string
28
- when Psych::Nodes::Scalar::LITERAL, Psych::Nodes::Scalar::FOLDED
29
- CodeLiteral.new(node.value)
30
- # This one shouldn't be possible
31
+ DoubleQuotedString.new(node.value, @file, node.start_line + 1)
32
+ # | style string
33
+ when Psych::Nodes::Scalar::LITERAL
34
+ CodeLiteral.new(node.value, @file, node.start_line + 1)
35
+ # > style string
31
36
  else
32
37
  @ss.tokenize(node.value)
33
38
  end
34
39
  else
35
40
  value = @ss.tokenize(node.value)
36
41
  if value.is_a?(String)
37
- BareString.new(value)
42
+ BareString.new(value, @file, node.start_line + 1)
38
43
  else
39
44
  value
40
45
  end
@@ -50,7 +55,7 @@ module Bolt
50
55
  else
51
56
  Psych.parse(yaml_string, source_ref)
52
57
  end
53
- PuppetVisitor.create_visitor.accept(parse_tree)
58
+ PuppetVisitor.create_visitor(source_ref).accept(parse_tree)
54
59
  end
55
60
 
56
61
  def self.from_string(name, yaml_string, source_ref)
@@ -168,7 +168,7 @@ module Bolt
168
168
  end
169
169
 
170
170
  def modules
171
- @modules ||= Bolt::Module.discover(@pal.modulepath)
171
+ @modules ||= Bolt::Module.discover(@pal.full_modulepath)
172
172
  end
173
173
 
174
174
  def add_plugin(plugin)
@@ -16,7 +16,7 @@ module Bolt
16
16
  mod = modules[name]
17
17
  if mod&.plugin?
18
18
  opts[:mod] = mod
19
- plugin = Bolt::Plugin::Module.new(opts)
19
+ plugin = Bolt::Plugin::Module.new(**opts)
20
20
  plugin.setup
21
21
  plugin
22
22
  else
@@ -16,9 +16,10 @@ module Bolt
16
16
  "These tasks are included in `bolt task show` output"
17
17
  }.freeze
18
18
 
19
- attr_reader :path, :data, :config_file, :inventory_file, :modulepath, :hiera_config,
19
+ attr_reader :path, :data, :config_file, :inventory_file, :hiera_config,
20
20
  :puppetfile, :rerunfile, :type, :resource_types, :logs, :project_file,
21
- :deprecations, :downloads, :plans_path
21
+ :deprecations, :downloads, :plans_path, :modulepath, :managed_moduledir,
22
+ :backup_dir
22
23
 
23
24
  def self.default_project(logs = [])
24
25
  create_project(File.expand_path(File.join('~', '.puppetlabs', 'bolt')), 'user', logs)
@@ -94,15 +95,16 @@ module Bolt
94
95
  @deprecations << { type: 'Using bolt.yaml for project configuration', msg: msg }
95
96
  end
96
97
 
97
- @inventory_file = @path + 'inventory.yaml'
98
- @modulepath = [(@path + 'modules').to_s, (@path + 'site-modules').to_s, (@path + 'site').to_s]
99
- @hiera_config = @path + 'hiera.yaml'
100
- @puppetfile = @path + 'Puppetfile'
101
- @rerunfile = @path + '.rerun.json'
102
- @resource_types = @path + '.resource_types'
103
- @type = type
104
- @downloads = @path + 'downloads'
105
- @plans_path = @path + 'plans'
98
+ @inventory_file = @path + 'inventory.yaml'
99
+ @hiera_config = @path + 'hiera.yaml'
100
+ @puppetfile = @path + 'Puppetfile'
101
+ @rerunfile = @path + '.rerun.json'
102
+ @resource_types = @path + '.resource_types'
103
+ @type = type
104
+ @downloads = @path + 'downloads'
105
+ @plans_path = @path + 'plans'
106
+ @managed_moduledir = @path + '.modules'
107
+ @backup_dir = @path + '.bolt-bak'
106
108
 
107
109
  tc = Bolt::Config::INVENTORY_OPTIONS.keys & raw_data.keys
108
110
  if tc.any?
@@ -112,6 +114,14 @@ module Bolt
112
114
 
113
115
  @data = raw_data.reject { |k, _| Bolt::Config::INVENTORY_OPTIONS.include?(k) }
114
116
 
117
+ # If the 'modules' key is present in the project configuration file,
118
+ # use the new, shorter modulepath.
119
+ @modulepath = if @data.key?('modules')
120
+ [(@path + 'modules').to_s]
121
+ else
122
+ [(@path + 'modules').to_s, (@path + 'site-modules').to_s, (@path + 'site').to_s]
123
+ end
124
+
115
125
  # Once bolt.yaml deprecation is removed, this attribute should be removed
116
126
  # and replaced with .project_file in lib/bolt/config.rb
117
127
  @config_file = if (Bolt::Config::BOLT_OPTIONS & @data.keys).any?
@@ -164,7 +174,13 @@ module Bolt
164
174
  end
165
175
 
166
176
  def modules
167
- @data['modules']
177
+ @modules ||= @data['modules']&.map do |mod|
178
+ if mod.is_a?(String)
179
+ { 'name' => mod }
180
+ else
181
+ mod
182
+ end
183
+ end
168
184
  end
169
185
 
170
186
  def validate
@@ -174,7 +190,7 @@ module Bolt
174
190
  Invalid project name '#{name}' in bolt-project.yaml; project name must begin with a lowercase letter
175
191
  and can include lowercase letters, numbers, and underscores.
176
192
  ERROR_STRING
177
- elsif Dir.children(Bolt::PAL::BOLTLIB_PATH).include?(name)
193
+ elsif Dir.children(Bolt::Config::Modulepath::BOLTLIB_PATH).include?(name)
178
194
  raise Bolt::ValidationError, "The project '#{name}' will not be loaded. The project name conflicts "\
179
195
  "with a built-in Bolt module of the same name."
180
196
  end
@@ -194,15 +210,9 @@ module Bolt
194
210
  raise Bolt::ValidationError, "'modules' in bolt-project.yaml must be an array"
195
211
  end
196
212
 
197
- @data['modules'].each do |mod|
198
- next if mod.is_a?(Hash)
199
- raise Bolt::ValidationError, "Module declaration #{mod.inspect} must be a hash"
200
- end
201
-
202
- unknown_keys = data['modules'].flat_map(&:keys).uniq - ['name']
203
- if unknown_keys.any?
204
- @logs << { warn: "Module declarations in bolt-project.yaml only support a name key. Ignoring "\
205
- "unsupported keys: #{unknown_keys.join(', ')}." }
213
+ @data['modules'].each do |spec|
214
+ next if spec.is_a?(Hash) || spec.is_a?(String)
215
+ raise Bolt::ValidationError, "Module specification #{spec.inspect} must be a hash or string"
206
216
  end
207
217
  end
208
218
  end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bolt/project_migrator/config'
4
+ require 'bolt/project_migrator/inventory'
5
+ require 'bolt/project_migrator/modules'
6
+
7
+ module Bolt
8
+ class ProjectMigrator
9
+ def initialize(config, outputter)
10
+ @config = config
11
+ @outputter = outputter
12
+ end
13
+
14
+ def migrate
15
+ unless $stdin.tty?
16
+ raise Bolt::Error.new(
17
+ "stdin is not a tty, unable to migrate project",
18
+ 'bolt/stdin-not-a-tty-error'
19
+ )
20
+ end
21
+
22
+ @outputter.print_message("Migrating project #{@config.project.path}\n\n")
23
+
24
+ @outputter.print_action_step(
25
+ "Migrating a Bolt project may make irreversible changes to the project's "\
26
+ "configuration and inventory files. Before continuing, make sure the "\
27
+ "project has a backup or uses a version control system."
28
+ )
29
+
30
+ return 0 unless Bolt::Util.prompt_yes_no("Continue with project migration?", @outputter)
31
+
32
+ @outputter.print_message('')
33
+
34
+ ok = migrate_inventory && migrate_config && migrate_modules
35
+
36
+ if ok
37
+ @outputter.print_message("Project successfully migrated")
38
+ else
39
+ @outputter.print_error("Project could not be migrated completely")
40
+ end
41
+
42
+ ok ? 0 : 1
43
+ end
44
+
45
+ # Migrates the project-level configuration file to the latest version.
46
+ #
47
+ private def migrate_config
48
+ migrator = Bolt::ProjectMigrator::Config.new(@outputter)
49
+
50
+ migrator.migrate(
51
+ @config.project.config_file,
52
+ @config.project.project_file,
53
+ @config.inventoryfile || @config.project.inventory_file,
54
+ @config.project.backup_dir
55
+ )
56
+ end
57
+
58
+ # Migrates the inventory file to the latest version.
59
+ #
60
+ private def migrate_inventory
61
+ migrator = Bolt::ProjectMigrator::Inventory.new(@outputter)
62
+
63
+ migrator.migrate(
64
+ @config.inventoryfile || @config.project.inventory_file,
65
+ @config.project.backup_dir
66
+ )
67
+ end
68
+
69
+ # Migrates the project's modules to use current best practices.
70
+ #
71
+ private def migrate_modules
72
+ migrator = Bolt::ProjectMigrator::Modules.new(@outputter)
73
+
74
+ migrator.migrate(
75
+ @config.project,
76
+ @config.modulepath
77
+ )
78
+ end
79
+ end
80
+ end