puppet 4.4.2 → 4.5.0
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.
- data/CONTRIBUTING.md +5 -5
- data/Gemfile +2 -2
- data/LICENSE +2 -2
- data/README.md +5 -0
- data/ext/project_data.yaml +2 -0
- data/lib/hiera_puppet.rb +6 -14
- data/lib/puppet/application/agent.rb +2 -3
- data/lib/puppet/data_providers/hiera_config.rb +2 -4
- data/lib/puppet/data_providers/hiera_interpolate.rb +12 -154
- data/lib/puppet/data_providers/json_data_provider_factory.rb +0 -7
- data/lib/puppet/data_providers/yaml_data_provider_factory.rb +2 -8
- data/lib/puppet/defaults.rb +70 -7
- data/lib/puppet/functions.rb +69 -0
- data/lib/puppet/functions/dig.rb +39 -0
- data/lib/puppet/functions/lest.rb +53 -0
- data/lib/puppet/functions/lookup.rb +40 -27
- data/lib/puppet/functions/new.rb +502 -0
- data/lib/puppet/functions/regsubst.rb +11 -10
- data/lib/puppet/functions/then.rb +74 -0
- data/lib/puppet/functions/type.rb +4 -4
- data/lib/puppet/functions/with.rb +1 -1
- data/lib/puppet/indirector/catalog/compiler.rb +2 -0
- data/lib/puppet/indirector/resource_type/parser.rb +5 -0
- data/lib/puppet/indirector/rest.rb +5 -1
- data/lib/puppet/loaders.rb +2 -0
- data/lib/puppet/metatype/manager.rb +19 -2
- data/lib/puppet/module_tool/applications/application.rb +1 -1
- data/lib/puppet/module_tool/skeleton/templates/generator/Gemfile +6 -2
- data/lib/puppet/module_tool/skeleton/templates/generator/Rakefile +19 -4
- data/lib/puppet/module_tool/skeleton/templates/generator/{tests → examples}/init.pp.erb +1 -1
- data/lib/puppet/module_tool/skeleton/templates/generator/spec/classes/init_spec.rb.erb +0 -1
- data/lib/puppet/network/http/api/master/v3/environment.rb +6 -2
- data/lib/puppet/parser/ast/pops_bridge.rb +20 -3
- data/lib/puppet/parser/compiler/catalog_validator/relationship_validator.rb +24 -2
- data/lib/puppet/parser/e4_parser_adapter.rb +13 -12
- data/lib/puppet/parser/environment_compiler.rb +2 -2
- data/lib/puppet/parser/resource.rb +14 -5
- data/lib/puppet/parser/scope.rb +18 -15
- data/lib/puppet/plugins/data_providers/data_provider.rb +19 -8
- data/lib/puppet/pops.rb +6 -0
- data/lib/puppet/pops/adapters.rb +5 -1
- data/lib/puppet/pops/evaluator/access_operator.rb +52 -14
- data/lib/puppet/pops/evaluator/compare_operator.rb +34 -4
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +75 -22
- data/lib/puppet/pops/evaluator/literal_evaluator.rb +7 -6
- data/lib/puppet/pops/evaluator/runtime3_converter.rb +13 -1
- data/lib/puppet/pops/evaluator/runtime3_support.rb +14 -4
- data/lib/puppet/pops/functions/dispatcher.rb +1 -1
- data/lib/puppet/pops/issues.rb +18 -2
- data/lib/puppet/pops/loader/base_loader.rb +48 -7
- data/lib/puppet/pops/loader/dependency_loader.rb +27 -2
- data/lib/puppet/pops/loader/loader.rb +12 -0
- data/lib/puppet/pops/loader/predefined_loader.rb +29 -0
- data/lib/puppet/pops/loader/runtime3_type_loader.rb +57 -0
- data/lib/puppet/pops/loader/static_loader.rb +92 -5
- data/lib/puppet/pops/loader/type_definition_instantiator.rb +25 -3
- data/lib/puppet/pops/loaders.rb +84 -14
- data/lib/puppet/pops/lookup/explainer.rb +38 -1
- data/lib/puppet/pops/lookup/interpolation.rb +115 -0
- data/lib/puppet/pops/lookup/sub_lookup.rb +86 -0
- data/lib/puppet/pops/model/ast_transformer.rb +8 -1
- data/lib/puppet/pops/model/factory.rb +31 -8
- data/lib/puppet/pops/model/model.rb +8 -0
- data/lib/puppet/pops/model/model_label_provider.rb +1 -0
- data/lib/puppet/pops/model/model_meta.rb +7 -1
- data/lib/puppet/pops/model/model_tree_dumper.rb +4 -0
- data/lib/puppet/pops/parser/egrammar.ra +24 -7
- data/lib/puppet/pops/parser/eparser.rb +863 -798
- data/lib/puppet/pops/parser/evaluating_parser.rb +4 -0
- data/lib/puppet/pops/parser/locator.rb +8 -4
- data/lib/puppet/pops/pcore.rb +30 -0
- data/lib/puppet/pops/types/class_loader.rb +2 -4
- data/lib/puppet/pops/types/implementation_registry.rb +146 -0
- data/lib/puppet/pops/types/iterable.rb +4 -4
- data/lib/puppet/pops/types/p_object_type.rb +846 -0
- data/lib/puppet/pops/types/p_runtime_type.rb +102 -0
- data/lib/puppet/pops/types/p_sem_ver_range_type.rb +164 -0
- data/lib/puppet/pops/types/p_sem_ver_type.rb +113 -0
- data/lib/puppet/pops/types/puppet_object.rb +21 -0
- data/lib/puppet/pops/types/ruby_generator.rb +258 -0
- data/lib/puppet/pops/types/string_converter.rb +922 -0
- data/lib/puppet/pops/types/type_calculator.rb +29 -5
- data/lib/puppet/pops/types/type_conversion_error.rb +15 -0
- data/lib/puppet/pops/types/type_factory.rb +49 -16
- data/lib/puppet/pops/types/type_formatter.rb +335 -112
- data/lib/puppet/pops/types/type_mismatch_describer.rb +110 -29
- data/lib/puppet/pops/types/type_parser.rb +205 -197
- data/lib/puppet/pops/types/types.rb +481 -103
- data/lib/puppet/pops/validation.rb +1 -1
- data/lib/puppet/pops/validation/checker4_0.rb +66 -4
- data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
- data/lib/puppet/pops/visitor.rb +3 -1
- data/lib/puppet/property.rb +1 -1
- data/lib/puppet/provider/augeas/augeas.rb +1 -1
- data/lib/puppet/provider/package/pip.rb +64 -20
- data/lib/puppet/provider/package/rpm.rb +112 -0
- data/lib/puppet/provider/package/yum.rb +7 -68
- data/lib/puppet/provider/service/daemontools.rb +3 -3
- data/lib/puppet/provider/service/init.rb +4 -2
- data/lib/puppet/provider/service/runit.rb +3 -3
- data/lib/puppet/provider/service/smf.rb +6 -3
- data/lib/puppet/provider/service/systemd.rb +59 -73
- data/lib/puppet/reference/providers.rb +1 -2
- data/lib/puppet/resource.rb +54 -37
- data/lib/puppet/resource/catalog.rb +31 -29
- data/lib/puppet/resource/type_collection.rb +23 -8
- data/lib/puppet/settings.rb +4 -2
- data/lib/puppet/settings/base_setting.rb +9 -3
- data/lib/puppet/settings/symbolic_enum_setting.rb +17 -0
- data/lib/puppet/test/test_helper.rb +0 -1
- data/lib/puppet/type.rb +9 -3
- data/lib/puppet/type/exec.rb +17 -17
- data/lib/puppet/type/file.rb +12 -0
- data/lib/puppet/type/file/content.rb +6 -6
- data/lib/puppet/type/file/ensure.rb +4 -4
- data/lib/puppet/type/file/source.rb +4 -4
- data/lib/puppet/type/file/target.rb +2 -2
- data/lib/puppet/type/mount.rb +18 -1
- data/lib/puppet/type/package.rb +3 -3
- data/lib/puppet/type/schedule.rb +4 -4
- data/lib/puppet/type/service.rb +15 -0
- data/lib/puppet/type/sshkey.rb +5 -3
- data/lib/puppet/type/tidy.rb +3 -3
- data/lib/puppet/type/zone.rb +5 -5
- data/lib/puppet/util/feature.rb +1 -1
- data/lib/puppet/util/monkey_patches.rb +8 -0
- data/lib/puppet/util/network_device/cisco/device.rb +16 -6
- data/lib/puppet/util/network_device/cisco/interface.rb +5 -6
- data/lib/puppet/util/plist.rb +3 -3
- data/lib/puppet/version.rb +1 -1
- data/spec/fixtures/unit/application/environments/production/data/common.yaml +13 -0
- data/spec/fixtures/unit/data_providers/environments/production/modules/abc/lib/puppet/functions/abc/data.rb +2 -1
- data/spec/fixtures/unit/data_providers/environments/production/modules/abc/manifests/init.pp +2 -1
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/data/empty_key.json +1 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/hiera.yaml +5 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/manifests/init.pp +2 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/metadata.json +9 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/data/empty_key.yaml +1 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/hiera.yaml +5 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/manifests/init.pp +2 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/metadata.json +9 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_yaml/data/empty.yaml +1 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/lib/puppet/type/usee_type.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/manifests/init.pp +6 -0
- data/spec/fixtures/unit/provider/service/smf/svcs.out +4 -3
- data/spec/integration/module_tool/tar/mini_spec.rb +27 -27
- data/spec/integration/parser/catalog_spec.rb +14 -2
- data/spec/integration/parser/compiler_spec.rb +94 -3
- data/spec/integration/parser/resource_expressions_spec.rb +1 -1
- data/spec/integration/resource/type_collection_spec.rb +8 -0
- data/spec/lib/puppet_spec/compiler.rb +11 -4
- data/spec/shared_contexts/types_setup.rb +4 -0
- data/spec/unit/application/lookup_spec.rb +91 -9
- data/spec/unit/appmgmt_spec.rb +44 -35
- data/spec/unit/capability_spec.rb +33 -53
- data/spec/unit/data_providers/function_data_provider_spec.rb +19 -1
- data/spec/unit/data_providers/hiera_data_provider_spec.rb +1 -1
- data/spec/unit/defaults_spec.rb +18 -0
- data/spec/unit/functions/assert_type_spec.rb +1 -1
- data/spec/unit/functions/dig_spec.rb +58 -0
- data/spec/unit/functions/lest_spec.rb +34 -0
- data/spec/unit/functions/lookup_spec.rb +108 -2
- data/spec/unit/functions/new_spec.rb +543 -0
- data/spec/unit/functions/regsubst_spec.rb +8 -0
- data/spec/unit/functions/then_spec.rb +40 -0
- data/spec/unit/functions4_spec.rb +78 -10
- data/spec/unit/hiera_puppet_spec.rb +49 -8
- data/spec/unit/indirector/resource_type/parser_spec.rb +5 -0
- data/spec/unit/indirector/rest_spec.rb +12 -0
- data/spec/unit/network/http/api/master/v3/environment_spec.rb +60 -0
- data/spec/unit/node/environment_spec.rb +10 -0
- data/spec/unit/parser/compiler_spec.rb +20 -1
- data/spec/unit/parser/functions/create_resources_spec.rb +2 -2
- data/spec/unit/parser/functions/shared.rb +1 -1
- data/spec/unit/parser/resource_spec.rb +8 -1
- data/spec/unit/parser/scope_spec.rb +45 -0
- data/spec/unit/pops/evaluator/access_ops_spec.rb +14 -0
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +13 -5
- data/spec/unit/pops/loaders/static_loader_spec.rb +92 -1
- data/spec/unit/{data_providers/hiera_interpolation_spec.rb → pops/lookup/interpolation_spec.rb} +7 -5
- data/spec/unit/pops/parser/lexer2_spec.rb +2 -9
- data/spec/unit/pops/parser/parse_application_spec.rb +3 -8
- data/spec/unit/pops/parser/parse_basic_expressions_spec.rb +19 -0
- data/spec/unit/pops/parser/parse_capabilities_spec.rb +3 -10
- data/spec/unit/pops/parser/parse_site_spec.rb +19 -10
- data/spec/unit/pops/parser/parser_rspec_helper.rb +0 -4
- data/spec/unit/pops/types/enumeration_spec.rb +13 -12
- data/spec/unit/pops/types/iterable_spec.rb +2 -2
- data/spec/unit/pops/types/p_object_type_spec.rb +1060 -0
- data/spec/unit/pops/types/p_sem_ver_type_spec.rb +285 -0
- data/spec/unit/pops/types/recursion_guard_spec.rb +19 -17
- data/spec/unit/pops/types/ruby_generator_spec.rb +261 -0
- data/spec/unit/pops/types/string_converter_spec.rb +904 -0
- data/spec/unit/pops/types/type_calculator_spec.rb +430 -406
- data/spec/unit/pops/types/type_factory_spec.rb +119 -104
- data/spec/unit/pops/types/type_formatter_spec.rb +73 -6
- data/spec/unit/pops/types/type_mismatch_describer_spec.rb +2 -2
- data/spec/unit/pops/types/type_parser_spec.rb +54 -15
- data/spec/unit/pops/types/types_spec.rb +113 -8
- data/spec/unit/pops/validator/validator_spec.rb +84 -10
- data/spec/unit/provider/package/pip3_spec.rb +9 -270
- data/spec/unit/provider/package/pip_spec.rb +85 -30
- data/spec/unit/provider/package/rpm_spec.rb +160 -3
- data/spec/unit/provider/package/yum_spec.rb +23 -134
- data/spec/unit/provider/service/smf_spec.rb +14 -2
- data/spec/unit/provider/service/systemd_spec.rb +33 -41
- data/spec/unit/resource/capability_finder_spec.rb +10 -2
- data/spec/unit/settings/file_setting_spec.rb +6 -0
- data/spec/unit/transaction/additional_resource_generator_spec.rb +80 -65
- data/spec/unit/type/mount_spec.rb +51 -10
- data/spec/unit/type/service_spec.rb +16 -0
- data/spec/unit/type_spec.rb +14 -0
- data/spec/unit/util/feature_spec.rb +1 -1
- data/spec/unit/util/monkey_patches_spec.rb +60 -0
- data/spec/unit/util/network_device/cisco/device_spec.rb +1 -1
- metadata +63 -11
- data/lib/puppet/pops/types/types_meta.rb +0 -0
- data/spec/integration/provider/package_spec.rb +0 -35
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'puppet/parser/compiler'
|
2
2
|
|
3
3
|
class Puppet::Parser::EnvironmentCompiler < Puppet::Parser::Compiler
|
4
|
-
def self.compile(env)
|
4
|
+
def self.compile(env, code_id=nil)
|
5
5
|
begin
|
6
6
|
env.check_for_reparse
|
7
7
|
|
8
8
|
node = Puppet::Node.new(env)
|
9
9
|
node.environment = env
|
10
|
-
new(node).compile
|
10
|
+
new(node, :code_id => code_id).compile
|
11
11
|
rescue => detail
|
12
12
|
message = "#{detail} in environment #{env.name}"
|
13
13
|
Puppet.log_exception(detail, message)
|
@@ -182,11 +182,20 @@ class Puppet::Parser::Resource < Puppet::Resource
|
|
182
182
|
alias []= set_parameter
|
183
183
|
|
184
184
|
def to_hash
|
185
|
-
@parameters.
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
185
|
+
@parameters.reduce({}) do |result, (_, param)|
|
186
|
+
value = param.value
|
187
|
+
value = (value == :undef) ? nil : value
|
188
|
+
|
189
|
+
unless value.nil?
|
190
|
+
case param.name
|
191
|
+
when :before, :subscribe, :notify, :require
|
192
|
+
value = value.flatten if value.is_a?(Array)
|
193
|
+
result[param.name] = value
|
194
|
+
else
|
195
|
+
result[param.name] = value
|
196
|
+
end
|
197
|
+
end
|
198
|
+
result
|
190
199
|
end
|
191
200
|
end
|
192
201
|
|
data/lib/puppet/parser/scope.rb
CHANGED
@@ -504,29 +504,32 @@ class Puppet::Parser::Scope
|
|
504
504
|
end
|
505
505
|
|
506
506
|
UNDEFINED_VARIABLES_KIND = 'undefined_variables'.freeze
|
507
|
+
DEPRECATION_KIND = 'deprecation'.freeze
|
508
|
+
|
509
|
+
# The exception raised when a throw is uncaught is different in different versions
|
510
|
+
# of ruby. In >=2.2.0 it is UncaughtThrowError (which did not exist prior to this)
|
511
|
+
#
|
512
|
+
UNCAUGHT_THROW_EXCEPTION = defined?(UncaughtThrowError) ? UncaughtThrowError : ArgumentError
|
507
513
|
|
508
514
|
def variable_not_found(name, reason=nil)
|
509
|
-
# Built in variables always exist
|
510
|
-
if BUILT_IN_VARS.include?(name)
|
515
|
+
# Built in variables and numeric variables always exist
|
516
|
+
if BUILT_IN_VARS.include?(name) || name =~ Puppet::Pops::Patterns::NUMERIC_VAR_NAME
|
511
517
|
return nil
|
512
518
|
end
|
513
|
-
|
519
|
+
begin
|
514
520
|
throw(:undefined_variable, reason)
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
# wait until a major release. It would then force all callers of scope to deal with
|
521
|
-
# the case of :undefined_variable. (Should check with include? first or catch the throw).
|
522
|
-
# Use deprecation warning to enable turning off these warnings, and to ensure each variable
|
523
|
-
# is only logged once.
|
524
|
-
unless name =~ Puppet::Pops::Patterns::NUMERIC_VAR_NAME
|
521
|
+
rescue UNCAUGHT_THROW_EXCEPTION
|
522
|
+
case Puppet[:strict]
|
523
|
+
when :off
|
524
|
+
# do nothing
|
525
|
+
when :warning
|
525
526
|
Puppet.warn_once(UNDEFINED_VARIABLES_KIND, "Variable: #{name}",
|
526
|
-
|
527
|
+
"Undefined variable '#{name}'; #{reason}" )
|
528
|
+
when :error
|
529
|
+
raise ArgumentError, "Undefined variable '#{name}'; #{reason}"
|
527
530
|
end
|
528
|
-
nil
|
529
531
|
end
|
532
|
+
nil
|
530
533
|
end
|
531
534
|
|
532
535
|
# Retrieves the variable value assigned to the name given as an argument. The name must be a String,
|
@@ -1,5 +1,9 @@
|
|
1
|
+
require 'puppet/pops/lookup/interpolation'
|
2
|
+
|
1
3
|
module Puppet::Plugins::DataProviders
|
2
4
|
module DataProvider
|
5
|
+
include Puppet::Pops::Lookup::Interpolation
|
6
|
+
|
3
7
|
# Performs a lookup with an endless recursion check.
|
4
8
|
#
|
5
9
|
# @param key [String] The key to lookup
|
@@ -19,10 +23,13 @@ module Puppet::Plugins::DataProviders
|
|
19
23
|
#
|
20
24
|
# @api public
|
21
25
|
def unchecked_lookup(key, lookup_invocation, merge)
|
26
|
+
segments = split_key(key)
|
27
|
+
root_key = segments.shift
|
22
28
|
lookup_invocation.with(:data_provider, self) do
|
23
|
-
hash = data(data_key(
|
24
|
-
value = hash[
|
25
|
-
if value || hash.include?(
|
29
|
+
hash = data(data_key(root_key, lookup_invocation), lookup_invocation)
|
30
|
+
value = hash[root_key]
|
31
|
+
if value || hash.include?(root_key)
|
32
|
+
value = sub_lookup(key, lookup_invocation, segments, value) unless segments.empty?
|
26
33
|
lookup_invocation.report_found(key, post_process(value, lookup_invocation))
|
27
34
|
else
|
28
35
|
lookup_invocation.report_not_found(key)
|
@@ -31,8 +38,8 @@ module Puppet::Plugins::DataProviders
|
|
31
38
|
end
|
32
39
|
end
|
33
40
|
|
34
|
-
# Perform optional post processing of found value.
|
35
|
-
#
|
41
|
+
# Perform optional post processing of found value. The default implementation resolves
|
42
|
+
# interpolation expressions
|
36
43
|
#
|
37
44
|
# @param value [Object] The value to perform post processing on
|
38
45
|
# @param lookup_invocation [Puppet::Pops::Lookup::Invocation] The current lookup invocation
|
@@ -40,7 +47,7 @@ module Puppet::Plugins::DataProviders
|
|
40
47
|
#
|
41
48
|
# @api public
|
42
49
|
def post_process(value, lookup_invocation)
|
43
|
-
value
|
50
|
+
interpolate(value, lookup_invocation, true)
|
44
51
|
end
|
45
52
|
|
46
53
|
# Gets the data from the compiler, or initializes it by calling #initialize_data if not present in the compiler.
|
@@ -223,6 +230,9 @@ module Puppet::Plugins::DataProviders
|
|
223
230
|
#
|
224
231
|
# @api public
|
225
232
|
def unchecked_lookup(key, lookup_invocation, merge)
|
233
|
+
segments = split_key(key)
|
234
|
+
root_key = segments.shift
|
235
|
+
|
226
236
|
module_name = @parent_data_provider.nil? ? nil : @parent_data_provider.data_key(key, lookup_invocation)
|
227
237
|
lookup_invocation.with(:data_provider, self) do
|
228
238
|
merge_strategy = Puppet::Pops::MergeStrategy.strategy(merge)
|
@@ -231,8 +241,9 @@ module Puppet::Plugins::DataProviders
|
|
231
241
|
lookup_invocation.with(:path, path) do
|
232
242
|
if path.exists?
|
233
243
|
hash = load_data(path.path, module_name, lookup_invocation)
|
234
|
-
value = hash[
|
235
|
-
if value || hash.include?(
|
244
|
+
value = hash[root_key]
|
245
|
+
if value || hash.include?(root_key)
|
246
|
+
value = sub_lookup(key, lookup_invocation, segments, value) unless segments.empty?
|
236
247
|
lookup_invocation.report_found(key, post_process(value, lookup_invocation))
|
237
248
|
else
|
238
249
|
lookup_invocation.report_not_found(key)
|
data/lib/puppet/pops.rb
CHANGED
@@ -10,6 +10,8 @@ module Puppet
|
|
10
10
|
#
|
11
11
|
# @api public
|
12
12
|
module Pops
|
13
|
+
require 'semantic'
|
14
|
+
|
13
15
|
require 'puppet/pops/patterns'
|
14
16
|
require 'puppet/pops/utils'
|
15
17
|
|
@@ -27,13 +29,16 @@ module Puppet
|
|
27
29
|
require 'puppet/pops/validation'
|
28
30
|
require 'puppet/pops/issue_reporter'
|
29
31
|
require 'puppet/pops/lookup'
|
32
|
+
require 'puppet/pops/lookup/interpolation'
|
30
33
|
require 'puppet/pops/lookup/invocation'
|
34
|
+
require 'puppet/pops/lookup/sub_lookup'
|
31
35
|
require 'puppet/pops/lookup/explainer'
|
32
36
|
|
33
37
|
require 'puppet/pops/model/model'
|
34
38
|
|
35
39
|
# (the Types module initializes itself)
|
36
40
|
require 'puppet/pops/types/types'
|
41
|
+
require 'puppet/pops/types/string_converter'
|
37
42
|
|
38
43
|
require 'puppet/pops/merge_strategy'
|
39
44
|
|
@@ -77,6 +82,7 @@ module Puppet
|
|
77
82
|
end
|
78
83
|
|
79
84
|
module Evaluator
|
85
|
+
require 'puppet/pops/evaluator/literal_evaluator'
|
80
86
|
require 'puppet/pops/evaluator/callable_signature'
|
81
87
|
require 'puppet/pops/evaluator/runtime3_converter'
|
82
88
|
require 'puppet/pops/evaluator/runtime3_support'
|
data/lib/puppet/pops/adapters.rb
CHANGED
@@ -103,7 +103,11 @@ module Adapters
|
|
103
103
|
# Produces an URI with path?line=n&pos=n. If origin is unknown the URI is string:?line=n&pos=n
|
104
104
|
def to_uri
|
105
105
|
f = locator.file
|
106
|
-
|
106
|
+
if f.nil? || f.empty?
|
107
|
+
f = 'string:'
|
108
|
+
else
|
109
|
+
f = Puppet::Util.path_to_uri(f).to_s
|
110
|
+
end
|
107
111
|
URI("#{f}?line=#{line.to_s}&pos=#{pos.to_s}")
|
108
112
|
end
|
109
113
|
end
|
@@ -154,6 +154,12 @@ class AccessOperator
|
|
154
154
|
Types::TypeFactory.variant(*keys)
|
155
155
|
end
|
156
156
|
|
157
|
+
def access_PSemVerType(o, scope, keys)
|
158
|
+
keys.flatten!
|
159
|
+
assert_keys(keys, o, 1, Float::INFINITY, String, Semantic::VersionRange)
|
160
|
+
Types::TypeFactory.sem_ver(*keys)
|
161
|
+
end
|
162
|
+
|
157
163
|
def access_PTupleType(o, scope, keys)
|
158
164
|
keys.flatten!
|
159
165
|
if Types::TypeFactory.is_range_parameter?(keys[-2]) && Types::TypeFactory.is_range_parameter?(keys[-1])
|
@@ -260,6 +266,15 @@ class AccessOperator
|
|
260
266
|
end
|
261
267
|
end
|
262
268
|
|
269
|
+
def access_PObjectType(o, scope, keys)
|
270
|
+
keys.flatten!
|
271
|
+
if keys.size == 1
|
272
|
+
Types::TypeFactory.object(keys[0])
|
273
|
+
else
|
274
|
+
fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, {:base_type => 'Object-Type', :min => 1, :actual => keys.size})
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
263
278
|
def access_PNotUndefType(o, scope, keys)
|
264
279
|
keys.flatten!
|
265
280
|
case keys.size
|
@@ -357,6 +372,10 @@ class AccessOperator
|
|
357
372
|
#
|
358
373
|
def access_PHashType(o, scope, keys)
|
359
374
|
keys.flatten!
|
375
|
+
if keys.size == 2 && keys[0].is_a?(Integer) && keys[1].is_a?(Integer)
|
376
|
+
return Types::PHashType.new(nil, nil, Types::PIntegerType.new(*keys))
|
377
|
+
end
|
378
|
+
|
360
379
|
keys[0,2].each_with_index do |k, index|
|
361
380
|
unless k.is_a?(Types::PAnyType)
|
362
381
|
fail(Issues::BAD_TYPE_SLICE_TYPE, @semantic.keys[index], {:base_type => 'Hash-Type', :actual => k.class})
|
@@ -364,18 +383,18 @@ class AccessOperator
|
|
364
383
|
end
|
365
384
|
case keys.size
|
366
385
|
when 2
|
367
|
-
|
386
|
+
size_t = nil
|
368
387
|
when 3
|
369
388
|
size_t = keys[2]
|
370
389
|
size_t = Types::PIntegerType.new(size_t) unless size_t.is_a?(Types::PIntegerType)
|
371
|
-
Types::PHashType.new(keys[0], keys[1], size_t)
|
372
390
|
when 4
|
373
|
-
|
391
|
+
size_t = collection_size_t(2, keys[2], keys[3])
|
374
392
|
else
|
375
393
|
fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic, {
|
376
394
|
:base_type => 'Hash-Type', :min => 2, :max => 4, :actual => keys.size
|
377
395
|
})
|
378
396
|
end
|
397
|
+
Types::PHashType.new(keys[0], keys[1], size_t)
|
379
398
|
end
|
380
399
|
|
381
400
|
# CollectionType is parameterized with a range
|
@@ -383,9 +402,9 @@ class AccessOperator
|
|
383
402
|
keys.flatten!
|
384
403
|
case keys.size
|
385
404
|
when 1
|
386
|
-
size_t = collection_size_t(
|
405
|
+
size_t = collection_size_t(0, keys[0])
|
387
406
|
when 2
|
388
|
-
size_t = collection_size_t(
|
407
|
+
size_t = collection_size_t(0, keys[0], keys[1])
|
389
408
|
else
|
390
409
|
fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic,
|
391
410
|
{:base_type => 'Collection-Type', :min => 1, :max => 2, :actual => keys.size})
|
@@ -399,19 +418,31 @@ class AccessOperator
|
|
399
418
|
keys.flatten!
|
400
419
|
case keys.size
|
401
420
|
when 1
|
421
|
+
unless keys[0].is_a?(Types::PAnyType)
|
422
|
+
fail(Issues::BAD_TYPE_SLICE_TYPE, @semantic.keys[0], {:base_type => 'Array-Type', :actual => keys[0].class})
|
423
|
+
end
|
424
|
+
type = keys[0]
|
402
425
|
size_t = nil
|
403
426
|
when 2
|
404
|
-
|
427
|
+
if keys[0].is_a?(Types::PAnyType)
|
428
|
+
size_t = collection_size_t(1, keys[1])
|
429
|
+
type = keys[0]
|
430
|
+
else
|
431
|
+
size_t = collection_size_t(0, keys[0], keys[1])
|
432
|
+
type = nil
|
433
|
+
end
|
405
434
|
when 3
|
406
|
-
|
435
|
+
if keys[0].is_a?(Types::PAnyType)
|
436
|
+
size_t = collection_size_t(1, keys[1], keys[2])
|
437
|
+
type = keys[0]
|
438
|
+
else
|
439
|
+
fail(Issues::BAD_TYPE_SLICE_TYPE, @semantic.keys[0], {:base_type => 'Array-Type', :actual => keys[0].class})
|
440
|
+
end
|
407
441
|
else
|
408
442
|
fail(Issues::BAD_TYPE_SLICE_ARITY, @semantic,
|
409
443
|
{:base_type => 'Array-Type', :min => 1, :max => 3, :actual => keys.size})
|
410
444
|
end
|
411
|
-
|
412
|
-
fail(Issues::BAD_TYPE_SLICE_TYPE, @semantic.keys[0], {:base_type => 'Array-Type', :actual => keys[0].class})
|
413
|
-
end
|
414
|
-
Types::PArrayType.new(keys[0], size_t)
|
445
|
+
Types::PArrayType.new(type, size_t)
|
415
446
|
end
|
416
447
|
|
417
448
|
# Produces an PIntegerType (range) given one or two keys.
|
@@ -438,6 +469,11 @@ class AccessOperator
|
|
438
469
|
access(t, scope, *keys)
|
439
470
|
end
|
440
471
|
|
472
|
+
# If a type reference is encountered here, it's an error
|
473
|
+
def access_PTypeReferenceType(o, scope, keys)
|
474
|
+
fail(Issues::UNKNOWN_RESOURCE_TYPE, @semantic, {:type_name => o.type_string })
|
475
|
+
end
|
476
|
+
|
441
477
|
# A Resource can create a new more specific Resource type, and/or an array of resource types
|
442
478
|
# If the given type has title set, it can not be specified further.
|
443
479
|
# @example
|
@@ -461,12 +497,12 @@ class AccessOperator
|
|
461
497
|
# Must know which concrete resource type to operate on in all cases.
|
462
498
|
# It is not allowed to specify the type in an array arg - e.g. Resource[[File, 'foo']]
|
463
499
|
# type_name is LHS type_name if set, else the first given arg
|
464
|
-
type_name = o.type_name || keys.shift
|
500
|
+
type_name = o.type_name || Types::TypeFormatter.singleton.capitalize_segments(keys.shift)
|
465
501
|
type_name = case type_name
|
466
502
|
when Types::PResourceType
|
467
503
|
type_name.type_name
|
468
504
|
when String
|
469
|
-
type_name
|
505
|
+
type_name
|
470
506
|
else
|
471
507
|
# blame given left expression if it defined the type, else the first given key expression
|
472
508
|
blame = o.type_name.nil? ? @semantic.keys[0] : @semantic.left_expr
|
@@ -474,7 +510,7 @@ class AccessOperator
|
|
474
510
|
end
|
475
511
|
|
476
512
|
# type name must conform
|
477
|
-
if type_name !~ Patterns::
|
513
|
+
if type_name !~ Patterns::CLASSREF_EXT
|
478
514
|
fail(Issues::ILLEGAL_CLASSREF, blamed, {:name=>type_name})
|
479
515
|
end
|
480
516
|
|
@@ -565,6 +601,8 @@ class AccessOperator
|
|
565
601
|
c.type_name
|
566
602
|
elsif c.is_a?(String)
|
567
603
|
c.downcase
|
604
|
+
elsif c.is_a?(Types::PTypeReferenceType)
|
605
|
+
c.type_string.downcase
|
568
606
|
else
|
569
607
|
fail(Issues::ILLEGAL_HOSTCLASS_NAME, @semantic.keys[i], {:name => c})
|
570
608
|
end
|
@@ -21,7 +21,6 @@ class CompareOperator
|
|
21
21
|
@@compare_visitor ||= Visitor.new(self, "cmp", 1, 1)
|
22
22
|
@@match_visitor ||= Visitor.new(self, "match", 2, 2)
|
23
23
|
@@include_visitor ||= Visitor.new(self, "include", 2, 2)
|
24
|
-
@type_calculator = Types::TypeCalculator.new()
|
25
24
|
end
|
26
25
|
|
27
26
|
def equals (a, b)
|
@@ -93,8 +92,13 @@ class CompareOperator
|
|
93
92
|
end
|
94
93
|
end
|
95
94
|
|
95
|
+
def cmp_Version(a, b)
|
96
|
+
raise ArgumentError.new('Versions not comparable to non Versions') unless b.is_a?(Semantic::Version)
|
97
|
+
a <=> b
|
98
|
+
end
|
99
|
+
|
96
100
|
def cmp_Object(a, b)
|
97
|
-
raise ArgumentError.new(
|
101
|
+
raise ArgumentError.new('Only Strings, Numbers, and Versions are comparable')
|
98
102
|
end
|
99
103
|
|
100
104
|
|
@@ -145,8 +149,10 @@ class CompareOperator
|
|
145
149
|
# Always set match data, a "not found" should not keep old match data visible
|
146
150
|
set_match_data(matched, scope) # creates ephemeral
|
147
151
|
return !!matched
|
152
|
+
when String, Semantic::Version
|
153
|
+
a.any? { |element| match(b, element, scope) }
|
148
154
|
when Types::PAnyType
|
149
|
-
a.each {|element| return true if
|
155
|
+
a.each {|element| return true if b.instance?(element) }
|
150
156
|
return false
|
151
157
|
else
|
152
158
|
a.each {|element| return true if equals(element, b) }
|
@@ -158,6 +164,10 @@ class CompareOperator
|
|
158
164
|
include?(a.keys, b, scope)
|
159
165
|
end
|
160
166
|
|
167
|
+
def include_VersionRange(a, b, scope)
|
168
|
+
Types::PSemVerRangeType.include?(a, b)
|
169
|
+
end
|
170
|
+
|
161
171
|
# Matches in general by using == operator
|
162
172
|
def match_Object(pattern, a, scope)
|
163
173
|
equals(a, pattern)
|
@@ -171,12 +181,32 @@ class CompareOperator
|
|
171
181
|
!!matched # convert to boolean
|
172
182
|
end
|
173
183
|
|
184
|
+
# Matches against semvers and strings
|
185
|
+
def match_Version(version, left, scope)
|
186
|
+
if left.is_a?(Semantic::Version)
|
187
|
+
version == left
|
188
|
+
elsif left.is_a? String
|
189
|
+
begin
|
190
|
+
version == Semantic::Version.parse(left)
|
191
|
+
rescue ArgumentError
|
192
|
+
false
|
193
|
+
end
|
194
|
+
else
|
195
|
+
false
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# Matches against semvers and strings
|
200
|
+
def match_VersionRange(range, left, scope)
|
201
|
+
Types::PSemVerRangeType.include?(range, left)
|
202
|
+
end
|
203
|
+
|
174
204
|
def match_PAnyType(any_type, left, scope)
|
175
205
|
# right is a type and left is not - check if left is an instance of the given type
|
176
206
|
# (The reverse is not terribly meaningful - computing which of the case options that first produces
|
177
207
|
# an instance of a given type).
|
178
208
|
#
|
179
|
-
|
209
|
+
any_type.instance?(left)
|
180
210
|
end
|
181
211
|
|
182
212
|
def match_Array(array, left, scope)
|
@@ -77,7 +77,7 @@ class EvaluatorImpl
|
|
77
77
|
@@eval_visitor.visit_this_1(self, target, scope)
|
78
78
|
|
79
79
|
rescue SemanticError => e
|
80
|
-
# A raised issue may not know the semantic target, use errors call stack, but fill in the
|
80
|
+
# A raised issue may not know the semantic target, use errors call stack, but fill in the
|
81
81
|
# rest from a supplied semantic object, or the target instruction if there is not semantic
|
82
82
|
# object.
|
83
83
|
#
|
@@ -223,6 +223,28 @@ class EvaluatorImpl
|
|
223
223
|
values.fetch(lval) {|k| fail(Issues::MISSING_MULTI_ASSIGNMENT_KEY, o, :key =>k)},
|
224
224
|
o, scope)
|
225
225
|
end
|
226
|
+
elsif values.is_a?(Puppet::Pops::Types::PHostClassType)
|
227
|
+
# assign variables from class variables
|
228
|
+
# lookup class resource and return one or more parameter values
|
229
|
+
# TODO: behavior when class_name is nil
|
230
|
+
resource = find_resource(scope, 'class', values.class_name)
|
231
|
+
if resource
|
232
|
+
base_name = "#{values.class_name.downcase}::"
|
233
|
+
idx = -1
|
234
|
+
result = lvalues.map do |lval|
|
235
|
+
idx += 1
|
236
|
+
varname = "#{base_name}#{lval}"
|
237
|
+
if variable_exists?(varname, scope)
|
238
|
+
result = get_variable_value(varname, o, scope)
|
239
|
+
assign(lval, result, o, scope)
|
240
|
+
else
|
241
|
+
fail(Puppet::Pops::Issues::MISSING_MULTI_ASSIGNMENT_VARIABLE, o.left_expr.values[idx], {:name => varname})
|
242
|
+
end
|
243
|
+
end
|
244
|
+
else
|
245
|
+
fail(Issues::UNKNOWN_RESOURCE, o.right_expr, {:type_name => 'Class', :title => values.class_name})
|
246
|
+
end
|
247
|
+
|
226
248
|
else
|
227
249
|
values = [values] unless values.is_a?(Array)
|
228
250
|
if values.size != lvalues.size
|
@@ -278,7 +300,9 @@ class EvaluatorImpl
|
|
278
300
|
# A QualifiedReference (i.e. a capitalized qualified name such as Foo, or Foo::Bar) evaluates to a PType
|
279
301
|
#
|
280
302
|
def eval_QualifiedReference(o, scope)
|
281
|
-
@@type_parser.interpret(o, scope)
|
303
|
+
type = @@type_parser.interpret(o, scope)
|
304
|
+
fail(Issues::UNKNOWN_RESOURCE_TYPE, o, {:type_name => type.type_string }) if type.is_a?(Types::PTypeReferenceType)
|
305
|
+
type
|
282
306
|
end
|
283
307
|
|
284
308
|
def eval_NotExpression(o, scope)
|
@@ -424,7 +448,15 @@ class EvaluatorImpl
|
|
424
448
|
#
|
425
449
|
def eval_AccessExpression(o, scope)
|
426
450
|
left = evaluate(o.left_expr, scope)
|
427
|
-
keys = o.keys
|
451
|
+
keys = o.keys || []
|
452
|
+
if left.is_a?(Types::PHostClassType)
|
453
|
+
# Evaluate qualified references without errors no undefined types
|
454
|
+
keys = keys.map {|key| key.is_a?(Model::QualifiedReference) ? @@type_parser.interpret(key, scope) : evaluate(key, scope) }
|
455
|
+
else
|
456
|
+
keys = keys.map {|key| evaluate(key, scope) }
|
457
|
+
# Resource[File] becomes File
|
458
|
+
return keys[0] if Types::PResourceType::DEFAULT == left && keys.size == 1 && keys[0].is_a?(Types::PResourceType)
|
459
|
+
end
|
428
460
|
AccessOperator.new(o).access(left, scope, *keys)
|
429
461
|
end
|
430
462
|
|
@@ -511,11 +543,17 @@ class EvaluatorImpl
|
|
511
543
|
# matches RHS types as instance of for all types except a parameterized Regexp[R]
|
512
544
|
if pattern.is_a?(Types::PAnyType)
|
513
545
|
# evaluate as instance? of type check
|
514
|
-
matched =
|
546
|
+
matched = pattern.instance?(left)
|
515
547
|
# convert match result to Boolean true, or false
|
516
548
|
return o.operator == :'=~' ? !!matched : !matched
|
517
549
|
end
|
518
550
|
|
551
|
+
if pattern.is_a?(Semantic::VersionRange)
|
552
|
+
# evaluate if range includes version
|
553
|
+
matched = Types::PSemVerRangeType.include?(pattern, left)
|
554
|
+
return o.operator == :'=~' ? matched : !matched
|
555
|
+
end
|
556
|
+
|
519
557
|
begin
|
520
558
|
pattern = Regexp.new(pattern) unless pattern.is_a?(Regexp)
|
521
559
|
rescue StandardError => e
|
@@ -692,6 +730,9 @@ class EvaluatorImpl
|
|
692
730
|
end
|
693
731
|
evaluated_name.type_name # assume validated
|
694
732
|
|
733
|
+
when Types::PTypeReferenceType
|
734
|
+
fail(Issues::UNKNOWN_RESOURCE_TYPE, o.type_string, {:type_name => evaluated_name.to_s})
|
735
|
+
|
695
736
|
else
|
696
737
|
actual = type_calculator.generalize(type_calculator.infer(evaluated_name)).to_s
|
697
738
|
fail(Issues::ILLEGAL_RESOURCE_TYPE, o.type_name, {:actual=>actual})
|
@@ -814,9 +855,20 @@ class EvaluatorImpl
|
|
814
855
|
# Evaluates function call by name.
|
815
856
|
#
|
816
857
|
def eval_CallNamedFunctionExpression(o, scope)
|
858
|
+
# If LHS is a type (i.e. Integer, or Integer[...]
|
859
|
+
# the call is taken as an instantiation of the given type
|
860
|
+
#
|
861
|
+
functor = o.functor_expr
|
862
|
+
if functor.is_a?(Model::QualifiedReference) ||
|
863
|
+
functor.is_a?(Model::AccessExpression) && functor.left_expr.is_a?(Model::QualifiedReference)
|
864
|
+
# instantiation
|
865
|
+
type = evaluate(functor, scope)
|
866
|
+
return call_function_with_block('new', unfold([type], o.arguments || [], scope), o, scope)
|
867
|
+
end
|
868
|
+
|
817
869
|
# The functor expression is not evaluated, it is not possible to select the function to call
|
818
870
|
# via an expression like $a()
|
819
|
-
case
|
871
|
+
case functor
|
820
872
|
when Model::QualifiedName
|
821
873
|
# ok
|
822
874
|
when Model::RenderStringExpression
|
@@ -841,6 +893,17 @@ class EvaluatorImpl
|
|
841
893
|
fail(Issues::ILLEGAL_EXPRESSION, o.functor_expr, {:feature=>'function name', :container => o})
|
842
894
|
end
|
843
895
|
name = name.value # the string function name
|
896
|
+
|
897
|
+
obj = receiver[0]
|
898
|
+
receiver_type = Types::TypeCalculator.infer(obj)
|
899
|
+
if receiver_type.is_a?(Types::PObjectType)
|
900
|
+
member = receiver_type[name]
|
901
|
+
unless member.nil?
|
902
|
+
args = unfold([], o.arguments || [], scope)
|
903
|
+
return o.lambda.nil? ? member.invoke(obj, scope, args) : member.invoke(obj, scope, args, &proc_from_lambda(o.lambda, scope))
|
904
|
+
end
|
905
|
+
end
|
906
|
+
|
844
907
|
call_function_with_block(name, unfold(receiver, o.arguments || [], scope), o, scope)
|
845
908
|
end
|
846
909
|
|
@@ -848,12 +911,17 @@ class EvaluatorImpl
|
|
848
911
|
if o.lambda.nil?
|
849
912
|
call_function(name, evaluated_arguments, o, scope)
|
850
913
|
else
|
851
|
-
|
852
|
-
call_function(name, evaluated_arguments, o, scope, &PuppetProc.new(closure) { |*args| closure.call(*args) })
|
914
|
+
call_function(name, evaluated_arguments, o, scope, &proc_from_lambda(o.lambda, scope))
|
853
915
|
end
|
854
916
|
end
|
855
917
|
private :call_function_with_block
|
856
918
|
|
919
|
+
def proc_from_lambda(lambda, scope)
|
920
|
+
closure = Closure.new(self, lambda, scope)
|
921
|
+
PuppetProc.new(closure) { |*args| closure.call(*args) }
|
922
|
+
end
|
923
|
+
private :proc_from_lambda
|
924
|
+
|
857
925
|
# @example
|
858
926
|
# $x ? { 10 => true, 20 => false, default => 0 }
|
859
927
|
#
|
@@ -1117,21 +1185,6 @@ class EvaluatorImpl
|
|
1117
1185
|
# of value except regular expression where a match is performed.
|
1118
1186
|
#
|
1119
1187
|
def is_match?(left, right, o, option_expr, scope)
|
1120
|
-
if right.is_a?(Regexp)
|
1121
|
-
return false unless left.is_a? String
|
1122
|
-
matched = right.match(left)
|
1123
|
-
set_match_data(matched, scope) # creates or clears ephemeral
|
1124
|
-
!!matched # convert to boolean
|
1125
|
-
elsif right.is_a?(Types::PAnyType)
|
1126
|
-
# right is a type and left is not - check if left is an instance of the given type
|
1127
|
-
# (The reverse is not terribly meaningful - computing which of the case options that first produces
|
1128
|
-
# an instance of a given type).
|
1129
|
-
#
|
1130
|
-
@@type_calculator.instance?(right, left)
|
1131
|
-
else
|
1132
|
-
# Handle equality the same way as the language '==' operator (case insensitive etc.)
|
1133
|
-
@@compare_operator.equals(left,right)
|
1134
|
-
end
|
1135
1188
|
@@compare_operator.match(left, right, scope)
|
1136
1189
|
end
|
1137
1190
|
|