bolt 2.7.0 → 2.8.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 +2 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +192 -0
- data/lib/bolt/applicator.rb +0 -1
- data/lib/bolt/apply_inventory.rb +1 -1
- data/lib/bolt/apply_target.rb +8 -0
- data/lib/bolt/bolt_option_parser.rb +9 -2
- data/lib/bolt/cli.rb +29 -18
- data/lib/bolt/config.rb +23 -23
- data/lib/bolt/config/transport/base.rb +3 -3
- data/lib/bolt/config/transport/orch.rb +2 -2
- data/lib/bolt/config/transport/ssh.rb +1 -1
- data/lib/bolt/config/transport/winrm.rb +1 -1
- data/lib/bolt/executor.rb +16 -0
- data/lib/bolt/pal.rb +30 -13
- data/lib/bolt/plugin.rb +2 -2
- data/lib/bolt/plugin/module.rb +40 -7
- data/lib/bolt/project.rb +128 -0
- data/lib/bolt/puppetdb/config.rb +6 -6
- data/lib/bolt/secret.rb +20 -4
- data/lib/bolt/shell/bash.rb +11 -4
- data/lib/bolt/target.rb +4 -0
- data/lib/bolt/transport/base.rb +24 -8
- data/lib/bolt/transport/orch.rb +4 -0
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_spec/bolt_context.rb +2 -2
- data/lib/bolt_spec/plans.rb +1 -1
- data/lib/bolt_spec/run.rb +8 -8
- metadata +6 -7
- data/lib/bolt/boltdir.rb +0 -54
- data/lib/bolt/plugin/pkcs7.rb +0 -104
- data/lib/bolt/secret/base.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bdb245ba4347b6309414b645bea7e8829651886d3f85152217801ce7463fdfb6
|
4
|
+
data.tar.gz: 4e93d16cbb9d5cd0314f1c12031cd1e7d1ca9eb0c40186119f15a902aa0732d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5264e15f6e29f8d2e8cd9b02f67161e110215c20161c9e5ef22cf85294597eb262c40f0e13491dcb83c683b5c11930bc26fa1f8e5b80bee5ce485c60567fa8f5
|
7
|
+
data.tar.gz: 3b6053135ba279dc70b41cfa13dcd7c5b00a70fa8dd2ed3370bcdd8b1e9c33b33ec2ea817bc6fc5c7afb6114a5abe1c93ea328e432c5b1748c22af04daad5a6f
|
data/Puppetfile
CHANGED
@@ -32,7 +32,8 @@ mod 'puppetlabs-ruby_plugin_helper', '0.1.0'
|
|
32
32
|
# Plugin modules
|
33
33
|
mod 'puppetlabs-aws_inventory', '0.5.0'
|
34
34
|
mod 'puppetlabs-azure_inventory', '0.3.0'
|
35
|
-
mod 'puppetlabs-gcloud_inventory', '0.1.
|
35
|
+
mod 'puppetlabs-gcloud_inventory', '0.1.1'
|
36
|
+
mod 'puppetlabs-pkcs7', '0.1.0'
|
36
37
|
mod 'puppetlabs-terraform', '0.5.0'
|
37
38
|
mod 'puppetlabs-vault', '0.3.0'
|
38
39
|
mod 'puppetlabs-yaml', '0.2.0'
|
@@ -0,0 +1,192 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
require 'bolt/pal'
|
5
|
+
require 'bolt/task'
|
6
|
+
|
7
|
+
# Runs a given instance of a `Task` with target-specific parameters on the given set of targets and
|
8
|
+
# returns the result from each. This function differs from {run_task} by accepting a block that returns
|
9
|
+
# a `Hash` of target-specific parameters that are passed to the task. This can be used to send parameters
|
10
|
+
# based on a target's attributes, such as its `facts`, or to use conditional logic to determine the
|
11
|
+
# parameters a task should receive for a specific target.
|
12
|
+
#
|
13
|
+
# This function does nothing if the list of targets is empty.
|
14
|
+
#
|
15
|
+
# > **Note:** Not available in apply block
|
16
|
+
#
|
17
|
+
# > **Note:** Not available to targets using the pcp transport
|
18
|
+
Puppet::Functions.create_function(:run_task_with) do
|
19
|
+
# Run a task with target-specific parameters.
|
20
|
+
# @param task_name The task to run.
|
21
|
+
# @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
|
22
|
+
# @param options A hash of additional options.
|
23
|
+
# @option options [Boolean] _catch_errors Whether to catch raised errors.
|
24
|
+
# @option options [Boolean] _noop Run the task in noop mode if available.
|
25
|
+
# @option options [String] _run_as User to run as using privilege escalation.
|
26
|
+
# @param block A block that returns a `Hash` of target-specific parameters for the task.
|
27
|
+
# @return A list of results, one entry per target.
|
28
|
+
# @example Run a task with target-specific parameters as root
|
29
|
+
# run_task_with('my_task', $targets, '_run_as' => 'root') |$t| {
|
30
|
+
# { 'param1' => $t.vars['var1'],
|
31
|
+
# 'param2' => $t.vars['var2'] }
|
32
|
+
# }
|
33
|
+
dispatch :run_task_with do
|
34
|
+
param 'String[1]', :task_name
|
35
|
+
param 'Boltlib::TargetSpec', :targets
|
36
|
+
optional_param 'Hash[String[1], Any]', :options
|
37
|
+
required_block_param 'Callable[Target]', :block
|
38
|
+
return_type 'ResultSet'
|
39
|
+
end
|
40
|
+
|
41
|
+
# Run a task with target-specific parameters, logging the provided description.
|
42
|
+
# @param task_name The task to run.
|
43
|
+
# @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
|
44
|
+
# @param description A description to be output when calling this function.
|
45
|
+
# @param options A hash of additional options.
|
46
|
+
# @option options [Boolean] _catch_errors Whether to catch raised errors.
|
47
|
+
# @option options [Boolean] _noop Run the task in noop mode if available.
|
48
|
+
# @option options [String] _run_as User to run as using privilege escalation.
|
49
|
+
# @param block A block that returns a `Hash` of target-specific parameters for the task.
|
50
|
+
# @return A list of results, one entry per target.
|
51
|
+
# @example Run a task with target-specific parameters and a description
|
52
|
+
# run_task_with('my_task', $targets, 'Update system packages') |$t| {
|
53
|
+
# { 'param1' => $t.vars['var1'],
|
54
|
+
# 'param2' => $t.vars['var2'] }
|
55
|
+
# }
|
56
|
+
dispatch :run_task_with_with_description do
|
57
|
+
param 'String[1]', :task_name
|
58
|
+
param 'Boltlib::TargetSpec', :targets
|
59
|
+
param 'Optional[String]', :description
|
60
|
+
optional_param 'Hash[String[1], Any]', :options
|
61
|
+
required_block_param 'Callable[Target]', :block
|
62
|
+
return_type 'ResultSet'
|
63
|
+
end
|
64
|
+
|
65
|
+
def run_task_with(task_name, targets, options = {}, &block)
|
66
|
+
run_task_with_with_description(task_name, targets, nil, options, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
def run_task_with_with_description(task_name, targets, description, options = {})
|
70
|
+
unless Puppet[:tasks]
|
71
|
+
raise Puppet::ParseErrorWithIssue
|
72
|
+
.from_issue_and_stack(
|
73
|
+
Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING,
|
74
|
+
action: 'run_task_with'
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
executor = Puppet.lookup(:bolt_executor)
|
79
|
+
inventory = Puppet.lookup(:bolt_inventory)
|
80
|
+
error_set = []
|
81
|
+
|
82
|
+
# Report to analytics
|
83
|
+
executor.report_function_call(self.class.name)
|
84
|
+
executor.report_bundled_content('Task', task_name)
|
85
|
+
|
86
|
+
# Keep valid metaparameters, discarding everything else
|
87
|
+
options = options.select { |k, _v| k.start_with?('_') }
|
88
|
+
.transform_keys { |k| k.sub(/^_/, '').to_sym }
|
89
|
+
|
90
|
+
options[:description] = description if description
|
91
|
+
|
92
|
+
# Get all the targets
|
93
|
+
targets = Array(inventory.get_targets(targets))
|
94
|
+
|
95
|
+
# If all targets use the 'pcp' transport, use a fake task instead of loading the local definition
|
96
|
+
# Otherwise, load the local task definition
|
97
|
+
if (pcp_only = targets.any? && targets.all? { |t| t.transport == 'pcp' })
|
98
|
+
task = Bolt::Task.new(task_name, {}, [{ 'name' => '', 'path' => '' }])
|
99
|
+
else
|
100
|
+
task_signature = Puppet::Pal::ScriptCompiler.new(closure_scope.compiler).task_signature(task_name)
|
101
|
+
|
102
|
+
if task_signature.nil?
|
103
|
+
raise Bolt::Error.unknown_task(task_name)
|
104
|
+
end
|
105
|
+
|
106
|
+
task = Bolt::Task.from_task_signature(task_signature)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Map the targets to their specific parameters and merge with the defaults
|
110
|
+
target_mapping = targets.each_with_object({}) do |target, mapping|
|
111
|
+
params = yield(target)
|
112
|
+
|
113
|
+
# Parameters returned from the block should be a Hash. If they're not, create a failing
|
114
|
+
# Result for the target that will later be added to the ResultSet.
|
115
|
+
unless params.is_a?(Hash)
|
116
|
+
exception = with_stack(
|
117
|
+
:TYPE_MISMATCH,
|
118
|
+
"Block must return a Hash of parameters, received #{params.class}"
|
119
|
+
)
|
120
|
+
error_set << Bolt::Result.from_exception(target, exception, action: 'task')
|
121
|
+
next
|
122
|
+
end
|
123
|
+
|
124
|
+
# If parameters are mismatched, create a failing result for the target that will later
|
125
|
+
# be added to the ResultSet.
|
126
|
+
unless pcp_only
|
127
|
+
params = task.parameter_defaults.merge(params)
|
128
|
+
|
129
|
+
type_match = task_signature.runnable_with?(params) do |mismatch_message|
|
130
|
+
exception = with_stack(:TYPE_MISMATCH, mismatch_message)
|
131
|
+
error_set << Bolt::Result.from_exception(target, exception, action: 'task')
|
132
|
+
end
|
133
|
+
|
134
|
+
next unless type_match
|
135
|
+
end
|
136
|
+
|
137
|
+
# If there is a type mismatch between the type Data and the type of the params, create
|
138
|
+
# a failing result for the target that will later be added to the ResultSet.
|
139
|
+
unless Puppet::Pops::Types::TypeFactory.data.instance?(params)
|
140
|
+
params_t = Puppet::Pops::Types::TypeCalculator.infer_set(params)
|
141
|
+
desc = Puppet::Pops::Types::TypeMismatchDescriber.singleton.describe_mismatch(
|
142
|
+
'Task parameters are not of type Data. run_task_with()',
|
143
|
+
Puppet::Pops::Types::TypeFactory.data, params_t
|
144
|
+
)
|
145
|
+
exception = with_stack(:TYPE_NOT_DATA, desc)
|
146
|
+
error_set << Bolt::Result.from_exception(target, exception, action: 'task')
|
147
|
+
next
|
148
|
+
end
|
149
|
+
|
150
|
+
# Wrap parameters marked with '"sensitive": true' in the task metadata with a
|
151
|
+
# Sensitive wrapper type. This way it's not shown in logs.
|
152
|
+
if (param_spec = task.parameters)
|
153
|
+
params.each do |k, v|
|
154
|
+
if param_spec[k] && param_spec[k]['sensitive']
|
155
|
+
params[k] = Puppet::Pops::Types::PSensitiveType::Sensitive.new(v)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
mapping[target] = task.parameter_defaults.merge(params)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Add a noop parameter if the function was called with the noop metaparameter.
|
164
|
+
if options[:noop]
|
165
|
+
if task.supports_noop
|
166
|
+
target_mapping.each_value { |params| params['_noop'] = true }
|
167
|
+
else
|
168
|
+
raise with_stack(:TASK_NO_NOOP, 'Task does not support noop')
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
if targets.empty?
|
173
|
+
Bolt::ResultSet.new([])
|
174
|
+
else
|
175
|
+
# Combine the results from the task run with any failing results that were
|
176
|
+
# generated earlier when creating the target mapping
|
177
|
+
task_result = executor.run_task_with(target_mapping, task, options)
|
178
|
+
result = Bolt::ResultSet.new(task_result.results + error_set)
|
179
|
+
|
180
|
+
if !result.ok && !options[:catch_errors]
|
181
|
+
raise Bolt::RunFailure.new(result, 'run_task', task_name)
|
182
|
+
end
|
183
|
+
|
184
|
+
result
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def with_stack(kind, msg)
|
189
|
+
issue = Puppet::Pops::Issues.issue(kind) { msg }
|
190
|
+
Puppet::ParseErrorWithIssue.from_issue_and_stack(issue)
|
191
|
+
end
|
192
|
+
end
|
data/lib/bolt/applicator.rb
CHANGED
data/lib/bolt/apply_inventory.rb
CHANGED
data/lib/bolt/apply_target.rb
CHANGED
@@ -57,6 +57,10 @@ module Bolt
|
|
57
57
|
@user = Addressable::URI.unencode_component(uri_obj.user) || t_conf['user']
|
58
58
|
end
|
59
59
|
|
60
|
+
def to_s
|
61
|
+
@safe_name
|
62
|
+
end
|
63
|
+
|
60
64
|
def parse_uri(string)
|
61
65
|
require 'addressable/uri'
|
62
66
|
if string.nil?
|
@@ -73,5 +77,9 @@ module Bolt
|
|
73
77
|
rescue Addressable::URI::InvalidURIError => e
|
74
78
|
raise Bolt::ParseError, "Could not parse target URI: #{e.message}"
|
75
79
|
end
|
80
|
+
|
81
|
+
def hash
|
82
|
+
@name.hash
|
83
|
+
end
|
76
84
|
end
|
77
85
|
end
|
@@ -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],
|
@@ -716,6 +716,10 @@ module Bolt
|
|
716
716
|
'Directory containing bolt.yaml will be used as the Boltdir.') do |path|
|
717
717
|
@options[:configfile] = path
|
718
718
|
end
|
719
|
+
define('--hiera-config FILEPATH',
|
720
|
+
'Specify where to load Hiera config from (default: ~/.puppetlabs/bolt/hiera.yaml)') do |path|
|
721
|
+
@options[:'hiera-config'] = path
|
722
|
+
end
|
719
723
|
define('-i', '--inventoryfile FILEPATH',
|
720
724
|
'Specify where to load inventory from (default: ~/.puppetlabs/bolt/inventory.yaml)') do |path|
|
721
725
|
if ENV.include?(Bolt::Inventory::ENVIRONMENT_VAR)
|
@@ -775,6 +779,9 @@ module Bolt
|
|
775
779
|
'when initializing a project. Resolves and installs all dependencies.') do |modules|
|
776
780
|
@options[:modules] = modules.split(',')
|
777
781
|
end
|
782
|
+
define('--force', 'Overwrite existing key pairs') do |_force|
|
783
|
+
@options[:force] = true
|
784
|
+
end
|
778
785
|
|
779
786
|
separator "\nGLOBAL OPTIONS"
|
780
787
|
define('-h', '--help', 'Display help') do |_|
|
data/lib/bolt/cli.rb
CHANGED
@@ -114,12 +114,12 @@ 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)
|
@@ -238,6 +238,12 @@ module Bolt
|
|
238
238
|
if options[:subcommand] == 'command' && (!options[:object] || options[:object].empty?)
|
239
239
|
raise Bolt::CLIError, "Must specify a command to run"
|
240
240
|
end
|
241
|
+
|
242
|
+
if options[:subcommand] == 'secret' &&
|
243
|
+
(options[:action] == 'decrypt' || options[:action] == 'encrypt') &&
|
244
|
+
!options[:object]
|
245
|
+
raise Bolt::CLIError, "Must specify a value to #{options[:action]}"
|
246
|
+
end
|
241
247
|
end
|
242
248
|
|
243
249
|
def handle_parser_errors
|
@@ -252,7 +258,7 @@ module Bolt
|
|
252
258
|
|
253
259
|
def puppetdb_client
|
254
260
|
return @puppetdb_client if @puppetdb_client
|
255
|
-
puppetdb_config = Bolt::PuppetDB::Config.load_config(nil, config.puppetdb, config.
|
261
|
+
puppetdb_config = Bolt::PuppetDB::Config.load_config(nil, config.puppetdb, config.project.path)
|
256
262
|
@puppetdb_client = Bolt::PuppetDB::Client.new(puppetdb_config)
|
257
263
|
end
|
258
264
|
|
@@ -314,7 +320,8 @@ module Bolt
|
|
314
320
|
|
315
321
|
screen_view_fields = {
|
316
322
|
output_format: config.format,
|
317
|
-
|
323
|
+
# For continuity
|
324
|
+
boltdir_type: config.project.type
|
318
325
|
}
|
319
326
|
|
320
327
|
# Only include target and inventory info for commands that take a targets
|
@@ -447,6 +454,7 @@ module Bolt
|
|
447
454
|
def list_tasks
|
448
455
|
tasks = pal.list_tasks
|
449
456
|
tasks.select! { |task| task.first.include?(options[:filter]) } if options[:filter]
|
457
|
+
tasks.select! { |task| config.project.tasks.include?(task.first) } unless config.project.tasks.nil?
|
450
458
|
outputter.print_tasks(tasks, pal.list_modulepath)
|
451
459
|
end
|
452
460
|
|
@@ -457,6 +465,7 @@ module Bolt
|
|
457
465
|
def list_plans
|
458
466
|
plans = pal.list_plans
|
459
467
|
plans.select! { |plan| plan.first.include?(options[:filter]) } if options[:filter]
|
468
|
+
plans.select! { |plan| config.project.plans.include?(plan.first) } unless config.project.plans.nil?
|
460
469
|
outputter.print_plans(plans, pal.list_modulepath)
|
461
470
|
end
|
462
471
|
|
@@ -567,10 +576,10 @@ module Bolt
|
|
567
576
|
# Initializes a specified directory as a Bolt project and installs any modules
|
568
577
|
# specified by the user, along with their dependencies
|
569
578
|
def initialize_project
|
570
|
-
|
571
|
-
config =
|
572
|
-
puppetfile =
|
573
|
-
modulepath = [
|
579
|
+
project = Pathname.new(File.expand_path(options[:object] || Dir.pwd))
|
580
|
+
config = project + 'bolt.yaml'
|
581
|
+
puppetfile = project + 'Puppetfile'
|
582
|
+
modulepath = [project + 'modules']
|
574
583
|
|
575
584
|
# If modules were specified, first check if there is already a Puppetfile at the project
|
576
585
|
# directory, erroring if there is. If there is no Puppetfile, generate the Puppetfile
|
@@ -590,20 +599,20 @@ module Bolt
|
|
590
599
|
# Warn the user if the project directory already exists. We don't error here since users
|
591
600
|
# might not have installed any modules yet.
|
592
601
|
if config.exist?
|
593
|
-
@logger.warn "Found existing project directory at #{
|
602
|
+
@logger.warn "Found existing project directory at #{project}"
|
594
603
|
end
|
595
604
|
|
596
605
|
# Create the project directory
|
597
|
-
FileUtils.mkdir_p(
|
606
|
+
FileUtils.mkdir_p(project)
|
598
607
|
|
599
|
-
# Bless the project directory as a
|
608
|
+
# Bless the project directory as a...wait for it...project
|
600
609
|
if FileUtils.touch(config)
|
601
|
-
outputter.print_message "Successfully created Bolt project at #{
|
610
|
+
outputter.print_message "Successfully created Bolt project at #{project}"
|
602
611
|
else
|
603
|
-
raise Bolt::FileError.new("Could not create Bolt project directory at #{
|
612
|
+
raise Bolt::FileError.new("Could not create Bolt project directory at #{project}", nil)
|
604
613
|
end
|
605
614
|
|
606
|
-
# Write the generated Puppetfile to the fancy new
|
615
|
+
# Write the generated Puppetfile to the fancy new project
|
607
616
|
if puppetfile_specs
|
608
617
|
File.write(puppetfile, puppetfile_specs.join("\n"))
|
609
618
|
outputter.print_message "Successfully created Puppetfile at #{puppetfile}"
|
@@ -752,12 +761,14 @@ module Bolt
|
|
752
761
|
end
|
753
762
|
|
754
763
|
def pal
|
764
|
+
project = config.project.load_as_module? ? config.project : nil
|
755
765
|
@pal ||= Bolt::PAL.new(config.modulepath,
|
756
766
|
config.hiera_config,
|
757
|
-
config.
|
767
|
+
config.project.resource_types,
|
758
768
|
config.compile_concurrency,
|
759
769
|
config.trusted_external,
|
760
|
-
config.apply_settings
|
770
|
+
config.apply_settings,
|
771
|
+
project)
|
761
772
|
end
|
762
773
|
|
763
774
|
def convert_plan(plan)
|
data/lib/bolt/config.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'etc'
|
4
4
|
require 'logging'
|
5
5
|
require 'pathname'
|
6
|
-
require 'bolt/
|
6
|
+
require 'bolt/project'
|
7
7
|
require 'bolt/logger'
|
8
8
|
require 'bolt/util'
|
9
9
|
# Transport config objects
|
@@ -23,7 +23,7 @@ module Bolt
|
|
23
23
|
end
|
24
24
|
|
25
25
|
class Config
|
26
|
-
attr_reader :config_files, :warnings, :data, :transports, :
|
26
|
+
attr_reader :config_files, :warnings, :data, :transports, :project
|
27
27
|
|
28
28
|
TRANSPORT_CONFIG = {
|
29
29
|
'ssh' => Bolt::Config::Transport::SSH,
|
@@ -102,30 +102,30 @@ module Bolt
|
|
102
102
|
}.freeze
|
103
103
|
|
104
104
|
def self.default
|
105
|
-
new(Bolt::
|
105
|
+
new(Bolt::Project.new('.'), {})
|
106
106
|
end
|
107
107
|
|
108
|
-
def self.
|
108
|
+
def self.from_project(project, overrides = {})
|
109
109
|
data = {
|
110
|
-
filepath:
|
111
|
-
data: Bolt::Util.read_optional_yaml_hash(
|
110
|
+
filepath: project.config_file,
|
111
|
+
data: Bolt::Util.read_optional_yaml_hash(project.config_file, 'config')
|
112
112
|
}
|
113
113
|
|
114
114
|
data = load_defaults.push(data).select { |config| config[:data]&.any? }
|
115
115
|
|
116
|
-
new(
|
116
|
+
new(project, data, overrides)
|
117
117
|
end
|
118
118
|
|
119
119
|
def self.from_file(configfile, overrides = {})
|
120
|
-
|
120
|
+
project = Bolt::Project.new(Pathname.new(configfile).expand_path.dirname)
|
121
121
|
|
122
122
|
data = {
|
123
|
-
filepath:
|
123
|
+
filepath: project.config_file,
|
124
124
|
data: Bolt::Util.read_yaml_hash(configfile, 'config')
|
125
125
|
}
|
126
126
|
data = load_defaults.push(data).select { |config| config[:data]&.any? }
|
127
127
|
|
128
|
-
new(
|
128
|
+
new(project, data, overrides)
|
129
129
|
end
|
130
130
|
|
131
131
|
def self.load_defaults
|
@@ -148,14 +148,14 @@ module Bolt
|
|
148
148
|
confs
|
149
149
|
end
|
150
150
|
|
151
|
-
def initialize(
|
151
|
+
def initialize(project, config_data, overrides = {})
|
152
152
|
unless config_data.is_a?(Array)
|
153
|
-
config_data = [{ filepath:
|
153
|
+
config_data = [{ filepath: project.config_file, data: config_data }]
|
154
154
|
end
|
155
155
|
|
156
156
|
@logger = Logging.logger[self]
|
157
157
|
@warnings = []
|
158
|
-
@
|
158
|
+
@project = project
|
159
159
|
@transports = {}
|
160
160
|
@config_files = []
|
161
161
|
|
@@ -184,7 +184,7 @@ module Bolt
|
|
184
184
|
@data = merge_config_layers(default_data, *loaded_data, override_data)
|
185
185
|
|
186
186
|
TRANSPORT_CONFIG.each do |transport, config|
|
187
|
-
@transports[transport] = config.new(@data.delete(transport), @
|
187
|
+
@transports[transport] = config.new(@data.delete(transport), @project.path)
|
188
188
|
end
|
189
189
|
|
190
190
|
finalize_data
|
@@ -250,7 +250,7 @@ module Bolt
|
|
250
250
|
@data['log'] = update_logs(@data['log'])
|
251
251
|
end
|
252
252
|
|
253
|
-
# Expand paths relative to the
|
253
|
+
# Expand paths relative to the project. Any settings that came from the
|
254
254
|
# CLI will already be absolute, so the expand will be skipped.
|
255
255
|
if @data.key?('modulepath')
|
256
256
|
moduledirs = if data['modulepath'].is_a?(String)
|
@@ -259,12 +259,12 @@ module Bolt
|
|
259
259
|
data['modulepath']
|
260
260
|
end
|
261
261
|
@data['modulepath'] = moduledirs.map do |moduledir|
|
262
|
-
File.expand_path(moduledir, @
|
262
|
+
File.expand_path(moduledir, @project.path)
|
263
263
|
end
|
264
264
|
end
|
265
265
|
|
266
266
|
%w[hiera-config inventoryfile trusted-external-command].each do |opt|
|
267
|
-
@data[opt] = File.expand_path(@data[opt], @
|
267
|
+
@data[opt] = File.expand_path(@data[opt], @project.path) if @data.key?(opt)
|
268
268
|
end
|
269
269
|
|
270
270
|
# Filter hashes to only include valid options
|
@@ -275,7 +275,7 @@ module Bolt
|
|
275
275
|
private def normalize_log(target)
|
276
276
|
return target if target == 'console'
|
277
277
|
target = target[5..-1] if target.start_with?('file:')
|
278
|
-
'file:' + File.expand_path(target, @
|
278
|
+
'file:' + File.expand_path(target, @project.path)
|
279
279
|
end
|
280
280
|
|
281
281
|
private def update_logs(logs)
|
@@ -348,23 +348,23 @@ module Bolt
|
|
348
348
|
end
|
349
349
|
|
350
350
|
def default_inventoryfile
|
351
|
-
@
|
351
|
+
@project.inventory_file
|
352
352
|
end
|
353
353
|
|
354
354
|
def rerunfile
|
355
|
-
@
|
355
|
+
@project.rerunfile
|
356
356
|
end
|
357
357
|
|
358
358
|
def hiera_config
|
359
|
-
@data['hiera-config'] || @
|
359
|
+
@data['hiera-config'] || @project.hiera_config
|
360
360
|
end
|
361
361
|
|
362
362
|
def puppetfile
|
363
|
-
@puppetfile || @
|
363
|
+
@puppetfile || @project.puppetfile
|
364
364
|
end
|
365
365
|
|
366
366
|
def modulepath
|
367
|
-
@data['modulepath'] || @
|
367
|
+
@data['modulepath'] || @project.modulepath
|
368
368
|
end
|
369
369
|
|
370
370
|
def modulepath=(value)
|