bolt 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bolt might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/bolt/cli.rb +43 -43
- data/lib/bolt/config.rb +25 -5
- data/lib/bolt/node.rb +3 -1
- data/lib/bolt/node/ssh.rb +15 -2
- data/lib/bolt/node/winrm.rb +20 -9
- data/lib/bolt/version.rb +1 -1
- data/modules/boltlib/lib/puppet/functions/run_plan.rb +1 -1
- data/modules/boltlib/lib/puppet/functions/run_task.rb +29 -32
- data/vendored/puppet/lib/puppet.rb +2 -5
- data/vendored/puppet/lib/puppet/application.rb +18 -1
- data/vendored/puppet/lib/puppet/application/agent.rb +8 -1
- data/vendored/puppet/lib/puppet/application/config.rb +1 -0
- data/vendored/puppet/lib/puppet/application/device.rb +1 -2
- data/vendored/puppet/lib/puppet/application/filebucket.rb +10 -2
- data/vendored/puppet/lib/puppet/application/help.rb +1 -0
- data/vendored/puppet/lib/puppet/application_support.rb +6 -1
- data/vendored/puppet/lib/puppet/configurer.rb +8 -3
- data/vendored/puppet/lib/puppet/defaults.rb +29 -9
- data/vendored/puppet/lib/puppet/environments.rb +2 -0
- data/vendored/puppet/lib/puppet/face/config.rb +14 -1
- data/vendored/puppet/lib/puppet/face/module/list.rb +1 -1
- data/vendored/puppet/lib/puppet/face/module/search.rb +4 -1
- data/vendored/puppet/lib/puppet/forge.rb +6 -0
- data/vendored/puppet/lib/puppet/functions/convert_to.rb +32 -0
- data/vendored/puppet/lib/puppet/gettext/config.rb +135 -37
- data/vendored/puppet/lib/puppet/gettext/module_translations.rb +42 -0
- data/vendored/puppet/lib/puppet/indirector/catalog/compiler.rb +2 -0
- data/vendored/puppet/lib/puppet/module.rb +10 -18
- data/vendored/puppet/lib/puppet/network/http/factory.rb +9 -0
- data/vendored/puppet/lib/puppet/node/environment.rb +14 -0
- data/vendored/puppet/lib/puppet/parser/functions/sprintf.rb +17 -3
- data/vendored/puppet/lib/puppet/parser/scope.rb +11 -0
- data/vendored/puppet/lib/puppet/pops.rb +0 -1
- data/vendored/puppet/lib/puppet/pops/evaluator/epp_evaluator.rb +13 -0
- data/vendored/puppet/lib/puppet/pops/loader/loader_paths.rb +39 -5
- data/vendored/puppet/lib/puppet/pops/loader/module_loaders.rb +64 -24
- data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/loader/task_instantiator.rb +21 -70
- data/vendored/puppet/lib/puppet/pops/lookup/hiera_config.rb +2 -2
- data/vendored/puppet/lib/puppet/pops/parser/parser_support.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/pcore.rb +43 -1
- data/vendored/puppet/lib/puppet/pops/types/type_factory.rb +4 -0
- data/vendored/puppet/lib/puppet/pops/types/types.rb +25 -5
- data/vendored/puppet/lib/puppet/provider/selmodule/semodule.rb +5 -3
- data/vendored/puppet/lib/puppet/provider/service/smf.rb +2 -0
- data/vendored/puppet/lib/puppet/settings/environment_conf.rb +14 -2
- data/vendored/puppet/lib/puppet/ssl/certificate_authority.rb +1 -1
- data/vendored/puppet/lib/puppet/ssl/certificate_signer.rb +6 -0
- data/vendored/puppet/lib/puppet/ssl/host.rb +1 -1
- data/vendored/puppet/lib/puppet/type/file/checksum.rb +1 -1
- data/vendored/puppet/lib/puppet/type/file/checksum_value.rb +4 -3
- data/vendored/puppet/lib/puppet/type/k5login.rb +101 -0
- data/vendored/puppet/lib/puppet/type/tidy.rb +4 -2
- data/vendored/puppet/lib/puppet/util/checksums.rb +82 -1
- data/vendored/puppet/lib/puppet/util/command_line.rb +5 -0
- data/vendored/puppet/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet.rb +5 -1
- data/vendored/puppet/lib/puppet_pal.rb +272 -11
- data/vendored/require_vendored.rb +0 -6
- metadata +8 -8
- data/vendored/puppet/lib/puppet/bindings.rb +0 -147
- data/vendored/puppet/lib/puppet/pops/types/task.rb +0 -116
@@ -260,8 +260,10 @@ Puppet::Type.newtype(:tidy) do
|
|
260
260
|
end
|
261
261
|
found_files = files.find_all { |path| tidy?(path) }.collect { |path| mkfile(path) }
|
262
262
|
result = found_files.each { |file| debug "Tidying #{file.ref}" }.sort { |a,b| b[:path] <=> a[:path] }
|
263
|
-
|
264
|
-
|
263
|
+
if found_files.size > 0
|
264
|
+
#TRANSLATORS "Tidy" is a program name and should not be translated
|
265
|
+
notice _("Tidying %{count} files") % { count: found_files.size }
|
266
|
+
end
|
265
267
|
|
266
268
|
# No need to worry about relationships if we don't have rmdirs; there won't be
|
267
269
|
# any directories.
|
@@ -10,7 +10,7 @@ module Puppet::Util::Checksums
|
|
10
10
|
# It's not a good idea to use some of these in some contexts: for example, I
|
11
11
|
# wouldn't try bucketing a file using the :none checksum type.
|
12
12
|
def known_checksum_types
|
13
|
-
[:sha256, :sha256lite, :md5, :md5lite, :sha1, :sha1lite,
|
13
|
+
[:sha256, :sha256lite, :md5, :md5lite, :sha1, :sha1lite, :sha512, :sha384, :sha224,
|
14
14
|
:mtime, :ctime, :none]
|
15
15
|
end
|
16
16
|
|
@@ -83,6 +83,87 @@ module Puppet::Util::Checksums
|
|
83
83
|
sha256_hex_length
|
84
84
|
end
|
85
85
|
|
86
|
+
# Calculate a checksum using Digest::SHA384.
|
87
|
+
def sha384(content)
|
88
|
+
require 'digest/sha2'
|
89
|
+
Digest::SHA384.hexdigest(content)
|
90
|
+
end
|
91
|
+
|
92
|
+
def sha384?(string)
|
93
|
+
string =~ /^\h{96}$/
|
94
|
+
end
|
95
|
+
|
96
|
+
def sha384_file(filename, lite = false)
|
97
|
+
require 'digest/sha2'
|
98
|
+
|
99
|
+
digest = Digest::SHA384.new
|
100
|
+
checksum_file(digest, filename, lite)
|
101
|
+
end
|
102
|
+
|
103
|
+
def sha384_stream(lite = false, &block)
|
104
|
+
require 'digest/sha2'
|
105
|
+
digest = Digest::SHA384.new
|
106
|
+
checksum_stream(digest, block, lite)
|
107
|
+
end
|
108
|
+
|
109
|
+
def sha384_hex_length
|
110
|
+
96
|
111
|
+
end
|
112
|
+
|
113
|
+
# Calculate a checksum using Digest::SHA512.
|
114
|
+
def sha512(content)
|
115
|
+
require 'digest/sha2'
|
116
|
+
Digest::SHA512.hexdigest(content)
|
117
|
+
end
|
118
|
+
|
119
|
+
def sha512?(string)
|
120
|
+
string =~ /^\h{128}$/
|
121
|
+
end
|
122
|
+
|
123
|
+
def sha512_file(filename, lite = false)
|
124
|
+
require 'digest/sha2'
|
125
|
+
|
126
|
+
digest = Digest::SHA512.new
|
127
|
+
checksum_file(digest, filename, lite)
|
128
|
+
end
|
129
|
+
|
130
|
+
def sha512_stream(lite = false, &block)
|
131
|
+
require 'digest/sha2'
|
132
|
+
digest = Digest::SHA512.new
|
133
|
+
checksum_stream(digest, block, lite)
|
134
|
+
end
|
135
|
+
|
136
|
+
def sha512_hex_length
|
137
|
+
128
|
138
|
+
end
|
139
|
+
|
140
|
+
# Calculate a checksum using Digest::SHA224.
|
141
|
+
def sha224(content)
|
142
|
+
require 'openssl'
|
143
|
+
OpenSSL::Digest::SHA224.new.hexdigest(content)
|
144
|
+
end
|
145
|
+
|
146
|
+
def sha224?(string)
|
147
|
+
string =~ /^\h{56}$/
|
148
|
+
end
|
149
|
+
|
150
|
+
def sha224_file(filename, lite = false)
|
151
|
+
require 'openssl'
|
152
|
+
|
153
|
+
digest = OpenSSL::Digest::SHA224.new
|
154
|
+
checksum_file(digest, filename, lite)
|
155
|
+
end
|
156
|
+
|
157
|
+
def sha224_stream(lite = false, &block)
|
158
|
+
require 'openssl'
|
159
|
+
digest = OpenSSL::Digest::SHA224.new
|
160
|
+
checksum_stream(digest, block, lite)
|
161
|
+
end
|
162
|
+
|
163
|
+
def sha224_hex_length
|
164
|
+
56
|
165
|
+
end
|
166
|
+
|
86
167
|
# Calculate a checksum using Digest::MD5.
|
87
168
|
def md5(content)
|
88
169
|
Digest::MD5.hexdigest(content)
|
@@ -14,6 +14,7 @@ require 'puppet/util'
|
|
14
14
|
require "puppet/util/rubygems"
|
15
15
|
require "puppet/util/limits"
|
16
16
|
require 'puppet/util/colors'
|
17
|
+
require 'puppet/gettext/module_translations'
|
17
18
|
|
18
19
|
module Puppet
|
19
20
|
module Util
|
@@ -122,6 +123,10 @@ module Puppet
|
|
122
123
|
$LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
|
123
124
|
end
|
124
125
|
|
126
|
+
Puppet::GettextConfig.reset_text_domain('cli')
|
127
|
+
Puppet::ModuleTranslations.load_from_modulepath(configured_environment.modules)
|
128
|
+
Puppet::ModuleTranslations.load_from_vardir(Puppet[:vardir])
|
129
|
+
|
125
130
|
# Puppet requires Facter, which initializes its lookup paths. Reset Facter to
|
126
131
|
# pickup the new $LOAD_PATH.
|
127
132
|
Facter.reset
|
@@ -1,5 +1,9 @@
|
|
1
1
|
module SemanticPuppet
|
2
|
-
|
2
|
+
locales_path = File.absolute_path('../locales', File.dirname(__FILE__))
|
3
|
+
# Only create a translation repository of the relevant translations exist
|
4
|
+
if Puppet::FileSystem.exist?(File.join(locales_path, Puppet::GettextConfig.current_locale))
|
5
|
+
Puppet::GettextConfig.load_translations('semantic_puppet', locales_path, :po)
|
6
|
+
end
|
3
7
|
|
4
8
|
autoload :Version, 'semantic_puppet/version'
|
5
9
|
autoload :VersionRange, 'semantic_puppet/version_range'
|
@@ -26,8 +26,9 @@ require 'puppet/parser/script_compiler'
|
|
26
26
|
module Puppet
|
27
27
|
module Pal
|
28
28
|
|
29
|
-
#
|
30
|
-
|
29
|
+
# A configured compiler as obtained in the callback from `with_script_compiler`.
|
30
|
+
# (Later, there may also be a catalog compiler available.)
|
31
|
+
#
|
31
32
|
class Compiler
|
32
33
|
attr_reader :internal_compiler
|
33
34
|
protected :internal_compiler
|
@@ -53,17 +54,51 @@ module Pal
|
|
53
54
|
internal_evaluator.evaluator.external_call_function(function_name, args, topscope, &block)
|
54
55
|
end
|
55
56
|
|
56
|
-
# Returns
|
57
|
+
# Returns a Puppet::Pal::FunctionSignature object or nil if function is not found
|
58
|
+
# The returned FunctionSignature has information about all overloaded signatures of the function
|
59
|
+
#
|
60
|
+
# @example using function_signature
|
61
|
+
# # returns true if 'myfunc' is callable with three integer arguments 1, 2, 3
|
62
|
+
# compiler.function_signature('myfunc').callable_with?([1,2,3])
|
63
|
+
#
|
57
64
|
# @param function_name [String] the name of the function to get a signature for
|
58
|
-
# @return [
|
59
|
-
|
65
|
+
# @return [Puppet::Pal::FunctionSignature] a function signature, or nil if function not found
|
66
|
+
#
|
67
|
+
def function_signature(function_name)
|
60
68
|
loader = internal_compiler.loaders.private_environment_loader
|
61
69
|
if func = loader.load(:function, function_name)
|
62
|
-
|
63
|
-
return t.is_a?(Puppet::Pops::Types::PVariantType) ? t.types : [t]
|
70
|
+
return FunctionSignature.new(func.class)
|
64
71
|
end
|
65
72
|
# Could not find function
|
66
|
-
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns an array of TypedName objects for all functions, optionally filtered by a regular expression.
|
77
|
+
# The returned array has more information than just the leaf name - the typical thing is to just get
|
78
|
+
# the name as showing the following example.
|
79
|
+
#
|
80
|
+
# @example getting the names of all functions
|
81
|
+
# compiler.list_functions.map {|tn| tn.name }
|
82
|
+
#
|
83
|
+
# @param filter_regex [Regexp] an optional regexp that filters based on name (matching names are included in the result)
|
84
|
+
# @return [Array<Puppet::Pops::Loader::TypedName>] an array of typed names
|
85
|
+
#
|
86
|
+
def list_functions(filter_regex = nil)
|
87
|
+
list_loadable_kind(:function, filter_regex)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Returns an array of TypedName objects for all functions, optionally filtered by a regular expression.
|
91
|
+
# The returned array has more information than just the leaf name - the typical thing is to just get
|
92
|
+
# the name as showing the following example.
|
93
|
+
#
|
94
|
+
# @example getting the names of all functions
|
95
|
+
# compiler.list_functions.map {|tn| tn.name }
|
96
|
+
#
|
97
|
+
# @param filter_regex [Regexp] an optional regexp that filters based on name (matching names are included in the result)
|
98
|
+
# @return [Array<Puppet::Pops::Loader::TypedName>] an array of typed names
|
99
|
+
#
|
100
|
+
def list_functions(filter_regex = nil)
|
101
|
+
list_loadable_kind(:function, filter_regex)
|
67
102
|
end
|
68
103
|
|
69
104
|
# Evaluates a string of puppet language code in top scope.
|
@@ -191,6 +226,17 @@ module Pal
|
|
191
226
|
call_function('new', t, *arguments)
|
192
227
|
end
|
193
228
|
|
229
|
+
protected
|
230
|
+
|
231
|
+
def list_loadable_kind(kind, filter_regex = nil)
|
232
|
+
loader = internal_compiler.loaders.private_environment_loader
|
233
|
+
if filter_regex.nil?
|
234
|
+
loader.discover(kind)
|
235
|
+
else
|
236
|
+
loader.discover(kind) {|f| f.name =~ filter_regex }
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
194
240
|
private
|
195
241
|
|
196
242
|
def topscope
|
@@ -199,18 +245,230 @@ module Pal
|
|
199
245
|
end
|
200
246
|
|
201
247
|
class ScriptCompiler < Compiler
|
202
|
-
# Returns the signature
|
248
|
+
# Returns the signature of the given plan name
|
203
249
|
# @param plan_name [String] the name of the plan to get the signature of
|
204
|
-
# @return [Puppet::
|
250
|
+
# @return [Puppet::Pal::PlanSignature, nil] returns a PlanSignature, or nil if plan is not found
|
205
251
|
#
|
206
252
|
def plan_signature(plan_name)
|
207
253
|
loader = internal_compiler.loaders.private_environment_loader
|
208
254
|
if func = loader.load(:plan, plan_name)
|
209
|
-
return func
|
255
|
+
return PlanSignature.new(func)
|
210
256
|
end
|
211
257
|
# Could not find plan
|
212
258
|
nil
|
213
259
|
end
|
260
|
+
|
261
|
+
# Returns an array of TypedName objects for all plans, optionally filtered by a regular expression.
|
262
|
+
# The returned array has more information than just the leaf name - the typical thing is to just get
|
263
|
+
# the name as showing the following example.
|
264
|
+
#
|
265
|
+
# @example getting the names of all plans
|
266
|
+
# compiler.list_plans.map {|tn| tn.name }
|
267
|
+
#
|
268
|
+
# @param filter_regex [Regexp] an optional regexp that filters based on name (matching names are included in the result)
|
269
|
+
# @return [Array<Puppet::Pops::Loader::TypedName>] an array of typed names
|
270
|
+
#
|
271
|
+
def list_plans(filter_regex = nil)
|
272
|
+
list_loadable_kind(:plan, filter_regex)
|
273
|
+
end
|
274
|
+
|
275
|
+
# Returns the signature callable of the given task (the arguments it accepts, and the data type it returns)
|
276
|
+
# @param task_name [String] the name of the task to get the signature of
|
277
|
+
# @return [Puppet::Pal::TaskSignature, nil] returns a TaskSignature, or nil if task is not found
|
278
|
+
#
|
279
|
+
def task_signature(task_name)
|
280
|
+
loader = internal_compiler.loaders.private_environment_loader
|
281
|
+
if task = loader.load(:task, task_name)
|
282
|
+
return TaskSignature.new(task)
|
283
|
+
end
|
284
|
+
# Could not find task
|
285
|
+
nil
|
286
|
+
end
|
287
|
+
|
288
|
+
# Returns an array of TypedName objects for all tasks, optionally filtered by a regular expression.
|
289
|
+
# The returned array has more information than just the leaf name - the typical thing is to just get
|
290
|
+
# the name as showing the following example.
|
291
|
+
#
|
292
|
+
# @example getting the names of all tasks
|
293
|
+
# compiler.list_tasks.map {|tn| tn.name }
|
294
|
+
#
|
295
|
+
# @param filter_regex [Regexp] an optional regexp that filters based on name (matching names are included in the result)
|
296
|
+
# @return [Array<Puppet::Pops::Loader::TypedName>] an array of typed names
|
297
|
+
#
|
298
|
+
def list_tasks(filter_regex = nil)
|
299
|
+
list_loadable_kind(:task, filter_regex)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
# A FunctionSignature is returned from `function_signature`. Its purpose is to answer questions about the function's parameters
|
304
|
+
# and if it can be called with a set of parameters.
|
305
|
+
#
|
306
|
+
# It is also possible to get an array of puppet Callable data type where each callable describes one possible way
|
307
|
+
# the function can be called.
|
308
|
+
#
|
309
|
+
# @api public
|
310
|
+
#
|
311
|
+
class FunctionSignature
|
312
|
+
# @api private
|
313
|
+
def initialize(function_class)
|
314
|
+
@func = function_class
|
315
|
+
end
|
316
|
+
|
317
|
+
# Returns true if the function can be called with the given arguments and false otherwise.
|
318
|
+
# If the function is not callable, and a code block is given, it is given a formatted error message that describes
|
319
|
+
# the type mismatch. That error message can be quite complex if the function has multiple dispatch depending on
|
320
|
+
# given types.
|
321
|
+
#
|
322
|
+
# @param args [Array] The arguments as given to the function call
|
323
|
+
# @param callable [Proc, nil] An optional ruby Proc or puppet lambda given to the function
|
324
|
+
# @yield [String] a formatted error message describing a type mismatch if the function is not callable with given args + block
|
325
|
+
# @return [Boolean] true if the function can be called with given args + block, and false otherwise
|
326
|
+
# @api public
|
327
|
+
#
|
328
|
+
def callable_with?(args, callable=nil)
|
329
|
+
signatures = @func.dispatcher.to_type
|
330
|
+
callables = signatures.is_a?(Puppet::Pops::Types::PVariantType) ? signatures.types : [signatures]
|
331
|
+
|
332
|
+
return true if callables.any? {|t| t.callable_with?(args) }
|
333
|
+
return false unless block_given?
|
334
|
+
args_type = Puppet::Pops::Types::TypeCalculator.singleton.infer_set(callable.nil? ? args : args + [callable])
|
335
|
+
error_message = Puppet::Pops::Types::TypeMismatchDescriber.describe_signatures(@func.name, @func.signatures, args_type)
|
336
|
+
yield error_message
|
337
|
+
false
|
338
|
+
end
|
339
|
+
|
340
|
+
# Returns an array of Callable puppet data type
|
341
|
+
# @return [Array<Puppet::Pops::Types::PCallableType] one callable per way the function can be called
|
342
|
+
#
|
343
|
+
# @api public
|
344
|
+
#
|
345
|
+
def callables
|
346
|
+
signatures = @func.dispatcher.to_type
|
347
|
+
signatures.is_a?(Puppet::Pops::Types::PVariantType) ? signatures.types : [signatures]
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
# A TaskSignature is returned from `task_signature`. Its purpose is to answer questions about the task's parameters
|
352
|
+
# and if it can be run/called with a hash of named parameters.
|
353
|
+
#
|
354
|
+
class TaskSignature
|
355
|
+
def initialize(task)
|
356
|
+
@task = task
|
357
|
+
end
|
358
|
+
|
359
|
+
# Returns whether or not the given arguments are acceptable when running the task.
|
360
|
+
# In addition to returning the boolean outcome, if a block is given, it is called with a string of formatted
|
361
|
+
# error messages that describes the difference between what was given and what is expected. The error message may
|
362
|
+
# have multiple lines of text, and each line is indented one space.
|
363
|
+
#
|
364
|
+
# @param args_hash [Hash] a hash mapping parameter names to argument values
|
365
|
+
# @yieldparam [String] a formatted error message if a type mismatch occurs that explains the mismatch
|
366
|
+
# @return [Boolean] if the given arguments are acceptable when running the task
|
367
|
+
#
|
368
|
+
def runnable_with?(args_hash)
|
369
|
+
params = @task.parameters
|
370
|
+
params_type = if params.nil?
|
371
|
+
T_GENERIC_TASK_HASH
|
372
|
+
else
|
373
|
+
key_to_type = {}
|
374
|
+
@task.parameters.each_pair { |k, v| key_to_type[k] = v['type'] }
|
375
|
+
Puppet::Pops::Types::TypeFactory.struct(key_to_type)
|
376
|
+
end
|
377
|
+
return true if params_type.instance?(args_hash)
|
378
|
+
|
379
|
+
if block_given?
|
380
|
+
tm = Puppet::Pops::Types::TypeMismatchDescriber.singleton
|
381
|
+
error = if params.nil?
|
382
|
+
tm.describe_mismatch('', params_type, Puppet::Pops::Types::TypeCalculator.infer_set(args_hash))
|
383
|
+
else
|
384
|
+
tm.describe_struct_signature(params_type, args_hash).flatten.map {|e| e.format }.join("\n")
|
385
|
+
end
|
386
|
+
yield "Task #{@task.name}:\n#{error}"
|
387
|
+
end
|
388
|
+
false
|
389
|
+
end
|
390
|
+
|
391
|
+
# Returns the Task instance as a hash
|
392
|
+
#
|
393
|
+
# @return [Hash{String=>Object}] the hash representation of the task
|
394
|
+
def task_hash
|
395
|
+
@task._pcore_init_hash
|
396
|
+
end
|
397
|
+
|
398
|
+
# Returns the Task instance which can be further explored. It contains all meta-data defined for
|
399
|
+
# the task such as the description, parameters, output, etc.
|
400
|
+
#
|
401
|
+
# @return [Puppet::Pops::Types::PuppetObject] An instance of a dynamically created Task class
|
402
|
+
def task
|
403
|
+
@task
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
# A PlanSignature is returned from `plan_signature`. Its purpose is to answer questions about the plans's parameters
|
408
|
+
# and if it can be called with a hash of named parameters.
|
409
|
+
#
|
410
|
+
# @api public
|
411
|
+
#
|
412
|
+
class PlanSignature
|
413
|
+
def initialize(plan_function)
|
414
|
+
@plan_func = plan_function
|
415
|
+
end
|
416
|
+
|
417
|
+
# Returns true or false depending on if the given PlanSignature is callable with a set of named arguments or not
|
418
|
+
# In addition to returning the boolean outcome, if a block is given, it is called with a string of formatted
|
419
|
+
# error messages that describes the difference between what was given and what is expected. The error message may
|
420
|
+
# have multiple lines of text, and each line is indented one space.
|
421
|
+
#
|
422
|
+
# @example Checking if signature is acceptable
|
423
|
+
#
|
424
|
+
# signature = pal.plan_signature('myplan')
|
425
|
+
# signature.callable_with?({x => 10}) { |errors| raise ArgumentError("Ooops: given arguments does not match\n#{errors}") }
|
426
|
+
#
|
427
|
+
# @api public
|
428
|
+
#
|
429
|
+
def callable_with?(args_hash)
|
430
|
+
dispatcher = @plan_func.class.dispatcher.dispatchers[0]
|
431
|
+
|
432
|
+
param_scope = {}
|
433
|
+
# Assign all non-nil values, even those that represent non-existent parameters.
|
434
|
+
args_hash.each { |k, v| param_scope[k] = v unless v.nil? }
|
435
|
+
dispatcher.parameters.each do |p|
|
436
|
+
name = p.name
|
437
|
+
arg = args_hash[name]
|
438
|
+
if arg.nil?
|
439
|
+
# Arg either wasn't given, or it was undef
|
440
|
+
if p.value.nil?
|
441
|
+
# No default. Assign nil if the args_hash included it
|
442
|
+
param_scope[name] = nil if args_hash.include?(name)
|
443
|
+
else
|
444
|
+
# parameter does not have a default value, it will be assigned its default when being called
|
445
|
+
# we assume that the default value is of the correct type and therefore simply skip
|
446
|
+
# checking this
|
447
|
+
# param_scope[name] = param_scope.evaluate(name, p.value, closure_scope, @evaluator)
|
448
|
+
end
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
errors = Puppet::Pops::Types::TypeMismatchDescriber.singleton.describe_struct_signature(dispatcher.params_struct, param_scope).flatten
|
453
|
+
return true if errors.empty?
|
454
|
+
if block_given?
|
455
|
+
yield errors.map {|e| e.format }.join("\n")
|
456
|
+
end
|
457
|
+
false
|
458
|
+
end
|
459
|
+
|
460
|
+
# Returns a PStructType describing the parameters as a puppet Struct data type
|
461
|
+
# Note that a `to_s` on the returned structure will result in a human readable Struct datatype as a
|
462
|
+
# description of what a plan expects.
|
463
|
+
#
|
464
|
+
# @return [Puppet::Pops::Types::PStructType] a struct data type describing the parameters and their types
|
465
|
+
#
|
466
|
+
# @api public
|
467
|
+
#
|
468
|
+
def params_type
|
469
|
+
dispatcher = @plan_func.class.dispatcher.dispatchers[0]
|
470
|
+
dispatcher.params_struct
|
471
|
+
end
|
214
472
|
end
|
215
473
|
|
216
474
|
# Defines a context in which multiple operations in an env with a script compiler can be performed in a given block.
|
@@ -571,6 +829,9 @@ module Pal
|
|
571
829
|
T_ANY_ARRAY = Puppet::Pops::Types::TypeFactory.array_of_any
|
572
830
|
T_BOOLEAN = Puppet::Pops::Types::PBooleanType::DEFAULT
|
573
831
|
|
832
|
+
T_GENERIC_TASK_HASH = Puppet::Pops::Types::TypeFactory.hash_kv(
|
833
|
+
Puppet::Pops::Types::TypeFactory.pattern(/\A[a-z][a-z0-9_]*\z/), Puppet::Pops::Types::TypeFactory.data)
|
834
|
+
|
574
835
|
def self.assert_type(type, value, what, allow_nil=false)
|
575
836
|
Puppet::Pops::Types::TypeAsserter.assert_instance_of(nil, type, value, allow_nil) { _('Puppet Pal: %{what}') % {what: what} }
|
576
837
|
end
|