bolt 2.34.0 → 2.40.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bolt might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Puppetfile +1 -1
- data/bolt-modules/boltlib/lib/puppet/datatypes/applyresult.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/catch_errors.rb +1 -3
- data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +17 -6
- data/bolt-modules/boltlib/lib/puppet/functions/parallelize.rb +56 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +24 -6
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +27 -8
- data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +21 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +18 -1
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +24 -6
- data/lib/bolt/analytics.rb +27 -8
- data/lib/bolt/apply_result.rb +3 -3
- data/lib/bolt/bolt_option_parser.rb +45 -18
- data/lib/bolt/cli.rb +98 -116
- data/lib/bolt/config.rb +184 -80
- data/lib/bolt/config/options.rb +148 -87
- data/lib/bolt/config/transport/base.rb +10 -19
- data/lib/bolt/config/transport/local.rb +1 -7
- data/lib/bolt/config/transport/options.rb +12 -69
- data/lib/bolt/config/transport/ssh.rb +8 -19
- data/lib/bolt/error.rb +24 -0
- data/lib/bolt/executor.rb +92 -18
- data/lib/bolt/inventory.rb +25 -0
- data/lib/bolt/inventory/group.rb +0 -8
- data/lib/bolt/inventory/options.rb +130 -0
- data/lib/bolt/inventory/target.rb +10 -11
- data/lib/bolt/module_installer.rb +21 -13
- data/lib/bolt/module_installer/resolver.rb +1 -1
- data/lib/bolt/outputter.rb +19 -5
- data/lib/bolt/outputter/human.rb +22 -3
- data/lib/bolt/outputter/json.rb +1 -1
- data/lib/bolt/outputter/logger.rb +1 -1
- data/lib/bolt/outputter/rainbow.rb +13 -2
- data/lib/bolt/pal.rb +18 -6
- data/lib/bolt/pal/yaml_plan.rb +7 -0
- data/lib/bolt/plugin.rb +41 -12
- data/lib/bolt/plugin/cache.rb +76 -0
- data/lib/bolt/plugin/module.rb +4 -4
- data/lib/bolt/plugin/puppetdb.rb +1 -1
- data/lib/bolt/project.rb +59 -40
- data/lib/bolt/project_manager.rb +201 -0
- data/lib/bolt/{project_migrator/config.rb → project_manager/config_migrator.rb} +49 -4
- data/lib/bolt/{project_migrator/inventory.rb → project_manager/inventory_migrator.rb} +3 -3
- data/lib/bolt/{project_migrator/base.rb → project_manager/migrator.rb} +2 -2
- data/lib/bolt/{project_migrator/modules.rb → project_manager/module_migrator.rb} +5 -3
- data/lib/bolt/puppetdb/client.rb +11 -2
- data/lib/bolt/puppetdb/config.rb +4 -3
- data/lib/bolt/rerun.rb +1 -5
- data/lib/bolt/shell/bash.rb +8 -2
- data/lib/bolt/shell/powershell.rb +21 -3
- data/lib/bolt/target.rb +4 -0
- data/lib/bolt/task/run.rb +1 -1
- data/lib/bolt/transport/local.rb +13 -0
- data/lib/bolt/transport/orch.rb +0 -5
- data/lib/bolt/transport/orch/connection.rb +10 -3
- data/lib/bolt/transport/ssh/exec_connection.rb +6 -2
- data/lib/bolt/util.rb +36 -7
- data/lib/bolt/validator.rb +227 -0
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt/yarn.rb +23 -0
- data/lib/bolt_server/base_config.rb +3 -1
- data/lib/bolt_server/config.rb +3 -1
- data/lib/bolt_server/plugin.rb +13 -0
- data/lib/bolt_server/plugin/puppet_connect_data.rb +37 -0
- data/lib/bolt_server/schemas/connect-data.json +22 -0
- data/lib/bolt_server/schemas/partials/task.json +2 -2
- data/lib/bolt_server/transport_app.rb +82 -23
- data/lib/bolt_spec/plans/mock_executor.rb +4 -1
- data/libexec/apply_catalog.rb +1 -1
- data/libexec/custom_facts.rb +1 -1
- data/libexec/query_resources.rb +1 -1
- metadata +22 -14
- data/lib/bolt/project_migrator.rb +0 -80
data/lib/bolt/pal.rb
CHANGED
@@ -26,7 +26,7 @@ module Bolt
|
|
26
26
|
details[:line] = err.line if defined?(err.line)
|
27
27
|
details[:column] = err.pos if defined?(err.pos)
|
28
28
|
|
29
|
-
error.add_filelineno(details)
|
29
|
+
error.add_filelineno(details.compact)
|
30
30
|
error
|
31
31
|
end
|
32
32
|
|
@@ -286,15 +286,26 @@ module Bolt
|
|
286
286
|
raise Bolt::PAL::PALError, "Failed to parse manifest: #{e}"
|
287
287
|
end
|
288
288
|
|
289
|
-
|
289
|
+
# Filters content by a list of names and glob patterns specified in project
|
290
|
+
# configuration.
|
291
|
+
def filter_content(content, patterns)
|
292
|
+
return content unless content && patterns
|
293
|
+
|
294
|
+
content.select do |name,|
|
295
|
+
patterns.any? { |pattern| File.fnmatch?(pattern, name, File::FNM_EXTGLOB) }
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
def list_tasks(filter_content: false)
|
290
300
|
in_bolt_compiler do |compiler|
|
291
|
-
tasks = compiler.list_tasks
|
292
|
-
tasks.map(&:name).sort.each_with_object([]) do |task_name, data|
|
301
|
+
tasks = compiler.list_tasks.map(&:name).sort.each_with_object([]) do |task_name, data|
|
293
302
|
task_sig = compiler.task_signature(task_name)
|
294
303
|
unless task_sig.task_hash['metadata']['private']
|
295
304
|
data << [task_name, task_sig.task_hash['metadata']['description']]
|
296
305
|
end
|
297
306
|
end
|
307
|
+
|
308
|
+
filter_content ? filter_content(tasks, @project&.tasks) : tasks
|
298
309
|
end
|
299
310
|
end
|
300
311
|
|
@@ -346,14 +357,15 @@ module Bolt
|
|
346
357
|
Bolt::Task.from_task_signature(task)
|
347
358
|
end
|
348
359
|
|
349
|
-
def list_plans
|
360
|
+
def list_plans(filter_content: false)
|
350
361
|
in_bolt_compiler do |compiler|
|
351
362
|
errors = []
|
352
363
|
plans = compiler.list_plans(nil, errors).map { |plan| [plan.name] }.sort
|
353
364
|
errors.each do |error|
|
354
365
|
@logger.warn(error.details['original_error'])
|
355
366
|
end
|
356
|
-
|
367
|
+
|
368
|
+
filter_content ? filter_content(plans, @project&.plans) : plans
|
357
369
|
end
|
358
370
|
end
|
359
371
|
|
data/lib/bolt/pal/yaml_plan.rb
CHANGED
@@ -45,6 +45,13 @@ module Bolt
|
|
45
45
|
used_names = Set.new(@parameters.map(&:name))
|
46
46
|
|
47
47
|
@steps = plan['steps'].each_with_index.map do |step, index|
|
48
|
+
unless step.is_a?(Hash)
|
49
|
+
raise Bolt::Error.new(
|
50
|
+
"Parse error in step number #{index + 1}: Plan step must be an object with valid step keys.",
|
51
|
+
'bolt/invalid-plan'
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
48
55
|
# Step keys also aren't allowed to be code and neither is the value of "name"
|
49
56
|
stringified_step = Bolt::Util.walk_keys(step) { |key| stringify(key) }
|
50
57
|
stringified_step['name'] = stringify(stringified_step['name']) if stringified_step.key?('name')
|
data/lib/bolt/plugin.rb
CHANGED
@@ -4,6 +4,7 @@ require 'bolt/inventory'
|
|
4
4
|
require 'bolt/executor'
|
5
5
|
require 'bolt/module'
|
6
6
|
require 'bolt/pal'
|
7
|
+
require 'bolt/plugin/cache'
|
7
8
|
require 'bolt/plugin/puppetdb'
|
8
9
|
|
9
10
|
module Bolt
|
@@ -36,6 +37,13 @@ module Bolt
|
|
36
37
|
super("Plugin #{plugin_name} does not support #{hook}", 'bolt/unsupported-hook')
|
37
38
|
end
|
38
39
|
end
|
40
|
+
|
41
|
+
class LoadingDisabled < PluginError
|
42
|
+
def initialize(plugin_name)
|
43
|
+
msg = "Cannot load plugin #{plugin_name}: plugin loading is disabled"
|
44
|
+
super(msg, 'bolt/plugin-loading-disabled', { 'plugin_name' => plugin_name })
|
45
|
+
end
|
46
|
+
end
|
39
47
|
end
|
40
48
|
|
41
49
|
class PluginContext
|
@@ -119,15 +127,8 @@ module Bolt
|
|
119
127
|
end
|
120
128
|
end
|
121
129
|
|
122
|
-
def self.setup(config, pal, analytics = Bolt::Analytics::NoopClient.new)
|
123
|
-
plugins = new(config, pal, analytics)
|
124
|
-
|
125
|
-
# Initialize any plugins referenced in plugin config. This will also indirectly
|
126
|
-
# initialize any plugins they depend on.
|
127
|
-
if plugins.reference?(config.plugins)
|
128
|
-
msg = "The 'plugins' setting cannot be set by a plugin reference"
|
129
|
-
raise PluginError.new(msg, 'bolt/plugin-error')
|
130
|
-
end
|
130
|
+
def self.setup(config, pal, analytics = Bolt::Analytics::NoopClient.new, **opts)
|
131
|
+
plugins = new(config, pal, analytics, **opts)
|
131
132
|
|
132
133
|
config.plugins.each_key do |plugin|
|
133
134
|
plugins.by_name(plugin)
|
@@ -148,12 +149,13 @@ module Bolt
|
|
148
149
|
|
149
150
|
private_class_method :new
|
150
151
|
|
151
|
-
def initialize(config, pal, analytics)
|
152
|
+
def initialize(config, pal, analytics, load_plugins: true)
|
152
153
|
@config = config
|
153
154
|
@analytics = analytics
|
154
155
|
@plugin_context = PluginContext.new(config, pal, self)
|
155
156
|
@plugins = {}
|
156
157
|
@pal = pal
|
158
|
+
@load_plugins = load_plugins
|
157
159
|
@unknown = Set.new
|
158
160
|
@resolution_stack = []
|
159
161
|
@unresolved_plugin_configs = config.plugins.dup
|
@@ -176,6 +178,8 @@ module Bolt
|
|
176
178
|
end
|
177
179
|
|
178
180
|
def add_ruby_plugin(plugin_name)
|
181
|
+
raise PluginError::LoadingDisabled, plugin_name unless @load_plugins
|
182
|
+
|
179
183
|
cls_name = Bolt::Util.snake_name_to_class_name(plugin_name)
|
180
184
|
filename = "bolt/plugin/#{plugin_name}"
|
181
185
|
require filename
|
@@ -192,10 +196,17 @@ module Bolt
|
|
192
196
|
def add_module_plugin(plugin_name)
|
193
197
|
opts = {
|
194
198
|
context: @plugin_context,
|
199
|
+
# Make sure that the plugin's config is validated _before_ the unknown-plugin
|
200
|
+
# and loading-disabled checks. This way, we can fail early on invalid plugin
|
201
|
+
# config instead of _after_ loading the modulepath (which can be expensive).
|
195
202
|
config: config_for_plugin(plugin_name)
|
196
203
|
}
|
197
204
|
|
198
|
-
|
205
|
+
mod = modules[plugin_name]
|
206
|
+
raise PluginError::Unknown, plugin_name unless mod&.plugin?
|
207
|
+
raise PluginError::LoadingDisabled, plugin_name unless @load_plugins
|
208
|
+
|
209
|
+
plugin = Bolt::Plugin::Module.load(mod, opts)
|
199
210
|
add_plugin(plugin)
|
200
211
|
end
|
201
212
|
|
@@ -284,6 +295,16 @@ module Bolt
|
|
284
295
|
# Evaluates a single reference. The value returned may be another
|
285
296
|
# reference.
|
286
297
|
def resolve_single_reference(reference)
|
298
|
+
plugin_cache = if cache?(reference)
|
299
|
+
cache = Bolt::Plugin::Cache.new(reference,
|
300
|
+
@config.project.cache_file,
|
301
|
+
@config.plugin_cache)
|
302
|
+
entry = cache.read_and_clean_cache
|
303
|
+
return entry unless entry.nil?
|
304
|
+
|
305
|
+
cache
|
306
|
+
end
|
307
|
+
|
287
308
|
plugin_name = reference['_plugin']
|
288
309
|
hook = get_hook(plugin_name, :resolve_reference)
|
289
310
|
|
@@ -295,16 +316,24 @@ module Bolt
|
|
295
316
|
|
296
317
|
validate_proc.call(reference)
|
297
318
|
|
298
|
-
begin
|
319
|
+
result = begin
|
299
320
|
# Evaluate the plugin and then recursively evaluate any plugin returned by it.
|
300
321
|
hook.call(reference)
|
301
322
|
rescue StandardError => e
|
302
323
|
loc = "resolve_reference in #{plugin_name}"
|
303
324
|
raise PluginError::ExecutionError.new(e.message, plugin_name, loc)
|
304
325
|
end
|
326
|
+
|
327
|
+
plugin_cache.write_cache(result) if cache?(reference)
|
328
|
+
|
329
|
+
result
|
305
330
|
end
|
306
331
|
private :resolve_single_reference
|
307
332
|
|
333
|
+
private def cache?(reference)
|
334
|
+
reference.key?('_cache') || @config.plugin_cache.key?('ttl')
|
335
|
+
end
|
336
|
+
|
308
337
|
# Checks whether a given value is a _plugin reference
|
309
338
|
def reference?(input)
|
310
339
|
input.is_a?(Hash) && input.key?('_plugin')
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'bolt/error'
|
5
|
+
require 'bolt/util'
|
6
|
+
|
7
|
+
module Bolt
|
8
|
+
class Plugin
|
9
|
+
class Cache
|
10
|
+
attr_reader :reference, :cache_file, :default_config, :id
|
11
|
+
|
12
|
+
def initialize(reference, cache_file, default_config)
|
13
|
+
@reference = reference
|
14
|
+
@cache_file = cache_file
|
15
|
+
@default_config = default_config
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_and_clean_cache
|
19
|
+
return if ttl == 0
|
20
|
+
validate
|
21
|
+
|
22
|
+
# Luckily we don't need to use a serious hash algorithm
|
23
|
+
require 'digest/bubblebabble'
|
24
|
+
r = reference.reject { |k, _| k == '_cache' }.sort.to_s
|
25
|
+
@id = Digest::SHA2.bubblebabble(r)[0..20]
|
26
|
+
|
27
|
+
unmodified = true
|
28
|
+
# First remove any cache entries past their ttl
|
29
|
+
# This prevents removing plugins from leaving orphaned cache entries
|
30
|
+
cache.delete_if do |_, entry|
|
31
|
+
expired = Time.now - Time.parse(entry['mtime']) >= entry['ttl']
|
32
|
+
unmodified = false if expired
|
33
|
+
expired
|
34
|
+
end
|
35
|
+
File.write(cache_file, cache.to_json) unless cache.empty? || unmodified
|
36
|
+
|
37
|
+
cache.dig(id, 'result')
|
38
|
+
end
|
39
|
+
|
40
|
+
private def cache
|
41
|
+
@cache ||= Bolt::Util.read_optional_json_file(@cache_file, 'cache')
|
42
|
+
end
|
43
|
+
|
44
|
+
def write_cache(result)
|
45
|
+
cache.merge!({ id => { 'result' => result,
|
46
|
+
'mtime' => Time.now,
|
47
|
+
'ttl' => ttl } })
|
48
|
+
FileUtils.touch(cache_file)
|
49
|
+
File.write(cache_file, cache.to_json)
|
50
|
+
end
|
51
|
+
|
52
|
+
def validate
|
53
|
+
# The default cache `plugin-cache` will be validated by the config
|
54
|
+
# validator
|
55
|
+
return if reference['_cache'].nil?
|
56
|
+
r = reference['_cache']
|
57
|
+
unless r.is_a?(Hash)
|
58
|
+
raise Bolt::ValidationError,
|
59
|
+
"_cache must be a Hash, received #{r.class}: #{r.inspect}"
|
60
|
+
end
|
61
|
+
|
62
|
+
unless r.key?('ttl')
|
63
|
+
raise Bolt::ValidationError, "_cache must set 'ttl' key."
|
64
|
+
end
|
65
|
+
|
66
|
+
unless r['ttl'] >= 0
|
67
|
+
raise Bolt::ValidationError, "'ttl' key under '_cache' must be a minimum of 0."
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private def ttl
|
72
|
+
@ttl ||= reference.dig('_cache', 'ttl') || default_config['ttl']
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/bolt/plugin/module.rb
CHANGED
@@ -12,15 +12,15 @@ module Bolt
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
if mod
|
15
|
+
# mod should not be nil
|
16
|
+
def self.load(mod, opts)
|
17
|
+
if mod.plugin?
|
18
18
|
opts[:mod] = mod
|
19
19
|
plugin = Bolt::Plugin::Module.new(**opts)
|
20
20
|
plugin.setup
|
21
21
|
plugin
|
22
22
|
else
|
23
|
-
raise PluginError::Unknown, name
|
23
|
+
raise PluginError::Unknown, mod.name
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
data/lib/bolt/plugin/puppetdb.rb
CHANGED
data/lib/bolt/project.rb
CHANGED
@@ -2,24 +2,19 @@
|
|
2
2
|
|
3
3
|
require 'pathname'
|
4
4
|
require 'bolt/config'
|
5
|
+
require 'bolt/validator'
|
5
6
|
require 'bolt/pal'
|
6
7
|
require 'bolt/module'
|
7
8
|
|
8
9
|
module Bolt
|
9
10
|
class Project
|
10
11
|
BOLTDIR_NAME = 'Boltdir'
|
11
|
-
|
12
|
-
"name" => "The name of the project",
|
13
|
-
"plans" => "An array of plan names to show, if they exist in the project."\
|
14
|
-
"These plans are included in `bolt plan show` and `Get-BoltPlan` output",
|
15
|
-
"tasks" => "An array of task names to show, if they exist in the project."\
|
16
|
-
"These tasks are included in `bolt task show` and `Get-BoltTask` output"
|
17
|
-
}.freeze
|
12
|
+
CONFIG_NAME = 'bolt-project.yaml'
|
18
13
|
|
19
14
|
attr_reader :path, :data, :config_file, :inventory_file, :hiera_config,
|
20
15
|
:puppetfile, :rerunfile, :type, :resource_types, :logs, :project_file,
|
21
16
|
:deprecations, :downloads, :plans_path, :modulepath, :managed_moduledir,
|
22
|
-
:backup_dir
|
17
|
+
:backup_dir, :cache_file
|
23
18
|
|
24
19
|
def self.default_project(logs = [])
|
25
20
|
create_project(File.expand_path(File.join('~', '.puppetlabs', 'bolt')), 'user', logs)
|
@@ -32,23 +27,31 @@ module Bolt
|
|
32
27
|
# directory called Boltdir or a file called bolt.yaml (for a control repo
|
33
28
|
# type Project). Otherwise, repeat the check on each directory up the
|
34
29
|
# hierarchy, falling back to the default if we reach the root.
|
35
|
-
def self.find_boltdir(dir, logs = [])
|
30
|
+
def self.find_boltdir(dir, logs = [], deprecations = [])
|
36
31
|
dir = Pathname.new(dir)
|
37
32
|
|
38
33
|
if (dir + BOLTDIR_NAME).directory?
|
39
34
|
create_project(dir + BOLTDIR_NAME, 'embedded', logs)
|
40
|
-
elsif (dir + 'bolt.yaml').file?
|
35
|
+
elsif (dir + 'bolt.yaml').file?
|
36
|
+
command = Bolt::Util.powershell? ? 'Update-BoltProject' : 'bolt project migrate'
|
37
|
+
msg = "Configuration file #{dir + 'bolt.yaml'} is deprecated and will be "\
|
38
|
+
"removed in Bolt 3.0.\nUpdate your Bolt project to the latest Bolt practices "\
|
39
|
+
"using #{command}"
|
40
|
+
deprecations << { type: "Project level bolt.yaml",
|
41
|
+
msg: msg }
|
42
|
+
create_project(dir, 'local', logs, deprecations)
|
43
|
+
elsif (dir + CONFIG_NAME).file?
|
41
44
|
create_project(dir, 'local', logs)
|
42
45
|
elsif dir.root?
|
43
46
|
default_project(logs)
|
44
47
|
else
|
45
48
|
logs << { debug: "Did not detect Boltdir, bolt.yaml, or bolt-project.yaml at '#{dir}'. "\
|
46
49
|
"This directory won't be loaded as a project." }
|
47
|
-
find_boltdir(dir.parent, logs)
|
50
|
+
find_boltdir(dir.parent, logs, deprecations)
|
48
51
|
end
|
49
52
|
end
|
50
53
|
|
51
|
-
def self.create_project(path, type = 'option', logs = [])
|
54
|
+
def self.create_project(path, type = 'option', logs = [], deprecations = [])
|
52
55
|
fullpath = Pathname.new(path).expand_path
|
53
56
|
|
54
57
|
if type == 'user'
|
@@ -73,21 +76,42 @@ module Bolt
|
|
73
76
|
)
|
74
77
|
end
|
75
78
|
|
76
|
-
project_file = File.join(fullpath,
|
77
|
-
data
|
78
|
-
default
|
79
|
-
exist
|
79
|
+
project_file = File.join(fullpath, CONFIG_NAME)
|
80
|
+
data = Bolt::Util.read_optional_yaml_hash(File.expand_path(project_file), 'project')
|
81
|
+
default = type =~ /user|system/ ? 'default ' : ''
|
82
|
+
exist = File.exist?(File.expand_path(project_file))
|
83
|
+
|
80
84
|
logs << { info: "Loaded #{default}project from '#{fullpath}'" } if exist
|
81
|
-
|
85
|
+
|
86
|
+
Bolt::Validator.new.tap do |validator|
|
87
|
+
validator.validate(data, schema, project_file)
|
88
|
+
|
89
|
+
validator.warnings.each { |warning| logs << { warn: warning } }
|
90
|
+
|
91
|
+
validator.deprecations.each do |dep|
|
92
|
+
deprecations << { type: "#{CONFIG_NAME} #{dep[:option]}", msg: dep[:message] }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
new(data, path, type, logs, deprecations)
|
82
97
|
end
|
83
98
|
|
84
|
-
|
85
|
-
|
99
|
+
# Builds the schema for bolt-project.yaml used by the validator.
|
100
|
+
#
|
101
|
+
def self.schema
|
102
|
+
{
|
103
|
+
type: Hash,
|
104
|
+
properties: Bolt::Config::BOLT_PROJECT_OPTIONS.map { |opt| [opt, _ref: opt] }.to_h,
|
105
|
+
definitions: Bolt::Config::OPTIONS
|
106
|
+
}
|
107
|
+
end
|
86
108
|
|
87
|
-
|
109
|
+
def initialize(raw_data, path, type = 'option', logs = [], deprecations = [])
|
110
|
+
@path = Pathname.new(path).expand_path
|
111
|
+
@project_file = @path + CONFIG_NAME
|
112
|
+
@logs = logs
|
113
|
+
@deprecations = deprecations
|
88
114
|
|
89
|
-
@logs = logs
|
90
|
-
@deprecations = []
|
91
115
|
if (@path + 'bolt.yaml').file? && project_file?
|
92
116
|
msg = "Project-level configuration in bolt.yaml is deprecated if using bolt-project.yaml. "\
|
93
117
|
"Transport config should be set in inventory.yaml, all other config should be set in "\
|
@@ -105,6 +129,7 @@ module Bolt
|
|
105
129
|
@plans_path = @path + 'plans'
|
106
130
|
@managed_moduledir = @path + '.modules'
|
107
131
|
@backup_dir = @path + '.bolt-bak'
|
132
|
+
@cache_file = @path + '.plugin_cache.json'
|
108
133
|
|
109
134
|
tc = Bolt::Config::INVENTORY_OPTIONS.keys & raw_data.keys
|
110
135
|
if tc.any?
|
@@ -173,6 +198,14 @@ module Bolt
|
|
173
198
|
@data['plans']
|
174
199
|
end
|
175
200
|
|
201
|
+
def plugin_cache
|
202
|
+
@data['plugin-cache']
|
203
|
+
end
|
204
|
+
|
205
|
+
def module_install
|
206
|
+
@data['module-install']
|
207
|
+
end
|
208
|
+
|
176
209
|
def modules
|
177
210
|
@modules ||= @data['modules']&.map do |mod|
|
178
211
|
if mod.is_a?(String)
|
@@ -194,27 +227,13 @@ module Bolt
|
|
194
227
|
raise Bolt::ValidationError, "The project '#{name}' will not be loaded. The project name conflicts "\
|
195
228
|
"with a built-in Bolt module of the same name."
|
196
229
|
end
|
197
|
-
|
230
|
+
elsif name.nil? &&
|
231
|
+
(File.directory?(plans_path) ||
|
232
|
+
File.directory?(@path + 'tasks') ||
|
233
|
+
File.directory?(@path + 'files'))
|
198
234
|
message = "No project name is specified in bolt-project.yaml. Project-level content will not be available."
|
199
235
|
@logs << { warn: message }
|
200
236
|
end
|
201
|
-
|
202
|
-
%w[tasks plans].each do |conf|
|
203
|
-
unless @data.fetch(conf, []).is_a?(Array)
|
204
|
-
raise Bolt::ValidationError, "'#{conf}' in bolt-project.yaml must be an array"
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
if @data['modules']
|
209
|
-
unless @data['modules'].is_a?(Array)
|
210
|
-
raise Bolt::ValidationError, "'modules' in bolt-project.yaml must be an array"
|
211
|
-
end
|
212
|
-
|
213
|
-
@data['modules'].each do |spec|
|
214
|
-
next if spec.is_a?(Hash) || spec.is_a?(String)
|
215
|
-
raise Bolt::ValidationError, "Module specification #{spec.inspect} must be a hash or string"
|
216
|
-
end
|
217
|
-
end
|
218
237
|
end
|
219
238
|
|
220
239
|
def check_deprecated_file
|