puppet 4.3.1 → 4.3.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ext/build_defaults.yaml +1 -1
- data/lib/hiera/scope.rb +1 -1
- data/lib/puppet/application/lookup.rb +41 -43
- data/lib/puppet/data_providers/lookup_adapter.rb +73 -26
- data/lib/puppet/functions/lookup.rb +126 -150
- data/lib/puppet/functions/match.rb +1 -0
- data/lib/puppet/indirector/hiera.rb +3 -1
- data/lib/puppet/indirector/indirection.rb +6 -2
- data/lib/puppet/indirector/json.rb +2 -2
- data/lib/puppet/module.rb +3 -2
- data/lib/puppet/node.rb +11 -2
- data/lib/puppet/parser/compiler.rb +1 -8
- data/lib/puppet/parser/functions/lookup.rb +128 -149
- data/lib/puppet/parser/functions/match.rb +1 -0
- data/lib/puppet/plugins/data_providers/data_provider.rb +3 -2
- data/lib/puppet/pops/adapters.rb +43 -0
- data/lib/puppet/pops/evaluator/access_operator.rb +3 -3
- data/lib/puppet/pops/evaluator/closure.rb +51 -51
- data/lib/puppet/pops/evaluator/collector_transformer.rb +16 -0
- data/lib/puppet/pops/evaluator/runtime3_support.rb +11 -2
- data/lib/puppet/pops/functions/function.rb +6 -2
- data/lib/puppet/pops/issues.rb +16 -0
- data/lib/puppet/pops/loader/puppet_function_instantiator.rb +3 -2
- data/lib/puppet/pops/lookup.rb +3 -0
- data/lib/puppet/pops/lookup/explainer.rb +73 -3
- data/lib/puppet/pops/lookup/invocation.rb +21 -19
- data/lib/puppet/pops/model/factory.rb +153 -155
- data/lib/puppet/pops/model/model.rb +9 -0
- data/lib/puppet/pops/model/model_label_provider.rb +1 -0
- data/lib/puppet/pops/parser/evaluating_parser.rb +3 -3
- data/lib/puppet/pops/parser/lexer2.rb +411 -393
- data/lib/puppet/pops/parser/slurp_support.rb +5 -1
- data/lib/puppet/pops/types/type_calculator.rb +2 -6
- data/lib/puppet/pops/types/types.rb +3 -9
- data/lib/puppet/pops/validation/checker4_0.rb +36 -12
- data/lib/puppet/provider/group/windows_adsi.rb +2 -2
- data/lib/puppet/provider/package/pip.rb +11 -1
- data/lib/puppet/provider/package/rpm.rb +0 -1
- data/lib/puppet/provider/package/yum.rb +1 -1
- data/lib/puppet/provider/service/debian.rb +5 -18
- data/lib/puppet/provider/service/init.rb +7 -0
- data/lib/puppet/provider/service/launchd.rb +6 -0
- data/lib/puppet/provider/service/systemd.rb +1 -1
- data/lib/puppet/provider/user/windows_adsi.rb +2 -2
- data/lib/puppet/provider/yumrepo/inifile.rb +6 -3
- data/lib/puppet/resource/type.rb +2 -1
- data/lib/puppet/transaction/additional_resource_generator.rb +17 -3
- data/lib/puppet/type/group.rb +6 -2
- data/lib/puppet/util/windows.rb +4 -0
- data/lib/puppet/util/windows/adsi.rb +61 -24
- data/lib/puppet/util/windows/principal.rb +181 -0
- data/lib/puppet/util/windows/registry.rb +21 -15
- data/lib/puppet/util/windows/sid.rb +42 -11
- data/lib/puppet/version.rb +1 -1
- data/spec/fixtures/unit/application/environments/production/data/common.yaml +4 -0
- data/spec/fixtures/unit/application/environments/production/manifests/site.pp +1 -0
- data/spec/fixtures/unit/application/environments/puppet_func_provider/environment.conf +1 -0
- data/spec/fixtures/unit/application/environments/puppet_func_provider/functions/data.pp +10 -0
- data/spec/fixtures/unit/application/environments/puppet_func_provider/manifests/site.pp +1 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_module_config/data/common.yaml +4 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_module_config/data/specific.yaml +4 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_module_config/hiera.yaml +7 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_modules/data/common.yaml +4 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_modules/data/specific.yaml +4 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_modules/environment.conf +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_modules/hiera.yaml +7 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_modules/manifests/site.pp +1 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/one/data/common.yaml +6 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/one/hiera.yaml +5 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/one/manifests/init.pp +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/one/metadata.json +9 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/two/data/common.yaml +4 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/two/hiera.yaml +5 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/two/manifests/init.pp +3 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/two/metadata.json +9 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/functions/usee_puppet.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/{usee → modules/usee}/lib/puppet/functions/usee/callee.rb +0 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/lib/puppet/functions/usee/usee_ruby.rb +6 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/manifests/init.pp +6 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee2/lib/puppet/functions/usee2/callee.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/functions/puppet_calling_puppet.pp +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/functions/puppet_calling_puppet_init.pp +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/functions/puppet_calling_ruby.pp +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/{user → modules/user}/lib/puppet/functions/user/caller.rb +0 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/lib/puppet/functions/user/caller2.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/lib/puppet/functions/user/ruby_calling_puppet.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/lib/puppet/functions/user/ruby_calling_puppet_init.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/lib/puppet/functions/user/ruby_calling_ruby.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/manifests/init.pp +81 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/{user → modules/user}/metadata.json +2 -1
- data/spec/integration/parser/collection_spec.rb +8 -0
- data/spec/integration/util/windows/principal_spec.rb +115 -0
- data/spec/{unit → integration}/util/windows/registry_spec.rb +91 -1
- data/spec/integration/util/windows/security_spec.rb +2 -2
- data/spec/unit/application/lookup_spec.rb +138 -28
- data/spec/unit/data_providers/hiera_data_provider_spec.rb +182 -5
- data/spec/unit/face/epp_face_spec.rb +2 -2
- data/spec/unit/functions/epp_spec.rb +6 -6
- data/spec/unit/functions/inline_epp_spec.rb +4 -4
- data/spec/unit/functions/lookup_spec.rb +30 -3
- data/spec/unit/functions4_spec.rb +1 -1
- data/spec/unit/hiera/scope_spec.rb +5 -2
- data/spec/unit/indirector/json_spec.rb +1 -1
- data/spec/unit/node_spec.rb +8 -0
- data/spec/unit/parser/compiler_spec.rb +0 -18
- data/spec/unit/pops/evaluator/access_ops_spec.rb +4 -4
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +1 -1
- data/spec/unit/pops/loaders/loaders_spec.rb +84 -2
- data/spec/unit/pops/parser/lexer2_spec.rb +6 -0
- data/spec/unit/pops/parser/parser_rspec_helper.rb +5 -0
- data/spec/unit/pops/types/type_calculator_spec.rb +0 -17
- data/spec/unit/pops/validator/validator_spec.rb +87 -0
- data/spec/unit/provider/group/windows_adsi_spec.rb +8 -8
- data/spec/unit/provider/package/pip_spec.rb +41 -13
- data/spec/unit/provider/package/rpm_spec.rb +2 -25
- data/spec/unit/provider/package/yum_spec.rb +1 -1
- data/spec/unit/provider/service/debian_spec.rb +6 -24
- data/spec/unit/provider/service/init_spec.rb +11 -1
- data/spec/unit/provider/service/launchd_spec.rb +11 -0
- data/spec/unit/provider/service/systemd_spec.rb +18 -12
- data/spec/unit/provider/service/upstart_spec.rb +57 -0
- data/spec/unit/provider/user/windows_adsi_spec.rb +5 -5
- data/spec/unit/provider/yumrepo/inifile_spec.rb +16 -0
- data/spec/unit/resource_spec.rb +12 -2
- data/spec/unit/util/windows/adsi_spec.rb +44 -36
- data/spec/unit/util/windows/sid_spec.rb +47 -10
- metadata +77 -10
data/lib/puppet/pops/adapters.rb
CHANGED
@@ -23,6 +23,7 @@ module Puppet::Pops::Adapters
|
|
23
23
|
#
|
24
24
|
class SourcePosAdapter < Puppet::Pops::Adaptable::Adapter
|
25
25
|
attr_accessor :locator
|
26
|
+
attr_reader :adapted
|
26
27
|
|
27
28
|
def self.create_adapter(o)
|
28
29
|
new(o)
|
@@ -117,5 +118,47 @@ module Puppet::Pops::Adapters
|
|
117
118
|
class LoaderAdapter < Puppet::Pops::Adaptable::Adapter
|
118
119
|
# @return [Puppet::Pops::Loader::Loader] the loader
|
119
120
|
attr_accessor :loader
|
121
|
+
|
122
|
+
# Attempts to find the module that `instance` originates from by looking at it's {SourcePosAdapter} and
|
123
|
+
# compare the `locator.file` found there with the module paths given in the environment found in the
|
124
|
+
# given `scope`. If the file is found to be relative to a path, then the first segment of the relative
|
125
|
+
# path is interpreted as the name of a module. The object that the {SourcePosAdapter} is adapted to
|
126
|
+
# will then be adapted to the private loader for that module and that adapter is returned.
|
127
|
+
#
|
128
|
+
# The method returns `nil` when no module could be found.
|
129
|
+
#
|
130
|
+
# @param scope
|
131
|
+
# @param instance
|
132
|
+
def self.adapt_by_source(scope, instance)
|
133
|
+
source_pos = Puppet::Pops::Utils.find_adapter(instance, SourcePosAdapter)
|
134
|
+
unless source_pos.nil?
|
135
|
+
mod = find_module_for_file(scope.environment, source_pos.locator.file)
|
136
|
+
unless mod.nil?
|
137
|
+
adapter = LoaderAdapter.adapt(source_pos.adapted)
|
138
|
+
adapter.loader = scope.compiler.loaders.private_loader_for_module(mod.name)
|
139
|
+
return adapter
|
140
|
+
end
|
141
|
+
end
|
142
|
+
nil
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.find_module_for_file(environment, file)
|
146
|
+
return nil if file.nil?
|
147
|
+
file_path = Pathname.new(file)
|
148
|
+
environment.modulepath.each do |path|
|
149
|
+
begin
|
150
|
+
relative_path = file_path.relative_path_from(Pathname.new(path)).to_s.split(File::SEPARATOR)
|
151
|
+
rescue ArgumentError
|
152
|
+
# file_path was not relative to the module_path. That's OK.
|
153
|
+
next
|
154
|
+
end
|
155
|
+
if relative_path.length > 1
|
156
|
+
mod = environment.module(relative_path[0])
|
157
|
+
return mod unless mod.nil?
|
158
|
+
end
|
159
|
+
end
|
160
|
+
nil
|
161
|
+
end
|
162
|
+
private_class_method :find_module_for_file
|
120
163
|
end
|
121
164
|
end
|
@@ -39,7 +39,7 @@ class Puppet::Pops::Evaluator::AccessOperator
|
|
39
39
|
fail(Puppet::Pops::Issues::BAD_STRING_SLICE_ARITY, @semantic.left_expr, {:actual => keys.size})
|
40
40
|
when 1
|
41
41
|
# Note that Ruby 1.8.7 requires a length of 1 to produce a String
|
42
|
-
k1 = coerce_numeric(keys[0], @semantic.keys, scope)
|
42
|
+
k1 = coerce_numeric(keys[0], @semantic.keys[0], scope)
|
43
43
|
bad_access_key_type(o, 0, k1, Integer) unless k1.is_a?(Integer)
|
44
44
|
k2 = 1
|
45
45
|
k1 = k1 < 0 ? o.length + k1 : k1 # abs pos
|
@@ -50,8 +50,8 @@ class Puppet::Pops::Evaluator::AccessOperator
|
|
50
50
|
o[ k1, k2 ]
|
51
51
|
end
|
52
52
|
when 2
|
53
|
-
k1 = coerce_numeric(keys[0], @semantic.keys, scope)
|
54
|
-
k2 = coerce_numeric(keys[1], @semantic.keys, scope)
|
53
|
+
k1 = coerce_numeric(keys[0], @semantic.keys[0], scope)
|
54
|
+
k2 = coerce_numeric(keys[1], @semantic.keys[1], scope)
|
55
55
|
[k1, k2].each_with_index { |k,i| bad_access_key_type(o, i, k, Integer) unless k.is_a?(Integer) }
|
56
56
|
|
57
57
|
k1 = k1 < 0 ? o.length + k1 : k1 # abs pos (negative is count from end)
|
@@ -54,40 +54,17 @@ class Puppet::Pops::Evaluator::Closure < Puppet::Pops::Evaluator::CallableSignat
|
|
54
54
|
# Call closure with argument assignment by name
|
55
55
|
def call_by_name(args_hash, enforce_parameters)
|
56
56
|
if enforce_parameters
|
57
|
-
|
58
|
-
raise ArgumentError, "Too many arguments: #{args_hash.size} for #{parameters.size}"
|
59
|
-
end
|
60
|
-
|
61
|
-
# associate values with parameters
|
62
|
-
scope_hash = {}
|
57
|
+
args_hash = args_hash.dup
|
63
58
|
parameters.each do |p|
|
64
59
|
name = p.name
|
65
|
-
if (
|
66
|
-
|
67
|
-
|
68
|
-
unless p.value.nil?
|
69
|
-
scope_hash[name] = @evaluator.evaluate(p.value, @enclosing_scope)
|
70
|
-
end
|
71
|
-
else
|
72
|
-
scope_hash[name] = arg_value
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
missing = parameters.select { |p| !scope_hash.include?(p.name) }
|
77
|
-
if missing.any?
|
78
|
-
raise ArgumentError, "Too few arguments; no value given for required parameters #{missing.collect(&:name).join(" ,")}"
|
79
|
-
end
|
80
|
-
|
81
|
-
tc = Puppet::Pops::Types::TypeCalculator.singleton
|
82
|
-
final_args = tc.infer_set(parameter_names.collect { |param| scope_hash[param] })
|
83
|
-
if !type.callable?(final_args)
|
84
|
-
raise ArgumentError, Puppet::Pops::Types::TypeMismatchDescriber.describe_signatures(closure_name, [self], final_args)
|
60
|
+
# only set result of default expr if it is defined (it is otherwise not possible to differentiate
|
61
|
+
# between explicit undef and no default expression
|
62
|
+
args_hash[name] = @evaluator.evaluate(p.value, @enclosing_scope) if args_hash[name].nil? && !p.value.nil?
|
85
63
|
end
|
86
|
-
|
87
|
-
scope_hash = args_hash
|
64
|
+
Puppet::Pops::Types::TypeMismatchDescriber.validate_parameters(closure_name, params_struct, args_hash)
|
88
65
|
end
|
89
66
|
|
90
|
-
@evaluator.evaluate_block_with_bindings(@enclosing_scope,
|
67
|
+
@evaluator.evaluate_block_with_bindings(@enclosing_scope, args_hash, @model.body)
|
91
68
|
end
|
92
69
|
|
93
70
|
def parameters
|
@@ -111,6 +88,11 @@ class Puppet::Pops::Evaluator::Closure < Puppet::Pops::Evaluator::CallableSignat
|
|
111
88
|
@callable ||= create_callable_type
|
112
89
|
end
|
113
90
|
|
91
|
+
# @api public
|
92
|
+
def params_struct
|
93
|
+
@params_struct ||= create_params_struct
|
94
|
+
end
|
95
|
+
|
114
96
|
# @api public
|
115
97
|
def last_captures_rest?
|
116
98
|
last = @model.parameters[-1]
|
@@ -196,28 +178,7 @@ class Puppet::Pops::Evaluator::Closure < Puppet::Pops::Evaluator::CallableSignat
|
|
196
178
|
range = [0, 0]
|
197
179
|
in_optional_parameters = false
|
198
180
|
parameters.each do |param|
|
199
|
-
type =
|
200
|
-
@evaluator.evaluate(param.type_expr, @enclosing_scope)
|
201
|
-
else
|
202
|
-
Puppet::Pops::Types::PAnyType::DEFAULT
|
203
|
-
end
|
204
|
-
|
205
|
-
if param.captures_rest && type.is_a?(Puppet::Pops::Types::PArrayType)
|
206
|
-
# An array on a slurp parameter is how a size range is defined for a
|
207
|
-
# slurp (Array[Integer, 1, 3] *$param). However, the callable that is
|
208
|
-
# created can't have the array in that position or else type checking
|
209
|
-
# will require the parameters to be arrays, which isn't what is
|
210
|
-
# intended. The array type contains the intended information and needs
|
211
|
-
# to be unpacked.
|
212
|
-
param_range = type.size_range
|
213
|
-
type = type.element_type
|
214
|
-
elsif param.captures_rest && !type.is_a?(Puppet::Pops::Types::PArrayType)
|
215
|
-
param_range = ANY_NUMBER_RANGE
|
216
|
-
elsif param.value
|
217
|
-
param_range = OPTIONAL_SINGLE_RANGE
|
218
|
-
else
|
219
|
-
param_range = REQUIRED_SINGLE_RANGE
|
220
|
-
end
|
181
|
+
type, param_range = create_param_type(param)
|
221
182
|
|
222
183
|
types << type
|
223
184
|
|
@@ -238,6 +199,45 @@ class Puppet::Pops::Evaluator::Closure < Puppet::Pops::Evaluator::CallableSignat
|
|
238
199
|
Puppet::Pops::Types::TypeFactory.callable(*(types + range))
|
239
200
|
end
|
240
201
|
|
202
|
+
def create_params_struct
|
203
|
+
type_factory = Puppet::Pops::Types::TypeFactory
|
204
|
+
members = {}
|
205
|
+
|
206
|
+
parameters.each do |param|
|
207
|
+
arg_type, param_range = create_param_type(param)
|
208
|
+
key_type = type_factory.string(nil, param.name.to_s)
|
209
|
+
key_type = type_factory.optional(key_type) unless param.value.nil?
|
210
|
+
members[key_type] = arg_type
|
211
|
+
end
|
212
|
+
type_factory.struct(members)
|
213
|
+
end
|
214
|
+
|
215
|
+
def create_param_type(param)
|
216
|
+
type = if param.type_expr
|
217
|
+
@evaluator.evaluate(param.type_expr, @enclosing_scope)
|
218
|
+
else
|
219
|
+
Puppet::Pops::Types::PAnyType::DEFAULT
|
220
|
+
end
|
221
|
+
|
222
|
+
if param.captures_rest && type.is_a?(Puppet::Pops::Types::PArrayType)
|
223
|
+
# An array on a slurp parameter is how a size range is defined for a
|
224
|
+
# slurp (Array[Integer, 1, 3] *$param). However, the callable that is
|
225
|
+
# created can't have the array in that position or else type checking
|
226
|
+
# will require the parameters to be arrays, which isn't what is
|
227
|
+
# intended. The array type contains the intended information and needs
|
228
|
+
# to be unpacked.
|
229
|
+
param_range = type.size_range
|
230
|
+
type = type.element_type
|
231
|
+
elsif param.captures_rest && !type.is_a?(Puppet::Pops::Types::PArrayType)
|
232
|
+
param_range = ANY_NUMBER_RANGE
|
233
|
+
elsif param.value
|
234
|
+
param_range = OPTIONAL_SINGLE_RANGE
|
235
|
+
else
|
236
|
+
param_range = REQUIRED_SINGLE_RANGE
|
237
|
+
end
|
238
|
+
[type, param_range]
|
239
|
+
end
|
240
|
+
|
241
241
|
# Produces information about parameters compatible with a 4x Function (which can have multiple signatures)
|
242
242
|
def signatures
|
243
243
|
[ self ]
|
@@ -125,6 +125,14 @@ protected
|
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
128
|
+
def query_AccessExpression(o, scope)
|
129
|
+
pops_object = @@evaluator.evaluate(o, scope)
|
130
|
+
|
131
|
+
# Convert to Puppet 3 style objects since that is how they are represented
|
132
|
+
# in the catalog.
|
133
|
+
@@evaluator.convert(pops_object, scope, nil)
|
134
|
+
end
|
135
|
+
|
128
136
|
def query_VariableExpression(o, scope)
|
129
137
|
@@evaluator.evaluate(o, scope)
|
130
138
|
end
|
@@ -157,6 +165,14 @@ protected
|
|
157
165
|
raise ArgumentError, "Cannot transform object of class #{o.class}"
|
158
166
|
end
|
159
167
|
|
168
|
+
def match_AccessExpression(o, scope)
|
169
|
+
pops_object = @@evaluator.evaluate(o, scope)
|
170
|
+
|
171
|
+
# Convert to Puppet 3 style objects since that is how they are represented
|
172
|
+
# in the catalog.
|
173
|
+
@@evaluator.convert(pops_object, scope, nil)
|
174
|
+
end
|
175
|
+
|
160
176
|
def match_AndExpression(o, scope)
|
161
177
|
left_match = match(o.left_expr, scope)
|
162
178
|
right_match = match(o.right_expr, scope)
|
@@ -248,7 +248,9 @@ module Puppet::Pops::Evaluator::Runtime3Support
|
|
248
248
|
# this is done from the perspective of the environment.
|
249
249
|
loader = loaders.private_environment_loader
|
250
250
|
if loader && func = loader.load(:function, name)
|
251
|
-
|
251
|
+
Puppet::Util::Profiler.profile(name, [:functions, name]) do
|
252
|
+
return func.call(scope, *args, &block)
|
253
|
+
end
|
252
254
|
end
|
253
255
|
|
254
256
|
# Call via 3x API if function exists there
|
@@ -267,9 +269,16 @@ module Puppet::Pops::Evaluator::Runtime3Support
|
|
267
269
|
loaders = scope.compiler.loaders
|
268
270
|
# find the loader that loaded the code, or use the private_environment_loader (sees env + all modules)
|
269
271
|
adapter = Puppet::Pops::Utils.find_adapter(o, Puppet::Pops::Adapters::LoaderAdapter)
|
272
|
+
|
273
|
+
# Use source location to determine calling module, or use the private_environment_loader (sees env + all modules)
|
274
|
+
# This is necessary since not all .pp files are loaded by a Puppet::Pops::Loader (see PUP-1833)
|
275
|
+
adapter ||= Puppet::Pops::Adapters::LoaderAdapter.adapt_by_source(scope, o)
|
276
|
+
|
270
277
|
loader = adapter.nil? ? loaders.private_environment_loader : adapter.loader
|
271
278
|
if loader && func = loader.load(:function, name)
|
272
|
-
|
279
|
+
Puppet::Util::Profiler.profile(name, [:functions, name]) do
|
280
|
+
return func.call(scope, *args, &block)
|
281
|
+
end
|
273
282
|
end
|
274
283
|
|
275
284
|
# Call via 3x API if function exists there
|
@@ -89,13 +89,17 @@ class Puppet::Pops::Functions::Function
|
|
89
89
|
raise ArgumentError, "Function #{self.class.name}(): cannot call function '#{function_name}' - no loader specified" unless the_loader
|
90
90
|
|
91
91
|
func = the_loader.load(:function, function_name)
|
92
|
-
|
92
|
+
if func
|
93
|
+
Puppet::Util::Profiler.profile(function_name, [:functions, function_name]) do
|
94
|
+
return func.call(scope, *args, &block)
|
95
|
+
end
|
96
|
+
end
|
93
97
|
|
94
98
|
# Check if a 3x function is present. Raise a generic error if it's not to allow upper layers to fill in the details
|
95
99
|
# about where in a puppet manifest this error originates. (Such information is not available here).
|
96
100
|
loader_scope = closure_scope
|
97
101
|
func_3x = Puppet::Parser::Functions.function(function_name, loader_scope.environment) if loader_scope.is_a?(Puppet::Parser::Scope)
|
98
|
-
raise ArgumentError, "Function #{self.class.name}():
|
102
|
+
raise ArgumentError, "Function #{self.class.name}(): Unknown function: '#{function_name}'" unless func_3x
|
99
103
|
|
100
104
|
# Call via 3x API
|
101
105
|
# Arguments must be mapped since functions are unaware of the new and magical creatures in 4x.
|
data/lib/puppet/pops/issues.rb
CHANGED
@@ -151,6 +151,10 @@ module Puppet::Pops::Issues
|
|
151
151
|
"Classes, definitions, and nodes may only appear at toplevel or inside other classes"
|
152
152
|
end
|
153
153
|
|
154
|
+
NOT_ABSOLUTE_TOP_LEVEL = hard_issue :NOT_ABSOLUTE_TOP_LEVEL do
|
155
|
+
"#{label.a_an_uc(semantic)} may only appear at toplevel"
|
156
|
+
end
|
157
|
+
|
154
158
|
CROSS_SCOPE_ASSIGNMENT = hard_issue :CROSS_SCOPE_ASSIGNMENT, :name do
|
155
159
|
"Illegal attempt to assign to '#{name}'. Cannot assign to variables in other namespaces"
|
156
160
|
end
|
@@ -536,6 +540,10 @@ module Puppet::Pops::Issues
|
|
536
540
|
"This #{label.label(semantic)} has no effect. A value was produced and then forgotten (one or more preceding expressions may have the wrong form)"
|
537
541
|
end
|
538
542
|
|
543
|
+
RESOURCE_WITHOUT_TITLE = issue :RESOURCE_WITHOUT_TITLE, :name do
|
544
|
+
"This expression is invalid. Did you try declaring a '#{name}' resource without a title?"
|
545
|
+
end
|
546
|
+
|
539
547
|
IDEM_NOT_ALLOWED_LAST = hard_issue :IDEM_NOT_ALLOWED_LAST, :container do
|
540
548
|
"This #{label.label(semantic)} has no effect. #{label.a_an_uc(container)} can not end with a value-producing expression without other effect"
|
541
549
|
end
|
@@ -564,6 +572,10 @@ module Puppet::Pops::Issues
|
|
564
572
|
"Resource Override can only operate on resources, got: #{label.label(actual)}"
|
565
573
|
end
|
566
574
|
|
575
|
+
DUPLICATE_PARAMETER = hard_issue :DUPLICATE_PARAMETER, :param_name do
|
576
|
+
"The parameter '#{param_name}' is declared more than once in the parameter list"
|
577
|
+
end
|
578
|
+
|
567
579
|
RESERVED_PARAMETER = hard_issue :RESERVED_PARAMETER, :container, :param_name do
|
568
580
|
"The parameter $#{param_name} redefines a built in parameter in #{label.the(container)}"
|
569
581
|
end
|
@@ -632,6 +644,10 @@ module Puppet::Pops::Issues
|
|
632
644
|
"Unclosed quote after #{after} followed by '#{followed_by}'"
|
633
645
|
end
|
634
646
|
|
647
|
+
UNCLOSED_MLCOMMENT = hard_issue :UNCLOSED_MLCOMMENT do
|
648
|
+
'Unclosed multiline comment'
|
649
|
+
end
|
650
|
+
|
635
651
|
EPP_INTERNAL_ERROR = hard_issue :EPP_INTERNAL_ERROR, :error do
|
636
652
|
"Internal error: #{error}"
|
637
653
|
end
|
@@ -43,7 +43,8 @@ class Puppet::Pops::Loader::PuppetFunctionInstantiator
|
|
43
43
|
# Adapt the function definition with loader - this is used from logic contained in it body to find the
|
44
44
|
# loader to use when making calls to the new function API. Such logic have a hard time finding the closure (where
|
45
45
|
# the loader is known - hence this mechanism
|
46
|
-
|
46
|
+
private_loader = loader.private_loader
|
47
|
+
Puppet::Pops::Adapters::LoaderAdapter.adapt(the_function_definition).loader = private_loader
|
47
48
|
|
48
49
|
# TODO: Cheating wrt. scope - assuming it is found in the context
|
49
50
|
closure_scope = Puppet.lookup(:global_scope) { {} }
|
@@ -53,7 +54,7 @@ class Puppet::Pops::Loader::PuppetFunctionInstantiator
|
|
53
54
|
# when calling functions etc.
|
54
55
|
# It should be bound to global scope
|
55
56
|
|
56
|
-
created.new(closure_scope,
|
57
|
+
created.new(closure_scope, private_loader)
|
57
58
|
end
|
58
59
|
|
59
60
|
# Creates Function class and instantiates it based on a FunctionDefinition model
|
data/lib/puppet/pops/lookup.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
# See puppet/functions/lookup.rb for documentation.
|
3
3
|
#
|
4
4
|
module Puppet::Pops::Lookup
|
5
|
+
LOOKUP_OPTIONS = 'lookup_options'.freeze
|
6
|
+
GLOBAL = '__global__'.freeze
|
7
|
+
|
5
8
|
# Performs a lookup in the configured scopes and optionally merges the default.
|
6
9
|
#
|
7
10
|
# This is a backing function and all parameters are assumed to have been type checked.
|
@@ -28,7 +28,8 @@ module Puppet::Pops::Lookup
|
|
28
28
|
end
|
29
29
|
|
30
30
|
class ExplainTreeNode < ExplainNode
|
31
|
-
attr_reader :parent, :event, :
|
31
|
+
attr_reader :parent, :event, :value
|
32
|
+
attr_accessor :key
|
32
33
|
|
33
34
|
def initialize(parent)
|
34
35
|
@parent = parent
|
@@ -133,6 +134,55 @@ module Puppet::Pops::Lookup
|
|
133
134
|
end
|
134
135
|
end
|
135
136
|
|
137
|
+
class ExplainTop < ExplainTreeNode
|
138
|
+
def initialize(parent, type, key)
|
139
|
+
super(parent)
|
140
|
+
@type = type
|
141
|
+
self.key = key
|
142
|
+
end
|
143
|
+
|
144
|
+
def dump_on(io, indent, first_indent)
|
145
|
+
io << first_indent << 'Searching for "' << key << "\"\n"
|
146
|
+
indent = increase_indent(indent)
|
147
|
+
branches.each {|b| b.dump_on(io, indent, indent)}
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class ExplainInvalidKey < ExplainTreeNode
|
152
|
+
def initialize(parent, key)
|
153
|
+
super(parent)
|
154
|
+
@key = key
|
155
|
+
end
|
156
|
+
|
157
|
+
def dump_on(io, indent, first_indent)
|
158
|
+
io << first_indent << "Invalid key \"" << @key << "\"\n"
|
159
|
+
end
|
160
|
+
|
161
|
+
def type
|
162
|
+
:invalid_key
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
class ExplainMergeSource < ExplainNode
|
167
|
+
attr_reader :merge_source
|
168
|
+
|
169
|
+
def initialize(merge_source)
|
170
|
+
@merge_source = merge_source
|
171
|
+
end
|
172
|
+
|
173
|
+
def dump_on(io, indent, first_indent)
|
174
|
+
io << first_indent << 'Using merge options from "' << merge_source << "\" hash\n"
|
175
|
+
end
|
176
|
+
|
177
|
+
def to_hash
|
178
|
+
{ :type => type, :merge_source => merge_source }
|
179
|
+
end
|
180
|
+
|
181
|
+
def type
|
182
|
+
:merge_source
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
136
186
|
class ExplainInterpolate < ExplainTreeNode
|
137
187
|
def initialize(parent, expression)
|
138
188
|
super(parent)
|
@@ -163,6 +213,8 @@ module Puppet::Pops::Lookup
|
|
163
213
|
end
|
164
214
|
|
165
215
|
def dump_on(io, indent, first_indent)
|
216
|
+
return if branches.size == 0
|
217
|
+
|
166
218
|
# It's pointless to report a merge where there's only one branch
|
167
219
|
return branches[0].dump_on(io, indent, first_indent) if branches.size == 1
|
168
220
|
|
@@ -297,7 +349,7 @@ module Puppet::Pops::Lookup
|
|
297
349
|
def dump_on(io, indent, first_indent)
|
298
350
|
io << indent << 'Path "' << @path.path << "\"\n"
|
299
351
|
indent = increase_indent(indent)
|
300
|
-
io << indent << 'Original path: ' << @path.original_path << "\n"
|
352
|
+
io << indent << 'Original path: "' << @path.original_path << "\"\n"
|
301
353
|
branches.each {|b| b.dump_on(io, indent, indent)}
|
302
354
|
io << indent << "Path not found\n" if @event == :path_not_found
|
303
355
|
dump_outcome(io, indent)
|
@@ -332,8 +384,10 @@ module Puppet::Pops::Lookup
|
|
332
384
|
end
|
333
385
|
|
334
386
|
class Explainer < ExplainNode
|
335
|
-
def initialize
|
387
|
+
def initialize(explain_options = false, only_explain_options = false)
|
336
388
|
@current = self
|
389
|
+
@explain_options = explain_options
|
390
|
+
@only_explain_options = only_explain_options
|
337
391
|
end
|
338
392
|
|
339
393
|
def push(qualifier_type, qualifier)
|
@@ -352,6 +406,10 @@ module Puppet::Pops::Lookup
|
|
352
406
|
ExplainMerge.new(@current, qualifier)
|
353
407
|
when :scope
|
354
408
|
ExplainScope.new(@current)
|
409
|
+
when :meta, :data
|
410
|
+
ExplainTop.new(@current, qualifier_type, qualifier)
|
411
|
+
when :invalid_key
|
412
|
+
ExplainInvalidKey.new(@current, qualifier)
|
355
413
|
else
|
356
414
|
raise ArgumentError, "Unknown Explain type #{qualifier_type}"
|
357
415
|
end
|
@@ -359,6 +417,14 @@ module Puppet::Pops::Lookup
|
|
359
417
|
@current = node
|
360
418
|
end
|
361
419
|
|
420
|
+
def only_explain_options?
|
421
|
+
@only_explain_options
|
422
|
+
end
|
423
|
+
|
424
|
+
def explain_options?
|
425
|
+
@explain_options
|
426
|
+
end
|
427
|
+
|
362
428
|
def pop
|
363
429
|
@current = @current.parent unless @current.parent.nil?
|
364
430
|
end
|
@@ -375,6 +441,10 @@ module Puppet::Pops::Lookup
|
|
375
441
|
@current.found(key, value)
|
376
442
|
end
|
377
443
|
|
444
|
+
def accept_merge_source(merge_source)
|
445
|
+
@current.branches << ExplainMergeSource.new(merge_source)
|
446
|
+
end
|
447
|
+
|
378
448
|
def accept_not_found(key)
|
379
449
|
@current.not_found(key)
|
380
450
|
end
|