bolt 2.6.0 → 2.11.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/applyresult.rb +2 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/resourceinstance.rb +27 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +2 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/resultset.rb +2 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/target.rb +4 -3
- data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +192 -0
- data/bolt-modules/boltlib/lib/puppet/functions/set_resources.rb +122 -0
- data/bolt-modules/boltlib/types/planresult.pp +12 -1
- data/bolt-modules/file/lib/puppet/functions/file/exists.rb +3 -1
- data/bolt-modules/file/lib/puppet/functions/file/join.rb +1 -1
- data/bolt-modules/file/lib/puppet/functions/file/read.rb +2 -1
- data/bolt-modules/file/lib/puppet/functions/file/readable.rb +3 -1
- data/bolt-modules/file/lib/puppet/functions/file/write.rb +3 -1
- data/bolt-modules/prompt/lib/puppet/functions/prompt.rb +43 -0
- data/lib/bolt/analytics.rb +1 -1
- data/lib/bolt/applicator.rb +3 -2
- data/lib/bolt/apply_inventory.rb +1 -1
- data/lib/bolt/apply_result.rb +1 -1
- data/lib/bolt/apply_target.rb +11 -2
- data/lib/bolt/bolt_option_parser.rb +27 -7
- data/lib/bolt/catalog.rb +32 -3
- data/lib/bolt/cli.rb +52 -22
- data/lib/bolt/config.rb +51 -27
- data/lib/bolt/config/transport/base.rb +3 -3
- data/lib/bolt/config/transport/docker.rb +7 -1
- data/lib/bolt/config/transport/local.rb +9 -1
- data/lib/bolt/config/transport/orch.rb +4 -2
- data/lib/bolt/config/transport/remote.rb +2 -0
- data/lib/bolt/config/transport/ssh.rb +81 -3
- data/lib/bolt/config/transport/winrm.rb +6 -1
- data/lib/bolt/executor.rb +38 -0
- data/lib/bolt/inventory.rb +2 -1
- data/lib/bolt/inventory/group.rb +1 -0
- data/lib/bolt/inventory/inventory.rb +9 -0
- data/lib/bolt/inventory/target.rb +17 -1
- data/lib/bolt/node/output.rb +1 -1
- data/lib/bolt/outputter/human.rb +5 -4
- data/lib/bolt/outputter/json.rb +1 -1
- data/lib/bolt/pal.rb +32 -14
- data/lib/bolt/pal/yaml_plan.rb +1 -0
- data/lib/bolt/plugin.rb +14 -8
- data/lib/bolt/plugin/env_var.rb +2 -1
- data/lib/bolt/plugin/module.rb +40 -7
- data/lib/bolt/plugin/prompt.rb +1 -1
- data/lib/bolt/plugin/puppetdb.rb +5 -2
- data/lib/bolt/project.rb +135 -0
- data/lib/bolt/puppetdb/config.rb +16 -28
- data/lib/bolt/rerun.rb +1 -1
- data/lib/bolt/resource_instance.rb +126 -0
- data/lib/bolt/result.rb +46 -23
- data/lib/bolt/result_set.rb +2 -5
- data/lib/bolt/secret.rb +20 -4
- data/lib/bolt/shell/bash.rb +27 -14
- data/lib/bolt/shell/bash/tmpdir.rb +1 -1
- data/lib/bolt/shell/powershell.rb +43 -15
- data/lib/bolt/shell/powershell/snippets.rb +1 -1
- data/lib/bolt/target.rb +18 -2
- data/lib/bolt/transport/base.rb +24 -8
- data/lib/bolt/transport/docker.rb +3 -3
- data/lib/bolt/transport/docker/connection.rb +11 -7
- data/lib/bolt/transport/local/connection.rb +13 -7
- data/lib/bolt/transport/orch.rb +5 -1
- data/lib/bolt/transport/ssh.rb +6 -2
- data/lib/bolt/transport/ssh/connection.rb +26 -1
- data/lib/bolt/transport/ssh/exec_connection.rb +110 -0
- data/lib/bolt/transport/winrm/connection.rb +10 -2
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/pe/pal.rb +1 -38
- data/lib/bolt_server/transport_app.rb +7 -7
- data/lib/bolt_spec/bolt_context.rb +3 -6
- data/lib/bolt_spec/plans.rb +78 -8
- data/lib/bolt_spec/plans/action_stubs.rb +37 -7
- data/lib/bolt_spec/plans/action_stubs/plan_stub.rb +55 -0
- data/lib/bolt_spec/plans/mock_executor.rb +62 -2
- data/lib/bolt_spec/run.rb +10 -13
- metadata +26 -7
- data/lib/bolt/boltdir.rb +0 -54
- data/lib/bolt/plugin/pkcs7.rb +0 -104
- data/lib/bolt/secret/base.rb +0 -41
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Check if a file exists
|
3
|
+
# Check if a local file exists using Puppet's
|
4
|
+
# `Puppet::Parser::Files.find_file()` function. This will only check files that
|
5
|
+
# are on the machine Bolt is run on.
|
4
6
|
Puppet::Functions.create_function(:'file::exists', Puppet::Functions::InternalFunction) do
|
5
7
|
# @param filename Absolute path or Puppet file path.
|
6
8
|
# @return Whether the file exists.
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Read a file and return its contents.
|
3
|
+
# Read a file on localhost and return its contents using ruby's `File.read`. This will
|
4
|
+
# only read files on the machine you run Bolt on.
|
4
5
|
Puppet::Functions.create_function(:'file::read', Puppet::Functions::InternalFunction) do
|
5
6
|
# @param filename Absolute path or Puppet file path.
|
6
7
|
# @return The file's contents.
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Check if a file is readable
|
3
|
+
# Check if a local file is readable using Puppet's
|
4
|
+
# `Puppet::Parser::Files.find_file()` function. This will only check files on the
|
5
|
+
# machine you run Bolt on.
|
4
6
|
Puppet::Functions.create_function(:'file::readable', Puppet::Functions::InternalFunction) do
|
5
7
|
# @param filename Absolute path or Puppet file path.
|
6
8
|
# @return Whether the file is readable.
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Write a string to a file.
|
3
|
+
# Write a string to a file on localhost using ruby's `File.write`. This will
|
4
|
+
# only write files to the machine you run Bolt on. Use `write_file()` to write
|
5
|
+
# to remote targets.
|
4
6
|
Puppet::Functions.create_function(:'file::write') do
|
5
7
|
# @param filename Absolute path.
|
6
8
|
# @param content File content to write.
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
|
5
|
+
# Display a prompt and wait for a response.
|
6
|
+
#
|
7
|
+
# > **Note:** Not available in apply block
|
8
|
+
Puppet::Functions.create_function(:prompt) do
|
9
|
+
# @param prompt The prompt to display.
|
10
|
+
# @param options A hash of additional options.
|
11
|
+
# @option options [Boolean] sensitive Disable echo back and mark the response as sensitive.
|
12
|
+
# @return The response to the prompt.
|
13
|
+
# @example Prompt the user if plan execution should continue
|
14
|
+
# $response = prompt('Continue executing plan? [Y\N]')
|
15
|
+
# @example Prompt the user for sensitive information
|
16
|
+
# $password = prompt('Enter your password', 'sensitive' => true)
|
17
|
+
dispatch :prompt do
|
18
|
+
param 'String', :prompt
|
19
|
+
optional_param 'Hash[String[1], Any]', :options
|
20
|
+
return_type 'Variant[String, Sensitive]'
|
21
|
+
end
|
22
|
+
|
23
|
+
def prompt(prompt, options = {})
|
24
|
+
unless Puppet[:tasks]
|
25
|
+
raise Puppet::ParseErrorWithIssue
|
26
|
+
.from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING,
|
27
|
+
action: 'prompt')
|
28
|
+
end
|
29
|
+
|
30
|
+
options = options.transform_keys(&:to_sym)
|
31
|
+
|
32
|
+
executor = Puppet.lookup(:bolt_executor)
|
33
|
+
executor.report_function_call(self.class.name)
|
34
|
+
|
35
|
+
response = executor.prompt(prompt, options)
|
36
|
+
|
37
|
+
if options[:sensitive]
|
38
|
+
Puppet::Pops::Types::PSensitiveType::Sensitive.new(response)
|
39
|
+
else
|
40
|
+
response
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/bolt/analytics.rb
CHANGED
@@ -63,7 +63,7 @@ module Bolt
|
|
63
63
|
disabled: true
|
64
64
|
|
65
65
|
Read more about what data Bolt collects and why here:
|
66
|
-
https://puppet.com/docs/bolt/latest/bolt_installing.html#
|
66
|
+
https://puppet.com/docs/bolt/latest/bolt_installing.html#analytics-data-collection
|
67
67
|
ANALYTICS
|
68
68
|
end
|
69
69
|
|
data/lib/bolt/applicator.rb
CHANGED
@@ -34,6 +34,8 @@ module Bolt
|
|
34
34
|
search_dirs << mod.plugins if mod.plugins?
|
35
35
|
search_dirs << mod.pluginfacts if mod.pluginfacts?
|
36
36
|
search_dirs << mod.files if mod.files?
|
37
|
+
type_files = "#{mod.path}/types"
|
38
|
+
search_dirs << type_files if File.exist?(type_files)
|
37
39
|
search_dirs
|
38
40
|
end
|
39
41
|
end
|
@@ -155,7 +157,6 @@ module Bolt
|
|
155
157
|
end
|
156
158
|
|
157
159
|
plan_vars = scope.to_hash(true, true)
|
158
|
-
%w[trusted server_facts facts].each { |k| plan_vars.delete(k) }
|
159
160
|
|
160
161
|
targets = @inventory.get_targets(args[0])
|
161
162
|
|
@@ -182,7 +183,7 @@ module Bolt
|
|
182
183
|
rich_data: true,
|
183
184
|
symbol_as_string: true,
|
184
185
|
type_by_reference: true,
|
185
|
-
local_reference:
|
186
|
+
local_reference: true)
|
186
187
|
|
187
188
|
scope = {
|
188
189
|
code_ast: ast,
|
data/lib/bolt/apply_inventory.rb
CHANGED
data/lib/bolt/apply_result.rb
CHANGED
@@ -57,7 +57,7 @@ module Bolt
|
|
57
57
|
msg = "Report result contains an '_output' key. Catalog application may have printed extraneous output to stdout: #{result['_output']}"
|
58
58
|
# rubocop:enable Layout/LineLength
|
59
59
|
else
|
60
|
-
msg = "Report did not contain all expected keys missing: #{missing_keys.join('
|
60
|
+
msg = "Report did not contain all expected keys missing: #{missing_keys.join(', ')}"
|
61
61
|
end
|
62
62
|
|
63
63
|
{ 'msg' => msg,
|
data/lib/bolt/apply_target.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Bolt
|
4
4
|
class ApplyTarget
|
5
5
|
ATTRIBUTES = %i[uri name target_alias config vars facts features
|
6
|
-
plugin_hooks safe_name].freeze
|
6
|
+
plugin_hooks resources safe_name].freeze
|
7
7
|
COMPUTED = %i[host password port protocol user].freeze
|
8
8
|
|
9
9
|
attr_reader(*ATTRIBUTES)
|
@@ -24,7 +24,8 @@ module Bolt
|
|
24
24
|
facts = nil,
|
25
25
|
vars = nil,
|
26
26
|
features = nil,
|
27
|
-
plugin_hooks = nil
|
27
|
+
plugin_hooks = nil,
|
28
|
+
resources = nil)
|
28
29
|
raise Bolt::Error.new("Target objects cannot be instantiated inside apply blocks", 'bolt/apply-error')
|
29
30
|
end
|
30
31
|
# rubocop:enable Lint/UnusedMethodArgument
|
@@ -57,6 +58,10 @@ module Bolt
|
|
57
58
|
@user = Addressable::URI.unencode_component(uri_obj.user) || t_conf['user']
|
58
59
|
end
|
59
60
|
|
61
|
+
def to_s
|
62
|
+
@safe_name
|
63
|
+
end
|
64
|
+
|
60
65
|
def parse_uri(string)
|
61
66
|
require 'addressable/uri'
|
62
67
|
if string.nil?
|
@@ -73,5 +78,9 @@ module Bolt
|
|
73
78
|
rescue Addressable::URI::InvalidURIError => e
|
74
79
|
raise Bolt::ParseError, "Could not parse target URI: #{e.message}"
|
75
80
|
end
|
81
|
+
|
82
|
+
def hash
|
83
|
+
@name.hash
|
84
|
+
end
|
76
85
|
end
|
77
86
|
end
|
@@ -9,9 +9,9 @@ module Bolt
|
|
9
9
|
OPTIONS = { inventory: %w[targets query rerun description],
|
10
10
|
authentication: %w[user password password-prompt private-key host-key-check ssl ssl-verify],
|
11
11
|
escalation: %w[run-as sudo-password sudo-password-prompt sudo-executable],
|
12
|
-
run_context: %w[concurrency inventoryfile save-rerun],
|
12
|
+
run_context: %w[concurrency inventoryfile save-rerun cleanup],
|
13
13
|
global_config_setters: %w[modulepath boltdir configfile],
|
14
|
-
transports: %w[transport connect-timeout tty],
|
14
|
+
transports: %w[transport connect-timeout tty ssh-command copy-command],
|
15
15
|
display: %w[format color verbose trace],
|
16
16
|
global: %w[help version debug] }.freeze
|
17
17
|
|
@@ -64,7 +64,7 @@ module Bolt
|
|
64
64
|
{ flags: OPTIONS[:global] + OPTIONS[:global_config_setters],
|
65
65
|
banner: PLAN_CONVERT_HELP }
|
66
66
|
when 'run'
|
67
|
-
{ flags: ACTION_OPTS + %w[params compile-concurrency tmpdir],
|
67
|
+
{ flags: ACTION_OPTS + %w[params compile-concurrency tmpdir hiera-config],
|
68
68
|
banner: PLAN_RUN_HELP }
|
69
69
|
when 'show'
|
70
70
|
{ flags: OPTIONS[:global] + OPTIONS[:global_config_setters] + %w[filter format],
|
@@ -112,7 +112,7 @@ module Bolt
|
|
112
112
|
when 'secret'
|
113
113
|
case action
|
114
114
|
when 'createkeys'
|
115
|
-
{ flags: OPTIONS[:global] + OPTIONS[:global_config_setters] + %w[plugin],
|
115
|
+
{ flags: OPTIONS[:global] + OPTIONS[:global_config_setters] + %w[plugin force],
|
116
116
|
banner: SECRET_CREATEKEYS_HELP }
|
117
117
|
when 'decrypt'
|
118
118
|
{ flags: OPTIONS[:global] + OPTIONS[:global_config_setters] + %w[plugin],
|
@@ -594,6 +594,7 @@ module Bolt
|
|
594
594
|
HELP
|
595
595
|
|
596
596
|
attr_reader :warnings
|
597
|
+
|
597
598
|
def initialize(options)
|
598
599
|
super()
|
599
600
|
|
@@ -655,8 +656,8 @@ module Bolt
|
|
655
656
|
@options[:password] = STDIN.noecho(&:gets).chomp
|
656
657
|
STDERR.puts
|
657
658
|
end
|
658
|
-
define('--private-key KEY', '
|
659
|
-
@options[:'private-key'] = key
|
659
|
+
define('--private-key KEY', 'Path to private ssh key to authenticate with') do |key|
|
660
|
+
@options[:'private-key'] = File.expand_path(key)
|
660
661
|
end
|
661
662
|
define('--[no-]host-key-check', 'Check host keys with SSH') do |host_key_check|
|
662
663
|
@options[:'host-key-check'] = host_key_check
|
@@ -688,13 +689,17 @@ module Bolt
|
|
688
689
|
|
689
690
|
separator "\nRUN CONTEXT OPTIONS"
|
690
691
|
define('-c', '--concurrency CONCURRENCY', Integer,
|
691
|
-
'Maximum number of simultaneous connections
|
692
|
+
'Maximum number of simultaneous connections') do |concurrency|
|
692
693
|
@options[:concurrency] = concurrency
|
693
694
|
end
|
694
695
|
define('--compile-concurrency CONCURRENCY', Integer,
|
695
696
|
'Maximum number of simultaneous manifest block compiles (default: number of cores)') do |concurrency|
|
696
697
|
@options[:'compile-concurrency'] = concurrency
|
697
698
|
end
|
699
|
+
define('--[no-]cleanup',
|
700
|
+
'Whether to clean up temporary files created on targets') do |cleanup|
|
701
|
+
@options[:cleanup] = cleanup
|
702
|
+
end
|
698
703
|
define('-m', '--modulepath MODULES',
|
699
704
|
"List of directories containing modules, separated by '#{File::PATH_SEPARATOR}'",
|
700
705
|
'Directories are case-sensitive') do |modulepath|
|
@@ -712,6 +717,10 @@ module Bolt
|
|
712
717
|
'Directory containing bolt.yaml will be used as the Boltdir.') do |path|
|
713
718
|
@options[:configfile] = path
|
714
719
|
end
|
720
|
+
define('--hiera-config FILEPATH',
|
721
|
+
'Specify where to load Hiera config from (default: ~/.puppetlabs/bolt/hiera.yaml)') do |path|
|
722
|
+
@options[:'hiera-config'] = File.expand_path(path)
|
723
|
+
end
|
715
724
|
define('-i', '--inventoryfile FILEPATH',
|
716
725
|
'Specify where to load inventory from (default: ~/.puppetlabs/bolt/inventory.yaml)') do |path|
|
717
726
|
if ENV.include?(Bolt::Inventory::ENVIRONMENT_VAR)
|
@@ -733,6 +742,14 @@ module Bolt
|
|
733
742
|
"Specify a default transport: #{TRANSPORTS.keys.join(', ')}") do |t|
|
734
743
|
@options[:transport] = t
|
735
744
|
end
|
745
|
+
define('--ssh-command EXEC', "Executable to use instead of the net-ssh ruby library. ",
|
746
|
+
"This option is experimental.") do |exec|
|
747
|
+
@options[:'ssh-command'] = exec
|
748
|
+
end
|
749
|
+
define('--copy-command EXEC', "Command to copy files to remote hosts if using external SSH. ",
|
750
|
+
"This option is experimental.") do |exec|
|
751
|
+
@options[:'copy-command'] = exec
|
752
|
+
end
|
736
753
|
define('--connect-timeout TIMEOUT', Integer, 'Connection timeout (defaults vary)') do |timeout|
|
737
754
|
@options[:'connect-timeout'] = timeout
|
738
755
|
end
|
@@ -771,6 +788,9 @@ module Bolt
|
|
771
788
|
'when initializing a project. Resolves and installs all dependencies.') do |modules|
|
772
789
|
@options[:modules] = modules.split(',')
|
773
790
|
end
|
791
|
+
define('--force', 'Overwrite existing key pairs') do |_force|
|
792
|
+
@options[:force] = true
|
793
|
+
end
|
774
794
|
|
775
795
|
separator "\nGLOBAL OPTIONS"
|
776
796
|
define('-h', '--help', 'Display help') do |_|
|
data/lib/bolt/catalog.rb
CHANGED
@@ -70,9 +70,38 @@ module Bolt
|
|
70
70
|
bolt_inventory: inv) do
|
71
71
|
Puppet.lookup(:pal_current_node).trusted_data = target['trusted']
|
72
72
|
pal.with_catalog_compiler do |compiler|
|
73
|
-
#
|
74
|
-
|
75
|
-
|
73
|
+
# Deserializing needs to happen inside the catalog compiler so
|
74
|
+
# loaders are initialized for loading
|
75
|
+
plan_vars = Puppet::Pops::Serialization::FromDataConverter.convert(request['plan_vars'])
|
76
|
+
|
77
|
+
# Facts will be set by the catalog compiler, so we need to ensure
|
78
|
+
# that any plan or target variables with the same name are not
|
79
|
+
# passed into the apply block to avoid a redefinition error.
|
80
|
+
# Filter out plan and target vars separately and raise a Puppet
|
81
|
+
# warning if there are any collisions for either. Puppet warning
|
82
|
+
# is the only way to log a message that will make it back to Bolt
|
83
|
+
# to be printed.
|
84
|
+
pv_collisions, pv_filtered = plan_vars.partition do |k, _|
|
85
|
+
target['facts'].keys.include?(k)
|
86
|
+
end.map(&:to_h)
|
87
|
+
unless pv_collisions.empty?
|
88
|
+
print_pv = pv_collisions.keys.map { |k| "$#{k}" }.join(', ')
|
89
|
+
plural = pv_collisions.keys.length == 1 ? '' : 's'
|
90
|
+
Puppet.warning("Plan variable#{plural} #{print_pv} will be overridden by fact#{plural} " \
|
91
|
+
"of the same name in the apply block")
|
92
|
+
end
|
93
|
+
|
94
|
+
tv_collisions, tv_filtered = target['variables'].partition do |k, _|
|
95
|
+
target['facts'].keys.include?(k)
|
96
|
+
end.map(&:to_h)
|
97
|
+
unless tv_collisions.empty?
|
98
|
+
print_tv = tv_collisions.keys.map { |k| "$#{k}" }.join(', ')
|
99
|
+
plural = tv_collisions.keys.length == 1 ? '' : 's'
|
100
|
+
Puppet.warning("Target variable#{plural} #{print_tv} " \
|
101
|
+
"will be overridden by fact#{plural} of the same name in the apply block")
|
102
|
+
end
|
103
|
+
|
104
|
+
pal.send(:add_variables, compiler.send(:topscope), tv_filtered.merge(pv_filtered))
|
76
105
|
|
77
106
|
# Configure language strictness in the CatalogCompiler. We want Bolt to be able
|
78
107
|
# to compile most Puppet 4+ manifests, so we default to allowing deprecated functions.
|
data/lib/bolt/cli.rb
CHANGED
@@ -114,18 +114,19 @@ module Bolt
|
|
114
114
|
@config = if options[:configfile]
|
115
115
|
Bolt::Config.from_file(options[:configfile], options)
|
116
116
|
else
|
117
|
-
|
118
|
-
Bolt::
|
117
|
+
project = if options[:boltdir]
|
118
|
+
Bolt::Project.new(options[:boltdir])
|
119
119
|
else
|
120
|
-
Bolt::
|
120
|
+
Bolt::Project.find_boltdir(Dir.pwd)
|
121
121
|
end
|
122
|
-
Bolt::Config.
|
122
|
+
Bolt::Config.from_project(project, options)
|
123
123
|
end
|
124
124
|
|
125
125
|
Bolt::Logger.configure(config.log, config.color)
|
126
126
|
|
127
|
-
# Logger must be configured before checking path case, otherwise warnings will not display
|
127
|
+
# Logger must be configured before checking path case and project file, otherwise warnings will not display
|
128
128
|
@config.check_path_case('modulepath', @config.modulepath)
|
129
|
+
@config.project.check_deprecated_file
|
129
130
|
|
130
131
|
# Log the file paths for loaded config files
|
131
132
|
config_loaded
|
@@ -238,6 +239,12 @@ module Bolt
|
|
238
239
|
if options[:subcommand] == 'command' && (!options[:object] || options[:object].empty?)
|
239
240
|
raise Bolt::CLIError, "Must specify a command to run"
|
240
241
|
end
|
242
|
+
|
243
|
+
if options[:subcommand] == 'secret' &&
|
244
|
+
(options[:action] == 'decrypt' || options[:action] == 'encrypt') &&
|
245
|
+
!options[:object]
|
246
|
+
raise Bolt::CLIError, "Must specify a value to #{options[:action]}"
|
247
|
+
end
|
241
248
|
end
|
242
249
|
|
243
250
|
def handle_parser_errors
|
@@ -251,13 +258,11 @@ module Bolt
|
|
251
258
|
end
|
252
259
|
|
253
260
|
def puppetdb_client
|
254
|
-
|
255
|
-
puppetdb_config = Bolt::PuppetDB::Config.load_config(nil, config.puppetdb, config.boltdir.path)
|
256
|
-
@puppetdb_client = Bolt::PuppetDB::Client.new(puppetdb_config)
|
261
|
+
plugins.puppetdb_client
|
257
262
|
end
|
258
263
|
|
259
264
|
def plugins
|
260
|
-
@plugins ||= Bolt::Plugin.setup(config, pal,
|
265
|
+
@plugins ||= Bolt::Plugin.setup(config, pal, analytics)
|
261
266
|
end
|
262
267
|
|
263
268
|
def query_puppetdb_nodes(query)
|
@@ -314,7 +319,8 @@ module Bolt
|
|
314
319
|
|
315
320
|
screen_view_fields = {
|
316
321
|
output_format: config.format,
|
317
|
-
|
322
|
+
# For continuity
|
323
|
+
boltdir_type: config.project.type
|
318
324
|
}
|
319
325
|
|
320
326
|
# Only include target and inventory info for commands that take a targets
|
@@ -447,6 +453,7 @@ module Bolt
|
|
447
453
|
def list_tasks
|
448
454
|
tasks = pal.list_tasks
|
449
455
|
tasks.select! { |task| task.first.include?(options[:filter]) } if options[:filter]
|
456
|
+
tasks.select! { |task| config.project.tasks.include?(task.first) } unless config.project.tasks.nil?
|
450
457
|
outputter.print_tasks(tasks, pal.list_modulepath)
|
451
458
|
end
|
452
459
|
|
@@ -457,6 +464,7 @@ module Bolt
|
|
457
464
|
def list_plans
|
458
465
|
plans = pal.list_plans
|
459
466
|
plans.select! { |plan| plan.first.include?(options[:filter]) } if options[:filter]
|
467
|
+
plans.select! { |plan| config.project.plans.include?(plan.first) } unless config.project.plans.nil?
|
460
468
|
outputter.print_plans(plans, pal.list_modulepath)
|
461
469
|
end
|
462
470
|
|
@@ -567,10 +575,10 @@ module Bolt
|
|
567
575
|
# Initializes a specified directory as a Bolt project and installs any modules
|
568
576
|
# specified by the user, along with their dependencies
|
569
577
|
def initialize_project
|
570
|
-
|
571
|
-
config =
|
572
|
-
puppetfile =
|
573
|
-
modulepath = [
|
578
|
+
project = Pathname.new(File.expand_path(options[:object] || Dir.pwd))
|
579
|
+
config = project + 'bolt.yaml'
|
580
|
+
puppetfile = project + 'Puppetfile'
|
581
|
+
modulepath = [project + 'modules']
|
574
582
|
|
575
583
|
# If modules were specified, first check if there is already a Puppetfile at the project
|
576
584
|
# directory, erroring if there is. If there is no Puppetfile, generate the Puppetfile
|
@@ -590,20 +598,20 @@ module Bolt
|
|
590
598
|
# Warn the user if the project directory already exists. We don't error here since users
|
591
599
|
# might not have installed any modules yet.
|
592
600
|
if config.exist?
|
593
|
-
@logger.warn "Found existing project directory at #{
|
601
|
+
@logger.warn "Found existing project directory at #{project}"
|
594
602
|
end
|
595
603
|
|
596
604
|
# Create the project directory
|
597
|
-
FileUtils.mkdir_p(
|
605
|
+
FileUtils.mkdir_p(project)
|
598
606
|
|
599
|
-
# Bless the project directory as a
|
607
|
+
# Bless the project directory as a...wait for it...project
|
600
608
|
if FileUtils.touch(config)
|
601
|
-
outputter.print_message "Successfully created Bolt project at #{
|
609
|
+
outputter.print_message "Successfully created Bolt project at #{project}"
|
602
610
|
else
|
603
|
-
raise Bolt::FileError.new("Could not create Bolt project directory at #{
|
611
|
+
raise Bolt::FileError.new("Could not create Bolt project directory at #{project}", nil)
|
604
612
|
end
|
605
613
|
|
606
|
-
# Write the generated Puppetfile to the fancy new
|
614
|
+
# Write the generated Puppetfile to the fancy new project
|
607
615
|
if puppetfile_specs
|
608
616
|
File.write(puppetfile, puppetfile_specs.join("\n"))
|
609
617
|
outputter.print_message "Successfully created Puppetfile at #{puppetfile}"
|
@@ -752,12 +760,14 @@ module Bolt
|
|
752
760
|
end
|
753
761
|
|
754
762
|
def pal
|
763
|
+
project = config.project.load_as_module? ? config.project : nil
|
755
764
|
@pal ||= Bolt::PAL.new(config.modulepath,
|
756
765
|
config.hiera_config,
|
757
|
-
config.
|
766
|
+
config.project.resource_types,
|
758
767
|
config.compile_concurrency,
|
759
768
|
config.trusted_external,
|
760
|
-
config.apply_settings
|
769
|
+
config.apply_settings,
|
770
|
+
project)
|
761
771
|
end
|
762
772
|
|
763
773
|
def convert_plan(plan)
|
@@ -793,6 +803,20 @@ module Bolt
|
|
793
803
|
end
|
794
804
|
|
795
805
|
def bundled_content
|
806
|
+
# If the bundled content directory is empty, Bolt is likely installed as a gem.
|
807
|
+
if ENV['BOLT_GEM'].nil? && incomplete_install?
|
808
|
+
msg = <<~MSG.chomp
|
809
|
+
Bolt may be installed as a gem. To use Bolt reliably and with all of its
|
810
|
+
dependencies, uninstall the 'bolt' gem and install Bolt as a package:
|
811
|
+
https://puppet.com/docs/bolt/latest/bolt_installing.html
|
812
|
+
|
813
|
+
If you meant to install Bolt as a gem and want to disable this warning,
|
814
|
+
set the BOLT_GEM environment variable.
|
815
|
+
MSG
|
816
|
+
|
817
|
+
@logger.warn(msg)
|
818
|
+
end
|
819
|
+
|
796
820
|
# We only need to enumerate bundled content when running a task or plan
|
797
821
|
content = { 'Plan' => [],
|
798
822
|
'Task' => [],
|
@@ -816,5 +840,11 @@ module Bolt
|
|
816
840
|
MSG
|
817
841
|
@logger.debug(msg)
|
818
842
|
end
|
843
|
+
|
844
|
+
# Gem installs include the aggregate, canary, and puppetdb_fact modules, while
|
845
|
+
# package installs include modules listed in the Bolt repo Puppetfile
|
846
|
+
def incomplete_install?
|
847
|
+
(Dir.children(Bolt::PAL::MODULES_PATH) - %w[aggregate canary puppetdb_fact]).empty?
|
848
|
+
end
|
819
849
|
end
|
820
850
|
end
|