bolt 2.25.0 → 2.30.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 +4 -3
- data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +2 -1
- data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +1 -1
- data/bolt-modules/dir/lib/puppet/functions/dir/children.rb +1 -1
- data/lib/bolt/analytics.rb +7 -3
- data/lib/bolt/applicator.rb +21 -21
- data/lib/bolt/bolt_option_parser.rb +116 -26
- data/lib/bolt/catalog.rb +5 -3
- data/lib/bolt/cli.rb +194 -185
- data/lib/bolt/config.rb +61 -26
- data/lib/bolt/config/options.rb +35 -2
- data/lib/bolt/executor.rb +2 -2
- data/lib/bolt/inventory.rb +8 -1
- data/lib/bolt/inventory/group.rb +1 -1
- data/lib/bolt/inventory/inventory.rb +1 -1
- data/lib/bolt/inventory/target.rb +1 -1
- data/lib/bolt/logger.rb +35 -21
- data/lib/bolt/module_installer.rb +172 -0
- data/lib/bolt/outputter.rb +4 -0
- data/lib/bolt/outputter/human.rb +53 -11
- data/lib/bolt/outputter/json.rb +7 -1
- data/lib/bolt/outputter/logger.rb +3 -3
- data/lib/bolt/pal.rb +29 -20
- data/lib/bolt/pal/yaml_plan/evaluator.rb +1 -1
- data/lib/bolt/plugin/module.rb +1 -1
- data/lib/bolt/plugin/puppetdb.rb +1 -1
- data/lib/bolt/project.rb +89 -28
- data/lib/bolt/project_migrator.rb +80 -0
- data/lib/bolt/project_migrator/base.rb +39 -0
- data/lib/bolt/project_migrator/config.rb +67 -0
- data/lib/bolt/project_migrator/inventory.rb +67 -0
- data/lib/bolt/project_migrator/modules.rb +198 -0
- data/lib/bolt/puppetdb/client.rb +1 -1
- data/lib/bolt/puppetdb/config.rb +1 -1
- data/lib/bolt/puppetfile.rb +142 -0
- data/lib/bolt/puppetfile/installer.rb +43 -0
- data/lib/bolt/puppetfile/module.rb +90 -0
- data/lib/bolt/r10k_log_proxy.rb +1 -1
- data/lib/bolt/rerun.rb +2 -2
- data/lib/bolt/result.rb +23 -0
- data/lib/bolt/shell.rb +1 -1
- data/lib/bolt/shell/bash.rb +1 -1
- data/lib/bolt/task.rb +1 -1
- data/lib/bolt/transport/base.rb +5 -5
- data/lib/bolt/transport/docker/connection.rb +1 -1
- data/lib/bolt/transport/local/connection.rb +1 -1
- data/lib/bolt/transport/ssh.rb +1 -1
- data/lib/bolt/transport/ssh/connection.rb +1 -1
- data/lib/bolt/transport/ssh/exec_connection.rb +1 -1
- data/lib/bolt/transport/winrm.rb +1 -1
- data/lib/bolt/transport/winrm/connection.rb +1 -1
- data/lib/bolt/util.rb +52 -11
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/acl.rb +2 -2
- data/lib/bolt_server/base_config.rb +3 -3
- data/lib/bolt_server/config.rb +1 -1
- data/lib/bolt_server/file_cache.rb +12 -12
- data/lib/bolt_server/transport_app.rb +125 -26
- data/lib/bolt_spec/bolt_context.rb +4 -4
- data/lib/bolt_spec/plans/mock_executor.rb +1 -1
- metadata +15 -13
- data/lib/bolt/project_migrate.rb +0 -138
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8ca2906e21e39d1da306c9a02ddb970f64955133fcab01574e4138c1e6e154e
|
4
|
+
data.tar.gz: 4c875d82bf7ff9d4117440eca9e1276c1b9c2fa842fda4669227ebb0ec56f170
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd8e4327ddfeb4d88fdd1f94ab4233bcf1f0d8ce1390769587197dec11bfa024a16889c5693ec4a4333565cd7553a8c13487b6674ba5427a63f9408961e6a3a7
|
7
|
+
data.tar.gz: f2bcbe28ba4c26bc36d3c52ab89a8bafa6a132c930c310a92e48b841d0274389022f2480d3ed397bcc4bcf1f77fb272da82697362d33feccfe05ab0ca203cf6c
|
data/Puppetfile
CHANGED
@@ -31,9 +31,10 @@ mod 'puppetlabs-ruby_plugin_helper', '0.1.0'
|
|
31
31
|
mod 'puppetlabs-stdlib', '6.3.0'
|
32
32
|
|
33
33
|
# Plugin modules
|
34
|
-
mod 'puppetlabs-aws_inventory', '0.5.
|
35
|
-
mod 'puppetlabs-azure_inventory', '0.
|
36
|
-
mod 'puppetlabs-gcloud_inventory', '0.1.
|
34
|
+
mod 'puppetlabs-aws_inventory', '0.5.2'
|
35
|
+
mod 'puppetlabs-azure_inventory', '0.4.1'
|
36
|
+
mod 'puppetlabs-gcloud_inventory', '0.1.3'
|
37
|
+
mod 'puppetlabs-http_request', '0.1.0'
|
37
38
|
mod 'puppetlabs-pkcs7', '0.1.1'
|
38
39
|
mod 'puppetlabs-terraform', '0.5.0'
|
39
40
|
mod 'puppetlabs-vault', '0.3.0'
|
@@ -9,11 +9,12 @@ Puppet::DataTypes.create_type('Result') do
|
|
9
9
|
functions => {
|
10
10
|
error => Callable[[], Optional[Error]],
|
11
11
|
message => Callable[[], Optional[String]],
|
12
|
+
sensitive => Callable[[], Optional[Sensitive[Data]]],
|
12
13
|
action => Callable[[], String],
|
13
14
|
status => Callable[[], String],
|
14
15
|
to_data => Callable[[], Hash],
|
15
16
|
ok => Callable[[], Boolean],
|
16
|
-
'[]' => Callable[[String[1]], Data]
|
17
|
+
'[]' => Callable[[String[1]], Variant[Data, Sensitive[Data]]]
|
17
18
|
}
|
18
19
|
PUPPET
|
19
20
|
|
@@ -96,7 +96,7 @@ Puppet::Functions.create_function(:download_file, Puppet::Functions::InternalFun
|
|
96
96
|
|
97
97
|
# Paths expand relative to the default downloads directory for the project
|
98
98
|
# e.g. ~/.puppetlabs/bolt/downloads/
|
99
|
-
destination = Puppet.lookup(:
|
99
|
+
destination = Puppet.lookup(:bolt_project).downloads + destination
|
100
100
|
|
101
101
|
# If the destination directory already exists, delete any existing contents
|
102
102
|
if Dir.exist?(destination)
|
@@ -25,7 +25,7 @@ Puppet::Functions.create_function(:'dir::children', Puppet::Functions::InternalF
|
|
25
25
|
full_mod_path = File.join(mod_path, subpath || '') if mod_path
|
26
26
|
|
27
27
|
# Expand relative to the project directory if path is relative
|
28
|
-
project = Puppet.lookup(:
|
28
|
+
project = Puppet.lookup(:bolt_project)
|
29
29
|
pathname = Pathname.new(dirname)
|
30
30
|
full_dir = pathname.absolute? ? dirname : File.expand_path(File.join(project.path, dirname))
|
31
31
|
|
data/lib/bolt/analytics.rb
CHANGED
@@ -27,7 +27,7 @@ module Bolt
|
|
27
27
|
}.freeze
|
28
28
|
|
29
29
|
def self.build_client
|
30
|
-
logger =
|
30
|
+
logger = Bolt::Logger.logger(self)
|
31
31
|
begin
|
32
32
|
config_file = config_path(logger)
|
33
33
|
config = load_config(config_file, logger)
|
@@ -93,6 +93,10 @@ module Bolt
|
|
93
93
|
def self.write_config(filename, config)
|
94
94
|
FileUtils.mkdir_p(File.dirname(filename))
|
95
95
|
File.write(filename, config.to_yaml)
|
96
|
+
rescue StandardError => e
|
97
|
+
Bolt::Logger.warn_once('unwriteable_file', "Could not write analytics configuration to #{filename}.")
|
98
|
+
# This will get caught by build_client and create a NoopClient
|
99
|
+
raise e
|
96
100
|
end
|
97
101
|
|
98
102
|
class Client
|
@@ -106,7 +110,7 @@ module Bolt
|
|
106
110
|
require 'httpclient'
|
107
111
|
require 'locale'
|
108
112
|
|
109
|
-
@logger =
|
113
|
+
@logger = Bolt::Logger.logger(self)
|
110
114
|
@http = HTTPClient.new
|
111
115
|
@user_id = user_id
|
112
116
|
@executor = Concurrent.global_io_executor
|
@@ -210,7 +214,7 @@ module Bolt
|
|
210
214
|
attr_accessor :bundled_content
|
211
215
|
|
212
216
|
def initialize
|
213
|
-
@logger =
|
217
|
+
@logger = Bolt::Logger.logger(self)
|
214
218
|
@bundled_content = []
|
215
219
|
end
|
216
220
|
|
data/lib/bolt/applicator.rb
CHANGED
@@ -28,7 +28,7 @@ module Bolt
|
|
28
28
|
@apply_settings = apply_settings || {}
|
29
29
|
|
30
30
|
@pool = Concurrent::ThreadPoolExecutor.new(name: 'apply', max_threads: max_compiles)
|
31
|
-
@logger =
|
31
|
+
@logger = Bolt::Logger.logger(self)
|
32
32
|
end
|
33
33
|
|
34
34
|
private def libexec
|
@@ -50,15 +50,15 @@ module Bolt
|
|
50
50
|
|
51
51
|
def catalog_apply_task
|
52
52
|
@catalog_apply_task ||= begin
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
53
|
+
path = File.join(libexec, 'apply_catalog.rb')
|
54
|
+
file = { 'name' => 'apply_catalog.rb', 'path' => path }
|
55
|
+
metadata = { 'supports_noop' => true, 'input_method' => 'stdin',
|
56
|
+
'implementations' => [
|
57
|
+
{ 'name' => 'apply_catalog.rb' },
|
58
|
+
{ 'name' => 'apply_catalog.rb', 'remote' => true }
|
59
|
+
] }
|
60
|
+
Bolt::Task.new('apply_helpers::apply_catalog', metadata, [file])
|
61
|
+
end
|
62
62
|
end
|
63
63
|
|
64
64
|
def query_resources_task
|
@@ -75,34 +75,35 @@ module Bolt
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
def compile(target,
|
78
|
+
def compile(target, scope)
|
79
79
|
# This simplified Puppet node object is what .local uses to determine the
|
80
80
|
# certname of the target
|
81
81
|
node = Puppet::Node.from_data_hash('name' => target.name,
|
82
82
|
'parameters' => { 'clientcert' => target.name })
|
83
83
|
trusted = Puppet::Context::TrustedInformation.local(node)
|
84
|
-
|
84
|
+
target_data = {
|
85
85
|
name: target.name,
|
86
86
|
facts: @inventory.facts(target).merge('bolt' => true),
|
87
87
|
variables: @inventory.vars(target),
|
88
88
|
trusted: trusted.to_h
|
89
89
|
}
|
90
|
+
catalog_request = scope.merge(target: target_data)
|
90
91
|
|
91
92
|
bolt_catalog_exe = File.join(libexec, 'bolt_catalog')
|
92
93
|
old_path = ENV['PATH']
|
93
94
|
ENV['PATH'] = "#{RbConfig::CONFIG['bindir']}#{File::PATH_SEPARATOR}#{old_path}"
|
94
|
-
out, err, stat = Open3.capture3('ruby', bolt_catalog_exe, 'compile', stdin_data:
|
95
|
+
out, err, stat = Open3.capture3('ruby', bolt_catalog_exe, 'compile', stdin_data: catalog_request.to_json)
|
95
96
|
ENV['PATH'] = old_path
|
96
97
|
|
97
98
|
# If bolt_catalog does not return valid JSON, we should print stderr to
|
98
99
|
# see what happened
|
99
100
|
print_logs = stat.success?
|
100
101
|
result = begin
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
102
|
+
JSON.parse(out)
|
103
|
+
rescue JSON::ParserError
|
104
|
+
print_logs = true
|
105
|
+
{ 'message' => "Something's gone terribly wrong! STDERR is logged." }
|
106
|
+
end
|
106
107
|
|
107
108
|
# Any messages logged by Puppet will be on stderr as JSON hashes, so we
|
108
109
|
# parse those and store them here. Any message on stderr that is not
|
@@ -183,17 +184,16 @@ module Bolt
|
|
183
184
|
type_by_reference: true,
|
184
185
|
local_reference: true)
|
185
186
|
|
186
|
-
bolt_project = @project if @project&.name
|
187
187
|
scope = {
|
188
188
|
code_ast: ast,
|
189
189
|
modulepath: @modulepath,
|
190
|
-
project:
|
190
|
+
project: @project.to_h,
|
191
191
|
pdb_config: @pdb_client.config.to_hash,
|
192
192
|
hiera_config: @hiera_config,
|
193
193
|
plan_vars: plan_vars,
|
194
194
|
# This data isn't available on the target config hash
|
195
195
|
config: @inventory.transport_data_get
|
196
|
-
}
|
196
|
+
}.freeze
|
197
197
|
description = options[:description] || 'apply catalog'
|
198
198
|
|
199
199
|
required_modules = options[:required_modules].nil? ? nil : Array(options[:required_modules])
|
@@ -64,6 +64,24 @@ module Bolt
|
|
64
64
|
when 'guide'
|
65
65
|
{ flags: OPTIONS[:global] + %w[format],
|
66
66
|
banner: GUIDE_HELP }
|
67
|
+
when 'module'
|
68
|
+
case action
|
69
|
+
when 'add'
|
70
|
+
{ flags: OPTIONS[:global] + %w[configfile project],
|
71
|
+
banner: MODULE_ADD_HELP }
|
72
|
+
when 'generate-types'
|
73
|
+
{ flags: OPTIONS[:global] + OPTIONS[:global_config_setters],
|
74
|
+
banner: MODULE_GENERATETYPES_HELP }
|
75
|
+
when 'install'
|
76
|
+
{ flags: OPTIONS[:global] + %w[configfile force project resolve],
|
77
|
+
banner: MODULE_INSTALL_HELP }
|
78
|
+
when 'show'
|
79
|
+
{ flags: OPTIONS[:global] + OPTIONS[:global_config_setters],
|
80
|
+
banner: MODULE_SHOW_HELP }
|
81
|
+
else
|
82
|
+
{ flags: OPTIONS[:global],
|
83
|
+
banner: MODULE_HELP }
|
84
|
+
end
|
67
85
|
when 'plan'
|
68
86
|
case action
|
69
87
|
when 'convert'
|
@@ -169,6 +187,7 @@ module Bolt
|
|
169
187
|
group Show the list of groups in the inventory
|
170
188
|
guide View guides for Bolt concepts and features
|
171
189
|
inventory Show the list of targets an action would run on
|
190
|
+
module Manage Bolt project modules
|
172
191
|
plan Convert, create, show, and run Bolt plans
|
173
192
|
project Create and migrate Bolt projects
|
174
193
|
puppetfile Install and list modules and generate type references
|
@@ -341,6 +360,87 @@ module Bolt
|
|
341
360
|
Show the list of targets an action would run on.
|
342
361
|
HELP
|
343
362
|
|
363
|
+
MODULE_HELP = <<~HELP
|
364
|
+
NAME
|
365
|
+
module
|
366
|
+
|
367
|
+
USAGE
|
368
|
+
bolt module <action> [options]
|
369
|
+
|
370
|
+
DESCRIPTION
|
371
|
+
Manage Bolt project modules
|
372
|
+
|
373
|
+
The module command is only supported when a project is configured
|
374
|
+
with the 'modules' key.
|
375
|
+
|
376
|
+
ACTIONS
|
377
|
+
add Add a module to the project
|
378
|
+
generate-types Generate type references to register in plans
|
379
|
+
install Install the project's modules
|
380
|
+
show List modules available to the Bolt project
|
381
|
+
HELP
|
382
|
+
|
383
|
+
MODULE_ADD_HELP = <<~HELP
|
384
|
+
NAME
|
385
|
+
add
|
386
|
+
|
387
|
+
USAGE
|
388
|
+
bolt module add <module> [options]
|
389
|
+
|
390
|
+
DESCRIPTION
|
391
|
+
Add a module to the project.
|
392
|
+
|
393
|
+
Module declarations are loaded from the project's configuration
|
394
|
+
file. Bolt will automatically resolve all module dependencies,
|
395
|
+
generate a Puppetfile, and install the modules.
|
396
|
+
|
397
|
+
The module command is only supported when a project is configured
|
398
|
+
with the 'modules' key.
|
399
|
+
HELP
|
400
|
+
|
401
|
+
MODULE_GENERATETYPES_HELP = <<~HELP
|
402
|
+
NAME
|
403
|
+
generate-types
|
404
|
+
|
405
|
+
USAGE
|
406
|
+
bolt module generate-types [options]
|
407
|
+
|
408
|
+
DESCRIPTION
|
409
|
+
Generate type references to register in plans.
|
410
|
+
|
411
|
+
The module command is only supported when a project is configured
|
412
|
+
with the 'modules' key.
|
413
|
+
HELP
|
414
|
+
|
415
|
+
MODULE_INSTALL_HELP = <<~HELP
|
416
|
+
NAME
|
417
|
+
install
|
418
|
+
|
419
|
+
USAGE
|
420
|
+
bolt module install [options]
|
421
|
+
|
422
|
+
DESCRIPTION
|
423
|
+
Install the project's modules.
|
424
|
+
|
425
|
+
Module declarations are loaded from the project's configuration
|
426
|
+
file. Bolt will automatically resolve all module dependencies,
|
427
|
+
generate a Puppetfile, and install the modules.
|
428
|
+
HELP
|
429
|
+
|
430
|
+
MODULE_SHOW_HELP = <<~HELP
|
431
|
+
NAME
|
432
|
+
show
|
433
|
+
|
434
|
+
USAGE
|
435
|
+
bolt module show [options]
|
436
|
+
|
437
|
+
DESCRIPTION
|
438
|
+
List modules available to the Bolt project.
|
439
|
+
|
440
|
+
The module command is only supported when a project is configured
|
441
|
+
with the 'modules' key.
|
442
|
+
HELP
|
443
|
+
|
344
444
|
PLAN_HELP = <<~HELP
|
345
445
|
NAME
|
346
446
|
plan
|
@@ -366,11 +466,11 @@ module Bolt
|
|
366
466
|
bolt plan convert <path> [options]
|
367
467
|
|
368
468
|
DESCRIPTION
|
369
|
-
Convert a YAML plan to a
|
469
|
+
Convert a YAML plan to a Puppet language plan and print the converted plan to stdout.
|
370
470
|
|
371
471
|
Converting a YAML plan may result in a plan that is syntactically
|
372
472
|
correct but has different behavior. Always verify a converted plan's
|
373
|
-
functionality.
|
473
|
+
functionality. Note that the converted plan is not written to a file.
|
374
474
|
|
375
475
|
EXAMPLES
|
376
476
|
bolt plan convert path/to/plan/myplan.yaml
|
@@ -421,9 +521,9 @@ module Bolt
|
|
421
521
|
the plan, including a list of available parameters.
|
422
522
|
|
423
523
|
EXAMPLES
|
424
|
-
Display a list of available
|
524
|
+
Display a list of available plans
|
425
525
|
bolt plan show
|
426
|
-
Display documentation for the
|
526
|
+
Display documentation for the aggregate::count plan
|
427
527
|
bolt plan show aggregate::count
|
428
528
|
HELP
|
429
529
|
|
@@ -678,7 +778,7 @@ module Bolt
|
|
678
778
|
'For SSH, port defaults to `22`',
|
679
779
|
'For WinRM, port defaults to `5985` or `5986` based on the --[no-]ssl setting') do |targets|
|
680
780
|
@options[:targets] ||= []
|
681
|
-
@options[:targets] << get_arg_input(targets)
|
781
|
+
@options[:targets] << Bolt::Util.get_arg_input(targets)
|
682
782
|
end
|
683
783
|
define('-q', '--query QUERY', 'Query PuppetDB to determine the targets') do |query|
|
684
784
|
@options[:query] = query
|
@@ -828,7 +928,7 @@ module Bolt
|
|
828
928
|
"This option is experimental.") do |exec|
|
829
929
|
@options[:'copy-command'] = exec
|
830
930
|
end
|
831
|
-
define('--connect-timeout TIMEOUT', Integer, 'Connection timeout (defaults vary)') do |timeout|
|
931
|
+
define('--connect-timeout TIMEOUT', Integer, 'Connection timeout in seconds (defaults vary)') do |timeout|
|
832
932
|
@options[:'connect-timeout'] = timeout
|
833
933
|
end
|
834
934
|
define('--[no-]tty', 'Request a pseudo TTY on targets that support it') do |tty|
|
@@ -838,6 +938,13 @@ module Bolt
|
|
838
938
|
@options[:tmpdir] = tmpdir
|
839
939
|
end
|
840
940
|
|
941
|
+
separator "\nMODULE OPTIONS"
|
942
|
+
define('--[no-]resolve',
|
943
|
+
'Use --no-resolve to install modules listed in the Puppetfile without resolving modules configured',
|
944
|
+
'in Bolt project configuration') do |resolve|
|
945
|
+
@options[:resolve] = resolve
|
946
|
+
end
|
947
|
+
|
841
948
|
separator "\nDISPLAY OPTIONS"
|
842
949
|
define('--filter FILTER', 'Filter tasks and plans by a matching substring') do |filter|
|
843
950
|
unless /^[a-z0-9_:]+$/.match(filter)
|
@@ -864,9 +971,9 @@ module Bolt
|
|
864
971
|
define('--modules MODULES',
|
865
972
|
'A comma-separated list of modules to install from the Puppet Forge',
|
866
973
|
'when initializing a project. Resolves and installs all dependencies.') do |modules|
|
867
|
-
@options[:modules] = modules.split(',')
|
974
|
+
@options[:modules] = modules.split(',').map { |mod| { 'name' => mod } }
|
868
975
|
end
|
869
|
-
define('--force', '
|
976
|
+
define('--force', 'Force a destructive action') do |_force|
|
870
977
|
@options[:force] = true
|
871
978
|
end
|
872
979
|
|
@@ -917,27 +1024,10 @@ module Bolt
|
|
917
1024
|
end
|
918
1025
|
|
919
1026
|
def parse_params(params)
|
920
|
-
json = get_arg_input(params)
|
1027
|
+
json = Bolt::Util.get_arg_input(params)
|
921
1028
|
JSON.parse(json)
|
922
1029
|
rescue JSON::ParserError => e
|
923
1030
|
raise Bolt::CLIError, "Unable to parse --params value as JSON: #{e}"
|
924
1031
|
end
|
925
|
-
|
926
|
-
def get_arg_input(value)
|
927
|
-
if value.start_with?('@')
|
928
|
-
file = value.sub(/^@/, '')
|
929
|
-
read_arg_file(file)
|
930
|
-
elsif value == '-'
|
931
|
-
$stdin.read
|
932
|
-
else
|
933
|
-
value
|
934
|
-
end
|
935
|
-
end
|
936
|
-
|
937
|
-
def read_arg_file(file)
|
938
|
-
File.read(File.expand_path(file))
|
939
|
-
rescue StandardError => e
|
940
|
-
raise Bolt::FileError.new("Error attempting to read #{file}: #{e}", file)
|
941
|
-
end
|
942
1032
|
end
|
943
1033
|
end
|
data/lib/bolt/catalog.rb
CHANGED
@@ -57,8 +57,10 @@ module Bolt
|
|
57
57
|
|
58
58
|
def compile_catalog(request)
|
59
59
|
pdb_client = Bolt::PuppetDB::Client.new(Bolt::PuppetDB::Config.new(request['pdb_config']))
|
60
|
-
project = request['project']
|
61
|
-
bolt_project = Struct.new(:name, :path).new(project['name'],
|
60
|
+
project = request['project']
|
61
|
+
bolt_project = Struct.new(:name, :path, :load_as_module?).new(project['name'],
|
62
|
+
project['path'],
|
63
|
+
project['load_as_module?'])
|
62
64
|
inv = Bolt::ApplyInventory.new(request['config'])
|
63
65
|
puppet_overrides = {
|
64
66
|
bolt_pdb_client: pdb_client,
|
@@ -95,7 +97,7 @@ module Bolt
|
|
95
97
|
}
|
96
98
|
|
97
99
|
with_puppet_settings(puppet_settings) do
|
98
|
-
Puppet::Pal.in_tmp_environment('bolt_catalog', env_conf) do |pal|
|
100
|
+
Puppet::Pal.in_tmp_environment('bolt_catalog', **env_conf) do |pal|
|
99
101
|
Puppet.override(puppet_overrides) do
|
100
102
|
Puppet.lookup(:pal_current_node).trusted_data = target['trusted']
|
101
103
|
pal.with_catalog_compiler do |compiler|
|
data/lib/bolt/cli.rb
CHANGED
@@ -20,33 +20,37 @@ require 'bolt/logger'
|
|
20
20
|
require 'bolt/outputter'
|
21
21
|
require 'bolt/puppetdb'
|
22
22
|
require 'bolt/plugin'
|
23
|
-
require 'bolt/
|
23
|
+
require 'bolt/project_migrator'
|
24
24
|
require 'bolt/pal'
|
25
25
|
require 'bolt/target'
|
26
26
|
require 'bolt/version'
|
27
27
|
require 'bolt/secret'
|
28
|
+
require 'bolt/module_installer'
|
28
29
|
|
29
30
|
module Bolt
|
30
31
|
class CLIExit < StandardError; end
|
31
32
|
class CLI
|
32
|
-
COMMANDS = {
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
33
|
+
COMMANDS = {
|
34
|
+
'command' => %w[run],
|
35
|
+
'script' => %w[run],
|
36
|
+
'task' => %w[show run],
|
37
|
+
'plan' => %w[show run convert new],
|
38
|
+
'file' => %w[download upload],
|
39
|
+
'puppetfile' => %w[install show-modules generate-types],
|
40
|
+
'secret' => %w[encrypt decrypt createkeys],
|
41
|
+
'inventory' => %w[show],
|
42
|
+
'group' => %w[show],
|
43
|
+
'project' => %w[init migrate],
|
44
|
+
'module' => %w[add generate-types install show],
|
45
|
+
'apply' => %w[],
|
46
|
+
'guide' => %w[]
|
47
|
+
}.freeze
|
44
48
|
|
45
49
|
attr_reader :config, :options
|
46
50
|
|
47
51
|
def initialize(argv)
|
48
52
|
Bolt::Logger.initialize_logging
|
49
|
-
@logger =
|
53
|
+
@logger = Bolt::Logger.logger(self)
|
50
54
|
@argv = argv
|
51
55
|
@options = {}
|
52
56
|
end
|
@@ -79,7 +83,7 @@ module Bolt
|
|
79
83
|
|
80
84
|
# Wrapper method that is called by the Bolt executable. Parses the command and
|
81
85
|
# then loads the project and config. Once config is loaded, it completes the
|
82
|
-
# setup process by configuring Bolt and
|
86
|
+
# setup process by configuring Bolt and logging messages.
|
83
87
|
#
|
84
88
|
# This separation is needed since the Bolt::Outputter class that normally handles
|
85
89
|
# printing errors relies on config being loaded. All setup that happens before
|
@@ -98,6 +102,10 @@ module Bolt
|
|
98
102
|
# This part aims to handle both `bolt <mode> --help` and `bolt help <mode>`.
|
99
103
|
remaining = handle_parser_errors { parser.permute(@argv) } unless @argv.empty?
|
100
104
|
if @argv.empty? || help?(remaining)
|
105
|
+
# If the subcommand is not enabled, display the default
|
106
|
+
# help text
|
107
|
+
options[:subcommand] = nil unless COMMANDS.include?(options[:subcommand])
|
108
|
+
|
101
109
|
# Update the parser for the subcommand (or lack thereof)
|
102
110
|
parser.update
|
103
111
|
puts parser.help
|
@@ -106,6 +114,11 @@ module Bolt
|
|
106
114
|
|
107
115
|
options[:object] = remaining.shift
|
108
116
|
|
117
|
+
# Handle reading a command from a file
|
118
|
+
if options[:subcommand] == 'command' && options[:object]
|
119
|
+
options[:object] = Bolt::Util.get_arg_input(options[:object])
|
120
|
+
end
|
121
|
+
|
109
122
|
# Only parse task_options for task or plan
|
110
123
|
if %w[task plan].include?(options[:subcommand])
|
111
124
|
task_options, remaining = remaining.partition { |s| s =~ /.+=/ }
|
@@ -167,25 +180,26 @@ module Bolt
|
|
167
180
|
raise e
|
168
181
|
end
|
169
182
|
|
170
|
-
# Completes the setup process by configuring Bolt and
|
183
|
+
# Completes the setup process by configuring Bolt and log messages
|
171
184
|
def finalize_setup
|
172
185
|
Bolt::Logger.configure(config.log, config.color)
|
173
186
|
Bolt::Logger.analytics = analytics
|
174
187
|
|
175
|
-
# Logger must be configured before checking path case and project file, otherwise
|
188
|
+
# Logger must be configured before checking path case and project file, otherwise logs will not display
|
176
189
|
config.check_path_case('modulepath', config.modulepath)
|
177
190
|
config.project.check_deprecated_file
|
178
191
|
|
179
|
-
# Log
|
180
|
-
|
181
|
-
|
182
|
-
# Display warnings created during parser and config initialization
|
183
|
-
config.warnings.each { |warning| @logger.warn(warning[:msg]) }
|
192
|
+
# Log messages created during parser and config initialization
|
193
|
+
config.logs.each { |log| @logger.send(log.keys[0], log.values[0]) }
|
184
194
|
@parser_deprecations.each { |dep| Bolt::Logger.deprecation_warning(dep[:type], dep[:msg]) }
|
185
195
|
config.deprecations.each { |dep| Bolt::Logger.deprecation_warning(dep[:type], dep[:msg]) }
|
186
196
|
|
187
197
|
warn_inventory_overrides_cli(options)
|
188
198
|
|
199
|
+
# Assert whether the puppetfile/module commands are available depending
|
200
|
+
# on whether 'modules' is configured.
|
201
|
+
assert_puppetfile_or_module_command(config.project.modules)
|
202
|
+
|
189
203
|
options
|
190
204
|
rescue Bolt::Error => e
|
191
205
|
outputter.fatal_error(e)
|
@@ -233,12 +247,6 @@ module Bolt
|
|
233
247
|
end
|
234
248
|
end
|
235
249
|
|
236
|
-
if options[:subcommand] != 'file' && options[:subcommand] != 'script' &&
|
237
|
-
!options[:leftovers].empty?
|
238
|
-
raise Bolt::CLIError,
|
239
|
-
"Unknown argument(s) #{options[:leftovers].join(', ')}"
|
240
|
-
end
|
241
|
-
|
242
250
|
if %w[task plan].include?(options[:subcommand]) && options[:action] == 'run'
|
243
251
|
if options[:object].nil?
|
244
252
|
raise Bolt::CLIError, "Must specify a #{options[:subcommand]} to run"
|
@@ -250,23 +258,6 @@ module Bolt
|
|
250
258
|
end
|
251
259
|
end
|
252
260
|
|
253
|
-
if options[:boltdir] && options[:configfile]
|
254
|
-
raise Bolt::CLIError, "Only one of '--boltdir', '--project', or '--configfile' may be specified"
|
255
|
-
end
|
256
|
-
|
257
|
-
if options[:noop] &&
|
258
|
-
!(options[:subcommand] == 'task' && options[:action] == 'run') && options[:subcommand] != 'apply'
|
259
|
-
raise Bolt::CLIError,
|
260
|
-
"Option '--noop' may only be specified when running a task or applying manifest code"
|
261
|
-
end
|
262
|
-
|
263
|
-
if options[:env_vars]
|
264
|
-
unless %w[command script].include?(options[:subcommand]) && options[:action] == 'run'
|
265
|
-
raise Bolt::CLIError,
|
266
|
-
"Option '--env-var' may only be specified when running a command or script"
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
261
|
if options[:subcommand] == 'apply' && (options[:object] && options[:code])
|
271
262
|
raise Bolt::CLIError, "--execute is unsupported when specifying a manifest file"
|
272
263
|
end
|
@@ -289,6 +280,38 @@ module Bolt
|
|
289
280
|
raise Bolt::CLIError, "Must specify a plan name."
|
290
281
|
end
|
291
282
|
|
283
|
+
if options[:subcommand] == 'module' && options[:action] == 'add' && !options[:object]
|
284
|
+
raise Bolt::CLIError, "Must specify a module name."
|
285
|
+
end
|
286
|
+
|
287
|
+
if options[:subcommand] == 'module' && options[:action] == 'install' && options[:object]
|
288
|
+
raise Bolt::CLIError, "Invalid argument '#{options[:object]}'. To add a new module to "\
|
289
|
+
"the project, run 'bolt module add #{options[:object]}'."
|
290
|
+
end
|
291
|
+
|
292
|
+
if options[:subcommand] != 'file' && options[:subcommand] != 'script' &&
|
293
|
+
!options[:leftovers].empty?
|
294
|
+
raise Bolt::CLIError,
|
295
|
+
"Unknown argument(s) #{options[:leftovers].join(', ')}"
|
296
|
+
end
|
297
|
+
|
298
|
+
if options[:boltdir] && options[:configfile]
|
299
|
+
raise Bolt::CLIError, "Only one of '--boltdir', '--project', or '--configfile' may be specified"
|
300
|
+
end
|
301
|
+
|
302
|
+
if options[:noop] &&
|
303
|
+
!(options[:subcommand] == 'task' && options[:action] == 'run') && options[:subcommand] != 'apply'
|
304
|
+
raise Bolt::CLIError,
|
305
|
+
"Option '--noop' may only be specified when running a task or applying manifest code"
|
306
|
+
end
|
307
|
+
|
308
|
+
if options[:env_vars]
|
309
|
+
unless %w[command script].include?(options[:subcommand]) && options[:action] == 'run'
|
310
|
+
raise Bolt::CLIError,
|
311
|
+
"Option '--env-var' may only be specified when running a command or script"
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
292
315
|
if options.key?(:debug) && options.key?(:log)
|
293
316
|
raise Bolt::CLIError, "Only one of '--debug' or '--log-level' may be specified"
|
294
317
|
end
|
@@ -356,7 +379,7 @@ module Bolt
|
|
356
379
|
# Initialize inventory and targets. Errors here are better to catch early.
|
357
380
|
# options[:target_args] will contain a string/array version of the targetting options this is passed to plans
|
358
381
|
# options[:targets] will contain a resolved set of Target objects
|
359
|
-
unless %w[project puppetfile secret
|
382
|
+
unless %w[guide module project puppetfile secret].include?(options[:subcommand]) ||
|
360
383
|
%w[convert new show].include?(options[:action])
|
361
384
|
update_targets(options)
|
362
385
|
end
|
@@ -382,7 +405,7 @@ module Bolt
|
|
382
405
|
inventory_version: inventory.version)
|
383
406
|
end
|
384
407
|
|
385
|
-
analytics.screen_view(screen, screen_view_fields)
|
408
|
+
analytics.screen_view(screen, **screen_view_fields)
|
386
409
|
|
387
410
|
case options[:action]
|
388
411
|
when 'show'
|
@@ -407,6 +430,8 @@ module Bolt
|
|
407
430
|
end
|
408
431
|
when 'group'
|
409
432
|
list_groups
|
433
|
+
when 'module'
|
434
|
+
list_modules
|
410
435
|
end
|
411
436
|
return 0
|
412
437
|
when 'show-modules'
|
@@ -435,9 +460,7 @@ module Bolt
|
|
435
460
|
when 'init'
|
436
461
|
code = initialize_project
|
437
462
|
when 'migrate'
|
438
|
-
|
439
|
-
path = config.project.path
|
440
|
-
code = Bolt::ProjectMigrate.new(path, outputter, inv).migrate_project
|
463
|
+
code = Bolt::ProjectMigrator.new(config, outputter).migrate
|
441
464
|
end
|
442
465
|
when 'plan'
|
443
466
|
case options[:action]
|
@@ -446,12 +469,25 @@ module Bolt
|
|
446
469
|
when 'run'
|
447
470
|
code = run_plan(options[:object], options[:task_options], options[:target_args], options)
|
448
471
|
end
|
472
|
+
when 'module'
|
473
|
+
case options[:action]
|
474
|
+
when 'add'
|
475
|
+
code = add_project_module(options[:object], config.project)
|
476
|
+
when 'install'
|
477
|
+
code = install_project_modules(config.project, options[:force], options[:resolve])
|
478
|
+
when 'generate-types'
|
479
|
+
code = generate_types
|
480
|
+
end
|
449
481
|
when 'puppetfile'
|
450
482
|
case options[:action]
|
451
483
|
when 'generate-types'
|
452
484
|
code = generate_types
|
453
485
|
when 'install'
|
454
|
-
code = install_puppetfile(
|
486
|
+
code = install_puppetfile(
|
487
|
+
config.puppetfile_config,
|
488
|
+
config.puppetfile,
|
489
|
+
config.modulepath.first
|
490
|
+
)
|
455
491
|
end
|
456
492
|
when 'secret'
|
457
493
|
code = Bolt::Secret.execute(plugins, outputter, options)
|
@@ -801,36 +837,39 @@ module Bolt
|
|
801
837
|
old_config = project + 'bolt.yaml'
|
802
838
|
config = project + 'bolt-project.yaml'
|
803
839
|
puppetfile = project + 'Puppetfile'
|
804
|
-
|
840
|
+
moduledir = project + 'modules'
|
841
|
+
|
842
|
+
# Warn the user if the project directory already exists. We don't error
|
843
|
+
# here since users might not have installed any modules yet. If both
|
844
|
+
# bolt.yaml and bolt-project.yaml exist, this will just warn about
|
845
|
+
# bolt-project.yaml and subsequent Bolt actions will warn about both files
|
846
|
+
# existing.
|
847
|
+
if config.exist?
|
848
|
+
@logger.warn "Found existing project directory at #{project}. Skipping file creation."
|
849
|
+
elsif old_config.exist?
|
850
|
+
@logger.warn "Found existing #{old_config.basename} at #{project}. "\
|
851
|
+
"#{old_config.basename} is deprecated, please rename to #{config.basename}."
|
852
|
+
end
|
805
853
|
|
806
|
-
# If modules were specified, first check if there is already a Puppetfile
|
807
|
-
# directory, erroring if there is. If there is no
|
808
|
-
#
|
809
|
-
#
|
810
|
-
# dependencies are caught early and do not create a project directory.
|
854
|
+
# If modules were specified, first check if there is already a Puppetfile
|
855
|
+
# at the project directory, erroring if there is. If there is no
|
856
|
+
# Puppetfile, install the specified modules. The module installer will
|
857
|
+
# resolve dependencies, generate a Puppetfile, and install the modules.
|
811
858
|
if options[:modules]
|
812
859
|
if puppetfile.exist?
|
813
860
|
raise Bolt::CLIError,
|
814
|
-
"Found existing Puppetfile at #{puppetfile}, unable to initialize
|
815
|
-
"
|
816
|
-
else
|
817
|
-
puppetfile_specs = resolve_puppetfile_specs
|
861
|
+
"Found existing Puppetfile at #{puppetfile}, unable to initialize "\
|
862
|
+
"project with modules."
|
818
863
|
end
|
864
|
+
|
865
|
+
installer = Bolt::ModuleInstaller.new(outputter, pal)
|
866
|
+
installer.install(options[:modules], puppetfile, moduledir)
|
819
867
|
end
|
820
868
|
|
821
|
-
#
|
822
|
-
#
|
823
|
-
#
|
824
|
-
|
825
|
-
# both files existing
|
826
|
-
if config.exist?
|
827
|
-
@logger.warn "Found existing project directory at #{project}. Skipping file creation."
|
828
|
-
# This won't get called if bolt-project.yaml exists
|
829
|
-
elsif old_config.exist?
|
830
|
-
@logger.warn "Found existing #{old_config.basename} at #{project}. "\
|
831
|
-
"#{old_config.basename} is deprecated, please rename to #{config.basename}."
|
832
|
-
# Bless the project directory as a...wait for it...project
|
833
|
-
else
|
869
|
+
# If either bolt.yaml or bolt-project.yaml exist, the user has already
|
870
|
+
# been warned and we can just finish project creation. Otherwise, create a
|
871
|
+
# bolt-project.yaml with the project name in it.
|
872
|
+
unless config.exist? || old_config.exist?
|
834
873
|
begin
|
835
874
|
content = { 'name' => name }
|
836
875
|
File.write(config.to_path, content.to_yaml)
|
@@ -840,109 +879,86 @@ module Bolt
|
|
840
879
|
end
|
841
880
|
end
|
842
881
|
|
843
|
-
# Write the generated Puppetfile to the fancy new project
|
844
|
-
if puppetfile_specs
|
845
|
-
File.write(puppetfile, puppetfile_specs.join("\n"))
|
846
|
-
outputter.print_message "Successfully created Puppetfile at #{puppetfile}"
|
847
|
-
# Install the modules from our shiny new Puppetfile
|
848
|
-
if install_puppetfile({}, puppetfile, modulepath)
|
849
|
-
outputter.print_message "Successfully installed #{options[:modules].join(', ')}"
|
850
|
-
else
|
851
|
-
raise Bolt::CLIError, "Could not install #{options[:modules].join(', ')}"
|
852
|
-
end
|
853
|
-
end
|
854
|
-
|
855
882
|
0
|
856
883
|
end
|
857
884
|
|
858
|
-
#
|
859
|
-
#
|
860
|
-
def
|
861
|
-
|
862
|
-
|
863
|
-
# Build the document model from the module names, defaulting to the latest version of each module
|
864
|
-
model = PuppetfileResolver::Puppetfile::Document.new('')
|
865
|
-
options[:modules].each do |mod_name|
|
866
|
-
model.add_module(
|
867
|
-
PuppetfileResolver::Puppetfile::ForgeModule.new(mod_name).tap { |mod| mod.version = :latest }
|
868
|
-
)
|
869
|
-
end
|
870
|
-
|
871
|
-
# Make sure the Puppetfile model is valid
|
872
|
-
unless model.valid?
|
873
|
-
raise Bolt::ValidationError,
|
874
|
-
"Unable to resolve dependencies for #{options[:modules].join(', ')}"
|
875
|
-
end
|
876
|
-
|
877
|
-
# Create the resolver using the Puppetfile model. nil disables Puppet version restrictions.
|
878
|
-
resolver = PuppetfileResolver::Resolver.new(model, nil)
|
879
|
-
|
880
|
-
# Configure and resolve the dependency graph
|
881
|
-
result = resolver.resolve(
|
882
|
-
cache: nil,
|
883
|
-
ui: nil,
|
884
|
-
module_paths: [],
|
885
|
-
allow_missing_modules: true
|
886
|
-
)
|
885
|
+
# Installs modules declared in the project configuration file.
|
886
|
+
#
|
887
|
+
def install_project_modules(project, force, resolve)
|
888
|
+
assert_project_file(project)
|
887
889
|
|
888
|
-
|
889
|
-
|
890
|
-
|
890
|
+
unless project.modules
|
891
|
+
outputter.print_message "Project configuration file #{project.project_file} does not "\
|
892
|
+
"specify any module dependencies. Nothing to do."
|
893
|
+
return 0
|
891
894
|
end
|
892
895
|
|
893
|
-
|
894
|
-
titles = model.modules.each_with_object({}) do |mod, acc|
|
895
|
-
acc[mod.name] = mod.title
|
896
|
-
end
|
896
|
+
installer = Bolt::ModuleInstaller.new(outputter, pal)
|
897
897
|
|
898
|
-
|
899
|
-
|
898
|
+
ok = installer.install(project.modules,
|
899
|
+
project.puppetfile,
|
900
|
+
project.managed_moduledir,
|
901
|
+
force: force,
|
902
|
+
resolve: resolve)
|
903
|
+
ok ? 0 : 1
|
904
|
+
end
|
900
905
|
|
901
|
-
|
902
|
-
|
903
|
-
|
906
|
+
# Adds a single module to the project.
|
907
|
+
#
|
908
|
+
def add_project_module(name, project)
|
909
|
+
assert_project_file(project)
|
910
|
+
|
911
|
+
modules = project.modules || []
|
912
|
+
installer = Bolt::ModuleInstaller.new(outputter, pal)
|
913
|
+
|
914
|
+
ok = installer.add(name,
|
915
|
+
modules,
|
916
|
+
project.puppetfile,
|
917
|
+
project.managed_moduledir,
|
918
|
+
project.project_file)
|
919
|
+
ok ? 0 : 1
|
920
|
+
end
|
904
921
|
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
922
|
+
# Asserts that there is a project configuration file.
|
923
|
+
#
|
924
|
+
def assert_project_file(project)
|
925
|
+
unless project.project_file?
|
926
|
+
msg = if project.config_file.exist?
|
927
|
+
"Detected Bolt configuration file #{project.config_file}, unable to install "\
|
928
|
+
"modules. To update to a project configuration file, run 'bolt project migrate'."
|
929
|
+
else
|
930
|
+
"Could not find project configuration file #{project.project_file}, unable "\
|
931
|
+
"to install modules. To create a Bolt project, run 'bolt project init'."
|
932
|
+
end
|
909
933
|
|
910
|
-
|
911
|
-
spec_graph.values.map do |spec|
|
912
|
-
"mod '#{spec.owner}-#{spec.name}', '#{spec.version}'"
|
934
|
+
raise Bolt::Error.new(msg, 'bolt/missing-project-config-error')
|
913
935
|
end
|
914
936
|
end
|
915
937
|
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
root: puppetfile.dirname.to_s,
|
924
|
-
puppetfile: puppetfile.to_s,
|
925
|
-
moduledir: moduledir
|
926
|
-
}
|
927
|
-
|
928
|
-
settings = R10K::Settings.global_settings.evaluate(config)
|
929
|
-
R10K::Initializers::GlobalInitializer.new(settings).call
|
930
|
-
install_action = R10K::Action::Puppetfile::Install.new(r10k_opts, nil)
|
931
|
-
|
932
|
-
# Override the r10k logger with a proxy to our own logger
|
933
|
-
R10K::Logging.instance_variable_set(:@outputter, Bolt::R10KLogProxy.new)
|
934
|
-
|
935
|
-
ok = install_action.call
|
936
|
-
outputter.print_puppetfile_result(ok, puppetfile, moduledir)
|
937
|
-
# Automatically generate types after installing modules
|
938
|
-
pal.generate_types
|
938
|
+
# Loads a Puppetfile and installs its modules.
|
939
|
+
#
|
940
|
+
def install_puppetfile(config, puppetfile, moduledir)
|
941
|
+
installer = Bolt::ModuleInstaller.new(outputter, pal)
|
942
|
+
ok = installer.install_puppetfile(puppetfile, moduledir, config)
|
943
|
+
ok ? 0 : 1
|
944
|
+
end
|
939
945
|
|
940
|
-
|
941
|
-
|
942
|
-
|
946
|
+
# Raises an error if the 'puppetfile install' command is deprecated due to
|
947
|
+
# modules being configured.
|
948
|
+
#
|
949
|
+
def assert_puppetfile_or_module_command(modules)
|
950
|
+
if modules && options[:subcommand] == 'puppetfile'
|
951
|
+
raise Bolt::CLIError,
|
952
|
+
"Unable to use command 'bolt puppetfile #{options[:action]}' when "\
|
953
|
+
"'modules' is configured in bolt-project.yaml. Use the 'module' command "\
|
954
|
+
"instead. For a list of available actions for the 'module' command, run "\
|
955
|
+
"'bolt module --help'."
|
956
|
+
elsif modules.nil? && options[:subcommand] == 'module'
|
957
|
+
raise Bolt::CLIError,
|
958
|
+
"Unable to use command 'bolt module #{options[:action]}'. To use "\
|
959
|
+
"this command, update your project configuration to manage module "\
|
960
|
+
"dependencies."
|
943
961
|
end
|
944
|
-
rescue R10K::Error => e
|
945
|
-
raise PuppetfileError, e
|
946
962
|
end
|
947
963
|
|
948
964
|
def pal
|
@@ -958,17 +974,17 @@ module Bolt
|
|
958
974
|
# Collects the list of Bolt guides and maps them to their topics.
|
959
975
|
def guides
|
960
976
|
@guides ||= begin
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
977
|
+
root_path = File.expand_path(File.join(__dir__, '..', '..', 'guides'))
|
978
|
+
files = Dir.children(root_path).sort
|
979
|
+
|
980
|
+
files.each_with_object({}) do |file, guides|
|
981
|
+
next if file !~ /\.txt\z/
|
982
|
+
topic = File.basename(file, '.txt')
|
983
|
+
guides[topic] = File.join(root_path, file)
|
984
|
+
end
|
985
|
+
rescue SystemCallError => e
|
986
|
+
raise Bolt::FileError.new("#{e.message}: unable to load guides directory", root_path)
|
987
|
+
end
|
972
988
|
end
|
973
989
|
|
974
990
|
# Display the list of available Bolt guides.
|
@@ -1019,10 +1035,10 @@ module Bolt
|
|
1019
1035
|
|
1020
1036
|
def analytics
|
1021
1037
|
@analytics ||= begin
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1038
|
+
client = Bolt::Analytics.build_client
|
1039
|
+
client.bundled_content = bundled_content
|
1040
|
+
client
|
1041
|
+
end
|
1026
1042
|
end
|
1027
1043
|
|
1028
1044
|
def bundled_content
|
@@ -1057,17 +1073,10 @@ module Bolt
|
|
1057
1073
|
content
|
1058
1074
|
end
|
1059
1075
|
|
1060
|
-
def config_loaded
|
1061
|
-
msg = <<~MSG.chomp
|
1062
|
-
Loaded configuration from: '#{config.config_files.join("', '")}'
|
1063
|
-
MSG
|
1064
|
-
@logger.info(msg)
|
1065
|
-
end
|
1066
|
-
|
1067
1076
|
# Gem installs include the aggregate, canary, and puppetdb_fact modules, while
|
1068
1077
|
# package installs include modules listed in the Bolt repo Puppetfile
|
1069
1078
|
def incomplete_install?
|
1070
|
-
(Dir.children(Bolt::PAL::MODULES_PATH) - %w[aggregate canary puppetdb_fact]).empty?
|
1079
|
+
(Dir.children(Bolt::PAL::MODULES_PATH) - %w[aggregate canary puppetdb_fact secure_env_vars]).empty?
|
1071
1080
|
end
|
1072
1081
|
|
1073
1082
|
# Mimicks the output from Outputter::Human#fatal_error. This should be used to print
|