bolt 2.33.2 → 2.38.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 +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 +48 -16
- data/lib/bolt/cli.rb +154 -249
- data/lib/bolt/config.rb +188 -55
- data/lib/bolt/config/options.rb +147 -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 +10 -68
- data/lib/bolt/config/transport/ssh.rb +8 -14
- data/lib/bolt/error.rb +33 -3
- data/lib/bolt/executor.rb +92 -6
- data/lib/bolt/inventory.rb +25 -0
- data/lib/bolt/inventory/group.rb +2 -1
- 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 +41 -10
- 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 +19 -7
- data/lib/bolt/pal/yaml_plan.rb +7 -0
- data/lib/bolt/plan_creator.rb +160 -0
- data/lib/bolt/plugin.rb +42 -13
- 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} +51 -5
- data/lib/bolt/{project_migrator/inventory.rb → project_manager/inventory_migrator.rb} +5 -5
- 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 +9 -8
- data/lib/bolt/rerun.rb +1 -5
- data/lib/bolt/shell/bash.rb +8 -2
- data/lib/bolt/shell/powershell.rb +22 -4
- 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/remote.rb +1 -1
- data/lib/bolt/transport/ssh/exec_connection.rb +6 -2
- data/lib/bolt/util.rb +41 -7
- data/lib/bolt/validator.rb +226 -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/file_cache.rb +2 -0
- 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 -13
- data/lib/bolt/project_migrator.rb +0 -80
data/lib/bolt/cli.rb
CHANGED
@@ -15,20 +15,22 @@ require 'bolt/config'
|
|
15
15
|
require 'bolt/error'
|
16
16
|
require 'bolt/executor'
|
17
17
|
require 'bolt/inventory'
|
18
|
-
require 'bolt/rerun'
|
19
18
|
require 'bolt/logger'
|
19
|
+
require 'bolt/module_installer'
|
20
20
|
require 'bolt/outputter'
|
21
|
-
require 'bolt/puppetdb'
|
22
|
-
require 'bolt/plugin'
|
23
|
-
require 'bolt/project_migrator'
|
24
21
|
require 'bolt/pal'
|
22
|
+
require 'bolt/plan_creator'
|
23
|
+
require 'bolt/plugin'
|
24
|
+
require 'bolt/project_manager'
|
25
|
+
require 'bolt/puppetdb'
|
26
|
+
require 'bolt/rerun'
|
27
|
+
require 'bolt/secret'
|
25
28
|
require 'bolt/target'
|
26
29
|
require 'bolt/version'
|
27
|
-
require 'bolt/secret'
|
28
|
-
require 'bolt/module_installer'
|
29
30
|
|
30
31
|
module Bolt
|
31
32
|
class CLIExit < StandardError; end
|
33
|
+
|
32
34
|
class CLI
|
33
35
|
COMMANDS = {
|
34
36
|
'command' => %w[run],
|
@@ -163,8 +165,9 @@ module Bolt
|
|
163
165
|
elsif options[:configfile]
|
164
166
|
Bolt::Config.from_file(options[:configfile], options)
|
165
167
|
else
|
166
|
-
|
167
|
-
|
168
|
+
cli_flag = options[:project] || options[:boltdir]
|
169
|
+
project = if cli_flag
|
170
|
+
dir = Pathname.new(cli_flag)
|
168
171
|
if (dir + Bolt::Project::BOLTDIR_NAME).directory?
|
169
172
|
Bolt::Project.create_project(dir + Bolt::Project::BOLTDIR_NAME)
|
170
173
|
else
|
@@ -194,11 +197,12 @@ module Bolt
|
|
194
197
|
@parser_deprecations.each { |dep| Bolt::Logger.deprecation_warning(dep[:type], dep[:msg]) }
|
195
198
|
config.deprecations.each { |dep| Bolt::Logger.deprecation_warning(dep[:type], dep[:msg]) }
|
196
199
|
|
197
|
-
|
200
|
+
if options[:clear_cache] && File.exist?(config.project.cache_file)
|
201
|
+
FileUtils.rm(config.project.cache_file)
|
202
|
+
end
|
198
203
|
|
199
|
-
|
200
|
-
|
201
|
-
assert_puppetfile_or_module_command(config.project.modules)
|
204
|
+
warn_inventory_overrides_cli(options)
|
205
|
+
validate_ps_version
|
202
206
|
|
203
207
|
options
|
204
208
|
rescue Bolt::Error => e
|
@@ -206,6 +210,17 @@ module Bolt
|
|
206
210
|
raise e
|
207
211
|
end
|
208
212
|
|
213
|
+
private def validate_ps_version
|
214
|
+
if Bolt::Util.powershell?
|
215
|
+
target = inventory.get_target('localhost')
|
216
|
+
Bolt::Transport::Local.new.with_connection(target) do |conn|
|
217
|
+
# This will automatically validate the powershell version on the Bolt
|
218
|
+
# controller
|
219
|
+
Bolt::Shell::Powershell.new(target, conn)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
209
224
|
def update_targets(options)
|
210
225
|
target_opts = options.keys.select { |opt| %i[query rerun targets].include?(opt) }
|
211
226
|
target_string = "'--targets', '--rerun', or '--query'"
|
@@ -228,9 +243,9 @@ module Bolt
|
|
228
243
|
|
229
244
|
def validate(options)
|
230
245
|
unless COMMANDS.include?(options[:subcommand])
|
246
|
+
command = Bolt::Util.powershell? ? 'Get-Command -Module PuppetBolt' : 'bolt help'
|
231
247
|
raise Bolt::CLIError,
|
232
|
-
"
|
233
|
-
"#{COMMANDS.keys.join(', ')}"
|
248
|
+
"'#{options[:subcommand]}' is not a Bolt command. See '#{command}'."
|
234
249
|
end
|
235
250
|
|
236
251
|
actions = COMMANDS[options[:subcommand]]
|
@@ -285,8 +300,9 @@ module Bolt
|
|
285
300
|
end
|
286
301
|
|
287
302
|
if options[:subcommand] == 'module' && options[:action] == 'install' && options[:object]
|
303
|
+
command = Bolt::Util.powershell? ? 'Add-BoltModule -Module' : 'bolt module add'
|
288
304
|
raise Bolt::CLIError, "Invalid argument '#{options[:object]}'. To add a new module to "\
|
289
|
-
"the project, run '
|
305
|
+
"the project, run '#{command} #{options[:object]}'."
|
290
306
|
end
|
291
307
|
|
292
308
|
if options[:subcommand] != 'file' && options[:subcommand] != 'script' &&
|
@@ -295,7 +311,7 @@ module Bolt
|
|
295
311
|
"Unknown argument(s) #{options[:leftovers].join(', ')}"
|
296
312
|
end
|
297
313
|
|
298
|
-
if options
|
314
|
+
if options.slice(:boltdir, :configfile, :project).length > 1
|
299
315
|
raise Bolt::CLIError, "Only one of '--boltdir', '--project', or '--configfile' may be specified"
|
300
316
|
end
|
301
317
|
|
@@ -342,15 +358,10 @@ module Bolt
|
|
342
358
|
def warn_inventory_overrides_cli(opts)
|
343
359
|
inventory_source = if ENV[Bolt::Inventory::ENVIRONMENT_VAR]
|
344
360
|
Bolt::Inventory::ENVIRONMENT_VAR
|
345
|
-
elsif config.inventoryfile
|
361
|
+
elsif config.inventoryfile
|
346
362
|
config.inventoryfile
|
347
|
-
|
348
|
-
|
349
|
-
Bolt::Util.file_stat(config.default_inventoryfile)
|
350
|
-
config.default_inventoryfile
|
351
|
-
rescue Errno::ENOENT
|
352
|
-
nil
|
353
|
-
end
|
363
|
+
elsif File.exist?(config.default_inventoryfile)
|
364
|
+
config.default_inventoryfile
|
354
365
|
end
|
355
366
|
|
356
367
|
inventory_cli_opts = %i[authentication escalation transports].each_with_object([]) do |key, acc|
|
@@ -394,7 +405,7 @@ module Bolt
|
|
394
405
|
output_format: config.format,
|
395
406
|
# For continuity
|
396
407
|
boltdir_type: config.project.type
|
397
|
-
}
|
408
|
+
}.merge!(analytics.plan_counts(config.project.plans_path))
|
398
409
|
|
399
410
|
# Only include target and inventory info for commands that take a targets
|
400
411
|
# list. This avoids loading inventory for commands that don't need it.
|
@@ -458,23 +469,31 @@ module Bolt
|
|
458
469
|
when 'project'
|
459
470
|
case options[:action]
|
460
471
|
when 'init'
|
461
|
-
code =
|
472
|
+
code = Bolt::ProjectManager.new(config, outputter, pal)
|
473
|
+
.create(Dir.pwd, options[:object], options[:modules])
|
462
474
|
when 'migrate'
|
463
|
-
code = Bolt::
|
475
|
+
code = Bolt::ProjectManager.new(config, outputter, pal).migrate
|
464
476
|
end
|
465
477
|
when 'plan'
|
466
478
|
case options[:action]
|
467
479
|
when 'new'
|
468
|
-
|
480
|
+
plan_name = options[:object]
|
481
|
+
|
482
|
+
# If this passes validation, it will return the path to the plan to create
|
483
|
+
Bolt::PlanCreator.validate_input(config.project, plan_name)
|
484
|
+
code = Bolt::PlanCreator.create_plan(config.project.plans_path,
|
485
|
+
plan_name,
|
486
|
+
outputter,
|
487
|
+
options[:puppet])
|
469
488
|
when 'run'
|
470
489
|
code = run_plan(options[:object], options[:task_options], options[:target_args], options)
|
471
490
|
end
|
472
491
|
when 'module'
|
473
492
|
case options[:action]
|
474
493
|
when 'add'
|
475
|
-
code = add_project_module(options[:object], config.project)
|
494
|
+
code = add_project_module(options[:object], config.project, config.module_install)
|
476
495
|
when 'install'
|
477
|
-
code = install_project_modules(config.project, options[:force], options[:resolve])
|
496
|
+
code = install_project_modules(config.project, config.module_install, options[:force], options[:resolve])
|
478
497
|
when 'generate-types'
|
479
498
|
code = generate_types
|
480
499
|
end
|
@@ -519,12 +538,15 @@ module Bolt
|
|
519
538
|
validate_file('script', script)
|
520
539
|
executor.run_script(targets, script, options[:leftovers], executor_opts)
|
521
540
|
when 'task'
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
541
|
+
r = outputter.spin do
|
542
|
+
pal.run_task(options[:object],
|
543
|
+
targets,
|
544
|
+
options[:task_options],
|
545
|
+
executor,
|
546
|
+
inventory,
|
547
|
+
options[:description])
|
548
|
+
end
|
549
|
+
r
|
528
550
|
when 'file'
|
529
551
|
src = options[:object]
|
530
552
|
dest = options[:leftovers].first
|
@@ -568,10 +590,15 @@ module Bolt
|
|
568
590
|
outputter.print_task_info(pal.get_task(task_name))
|
569
591
|
end
|
570
592
|
|
593
|
+
# Filters a list of content by matching substring.
|
594
|
+
#
|
595
|
+
private def filter_content(content, filter)
|
596
|
+
return content unless content && filter
|
597
|
+
content.select { |name,| name.include?(filter) }
|
598
|
+
end
|
599
|
+
|
571
600
|
def list_tasks
|
572
|
-
tasks = pal.list_tasks
|
573
|
-
tasks.select! { |task| task.first.include?(options[:filter]) } if options[:filter]
|
574
|
-
tasks.select! { |task| config.project.tasks.include?(task.first) } unless config.project.tasks.nil?
|
601
|
+
tasks = filter_content(pal.list_tasks(filter_content: true), options[:filter])
|
575
602
|
outputter.print_tasks(tasks, pal.user_modulepath)
|
576
603
|
end
|
577
604
|
|
@@ -580,9 +607,7 @@ module Bolt
|
|
580
607
|
end
|
581
608
|
|
582
609
|
def list_plans
|
583
|
-
plans = pal.list_plans
|
584
|
-
plans.select! { |plan| plan.first.include?(options[:filter]) } if options[:filter]
|
585
|
-
plans.select! { |plan| config.project.plans.include?(plan.first) } unless config.project.plans.nil?
|
610
|
+
plans = filter_content(pal.list_plans(filter_content: true), options[:filter])
|
586
611
|
outputter.print_plans(plans, pal.user_modulepath)
|
587
612
|
end
|
588
613
|
|
@@ -617,118 +642,6 @@ module Bolt
|
|
617
642
|
outputter.print_groups(groups)
|
618
643
|
end
|
619
644
|
|
620
|
-
def new_plan(plan_name)
|
621
|
-
@logger.warn("Command 'bolt plan new' is experimental and subject to changes.")
|
622
|
-
|
623
|
-
if config.project.name.nil?
|
624
|
-
raise Bolt::Error.new(
|
625
|
-
"Project directory '#{config.project.path}' is not a named project. Unable to create "\
|
626
|
-
"a project-level plan. To name a project, set the 'name' key in the 'bolt-project.yaml' "\
|
627
|
-
"configuration file.",
|
628
|
-
"bolt/unnamed-project-error"
|
629
|
-
)
|
630
|
-
end
|
631
|
-
|
632
|
-
if plan_name !~ Bolt::Module::CONTENT_NAME_REGEX
|
633
|
-
message = <<~MESSAGE.chomp
|
634
|
-
Invalid plan name '#{plan_name}'. Plan names are composed of one or more name segments
|
635
|
-
separated by double colons '::'.
|
636
|
-
|
637
|
-
Each name segment must begin with a lowercase letter, and may only include lowercase
|
638
|
-
letters, digits, and underscores.
|
639
|
-
|
640
|
-
Examples of valid plan names:
|
641
|
-
- #{config.project.name}
|
642
|
-
- #{config.project.name}::my_plan
|
643
|
-
MESSAGE
|
644
|
-
|
645
|
-
raise Bolt::ValidationError, message
|
646
|
-
end
|
647
|
-
|
648
|
-
prefix, *name_segments, basename = plan_name.split('::')
|
649
|
-
|
650
|
-
# If the plan name is just the project name, then create an 'init' plan.
|
651
|
-
# Otherwise, use the last name segment for the plan's filename.
|
652
|
-
basename ||= 'init'
|
653
|
-
|
654
|
-
unless prefix == config.project.name
|
655
|
-
message = "First segment of plan name '#{plan_name}' must match project name '#{config.project.name}'. "\
|
656
|
-
"Did you mean '#{config.project.name}::#{plan_name}'?"
|
657
|
-
|
658
|
-
raise Bolt::ValidationError, message
|
659
|
-
end
|
660
|
-
|
661
|
-
dir_path = config.project.plans_path.join(*name_segments)
|
662
|
-
|
663
|
-
%w[pp yaml].each do |ext|
|
664
|
-
next unless (path = config.project.plans_path + "#{basename}.#{ext}").exist?
|
665
|
-
raise Bolt::Error.new(
|
666
|
-
"A plan with the name '#{plan_name}' already exists at '#{path}', nothing to do.",
|
667
|
-
'bolt/existing-plan-error'
|
668
|
-
)
|
669
|
-
end
|
670
|
-
|
671
|
-
begin
|
672
|
-
FileUtils.mkdir_p(dir_path)
|
673
|
-
rescue Errno::EEXIST => e
|
674
|
-
raise Bolt::Error.new(
|
675
|
-
"#{e.message}; unable to create plan directory '#{dir_path}'",
|
676
|
-
'bolt/existing-file-error'
|
677
|
-
)
|
678
|
-
end
|
679
|
-
|
680
|
-
plan_path = dir_path + "#{basename}.yaml"
|
681
|
-
|
682
|
-
plan_template = <<~PLAN
|
683
|
-
# This is the structure of a simple plan. To learn more about writing
|
684
|
-
# YAML plans, see the documentation: http://pup.pt/bolt-yaml-plans
|
685
|
-
|
686
|
-
# The description sets the description of the plan that will appear
|
687
|
-
# in 'bolt plan show' output.
|
688
|
-
description: A plan created with bolt plan new
|
689
|
-
|
690
|
-
# The parameters key defines the parameters that can be passed to
|
691
|
-
# the plan.
|
692
|
-
parameters:
|
693
|
-
targets:
|
694
|
-
type: TargetSpec
|
695
|
-
description: A list of targets to run actions on
|
696
|
-
default: localhost
|
697
|
-
|
698
|
-
# The steps key defines the actions the plan will take in order.
|
699
|
-
steps:
|
700
|
-
- message: Hello from #{plan_name}
|
701
|
-
- name: command_step
|
702
|
-
command: whoami
|
703
|
-
targets: $targets
|
704
|
-
|
705
|
-
# The return key sets the return value of the plan.
|
706
|
-
return: $command_step
|
707
|
-
PLAN
|
708
|
-
|
709
|
-
begin
|
710
|
-
File.write(plan_path, plan_template)
|
711
|
-
rescue Errno::EACCES => e
|
712
|
-
raise Bolt::FileError.new(
|
713
|
-
"#{e.message}; unable to create plan",
|
714
|
-
plan_path
|
715
|
-
)
|
716
|
-
end
|
717
|
-
|
718
|
-
output = <<~OUTPUT
|
719
|
-
Created plan '#{plan_name}' at '#{plan_path}'
|
720
|
-
|
721
|
-
Show this plan with:
|
722
|
-
bolt plan show #{plan_name}
|
723
|
-
Run this plan with:
|
724
|
-
bolt plan run #{plan_name}
|
725
|
-
OUTPUT
|
726
|
-
|
727
|
-
outputter.print_message(output)
|
728
|
-
|
729
|
-
0
|
730
|
-
end
|
731
|
-
|
732
645
|
def run_plan(plan_name, plan_arguments, nodes, options)
|
733
646
|
unless nodes.empty?
|
734
647
|
if plan_arguments['nodes'] || plan_arguments['targets']
|
@@ -768,7 +681,9 @@ module Bolt
|
|
768
681
|
|
769
682
|
executor.subscribe(log_outputter)
|
770
683
|
executor.start_plan(plan_context)
|
771
|
-
result =
|
684
|
+
result = outputter.spin do
|
685
|
+
pal.run_plan(plan_name, plan_arguments, executor, inventory, puppetdb_client)
|
686
|
+
end
|
772
687
|
|
773
688
|
# If a non-bolt exception bubbles up the plan won't get finished
|
774
689
|
executor.finish_plan(result)
|
@@ -820,88 +735,22 @@ module Bolt
|
|
820
735
|
end
|
821
736
|
|
822
737
|
def list_modules
|
738
|
+
assert_puppetfile_or_module_command(config.project.modules)
|
823
739
|
outputter.print_module_list(pal.list_modules)
|
824
740
|
end
|
825
741
|
|
826
742
|
def generate_types
|
743
|
+
assert_puppetfile_or_module_command(config.project.modules)
|
827
744
|
# generate_types will surface a nice error with helpful message if it fails
|
828
745
|
pal.generate_types
|
829
746
|
0
|
830
747
|
end
|
831
748
|
|
832
|
-
# Initializes a specified directory as a Bolt project and installs any modules
|
833
|
-
# specified by the user, along with their dependencies
|
834
|
-
def initialize_project
|
835
|
-
# Dir.pwd will return backslashes on Windows, but Pathname always uses
|
836
|
-
# forward slashes to concatenate paths. This results in paths like
|
837
|
-
# C:\User\Administrator/modules, which fail module install. This ensure
|
838
|
-
# forward slashes in the cwd path.
|
839
|
-
dir = File.expand_path(Dir.pwd)
|
840
|
-
name = options[:object] || File.basename(dir)
|
841
|
-
if name !~ Bolt::Module::MODULE_NAME_REGEX
|
842
|
-
if options[:object]
|
843
|
-
raise Bolt::ValidationError, "The provided project name '#{name}' is invalid; "\
|
844
|
-
"project name must begin with a lowercase letter and can include lowercase "\
|
845
|
-
"letters, numbers, and underscores."
|
846
|
-
else
|
847
|
-
raise Bolt::ValidationError, "The current directory name '#{name}' is an invalid "\
|
848
|
-
"project name. Please specify a name using 'bolt project init <name>'."
|
849
|
-
end
|
850
|
-
end
|
851
|
-
|
852
|
-
project = Pathname.new(dir)
|
853
|
-
old_config = project + 'bolt.yaml'
|
854
|
-
config = project + 'bolt-project.yaml'
|
855
|
-
puppetfile = project + 'Puppetfile'
|
856
|
-
moduledir = project + 'modules'
|
857
|
-
|
858
|
-
# Warn the user if the project directory already exists. We don't error
|
859
|
-
# here since users might not have installed any modules yet. If both
|
860
|
-
# bolt.yaml and bolt-project.yaml exist, this will just warn about
|
861
|
-
# bolt-project.yaml and subsequent Bolt actions will warn about both files
|
862
|
-
# existing.
|
863
|
-
if config.exist?
|
864
|
-
@logger.warn "Found existing project directory at #{project}. Skipping file creation."
|
865
|
-
elsif old_config.exist?
|
866
|
-
@logger.warn "Found existing #{old_config.basename} at #{project}. "\
|
867
|
-
"#{old_config.basename} is deprecated, please rename to #{config.basename}."
|
868
|
-
end
|
869
|
-
|
870
|
-
# If modules were specified, first check if there is already a Puppetfile
|
871
|
-
# at the project directory, erroring if there is. If there is no
|
872
|
-
# Puppetfile, install the specified modules. The module installer will
|
873
|
-
# resolve dependencies, generate a Puppetfile, and install the modules.
|
874
|
-
if options[:modules]
|
875
|
-
if puppetfile.exist?
|
876
|
-
raise Bolt::CLIError,
|
877
|
-
"Found existing Puppetfile at #{puppetfile}, unable to initialize "\
|
878
|
-
"project with modules."
|
879
|
-
end
|
880
|
-
|
881
|
-
installer = Bolt::ModuleInstaller.new(outputter, pal)
|
882
|
-
installer.install(options[:modules], puppetfile, moduledir)
|
883
|
-
end
|
884
|
-
|
885
|
-
# If either bolt.yaml or bolt-project.yaml exist, the user has already
|
886
|
-
# been warned and we can just finish project creation. Otherwise, create a
|
887
|
-
# bolt-project.yaml with the project name in it.
|
888
|
-
unless config.exist? || old_config.exist?
|
889
|
-
begin
|
890
|
-
content = { 'name' => name }
|
891
|
-
File.write(config.to_path, content.to_yaml)
|
892
|
-
outputter.print_message "Successfully created Bolt project at #{project}"
|
893
|
-
rescue StandardError => e
|
894
|
-
raise Bolt::FileError.new("Could not create bolt-project.yaml at #{project}: #{e.message}", nil)
|
895
|
-
end
|
896
|
-
end
|
897
|
-
|
898
|
-
0
|
899
|
-
end
|
900
|
-
|
901
749
|
# Installs modules declared in the project configuration file.
|
902
750
|
#
|
903
|
-
def install_project_modules(project, force, resolve)
|
751
|
+
def install_project_modules(project, config, force, resolve)
|
904
752
|
assert_project_file(project)
|
753
|
+
assert_puppetfile_or_module_command(project.modules)
|
905
754
|
|
906
755
|
unless project.modules
|
907
756
|
outputter.print_message "Project configuration file #{project.project_file} does not "\
|
@@ -909,29 +758,55 @@ module Bolt
|
|
909
758
|
return 0
|
910
759
|
end
|
911
760
|
|
761
|
+
if resolve != false && config.any?
|
762
|
+
@logger.warn(
|
763
|
+
"Detected configuration for 'module-install'. This configuration is currently "\
|
764
|
+
"only supported when installing modules, not when resolving module dependencies. "\
|
765
|
+
"For more information, see https://pup.pt/bolt-module-install"
|
766
|
+
)
|
767
|
+
end
|
768
|
+
|
769
|
+
modules = project.modules || []
|
912
770
|
installer = Bolt::ModuleInstaller.new(outputter, pal)
|
913
771
|
|
914
|
-
ok =
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
772
|
+
ok = outputter.spin do
|
773
|
+
installer.install(modules,
|
774
|
+
project.puppetfile,
|
775
|
+
project.managed_moduledir,
|
776
|
+
config,
|
777
|
+
force: force,
|
778
|
+
resolve: resolve)
|
779
|
+
end
|
780
|
+
|
919
781
|
ok ? 0 : 1
|
920
782
|
end
|
921
783
|
|
922
784
|
# Adds a single module to the project.
|
923
785
|
#
|
924
|
-
def add_project_module(name, project)
|
786
|
+
def add_project_module(name, project, config)
|
925
787
|
assert_project_file(project)
|
788
|
+
assert_puppetfile_or_module_command(project.modules)
|
789
|
+
|
790
|
+
if config.any?
|
791
|
+
@logger.warn(
|
792
|
+
"Detected configuration for 'module-install'. This configuration is currently "\
|
793
|
+
"only supported when installing modules, not when resolving module dependencies. "\
|
794
|
+
"For more information, see https://pup.pt/bolt-module-install"
|
795
|
+
)
|
796
|
+
end
|
926
797
|
|
927
798
|
modules = project.modules || []
|
928
799
|
installer = Bolt::ModuleInstaller.new(outputter, pal)
|
929
800
|
|
930
|
-
ok =
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
801
|
+
ok = outputter.spin do
|
802
|
+
installer.add(name,
|
803
|
+
modules,
|
804
|
+
project.puppetfile,
|
805
|
+
project.managed_moduledir,
|
806
|
+
project.project_file,
|
807
|
+
config)
|
808
|
+
end
|
809
|
+
|
935
810
|
ok ? 0 : 1
|
936
811
|
end
|
937
812
|
|
@@ -940,11 +815,13 @@ module Bolt
|
|
940
815
|
def assert_project_file(project)
|
941
816
|
unless project.project_file?
|
942
817
|
msg = if project.config_file.exist?
|
818
|
+
command = Bolt::Util.powershell? ? 'Update-BoltProject' : 'bolt project migrate'
|
943
819
|
"Detected Bolt configuration file #{project.config_file}, unable to install "\
|
944
|
-
"modules. To update to a project configuration file, run '
|
820
|
+
"modules. To update to a project configuration file, run '#{command}'."
|
945
821
|
else
|
822
|
+
command = Bolt::Util.powershell? ? 'New-BoltProject' : 'bolt project init'
|
946
823
|
"Could not find project configuration file #{project.project_file}, unable "\
|
947
|
-
"to install modules. To create a Bolt project, run '
|
824
|
+
"to install modules. To create a Bolt project, run '#{command}'."
|
948
825
|
end
|
949
826
|
|
950
827
|
raise Bolt::Error.new(msg, 'bolt/missing-project-config-error')
|
@@ -953,10 +830,15 @@ module Bolt
|
|
953
830
|
|
954
831
|
# Loads a Puppetfile and installs its modules.
|
955
832
|
#
|
956
|
-
def install_puppetfile(
|
833
|
+
def install_puppetfile(puppetfile_config, puppetfile, moduledir)
|
834
|
+
assert_puppetfile_or_module_command(config.project.modules)
|
835
|
+
|
957
836
|
outputter.print_message("Installing modules from Puppetfile")
|
958
837
|
installer = Bolt::ModuleInstaller.new(outputter, pal)
|
959
|
-
ok =
|
838
|
+
ok = outputter.spin do
|
839
|
+
installer.install_puppetfile(puppetfile, moduledir, puppetfile_config)
|
840
|
+
end
|
841
|
+
|
960
842
|
ok ? 0 : 1
|
961
843
|
end
|
962
844
|
|
@@ -964,17 +846,36 @@ module Bolt
|
|
964
846
|
# modules being configured.
|
965
847
|
#
|
966
848
|
def assert_puppetfile_or_module_command(modules)
|
849
|
+
if Bolt::Util.powershell?
|
850
|
+
case options[:action]
|
851
|
+
when 'generate-types'
|
852
|
+
old_command = 'Register-BoltPuppetfileTypes'
|
853
|
+
new_command = 'Register-BoltModuleTypes'
|
854
|
+
when 'install'
|
855
|
+
old_command = 'Install-BoltPuppetfile'
|
856
|
+
new_command = 'Install-BoltModule'
|
857
|
+
when 'show', 'show-modules'
|
858
|
+
old_command = 'Get-BoltPuppetfileModules'
|
859
|
+
new_command = 'Get-BoltModule'
|
860
|
+
end
|
861
|
+
else
|
862
|
+
old_command = "bolt puppetfile #{options[:action]}"
|
863
|
+
new_command = if options[:action] == 'show-modules'
|
864
|
+
'bolt module show'
|
865
|
+
else
|
866
|
+
"bolt module #{options[:action]}"
|
867
|
+
end
|
868
|
+
end
|
869
|
+
|
967
870
|
if modules && options[:subcommand] == 'puppetfile'
|
968
871
|
raise Bolt::CLIError,
|
969
|
-
"Unable to use command '
|
970
|
-
"
|
971
|
-
"instead. For a list of available actions for the 'module' command, run "\
|
972
|
-
"'bolt module --help'."
|
872
|
+
"Unable to use command '#{old_command}' when 'modules' is configured in "\
|
873
|
+
"bolt-project.yaml. Use '#{new_command}' instead."
|
973
874
|
elsif modules.nil? && options[:subcommand] == 'module'
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
875
|
+
msg = "Unable to use command '#{new_command}' when 'modules' is not configured in "\
|
876
|
+
"bolt-project.yaml. "
|
877
|
+
msg += "Use '#{old_command}' instead." if options[:action] != 'add'
|
878
|
+
raise Bolt::CLIError, msg
|
978
879
|
end
|
979
880
|
end
|
980
881
|
|
@@ -1043,7 +944,11 @@ module Bolt
|
|
1043
944
|
end
|
1044
945
|
|
1045
946
|
def outputter
|
1046
|
-
@outputter ||= Bolt::Outputter.for_format(config.format,
|
947
|
+
@outputter ||= Bolt::Outputter.for_format(config.format,
|
948
|
+
config.color,
|
949
|
+
options[:verbose],
|
950
|
+
config.trace,
|
951
|
+
config.spinner)
|
1047
952
|
end
|
1048
953
|
|
1049
954
|
def log_outputter
|