bolt 2.44.0 → 3.4.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 +11 -9
- data/bolt-modules/boltlib/lib/puppet/functions/add_facts.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +25 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +20 -2
- data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +2 -2
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +44 -5
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb +7 -3
- data/bolt-modules/file/lib/puppet/functions/file/read.rb +3 -2
- data/bolt-modules/prompt/lib/puppet/functions/prompt.rb +20 -2
- data/bolt-modules/prompt/lib/puppet/functions/prompt/menu.rb +103 -0
- data/lib/bolt/apply_result.rb +1 -1
- data/lib/bolt/bolt_option_parser.rb +9 -123
- data/lib/bolt/cli.rb +125 -127
- data/lib/bolt/config.rb +39 -214
- data/lib/bolt/config/options.rb +34 -125
- data/lib/bolt/config/transport/local.rb +1 -0
- data/lib/bolt/config/transport/lxd.rb +23 -0
- data/lib/bolt/config/transport/options.rb +9 -2
- data/lib/bolt/executor.rb +20 -5
- data/lib/bolt/logger.rb +9 -1
- data/lib/bolt/module_installer.rb +2 -2
- data/lib/bolt/module_installer/puppetfile.rb +2 -2
- data/lib/bolt/module_installer/specs/forge_spec.rb +2 -2
- data/lib/bolt/module_installer/specs/git_spec.rb +2 -2
- data/lib/bolt/node/output.rb +14 -4
- data/lib/bolt/outputter/human.rb +52 -24
- data/lib/bolt/outputter/json.rb +16 -16
- data/lib/bolt/pal.rb +26 -5
- data/lib/bolt/pal/yaml_plan.rb +1 -2
- data/lib/bolt/pal/yaml_plan/evaluator.rb +5 -153
- data/lib/bolt/pal/yaml_plan/step.rb +91 -52
- data/lib/bolt/pal/yaml_plan/step/command.rb +21 -13
- data/lib/bolt/pal/yaml_plan/step/download.rb +15 -16
- data/lib/bolt/pal/yaml_plan/step/eval.rb +11 -11
- data/lib/bolt/pal/yaml_plan/step/message.rb +13 -4
- data/lib/bolt/pal/yaml_plan/step/plan.rb +19 -15
- data/lib/bolt/pal/yaml_plan/step/resources.rb +82 -21
- data/lib/bolt/pal/yaml_plan/step/script.rb +36 -17
- data/lib/bolt/pal/yaml_plan/step/task.rb +19 -16
- data/lib/bolt/pal/yaml_plan/step/upload.rb +16 -17
- data/lib/bolt/pal/yaml_plan/transpiler.rb +3 -3
- data/lib/bolt/plan_creator.rb +1 -1
- data/lib/bolt/plugin/module.rb +0 -23
- data/lib/bolt/plugin/puppet_connect_data.rb +45 -3
- data/lib/bolt/project.rb +16 -56
- data/lib/bolt/project_manager.rb +5 -4
- data/lib/bolt/project_manager/module_migrator.rb +7 -6
- data/lib/bolt/result.rb +10 -11
- data/lib/bolt/shell.rb +16 -0
- data/lib/bolt/shell/bash.rb +61 -31
- data/lib/bolt/shell/bash/tmpdir.rb +2 -2
- data/lib/bolt/shell/powershell.rb +35 -14
- data/lib/bolt/shell/powershell/snippets.rb +37 -150
- data/lib/bolt/task.rb +1 -1
- data/lib/bolt/transport/base.rb +0 -9
- data/lib/bolt/transport/docker.rb +1 -125
- data/lib/bolt/transport/docker/connection.rb +86 -161
- data/lib/bolt/transport/local.rb +1 -9
- data/lib/bolt/transport/lxd.rb +26 -0
- data/lib/bolt/transport/lxd/connection.rb +99 -0
- data/lib/bolt/transport/orch.rb +13 -5
- data/lib/bolt/transport/ssh/connection.rb +1 -1
- data/lib/bolt/transport/winrm/connection.rb +1 -1
- data/lib/bolt/util.rb +8 -0
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/transport_app.rb +61 -33
- data/lib/bolt_spec/bolt_context.rb +9 -4
- data/lib/bolt_spec/plans.rb +1 -109
- data/lib/bolt_spec/plans/action_stubs.rb +1 -1
- data/lib/bolt_spec/plans/action_stubs/command_stub.rb +8 -1
- data/lib/bolt_spec/plans/action_stubs/script_stub.rb +8 -1
- data/lib/bolt_spec/plans/mock_executor.rb +4 -0
- data/modules/aggregate/plans/count.pp +21 -0
- data/modules/aggregate/plans/targets.pp +21 -0
- data/modules/puppet_connect/plans/test_input_data.pp +67 -0
- data/modules/puppetdb_fact/plans/init.pp +10 -0
- metadata +7 -3
- data/modules/aggregate/plans/nodes.pp +0 -36
data/lib/bolt/apply_result.rb
CHANGED
@@ -54,7 +54,7 @@ module Bolt
|
|
54
54
|
unless missing_keys.empty?
|
55
55
|
if result['_output']
|
56
56
|
# rubocop:disable Layout/LineLength
|
57
|
-
msg = "Report result contains an '_output' key. Catalog application
|
57
|
+
msg = "Report result contains an '_output' key. Catalog application might have printed extraneous output to stdout: #{result['_output']}"
|
58
58
|
# rubocop:enable Layout/LineLength
|
59
59
|
else
|
60
60
|
msg = "Report did not contain all expected keys missing: #{missing_keys.join(', ')}"
|
@@ -6,15 +6,15 @@ require 'optparse'
|
|
6
6
|
|
7
7
|
module Bolt
|
8
8
|
class BoltOptionParser < OptionParser
|
9
|
-
PROJECT_PATHS = %w[project
|
10
|
-
OPTIONS = { inventory: %w[targets query rerun
|
9
|
+
PROJECT_PATHS = %w[project].freeze
|
10
|
+
OPTIONS = { inventory: %w[targets query rerun],
|
11
11
|
authentication: %w[user password password-prompt private-key host-key-check ssl ssl-verify],
|
12
12
|
escalation: %w[run-as sudo-password sudo-password-prompt sudo-executable],
|
13
13
|
run_context: %w[concurrency inventoryfile save-rerun cleanup],
|
14
14
|
global_config_setters: PROJECT_PATHS + %w[modulepath],
|
15
15
|
transports: %w[transport connect-timeout tty native-ssh ssh-command copy-command],
|
16
|
-
display: %w[format color verbose trace],
|
17
|
-
global: %w[help version
|
16
|
+
display: %w[format color verbose trace stream],
|
17
|
+
global: %w[help version log-level clear-cache] }.freeze
|
18
18
|
|
19
19
|
ACTION_OPTS = OPTIONS.values.flatten.freeze
|
20
20
|
|
@@ -114,21 +114,6 @@ module Bolt
|
|
114
114
|
{ flags: OPTIONS[:global],
|
115
115
|
banner: PROJECT_HELP }
|
116
116
|
end
|
117
|
-
when 'puppetfile'
|
118
|
-
case action
|
119
|
-
when 'install'
|
120
|
-
{ flags: OPTIONS[:global] + OPTIONS[:global_config_setters] + %w[puppetfile],
|
121
|
-
banner: PUPPETFILE_INSTALL_HELP }
|
122
|
-
when 'show-modules'
|
123
|
-
{ flags: OPTIONS[:global] + OPTIONS[:global_config_setters],
|
124
|
-
banner: PUPPETFILE_SHOWMODULES_HELP }
|
125
|
-
when 'generate-types'
|
126
|
-
{ flags: OPTIONS[:global] + OPTIONS[:global_config_setters],
|
127
|
-
banner: PUPPETFILE_GENERATETYPES_HELP }
|
128
|
-
else
|
129
|
-
{ flags: OPTIONS[:global],
|
130
|
-
banner: PUPPETFILE_HELP }
|
131
|
-
end
|
132
117
|
when 'script'
|
133
118
|
case action
|
134
119
|
when 'run'
|
@@ -192,7 +177,6 @@ module Bolt
|
|
192
177
|
module Manage Bolt project modules
|
193
178
|
plan Convert, create, show, and run Bolt plans
|
194
179
|
project Create and migrate Bolt projects
|
195
|
-
puppetfile Install and list modules and generate type references
|
196
180
|
script Upload a local script and run it remotely
|
197
181
|
secret Create encryption keys and encrypt and decrypt values
|
198
182
|
task Show and run Bolt tasks
|
@@ -470,7 +454,7 @@ module Bolt
|
|
470
454
|
DESCRIPTION
|
471
455
|
Convert a YAML plan to a Puppet language plan and print the converted plan to stdout.
|
472
456
|
|
473
|
-
Converting a YAML plan
|
457
|
+
Converting a YAML plan might result in a plan that is syntactically
|
474
458
|
correct but has different behavior. Always verify a converted plan's
|
475
459
|
functionality. Note that the converted plan is not written to a file.
|
476
460
|
|
@@ -576,55 +560,6 @@ module Bolt
|
|
576
560
|
Migrate a Bolt project to use current best practices and the latest version of configuration files.
|
577
561
|
HELP
|
578
562
|
|
579
|
-
PUPPETFILE_HELP = <<~HELP
|
580
|
-
NAME
|
581
|
-
puppetfile
|
582
|
-
|
583
|
-
USAGE
|
584
|
-
bolt puppetfile <action> [options]
|
585
|
-
|
586
|
-
DESCRIPTION
|
587
|
-
Install and list modules and generate type references
|
588
|
-
|
589
|
-
ACTIONS
|
590
|
-
generate-types Generate type references to register in plans
|
591
|
-
install Install modules from a Puppetfile into a project
|
592
|
-
show-modules List modules available to the Bolt project
|
593
|
-
HELP
|
594
|
-
|
595
|
-
PUPPETFILE_GENERATETYPES_HELP = <<~HELP
|
596
|
-
NAME
|
597
|
-
generate-types
|
598
|
-
|
599
|
-
USAGE
|
600
|
-
bolt puppetfile generate-types [options]
|
601
|
-
|
602
|
-
DESCRIPTION
|
603
|
-
Generate type references to register in plans.
|
604
|
-
HELP
|
605
|
-
|
606
|
-
PUPPETFILE_INSTALL_HELP = <<~HELP
|
607
|
-
NAME
|
608
|
-
install
|
609
|
-
|
610
|
-
USAGE
|
611
|
-
bolt puppetfile install [options]
|
612
|
-
|
613
|
-
DESCRIPTION
|
614
|
-
Install modules from a Puppetfile into a project
|
615
|
-
HELP
|
616
|
-
|
617
|
-
PUPPETFILE_SHOWMODULES_HELP = <<~HELP
|
618
|
-
NAME
|
619
|
-
show-modules
|
620
|
-
|
621
|
-
USAGE
|
622
|
-
bolt puppetfile show-modules [options]
|
623
|
-
|
624
|
-
DESCRIPTION
|
625
|
-
List modules available to the Bolt project.
|
626
|
-
HELP
|
627
|
-
|
628
563
|
SCRIPT_HELP = <<~HELP
|
629
564
|
NAME
|
630
565
|
script
|
@@ -772,7 +707,7 @@ module Bolt
|
|
772
707
|
"Or read a target list from an input file '@<file>' or stdin '-'.",
|
773
708
|
'Example: --targets localhost,target_group,ssh://nix.com:23,winrm://windows.puppet.com',
|
774
709
|
'URI format is [protocol://]host[:port]',
|
775
|
-
"SSH is the default protocol;
|
710
|
+
"SSH is the default protocol; can be #{TRANSPORTS.keys.join(', ')}",
|
776
711
|
'For Windows targets, specify the winrm:// protocol if it has not be configured',
|
777
712
|
'For SSH, port defaults to `22`',
|
778
713
|
'For WinRM, port defaults to `5985` or `5986` based on the --[no-]ssl setting') do |targets|
|
@@ -791,15 +726,6 @@ module Bolt
|
|
791
726
|
define('--noop', 'See what changes Bolt will make without actually executing the changes') do |_|
|
792
727
|
@options[:noop] = true
|
793
728
|
end
|
794
|
-
define('--description DESCRIPTION',
|
795
|
-
'Deprecated. Description to use for the job') do |description|
|
796
|
-
Bolt::Logger.deprecate(
|
797
|
-
"description_cli_option",
|
798
|
-
"Command line option '--description' is deprecated, and will be "\
|
799
|
-
"removed in Bolt 3.0."
|
800
|
-
)
|
801
|
-
@options[:description] = description
|
802
|
-
end
|
803
729
|
define('--params PARAMETERS',
|
804
730
|
"Parameters to a task or plan as json, a json file '@<file>', or on stdin '-'") do |params|
|
805
731
|
@options[:task_options] = parse_params(params)
|
@@ -877,31 +803,10 @@ module Bolt
|
|
877
803
|
File.expand_path(moduledir)
|
878
804
|
end
|
879
805
|
end
|
880
|
-
define('--boltdir PATH',
|
881
|
-
'Deprecated. Specify what project to load config from (default:',
|
882
|
-
'autodiscovered from current working dir)') do |path|
|
883
|
-
Bolt::Logger.deprecate(
|
884
|
-
"boltdir_cli_option",
|
885
|
-
"Command line option '--boltdir' is deprecated, use '--project' instead."
|
886
|
-
)
|
887
|
-
@options[:boltdir] = path
|
888
|
-
end
|
889
806
|
define('--project PATH',
|
890
807
|
'Path to load the Bolt project from (default: autodiscovered from current dir)') do |path|
|
891
808
|
@options[:project] = path
|
892
809
|
end
|
893
|
-
define('--configfile PATH',
|
894
|
-
'Deprecated. Specify where to load config from (default:',
|
895
|
-
'~/.puppetlabs/bolt/bolt.yaml). Directory containing bolt.yaml will be',
|
896
|
-
'used as the project directory.') do |path|
|
897
|
-
Bolt::Logger.deprecate(
|
898
|
-
"configfile_cli_option",
|
899
|
-
"Command line option '--configfile' is deprecated, and " \
|
900
|
-
"will be removed in Bolt 3.0. Use '--project' and provide the "\
|
901
|
-
"directory path instead."
|
902
|
-
)
|
903
|
-
@options[:configfile] = path
|
904
|
-
end
|
905
810
|
define('--hiera-config PATH',
|
906
811
|
'Specify where to load Hiera config from (default: ~/.puppetlabs/bolt/hiera.yaml)') do |path|
|
907
812
|
@options[:'hiera-config'] = File.expand_path(path)
|
@@ -913,19 +818,6 @@ module Bolt
|
|
913
818
|
end
|
914
819
|
@options[:inventoryfile] = File.expand_path(path)
|
915
820
|
end
|
916
|
-
define('--puppetfile PATH',
|
917
|
-
'Deprecated. Specify a Puppetfile to use when installing modules.',
|
918
|
-
' (default: ~/.puppetlabs/bolt/Puppetfile)',
|
919
|
-
'Modules are installed in the current project.') do |path|
|
920
|
-
command = Bolt::Util.powershell? ? 'Update-BoltProject' : 'bolt project migrate'
|
921
|
-
Bolt::Logger.deprecate(
|
922
|
-
"puppetfile_cli_option",
|
923
|
-
"Command line option '--puppetfile' is deprecated, and will be removed "\
|
924
|
-
"in Bolt 3.0. You can migrate to using the new module management "\
|
925
|
-
"workflow using '#{command}'."
|
926
|
-
)
|
927
|
-
@options[:puppetfile_path] = File.expand_path(path)
|
928
|
-
end
|
929
821
|
define('--[no-]save-rerun', 'Whether to update the rerun file after this command.') do |save|
|
930
822
|
@options[:'save-rerun'] = save
|
931
823
|
end
|
@@ -996,6 +888,9 @@ module Bolt
|
|
996
888
|
define('-v', '--[no-]verbose', 'Display verbose logging') do |value|
|
997
889
|
@options[:verbose] = value
|
998
890
|
end
|
891
|
+
define('--stream', 'Stream output from scripts and commands to the console') do |_|
|
892
|
+
@options[:stream] = true
|
893
|
+
end
|
999
894
|
define('--trace', 'Display error stack traces') do |_|
|
1000
895
|
@options[:trace] = true
|
1001
896
|
end
|
@@ -1018,15 +913,6 @@ module Bolt
|
|
1018
913
|
puts Bolt::VERSION
|
1019
914
|
raise Bolt::CLIExit
|
1020
915
|
end
|
1021
|
-
define('--debug', 'Display debug logging') do |_|
|
1022
|
-
@options[:debug] = true
|
1023
|
-
# We don't actually set '--log-level debug' here, but once the options are evaluated by
|
1024
|
-
# the config class the end result is the same.
|
1025
|
-
Bolt::Logger.deprecate(
|
1026
|
-
"debug_cli_option",
|
1027
|
-
"Command line option '--debug' is deprecated, set '--log-level debug' instead."
|
1028
|
-
)
|
1029
|
-
end
|
1030
916
|
define('--log-level LEVEL',
|
1031
917
|
"Set the log level for the console. Available options are",
|
1032
918
|
"trace, debug, info, warn, error, fatal, any.") do |level|
|
data/lib/bolt/cli.rb
CHANGED
@@ -33,19 +33,18 @@ module Bolt
|
|
33
33
|
|
34
34
|
class CLI
|
35
35
|
COMMANDS = {
|
36
|
-
'command'
|
37
|
-
'script'
|
38
|
-
'task'
|
39
|
-
'plan'
|
40
|
-
'file'
|
41
|
-
'
|
42
|
-
'
|
43
|
-
'
|
44
|
-
'
|
45
|
-
'
|
46
|
-
'
|
47
|
-
'
|
48
|
-
'guide' => %w[]
|
36
|
+
'command' => %w[run],
|
37
|
+
'script' => %w[run],
|
38
|
+
'task' => %w[show run],
|
39
|
+
'plan' => %w[show run convert new],
|
40
|
+
'file' => %w[download upload],
|
41
|
+
'secret' => %w[encrypt decrypt createkeys],
|
42
|
+
'inventory' => %w[show],
|
43
|
+
'group' => %w[show],
|
44
|
+
'project' => %w[init migrate],
|
45
|
+
'module' => %w[add generate-types install show],
|
46
|
+
'apply' => %w[],
|
47
|
+
'guide' => %w[]
|
49
48
|
}.freeze
|
50
49
|
|
51
50
|
attr_reader :config, :options
|
@@ -97,6 +96,48 @@ module Bolt
|
|
97
96
|
finalize_setup
|
98
97
|
end
|
99
98
|
|
99
|
+
# Prints a welcome message when users first install Bolt and run `bolt`, `bolt help` or `bolt --help`
|
100
|
+
def welcome_message
|
101
|
+
bolt = <<~BOLT
|
102
|
+
`.::-`
|
103
|
+
`.-:///////-.`
|
104
|
+
`-:////:. `-:///:- /ooo. .ooo/
|
105
|
+
`.-:///::///:-` `-//: ymmm- :mmmy .---.
|
106
|
+
:///:-. `.:////. -//: ymmm- :mmmy +mmm+
|
107
|
+
://. ///. -//: ymmm--/++/- `-/++/:` :mmmy-:smmms::-
|
108
|
+
://. ://. .://: ymmmdmmmmmmdo` .smmmmmmmmh: :mmmysmmmmmmmms
|
109
|
+
://. ://:///:-. ymmmh/--/hmmmy -mmmd/-.:hmmm+:mmmy.-smmms--.
|
110
|
+
://:.` .-////:-` ymmm- ymmm:hmmm- `dmmm/mmmy +mmm+
|
111
|
+
`-:///:-..:///:-.` ymmm- ommm/dmmm` hmmm+mmmy +mmm+
|
112
|
+
`.-:////:-` ymmm+ /mmmm.ommms` /mmmh:mmmy +mmmo
|
113
|
+
`-.` ymmmmmhhmmmmd: ommmmhydmmmy`:mmmy -mmmmdhd
|
114
|
+
oyyy+shddhs/` .+shddhy+- -yyyo .ohddhs
|
115
|
+
|
116
|
+
|
117
|
+
BOLT
|
118
|
+
example_cmd = if Bolt::Util.windows?
|
119
|
+
"Invoke-BoltCommand -Command 'hostname' -Targets localhost"
|
120
|
+
else
|
121
|
+
"bolt command run 'hostname' --target localhost"
|
122
|
+
end
|
123
|
+
prev_cmd = String.new("bolt")
|
124
|
+
prev_cmd << " #{@argv[0]}" unless @argv.empty?
|
125
|
+
|
126
|
+
message = <<~MSG
|
127
|
+
🎉 Welcome to Bolt #{VERSION}
|
128
|
+
😌 We're here to help bring order to the chaos
|
129
|
+
📖 Find our documentation at https://bolt.guide
|
130
|
+
🙋 Ask a question in #bolt on https://slack.puppet.com/
|
131
|
+
🔩 Contribute at https://github.com/puppetlabs/bolt/
|
132
|
+
💡 Not sure where to start? Try "#{example_cmd}"
|
133
|
+
|
134
|
+
We only print this message once. Run "#{prev_cmd}" again for help text.
|
135
|
+
MSG
|
136
|
+
|
137
|
+
$stdout.print "\033[36m#{bolt}\033[0m"
|
138
|
+
$stdout.print message
|
139
|
+
end
|
140
|
+
|
100
141
|
# Parses the command and validates options. All errors that are raised here
|
101
142
|
# are not handled by the outputter, as it relies on config being loaded.
|
102
143
|
def parse_command
|
@@ -108,6 +149,16 @@ module Bolt
|
|
108
149
|
# help text
|
109
150
|
options[:subcommand] = nil unless COMMANDS.include?(options[:subcommand])
|
110
151
|
|
152
|
+
if Bolt::Util.first_run?
|
153
|
+
FileUtils.mkdir_p(Bolt::Util.first_runs_free.dirname)
|
154
|
+
FileUtils.touch(Bolt::Util.first_runs_free)
|
155
|
+
|
156
|
+
if options[:subcommand].nil? && $stdout.isatty
|
157
|
+
welcome_message
|
158
|
+
raise Bolt::CLIExit
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
111
162
|
# Update the parser for the subcommand (or lack thereof)
|
112
163
|
parser.update
|
113
164
|
puts parser.help
|
@@ -155,25 +206,19 @@ module Bolt
|
|
155
206
|
# Loads the project and configuration. All errors that are raised here are not
|
156
207
|
# handled by the outputter, as it relies on config being loaded.
|
157
208
|
def load_config
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
Bolt::
|
209
|
+
project = if ENV['BOLT_PROJECT']
|
210
|
+
Bolt::Project.create_project(ENV['BOLT_PROJECT'], 'environment')
|
211
|
+
elsif options[:project]
|
212
|
+
dir = Pathname.new(options[:project])
|
213
|
+
if (dir + Bolt::Project::BOLTDIR_NAME).directory?
|
214
|
+
Bolt::Project.create_project(dir + Bolt::Project::BOLTDIR_NAME)
|
215
|
+
else
|
216
|
+
Bolt::Project.create_project(dir)
|
217
|
+
end
|
163
218
|
else
|
164
|
-
|
165
|
-
project = if cli_flag
|
166
|
-
dir = Pathname.new(cli_flag)
|
167
|
-
if (dir + Bolt::Project::BOLTDIR_NAME).directory?
|
168
|
-
Bolt::Project.create_project(dir + Bolt::Project::BOLTDIR_NAME)
|
169
|
-
else
|
170
|
-
Bolt::Project.create_project(dir)
|
171
|
-
end
|
172
|
-
else
|
173
|
-
Bolt::Project.find_boltdir(Dir.pwd)
|
174
|
-
end
|
175
|
-
Bolt::Config.from_project(project, options)
|
219
|
+
Bolt::Project.find_boltdir(Dir.pwd)
|
176
220
|
end
|
221
|
+
@config = Bolt::Config.from_project(project, options)
|
177
222
|
rescue Bolt::Error => e
|
178
223
|
fatal_error(e)
|
179
224
|
raise e
|
@@ -182,6 +227,7 @@ module Bolt
|
|
182
227
|
# Completes the setup process by configuring Bolt and log messages
|
183
228
|
def finalize_setup
|
184
229
|
Bolt::Logger.configure(config.log, config.color, config.disable_warnings)
|
230
|
+
Bolt::Logger.stream = config.stream
|
185
231
|
Bolt::Logger.analytics = analytics
|
186
232
|
Bolt::Logger.flush_queue
|
187
233
|
|
@@ -210,9 +256,8 @@ module Bolt
|
|
210
256
|
|
211
257
|
return unless !stdout.empty? && stdout.to_i < 3
|
212
258
|
|
213
|
-
msg = "Detected PowerShell 2 on controller. PowerShell 2 is
|
214
|
-
|
215
|
-
Bolt::Logger.deprecate("powershell_2_controller", msg)
|
259
|
+
msg = "Detected PowerShell 2 on controller. PowerShell 2 is unsupported."
|
260
|
+
Bolt::Logger.deprecation_warning("powershell_2_controller", msg)
|
216
261
|
end
|
217
262
|
end
|
218
263
|
|
@@ -220,7 +265,7 @@ module Bolt
|
|
220
265
|
target_opts = options.keys.select { |opt| %i[query rerun targets].include?(opt) }
|
221
266
|
target_string = "'--targets', '--rerun', or '--query'"
|
222
267
|
if target_opts.length > 1
|
223
|
-
raise Bolt::CLIError, "Only one targeting option #{target_string}
|
268
|
+
raise Bolt::CLIError, "Only one targeting option #{target_string} can be specified"
|
224
269
|
elsif target_opts.empty? && options[:subcommand] != 'plan'
|
225
270
|
raise Bolt::CLIError, "Command requires a targeting option: #{target_string}"
|
226
271
|
end
|
@@ -257,11 +302,14 @@ module Bolt
|
|
257
302
|
end
|
258
303
|
end
|
259
304
|
|
260
|
-
if %w[task plan].include?(options[:subcommand]) && options[:action] == 'run'
|
305
|
+
if %w[task plan script].include?(options[:subcommand]) && options[:action] == 'run'
|
261
306
|
if options[:object].nil?
|
262
307
|
raise Bolt::CLIError, "Must specify a #{options[:subcommand]} to run"
|
263
308
|
end
|
264
|
-
|
309
|
+
end
|
310
|
+
|
311
|
+
# This may mean that we parsed a parameter as the object
|
312
|
+
if %w[task plan].include?(options[:subcommand]) && options[:action] == 'run'
|
265
313
|
unless options[:object] =~ /\A([a-z][a-z0-9_]*)?(::[a-z][a-z0-9_]*)*\Z/
|
266
314
|
raise Bolt::CLIError,
|
267
315
|
"Invalid #{options[:subcommand]} '#{options[:object]}'"
|
@@ -306,26 +354,18 @@ module Bolt
|
|
306
354
|
"Unknown argument(s) #{options[:leftovers].join(', ')}"
|
307
355
|
end
|
308
356
|
|
309
|
-
if options.slice(:boltdir, :configfile, :project).length > 1
|
310
|
-
raise Bolt::CLIError, "Only one of '--boltdir', '--project', or '--configfile' may be specified"
|
311
|
-
end
|
312
|
-
|
313
357
|
if options[:noop] &&
|
314
358
|
!(options[:subcommand] == 'task' && options[:action] == 'run') && options[:subcommand] != 'apply'
|
315
359
|
raise Bolt::CLIError,
|
316
|
-
"Option '--noop'
|
360
|
+
"Option '--noop' can only be specified when running a task or applying manifest code"
|
317
361
|
end
|
318
362
|
|
319
363
|
if options[:env_vars]
|
320
364
|
unless %w[command script].include?(options[:subcommand]) && options[:action] == 'run'
|
321
365
|
raise Bolt::CLIError,
|
322
|
-
"Option '--env-var'
|
366
|
+
"Option '--env-var' can only be specified when running a command or script"
|
323
367
|
end
|
324
368
|
end
|
325
|
-
|
326
|
-
if options.key?(:debug) && options.key?(:log)
|
327
|
-
raise Bolt::CLIError, "Only one of '--debug' or '--log-level' may be specified"
|
328
|
-
end
|
329
369
|
end
|
330
370
|
|
331
371
|
def handle_parser_errors
|
@@ -370,7 +410,7 @@ module Bolt
|
|
370
410
|
if inventory_source && conflicting_options.any?
|
371
411
|
Bolt::Logger.warn(
|
372
412
|
"cli_overrides",
|
373
|
-
"CLI arguments #{conflicting_options.to_a}
|
413
|
+
"CLI arguments #{conflicting_options.to_a} might be overridden by Inventory: #{inventory_source}"
|
374
414
|
)
|
375
415
|
end
|
376
416
|
end
|
@@ -388,7 +428,7 @@ module Bolt
|
|
388
428
|
# Initialize inventory and targets. Errors here are better to catch early.
|
389
429
|
# options[:target_args] will contain a string/array version of the targetting options this is passed to plans
|
390
430
|
# options[:targets] will contain a resolved set of Target objects
|
391
|
-
unless %w[guide module project
|
431
|
+
unless %w[guide module project secret].include?(options[:subcommand]) ||
|
392
432
|
%w[convert new show].include?(options[:action])
|
393
433
|
update_targets(options)
|
394
434
|
end
|
@@ -443,15 +483,12 @@ module Bolt
|
|
443
483
|
list_modules
|
444
484
|
end
|
445
485
|
return 0
|
446
|
-
when 'show-modules'
|
447
|
-
list_modules
|
448
|
-
return 0
|
449
486
|
when 'convert'
|
450
487
|
pal.convert_plan(options[:object])
|
451
488
|
return 0
|
452
489
|
end
|
453
490
|
|
454
|
-
message = 'There
|
491
|
+
message = 'There might be processes left executing on some nodes.'
|
455
492
|
|
456
493
|
if %w[task plan].include?(options[:subcommand]) && options[:task_options] && !options[:params_parsed] && pal
|
457
494
|
options[:task_options] = pal.parse_params(options[:subcommand], options[:object], options[:task_options])
|
@@ -495,17 +532,6 @@ module Bolt
|
|
495
532
|
when 'generate-types'
|
496
533
|
code = generate_types
|
497
534
|
end
|
498
|
-
when 'puppetfile'
|
499
|
-
case options[:action]
|
500
|
-
when 'generate-types'
|
501
|
-
code = generate_types
|
502
|
-
when 'install'
|
503
|
-
code = install_puppetfile(
|
504
|
-
config.puppetfile_config,
|
505
|
-
config.puppetfile,
|
506
|
-
config.modulepath.first
|
507
|
-
)
|
508
|
-
end
|
509
535
|
when 'secret'
|
510
536
|
code = Bolt::Secret.execute(plugins, outputter, options)
|
511
537
|
when 'apply'
|
@@ -523,7 +549,6 @@ module Bolt
|
|
523
549
|
|
524
550
|
elapsed_time = Benchmark.realtime do
|
525
551
|
executor_opts = {}
|
526
|
-
executor_opts[:description] = options[:description] if options.key?(:description)
|
527
552
|
executor_opts[:env_vars] = options[:env_vars] if options.key?(:env_vars)
|
528
553
|
executor.subscribe(outputter)
|
529
554
|
executor.subscribe(log_outputter)
|
@@ -532,16 +557,14 @@ module Bolt
|
|
532
557
|
when 'command'
|
533
558
|
executor.run_command(targets, options[:object], executor_opts)
|
534
559
|
when 'script'
|
535
|
-
|
536
|
-
|
537
|
-
executor.run_script(targets, script, options[:leftovers], executor_opts)
|
560
|
+
script_path = find_file(options[:object])
|
561
|
+
executor.run_script(targets, script_path, options[:leftovers], executor_opts)
|
538
562
|
when 'task'
|
539
563
|
pal.run_task(options[:object],
|
540
564
|
targets,
|
541
565
|
options[:task_options],
|
542
566
|
executor,
|
543
|
-
inventory
|
544
|
-
options[:description])
|
567
|
+
inventory)
|
545
568
|
when 'file'
|
546
569
|
src = options[:object]
|
547
570
|
dest = options[:leftovers].first
|
@@ -642,7 +665,7 @@ module Bolt
|
|
642
665
|
if plan_arguments['nodes'] || plan_arguments['targets']
|
643
666
|
key = plan_arguments.include?('nodes') ? 'nodes' : 'targets'
|
644
667
|
raise Bolt::CLIError,
|
645
|
-
"A plan's '#{key}' parameter
|
668
|
+
"A plan's '#{key}' parameter can be specified using the --#{key} option, but in that " \
|
646
669
|
"case it must not be specified as a separate #{key}=<value> parameter nor included " \
|
647
670
|
"in the JSON data passed in the --params option"
|
648
671
|
end
|
@@ -664,7 +687,6 @@ module Bolt
|
|
664
687
|
|
665
688
|
plan_context = { plan_name: plan_name,
|
666
689
|
params: plan_arguments }
|
667
|
-
plan_context[:description] = options[:description] if options[:description]
|
668
690
|
|
669
691
|
executor = Bolt::Executor.new(config.concurrency, analytics, options[:noop], config.modified_concurrency)
|
670
692
|
if %w[human rainbow].include?(options.fetch(:format, 'human'))
|
@@ -728,12 +750,10 @@ module Bolt
|
|
728
750
|
end
|
729
751
|
|
730
752
|
def list_modules
|
731
|
-
assert_puppetfile_or_module_command(config.project.modules)
|
732
753
|
outputter.print_module_list(pal.list_modules)
|
733
754
|
end
|
734
755
|
|
735
756
|
def generate_types
|
736
|
-
assert_puppetfile_or_module_command(config.project.modules)
|
737
757
|
# generate_types will surface a nice error with helpful message if it fails
|
738
758
|
pal.generate_types(cache: true)
|
739
759
|
0
|
@@ -743,19 +763,19 @@ module Bolt
|
|
743
763
|
#
|
744
764
|
def install_project_modules(project, config, force, resolve)
|
745
765
|
assert_project_file(project)
|
746
|
-
assert_puppetfile_or_module_command(project.modules)
|
747
766
|
|
748
|
-
|
749
|
-
outputter.print_message
|
750
|
-
|
767
|
+
if project.modules.empty? && resolve != false
|
768
|
+
outputter.print_message(
|
769
|
+
"Project configuration file #{project.project_file} does not "\
|
770
|
+
"specify any module dependencies. Nothing to do."
|
771
|
+
)
|
751
772
|
return 0
|
752
773
|
end
|
753
774
|
|
754
|
-
modules = project.modules || []
|
755
775
|
installer = Bolt::ModuleInstaller.new(outputter, pal)
|
756
776
|
|
757
777
|
ok = outputter.spin do
|
758
|
-
installer.install(modules,
|
778
|
+
installer.install(project.modules,
|
759
779
|
project.puppetfile,
|
760
780
|
project.managed_moduledir,
|
761
781
|
config,
|
@@ -770,14 +790,12 @@ module Bolt
|
|
770
790
|
#
|
771
791
|
def add_project_module(name, project, config)
|
772
792
|
assert_project_file(project)
|
773
|
-
assert_puppetfile_or_module_command(project.modules)
|
774
793
|
|
775
|
-
modules = project.modules || []
|
776
794
|
installer = Bolt::ModuleInstaller.new(outputter, pal)
|
777
795
|
|
778
796
|
ok = outputter.spin do
|
779
797
|
installer.add(name,
|
780
|
-
modules,
|
798
|
+
project.modules,
|
781
799
|
project.puppetfile,
|
782
800
|
project.managed_moduledir,
|
783
801
|
project.project_file,
|
@@ -808,8 +826,6 @@ module Bolt
|
|
808
826
|
# Loads a Puppetfile and installs its modules.
|
809
827
|
#
|
810
828
|
def install_puppetfile(puppetfile_config, puppetfile, moduledir)
|
811
|
-
assert_puppetfile_or_module_command(config.project.modules)
|
812
|
-
|
813
829
|
outputter.print_message("Installing modules from Puppetfile")
|
814
830
|
installer = Bolt::ModuleInstaller.new(outputter, pal)
|
815
831
|
ok = outputter.spin do
|
@@ -819,47 +835,6 @@ module Bolt
|
|
819
835
|
ok ? 0 : 1
|
820
836
|
end
|
821
837
|
|
822
|
-
# Raises an error if the 'puppetfile install' command is deprecated due to
|
823
|
-
# modules being configured.
|
824
|
-
#
|
825
|
-
def assert_puppetfile_or_module_command(modules)
|
826
|
-
if Bolt::Util.powershell?
|
827
|
-
case options[:action]
|
828
|
-
when 'generate-types'
|
829
|
-
old_command = 'Register-BoltPuppetfileTypes'
|
830
|
-
new_command = 'Register-BoltModuleTypes'
|
831
|
-
when 'install'
|
832
|
-
old_command = 'Install-BoltPuppetfile'
|
833
|
-
new_command = 'Install-BoltModule'
|
834
|
-
when 'show', 'show-modules'
|
835
|
-
old_command = 'Get-BoltPuppetfileModules'
|
836
|
-
new_command = 'Get-BoltModule'
|
837
|
-
end
|
838
|
-
else
|
839
|
-
old_command = "bolt puppetfile #{options[:action]}"
|
840
|
-
new_command = if options[:action] == 'show-modules'
|
841
|
-
'bolt module show'
|
842
|
-
else
|
843
|
-
"bolt module #{options[:action]}"
|
844
|
-
end
|
845
|
-
end
|
846
|
-
|
847
|
-
if modules && options[:subcommand] == 'puppetfile'
|
848
|
-
raise Bolt::CLIError,
|
849
|
-
"Unable to use command '#{old_command}' when 'modules' is configured in "\
|
850
|
-
"bolt-project.yaml. Use '#{new_command}' instead."
|
851
|
-
elsif modules.nil? && options[:subcommand] == 'puppetfile'
|
852
|
-
msg = "Command '#{old_command}' is deprecated and will be removed in Bolt 3.0. Update your project to use "\
|
853
|
-
"the module management feature. For more information, see https://pup.pt/bolt-module-migrate."
|
854
|
-
Bolt::Logger.deprecate("puppetfile_command", msg)
|
855
|
-
elsif modules.nil? && options[:subcommand] == 'module'
|
856
|
-
msg = "Unable to use command '#{new_command}' when 'modules' is not configured in "\
|
857
|
-
"bolt-project.yaml. "
|
858
|
-
msg += "Use '#{old_command}' instead." if options[:action] != 'add'
|
859
|
-
raise Bolt::CLIError, msg
|
860
|
-
end
|
861
|
-
end
|
862
|
-
|
863
838
|
def pal
|
864
839
|
@pal ||= Bolt::PAL.new(Bolt::Config::Modulepath.new(config.modulepath),
|
865
840
|
config.hiera_config,
|
@@ -920,6 +895,28 @@ module Bolt
|
|
920
895
|
Bolt::Util.validate_file(type, path, allow_dir)
|
921
896
|
end
|
922
897
|
|
898
|
+
# Returns the path to a file. If the path is an absolute or relative to
|
899
|
+
# a file, and the file exists, returns the path as-is. Otherwise, checks if
|
900
|
+
# the path is a Puppet file path and looks for the file in a module's files
|
901
|
+
# directory.
|
902
|
+
#
|
903
|
+
def find_file(path)
|
904
|
+
unless File.exist?(path) || Pathname.new(path).absolute?
|
905
|
+
modulepath = Bolt::Config::Modulepath.new(config.modulepath)
|
906
|
+
modules = Bolt::Module.discover(modulepath.full_modulepath, config.project)
|
907
|
+
mod, file = path.split(File::SEPARATOR, 2)
|
908
|
+
|
909
|
+
if modules[mod]
|
910
|
+
@logger.debug("Did not find file at #{File.expand_path(path)}, checking in module '#{mod}'")
|
911
|
+
path = File.join(modules[mod].path, 'files', file)
|
912
|
+
end
|
913
|
+
end
|
914
|
+
|
915
|
+
Bolt::Util.validate_file('script', path)
|
916
|
+
|
917
|
+
path
|
918
|
+
end
|
919
|
+
|
923
920
|
def rerun
|
924
921
|
@rerun ||= Bolt::Rerun.new(config.rerunfile, config.save_rerun)
|
925
922
|
end
|
@@ -948,7 +945,7 @@ module Bolt
|
|
948
945
|
# If the bundled content directory is empty, Bolt is likely installed as a gem.
|
949
946
|
if ENV['BOLT_GEM'].nil? && incomplete_install?
|
950
947
|
msg = <<~MSG.chomp
|
951
|
-
Bolt
|
948
|
+
Bolt might be installed as a gem. To use Bolt reliably and with all of its
|
952
949
|
dependencies, uninstall the 'bolt' gem and install Bolt as a package:
|
953
950
|
https://puppet.com/docs/bolt/latest/bolt_installing.html
|
954
951
|
|
@@ -979,7 +976,8 @@ module Bolt
|
|
979
976
|
# Gem installs include the aggregate, canary, and puppetdb_fact modules, while
|
980
977
|
# package installs include modules listed in the Bolt repo Puppetfile
|
981
978
|
def incomplete_install?
|
982
|
-
|
979
|
+
builtin_module_list = %w[aggregate canary puppetdb_fact secure_env_vars puppet_connect]
|
980
|
+
(Dir.children(Bolt::Config::Modulepath::MODULES_PATH) - builtin_module_list).empty?
|
983
981
|
end
|
984
982
|
|
985
983
|
# Mimicks the output from Outputter::Human#fatal_error. This should be used to print
|