bolt 2.33.2 → 2.38.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 +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 +48 -16
- data/lib/bolt/cli.rb +154 -249
- data/lib/bolt/config.rb +188 -55
- data/lib/bolt/config/options.rb +147 -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 +10 -68
- data/lib/bolt/config/transport/ssh.rb +8 -14
- data/lib/bolt/error.rb +33 -3
- data/lib/bolt/executor.rb +92 -6
- data/lib/bolt/inventory.rb +25 -0
- data/lib/bolt/inventory/group.rb +2 -1
- 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 +41 -10
- 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 +19 -7
- data/lib/bolt/pal/yaml_plan.rb +7 -0
- data/lib/bolt/plan_creator.rb +160 -0
- data/lib/bolt/plugin.rb +42 -13
- 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} +51 -5
- data/lib/bolt/{project_migrator/inventory.rb → project_manager/inventory_migrator.rb} +5 -5
- 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 +9 -8
- data/lib/bolt/rerun.rb +1 -5
- data/lib/bolt/shell/bash.rb +8 -2
- data/lib/bolt/shell/powershell.rb +22 -4
- 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/remote.rb +1 -1
- data/lib/bolt/transport/ssh/exec_connection.rb +6 -2
- data/lib/bolt/util.rb +41 -7
- data/lib/bolt/validator.rb +226 -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/file_cache.rb +2 -0
- 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 -13
- data/lib/bolt/project_migrator.rb +0 -80
@@ -0,0 +1,226 @@
|
|
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 Validator
|
10
|
+
attr_reader :deprecations, :warnings
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@errors = []
|
14
|
+
@deprecations = []
|
15
|
+
@warnings = []
|
16
|
+
@path = []
|
17
|
+
end
|
18
|
+
|
19
|
+
# This is the entry method for validating data against the schema.
|
20
|
+
#
|
21
|
+
def validate(data, schema, location = nil)
|
22
|
+
@schema = schema
|
23
|
+
@location = location
|
24
|
+
|
25
|
+
validate_value(data, schema)
|
26
|
+
|
27
|
+
raise_error
|
28
|
+
end
|
29
|
+
|
30
|
+
# Raises a ValidationError if there are any errors. All error messages
|
31
|
+
# created during validation are concatenated into a single error
|
32
|
+
# message.
|
33
|
+
#
|
34
|
+
private def raise_error
|
35
|
+
return unless @errors.any?
|
36
|
+
|
37
|
+
message = "Invalid configuration"
|
38
|
+
message += " at #{@location}" if @location
|
39
|
+
message += ":\n"
|
40
|
+
message += @errors.map { |error| "\s\s#{error}" }.join("\n")
|
41
|
+
|
42
|
+
raise Bolt::ValidationError, message
|
43
|
+
end
|
44
|
+
|
45
|
+
# Validate an individual value. This performs validation that is
|
46
|
+
# common to all values, including type validation. After validating
|
47
|
+
# the value's type, the value is passed off to an individual
|
48
|
+
# validation method for the value's type.
|
49
|
+
#
|
50
|
+
private def validate_value(value, definition)
|
51
|
+
definition = @schema.dig(:definitions, definition[:_ref]) if definition[:_ref]
|
52
|
+
|
53
|
+
return if plugin_reference?(value, definition)
|
54
|
+
return unless valid_type?(value, definition)
|
55
|
+
|
56
|
+
case value
|
57
|
+
when Hash
|
58
|
+
validate_hash(value, definition)
|
59
|
+
when Array
|
60
|
+
validate_array(value, definition)
|
61
|
+
when String
|
62
|
+
validate_string(value, definition)
|
63
|
+
when Numeric
|
64
|
+
validate_number(value, definition)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Validates a hash value, logging errors for any validations that fail.
|
69
|
+
# This will enumerate each key-value pair in the hash and validate each
|
70
|
+
# value individually.
|
71
|
+
#
|
72
|
+
private def validate_hash(value, definition)
|
73
|
+
properties = definition[:properties] ? definition[:properties].keys : []
|
74
|
+
|
75
|
+
if definition[:properties] && definition[:additionalProperties].nil?
|
76
|
+
validate_keys(value.keys, properties)
|
77
|
+
end
|
78
|
+
|
79
|
+
if definition[:required] && (definition[:required] - value.keys).any?
|
80
|
+
missing = definition[:required] - value.keys
|
81
|
+
@errors << "Value at '#{path}' is missing required keys #{missing.join(', ')}"
|
82
|
+
end
|
83
|
+
|
84
|
+
value.each_pair do |key, val|
|
85
|
+
@path.push(key)
|
86
|
+
|
87
|
+
if properties.include?(key)
|
88
|
+
check_deprecated(key, definition[:properties][key])
|
89
|
+
validate_value(val, definition[:properties][key])
|
90
|
+
elsif definition[:additionalProperties]
|
91
|
+
validate_value(val, definition[:additionalProperties])
|
92
|
+
end
|
93
|
+
ensure
|
94
|
+
@path.pop
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Validates an array value, logging errors for any validations that fail.
|
99
|
+
# This will enumerate the items in the array and validate each item
|
100
|
+
# individually.
|
101
|
+
#
|
102
|
+
private def validate_array(value, definition)
|
103
|
+
if definition[:uniqueItems] && value.size != value.uniq.size
|
104
|
+
@errors << "Value at '#{path}' must not include duplicate elements"
|
105
|
+
return
|
106
|
+
end
|
107
|
+
|
108
|
+
return unless definition.key?(:items)
|
109
|
+
|
110
|
+
value.each_with_index do |item, index|
|
111
|
+
@path.push(index)
|
112
|
+
validate_value(item, definition[:items])
|
113
|
+
ensure
|
114
|
+
@path.pop
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Validates a string value, logging errors for any validations that fail.
|
119
|
+
#
|
120
|
+
private def validate_string(value, definition)
|
121
|
+
if definition.key?(:enum) && !definition[:enum].include?(value)
|
122
|
+
message = "Value at '#{path}' must be "
|
123
|
+
message += "one of " if definition[:enum].count > 1
|
124
|
+
message += definition[:enum].join(', ')
|
125
|
+
multitype_error(message, value, definition)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Validates a numeric value, logging errors for any validations that fail.
|
130
|
+
#
|
131
|
+
private def validate_number(value, definition)
|
132
|
+
if definition.key?(:minimum) && value < definition[:minimum]
|
133
|
+
@errors << "Value at '#{path}' must be a minimum of #{definition[:minimum]}"
|
134
|
+
end
|
135
|
+
|
136
|
+
if definition.key?(:maximum) && value > definition[:maximum]
|
137
|
+
@errors << "Value at '#{path}' must be a maximum of #{definition[:maximum]}"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Adds warnings for unknown config options.
|
142
|
+
#
|
143
|
+
private def validate_keys(keys, known_keys)
|
144
|
+
(keys - known_keys).each do |key|
|
145
|
+
message = "Unknown option '#{key}'"
|
146
|
+
message += " at '#{path}'" if @path.any?
|
147
|
+
message += " at #{@location}" if @location
|
148
|
+
message += "."
|
149
|
+
@warnings << message
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Adds a warning if the given option is deprecated.
|
154
|
+
#
|
155
|
+
private def check_deprecated(key, definition)
|
156
|
+
definition = @schema.dig(:definitions, definition[:_ref]) if definition[:_ref]
|
157
|
+
|
158
|
+
if definition.key?(:_deprecation)
|
159
|
+
message = "Option '#{path}' "
|
160
|
+
message += "at #{@location} " if @location
|
161
|
+
message += "is deprecated. #{definition[:_deprecation]}"
|
162
|
+
@deprecations << { option: key, message: message }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Returns true if a value is a plugin reference. This also validates whether
|
167
|
+
# a value can be a plugin reference in the first place. If the value is a
|
168
|
+
# plugin reference but cannot be one according to the schema, then this will
|
169
|
+
# log an error.
|
170
|
+
#
|
171
|
+
private def plugin_reference?(value, definition)
|
172
|
+
if value.is_a?(Hash) && value.key?('_plugin')
|
173
|
+
unless definition[:_plugin]
|
174
|
+
@errors << "Value at '#{path}' is a plugin reference, which is unsupported at "\
|
175
|
+
"this location"
|
176
|
+
end
|
177
|
+
|
178
|
+
true
|
179
|
+
else
|
180
|
+
false
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# Asserts the type for each option against the type specified in the schema
|
185
|
+
# definition. The schema definition can specify multiple valid types, so the
|
186
|
+
# value needs to only match one of the types to be valid. Returns early if
|
187
|
+
# there is no type in the definition (in practice this shouldn't happen, but
|
188
|
+
# this will safeguard against any dev mistakes).
|
189
|
+
#
|
190
|
+
private def valid_type?(value, definition)
|
191
|
+
return unless definition.key?(:type)
|
192
|
+
|
193
|
+
types = Array(definition[:type])
|
194
|
+
|
195
|
+
if types.include?(value.class)
|
196
|
+
true
|
197
|
+
else
|
198
|
+
if types.include?(TrueClass) || types.include?(FalseClass)
|
199
|
+
types = types - [TrueClass, FalseClass] + ['Boolean']
|
200
|
+
end
|
201
|
+
|
202
|
+
@errors << "Value at '#{path}' must be of type #{types.join(' or ')}"
|
203
|
+
|
204
|
+
false
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# Adds an error that includes additional helpful information for values
|
209
|
+
# that accept multiple types.
|
210
|
+
#
|
211
|
+
private def multitype_error(message, value, definition)
|
212
|
+
if Array(definition[:type]).count > 1
|
213
|
+
types = Array(definition[:type]) - [value.class]
|
214
|
+
message += " or must be of type #{types.join(' or ')}"
|
215
|
+
end
|
216
|
+
|
217
|
+
@errors << message
|
218
|
+
end
|
219
|
+
|
220
|
+
# Returns the formatted path for the key.
|
221
|
+
#
|
222
|
+
private def path
|
223
|
+
@path.join('.')
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
data/lib/bolt/version.rb
CHANGED
data/lib/bolt/yarn.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fiber'
|
4
|
+
|
5
|
+
module Bolt
|
6
|
+
class Yarn
|
7
|
+
attr_reader :fiber, :value, :index
|
8
|
+
|
9
|
+
def initialize(fiber, index)
|
10
|
+
@fiber = fiber
|
11
|
+
@index = index
|
12
|
+
@value = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def alive?
|
16
|
+
fiber.alive?
|
17
|
+
end
|
18
|
+
|
19
|
+
def resume
|
20
|
+
@value = fiber.resume
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -7,7 +7,9 @@ module BoltServer
|
|
7
7
|
class BaseConfig
|
8
8
|
def config_keys
|
9
9
|
%w[host port ssl-cert ssl-key ssl-ca-cert
|
10
|
-
ssl-cipher-suites loglevel logfile allowlist
|
10
|
+
ssl-cipher-suites loglevel logfile allowlist
|
11
|
+
projects-dir environments-codedir
|
12
|
+
environmentpath basemodulepath]
|
11
13
|
end
|
12
14
|
|
13
15
|
def env_keys
|
data/lib/bolt_server/config.rb
CHANGED
@@ -7,7 +7,9 @@ require 'bolt/error'
|
|
7
7
|
module BoltServer
|
8
8
|
class Config < BoltServer::BaseConfig
|
9
9
|
def config_keys
|
10
|
-
super + %w[concurrency cache-dir file-server-conn-timeout
|
10
|
+
super + %w[concurrency cache-dir file-server-conn-timeout
|
11
|
+
file-server-uri projects-dir environments-codedir
|
12
|
+
environmentpath basemodulepath]
|
11
13
|
end
|
12
14
|
|
13
15
|
def env_keys
|
@@ -63,6 +63,7 @@ module BoltServer
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def client
|
66
|
+
# rubocop:disable Naming/VariableNumber
|
66
67
|
@client ||= begin
|
67
68
|
uri = URI(@config['file-server-uri'])
|
68
69
|
https = Net::HTTP.new(uri.host, uri.port)
|
@@ -75,6 +76,7 @@ module BoltServer
|
|
75
76
|
https.open_timeout = @config['file-server-conn-timeout']
|
76
77
|
https
|
77
78
|
end
|
79
|
+
# rubocop:enable Naming/VariableNumber
|
78
80
|
end
|
79
81
|
|
80
82
|
def request_file(path, params, file)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
|
5
|
+
module BoltServer
|
6
|
+
class Plugin
|
7
|
+
class PluginNotSupported < Bolt::Error
|
8
|
+
def initialize(msg, plugin_name)
|
9
|
+
super(msg, 'bolt/plugin-not-supported', { "plugin_name" => plugin_name })
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BoltServer
|
4
|
+
class Plugin
|
5
|
+
class PuppetConnectData
|
6
|
+
def initialize(data, **_opts)
|
7
|
+
@data = data
|
8
|
+
end
|
9
|
+
|
10
|
+
def name
|
11
|
+
'puppet_connect_data'
|
12
|
+
end
|
13
|
+
|
14
|
+
def hooks
|
15
|
+
%i[resolve_reference validate_resolve_reference]
|
16
|
+
end
|
17
|
+
|
18
|
+
def resolve_reference(opts)
|
19
|
+
key = opts['key']
|
20
|
+
|
21
|
+
@data.dig(key, 'value')
|
22
|
+
end
|
23
|
+
|
24
|
+
def validate_resolve_reference(opts)
|
25
|
+
unless opts['key']
|
26
|
+
raise Bolt::ValidationError,
|
27
|
+
"puppet_connect_data plugin requires that 'key' be specified"
|
28
|
+
end
|
29
|
+
|
30
|
+
unless @data.key?(opts['key'])
|
31
|
+
raise Bolt::ValidationError,
|
32
|
+
"puppet_connect_data plugin tried to lookup key '#{opts['key']}' but no value was found"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
3
|
+
"title": "project_inventory_targets connect plugin data",
|
4
|
+
"description": "POST project_inventory_targets connect plugin data",
|
5
|
+
"type": "object",
|
6
|
+
"properties": {
|
7
|
+
"puppet_connect_data": {
|
8
|
+
"type": "object",
|
9
|
+
"patternProperties": {
|
10
|
+
".*": {
|
11
|
+
"type": "object",
|
12
|
+
"properties": {
|
13
|
+
"value": {}
|
14
|
+
},
|
15
|
+
"required": ["value"]
|
16
|
+
}
|
17
|
+
},
|
18
|
+
"additionalProperties": false
|
19
|
+
}
|
20
|
+
},
|
21
|
+
"required": ["puppet_connect_data"]
|
22
|
+
}
|
@@ -64,7 +64,7 @@
|
|
64
64
|
"description": "Environment the task is in",
|
65
65
|
"type": "string"
|
66
66
|
},
|
67
|
-
"
|
67
|
+
"versioned_project": {
|
68
68
|
"description": "Project the task is in",
|
69
69
|
"type": "string"
|
70
70
|
}
|
@@ -77,7 +77,7 @@
|
|
77
77
|
},
|
78
78
|
{
|
79
79
|
"required": [
|
80
|
-
"
|
80
|
+
"versioned_project"
|
81
81
|
]
|
82
82
|
}
|
83
83
|
],
|
@@ -8,6 +8,8 @@ require 'bolt/inventory'
|
|
8
8
|
require 'bolt/project'
|
9
9
|
require 'bolt/target'
|
10
10
|
require 'bolt_server/file_cache'
|
11
|
+
require 'bolt_server/plugin'
|
12
|
+
require 'bolt_server/plugin/puppet_connect_data'
|
11
13
|
require 'bolt/task/puppet_server'
|
12
14
|
require 'json'
|
13
15
|
require 'json-schema'
|
@@ -35,6 +37,7 @@ module BoltServer
|
|
35
37
|
action-upload_file
|
36
38
|
transport-ssh
|
37
39
|
transport-winrm
|
40
|
+
connect-data
|
38
41
|
].freeze
|
39
42
|
|
40
43
|
# PE_BOLTLIB_PATH is intended to function exactly like the BOLTLIB_PATH used
|
@@ -48,6 +51,10 @@ module BoltServer
|
|
48
51
|
# See the `orchestrator.bolt.codedir` tk config setting.
|
49
52
|
DEFAULT_BOLT_CODEDIR = '/opt/puppetlabs/server/data/orchestration-services/code'
|
50
53
|
|
54
|
+
MISSING_VERSIONED_PROJECT_RESPONSE = [
|
55
|
+
400, Bolt::ValidationError.new('`versioned_project` is a required argument').to_json
|
56
|
+
].freeze
|
57
|
+
|
51
58
|
def initialize(config)
|
52
59
|
@config = config
|
53
60
|
@schemas = Hash[REQUEST_SCHEMAS.map do |basename|
|
@@ -231,9 +238,9 @@ module BoltServer
|
|
231
238
|
#
|
232
239
|
# WARNING: THIS FUNCTION SHOULD ONLY BE CALLED INSIDE A SYNCHRONIZED PAL MUTEX
|
233
240
|
def modulepath_from_environment(environment_name)
|
234
|
-
codedir = DEFAULT_BOLT_CODEDIR
|
235
|
-
environmentpath = "#{codedir}/environments"
|
236
|
-
basemodulepath = "#{codedir}/modules:/opt/puppetlabs/puppet/modules"
|
241
|
+
codedir = @config['environments-codedir'] || DEFAULT_BOLT_CODEDIR
|
242
|
+
environmentpath = @config['environmentpath'] || "#{codedir}/environments"
|
243
|
+
basemodulepath = @config['basemodulepath'] || "#{codedir}/modules:/opt/puppetlabs/puppet/modules"
|
237
244
|
modulepath_dirs = nil
|
238
245
|
with_pe_pal_init_settings(codedir, environmentpath, basemodulepath) do
|
239
246
|
environment = Puppet.lookup(:environments).get!(environment_name)
|
@@ -261,13 +268,16 @@ module BoltServer
|
|
261
268
|
end
|
262
269
|
end
|
263
270
|
|
264
|
-
def
|
265
|
-
|
266
|
-
project_dir
|
267
|
-
|
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
|
+
project = Bolt::Project.create_project(project_dir)
|
275
|
+
Bolt::Config.from_project(project, { log: { 'bolt-debug.log' => 'disable' } })
|
276
|
+
end
|
277
|
+
|
278
|
+
def in_bolt_project(versioned_project)
|
268
279
|
@pal_mutex.synchronize do
|
269
|
-
|
270
|
-
bolt_config = Bolt::Config.from_project(project, { log: { 'bolt-debug.log' => 'disable' } })
|
280
|
+
bolt_config = config_from_project(versioned_project)
|
271
281
|
modulepath_object = Bolt::Config::Modulepath.new(
|
272
282
|
bolt_config.modulepath,
|
273
283
|
boltlib_path: [PE_BOLTLIB_PATH, Bolt::Config::Modulepath::BOLTLIB_PATH]
|
@@ -278,8 +288,6 @@ module BoltServer
|
|
278
288
|
config: bolt_config
|
279
289
|
}
|
280
290
|
yield context
|
281
|
-
rescue Bolt::Error => e
|
282
|
-
[400, e.to_json]
|
283
291
|
end
|
284
292
|
end
|
285
293
|
|
@@ -506,13 +514,16 @@ module BoltServer
|
|
506
514
|
|
507
515
|
# Fetches the metadata for a single plan
|
508
516
|
#
|
509
|
-
# @param
|
517
|
+
# @param versioned_project [String] the project to fetch the plan from
|
510
518
|
get '/project_plans/:module_name/:plan_name' do
|
511
|
-
|
519
|
+
return MISSING_VERSIONED_PROJECT_RESPONSE if params['versioned_project'].nil?
|
520
|
+
in_bolt_project(params['versioned_project']) do |context|
|
512
521
|
plan_info = pe_plan_info(context[:pal], params[:module_name], params[:plan_name])
|
513
522
|
plan_info = allowed_helper(plan_info, context[:config].project.plans)
|
514
523
|
[200, plan_info.to_json]
|
515
524
|
end
|
525
|
+
rescue Bolt::Error => e
|
526
|
+
[400, e.to_json]
|
516
527
|
end
|
517
528
|
|
518
529
|
# Fetches the metadata for a single task
|
@@ -530,16 +541,19 @@ module BoltServer
|
|
530
541
|
|
531
542
|
# Fetches the metadata for a single task
|
532
543
|
#
|
533
|
-
# @param
|
544
|
+
# @param bolt_versioned_project [String] the reference to the bolt-project directory to load task metadata from
|
534
545
|
get '/project_tasks/:module_name/:task_name' do
|
535
|
-
|
546
|
+
return MISSING_VERSIONED_PROJECT_RESPONSE if params['versioned_project'].nil?
|
547
|
+
in_bolt_project(params['versioned_project']) do |context|
|
536
548
|
ps_parameters = {
|
537
|
-
'
|
549
|
+
'versioned_project' => params['versioned_project']
|
538
550
|
}
|
539
551
|
task_info = pe_task_info(context[:pal], params[:module_name], params[:task_name], ps_parameters)
|
540
552
|
task_info = allowed_helper(task_info, context[:config].project.tasks)
|
541
553
|
[200, task_info.to_json]
|
542
554
|
end
|
555
|
+
rescue Bolt::Error => e
|
556
|
+
[400, e.to_json]
|
543
557
|
end
|
544
558
|
|
545
559
|
# Fetches the list of plans for an environment, optionally fetching all metadata for each plan
|
@@ -568,9 +582,10 @@ module BoltServer
|
|
568
582
|
|
569
583
|
# Fetches the list of plans for a project
|
570
584
|
#
|
571
|
-
# @param
|
585
|
+
# @param versioned_project [String] the project to fetch the list of plans from
|
572
586
|
get '/project_plans' do
|
573
|
-
|
587
|
+
return MISSING_VERSIONED_PROJECT_RESPONSE if params['versioned_project'].nil?
|
588
|
+
in_bolt_project(params['versioned_project']) do |context|
|
574
589
|
plans_response = plan_list(context[:pal])
|
575
590
|
|
576
591
|
# Dig in context for the allowlist of plans from project object
|
@@ -582,6 +597,8 @@ module BoltServer
|
|
582
597
|
# to bolt-server smaller/simpler.
|
583
598
|
[200, plans_response.to_json]
|
584
599
|
end
|
600
|
+
rescue Bolt::Error => e
|
601
|
+
[400, e.to_json]
|
585
602
|
end
|
586
603
|
|
587
604
|
# Fetches the list of tasks for an environment
|
@@ -601,9 +618,10 @@ module BoltServer
|
|
601
618
|
|
602
619
|
# Fetches the list of tasks for a bolt-project
|
603
620
|
#
|
604
|
-
# @param
|
621
|
+
# @param versioned_project [String] the project to fetch the list of tasks from
|
605
622
|
get '/project_tasks' do
|
606
|
-
|
623
|
+
return MISSING_VERSIONED_PROJECT_RESPONSE if params['versioned_project'].nil?
|
624
|
+
in_bolt_project(params['versioned_project']) do |context|
|
607
625
|
tasks_response = task_list(context[:pal])
|
608
626
|
|
609
627
|
# Dig in context for the allowlist of tasks from project object
|
@@ -615,28 +633,69 @@ module BoltServer
|
|
615
633
|
# to bolt-server smaller/simpler.
|
616
634
|
[200, tasks_response.to_json]
|
617
635
|
end
|
636
|
+
rescue Bolt::Error => e
|
637
|
+
[400, e.to_json]
|
618
638
|
end
|
619
639
|
|
620
640
|
# Implements puppetserver's file_metadatas endpoint for projects.
|
621
641
|
#
|
622
|
-
# @param
|
642
|
+
# @param versioned_project [String] the versioned_project to fetch the file metadatas from
|
623
643
|
get '/project_file_metadatas/:module_name/*' do
|
624
|
-
|
644
|
+
return MISSING_VERSIONED_PROJECT_RESPONSE if params['versioned_project'].nil?
|
645
|
+
in_bolt_project(params['versioned_project']) do |context|
|
625
646
|
file = params[:splat].first
|
626
647
|
metadatas = file_metadatas(context[:pal], params[:module_name], file)
|
627
648
|
[200, metadatas.to_json]
|
628
649
|
end
|
650
|
+
rescue Bolt::Error => e
|
651
|
+
[400, e.to_json]
|
629
652
|
rescue ArgumentError => e
|
630
653
|
[400, e.message]
|
631
654
|
end
|
632
655
|
|
656
|
+
# Returns a list of targets parsed from a Project inventory
|
657
|
+
#
|
658
|
+
# @param versioned_project [String] the versioned_project to compute the inventory from
|
659
|
+
post '/project_inventory_targets' do
|
660
|
+
return MISSING_VERSIONED_PROJECT_RESPONSE if params['versioned_project'].nil?
|
661
|
+
content_type :json
|
662
|
+
body = JSON.parse(request.body.read)
|
663
|
+
error = validate_schema(@schemas["connect-data"], body)
|
664
|
+
return [400, error_result(error).to_json] unless error.nil?
|
665
|
+
in_bolt_project(params['versioned_project']) do |context|
|
666
|
+
if context[:config].inventoryfile &&
|
667
|
+
context[:config].project.inventory_file.to_s !=
|
668
|
+
context[:config].inventoryfile
|
669
|
+
raise Bolt::ValidationError, "Project inventory must be defined in the " \
|
670
|
+
"inventory.yaml file at the root of the project directory"
|
671
|
+
end
|
672
|
+
|
673
|
+
Bolt::Util.validate_file('inventory file', context[:config].project.inventory_file)
|
674
|
+
|
675
|
+
begin
|
676
|
+
connect_plugin = BoltServer::Plugin::PuppetConnectData.new(body['puppet_connect_data'])
|
677
|
+
plugins = Bolt::Plugin.setup(context[:config], context[:pal], load_plugins: false)
|
678
|
+
plugins.add_plugin(connect_plugin)
|
679
|
+
inventory = Bolt::Inventory.from_config(context[:config], plugins)
|
680
|
+
target_list = inventory.get_targets('all').map { |targ| targ.to_h.merge({ 'transport' => targ.transport }) }
|
681
|
+
rescue Bolt::Plugin::PluginError::LoadingDisabled => e
|
682
|
+
msg = "Cannot load plugin #{e.details['plugin_name']}: plugin not supported"
|
683
|
+
raise BoltServer::Plugin::PluginNotSupported.new(msg, e.details['plugin_name'])
|
684
|
+
end
|
685
|
+
|
686
|
+
[200, target_list.to_json]
|
687
|
+
end
|
688
|
+
rescue Bolt::Error => e
|
689
|
+
[500, e.to_json]
|
690
|
+
end
|
691
|
+
|
633
692
|
error 404 do
|
634
693
|
err = Bolt::Error.new("Could not find route #{request.path}",
|
635
694
|
'boltserver/not-found')
|
636
695
|
[404, err.to_json]
|
637
696
|
end
|
638
697
|
|
639
|
-
error
|
698
|
+
error StandardError do
|
640
699
|
e = env['sinatra.error']
|
641
700
|
err = Bolt::Error.new("500: Unknown error: #{e.message}",
|
642
701
|
'boltserver/server-error')
|