bolt 2.37.0 → 2.44.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 +17 -17
- data/bolt-modules/boltlib/lib/puppet/functions/parallelize.rb +6 -8
- data/lib/bolt/analytics.rb +3 -2
- data/lib/bolt/applicator.rb +11 -1
- data/lib/bolt/bolt_option_parser.rb +20 -13
- data/lib/bolt/catalog.rb +10 -29
- data/lib/bolt/cli.rb +58 -40
- data/lib/bolt/config.rb +134 -119
- data/lib/bolt/config/options.rb +142 -77
- data/lib/bolt/config/transport/base.rb +2 -2
- data/lib/bolt/config/transport/local.rb +1 -0
- data/lib/bolt/config/transport/options.rb +18 -68
- data/lib/bolt/config/transport/orch.rb +1 -0
- data/lib/bolt/config/transport/ssh.rb +0 -5
- data/lib/bolt/executor.rb +15 -5
- data/lib/bolt/inventory.rb +26 -0
- data/lib/bolt/inventory/group.rb +35 -12
- data/lib/bolt/inventory/inventory.rb +1 -1
- data/lib/bolt/inventory/options.rb +130 -0
- data/lib/bolt/inventory/target.rb +10 -11
- data/lib/bolt/logger.rb +114 -10
- data/lib/bolt/module.rb +10 -2
- data/lib/bolt/module_installer.rb +25 -15
- data/lib/bolt/module_installer/resolver.rb +65 -12
- data/lib/bolt/module_installer/specs/forge_spec.rb +8 -2
- data/lib/bolt/module_installer/specs/git_spec.rb +17 -2
- data/lib/bolt/outputter.rb +19 -5
- data/lib/bolt/outputter/human.rb +24 -1
- data/lib/bolt/outputter/json.rb +1 -1
- data/lib/bolt/outputter/logger.rb +1 -1
- data/lib/bolt/outputter/rainbow.rb +12 -1
- data/lib/bolt/pal.rb +93 -14
- data/lib/bolt/pal/yaml_plan.rb +8 -2
- data/lib/bolt/pal/yaml_plan/evaluator.rb +2 -2
- data/lib/bolt/pal/yaml_plan/transpiler.rb +6 -1
- data/lib/bolt/plugin.rb +3 -3
- data/lib/bolt/plugin/cache.rb +8 -8
- data/lib/bolt/plugin/module.rb +1 -1
- data/lib/bolt/plugin/puppet_connect_data.rb +35 -0
- data/lib/bolt/plugin/puppetdb.rb +2 -2
- data/lib/bolt/project.rb +76 -50
- data/lib/bolt/project_manager.rb +2 -0
- data/lib/bolt/project_manager/config_migrator.rb +9 -1
- data/lib/bolt/project_manager/module_migrator.rb +2 -0
- data/lib/bolt/puppetdb/client.rb +8 -0
- data/lib/bolt/rerun.rb +1 -1
- data/lib/bolt/shell/bash.rb +1 -1
- data/lib/bolt/shell/bash/tmpdir.rb +4 -1
- data/lib/bolt/shell/powershell.rb +7 -5
- data/lib/bolt/target.rb +4 -0
- data/lib/bolt/task.rb +1 -1
- data/lib/bolt/transport/docker/connection.rb +2 -2
- data/lib/bolt/transport/local.rb +13 -0
- data/lib/bolt/transport/orch/connection.rb +1 -1
- data/lib/bolt/transport/ssh.rb +1 -2
- data/lib/bolt/transport/ssh/connection.rb +1 -1
- data/lib/bolt/validator.rb +227 -0
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/config.rb +1 -1
- data/lib/bolt_server/schemas/partials/task.json +1 -1
- data/lib/bolt_server/transport_app.rb +28 -27
- data/libexec/bolt_catalog +1 -1
- metadata +27 -11
- data/lib/bolt/config/validator.rb +0 -231
data/lib/bolt/version.rb
CHANGED
data/lib/bolt_server/config.rb
CHANGED
@@ -9,7 +9,7 @@ module BoltServer
|
|
9
9
|
def config_keys
|
10
10
|
super + %w[concurrency cache-dir file-server-conn-timeout
|
11
11
|
file-server-uri projects-dir environments-codedir
|
12
|
-
environmentpath basemodulepath]
|
12
|
+
environmentpath basemodulepath builtin-content-dir]
|
13
13
|
end
|
14
14
|
|
15
15
|
def env_keys
|
@@ -51,8 +51,8 @@ module BoltServer
|
|
51
51
|
# See the `orchestrator.bolt.codedir` tk config setting.
|
52
52
|
DEFAULT_BOLT_CODEDIR = '/opt/puppetlabs/server/data/orchestration-services/code'
|
53
53
|
|
54
|
-
|
55
|
-
400, Bolt::ValidationError.new('`
|
54
|
+
MISSING_VERSIONED_PROJECT_RESPONSE = [
|
55
|
+
400, Bolt::ValidationError.new('`versioned_project` is a required argument').to_json
|
56
56
|
].freeze
|
57
57
|
|
58
58
|
def initialize(config)
|
@@ -268,19 +268,20 @@ module BoltServer
|
|
268
268
|
end
|
269
269
|
end
|
270
270
|
|
271
|
-
def config_from_project(
|
272
|
-
project_dir = File.join(@config['projects-dir'],
|
273
|
-
raise Bolt::ValidationError, "`
|
271
|
+
def config_from_project(versioned_project)
|
272
|
+
project_dir = File.join(@config['projects-dir'], versioned_project)
|
273
|
+
raise Bolt::ValidationError, "`versioned_project`: #{project_dir} does not exist" unless Dir.exist?(project_dir)
|
274
274
|
project = Bolt::Project.create_project(project_dir)
|
275
275
|
Bolt::Config.from_project(project, { log: { 'bolt-debug.log' => 'disable' } })
|
276
276
|
end
|
277
277
|
|
278
|
-
def in_bolt_project(
|
278
|
+
def in_bolt_project(versioned_project)
|
279
279
|
@pal_mutex.synchronize do
|
280
|
-
bolt_config = config_from_project(
|
280
|
+
bolt_config = config_from_project(versioned_project)
|
281
281
|
modulepath_object = Bolt::Config::Modulepath.new(
|
282
282
|
bolt_config.modulepath,
|
283
|
-
boltlib_path: [PE_BOLTLIB_PATH, Bolt::Config::Modulepath::BOLTLIB_PATH]
|
283
|
+
boltlib_path: [PE_BOLTLIB_PATH, Bolt::Config::Modulepath::BOLTLIB_PATH],
|
284
|
+
builtin_content_path: @config['builtin-content-dir']
|
284
285
|
)
|
285
286
|
pal = Bolt::PAL.new(modulepath_object, nil, nil, nil, nil, nil, bolt_config.project)
|
286
287
|
context = {
|
@@ -514,10 +515,10 @@ module BoltServer
|
|
514
515
|
|
515
516
|
# Fetches the metadata for a single plan
|
516
517
|
#
|
517
|
-
# @param
|
518
|
+
# @param versioned_project [String] the project to fetch the plan from
|
518
519
|
get '/project_plans/:module_name/:plan_name' do
|
519
|
-
return
|
520
|
-
in_bolt_project(params['
|
520
|
+
return MISSING_VERSIONED_PROJECT_RESPONSE if params['versioned_project'].nil?
|
521
|
+
in_bolt_project(params['versioned_project']) do |context|
|
521
522
|
plan_info = pe_plan_info(context[:pal], params[:module_name], params[:plan_name])
|
522
523
|
plan_info = allowed_helper(plan_info, context[:config].project.plans)
|
523
524
|
[200, plan_info.to_json]
|
@@ -541,12 +542,12 @@ module BoltServer
|
|
541
542
|
|
542
543
|
# Fetches the metadata for a single task
|
543
544
|
#
|
544
|
-
# @param
|
545
|
+
# @param bolt_versioned_project [String] the reference to the bolt-project directory to load task metadata from
|
545
546
|
get '/project_tasks/:module_name/:task_name' do
|
546
|
-
return
|
547
|
-
in_bolt_project(params['
|
547
|
+
return MISSING_VERSIONED_PROJECT_RESPONSE if params['versioned_project'].nil?
|
548
|
+
in_bolt_project(params['versioned_project']) do |context|
|
548
549
|
ps_parameters = {
|
549
|
-
'versioned_project' => params['
|
550
|
+
'versioned_project' => params['versioned_project']
|
550
551
|
}
|
551
552
|
task_info = pe_task_info(context[:pal], params[:module_name], params[:task_name], ps_parameters)
|
552
553
|
task_info = allowed_helper(task_info, context[:config].project.tasks)
|
@@ -582,10 +583,10 @@ module BoltServer
|
|
582
583
|
|
583
584
|
# Fetches the list of plans for a project
|
584
585
|
#
|
585
|
-
# @param
|
586
|
+
# @param versioned_project [String] the project to fetch the list of plans from
|
586
587
|
get '/project_plans' do
|
587
|
-
return
|
588
|
-
in_bolt_project(params['
|
588
|
+
return MISSING_VERSIONED_PROJECT_RESPONSE if params['versioned_project'].nil?
|
589
|
+
in_bolt_project(params['versioned_project']) do |context|
|
589
590
|
plans_response = plan_list(context[:pal])
|
590
591
|
|
591
592
|
# Dig in context for the allowlist of plans from project object
|
@@ -618,10 +619,10 @@ module BoltServer
|
|
618
619
|
|
619
620
|
# Fetches the list of tasks for a bolt-project
|
620
621
|
#
|
621
|
-
# @param
|
622
|
+
# @param versioned_project [String] the project to fetch the list of tasks from
|
622
623
|
get '/project_tasks' do
|
623
|
-
return
|
624
|
-
in_bolt_project(params['
|
624
|
+
return MISSING_VERSIONED_PROJECT_RESPONSE if params['versioned_project'].nil?
|
625
|
+
in_bolt_project(params['versioned_project']) do |context|
|
625
626
|
tasks_response = task_list(context[:pal])
|
626
627
|
|
627
628
|
# Dig in context for the allowlist of tasks from project object
|
@@ -639,10 +640,10 @@ module BoltServer
|
|
639
640
|
|
640
641
|
# Implements puppetserver's file_metadatas endpoint for projects.
|
641
642
|
#
|
642
|
-
# @param
|
643
|
+
# @param versioned_project [String] the versioned_project to fetch the file metadatas from
|
643
644
|
get '/project_file_metadatas/:module_name/*' do
|
644
|
-
return
|
645
|
-
in_bolt_project(params['
|
645
|
+
return MISSING_VERSIONED_PROJECT_RESPONSE if params['versioned_project'].nil?
|
646
|
+
in_bolt_project(params['versioned_project']) do |context|
|
646
647
|
file = params[:splat].first
|
647
648
|
metadatas = file_metadatas(context[:pal], params[:module_name], file)
|
648
649
|
[200, metadatas.to_json]
|
@@ -655,14 +656,14 @@ module BoltServer
|
|
655
656
|
|
656
657
|
# Returns a list of targets parsed from a Project inventory
|
657
658
|
#
|
658
|
-
# @param
|
659
|
+
# @param versioned_project [String] the versioned_project to compute the inventory from
|
659
660
|
post '/project_inventory_targets' do
|
660
|
-
return
|
661
|
+
return MISSING_VERSIONED_PROJECT_RESPONSE if params['versioned_project'].nil?
|
661
662
|
content_type :json
|
662
663
|
body = JSON.parse(request.body.read)
|
663
664
|
error = validate_schema(@schemas["connect-data"], body)
|
664
665
|
return [400, error_result(error).to_json] unless error.nil?
|
665
|
-
in_bolt_project(params['
|
666
|
+
in_bolt_project(params['versioned_project']) do |context|
|
666
667
|
if context[:config].inventoryfile &&
|
667
668
|
context[:config].project.inventory_file.to_s !=
|
668
669
|
context[:config].inventoryfile
|
data/libexec/bolt_catalog
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bolt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.44.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Puppet
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: ffi
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "<"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.14.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "<"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.14.0
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: hiera-eyaml
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -170,14 +184,14 @@ dependencies:
|
|
170
184
|
requirements:
|
171
185
|
- - "~>"
|
172
186
|
- !ruby/object:Gem::Version
|
173
|
-
version: '0.
|
187
|
+
version: '0.5'
|
174
188
|
type: :runtime
|
175
189
|
prerelease: false
|
176
190
|
version_requirements: !ruby/object:Gem::Requirement
|
177
191
|
requirements:
|
178
192
|
- - "~>"
|
179
193
|
- !ruby/object:Gem::Version
|
180
|
-
version: '0.
|
194
|
+
version: '0.5'
|
181
195
|
- !ruby/object:Gem::Dependency
|
182
196
|
name: puppet
|
183
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -198,14 +212,14 @@ dependencies:
|
|
198
212
|
requirements:
|
199
213
|
- - "~>"
|
200
214
|
- !ruby/object:Gem::Version
|
201
|
-
version: '0.
|
215
|
+
version: '0.5'
|
202
216
|
type: :runtime
|
203
217
|
prerelease: false
|
204
218
|
version_requirements: !ruby/object:Gem::Requirement
|
205
219
|
requirements:
|
206
220
|
- - "~>"
|
207
221
|
- !ruby/object:Gem::Version
|
208
|
-
version: '0.
|
222
|
+
version: '0.5'
|
209
223
|
- !ruby/object:Gem::Dependency
|
210
224
|
name: puppet-resource_api
|
211
225
|
requirement: !ruby/object:Gem::Requirement
|
@@ -336,16 +350,16 @@ dependencies:
|
|
336
350
|
name: puppetlabs_spec_helper
|
337
351
|
requirement: !ruby/object:Gem::Requirement
|
338
352
|
requirements:
|
339
|
-
- - "
|
353
|
+
- - "<="
|
340
354
|
- !ruby/object:Gem::Version
|
341
|
-
version:
|
355
|
+
version: 2.15.0
|
342
356
|
type: :development
|
343
357
|
prerelease: false
|
344
358
|
version_requirements: !ruby/object:Gem::Requirement
|
345
359
|
requirements:
|
346
|
-
- - "
|
360
|
+
- - "<="
|
347
361
|
- !ruby/object:Gem::Version
|
348
|
-
version:
|
362
|
+
version: 2.15.0
|
349
363
|
- !ruby/object:Gem::Dependency
|
350
364
|
name: rake
|
351
365
|
requirement: !ruby/object:Gem::Requirement
|
@@ -458,12 +472,12 @@ files:
|
|
458
472
|
- lib/bolt/config/transport/remote.rb
|
459
473
|
- lib/bolt/config/transport/ssh.rb
|
460
474
|
- lib/bolt/config/transport/winrm.rb
|
461
|
-
- lib/bolt/config/validator.rb
|
462
475
|
- lib/bolt/error.rb
|
463
476
|
- lib/bolt/executor.rb
|
464
477
|
- lib/bolt/inventory.rb
|
465
478
|
- lib/bolt/inventory/group.rb
|
466
479
|
- lib/bolt/inventory/inventory.rb
|
480
|
+
- lib/bolt/inventory/options.rb
|
467
481
|
- lib/bolt/inventory/target.rb
|
468
482
|
- lib/bolt/logger.rb
|
469
483
|
- lib/bolt/module.rb
|
@@ -509,6 +523,7 @@ files:
|
|
509
523
|
- lib/bolt/plugin/env_var.rb
|
510
524
|
- lib/bolt/plugin/module.rb
|
511
525
|
- lib/bolt/plugin/prompt.rb
|
526
|
+
- lib/bolt/plugin/puppet_connect_data.rb
|
512
527
|
- lib/bolt/plugin/puppetdb.rb
|
513
528
|
- lib/bolt/plugin/task.rb
|
514
529
|
- lib/bolt/project.rb
|
@@ -551,6 +566,7 @@ files:
|
|
551
566
|
- lib/bolt/transport/winrm/connection.rb
|
552
567
|
- lib/bolt/util.rb
|
553
568
|
- lib/bolt/util/puppet_log_level.rb
|
569
|
+
- lib/bolt/validator.rb
|
554
570
|
- lib/bolt/version.rb
|
555
571
|
- lib/bolt/yarn.rb
|
556
572
|
- lib/bolt_server/acl.rb
|
@@ -1,231 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'bolt/error'
|
4
|
-
|
5
|
-
# This class validates config against a schema, raising an error that includes
|
6
|
-
# details about any invalid configuration.
|
7
|
-
#
|
8
|
-
module Bolt
|
9
|
-
class Config
|
10
|
-
class Validator
|
11
|
-
attr_reader :deprecations, :warnings
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
@errors = []
|
15
|
-
@deprecations = []
|
16
|
-
@warnings = []
|
17
|
-
@path = []
|
18
|
-
end
|
19
|
-
|
20
|
-
# This is the entry method for validating data against the schema.
|
21
|
-
# It loops over each key-value pair in the data hash and validates
|
22
|
-
# the value against the relevant schema definition.
|
23
|
-
#
|
24
|
-
def validate(data, schema, location = nil)
|
25
|
-
@location = location
|
26
|
-
|
27
|
-
validate_keys(data.keys, schema.keys)
|
28
|
-
|
29
|
-
data.each_pair do |key, value|
|
30
|
-
next unless schema.key?(key)
|
31
|
-
|
32
|
-
@path.push(key)
|
33
|
-
|
34
|
-
check_deprecated(key, schema[key], location)
|
35
|
-
validate_value(value, schema[key])
|
36
|
-
ensure
|
37
|
-
@path.pop
|
38
|
-
end
|
39
|
-
|
40
|
-
raise_error
|
41
|
-
end
|
42
|
-
|
43
|
-
# Adds a warning if the given option is deprecated.
|
44
|
-
#
|
45
|
-
def check_deprecated(key, definition, location)
|
46
|
-
if definition.key?(:_deprecation)
|
47
|
-
message = "Option '#{path}' "
|
48
|
-
message += "at #{location} " if location
|
49
|
-
message += "is deprecated. #{definition[:_deprecation]}"
|
50
|
-
@deprecations << { option: key, message: message }
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# Raises a ValidationError if there are any errors. All error messages
|
55
|
-
# created during validation are concatenated into a single error
|
56
|
-
# message.
|
57
|
-
#
|
58
|
-
private def raise_error
|
59
|
-
return unless @errors.any?
|
60
|
-
|
61
|
-
message = "Invalid configuration"
|
62
|
-
message += " at #{@location}" if @location
|
63
|
-
message += ":\n"
|
64
|
-
message += @errors.map { |error| "\s\s#{error}" }.join("\n")
|
65
|
-
|
66
|
-
raise Bolt::ValidationError, message
|
67
|
-
end
|
68
|
-
|
69
|
-
# Validate an individual value. This performs validation that is
|
70
|
-
# common to all values, including type validation. After validating
|
71
|
-
# the value's type, the value is passed off to an individual
|
72
|
-
# validation method for the value's type.
|
73
|
-
#
|
74
|
-
private def validate_value(value, definition)
|
75
|
-
return if plugin_reference?(value, definition)
|
76
|
-
return unless valid_type?(value, definition)
|
77
|
-
|
78
|
-
case value
|
79
|
-
when Hash
|
80
|
-
validate_hash(value, definition)
|
81
|
-
when Array
|
82
|
-
validate_array(value, definition)
|
83
|
-
when String
|
84
|
-
validate_string(value, definition)
|
85
|
-
when Numeric
|
86
|
-
validate_number(value, definition)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# Validates a hash value, logging errors for any validations that fail.
|
91
|
-
# This will enumerate each key-value pair in the hash and validate each
|
92
|
-
# value individually.
|
93
|
-
#
|
94
|
-
private def validate_hash(value, definition)
|
95
|
-
properties = definition[:properties] ? definition[:properties].keys : []
|
96
|
-
|
97
|
-
if definition[:properties] && definition[:additionalProperties].nil?
|
98
|
-
validate_keys(value.keys, properties)
|
99
|
-
end
|
100
|
-
|
101
|
-
if definition[:required] && (definition[:required] - value.keys).any?
|
102
|
-
missing = definition[:required] - value.keys
|
103
|
-
@errors << "Value at '#{path}' is missing required keys #{missing.join(', ')}"
|
104
|
-
end
|
105
|
-
|
106
|
-
value.each_pair do |key, val|
|
107
|
-
@path.push(key)
|
108
|
-
|
109
|
-
if properties.include?(key)
|
110
|
-
validate_value(val, definition[:properties][key])
|
111
|
-
elsif definition[:additionalProperties]
|
112
|
-
validate_value(val, definition[:additionalProperties])
|
113
|
-
end
|
114
|
-
ensure
|
115
|
-
@path.pop
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# Validates an array value, logging errors for any validations that fail.
|
120
|
-
# This will enumerate the items in the array and validate each item
|
121
|
-
# individually.
|
122
|
-
#
|
123
|
-
private def validate_array(value, definition)
|
124
|
-
if definition[:uniqueItems] && value.size != value.uniq.size
|
125
|
-
@errors << "Value at '#{path}' must not include duplicate elements"
|
126
|
-
return
|
127
|
-
end
|
128
|
-
|
129
|
-
return unless definition.key?(:items)
|
130
|
-
|
131
|
-
value.each_with_index do |item, index|
|
132
|
-
@path.push(index)
|
133
|
-
validate_value(item, definition[:items])
|
134
|
-
ensure
|
135
|
-
@path.pop
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
# Validates a string value, logging errors for any validations that fail.
|
140
|
-
#
|
141
|
-
private def validate_string(value, definition)
|
142
|
-
if definition.key?(:enum) && !definition[:enum].include?(value)
|
143
|
-
message = "Value at '#{path}' must be "
|
144
|
-
message += "one of " if definition[:enum].count > 1
|
145
|
-
message += definition[:enum].join(', ')
|
146
|
-
multitype_error(message, value, definition)
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
# Validates a numeric value, logging errors for any validations that fail.
|
151
|
-
#
|
152
|
-
private def validate_number(value, definition)
|
153
|
-
if definition.key?(:minimum) && value < definition[:minimum]
|
154
|
-
@errors << "Value at '#{path}' must be a minimum of #{definition[:minimum]}"
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
# Adds warnings for unknown config options.
|
159
|
-
#
|
160
|
-
private def validate_keys(keys, known_keys)
|
161
|
-
(keys - known_keys).each do |key|
|
162
|
-
message = "Unknown option '#{key}'"
|
163
|
-
message += " at '#{path}'" if @path.any?
|
164
|
-
message += " at #{@location}" if @location
|
165
|
-
message += "."
|
166
|
-
@warnings << message
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
# Returns true if a value is a plugin reference. This also validates whether
|
171
|
-
# a value can be a plugin reference in the first place. If the value is a
|
172
|
-
# plugin reference but cannot be one according to the schema, then this will
|
173
|
-
# log an error.
|
174
|
-
#
|
175
|
-
private def plugin_reference?(value, definition)
|
176
|
-
if value.is_a?(Hash) && value.key?('_plugin')
|
177
|
-
unless definition[:_plugin]
|
178
|
-
@errors << "Value at '#{path}' is a plugin reference, which is unsupported at "\
|
179
|
-
"this location"
|
180
|
-
end
|
181
|
-
|
182
|
-
true
|
183
|
-
else
|
184
|
-
false
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
# Asserts the type for each option against the type specified in the schema
|
189
|
-
# definition. The schema definition can specify multiple valid types, so the
|
190
|
-
# value needs to only match one of the types to be valid. Returns early if
|
191
|
-
# there is no type in the definition (in practice this shouldn't happen, but
|
192
|
-
# this will safeguard against any dev mistakes).
|
193
|
-
#
|
194
|
-
private def valid_type?(value, definition)
|
195
|
-
return unless definition.key?(:type)
|
196
|
-
|
197
|
-
types = Array(definition[:type])
|
198
|
-
|
199
|
-
if types.include?(value.class)
|
200
|
-
true
|
201
|
-
else
|
202
|
-
if types.include?(TrueClass) || types.include?(FalseClass)
|
203
|
-
types = types - [TrueClass, FalseClass] + ['Boolean']
|
204
|
-
end
|
205
|
-
|
206
|
-
@errors << "Value at '#{path}' must be of type #{types.join(' or ')}"
|
207
|
-
|
208
|
-
false
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
# Adds an error that includes additional helpful information for values
|
213
|
-
# that accept multiple types.
|
214
|
-
#
|
215
|
-
private def multitype_error(message, value, definition)
|
216
|
-
if Array(definition[:type]).count > 1
|
217
|
-
types = Array(definition[:type]) - [value.class]
|
218
|
-
message += " or must be of type #{types.join(' or ')}"
|
219
|
-
end
|
220
|
-
|
221
|
-
@errors << message
|
222
|
-
end
|
223
|
-
|
224
|
-
# Returns the formatted path for the key.
|
225
|
-
#
|
226
|
-
private def path
|
227
|
-
@path.join('.')
|
228
|
-
end
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|