puppet 4.8.2-x64-mingw32 → 4.9.0-x64-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- checksums.yaml +15 -0
- data/CONTRIBUTING.md +25 -1
- data/Gemfile +6 -0
- data/Rakefile +1 -0
- data/ext/project_data.yaml +5 -1
- data/ext/windows/service/daemon.rb +2 -1
- data/install.rb +43 -6
- data/lib/hiera/puppet_function.rb +15 -17
- data/lib/hiera/scope.rb +12 -14
- data/lib/puppet.rb +52 -0
- data/lib/puppet/application/face_base.rb +4 -0
- data/lib/puppet/application/lookup.rb +4 -2
- data/lib/puppet/application/resource.rb +1 -1
- data/lib/puppet/data_providers.rb +6 -3
- data/lib/puppet/data_providers/data_adapter.rb +6 -0
- data/lib/puppet/data_providers/data_function_support.rb +7 -0
- data/lib/puppet/data_providers/function_env_data_provider.rb +7 -0
- data/lib/puppet/data_providers/function_module_data_provider.rb +6 -0
- data/lib/puppet/data_providers/hiera_config.rb +31 -10
- data/lib/puppet/data_providers/hiera_env_data_provider.rb +6 -0
- data/lib/puppet/data_providers/hiera_interpolate.rb +2 -1
- data/lib/puppet/data_providers/hiera_module_data_provider.rb +6 -0
- data/lib/puppet/data_providers/hiera_support.rb +6 -0
- data/lib/puppet/data_providers/json_data_provider_factory.rb +12 -0
- data/lib/puppet/data_providers/yaml_data_provider_factory.rb +12 -0
- data/lib/puppet/defaults.rb +25 -4
- data/lib/puppet/face/ca.rb +2 -0
- data/lib/puppet/face/certificate_request.rb +2 -0
- data/lib/puppet/face/certificate_revocation_list.rb +2 -0
- data/lib/puppet/face/file.rb +3 -0
- data/lib/puppet/face/help.rb +19 -17
- data/lib/puppet/face/help/face.erb +3 -0
- data/lib/puppet/face/key.rb +1 -0
- data/lib/puppet/face/man.rb +4 -2
- data/lib/puppet/face/module/generate.rb +1 -1
- data/lib/puppet/face/status.rb +2 -0
- data/lib/puppet/feature/base.rb +9 -2
- data/lib/puppet/feature/hocon.rb +3 -0
- data/lib/puppet/file_system.rb +15 -3
- data/lib/puppet/file_system/windows.rb +8 -0
- data/lib/puppet/forge.rb +6 -6
- data/lib/puppet/forge/repository.rb +1 -2
- data/lib/puppet/functions/binary_file.rb +4 -10
- data/lib/puppet/functions/hiera_array.rb +1 -1
- data/lib/puppet/functions/hiera_include.rb +1 -1
- data/lib/puppet/functions/hocon_data.rb +24 -0
- data/lib/puppet/functions/json_data.rb +18 -0
- data/lib/puppet/functions/yaml_data.rb +21 -0
- data/lib/puppet/generate/type.rb +1 -1
- data/lib/puppet/graph/simple_graph.rb +4 -2
- data/lib/puppet/indirector/file_bucket_file/file.rb +10 -2
- data/lib/puppet/indirector/request.rb +5 -1
- data/lib/puppet/interface.rb +14 -2
- data/lib/puppet/interface/face_collection.rb +1 -1
- data/lib/puppet/module.rb +14 -2
- data/lib/puppet/module_tool.rb +4 -4
- data/lib/puppet/module_tool/applications/builder.rb +3 -2
- data/lib/puppet/module_tool/applications/installer.rb +14 -14
- data/lib/puppet/module_tool/applications/upgrader.rb +13 -13
- data/lib/puppet/module_tool/installed_modules.rb +7 -7
- data/lib/puppet/module_tool/local_tarball.rb +3 -3
- data/lib/puppet/module_tool/metadata.rb +1 -1
- data/lib/puppet/network/http/connection.rb +2 -0
- data/lib/puppet/network/http/webrick.rb +2 -1
- data/lib/puppet/parser/functions/hiera.rb +14 -0
- data/lib/puppet/parser/functions/hiera_array.rb +14 -0
- data/lib/puppet/parser/functions/hiera_hash.rb +14 -0
- data/lib/puppet/parser/functions/hiera_include.rb +14 -0
- data/lib/puppet/parser/scope.rb +14 -20
- data/lib/puppet/plugins/data_providers.rb +2 -0
- data/lib/puppet/plugins/data_providers/data_provider.rb +108 -17
- data/lib/puppet/plugins/data_providers/registry.rb +2 -36
- data/lib/puppet/pops.rb +6 -9
- data/lib/puppet/pops/adaptable.rb +0 -3
- data/lib/puppet/pops/binder/producers.rb +3 -3
- data/lib/puppet/pops/evaluator/access_operator.rb +4 -4
- data/lib/puppet/pops/evaluator/closure.rb +1 -1
- data/lib/puppet/pops/evaluator/compare_operator.rb +4 -4
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +1 -1
- data/lib/puppet/pops/issues.rb +4 -0
- data/lib/puppet/pops/label_provider.rb +14 -0
- data/lib/puppet/pops/loader/loader_paths.rb +3 -1
- data/lib/puppet/pops/loader/module_loaders.rb +21 -7
- data/lib/puppet/pops/loader/typed_name.rb +0 -2
- data/lib/puppet/pops/loaders.rb +31 -12
- data/lib/puppet/pops/lookup.rb +4 -3
- data/lib/puppet/pops/lookup/configured_data_provider.rb +87 -0
- data/lib/puppet/pops/lookup/context.rb +121 -71
- data/lib/puppet/pops/lookup/data_adapter.rb +27 -0
- data/lib/puppet/pops/lookup/data_dig_function_provider.rb +55 -0
- data/lib/puppet/pops/lookup/data_hash_function_provider.rb +111 -0
- data/lib/puppet/pops/lookup/data_provider.rb +102 -0
- data/lib/puppet/pops/lookup/environment_data_provider.rb +27 -0
- data/lib/puppet/pops/lookup/explainer.rb +122 -82
- data/lib/puppet/pops/lookup/function_provider.rb +82 -0
- data/lib/puppet/pops/lookup/global_data_provider.rb +49 -0
- data/lib/puppet/pops/lookup/hiera_config.rb +601 -0
- data/lib/puppet/pops/lookup/interpolation.rb +56 -35
- data/lib/puppet/pops/lookup/invocation.rb +179 -101
- data/lib/puppet/pops/lookup/location_resolver.rb +72 -0
- data/lib/puppet/pops/lookup/lookup_adapter.rb +451 -0
- data/lib/puppet/pops/lookup/lookup_key.rb +99 -0
- data/lib/puppet/pops/lookup/lookup_key_function_provider.rb +119 -0
- data/lib/puppet/pops/lookup/module_data_provider.rb +58 -0
- data/lib/puppet/pops/lookup/sub_lookup.rb +8 -4
- data/lib/puppet/pops/merge_strategy.rb +120 -39
- data/lib/puppet/pops/parser/egrammar.ra +2 -0
- data/lib/puppet/pops/parser/eparser.rb +816 -808
- data/lib/puppet/pops/parser/locator.rb +3 -3
- data/lib/puppet/pops/parser/slurp_support.rb +4 -3
- data/lib/puppet/pops/pcore.rb +21 -12
- data/lib/puppet/pops/serialization/abstract_reader.rb +17 -7
- data/lib/puppet/pops/serialization/abstract_writer.rb +27 -12
- data/lib/puppet/pops/serialization/deserializer.rb +17 -4
- data/lib/puppet/pops/serialization/extension.rb +37 -8
- data/lib/puppet/pops/serialization/object.rb +14 -6
- data/lib/puppet/pops/serialization/rgen.rb +2 -1
- data/lib/puppet/pops/serialization/serializer.rb +30 -7
- data/lib/puppet/pops/types/implementation_registry.rb +1 -1
- data/lib/puppet/pops/types/p_object_type.rb +55 -12
- data/lib/puppet/pops/types/p_sem_ver_range_type.rb +27 -27
- data/lib/puppet/pops/types/p_sem_ver_type.rb +12 -12
- data/lib/puppet/pops/types/p_timespan_type.rb +6 -6
- data/lib/puppet/pops/types/p_timestamp_type.rb +2 -2
- data/lib/puppet/pops/types/p_type_set_type.rb +7 -16
- data/lib/puppet/pops/types/recursion_guard.rb +64 -20
- data/lib/puppet/pops/types/ruby_generator.rb +10 -0
- data/lib/puppet/pops/types/type_calculator.rb +23 -13
- data/lib/puppet/pops/types/type_factory.rb +20 -9
- data/lib/puppet/pops/types/type_formatter.rb +37 -17
- data/lib/puppet/pops/types/type_mismatch_describer.rb +7 -6
- data/lib/puppet/pops/types/type_parser.rb +6 -0
- data/lib/puppet/pops/types/types.rb +225 -132
- data/lib/puppet/pops/validation.rb +1 -1
- data/lib/puppet/pops/validation/checker4_0.rb +12 -2
- data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
- data/lib/puppet/pops/visitor.rb +4 -3
- data/lib/puppet/provider/mcx/mcxcontent.rb +2 -1
- data/lib/puppet/provider/nameservice.rb +15 -0
- data/lib/puppet/provider/package/appdmg.rb +1 -1
- data/lib/puppet/provider/package/dnf.rb +1 -1
- data/lib/puppet/provider/package/pkg.rb +1 -1
- data/lib/puppet/provider/package/pkgdmg.rb +1 -1
- data/lib/puppet/provider/package/pkgng.rb +1 -1
- data/lib/puppet/provider/package/rpm.rb +2 -2
- data/lib/puppet/provider/service/smf.rb +3 -3
- data/lib/puppet/provider/service/systemd.rb +5 -1
- data/lib/puppet/provider/user/directoryservice.rb +1 -0
- data/lib/puppet/provider/user/user_role_add.rb +15 -0
- data/lib/puppet/provider/yumrepo/inifile.rb +2 -2
- data/lib/puppet/provider/zone/solaris.rb +4 -1
- data/lib/puppet/reference/indirection.rb +1 -1
- data/lib/puppet/resource.rb +2 -3
- data/lib/puppet/resource/catalog.rb +12 -4
- data/lib/puppet/resource/type.rb +3 -3
- data/lib/puppet/settings.rb +1 -1
- data/lib/puppet/settings/config_file.rb +2 -1
- data/lib/puppet/settings/directory_setting.rb +6 -0
- data/lib/puppet/settings/environment_conf.rb +6 -2
- data/lib/puppet/settings/file_or_directory_setting.rb +6 -0
- data/lib/puppet/settings/file_setting.rb +10 -0
- data/lib/puppet/ssl/certificate_authority.rb +13 -2
- data/lib/puppet/ssl/host.rb +23 -1
- data/lib/puppet/transaction/additional_resource_generator.rb +7 -0
- data/lib/puppet/type/user.rb +16 -3
- data/lib/puppet/util.rb +1 -0
- data/lib/puppet/util/execution.rb +3 -3
- data/lib/puppet/util/filetype.rb +11 -5
- data/lib/puppet/util/logging.rb +2 -1
- data/lib/puppet/util/network_device/config.rb +1 -1
- data/lib/puppet/util/plist.rb +6 -0
- data/lib/puppet/util/profiler/aggregate.rb +1 -1
- data/lib/puppet/util/rdoc/generators/puppet_generator.rb +2 -2
- data/lib/puppet/util/rdoc/parser/puppet_parser_core.rb +2 -1
- data/lib/puppet/util/windows/adsi.rb +15 -12
- data/lib/puppet/vendor/load_semantic_puppet.rb +1 -0
- data/lib/puppet/vendor/pathspec/lib/pathspec.rb +2 -1
- data/lib/puppet/vendor/require_vendored.rb +0 -1
- data/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet.rb +17 -0
- data/lib/puppet/vendor/{semantic/lib/semantic → semantic_puppet/lib/semantic_puppet}/dependency.rb +7 -7
- data/lib/puppet/vendor/{semantic/lib/semantic → semantic_puppet/lib/semantic_puppet}/dependency/graph.rb +2 -2
- data/lib/puppet/vendor/{semantic/lib/semantic → semantic_puppet/lib/semantic_puppet}/dependency/graph_node.rb +2 -2
- data/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet/dependency/module_release.rb +58 -0
- data/lib/puppet/vendor/{semantic/lib/semantic → semantic_puppet/lib/semantic_puppet}/dependency/source.rb +2 -2
- data/lib/puppet/vendor/{semantic/lib/semantic → semantic_puppet/lib/semantic_puppet}/dependency/unsatisfiable_graph.rb +2 -2
- data/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet/gem_version.rb +3 -0
- data/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet/locales/config.yaml +21 -0
- data/lib/puppet/vendor/{semantic/lib/semantic → semantic_puppet/lib/semantic_puppet}/version.rb +48 -21
- data/lib/puppet/vendor/{semantic/lib/semantic → semantic_puppet/lib/semantic_puppet}/version_range.rb +15 -17
- data/lib/puppet/version.rb +1 -1
- data/lib/semver.rb +19 -12
- data/locales/config.yaml +29 -0
- data/locales/puppet.pot +79 -0
- data/man/man5/puppet.conf.5 +1 -1
- data/spec/fixtures/unit/application/environments/puppet_func_provider/functions/{data.pp → environment/data.pp} +0 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_misc/data/common.yaml +2 -0
- data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/two/data/common.yaml +1 -1
- data/spec/fixtures/unit/data_providers/environments/sample/modules/backend/hiera.yaml +5 -0
- data/spec/fixtures/unit/data_providers/environments/sample/modules/backend/lib/puppet/bindings/backend/default.rb +9 -0
- data/spec/fixtures/unit/data_providers/environments/sample/modules/backend/lib/puppet_x/backend/special_data_provider_factory.rb +23 -0
- data/spec/fixtures/unit/data_providers/environments/sample/modules/backend/manifests/init.pp +5 -0
- data/spec/fixtures/unit/data_providers/environments/sample/modules/backend/metadata.json +9 -0
- data/spec/fixtures/unit/data_providers/environments/sample/modules/dataprovider/lib/puppet_x/helindbe/sample_env_data.rb +1 -0
- data/spec/fixtures/unit/data_providers/environments/sample/modules/dataprovider/manifests/init.pp +1 -1
- data/spec/fixtures/unit/functions/lookup/data/common.yaml +19 -0
- data/spec/fixtures/unit/functions/lookup_fixture/data/common.yaml +19 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/environment.conf +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/lib/puppet/functions/environment/data.rb +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/abc/lib/puppet/bindings/abc/default.rb +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/abc/lib/puppet/functions/abc/data.rb +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/abc/manifests/init.pp +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/bad_data/lib/puppet/bindings/bad_data/default.rb +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/bad_data/lib/puppet/functions/bad_data/data.rb +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/bad_data/manifests/init.pp +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/bca/lib/puppet/bindings/bca/default.rb +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/bca/lib/puppet/functions/bca/data.rb +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/bca/manifests/init.pp +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_json/data/empty.json +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_json/hiera.yaml +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_json/manifests/init.pp +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_json/metadata.json +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_json/data/empty_key.json +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_json/hiera.yaml +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_json/manifests/init.pp +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_json/metadata.json +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_yaml/data/empty_key.yaml +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_yaml/hiera.yaml +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_yaml/manifests/init.pp +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_yaml/metadata.json +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_yaml/data/empty.yaml +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_yaml/hiera.yaml +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_yaml/manifests/init.pp +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_yaml/metadata.json +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/hieraprovider/data/first.json +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/hieraprovider/hiera.yaml +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/hieraprovider/manifests/init.pp +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/hieraprovider/metadata.json +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/meta/lib/puppet/functions/meta/data.rb +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/meta/manifests/init.pp +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/meta/metadata.json +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/metawcp/lib/puppet/bindings/metawcp/default.rb +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/metawcp/lib/puppet_x/thallgren/sample_module_data.rb +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/metawcp/manifests/init.pp +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/metawcp/metadata.json +0 -0
- data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/no_provider/manifests/init.pp +0 -0
- data/spec/integration/application/apply_spec.rb +88 -2
- data/spec/integration/application/lookup_spec.rb +155 -0
- data/spec/integration/data_binding_spec.rb +5 -5
- data/spec/integration/defaults_spec.rb +13 -0
- data/spec/integration/environments/default_manifest_spec.rb +16 -16
- data/spec/integration/environments/setting_hooks_spec.rb +1 -1
- data/spec/integration/test/test_helper_spec.rb +6 -2
- data/spec/integration/transaction_spec.rb +74 -0
- data/spec/integration/util/execution_spec.rb +8 -0
- data/spec/lib/puppet_spec/module_tool/shared_functions.rb +2 -2
- data/spec/lib/puppet_spec/module_tool/stub_source.rb +1 -1
- data/spec/lib/puppet_spec/unindent.rb +2 -2
- data/spec/unit/application/face_base_spec.rb +16 -0
- data/spec/unit/application/lookup_spec.rb +262 -227
- data/spec/unit/data_providers/{sample_data_provider_spec.rb → custom_data_provider_spec.rb} +14 -16
- data/spec/unit/data_providers/function_data_provider_spec.rb +2 -2
- data/spec/unit/data_providers/hiera_data_provider_spec.rb +60 -97
- data/spec/unit/defaults_spec.rb +1 -1
- data/spec/unit/face/ca_spec.rb +10 -0
- data/spec/unit/face/certificate_request_spec.rb +10 -0
- data/spec/unit/face/certificate_revocation_list_spec.rb +10 -0
- data/spec/unit/face/file_spec.rb +4 -0
- data/spec/unit/face/help_spec.rb +17 -0
- data/spec/unit/face/key_spec.rb +10 -0
- data/spec/unit/face/status_spec.rb +10 -0
- data/spec/unit/file_system_spec.rb +143 -6
- data/spec/unit/functions/binary_file_spec.rb +1 -1
- data/spec/unit/functions/hiera_spec.rb +257 -47
- data/spec/unit/functions/lookup_fixture_spec.rb +693 -0
- data/spec/unit/functions/lookup_spec.rb +1319 -608
- data/spec/unit/functions/new_spec.rb +3 -3
- data/spec/unit/graph/rb_tree_map_spec.rb +1 -1
- data/spec/unit/graph/simple_graph_spec.rb +1 -1
- data/spec/unit/hiera/scope_spec.rb +4 -4
- data/spec/unit/indirector/request_spec.rb +9 -0
- data/spec/unit/interface_spec.rb +27 -0
- data/spec/unit/man_spec.rb +1 -1
- data/spec/unit/module_spec.rb +1 -1
- data/spec/unit/module_tool/applications/builder_spec.rb +16 -1
- data/spec/unit/module_tool/applications/installer_spec.rb +1 -1
- data/spec/unit/module_tool/applications/upgrader_spec.rb +1 -1
- data/spec/unit/module_tool/installed_modules_spec.rb +6 -6
- data/spec/unit/module_tool_spec.rb +3 -3
- data/spec/unit/network/http/connection_spec.rb +10 -0
- data/spec/unit/network/http/webrick_spec.rb +1 -1
- data/spec/unit/pops/evaluator/access_ops_spec.rb +2 -2
- data/spec/unit/pops/evaluator/runtime3_converter_spec.rb +9 -9
- data/spec/unit/pops/loaders/environment_loader_spec.rb +172 -0
- data/spec/unit/pops/lookup/context_spec.rb +45 -16
- data/spec/unit/pops/lookup/interpolation_spec.rb +28 -20
- data/spec/unit/pops/lookup/lookup_spec.rb +197 -0
- data/spec/unit/pops/merge_strategy_spec.rb +18 -0
- data/spec/unit/pops/parser/lexer2_spec.rb +16 -1
- data/spec/unit/pops/parser/parse_site_spec.rb +4 -0
- data/spec/unit/pops/serialization/packer_spec.rb +4 -23
- data/spec/unit/pops/serialization/serialization_spec.rb +32 -8
- data/spec/unit/pops/types/p_object_type_spec.rb +68 -3
- data/spec/unit/pops/types/p_sem_ver_type_spec.rb +4 -4
- data/spec/unit/pops/types/p_type_set_type_spec.rb +31 -2
- data/spec/unit/pops/types/type_acceptor_spec.rb +18 -17
- data/spec/unit/pops/types/type_calculator_spec.rb +39 -40
- data/spec/unit/pops/types/type_factory_spec.rb +3 -3
- data/spec/unit/pops/types/type_formatter_spec.rb +7 -3
- data/spec/unit/pops/types/type_mismatch_describer_spec.rb +13 -2
- data/spec/unit/pops/types/types_spec.rb +25 -2
- data/spec/unit/pops/validator/validator_spec.rb +60 -4
- data/spec/unit/provider/nameservice_spec.rb +42 -0
- data/spec/unit/provider/package/aptrpm_spec.rb +1 -1
- data/spec/unit/provider/package/pkg_spec.rb +22 -0
- data/spec/unit/provider/package/pkgng_spec.rb +12 -0
- data/spec/unit/provider/package/rpm_spec.rb +8 -8
- data/spec/unit/provider/service/smf_spec.rb +13 -11
- data/spec/unit/provider/service/systemd_spec.rb +8 -1
- data/spec/unit/provider/user/useradd_spec.rb +1 -0
- data/spec/unit/puppet_spec.rb +14 -0
- data/spec/unit/resource/catalog_spec.rb +15 -9
- data/spec/unit/resource_spec.rb +20 -17
- data/spec/unit/semver_spec.rb +14 -0
- data/spec/unit/ssl/certificate_authority_spec.rb +12 -1
- data/spec/unit/transaction/additional_resource_generator_spec.rb +11 -0
- data/spec/unit/type/user_spec.rb +32 -6
- data/spec/unit/util/filetype_spec.rb +3 -3
- data/spec/unit/util/yaml_spec.rb +1 -1
- data/spec/unit/util_spec.rb +10 -2
- data/tasks/i18n.rake +20 -0
- metadata +2661 -2607
- data/lib/puppet/data_providers/lookup_adapter.rb +0 -254
- data/lib/puppet/vendor/load_semantic.rb +0 -1
- data/lib/puppet/vendor/semantic/Gemfile +0 -20
- data/lib/puppet/vendor/semantic/PUPPET_README.md +0 -6
- data/lib/puppet/vendor/semantic/Rakefile +0 -69
- data/lib/puppet/vendor/semantic/lib/semantic.rb +0 -7
- data/lib/puppet/vendor/semantic/lib/semantic/dependency/module_release.rb +0 -60
- data/lib/puppet/vendor/semantic/spec/spec_helper.rb +0 -24
- data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/graph_node_spec.rb +0 -141
- data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/graph_spec.rb +0 -162
- data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/module_release_spec.rb +0 -143
- data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/source_spec.rb +0 -5
- data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/unsatisfiable_graph_spec.rb +0 -44
- data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency_spec.rb +0 -383
- data/lib/puppet/vendor/semantic/spec/unit/semantic/version_range_spec.rb +0 -307
- data/lib/puppet/vendor/semantic/spec/unit/semantic/version_spec.rb +0 -608
- data/spec/fixtures/unit/data_providers/environments/sample/manifests/site.pp +0 -6
| @@ -1,733 +1,1444 @@ | |
| 1 1 | 
             
            #! /usr/bin/env ruby
         | 
| 2 2 | 
             
            require 'spec_helper'
         | 
| 3 3 | 
             
            require 'puppet_spec/compiler'
         | 
| 4 | 
            +
            require 'puppet_spec/files'
         | 
| 4 5 | 
             
            require 'puppet/pops'
         | 
| 6 | 
            +
            require 'deep_merge/core'
         | 
| 5 7 |  | 
| 6 | 
            -
            describe " | 
| 8 | 
            +
            describe "The lookup function" do
         | 
| 7 9 | 
             
              include PuppetSpec::Compiler
         | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
               | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
              # There is a fully configured 'production' environment in fixtures at this location
         | 
| 51 | 
            -
              let(:environmentpath) { File.join(my_fixture_dir, 'environments') }
         | 
| 52 | 
            -
              let(:node) { Puppet::Node.new("testnode", :facts => Puppet::Node::Facts.new("facts", {}), :environment => 'production') }
         | 
| 53 | 
            -
              let(:compiler) { Puppet::Parser::Compiler.new(node) }
         | 
| 54 | 
            -
             | 
| 55 | 
            -
              around(:each) do |example|
         | 
| 56 | 
            -
                # Initialize settings to get a full compile as close as possible to a real
         | 
| 57 | 
            -
                # environment load
         | 
| 58 | 
            -
                Puppet.settings.initialize_global_settings
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                # Initialize loaders based on the environmentpath. It does not work to
         | 
| 61 | 
            -
                # just set the setting environmentpath for some reason - this achieves the same:
         | 
| 62 | 
            -
                # - first a loader is created, loading directory environments from the fixture (there is
         | 
| 63 | 
            -
                # one environment, 'sample', which will be loaded since the node references this
         | 
| 64 | 
            -
                # environment by name).
         | 
| 65 | 
            -
                # - secondly, the created env loader is set as 'environments' in the puppet context.
         | 
| 66 | 
            -
                #
         | 
| 67 | 
            -
                environments = Puppet::Environments::Directories.new(environmentpath, [])
         | 
| 68 | 
            -
                Puppet.override(:environments => environments) do
         | 
| 69 | 
            -
                  example.run
         | 
| 10 | 
            +
              include PuppetSpec::Files
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              context 'with an environment' do
         | 
| 13 | 
            +
                let(:env_name) { 'spec' }
         | 
| 14 | 
            +
                let(:code_dir_files) { {} }
         | 
| 15 | 
            +
                let(:code_dir) { tmpdir('code') }
         | 
| 16 | 
            +
                let(:environment_files) do
         | 
| 17 | 
            +
                  {
         | 
| 18 | 
            +
                    env_name => {
         | 
| 19 | 
            +
                      'modules' => {},
         | 
| 20 | 
            +
                      'hiera.yaml' => <<-YAML.unindent,
         | 
| 21 | 
            +
                      ---
         | 
| 22 | 
            +
                      version: 5
         | 
| 23 | 
            +
                      hierarchy:
         | 
| 24 | 
            +
                        - name: "Common"
         | 
| 25 | 
            +
                          data_hash: yaml_data
         | 
| 26 | 
            +
                          path: "common.yaml"
         | 
| 27 | 
            +
                    YAML
         | 
| 28 | 
            +
                    'data' => {
         | 
| 29 | 
            +
                      'common.yaml' => <<-YAML.unindent
         | 
| 30 | 
            +
                        ---
         | 
| 31 | 
            +
                        a: value a
         | 
| 32 | 
            +
                        mod_a::a: value mod_a::a (from environment)
         | 
| 33 | 
            +
                        mod_a::hash_a:
         | 
| 34 | 
            +
                          a: value mod_a::hash_a.a (from environment)
         | 
| 35 | 
            +
                        mod_a::hash_b:
         | 
| 36 | 
            +
                          a: value mod_a::hash_b.a (from environment)
         | 
| 37 | 
            +
                        hash_b:
         | 
| 38 | 
            +
                          hash_ba:
         | 
| 39 | 
            +
                            bab: value hash_b.hash_ba.bab (from environment)
         | 
| 40 | 
            +
                        hash_c:
         | 
| 41 | 
            +
                          hash_ca:
         | 
| 42 | 
            +
                            caa: value hash_c.hash_ca.caa (from environment)
         | 
| 43 | 
            +
                        lookup_options:
         | 
| 44 | 
            +
                          mod_a::hash_b:
         | 
| 45 | 
            +
                            merge: hash
         | 
| 46 | 
            +
                          hash_c:
         | 
| 47 | 
            +
                            merge: hash
         | 
| 48 | 
            +
                        YAML
         | 
| 49 | 
            +
                      }
         | 
| 50 | 
            +
                    }
         | 
| 51 | 
            +
                  }
         | 
| 70 52 | 
             
                end
         | 
| 71 | 
            -
              end
         | 
| 72 53 |  | 
| 73 | 
            -
             | 
| 74 | 
            -
                 | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 54 | 
            +
                let(:logs) { [] }
         | 
| 55 | 
            +
                let(:notices) { logs.select { |log| log.level == :notice }.map { |log| log.message } }
         | 
| 56 | 
            +
                let(:warnings) { logs.select { |log| log.level == :warning }.map { |log| log.message } }
         | 
| 57 | 
            +
                let(:debugs) { logs.select { |log| log.level == :debug }.map { |log| log.message } }
         | 
| 58 | 
            +
                let(:env) { Puppet::Node::Environment.create(env_name.to_sym, [File.join(populated_env_dir, env_name, 'modules')]) }
         | 
| 59 | 
            +
                let(:environments) { Puppet::Environments::Directories.new(populated_env_dir, []) }
         | 
| 60 | 
            +
                let(:node) { Puppet::Node.new('test_lookup', :environment => env) }
         | 
| 61 | 
            +
                let(:compiler) { Puppet::Parser::Compiler.new(node) }
         | 
| 62 | 
            +
                let(:lookup_func) { Puppet.lookup(:loaders).puppet_system_loader.load(:function, 'lookup') }
         | 
| 63 | 
            +
                let(:defaults) {
         | 
| 64 | 
            +
                  {
         | 
| 65 | 
            +
                    'mod_a::xd' => 'value mod_a::xd (from default)',
         | 
| 66 | 
            +
                    'mod_a::xd_found' => 'value mod_a::xd_found (from default)',
         | 
| 67 | 
            +
                    'scope_xd' => 'value scope_xd (from default)'
         | 
| 68 | 
            +
                  }}
         | 
| 69 | 
            +
                let(:overrides) {
         | 
| 70 | 
            +
                  {
         | 
| 71 | 
            +
                    'mod_a::xo' => 'value mod_a::xo (from override)',
         | 
| 72 | 
            +
                    'scope_xo' => 'value scope_xo (from override)'
         | 
| 73 | 
            +
                  }}
         | 
| 74 | 
            +
                let(:invocation_with_explain) { Puppet::Pops::Lookup::Invocation.new(compiler.topscope, {}, {}, true) }
         | 
| 75 | 
            +
                let(:explanation) { invocation_with_explain.explainer.explain }
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                let(:populated_code_dir) do
         | 
| 78 | 
            +
                  dir_contained_in(code_dir, code_dir_files)
         | 
| 79 | 
            +
                  code_dir
         | 
| 77 80 | 
             
                end
         | 
| 78 81 |  | 
| 79 | 
            -
                 | 
| 80 | 
            -
                   | 
| 81 | 
            -
                   | 
| 82 | 
            +
                let(:env_dir) do
         | 
| 83 | 
            +
                  d = File.join(populated_code_dir, 'environments')
         | 
| 84 | 
            +
                  Dir.mkdir(d)
         | 
| 85 | 
            +
                  d
         | 
| 82 86 | 
             
                end
         | 
| 83 87 |  | 
| 84 | 
            -
                 | 
| 85 | 
            -
                   | 
| 86 | 
            -
                   | 
| 88 | 
            +
                let(:populated_env_dir) do
         | 
| 89 | 
            +
                  dir_contained_in(env_dir, environment_files)
         | 
| 90 | 
            +
                  env_dir
         | 
| 87 91 | 
             
                end
         | 
| 88 92 |  | 
| 89 | 
            -
                 | 
| 90 | 
            -
                   | 
| 91 | 
            -
                   | 
| 93 | 
            +
                before(:each) do
         | 
| 94 | 
            +
                  Puppet.settings[:codedir] = code_dir
         | 
| 95 | 
            +
                  Puppet.push_context(:environments => environments, :current_environment => env)
         | 
| 92 96 | 
             
                end
         | 
| 93 97 |  | 
| 94 | 
            -
                 | 
| 95 | 
            -
                   | 
| 96 | 
            -
                   | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 98 | 
            +
                after(:each) do
         | 
| 99 | 
            +
                  Puppet.pop_context
         | 
| 100 | 
            +
                  if Object.const_defined?(:Hiera)
         | 
| 101 | 
            +
                    Hiera.send(:remove_instance_variable, :@config) if Hiera.instance_variable_defined?(:@config)
         | 
| 102 | 
            +
                    Hiera.send(:remove_instance_variable, :@logger) if Hiera.instance_variable_defined?(:@logger)
         | 
| 103 | 
            +
                    if Hiera.const_defined?(:Config)
         | 
| 104 | 
            +
                      Hiera::Config.send(:remove_instance_variable, :@config) if Hiera::Config.instance_variable_defined?(:@config)
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                    if Hiera.const_defined?(:Backend)
         | 
| 107 | 
            +
                      Hiera::Backend.clear!
         | 
| 108 | 
            +
                    end
         | 
| 109 | 
            +
                  end
         | 
| 99 110 | 
             
                end
         | 
| 100 111 |  | 
| 101 | 
            -
                 | 
| 102 | 
            -
                   | 
| 103 | 
            -
                   | 
| 112 | 
            +
                def collect_notices(code, explain = false, &block)
         | 
| 113 | 
            +
                  Puppet[:code] = code
         | 
| 114 | 
            +
                  Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
         | 
| 115 | 
            +
                    scope = compiler.topscope
         | 
| 116 | 
            +
                    scope['environment'] = env_name
         | 
| 117 | 
            +
                    scope['domain'] = 'example.com'
         | 
| 118 | 
            +
                    scope['scope_scalar'] = 'scope scalar value'
         | 
| 119 | 
            +
                    scope['scope_hash'] = { 'a' => 'scope hash a', 'b' => 'scope hash b' }
         | 
| 120 | 
            +
                    if explain
         | 
| 121 | 
            +
                      begin
         | 
| 122 | 
            +
                        invocation_with_explain.lookup('dummy', nil) do
         | 
| 123 | 
            +
                          if block_given?
         | 
| 124 | 
            +
                            compiler.compile { |catalog| block.call(compiler.topscope); catalog }
         | 
| 125 | 
            +
                          else
         | 
| 126 | 
            +
                            compiler.compile
         | 
| 127 | 
            +
                          end
         | 
| 128 | 
            +
                        end
         | 
| 129 | 
            +
                      rescue Puppet::DataBinding::LookupError => e
         | 
| 130 | 
            +
                        invocation_with_explain.report_text { e.message }
         | 
| 131 | 
            +
                      end
         | 
| 132 | 
            +
                    else
         | 
| 133 | 
            +
                      if block_given?
         | 
| 134 | 
            +
                        compiler.compile { |catalog| block.call(compiler.topscope); catalog }
         | 
| 135 | 
            +
                      else
         | 
| 136 | 
            +
                        compiler.compile
         | 
| 137 | 
            +
                      end
         | 
| 138 | 
            +
                    end
         | 
| 139 | 
            +
                  end
         | 
| 140 | 
            +
                  nil
         | 
| 104 141 | 
             
                end
         | 
| 105 142 |  | 
| 106 | 
            -
                 | 
| 107 | 
            -
                   | 
| 108 | 
            -
                   | 
| 143 | 
            +
                def lookup(key, options = {}, explain = false)
         | 
| 144 | 
            +
                  nc_opts = options.empty? ? '' : ", #{Puppet::Pops::Types::TypeFormatter.string(options)}"
         | 
| 145 | 
            +
                  keys = key.is_a?(Array) ? key : [key]
         | 
| 146 | 
            +
                  collect_notices(keys.map { |k| "notice(String(lookup('#{k}'#{nc_opts}), '%p'))" }.join("\n"), explain)
         | 
| 147 | 
            +
                  if explain
         | 
| 148 | 
            +
                    explanation
         | 
| 149 | 
            +
                  else
         | 
| 150 | 
            +
                    result = notices.map { |n| Puppet::Pops::Types::TypeParser.singleton.parse_literal(n) }
         | 
| 151 | 
            +
                    key.is_a?(Array) ? result : result[0]
         | 
| 152 | 
            +
                  end
         | 
| 109 153 | 
             
                end
         | 
| 110 154 |  | 
| 111 | 
            -
                 | 
| 112 | 
            -
                   | 
| 113 | 
            -
                   | 
| 155 | 
            +
                def explain(key, options = {})
         | 
| 156 | 
            +
                  lookup(key, options, true)[1]
         | 
| 157 | 
            +
                  explanation
         | 
| 114 158 | 
             
                end
         | 
| 115 159 |  | 
| 116 | 
            -
                it  | 
| 117 | 
            -
                   | 
| 118 | 
            -
                  expect(resources).to include('env_d1_env_d2_env_d3')
         | 
| 160 | 
            +
                it 'finds data in the environment' do
         | 
| 161 | 
            +
                  expect(lookup('a')).to eql('value a')
         | 
| 119 162 | 
             
                end
         | 
| 120 163 |  | 
| 121 | 
            -
                 | 
| 122 | 
            -
                   | 
| 123 | 
            -
             | 
| 124 | 
            -
             | 
| 164 | 
            +
                context 'that has no lookup configured' do
         | 
| 165 | 
            +
                  let(:environment_files) do
         | 
| 166 | 
            +
                    {
         | 
| 167 | 
            +
                      env_name => {
         | 
| 168 | 
            +
                        'modules' => {},
         | 
| 169 | 
            +
                        'data' => {
         | 
| 170 | 
            +
                          'common.yaml' => <<-YAML.unindent
         | 
| 171 | 
            +
                          ---
         | 
| 172 | 
            +
                          a: value a
         | 
| 173 | 
            +
                        YAML
         | 
| 174 | 
            +
                        }
         | 
| 175 | 
            +
                      }
         | 
| 176 | 
            +
                    }
         | 
| 177 | 
            +
                  end
         | 
| 125 178 |  | 
| 126 | 
            -
             | 
| 127 | 
            -
             | 
| 128 | 
            -
                   | 
| 129 | 
            -
                  resources = assemble_and_compile('${r[k1]}_${r[k2]}_${r[k3]}', "'abc::e'", 'Hash[String,String]', "'hash'")
         | 
| 130 | 
            -
                  expect(resources).to include('global_e1_module_e2_env_e3')
         | 
| 131 | 
            -
                end
         | 
| 179 | 
            +
                  it 'does not find data in the environment' do
         | 
| 180 | 
            +
                    expect { lookup('a') }.to raise_error(Puppet::DataBinding::LookupError, /did not find a value for the name 'a'/)
         | 
| 181 | 
            +
                  end
         | 
| 132 182 |  | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 183 | 
            +
                  context "but an environment.conf with 'environment_data_provider=hiera'" do
         | 
| 184 | 
            +
                    let(:environment_files_1) do
         | 
| 185 | 
            +
                      DeepMerge.deep_merge!(environment_files, 'environment.conf' => "environment_data_provider=hiera\n")
         | 
| 186 | 
            +
                    end
         | 
| 137 187 |  | 
| 138 | 
            -
             | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 188 | 
            +
                    let(:populated_env_dir) do
         | 
| 189 | 
            +
                      dir_contained_in(env_dir, DeepMerge.deep_merge!(environment_files, env_name => environment_files_1))
         | 
| 190 | 
            +
                      env_dir
         | 
| 191 | 
            +
                    end
         | 
| 142 192 |  | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 193 | 
            +
                    it 'finds data in the environment and reports deprecation warning for environment.conf' do
         | 
| 194 | 
            +
                      expect(lookup('a')).to eql('value a')
         | 
| 195 | 
            +
                      expect(warnings).to include(/Defining environment_data_provider='hiera' in environment.conf is deprecated. A 'hiera.yaml' file should be used instead/)
         | 
| 196 | 
            +
                    end
         | 
| 147 197 |  | 
| 148 | 
            -
             | 
| 149 | 
            -
             | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 198 | 
            +
                    context 'and a hiera.yaml file' do
         | 
| 199 | 
            +
                      let(:environment_files_2) { DeepMerge.deep_merge!(environment_files_1,'hiera.yaml' => <<-YAML.unindent) }
         | 
| 200 | 
            +
                        ---
         | 
| 201 | 
            +
                        version: 4
         | 
| 202 | 
            +
                        hierarchy:
         | 
| 203 | 
            +
                          - name: common
         | 
| 204 | 
            +
                            backend: yaml
         | 
| 205 | 
            +
                        YAML
         | 
| 206 | 
            +
             | 
| 207 | 
            +
                      let(:populated_env_dir) do
         | 
| 208 | 
            +
                        dir_contained_in(env_dir, DeepMerge.deep_merge!(environment_files, env_name => environment_files_2))
         | 
| 209 | 
            +
                        env_dir
         | 
| 210 | 
            +
                      end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                      it 'finds data in the environment and reports deprecation warnings for both environment.conf and hiera.yaml' do
         | 
| 213 | 
            +
                        expect(lookup('a')).to eql('value a')
         | 
| 214 | 
            +
                        expect(warnings).to include(/Defining environment_data_provider='hiera' in environment.conf is deprecated/)
         | 
| 215 | 
            +
                        expect(warnings).to include(/Use of 'hiera.yaml' version 4 is deprecated. It should be converted to version 5/)
         | 
| 216 | 
            +
                      end
         | 
| 217 | 
            +
                    end
         | 
| 218 | 
            +
                  end
         | 
| 153 219 |  | 
| 154 | 
            -
             | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 157 | 
            -
             | 
| 158 | 
            -
             | 
| 220 | 
            +
                  context "but an environment.conf with 'environment_data_provider=function'" do
         | 
| 221 | 
            +
                    let(:environment_files) do
         | 
| 222 | 
            +
                      {
         | 
| 223 | 
            +
                        env_name => {
         | 
| 224 | 
            +
                          'environment.conf' => "environment_data_provider=function\n",
         | 
| 225 | 
            +
                          'functions' => {
         | 
| 226 | 
            +
                            'environment' => { 'data.pp' => <<-PUPPET.unindent }
         | 
| 227 | 
            +
                                function environment::data() {
         | 
| 228 | 
            +
                                  { 'a' => 'value a' }
         | 
| 229 | 
            +
                                }
         | 
| 230 | 
            +
                                PUPPET
         | 
| 231 | 
            +
                          }
         | 
| 232 | 
            +
                        }
         | 
| 233 | 
            +
                      }
         | 
| 234 | 
            +
                    end
         | 
| 159 235 |  | 
| 160 | 
            -
             | 
| 161 | 
            -
             | 
| 162 | 
            -
             | 
| 236 | 
            +
                    it 'finds data in the environment and reports deprecation warning for environment.conf' do
         | 
| 237 | 
            +
                      expect(lookup('a')).to eql('value a')
         | 
| 238 | 
            +
                      expect(warnings).to include(/Defining environment_data_provider='function' in environment.conf is deprecated. A 'hiera.yaml' file should be used instead/)
         | 
| 239 | 
            +
                      expect(warnings).to include(/Using of legacy data provider function 'environment::data'. Please convert to a 'data_hash' function/)
         | 
| 240 | 
            +
                    end
         | 
| 241 | 
            +
                  end
         | 
| 163 242 | 
             
                end
         | 
| 164 243 |  | 
| 165 | 
            -
                 | 
| 166 | 
            -
                   | 
| 167 | 
            -
             | 
| 168 | 
            -
             | 
| 244 | 
            +
                context 'that has interpolated paths configured' do
         | 
| 245 | 
            +
                  let(:environment_files) do
         | 
| 246 | 
            +
                    {
         | 
| 247 | 
            +
                      env_name => {
         | 
| 248 | 
            +
                        'hiera.yaml' => <<-YAML.unindent,
         | 
| 249 | 
            +
                          ---
         | 
| 250 | 
            +
                          version: 5
         | 
| 251 | 
            +
                          hierarchy:
         | 
| 252 | 
            +
                            - name: "Varying"
         | 
| 253 | 
            +
                              data_hash: yaml_data
         | 
| 254 | 
            +
                              path: "x%{::var}.yaml"
         | 
| 255 | 
            +
                          YAML
         | 
| 256 | 
            +
                        'modules' => {},
         | 
| 257 | 
            +
                        'data' => {
         | 
| 258 | 
            +
                          'x.yaml' => <<-YAML.unindent,
         | 
| 259 | 
            +
                            y: value y from x
         | 
| 260 | 
            +
                          YAML
         | 
| 261 | 
            +
                          'x_d.yaml' => <<-YAML.unindent
         | 
| 262 | 
            +
                            y: value y from x_d
         | 
| 263 | 
            +
                          YAML
         | 
| 264 | 
            +
                        }
         | 
| 265 | 
            +
                      }
         | 
| 266 | 
            +
                    }
         | 
| 267 | 
            +
                  end
         | 
| 169 268 |  | 
| 170 | 
            -
             | 
| 171 | 
            -
             | 
| 172 | 
            -
                     | 
| 173 | 
            -
             | 
| 269 | 
            +
                  it 'reloads the configuration if interpolated values change' do
         | 
| 270 | 
            +
                    Puppet[:log_level] = 'debug'
         | 
| 271 | 
            +
                    collect_notices("notice('success')") do |scope|
         | 
| 272 | 
            +
                      expect(lookup_func.call(scope, 'y')).to eql('value y from x')
         | 
| 273 | 
            +
                      scope['var'] = '_d'
         | 
| 274 | 
            +
                      expect(lookup_func.call(scope, 'y')).to eql('value y from x_d')
         | 
| 275 | 
            +
                    end
         | 
| 276 | 
            +
                    expect(notices).to eql(['success'])
         | 
| 277 | 
            +
                    expect(debugs.any? { |m| m =~ /Hiera configuration recreated due to change of scope variables used in interpolation expressions/ }).to be_truthy
         | 
| 278 | 
            +
                  end
         | 
| 174 279 | 
             
                end
         | 
| 175 280 |  | 
| 176 | 
            -
                 | 
| 177 | 
            -
                   | 
| 178 | 
            -
                     | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 281 | 
            +
                context 'that uses reserved option' do
         | 
| 282 | 
            +
                  let(:environment_files) do
         | 
| 283 | 
            +
                    {
         | 
| 284 | 
            +
                      env_name => {
         | 
| 285 | 
            +
                        'hiera.yaml' => <<-YAML.unindent,
         | 
| 286 | 
            +
                          ---
         | 
| 287 | 
            +
                          version: 5
         | 
| 288 | 
            +
                          hierarchy:
         | 
| 289 | 
            +
                            - name: "Illegal"
         | 
| 290 | 
            +
                              options:
         | 
| 291 | 
            +
                                #{opt_spec}
         | 
| 292 | 
            +
                              data_hash: yaml_data
         | 
| 293 | 
            +
                          YAML
         | 
| 294 | 
            +
                        'data' => {
         | 
| 295 | 
            +
                          'foo.yaml' => "a: The value a\n"
         | 
| 296 | 
            +
                        }
         | 
| 297 | 
            +
                      }
         | 
| 298 | 
            +
                    }
         | 
| 299 | 
            +
                  end
         | 
| 181 300 |  | 
| 182 | 
            -
             | 
| 183 | 
            -
             | 
| 184 | 
            -
                  expect(resources).to include('env_d1_env_d2_env_d3')
         | 
| 185 | 
            -
                end
         | 
| 301 | 
            +
                  context 'path' do
         | 
| 302 | 
            +
                    let(:opt_spec) { 'path: data/foo.yaml' }
         | 
| 186 303 |  | 
| 187 | 
            -
             | 
| 188 | 
            -
             | 
| 189 | 
            -
             | 
| 190 | 
            -
             | 
| 304 | 
            +
                    it 'fails and reports the reserved option key' do
         | 
| 305 | 
            +
                      expect { lookup('a') }.to raise_error do |e|
         | 
| 306 | 
            +
                        expect(e.message).to match(/Option key 'path' used in hierarchy 'Illegal' is reserved by Puppet/)
         | 
| 307 | 
            +
                      end
         | 
| 308 | 
            +
                    end
         | 
| 309 | 
            +
                  end
         | 
| 191 310 |  | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 194 | 
            -
                  Hiera.any_instance.expects(:lookup).with('abc::f', any_parameters).returns({ 'k1' => { 's1' => 'global_f11' }, 'k2' => { 's3' => 'global_f23' }})
         | 
| 195 | 
            -
                  resources = assemble_and_compile('${r[k1][s1]}_${r[k1][s2]}_${r[k1][s3]}_${r[k2][s1]}_${r[k2][s2]}_${r[k2][s3]}', "'abc::f'", 'Hash[String,Hash[String,String]]', "'deep'")
         | 
| 196 | 
            -
                  expect(resources).to include('global_f11_env_f12_module_f13_env_f21_module_f22_global_f23')
         | 
| 197 | 
            -
                end
         | 
| 311 | 
            +
                  context 'uri' do
         | 
| 312 | 
            +
                    let(:opt_spec) { 'uri: file:///data/foo.yaml' }
         | 
| 198 313 |  | 
| 199 | 
            -
             | 
| 200 | 
            -
             | 
| 201 | 
            -
             | 
| 202 | 
            -
             | 
| 203 | 
            -
             | 
| 314 | 
            +
                    it 'fails and reports the reserved option key' do
         | 
| 315 | 
            +
                      expect { lookup('a') }.to raise_error do |e|
         | 
| 316 | 
            +
                        expect(e.message).to match(/Option key 'uri' used in hierarchy 'Illegal' is reserved by Puppet/)
         | 
| 317 | 
            +
                      end
         | 
| 318 | 
            +
                    end
         | 
| 319 | 
            +
                  end
         | 
| 204 320 | 
             
                end
         | 
| 205 321 |  | 
| 206 | 
            -
                it 'will propagate a Hash resolution_type with :behavior => :native to Hiera when merge == \'hash\''  do
         | 
| 207 | 
            -
                  Hiera.any_instance.expects(:lookup).with('lookup_options', any_parameters).at_most_once.throws(:no_such_key)
         | 
| 208 | 
            -
                  Hiera.any_instance.expects(:lookup).with('abc::e', anything, anything, anything, { :behavior => :native }).returns({ 'k1' => 'global_e1' })
         | 
| 209 | 
            -
                  resources = assemble_and_compile('${r[k1]}_${r[k2]}_${r[k3]}', "'abc::e'", 'Hash[String,String]', "{strategy => 'hash'}")
         | 
| 210 | 
            -
                  expect(resources).to include('global_e1_module_e2_env_e3')
         | 
| 211 | 
            -
                end
         | 
| 212 322 |  | 
| 213 | 
            -
                 | 
| 214 | 
            -
                   | 
| 215 | 
            -
             | 
| 216 | 
            -
             | 
| 217 | 
            -
             | 
| 218 | 
            -
             | 
| 323 | 
            +
                context 'with lookup_options configured using patterns' do
         | 
| 324 | 
            +
                  let(:mod_common) {
         | 
| 325 | 
            +
                    <<-YAML.unindent
         | 
| 326 | 
            +
                      mod::hash_a:
         | 
| 327 | 
            +
                        aa:
         | 
| 328 | 
            +
                          aaa: aaa (from module)
         | 
| 329 | 
            +
                        ab:
         | 
| 330 | 
            +
                          aba: aba (from module)
         | 
| 331 | 
            +
                      mod::hash_b:
         | 
| 332 | 
            +
                        ba:
         | 
| 333 | 
            +
                          baa: baa (from module)
         | 
| 334 | 
            +
                        bb:
         | 
| 335 | 
            +
                          bba: bba (from module)
         | 
| 336 | 
            +
                      lookup_options:
         | 
| 337 | 
            +
                        '^mod::ha.*_a':
         | 
| 338 | 
            +
                          merge: deep
         | 
| 339 | 
            +
                        '^mod::ha.*_b':
         | 
| 340 | 
            +
                          merge: deep
         | 
| 341 | 
            +
                    YAML
         | 
| 342 | 
            +
                  }
         | 
| 219 343 |  | 
| 220 | 
            -
             | 
| 221 | 
            -
             | 
| 222 | 
            -
             | 
| 223 | 
            -
             | 
| 224 | 
            -
             | 
| 225 | 
            -
             | 
| 344 | 
            +
                  let(:mod_base) do
         | 
| 345 | 
            +
                    {
         | 
| 346 | 
            +
                      'hiera.yaml' => <<-YAML.unindent,
         | 
| 347 | 
            +
                        version: 5
         | 
| 348 | 
            +
                        YAML
         | 
| 349 | 
            +
                      'data' => {
         | 
| 350 | 
            +
                        'common.yaml' => mod_common
         | 
| 351 | 
            +
                      }
         | 
| 352 | 
            +
                    }
         | 
| 353 | 
            +
                  end
         | 
| 226 354 |  | 
| 227 | 
            -
             | 
| 228 | 
            -
             | 
| 229 | 
            -
             | 
| 230 | 
            -
             | 
| 355 | 
            +
                  let(:environment_files) do
         | 
| 356 | 
            +
                    {
         | 
| 357 | 
            +
                      env_name => {
         | 
| 358 | 
            +
                        'hiera.yaml' => <<-YAML.unindent,
         | 
| 359 | 
            +
                          ---
         | 
| 360 | 
            +
                          version: 5
         | 
| 361 | 
            +
                          hierarchy:
         | 
| 362 | 
            +
                            - name: X
         | 
| 363 | 
            +
                              paths:
         | 
| 364 | 
            +
                              - first.yaml
         | 
| 365 | 
            +
                              - second.yaml
         | 
| 366 | 
            +
                          YAML
         | 
| 367 | 
            +
                        'data' => {
         | 
| 368 | 
            +
                          'first.yaml' => <<-YAML.unindent,
         | 
| 369 | 
            +
                            a:
         | 
| 370 | 
            +
                              aa:
         | 
| 371 | 
            +
                                aaa: a.aa.aaa
         | 
| 372 | 
            +
                            b:
         | 
| 373 | 
            +
                              ba:
         | 
| 374 | 
            +
                                baa: b.ba.baa
         | 
| 375 | 
            +
                              bb:
         | 
| 376 | 
            +
                                bba: b.bb.bba
         | 
| 377 | 
            +
                            c:
         | 
| 378 | 
            +
                              ca:
         | 
| 379 | 
            +
                                caa: c.ca.caa
         | 
| 380 | 
            +
                            mod::hash_a:
         | 
| 381 | 
            +
                              aa:
         | 
| 382 | 
            +
                                aab: aab (from environment)
         | 
| 383 | 
            +
                              ab:
         | 
| 384 | 
            +
                                aba: aba (from environment)
         | 
| 385 | 
            +
                                abb: abb (from environment)
         | 
| 386 | 
            +
                            mod::hash_b:
         | 
| 387 | 
            +
                              ba:
         | 
| 388 | 
            +
                                bab: bab (from environment)
         | 
| 389 | 
            +
                              bc:
         | 
| 390 | 
            +
                                bca: bca (from environment)
         | 
| 391 | 
            +
                            lookup_options:
         | 
| 392 | 
            +
                              b:
         | 
| 393 | 
            +
                                merge: hash
         | 
| 394 | 
            +
                              '^[^b]$':
         | 
| 395 | 
            +
                                 merge: deep
         | 
| 396 | 
            +
                              '^c':
         | 
| 397 | 
            +
                                 merge: first
         | 
| 398 | 
            +
                              '^b':
         | 
| 399 | 
            +
                                 merge: first
         | 
| 400 | 
            +
                              '^mod::ha.*_b':
         | 
| 401 | 
            +
                                merge: hash
         | 
| 402 | 
            +
                            YAML
         | 
| 403 | 
            +
                          'second.yaml' => <<-YAML.unindent,
         | 
| 404 | 
            +
                            a:
         | 
| 405 | 
            +
                              aa:
         | 
| 406 | 
            +
                                aab: a.aa.aab
         | 
| 407 | 
            +
                            b:
         | 
| 408 | 
            +
                              ba:
         | 
| 409 | 
            +
                                bab: b.ba.bab
         | 
| 410 | 
            +
                              bb:
         | 
| 411 | 
            +
                                bbb: b.bb.bbb
         | 
| 412 | 
            +
                            c:
         | 
| 413 | 
            +
                              ca:
         | 
| 414 | 
            +
                                cab: c.ca.cab
         | 
| 415 | 
            +
                            YAML
         | 
| 416 | 
            +
                        },
         | 
| 417 | 
            +
                        'modules' => {
         | 
| 418 | 
            +
                          'mod' => mod_base
         | 
| 419 | 
            +
                        }
         | 
| 420 | 
            +
                      }
         | 
| 421 | 
            +
                    }
         | 
| 231 422 | 
             
                  end
         | 
| 232 423 |  | 
| 233 | 
            -
                  it ' | 
| 234 | 
            -
                     | 
| 235 | 
            -
                    expect(resources).to include('dflt_x')
         | 
| 424 | 
            +
                  it 'finds lookup_options that matches a pattern' do
         | 
| 425 | 
            +
                    expect(lookup('a')).to eql({'aa' => { 'aaa' => 'a.aa.aaa', 'aab' => 'a.aa.aab' }})
         | 
| 236 426 | 
             
                  end
         | 
| 237 427 |  | 
| 238 | 
            -
                  it ' | 
| 239 | 
            -
                     | 
| 240 | 
            -
                    expect(resources).to include('dflt_x_dflt_y')
         | 
| 428 | 
            +
                  it 'gives a direct key match higher priority than a matching pattern' do
         | 
| 429 | 
            +
                    expect(lookup('b')).to eql({'ba' => { 'baa' => 'b.ba.baa' }, 'bb' => { 'bba'=>'b.bb.bba' }})
         | 
| 241 430 | 
             
                  end
         | 
| 242 431 |  | 
| 243 | 
            -
                  it ' | 
| 244 | 
            -
                     | 
| 245 | 
            -
                    expect(resources).to include('dflt_x_dflt_y')
         | 
| 432 | 
            +
                  it 'uses the first matching pattern' do
         | 
| 433 | 
            +
                    expect(lookup('c')).to eql({'ca' => { 'caa' => 'c.ca.caa', 'cab' => 'c.ca.cab' }})
         | 
| 246 434 | 
             
                  end
         | 
| 247 435 |  | 
| 248 | 
            -
                  it ' | 
| 249 | 
            -
                    expect  | 
| 250 | 
            -
                       | 
| 251 | 
            -
             | 
| 252 | 
            -
             | 
| 436 | 
            +
                  it 'uses lookup_option found by pattern from module' do
         | 
| 437 | 
            +
                    expect(lookup('mod::hash_a')).to eql({
         | 
| 438 | 
            +
                      'aa' => {
         | 
| 439 | 
            +
                        'aaa' => 'aaa (from module)',
         | 
| 440 | 
            +
                        'aab' => 'aab (from environment)'
         | 
| 441 | 
            +
                      },
         | 
| 442 | 
            +
                      'ab' => {
         | 
| 443 | 
            +
                        'aba' => 'aba (from environment)',
         | 
| 444 | 
            +
                        'abb' => 'abb (from environment)'
         | 
| 445 | 
            +
                      }
         | 
| 446 | 
            +
                    })
         | 
| 447 | 
            +
                  end
         | 
| 448 | 
            +
             | 
| 449 | 
            +
                  it 'merges lookup_options found by pattern in environment and module (environment wins)' do
         | 
| 450 | 
            +
                    expect(lookup('mod::hash_b')).to eql({
         | 
| 451 | 
            +
                      'ba' => {
         | 
| 452 | 
            +
                        'bab' => 'bab (from environment)'
         | 
| 453 | 
            +
                      },
         | 
| 454 | 
            +
                      'bb' => {
         | 
| 455 | 
            +
                        'bba' => 'bba (from module)'
         | 
| 456 | 
            +
                      },
         | 
| 457 | 
            +
                      'bc' => {
         | 
| 458 | 
            +
                        'bca' => 'bca (from environment)'
         | 
| 459 | 
            +
                      }
         | 
| 460 | 
            +
                    })
         | 
| 461 | 
            +
                  end
         | 
| 462 | 
            +
             | 
| 463 | 
            +
                  context 'and patterns in module are not limited to module keys' do
         | 
| 464 | 
            +
                    let(:mod_common) {
         | 
| 465 | 
            +
                      <<-YAML.unindent
         | 
| 466 | 
            +
                      mod::hash_a:
         | 
| 467 | 
            +
                        aa:
         | 
| 468 | 
            +
                          aaa: aaa (from module)
         | 
| 469 | 
            +
                        ab:
         | 
| 470 | 
            +
                          aba: aba (from module)
         | 
| 471 | 
            +
                      lookup_options:
         | 
| 472 | 
            +
                        '^.*_a':
         | 
| 473 | 
            +
                          merge: deep
         | 
| 474 | 
            +
                      YAML
         | 
| 475 | 
            +
                    }
         | 
| 476 | 
            +
             | 
| 477 | 
            +
                    it 'fails with error' do
         | 
| 478 | 
            +
                      expect { lookup('mod::a') }.to raise_error(Puppet::DataBinding::LookupError, /all lookup_options patterns must match a key starting with module name/)
         | 
| 479 | 
            +
                    end
         | 
| 253 480 | 
             
                  end
         | 
| 254 481 | 
             
                end
         | 
| 255 482 |  | 
| 256 | 
            -
                context ' | 
| 257 | 
            -
                   | 
| 258 | 
            -
                     | 
| 259 | 
            -
             | 
| 483 | 
            +
                context 'and a global Hiera v4 configuration' do
         | 
| 484 | 
            +
                  let(:code_dir_files) do
         | 
| 485 | 
            +
                    {
         | 
| 486 | 
            +
                      'hiera.yaml' => <<-YAML.unindent,
         | 
| 487 | 
            +
                        ---
         | 
| 488 | 
            +
                        version: 4
         | 
| 489 | 
            +
                    YAML
         | 
| 490 | 
            +
                    }
         | 
| 260 491 | 
             
                  end
         | 
| 261 492 |  | 
| 262 | 
            -
                   | 
| 263 | 
            -
                     | 
| 264 | 
            -
                     | 
| 493 | 
            +
                  before(:each) do
         | 
| 494 | 
            +
                    # Need to set here since spec_helper defines these settings in its "before each"
         | 
| 495 | 
            +
                    Puppet.settings[:codedir] = populated_code_dir
         | 
| 496 | 
            +
                    Puppet.settings[:hiera_config] = File.join(code_dir, 'hiera.yaml')
         | 
| 265 497 | 
             
                  end
         | 
| 266 498 |  | 
| 267 | 
            -
                  it ' | 
| 268 | 
            -
                     | 
| 269 | 
            -
                    expect(resources).to include('dflt_x_dflt_y')
         | 
| 499 | 
            +
                  it 'raises an error' do
         | 
| 500 | 
            +
                    expect { lookup('a') }.to raise_error(Puppet::Error, /hiera configuration version 4 cannot be used in the global layer/)
         | 
| 270 501 | 
             
                  end
         | 
| 502 | 
            +
                end
         | 
| 271 503 |  | 
| 272 | 
            -
             | 
| 273 | 
            -
             | 
| 274 | 
            -
                     | 
| 504 | 
            +
                context 'and an environment Hiera v3 configuration' do
         | 
| 505 | 
            +
                  let(:environment_files) do
         | 
| 506 | 
            +
                    {
         | 
| 507 | 
            +
                      env_name => {
         | 
| 508 | 
            +
                        'hiera.yaml' => <<-YAML.unindent,
         | 
| 509 | 
            +
                          ---
         | 
| 510 | 
            +
                          :backends: yaml
         | 
| 511 | 
            +
                      YAML
         | 
| 512 | 
            +
                      }
         | 
| 513 | 
            +
                    }
         | 
| 275 514 | 
             
                  end
         | 
| 276 515 |  | 
| 277 | 
            -
                  it ' | 
| 278 | 
            -
                     | 
| 279 | 
            -
                    expect(resources).to include('no_value')
         | 
| 516 | 
            +
                  it 'raises an error' do
         | 
| 517 | 
            +
                    expect { lookup('a') }.to raise_error(Puppet::Error, /hiera configuration version 3 cannot be used in an environment/)
         | 
| 280 518 | 
             
                  end
         | 
| 519 | 
            +
                end
         | 
| 281 520 |  | 
| 282 | 
            -
             | 
| 283 | 
            -
             | 
| 284 | 
            -
             | 
| 285 | 
            -
                     | 
| 286 | 
            -
                       | 
| 521 | 
            +
                context 'and a global empty Hiera configuration' do
         | 
| 522 | 
            +
                  let(:hiera_yaml_path) { File.join(code_dir, 'hiera.yaml') }
         | 
| 523 | 
            +
                  let(:code_dir_files) do
         | 
| 524 | 
            +
                    {
         | 
| 525 | 
            +
                      'hiera.yaml' => '',
         | 
| 526 | 
            +
                    }
         | 
| 287 527 | 
             
                  end
         | 
| 288 528 |  | 
| 289 | 
            -
                   | 
| 290 | 
            -
                     | 
| 291 | 
            -
             | 
| 529 | 
            +
                  let(:environment_files) do
         | 
| 530 | 
            +
                    {
         | 
| 531 | 
            +
                      env_name => {
         | 
| 532 | 
            +
                        'hieradata' => {
         | 
| 533 | 
            +
                          'common.yaml' =>  <<-YAML.unindent,
         | 
| 534 | 
            +
                            x: value x (from environment)
         | 
| 535 | 
            +
                            YAML
         | 
| 536 | 
            +
                        }
         | 
| 537 | 
            +
                      }
         | 
| 538 | 
            +
                    }
         | 
| 292 539 | 
             
                  end
         | 
| 293 540 |  | 
| 294 | 
            -
                   | 
| 295 | 
            -
                     | 
| 296 | 
            -
                     | 
| 541 | 
            +
                  before(:each) do
         | 
| 542 | 
            +
                    # Need to set here since spec_helper defines these settings in its "before each"
         | 
| 543 | 
            +
                    Puppet.settings[:hiera_config] = hiera_yaml_path
         | 
| 297 544 | 
             
                  end
         | 
| 298 | 
            -
                end
         | 
| 299 | 
            -
              end
         | 
| 300 545 |  | 
| 301 | 
            -
             | 
| 302 | 
            -
             | 
| 303 | 
            -
                   | 
| 304 | 
            -
                  function environment::data() {
         | 
| 305 | 
            -
                    { a => { b => { c => 'the data' }}}
         | 
| 306 | 
            -
                  }
         | 
| 307 | 
            -
                  notice(lookup('a.b.c'))
         | 
| 308 | 
            -
                  CODE
         | 
| 309 | 
            -
                  expect(eval_and_collect_notices(source)).to include('the data')
         | 
| 310 | 
            -
                end
         | 
| 546 | 
            +
                  it 'uses a Hiera version 3 defaults' do
         | 
| 547 | 
            +
                    expect(lookup('x')).to eql('value x (from environment)')
         | 
| 548 | 
            +
                  end
         | 
| 311 549 |  | 
| 312 | 
            -
             | 
| 313 | 
            -
             | 
| 314 | 
            -
                  function environment::data() {
         | 
| 315 | 
            -
                    { 'a.b.c' => 'the data' }
         | 
| 316 | 
            -
                  }
         | 
| 317 | 
            -
                  notice(lookup('"a.b.c"'))
         | 
| 318 | 
            -
                  CODE
         | 
| 319 | 
            -
                  expect(eval_and_collect_notices(source)).to include('the data')
         | 
| 320 | 
            -
                end
         | 
| 550 | 
            +
                  context 'obtained using /dev/null', :unless => Puppet.features.microsoft_windows? do
         | 
| 551 | 
            +
                    let(:code_dir_files) { {} }
         | 
| 321 552 |  | 
| 322 | 
            -
             | 
| 323 | 
            -
             | 
| 324 | 
            -
             | 
| 325 | 
            -
                     | 
| 326 | 
            -
                   | 
| 327 | 
            -
                  notice(lookup('a."b.c"'))
         | 
| 328 | 
            -
                  CODE
         | 
| 329 | 
            -
                  expect(eval_and_collect_notices(source)).to include('the data')
         | 
| 553 | 
            +
                    it 'uses a Hiera version 3 defaults' do
         | 
| 554 | 
            +
                      Puppet[:hiera_config] = '/dev/null'
         | 
| 555 | 
            +
                      expect(lookup('x')).to eql('value x (from environment)')
         | 
| 556 | 
            +
                    end
         | 
| 557 | 
            +
                  end
         | 
| 330 558 | 
             
                end
         | 
| 331 | 
            -
              end
         | 
| 332 559 |  | 
| 333 | 
            -
             | 
| 334 | 
            -
             | 
| 335 | 
            -
             | 
| 336 | 
            -
             | 
| 337 | 
            -
             | 
| 560 | 
            +
                context 'and a global configuration' do
         | 
| 561 | 
            +
                  let(:hiera_yaml) do
         | 
| 562 | 
            +
                    <<-YAML.unindent
         | 
| 563 | 
            +
                    ---
         | 
| 564 | 
            +
                    :backends:
         | 
| 565 | 
            +
                      - yaml
         | 
| 566 | 
            +
                      - json
         | 
| 567 | 
            +
                      - custom
         | 
| 568 | 
            +
                      - hocon
         | 
| 569 | 
            +
                    :yaml:
         | 
| 570 | 
            +
                      :datadir: #{code_dir}/hieradata
         | 
| 571 | 
            +
                    :json:
         | 
| 572 | 
            +
                      :datadir: #{code_dir}/hieradata
         | 
| 573 | 
            +
                    :hocon:
         | 
| 574 | 
            +
                      :datadir: #{code_dir}/hieradata
         | 
| 575 | 
            +
                    :hierarchy:
         | 
| 576 | 
            +
                      - common
         | 
| 577 | 
            +
                      - "%{domain}"
         | 
| 578 | 
            +
                    :merge_behavior: deeper
         | 
| 579 | 
            +
                    YAML
         | 
| 580 | 
            +
                  end
         | 
| 338 581 |  | 
| 339 | 
            -
             | 
| 340 | 
            -
             | 
| 341 | 
            -
             | 
| 342 | 
            -
             | 
| 582 | 
            +
                  let(:code_dir_files) do
         | 
| 583 | 
            +
                    {
         | 
| 584 | 
            +
                      'hiera.yaml' => hiera_yaml,
         | 
| 585 | 
            +
                      'ruby_stuff' => {
         | 
| 586 | 
            +
                        'hiera' => {
         | 
| 587 | 
            +
                          'backend' => {
         | 
| 588 | 
            +
                            'custom_backend.rb' => <<-RUBY.unindent,
         | 
| 589 | 
            +
                              class Hiera::Backend::Custom_backend
         | 
| 590 | 
            +
                                def lookup(key, scope, order_override, resolution_type, context)
         | 
| 591 | 
            +
                                  case key
         | 
| 592 | 
            +
                                  when 'hash_c'
         | 
| 593 | 
            +
                                    { 'hash_ca' => { 'cad' => 'value hash_c.hash_ca.cad (from global custom)' }}
         | 
| 594 | 
            +
                                  when 'datasources'
         | 
| 595 | 
            +
                                    Hiera::Backend.datasources(scope, order_override) { |source| source }
         | 
| 596 | 
            +
                                  else
         | 
| 597 | 
            +
                                    throw :no_such_key
         | 
| 598 | 
            +
                                  end
         | 
| 599 | 
            +
                                end
         | 
| 600 | 
            +
                              end
         | 
| 601 | 
            +
                              RUBY
         | 
| 602 | 
            +
                            'other_backend.rb' => <<-RUBY.unindent,
         | 
| 603 | 
            +
                              class Hiera::Backend::Other_backend
         | 
| 604 | 
            +
                                def lookup(key, scope, order_override, resolution_type, context)
         | 
| 605 | 
            +
                                  value = Hiera::Config[:other][key.to_sym]
         | 
| 606 | 
            +
                                  throw :no_such_key if value.nil?
         | 
| 607 | 
            +
                                  value
         | 
| 608 | 
            +
                                end
         | 
| 609 | 
            +
                              end
         | 
| 610 | 
            +
                              RUBY
         | 
| 611 | 
            +
                          }
         | 
| 612 | 
            +
                        }
         | 
| 613 | 
            +
                      },
         | 
| 614 | 
            +
                      'hieradata' => {
         | 
| 615 | 
            +
                        'common.yaml' =>  <<-YAML.unindent,
         | 
| 616 | 
            +
                          a: value a (from global)
         | 
| 617 | 
            +
                          hash_b:
         | 
| 618 | 
            +
                            hash_ba:
         | 
| 619 | 
            +
                              bab: value hash_b.hash_ba.bab (from global)
         | 
| 620 | 
            +
                          hash_c:
         | 
| 621 | 
            +
                            hash_ca:
         | 
| 622 | 
            +
                              cab: value hash_c.hash_ca.cab (from global)
         | 
| 623 | 
            +
                          YAML
         | 
| 624 | 
            +
                        'example.com.yaml' =>  <<-YAML.unindent,
         | 
| 625 | 
            +
                          x: value x (from global example.com.yaml)
         | 
| 626 | 
            +
                          YAML
         | 
| 627 | 
            +
                        'common.json' =>  <<-JSON.unindent,
         | 
| 628 | 
            +
                          {
         | 
| 629 | 
            +
                            "hash_b": {
         | 
| 630 | 
            +
                              "hash_ba": {
         | 
| 631 | 
            +
                                "bac": "value hash_b.hash_ba.bac (from global json)"
         | 
| 632 | 
            +
                              }
         | 
| 633 | 
            +
                            },
         | 
| 634 | 
            +
                            "hash_c": {
         | 
| 635 | 
            +
                              "hash_ca": {
         | 
| 636 | 
            +
                                "cac": "value hash_c.hash_ca.cac (from global json)"
         | 
| 637 | 
            +
                              }
         | 
| 638 | 
            +
                            }
         | 
| 639 | 
            +
                          }
         | 
| 640 | 
            +
                          JSON
         | 
| 641 | 
            +
                        'common.conf' =>  <<-HOCON.unindent,
         | 
| 642 | 
            +
                          // The 'xs' is a value used for testing
         | 
| 643 | 
            +
                          xs = { subkey = value xs.subkey (from global hocon) }
         | 
| 644 | 
            +
                          HOCON
         | 
| 645 | 
            +
                      }
         | 
| 646 | 
            +
                    }
         | 
| 647 | 
            +
                  end
         | 
| 343 648 |  | 
| 344 | 
            -
             | 
| 345 | 
            -
             | 
| 346 | 
            -
             | 
| 347 | 
            -
             | 
| 649 | 
            +
                  before(:each) do
         | 
| 650 | 
            +
                    # Need to set here since spec_helper defines these settings in its "before each"
         | 
| 651 | 
            +
                    Puppet.settings[:codedir] = populated_code_dir
         | 
| 652 | 
            +
                    Puppet.settings[:hiera_config] = File.join(code_dir, 'hiera.yaml')
         | 
| 653 | 
            +
                  end
         | 
| 348 654 |  | 
| 349 | 
            -
             | 
| 350 | 
            -
             | 
| 351 | 
            -
             | 
| 352 | 
            -
             | 
| 655 | 
            +
                  around(:each) do |example|
         | 
| 656 | 
            +
                    # Faking the load path to enable 'require' to load from 'ruby_stuff'. It removes the need for a static fixture
         | 
| 657 | 
            +
                    # for the custom backend
         | 
| 658 | 
            +
                    $LOAD_PATH.unshift(File.join(code_dir, 'ruby_stuff'))
         | 
| 659 | 
            +
                    begin
         | 
| 660 | 
            +
                      Puppet.override(:environments => environments, :current_environment => env) do
         | 
| 661 | 
            +
                        example.run
         | 
| 662 | 
            +
                      end
         | 
| 663 | 
            +
                    ensure
         | 
| 664 | 
            +
                      Hiera::Backend.send(:remove_const, :Custom_backend) if Hiera::Backend.const_defined?(:Custom_backend)
         | 
| 665 | 
            +
                      Hiera::Backend.send(:remove_const, :Other_backend) if Hiera::Backend.const_defined?(:Other_backend)
         | 
| 666 | 
            +
                      $LOAD_PATH.shift
         | 
| 667 | 
            +
                    end
         | 
| 668 | 
            +
                  end
         | 
| 353 669 |  | 
| 354 | 
            -
             | 
| 355 | 
            -
             | 
| 356 | 
            -
             | 
| 357 | 
            -
             | 
| 670 | 
            +
                  context 'version 3' do
         | 
| 671 | 
            +
                    it 'finds data in the environment and reports deprecation warnings for both environment.conf and hiera.yaml' do
         | 
| 672 | 
            +
                      expect(lookup('a')).to eql('value a (from global)')
         | 
| 673 | 
            +
                      expect(warnings).to include(/Use of 'hiera.yaml' version 3 is deprecated. It should be converted to version 5/)
         | 
| 674 | 
            +
                    end
         | 
| 358 675 |  | 
| 359 | 
            -
             | 
| 360 | 
            -
             | 
| 361 | 
            -
             | 
| 362 | 
            -
             | 
| 676 | 
            +
                    it 'explain contains output from global layer' do
         | 
| 677 | 
            +
                      explanation = explain('a')
         | 
| 678 | 
            +
                      expect(explanation).to include('Global Data Provider (hiera configuration version 3)')
         | 
| 679 | 
            +
                      expect(explanation).to include('Hierarchy entry "yaml"')
         | 
| 680 | 
            +
                      expect(explanation).to include('Hierarchy entry "json"')
         | 
| 681 | 
            +
                      expect(explanation).to include('Found key: "a" value: "value a (from global)"')
         | 
| 682 | 
            +
                    end
         | 
| 363 683 |  | 
| 364 | 
            -
             | 
| 365 | 
            -
             | 
| 366 | 
            -
             | 
| 367 | 
            -
             | 
| 684 | 
            +
                    it 'uses the merge behavior specified in global hiera.yaml to merge only global backends' do
         | 
| 685 | 
            +
                      expect(lookup('hash_b')).to eql(
         | 
| 686 | 
            +
                        { 'hash_ba' => { 'bab' => 'value hash_b.hash_ba.bab (from global)', 'bac' => 'value hash_b.hash_ba.bac (from global json)' } })
         | 
| 687 | 
            +
                    end
         | 
| 368 688 |  | 
| 369 | 
            -
             | 
| 370 | 
            -
             | 
| 371 | 
            -
             | 
| 372 | 
            -
             | 
| 373 | 
            -
                end
         | 
| 689 | 
            +
                    it 'uses the merge from lookup options to merge all layers and override merge_behavior specified in global hiera.yaml' do
         | 
| 690 | 
            +
                      expect(lookup('hash_c')).to eql(
         | 
| 691 | 
            +
                        { 'hash_ca' => { 'cab' => 'value hash_c.hash_ca.cab (from global)' } })
         | 
| 692 | 
            +
                    end
         | 
| 374 693 |  | 
| 375 | 
            -
             | 
| 376 | 
            -
             | 
| 377 | 
            -
             | 
| 378 | 
            -
             | 
| 379 | 
            -
             | 
| 694 | 
            +
                    it 'uses the explicitly given merge to override lookup options and to merge all layers' do
         | 
| 695 | 
            +
                      expect(lookup('hash_c', 'merge' => 'deep')).to eql(
         | 
| 696 | 
            +
                        {
         | 
| 697 | 
            +
                          'hash_ca' =>
         | 
| 698 | 
            +
                          {
         | 
| 699 | 
            +
                            'caa' => 'value hash_c.hash_ca.caa (from environment)',
         | 
| 700 | 
            +
                            'cab' => 'value hash_c.hash_ca.cab (from global)',
         | 
| 701 | 
            +
                            'cac' => 'value hash_c.hash_ca.cac (from global json)',
         | 
| 702 | 
            +
                            'cad' => 'value hash_c.hash_ca.cad (from global custom)'
         | 
| 703 | 
            +
                          }
         | 
| 704 | 
            +
                        })
         | 
| 705 | 
            +
                    end
         | 
| 380 706 |  | 
| 381 | 
            -
             | 
| 382 | 
            -
             | 
| 383 | 
            -
             | 
| 384 | 
            -
                  Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
         | 
| 385 | 
            -
                    Puppet[:code] = "include bad_data\nlookup('bad_data::b')"
         | 
| 386 | 
            -
                    expect { compiler.compile }.to raise_error(Puppet::ParseError, /did not find a value for the name 'bad_data::b'/)
         | 
| 387 | 
            -
                  end
         | 
| 388 | 
            -
                  warnings = logs.select {|log| log.level == :warning }.map {|log| log.message }
         | 
| 389 | 
            -
                  expect(warnings).to include("Module data for module 'bad_data' must use keys qualified with the name of the module")
         | 
| 390 | 
            -
                end
         | 
| 707 | 
            +
                    it 'paths are interpolated' do
         | 
| 708 | 
            +
                      expect(lookup('x')).to eql('value x (from global example.com.yaml)')
         | 
| 709 | 
            +
                    end
         | 
| 391 710 |  | 
| 392 | 
            -
             | 
| 393 | 
            -
             | 
| 394 | 
            -
             | 
| 395 | 
            -
                  Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
         | 
| 396 | 
            -
                    resources = compile_and_get_notifications(<<-END.gsub(/^ {10}/, ''))
         | 
| 397 | 
            -
                      include bad_data
         | 
| 398 | 
            -
                      notify { lookup('bad_data::c'): }
         | 
| 399 | 
            -
                    END
         | 
| 400 | 
            -
                    expect(resources).to include('module_c')
         | 
| 401 | 
            -
                  end
         | 
| 402 | 
            -
                  warnings = logs.select {|log| log.level == :warning }.map {|log| log.message }
         | 
| 403 | 
            -
                  expect(warnings).to include("Module data for module 'bad_data' must use keys qualified with the name of the module")
         | 
| 404 | 
            -
                end
         | 
| 711 | 
            +
                    it 'backend data sources are propagated to custom backend' do
         | 
| 712 | 
            +
                      expect(lookup('datasources')).to eql(['common', 'example.com'])
         | 
| 713 | 
            +
                    end
         | 
| 405 714 |  | 
| 406 | 
            -
             | 
| 407 | 
            -
             | 
| 408 | 
            -
             | 
| 409 | 
            -
                  resources = compile_and_get_notifications(<<-END.gsub(/^ {8}/, '')
         | 
| 410 | 
            -
                    include bca
         | 
| 411 | 
            -
                    $r = lookup(bca::e, Hash[String,String], hash)
         | 
| 412 | 
            -
                    notify { "${r[k1]}_${r[k2]}_${r[k3]}": }
         | 
| 413 | 
            -
                  END
         | 
| 414 | 
            -
                  )
         | 
| 415 | 
            -
                  expect(resources).to include('global_e1_module_bca_e2_env_bca_e3')
         | 
| 416 | 
            -
                end
         | 
| 715 | 
            +
                    it 'delegates configured hocon backend to hocon_data function' do
         | 
| 716 | 
            +
                      expect(explain('xs')).to match(/Hierarchy entry "hocon"\n.*\n.*\n.*"common"\n\s*Found key: "xs"/m)
         | 
| 717 | 
            +
                    end
         | 
| 417 718 |  | 
| 418 | 
            -
             | 
| 419 | 
            -
             | 
| 420 | 
            -
             | 
| 421 | 
            -
                  resources = compile_and_get_notifications(<<-END.gsub(/^ {8}/, '')
         | 
| 422 | 
            -
                    include no_provider
         | 
| 423 | 
            -
                    $r = lookup(no_provider::e, Hash[String,String], hash)
         | 
| 424 | 
            -
                    notify { "${r[k1]}_${r[k2]}_${r[k3]}": }
         | 
| 425 | 
            -
                  END
         | 
| 426 | 
            -
                  )
         | 
| 427 | 
            -
                  expect(resources).to include('global_e1__env_no_provider_e3') # k2 is missing
         | 
| 428 | 
            -
                end
         | 
| 429 | 
            -
              end
         | 
| 719 | 
            +
                    it 'can dig down into subkeys provided by hocon_data function' do
         | 
| 720 | 
            +
                      expect(lookup('xs.subkey')).to eql('value xs.subkey (from global hocon)')
         | 
| 721 | 
            +
                    end
         | 
| 430 722 |  | 
| 431 | 
            -
             | 
| 432 | 
            -
             | 
| 433 | 
            -
             | 
| 434 | 
            -
             | 
| 435 | 
            -
             | 
| 436 | 
            -
             | 
| 437 | 
            -
             | 
| 438 | 
            -
             | 
| 439 | 
            -
             | 
| 440 | 
            -
             | 
| 723 | 
            +
                    context 'using deep_merge_options supported by deep_merge gem but not supported by Puppet' do
         | 
| 724 | 
            +
             | 
| 725 | 
            +
                      let(:hiera_yaml) do
         | 
| 726 | 
            +
                        <<-YAML.unindent
         | 
| 727 | 
            +
                          ---
         | 
| 728 | 
            +
                          :backends:
         | 
| 729 | 
            +
                            - yaml
         | 
| 730 | 
            +
                          :yaml:
         | 
| 731 | 
            +
                            :datadir: #{code_dir}/hieradata
         | 
| 732 | 
            +
                          :hierarchy:
         | 
| 733 | 
            +
                            - other
         | 
| 734 | 
            +
                            - common
         | 
| 735 | 
            +
                          :merge_behavior: deeper
         | 
| 736 | 
            +
                          :deep_merge_options:
         | 
| 737 | 
            +
                            :unpack_arrays: ','
         | 
| 738 | 
            +
                          YAML
         | 
| 739 | 
            +
                      end
         | 
| 740 | 
            +
             | 
| 741 | 
            +
                      let(:code_dir_files) do
         | 
| 742 | 
            +
                        {
         | 
| 743 | 
            +
                          'hiera.yaml' => hiera_yaml,
         | 
| 744 | 
            +
                          'hieradata' => {
         | 
| 745 | 
            +
                            'common.yaml' => <<-YAML.unindent,
         | 
| 746 | 
            +
                              a:
         | 
| 747 | 
            +
                                - x1,x2
         | 
| 748 | 
            +
                              YAML
         | 
| 749 | 
            +
                            'other.yaml' => <<-YAML.unindent,
         | 
| 750 | 
            +
                              a:
         | 
| 751 | 
            +
                                - x3
         | 
| 752 | 
            +
                                - x4
         | 
| 753 | 
            +
                              YAML
         | 
| 754 | 
            +
                          }
         | 
| 755 | 
            +
                        }
         | 
| 756 | 
            +
                      end
         | 
| 441 757 |  | 
| 442 | 
            -
             | 
| 443 | 
            -
             | 
| 444 | 
            -
             | 
| 445 | 
            -
             | 
| 446 | 
            -
             | 
| 758 | 
            +
                      it 'honors option :unpack_arrays: (unsupported by puppet)' do
         | 
| 759 | 
            +
                        expect(lookup('a')).to eql(%w(x1 x2 x3 x4))
         | 
| 760 | 
            +
                      end
         | 
| 761 | 
            +
                    end
         | 
| 762 | 
            +
             | 
| 763 | 
            +
                    context 'using relative datadir paths' do
         | 
| 764 | 
            +
                      let(:hiera_yaml) do
         | 
| 765 | 
            +
                        <<-YAML.unindent
         | 
| 766 | 
            +
                      ---
         | 
| 767 | 
            +
                      :backends:
         | 
| 768 | 
            +
                        - yaml
         | 
| 769 | 
            +
                      :yaml:
         | 
| 770 | 
            +
                        :datadir: relative_data
         | 
| 771 | 
            +
                      :hierarchy:
         | 
| 772 | 
            +
                        - common
         | 
| 773 | 
            +
                        YAML
         | 
| 774 | 
            +
                      end
         | 
| 775 | 
            +
             | 
| 776 | 
            +
                      let(:populated_code_dir) do
         | 
| 777 | 
            +
                        dir_contained_in(code_dir, code_dir_files.merge({
         | 
| 778 | 
            +
                          'fake_cwd' => {
         | 
| 779 | 
            +
                            'relative_data' => {
         | 
| 780 | 
            +
                              'common.yaml' => <<-YAML.unindent
         | 
| 781 | 
            +
                                a: value a (from fake_cwd/relative_data/common.yaml)
         | 
| 782 | 
            +
                              YAML
         | 
| 783 | 
            +
                            }
         | 
| 784 | 
            +
                          }
         | 
| 785 | 
            +
                        }))
         | 
| 786 | 
            +
                        code_dir
         | 
| 787 | 
            +
                      end
         | 
| 788 | 
            +
             | 
| 789 | 
            +
                      around(:each) do |example|
         | 
| 790 | 
            +
                        cwd = Dir.pwd
         | 
| 791 | 
            +
                        Dir.chdir(File.join(code_dir, 'fake_cwd'))
         | 
| 792 | 
            +
                        begin
         | 
| 793 | 
            +
                          example.run
         | 
| 794 | 
            +
                        ensure
         | 
| 795 | 
            +
                          Dir.chdir(cwd)
         | 
| 796 | 
            +
                        end
         | 
| 797 | 
            +
                      end
         | 
| 798 | 
            +
             | 
| 799 | 
            +
                      it 'finds data from data file beneath relative datadir' do
         | 
| 800 | 
            +
                        expect(lookup('a')).to eql('value a (from fake_cwd/relative_data/common.yaml)')
         | 
| 801 | 
            +
                      end
         | 
| 802 | 
            +
                    end
         | 
| 447 803 | 
             
                  end
         | 
| 448 | 
            -
                  warnings = logs.select {|log| log.level == :warning }.map {|log| log.message }
         | 
| 449 | 
            -
                  expect(warnings).to include("Module data for module 'hieraprovider' must use keys qualified with the name of the module")
         | 
| 450 | 
            -
                end
         | 
| 451 | 
            -
              end
         | 
| 452 804 |  | 
| 453 | 
            -
             | 
| 454 | 
            -
             | 
| 455 | 
            -
             | 
| 456 | 
            -
             | 
| 457 | 
            -
             | 
| 458 | 
            -
             | 
| 805 | 
            +
                  context 'version 5' do
         | 
| 806 | 
            +
                    let(:hiera_yaml) do
         | 
| 807 | 
            +
                      <<-YAML.unindent
         | 
| 808 | 
            +
                      ---
         | 
| 809 | 
            +
                      version: 5
         | 
| 810 | 
            +
                      defaults:
         | 
| 811 | 
            +
                        datadir: hieradata
         | 
| 812 | 
            +
             | 
| 813 | 
            +
                      hierarchy:
         | 
| 814 | 
            +
                        - name: Yaml
         | 
| 815 | 
            +
                          data_hash: yaml_data
         | 
| 816 | 
            +
                          paths:
         | 
| 817 | 
            +
                            - common.yaml
         | 
| 818 | 
            +
                            - "%{domain}.yaml"
         | 
| 819 | 
            +
                        - name: Json
         | 
| 820 | 
            +
                          data_hash: json_data
         | 
| 821 | 
            +
                          paths:
         | 
| 822 | 
            +
                            - common.json
         | 
| 823 | 
            +
                            - "%{domain}.json"
         | 
| 824 | 
            +
                        - name: Hocon
         | 
| 825 | 
            +
                          data_hash: hocon_data
         | 
| 826 | 
            +
                          paths:
         | 
| 827 | 
            +
                            - common.conf
         | 
| 828 | 
            +
                            - "%{domain}.conf"
         | 
| 829 | 
            +
                        - name: Custom
         | 
| 830 | 
            +
                          hiera3_backend: custom
         | 
| 831 | 
            +
                          paths:
         | 
| 832 | 
            +
                            - common.custom
         | 
| 833 | 
            +
                            - "%{domain}.custom"
         | 
| 834 | 
            +
                        - name: Other
         | 
| 835 | 
            +
                          hiera3_backend: other
         | 
| 836 | 
            +
                          options:
         | 
| 837 | 
            +
                            other_option: value of other_option
         | 
| 838 | 
            +
                          paths:
         | 
| 839 | 
            +
                            - common.other
         | 
| 840 | 
            +
                            - "%{domain}.other"
         | 
| 841 | 
            +
                          YAML
         | 
| 842 | 
            +
                    end
         | 
| 459 843 |  | 
| 460 | 
            -
             | 
| 461 | 
            -
             | 
| 462 | 
            -
             | 
| 463 | 
            -
             | 
| 464 | 
            -
                end
         | 
| 465 | 
            -
              end
         | 
| 844 | 
            +
                    it 'finds data in the environment and reports no deprecation warnings' do
         | 
| 845 | 
            +
                      expect(lookup('a')).to eql('value a (from global)')
         | 
| 846 | 
            +
                      expect(warnings).to be_empty
         | 
| 847 | 
            +
                    end
         | 
| 466 848 |  | 
| 467 | 
            -
             | 
| 468 | 
            -
             | 
| 469 | 
            -
             | 
| 470 | 
            -
             | 
| 471 | 
            -
             | 
| 472 | 
            -
             | 
| 473 | 
            -
                       | 
| 474 | 
            -
             | 
| 475 | 
            -
                    end
         | 
| 476 | 
            -
                    expect(lookup_invocation.explainer.to_s).to eq(<<EOS)
         | 
| 477 | 
            -
            Merge strategy first
         | 
| 478 | 
            -
              Data Binding "hiera"
         | 
| 479 | 
            -
                No such key: "empty_key_yaml::has_undef_value"
         | 
| 480 | 
            -
              Data Provider "FunctionEnvDataProvider"
         | 
| 481 | 
            -
                No such key: "empty_key_yaml::has_undef_value"
         | 
| 482 | 
            -
              Module "empty_key_yaml" using Data Provider "Hiera Data Provider, version 4"
         | 
| 483 | 
            -
                ConfigurationPath "#{environmentpath}/production/modules/empty_key_yaml/hiera.yaml"
         | 
| 484 | 
            -
                Data Provider "empty_key"
         | 
| 485 | 
            -
                  Path "#{environmentpath}/production/modules/empty_key_yaml/data/empty_key.yaml"
         | 
| 486 | 
            -
                    Original path: "empty_key"
         | 
| 487 | 
            -
                    Found key: "empty_key_yaml::has_undef_value" value: nil
         | 
| 488 | 
            -
              Merged result: nil
         | 
| 489 | 
            -
            EOS
         | 
| 490 | 
            -
                  end
         | 
| 491 | 
            -
                end
         | 
| 849 | 
            +
                    it 'explain contains output from global layer' do
         | 
| 850 | 
            +
                      explanation = explain('a')
         | 
| 851 | 
            +
                      expect(explanation).to include('Global Data Provider (hiera configuration version 5)')
         | 
| 852 | 
            +
                      expect(explanation).to include('Hierarchy entry "Yaml"')
         | 
| 853 | 
            +
                      expect(explanation).to include('Hierarchy entry "Json"')
         | 
| 854 | 
            +
                      expect(explanation).to include('Hierarchy entry "Hocon"')
         | 
| 855 | 
            +
                      expect(explanation).to include('Hierarchy entry "Custom"')
         | 
| 856 | 
            +
                      expect(explanation).to include('Found key: "a" value: "value a (from global)"')
         | 
| 857 | 
            +
                    end
         | 
| 492 858 |  | 
| 493 | 
            -
             | 
| 494 | 
            -
             | 
| 495 | 
            -
             | 
| 496 | 
            -
             | 
| 497 | 
            -
             | 
| 498 | 
            -
             | 
| 499 | 
            -
             | 
| 500 | 
            -
             | 
| 501 | 
            -
             | 
| 502 | 
            -
             | 
| 503 | 
            -
             | 
| 504 | 
            -
             | 
| 505 | 
            -
              Data Provider "FunctionEnvDataProvider"
         | 
| 506 | 
            -
                No such key: "empty_key_json::has_undef_value"
         | 
| 507 | 
            -
              Module "empty_key_json" using Data Provider "Hiera Data Provider, version 4"
         | 
| 508 | 
            -
                ConfigurationPath "#{environmentpath}/production/modules/empty_key_json/hiera.yaml"
         | 
| 509 | 
            -
                Data Provider "empty_key"
         | 
| 510 | 
            -
                  Path "#{environmentpath}/production/modules/empty_key_json/data/empty_key.json"
         | 
| 511 | 
            -
                    Original path: "empty_key"
         | 
| 512 | 
            -
                    Found key: "empty_key_json::has_undef_value" value: nil
         | 
| 513 | 
            -
              Merged result: nil
         | 
| 514 | 
            -
            EOS
         | 
| 515 | 
            -
                  end
         | 
| 516 | 
            -
                end
         | 
| 517 | 
            -
              end
         | 
| 859 | 
            +
                    it 'uses the explicitly given merge to override lookup options and to merge all layers' do
         | 
| 860 | 
            +
                      expect(lookup('hash_c', 'merge' => 'deep')).to eql(
         | 
| 861 | 
            +
                        {
         | 
| 862 | 
            +
                          'hash_ca' =>
         | 
| 863 | 
            +
                            {
         | 
| 864 | 
            +
                              'caa' => 'value hash_c.hash_ca.caa (from environment)',
         | 
| 865 | 
            +
                              'cab' => 'value hash_c.hash_ca.cab (from global)',
         | 
| 866 | 
            +
                              'cac' => 'value hash_c.hash_ca.cac (from global json)',
         | 
| 867 | 
            +
                              'cad' => 'value hash_c.hash_ca.cad (from global custom)'
         | 
| 868 | 
            +
                            }
         | 
| 869 | 
            +
                        })
         | 
| 870 | 
            +
                    end
         | 
| 518 871 |  | 
| 519 | 
            -
             | 
| 520 | 
            -
             | 
| 521 | 
            -
             | 
| 522 | 
            -
                    lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {}, true)
         | 
| 523 | 
            -
                    begin
         | 
| 524 | 
            -
                      Puppet::Pops::Lookup.lookup('ppx::e',nil, nil, false, nil, lookup_invocation)
         | 
| 525 | 
            -
                    rescue Puppet::Error
         | 
| 526 | 
            -
                    end
         | 
| 527 | 
            -
                    expect(lookup_invocation.explainer.to_s).to eq(<<EOS)
         | 
| 528 | 
            -
            Merge strategy first
         | 
| 529 | 
            -
              Data Binding "hiera"
         | 
| 530 | 
            -
                No such key: "ppx::e"
         | 
| 531 | 
            -
              Data Provider "FunctionEnvDataProvider"
         | 
| 532 | 
            -
                No such key: "ppx::e"
         | 
| 533 | 
            -
              Module "ppx"
         | 
| 534 | 
            -
                Module not found
         | 
| 535 | 
            -
            EOS
         | 
| 536 | 
            -
                  end
         | 
| 537 | 
            -
                end
         | 
| 872 | 
            +
                    it 'backend data sources are propagated to custom backend' do
         | 
| 873 | 
            +
                      expect(lookup('datasources')).to eql(['common', 'example.com'])
         | 
| 874 | 
            +
                    end
         | 
| 538 875 |  | 
| 539 | 
            -
             | 
| 540 | 
            -
             | 
| 541 | 
            -
                     | 
| 542 | 
            -
                    begin
         | 
| 543 | 
            -
                      Puppet::Pops::Lookup.lookup('abc::x', nil, nil, false, nil, lookup_invocation)
         | 
| 544 | 
            -
                    rescue Puppet::Error
         | 
| 545 | 
            -
                    end
         | 
| 546 | 
            -
                    expect(lookup_invocation.explainer.to_s).to eq(<<EOS)
         | 
| 547 | 
            -
            Merge strategy first
         | 
| 548 | 
            -
              Data Binding "hiera"
         | 
| 549 | 
            -
                No such key: "abc::x"
         | 
| 550 | 
            -
              Data Provider "FunctionEnvDataProvider"
         | 
| 551 | 
            -
                No such key: "abc::x"
         | 
| 552 | 
            -
              Module "abc" using Data Provider "FunctionModuleDataProvider"
         | 
| 553 | 
            -
                No such key: "abc::x"
         | 
| 554 | 
            -
            EOS
         | 
| 555 | 
            -
                  end
         | 
| 556 | 
            -
                end
         | 
| 876 | 
            +
                    it 'backend specific options are propagated to custom backend' do
         | 
| 877 | 
            +
                      expect(lookup('other_option')).to eql('value of other_option')
         | 
| 878 | 
            +
                    end
         | 
| 557 879 |  | 
| 558 | 
            -
             | 
| 559 | 
            -
             | 
| 560 | 
            -
             | 
| 561 | 
            -
             | 
| 562 | 
            -
             | 
| 563 | 
            -
             | 
| 564 | 
            -
             | 
| 565 | 
            -
             | 
| 566 | 
            -
             | 
| 567 | 
            -
             | 
| 568 | 
            -
             | 
| 569 | 
            -
             | 
| 570 | 
            -
             | 
| 571 | 
            -
             | 
| 572 | 
            -
                Found key: "abc::e" value: {
         | 
| 573 | 
            -
                  "k1" => "module_e1",
         | 
| 574 | 
            -
                  "k2" => "module_e2"
         | 
| 575 | 
            -
                }
         | 
| 576 | 
            -
              Merged result: {
         | 
| 577 | 
            -
                "k1" => "env_e1",
         | 
| 578 | 
            -
                "k2" => "module_e2",
         | 
| 579 | 
            -
                "k3" => "env_e3"
         | 
| 580 | 
            -
              }
         | 
| 581 | 
            -
            EOS
         | 
| 582 | 
            -
                  end
         | 
| 583 | 
            -
                end
         | 
| 880 | 
            +
                    it 'multiple hiera3_backend declarations can be used and are merged into the generated config' do
         | 
| 881 | 
            +
                      expect(lookup(['datasources', 'other_option'])).to eql([['common', 'example.com'], 'value of other_option'])
         | 
| 882 | 
            +
                      expect(Hiera::Config.instance_variable_get(:@config)).to eql(
         | 
| 883 | 
            +
                        {
         | 
| 884 | 
            +
                          :backends => ['custom', 'other'],
         | 
| 885 | 
            +
                          :hierarchy => ['common', '%{domain}'],
         | 
| 886 | 
            +
                          :custom => { :datadir => "#{code_dir}/hieradata" },
         | 
| 887 | 
            +
                          :other => { :other_option => 'value of other_option', :datadir=>"#{code_dir}/hieradata" },
         | 
| 888 | 
            +
                          :logger => 'puppet'
         | 
| 889 | 
            +
                        })
         | 
| 890 | 
            +
                    end
         | 
| 891 | 
            +
             | 
| 892 | 
            +
                    it 'provides a sensible error message when the hocon library is not loaded' do
         | 
| 893 | 
            +
                      Puppet.features.stubs(:hocon?).returns(false)
         | 
| 584 894 |  | 
| 585 | 
            -
             | 
| 586 | 
            -
             | 
| 587 | 
            -
             | 
| 588 | 
            -
                     | 
| 589 | 
            -
                    Puppet::Pops::Lookup.lookup('abc::e', Puppet::Pops::Types::TypeParser.singleton.parse('Hash[String,String]'), nil, false, {'strategy' => 'deep', 'merge_hash_arrays' => true}, lookup_invocation)
         | 
| 590 | 
            -
                    expect(lookup_invocation.explainer.to_s).to eq(<<EOS)
         | 
| 591 | 
            -
            Merge strategy deep
         | 
| 592 | 
            -
              Options: {
         | 
| 593 | 
            -
                "merge_hash_arrays" => true
         | 
| 594 | 
            -
              }
         | 
| 595 | 
            -
              Data Binding "hiera"
         | 
| 596 | 
            -
                Found key: "abc::e" value: {
         | 
| 597 | 
            -
                  "k1" => "global_g1"
         | 
| 598 | 
            -
                }
         | 
| 599 | 
            -
              Data Provider "FunctionEnvDataProvider"
         | 
| 600 | 
            -
                Found key: "abc::e" value: {
         | 
| 601 | 
            -
                  "k1" => "env_e1",
         | 
| 602 | 
            -
                  "k3" => "env_e3"
         | 
| 603 | 
            -
                }
         | 
| 604 | 
            -
              Module "abc" using Data Provider "FunctionModuleDataProvider"
         | 
| 605 | 
            -
                Found key: "abc::e" value: {
         | 
| 606 | 
            -
                  "k1" => "module_e1",
         | 
| 607 | 
            -
                  "k2" => "module_e2"
         | 
| 608 | 
            -
                }
         | 
| 609 | 
            -
              Merged result: {
         | 
| 610 | 
            -
                "k1" => "global_g1",
         | 
| 611 | 
            -
                "k2" => "module_e2",
         | 
| 612 | 
            -
                "k3" => "env_e3"
         | 
| 613 | 
            -
              }
         | 
| 614 | 
            -
            EOS
         | 
| 895 | 
            +
                      expect { lookup('a') }.to raise_error do |e|
         | 
| 896 | 
            +
                        expect(e.message).to match(/Lookup using Hocon data_hash function is not supported without hocon library/)
         | 
| 897 | 
            +
                      end
         | 
| 898 | 
            +
                    end
         | 
| 615 899 | 
             
                  end
         | 
| 616 | 
            -
                end
         | 
| 617 900 |  | 
| 618 | 
            -
             | 
| 619 | 
            -
             | 
| 620 | 
            -
             | 
| 621 | 
            -
             | 
| 622 | 
            -
                       | 
| 623 | 
            -
             | 
| 624 | 
            -
             | 
| 625 | 
            -
             | 
| 626 | 
            -
             | 
| 627 | 
            -
             | 
| 628 | 
            -
             | 
| 629 | 
            -
             | 
| 630 | 
            -
             | 
| 631 | 
            -
             | 
| 632 | 
            -
             | 
| 633 | 
            -
                Data Provider "two paths"
         | 
| 634 | 
            -
                  Merge strategy first
         | 
| 635 | 
            -
                    Path "#{environmentpath}/production/modules/hieraprovider/data/first.json"
         | 
| 636 | 
            -
                      Original path: "first"
         | 
| 637 | 
            -
                      No such key: "hieraprovider::test::not_found"
         | 
| 638 | 
            -
                    Path "#{environmentpath}/production/modules/hieraprovider/data/second_not_present.json"
         | 
| 639 | 
            -
                      Original path: "second_not_present"
         | 
| 640 | 
            -
                      Path not found
         | 
| 641 | 
            -
            EOS
         | 
| 901 | 
            +
                  context 'with a hiera3_backend that has no paths' do
         | 
| 902 | 
            +
                    let(:hiera_yaml) do
         | 
| 903 | 
            +
                      <<-YAML.unindent
         | 
| 904 | 
            +
                      ---
         | 
| 905 | 
            +
                      version: 5
         | 
| 906 | 
            +
                      hierarchy:
         | 
| 907 | 
            +
                        - name: Custom
         | 
| 908 | 
            +
                          hiera3_backend: custom
         | 
| 909 | 
            +
                      YAML
         | 
| 910 | 
            +
                    end
         | 
| 911 | 
            +
             | 
| 912 | 
            +
                    it 'calls the backend' do
         | 
| 913 | 
            +
                      expect(lookup('hash_c')).to eql(
         | 
| 914 | 
            +
                        { 'hash_ca' => { 'cad' => 'value hash_c.hash_ca.cad (from global custom)' }})
         | 
| 915 | 
            +
                    end
         | 
| 642 916 | 
             
                  end
         | 
| 643 917 | 
             
                end
         | 
| 644 918 |  | 
| 645 | 
            -
                 | 
| 646 | 
            -
                   | 
| 647 | 
            -
             | 
| 648 | 
            -
             | 
| 649 | 
            -
                     | 
| 650 | 
            -
             | 
| 651 | 
            -
              Data Binding "hiera"
         | 
| 652 | 
            -
                No such key: "abc::f.k1.s1"
         | 
| 653 | 
            -
              Data Provider "FunctionEnvDataProvider"
         | 
| 654 | 
            -
                Sub key: "k1.s1"
         | 
| 655 | 
            -
                  Found key: "k1" value: {
         | 
| 656 | 
            -
                    "s1" => "env_f11",
         | 
| 657 | 
            -
                    "s2" => "env_f12"
         | 
| 658 | 
            -
                  }
         | 
| 659 | 
            -
                  Found key: "s1" value: "env_f11"
         | 
| 660 | 
            -
                Found key: "abc::f.k1.s1" value: "env_f11"
         | 
| 661 | 
            -
              Merged result: "env_f11"
         | 
| 662 | 
            -
            EOS
         | 
| 919 | 
            +
                context 'and a module' do
         | 
| 920 | 
            +
                  let(:mod_a_files) { {} }
         | 
| 921 | 
            +
             | 
| 922 | 
            +
                  let(:populated_env_dir) do
         | 
| 923 | 
            +
                    dir_contained_in(env_dir, DeepMerge.deep_merge!(environment_files, env_name => { 'modules' => mod_a_files }))
         | 
| 924 | 
            +
                    env_dir
         | 
| 663 925 | 
             
                  end
         | 
| 664 | 
            -
                end
         | 
| 665 926 |  | 
| 927 | 
            +
                  context 'that has no lookup configured' do
         | 
| 928 | 
            +
                    let(:mod_a_files) do
         | 
| 929 | 
            +
                      {
         | 
| 930 | 
            +
                        'mod_a' => {
         | 
| 931 | 
            +
                          'data' => {
         | 
| 932 | 
            +
                            'common.yaml' => <<-YAML.unindent
         | 
| 933 | 
            +
                            ---
         | 
| 934 | 
            +
                            mod_a::b: value mod_a::b (from mod_a)
         | 
| 935 | 
            +
                          YAML
         | 
| 936 | 
            +
                          }
         | 
| 937 | 
            +
                        }
         | 
| 938 | 
            +
                      }
         | 
| 939 | 
            +
                    end
         | 
| 940 | 
            +
             | 
| 941 | 
            +
                    it 'does not find data in the module' do
         | 
| 942 | 
            +
                      expect { lookup('mod_a::b') }.to raise_error(Puppet::DataBinding::LookupError, /did not find a value for the name 'mod_a::b'/)
         | 
| 943 | 
            +
                    end
         | 
| 666 944 |  | 
| 667 | 
            -
             | 
| 668 | 
            -
             | 
| 669 | 
            -
                    lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {}, true)
         | 
| 670 | 
            -
                    Puppet::Pops::Lookup.lookup('abc::e', Puppet::Pops::Types::TypeParser.singleton.parse('Hash[String,String]'), nil, false, {'strategy' => 'deep', 'merge_hash_arrays' => true}, lookup_invocation)
         | 
| 671 | 
            -
                    expect(lookup_invocation.explainer.to_hash).to eq(
         | 
| 945 | 
            +
                    context 'with a Hiera v3 configuration' do
         | 
| 946 | 
            +
                      let(:mod_a_files) do
         | 
| 672 947 | 
             
                        {
         | 
| 673 | 
            -
                           | 
| 948 | 
            +
                          'mod_a' => {
         | 
| 949 | 
            +
                            'hiera.yaml' => <<-YAML.unindent
         | 
| 950 | 
            +
                              ---
         | 
| 951 | 
            +
                              :backends: yaml
         | 
| 952 | 
            +
                              YAML
         | 
| 953 | 
            +
                          }
         | 
| 954 | 
            +
                        }
         | 
| 955 | 
            +
                      end
         | 
| 956 | 
            +
             | 
| 957 | 
            +
                      it 'raises an error' do
         | 
| 958 | 
            +
                        expect { lookup('mod_a::a') }.to raise_error(Puppet::Error, /hiera configuration version 3 cannot be used in a module/)
         | 
| 959 | 
            +
                      end
         | 
| 960 | 
            +
                    end
         | 
| 961 | 
            +
             | 
| 962 | 
            +
                    context "but a metadata.json with 'module_data_provider=hiera'" do
         | 
| 963 | 
            +
                      let(:mod_a_files_1) { DeepMerge.deep_merge!(mod_a_files, 'mod_a' => { 'metadata.json' => <<-JSON.unindent }) }
         | 
| 674 964 | 
             
                          {
         | 
| 675 | 
            -
             | 
| 676 | 
            -
             | 
| 677 | 
            -
             | 
| 678 | 
            -
             | 
| 965 | 
            +
                              "name": "example/mod_a",
         | 
| 966 | 
            +
                              "version": "0.0.2",
         | 
| 967 | 
            +
                              "source": "git@github.com/example/mod_a.git",
         | 
| 968 | 
            +
                              "dependencies": [],
         | 
| 969 | 
            +
                              "author": "Bob the Builder",
         | 
| 970 | 
            +
                              "license": "Apache-2.0",
         | 
| 971 | 
            +
                              "data_provider": "hiera"
         | 
| 972 | 
            +
                          }
         | 
| 973 | 
            +
                          JSON
         | 
| 974 | 
            +
             | 
| 975 | 
            +
                      let(:populated_env_dir) do
         | 
| 976 | 
            +
                        dir_contained_in(env_dir, DeepMerge.deep_merge!(environment_files, env_name => { 'modules' => mod_a_files_1 }))
         | 
| 977 | 
            +
                        env_dir
         | 
| 978 | 
            +
                      end
         | 
| 979 | 
            +
             | 
| 980 | 
            +
                      it 'finds data in the module and reports deprecation warning for metadata.json' do
         | 
| 981 | 
            +
                        expect(lookup('mod_a::b')).to eql('value mod_a::b (from mod_a)')
         | 
| 982 | 
            +
                        expect(warnings).to include(/Defining "data_provider": "hiera" in metadata.json is deprecated. A 'hiera.yaml' file should be used instead/)
         | 
| 983 | 
            +
                      end
         | 
| 984 | 
            +
             | 
| 985 | 
            +
                      context 'and a hiera.yaml file' do
         | 
| 986 | 
            +
                        let(:mod_a_files_2) { DeepMerge.deep_merge!(mod_a_files_1, 'mod_a' => { 'hiera.yaml' => <<-YAML.unindent }) }
         | 
| 987 | 
            +
                        ---
         | 
| 988 | 
            +
                        version: 4
         | 
| 989 | 
            +
                        hierarchy:
         | 
| 990 | 
            +
                          - name: common
         | 
| 991 | 
            +
                            backend: yaml
         | 
| 992 | 
            +
                        YAML
         | 
| 993 | 
            +
             | 
| 994 | 
            +
                        let(:populated_env_dir) do
         | 
| 995 | 
            +
                          dir_contained_in(env_dir, DeepMerge.deep_merge!(environment_files, env_name => { 'modules' => mod_a_files_2 }))
         | 
| 996 | 
            +
                          env_dir
         | 
| 997 | 
            +
                        end
         | 
| 998 | 
            +
             | 
| 999 | 
            +
                        it 'finds data in the module and reports deprecation warnings for both metadata.json and hiera.yaml' do
         | 
| 1000 | 
            +
                          expect(lookup('mod_a::b')).to eql('value mod_a::b (from mod_a)')
         | 
| 1001 | 
            +
                          expect(warnings).to include(/Defining "data_provider": "hiera" in metadata.json is deprecated/)
         | 
| 1002 | 
            +
                          expect(warnings).to include(/Use of 'hiera.yaml' version 4 is deprecated. It should be converted to version 5/)
         | 
| 1003 | 
            +
                        end
         | 
| 1004 | 
            +
                      end
         | 
| 1005 | 
            +
                    end
         | 
| 1006 | 
            +
                  end
         | 
| 1007 | 
            +
             | 
| 1008 | 
            +
                  context 'using a data_hash that reads a yaml file' do
         | 
| 1009 | 
            +
                    let(:mod_a_files) do
         | 
| 1010 | 
            +
                      {
         | 
| 1011 | 
            +
                        'mod_a' => {
         | 
| 1012 | 
            +
                          'data' => {
         | 
| 1013 | 
            +
                            'common.yaml' => <<-YAML.unindent
         | 
| 1014 | 
            +
                            ---
         | 
| 1015 | 
            +
                            mod_a::a: value mod_a::a (from mod_a)
         | 
| 1016 | 
            +
                            mod_a::b: value mod_a::b (from mod_a)
         | 
| 1017 | 
            +
                            mod_a::xo: value mod_a::xo (from mod_a)
         | 
| 1018 | 
            +
                            mod_a::xd_found: value mod_a::xd_found (from mod_a)
         | 
| 1019 | 
            +
                            mod_a::interpolate_xo: "-- %{lookup('mod_a::xo')} --"
         | 
| 1020 | 
            +
                            mod_a::interpolate_xd: "-- %{lookup('mod_a::xd')} --"
         | 
| 1021 | 
            +
                            mod_a::interpolate_scope_xo: "-- %{scope_xo} --"
         | 
| 1022 | 
            +
                            mod_a::interpolate_scope_xd: "-- %{scope_xd} --"
         | 
| 1023 | 
            +
                            mod_a::hash_a:
         | 
| 1024 | 
            +
                              a: value mod_a::hash_a.a (from mod_a)
         | 
| 1025 | 
            +
                              b: value mod_a::hash_a.b (from mod_a)
         | 
| 1026 | 
            +
                            mod_a::hash_b:
         | 
| 1027 | 
            +
                              a: value mod_a::hash_b.a (from mod_a)
         | 
| 1028 | 
            +
                              b: value mod_a::hash_b.b (from mod_a)
         | 
| 1029 | 
            +
                            mod_a::interpolated: "-- %{lookup('mod_a::a')} --"
         | 
| 1030 | 
            +
                            mod_a::a_a: "-- %{lookup('mod_a::hash_a.a')} --"
         | 
| 1031 | 
            +
                            mod_a::a_b: "-- %{lookup('mod_a::hash_a.b')} --"
         | 
| 1032 | 
            +
                            mod_a::b_a: "-- %{lookup('mod_a::hash_b.a')} --"
         | 
| 1033 | 
            +
                            mod_a::b_b: "-- %{lookup('mod_a::hash_b.b')} --"
         | 
| 1034 | 
            +
                            mod_a::interpolate_array:
         | 
| 1035 | 
            +
                              - "-- %{lookup('mod_a::a')} --"
         | 
| 1036 | 
            +
                              - "-- %{lookup('mod_a::b')} --"
         | 
| 1037 | 
            +
                            mod_a::interpolate_literal: "-- %{literal('hello')} --"
         | 
| 1038 | 
            +
                            mod_a::interpolate_scope: "-- %{scope_scalar} --"
         | 
| 1039 | 
            +
                            mod_a::interpolate_scope_not_found: "-- %{scope_nope} --"
         | 
| 1040 | 
            +
                            mod_a::interpolate_scope_dig: "-- %{scope_hash.a} --"
         | 
| 1041 | 
            +
                            mod_a::interpolate_scope_dig_not_found: "-- %{scope_hash.nope} --"
         | 
| 1042 | 
            +
                            mod_a::quoted_interpolation: '-- %{lookup(''"mod_a::a.quoted.key"'')} --'
         | 
| 1043 | 
            +
                            "mod_a::a.quoted.key": "value mod_a::a.quoted.key (from mod_a)"
         | 
| 1044 | 
            +
                          YAML
         | 
| 679 1045 | 
             
                          },
         | 
| 680 | 
            -
                           | 
| 681 | 
            -
             | 
| 682 | 
            -
             | 
| 683 | 
            -
             | 
| 684 | 
            -
                            : | 
| 685 | 
            -
             | 
| 1046 | 
            +
                          'hiera.yaml' => <<-YAML.unindent,
         | 
| 1047 | 
            +
                          ---
         | 
| 1048 | 
            +
                          version: 5
         | 
| 1049 | 
            +
                          hierarchy:
         | 
| 1050 | 
            +
                            - name: "Common"
         | 
| 1051 | 
            +
                              data_hash: yaml_data
         | 
| 1052 | 
            +
                              path: "common.yaml"
         | 
| 1053 | 
            +
                        YAML
         | 
| 1054 | 
            +
                        }
         | 
| 1055 | 
            +
                      }
         | 
| 1056 | 
            +
                    end
         | 
| 1057 | 
            +
             | 
| 1058 | 
            +
                    it 'finds data in the module' do
         | 
| 1059 | 
            +
                      expect(lookup('mod_a::b')).to eql('value mod_a::b (from mod_a)')
         | 
| 1060 | 
            +
                    end
         | 
| 1061 | 
            +
             | 
| 1062 | 
            +
                    it 'environment data has higher priority than module data' do
         | 
| 1063 | 
            +
                      expect(lookup('mod_a::a')).to eql('value mod_a::a (from environment)')
         | 
| 1064 | 
            +
                    end
         | 
| 1065 | 
            +
             | 
| 1066 | 
            +
                    it 'environment data has higher priority than module data in interpolated module data' do
         | 
| 1067 | 
            +
                      expect(lookup('mod_a::interpolated')).to eql('-- value mod_a::a (from environment) --')
         | 
| 1068 | 
            +
                    end
         | 
| 1069 | 
            +
             | 
| 1070 | 
            +
                    it 'overrides have higher priority than found data' do
         | 
| 1071 | 
            +
                      expect(lookup('mod_a::xo', { 'override' => overrides })).to eql('value mod_a::xo (from override)')
         | 
| 1072 | 
            +
                    end
         | 
| 1073 | 
            +
             | 
| 1074 | 
            +
                    it 'overrides have higher priority than found data in lookup interpolations' do
         | 
| 1075 | 
            +
                      expect(lookup('mod_a::interpolate_xo', { 'override' => overrides })).to eql('-- value mod_a::xo (from override) --')
         | 
| 1076 | 
            +
                    end
         | 
| 1077 | 
            +
             | 
| 1078 | 
            +
                    it 'overrides have higher priority than found data in scope interpolations' do
         | 
| 1079 | 
            +
                      expect(lookup('mod_a::interpolate_scope_xo', { 'override' => overrides })).to eql('-- value scope_xo (from override) --')
         | 
| 1080 | 
            +
                    end
         | 
| 1081 | 
            +
             | 
| 1082 | 
            +
                    it 'defaults have lower priority than found data' do
         | 
| 1083 | 
            +
                      expect(lookup('mod_a::xd_found', { 'default_values_hash' => defaults })).to eql('value mod_a::xd_found (from mod_a)')
         | 
| 1084 | 
            +
                    end
         | 
| 1085 | 
            +
             | 
| 1086 | 
            +
                    it 'defaults are used when data is not found' do
         | 
| 1087 | 
            +
                      expect(lookup('mod_a::xd', { 'default_values_hash' => defaults })).to eql('value mod_a::xd (from default)')
         | 
| 1088 | 
            +
                    end
         | 
| 1089 | 
            +
             | 
| 1090 | 
            +
                    it 'defaults are used when data is not found in lookup interpolations' do
         | 
| 1091 | 
            +
                      expect(lookup('mod_a::interpolate_xd', { 'default_values_hash' => defaults })).to eql('-- value mod_a::xd (from default) --')
         | 
| 1092 | 
            +
                    end
         | 
| 1093 | 
            +
             | 
| 1094 | 
            +
                    it 'defaults are used when data is not found in scope interpolations' do
         | 
| 1095 | 
            +
                      expect(lookup('mod_a::interpolate_scope_xd', { 'default_values_hash' => defaults })).to eql('-- value scope_xd (from default) --')
         | 
| 1096 | 
            +
                    end
         | 
| 1097 | 
            +
             | 
| 1098 | 
            +
                    it 'merges hashes from environment and module unless strategy hash is used' do
         | 
| 1099 | 
            +
                      expect(lookup('mod_a::hash_a')).to eql({'a' => 'value mod_a::hash_a.a (from environment)'})
         | 
| 1100 | 
            +
                    end
         | 
| 1101 | 
            +
             | 
| 1102 | 
            +
                    it 'merges hashes from environment and module when merge strategy hash is used' do
         | 
| 1103 | 
            +
                      expect(lookup('mod_a::hash_a', :merge => 'hash')).to eql(
         | 
| 1104 | 
            +
                        {'a' => 'value mod_a::hash_a.a (from environment)', 'b' => 'value mod_a::hash_a.b (from mod_a)'})
         | 
| 1105 | 
            +
                    end
         | 
| 1106 | 
            +
             | 
| 1107 | 
            +
                    it 'will not merge hashes from environment and module in interpolated expressions' do
         | 
| 1108 | 
            +
                      expect(lookup(['mod_a::a_a', 'mod_a::a_b'])).to eql(
         | 
| 1109 | 
            +
                        ['-- value mod_a::hash_a.a (from environment) --', '--  --']) # root key found in environment, no hash merge is performed
         | 
| 1110 | 
            +
                    end
         | 
| 1111 | 
            +
             | 
| 1112 | 
            +
                    it 'interpolates arrays' do
         | 
| 1113 | 
            +
                      expect(lookup('mod_a::interpolate_array')).to eql(['-- value mod_a::a (from environment) --', '-- value mod_a::b (from mod_a) --'])
         | 
| 1114 | 
            +
                    end
         | 
| 1115 | 
            +
             | 
| 1116 | 
            +
                    it 'can dig into arrays using subkeys' do
         | 
| 1117 | 
            +
                      expect(lookup('mod_a::interpolate_array.1')).to eql('-- value mod_a::b (from mod_a) --')
         | 
| 1118 | 
            +
                    end
         | 
| 1119 | 
            +
             | 
| 1120 | 
            +
                    it 'treats an out of range subkey as not found' do
         | 
| 1121 | 
            +
                      expect(explain('mod_a::interpolate_array.2')).to match(/No such key: "2"/)
         | 
| 1122 | 
            +
                    end
         | 
| 1123 | 
            +
             | 
| 1124 | 
            +
                    it 'interpolates a literal' do
         | 
| 1125 | 
            +
                      expect(lookup('mod_a::interpolate_literal')).to eql('-- hello --')
         | 
| 1126 | 
            +
                    end
         | 
| 1127 | 
            +
             | 
| 1128 | 
            +
                    it 'interpolates scalar from scope' do
         | 
| 1129 | 
            +
                      expect(lookup('mod_a::interpolate_scope')).to eql('-- scope scalar value --')
         | 
| 1130 | 
            +
                    end
         | 
| 1131 | 
            +
             | 
| 1132 | 
            +
                    it 'interpolates not found in scope as empty string' do
         | 
| 1133 | 
            +
                      expect(lookup('mod_a::interpolate_scope_not_found')).to eql('--  --')
         | 
| 1134 | 
            +
                    end
         | 
| 1135 | 
            +
             | 
| 1136 | 
            +
                    it 'interpolates dotted key from scope' do
         | 
| 1137 | 
            +
                      expect(lookup('mod_a::interpolate_scope_dig')).to eql('-- scope hash a --')
         | 
| 1138 | 
            +
                    end
         | 
| 1139 | 
            +
             | 
| 1140 | 
            +
                    it 'treates interpolated dotted key but not found in scope as empty string' do
         | 
| 1141 | 
            +
                      expect(lookup('mod_a::interpolate_scope_dig_not_found')).to eql('--  --')
         | 
| 1142 | 
            +
                    end
         | 
| 1143 | 
            +
             | 
| 1144 | 
            +
                    it 'can use quoted keys in interpolation' do
         | 
| 1145 | 
            +
                      expect(lookup('mod_a::quoted_interpolation')).to eql('-- value mod_a::a.quoted.key (from mod_a) --') # root key found in environment, no hash merge is performed
         | 
| 1146 | 
            +
                    end
         | 
| 1147 | 
            +
             | 
| 1148 | 
            +
                    it 'merges hashes from environment and module in interpolated expressions if hash merge is specified in lookup options' do
         | 
| 1149 | 
            +
                      expect(lookup(['mod_a::b_a', 'mod_a::b_b'])).to eql(
         | 
| 1150 | 
            +
                        ['-- value mod_a::hash_b.a (from environment) --', '-- value mod_a::hash_b.b (from mod_a) --'])
         | 
| 1151 | 
            +
                    end
         | 
| 1152 | 
            +
                  end
         | 
| 1153 | 
            +
             | 
| 1154 | 
            +
                  context 'using a lookup_key that uses a path' do
         | 
| 1155 | 
            +
                    let(:mod_a_files) do
         | 
| 1156 | 
            +
                      {
         | 
| 1157 | 
            +
                        'mod_a' => {
         | 
| 1158 | 
            +
                          'functions' => {
         | 
| 1159 | 
            +
                            'pp_lookup_key.pp' => <<-PUPPET.unindent
         | 
| 1160 | 
            +
                              function mod_a::pp_lookup_key($key, $options, $context) {
         | 
| 1161 | 
            +
                                if !$context.cache_has_key(undef) {
         | 
| 1162 | 
            +
                                  $context.cache_all(yaml_data($options, $context))
         | 
| 1163 | 
            +
                                  $context.cache(undef, true)
         | 
| 1164 | 
            +
                                }
         | 
| 1165 | 
            +
                                if $context.cache_has_key($key) { $context.cached_value($key) } else { $context.not_found }
         | 
| 1166 | 
            +
                              }
         | 
| 1167 | 
            +
                              PUPPET
         | 
| 686 1168 | 
             
                          },
         | 
| 687 | 
            -
                           | 
| 688 | 
            -
                             | 
| 689 | 
            -
                            : | 
| 690 | 
            -
                            : | 
| 691 | 
            -
             | 
| 692 | 
            -
             | 
| 693 | 
            -
             | 
| 1169 | 
            +
                          'hiera.yaml' => <<-YAML.unindent,
         | 
| 1170 | 
            +
                            ---
         | 
| 1171 | 
            +
                            version: 5
         | 
| 1172 | 
            +
                            hierarchy:
         | 
| 1173 | 
            +
                              - name: "Common"
         | 
| 1174 | 
            +
                                lookup_key: mod_a::pp_lookup_key
         | 
| 1175 | 
            +
                                path: common.yaml
         | 
| 1176 | 
            +
                            YAML
         | 
| 1177 | 
            +
                          'data' => {
         | 
| 1178 | 
            +
                            'common.yaml' => <<-YAML.unindent
         | 
| 1179 | 
            +
                              mod_a::b: value mod_a::b (from mod_a)
         | 
| 1180 | 
            +
                              YAML
         | 
| 694 1181 | 
             
                          }
         | 
| 695 | 
            -
                        ],
         | 
| 696 | 
            -
                          :value => { 'k1' => 'env_e1', 'k2' => 'module_e2', 'k3' => 'env_e3' },
         | 
| 697 | 
            -
                          :event => :result,
         | 
| 698 | 
            -
                          :merge => :deep,
         | 
| 699 | 
            -
                          :options => { 'merge_hash_arrays' => true },
         | 
| 700 | 
            -
                          :type => :merge
         | 
| 701 1182 | 
             
                        }
         | 
| 702 | 
            -
                       | 
| 1183 | 
            +
                      }
         | 
| 1184 | 
            +
                    end
         | 
| 1185 | 
            +
             | 
| 1186 | 
            +
                    it 'finds data in the module' do
         | 
| 1187 | 
            +
                      expect(lookup('mod_a::b')).to eql('value mod_a::b (from mod_a)')
         | 
| 1188 | 
            +
                    end
         | 
| 703 1189 | 
             
                  end
         | 
| 704 | 
            -
                end
         | 
| 705 1190 |  | 
| 706 | 
            -
             | 
| 707 | 
            -
             | 
| 708 | 
            -
             | 
| 709 | 
            -
             | 
| 710 | 
            -
             | 
| 711 | 
            -
             | 
| 1191 | 
            +
                  context 'using a lookup_key that is a puppet function' do
         | 
| 1192 | 
            +
                    let(:mod_a_files) do
         | 
| 1193 | 
            +
                      {
         | 
| 1194 | 
            +
                        'mod_a' => {
         | 
| 1195 | 
            +
                          'functions' => {
         | 
| 1196 | 
            +
                            'pp_lookup_key.pp' => <<-PUPPET.unindent
         | 
| 1197 | 
            +
                            function mod_a::pp_lookup_key($key, $options, $context) {
         | 
| 1198 | 
            +
                              case $key {
         | 
| 1199 | 
            +
                                'mod_a::really_interpolated': { $context.interpolate("-- %{lookup('mod_a::a')} --") }
         | 
| 1200 | 
            +
                                'mod_a::recursive': { lookup($key) }
         | 
| 1201 | 
            +
                                default: {
         | 
| 1202 | 
            +
                                  if $context.cache_has_key(mod_a::a) {
         | 
| 1203 | 
            +
                                    $context.explain || { 'reusing cache' }
         | 
| 1204 | 
            +
                                  } else {
         | 
| 1205 | 
            +
                                    $context.explain || { 'initializing cache' }
         | 
| 1206 | 
            +
                                    $context.cache_all({
         | 
| 1207 | 
            +
                                      mod_a::a => 'value mod_a::a (from mod_a)',
         | 
| 1208 | 
            +
                                      mod_a::b => 'value mod_a::b (from mod_a)',
         | 
| 1209 | 
            +
                                      mod_a::c => 'value mod_a::c (from mod_a)',
         | 
| 1210 | 
            +
                                      mod_a::hash_a => {
         | 
| 1211 | 
            +
                                        a => 'value mod_a::hash_a.a (from mod_a)',
         | 
| 1212 | 
            +
                                        b => 'value mod_a::hash_a.b (from mod_a)'
         | 
| 1213 | 
            +
                                      },
         | 
| 1214 | 
            +
                                      mod_a::hash_b => {
         | 
| 1215 | 
            +
                                        a => 'value mod_a::hash_b.a (from mod_a)',
         | 
| 1216 | 
            +
                                        b => 'value mod_a::hash_b.b (from mod_a)'
         | 
| 1217 | 
            +
                                      },
         | 
| 1218 | 
            +
                                      mod_a::interpolated => "-- %{lookup('mod_a::a')} --",
         | 
| 1219 | 
            +
                                      mod_a::a_a => "-- %{lookup('mod_a::hash_a.a')} --",
         | 
| 1220 | 
            +
                                      mod_a::a_b => "-- %{lookup('mod_a::hash_a.b')} --",
         | 
| 1221 | 
            +
                                      mod_a::b_a => "-- %{lookup('mod_a::hash_b.a')} --",
         | 
| 1222 | 
            +
                                      mod_a::b_b => "-- %{lookup('mod_a::hash_b.b')} --",
         | 
| 1223 | 
            +
                                      'mod_a::a.quoted.key' => 'value mod_a::a.quoted.key (from mod_a)',
         | 
| 1224 | 
            +
                                      mod_a::sensitive => Sensitive('reduct me please'),
         | 
| 1225 | 
            +
                                      mod_a::type => Object[{name => 'FindMe', 'attributes' => {'x' => String}}],
         | 
| 1226 | 
            +
                                      mod_a::version => SemVer('3.4.1'),
         | 
| 1227 | 
            +
                                      mod_a::version_range => SemVerRange('>=3.4.1'),
         | 
| 1228 | 
            +
                                      mod_a::timestamp => Timestamp("1994-03-25T19:30:00"),
         | 
| 1229 | 
            +
                                      mod_a::timespan => Timespan("3-10:00:00")
         | 
| 1230 | 
            +
                                    })
         | 
| 1231 | 
            +
                                  }
         | 
| 1232 | 
            +
                                  if !$context.cache_has_key($key) {
         | 
| 1233 | 
            +
                                    $context.not_found
         | 
| 1234 | 
            +
                                  }
         | 
| 1235 | 
            +
                                  $context.explain || { "returning value for $key" }
         | 
| 1236 | 
            +
                                  $context.cached_value($key)
         | 
| 1237 | 
            +
                                }
         | 
| 1238 | 
            +
                              }
         | 
| 1239 | 
            +
                            }
         | 
| 1240 | 
            +
                          PUPPET
         | 
| 1241 | 
            +
                          },
         | 
| 1242 | 
            +
                          'hiera.yaml' => <<-YAML.unindent,
         | 
| 1243 | 
            +
                          ---
         | 
| 1244 | 
            +
                          version: 5
         | 
| 1245 | 
            +
                          hierarchy:
         | 
| 1246 | 
            +
                            - name: "Common"
         | 
| 1247 | 
            +
                              lookup_key: mod_a::pp_lookup_key
         | 
| 1248 | 
            +
                        YAML
         | 
| 1249 | 
            +
                        }
         | 
| 1250 | 
            +
                      }
         | 
| 1251 | 
            +
                    end
         | 
| 1252 | 
            +
             | 
| 1253 | 
            +
                    it 'finds data in the module' do
         | 
| 1254 | 
            +
                      expect(lookup('mod_a::b')).to eql('value mod_a::b (from mod_a)')
         | 
| 1255 | 
            +
                    end
         | 
| 1256 | 
            +
             | 
| 1257 | 
            +
                    it 'environment data has higher priority than module data' do
         | 
| 1258 | 
            +
                      expect(lookup('mod_a::a')).to eql('value mod_a::a (from environment)')
         | 
| 1259 | 
            +
                    end
         | 
| 1260 | 
            +
             | 
| 1261 | 
            +
                    it 'finds quoted keys in the module' do
         | 
| 1262 | 
            +
                      expect(lookup('"mod_a::a.quoted.key"')).to eql('value mod_a::a.quoted.key (from mod_a)')
         | 
| 1263 | 
            +
                    end
         | 
| 1264 | 
            +
             | 
| 1265 | 
            +
                    it 'will not resolve interpolated expressions' do
         | 
| 1266 | 
            +
                      expect(lookup('mod_a::interpolated')).to eql("-- %{lookup('mod_a::a')} --")
         | 
| 1267 | 
            +
                    end
         | 
| 1268 | 
            +
             | 
| 1269 | 
            +
                    it 'resolves interpolated expressions using Context#interpolate' do
         | 
| 1270 | 
            +
                      expect(lookup('mod_a::really_interpolated')).to eql("-- value mod_a::a (from environment) --")
         | 
| 1271 | 
            +
                    end
         | 
| 1272 | 
            +
             | 
| 1273 | 
            +
                    it 'will not merge hashes from environment and module unless strategy hash is used' do
         | 
| 1274 | 
            +
                      expect(lookup('mod_a::hash_a')).to eql({ 'a' => 'value mod_a::hash_a.a (from environment)' })
         | 
| 1275 | 
            +
                    end
         | 
| 1276 | 
            +
             | 
| 1277 | 
            +
                    it 'merges hashes from environment and module when merge strategy hash is used' do
         | 
| 1278 | 
            +
                      expect(lookup('mod_a::hash_a', :merge => 'hash')).to eql({ 'a' => 'value mod_a::hash_a.a (from environment)', 'b' => 'value mod_a::hash_a.b (from mod_a)' })
         | 
| 1279 | 
            +
                    end
         | 
| 1280 | 
            +
             | 
| 1281 | 
            +
                    it 'traps recursive lookup trapped' do
         | 
| 1282 | 
            +
                      expect(explain('mod_a::recursive')).to include('Recursive lookup detected')
         | 
| 1283 | 
            +
                    end
         | 
| 1284 | 
            +
             | 
| 1285 | 
            +
                    it 'private cache is persisted over multiple calls' do
         | 
| 1286 | 
            +
                      collect_notices("notice(lookup('mod_a::b')) notice(lookup('mod_a::c'))", true)
         | 
| 1287 | 
            +
                      expect(notices).to eql(['value mod_a::b (from mod_a)', 'value mod_a::c (from mod_a)'])
         | 
| 1288 | 
            +
                      expect(explanation).to match(/initializing cache.*reusing cache/m)
         | 
| 1289 | 
            +
                      expect(explanation).not_to match(/initializing cache.*initializing cache/m)
         | 
| 1290 | 
            +
                    end
         | 
| 1291 | 
            +
             | 
| 1292 | 
            +
                    it 'the same key is requested only once' do
         | 
| 1293 | 
            +
                      collect_notices("notice(lookup('mod_a::b')) notice(lookup('mod_a::b'))", true)
         | 
| 1294 | 
            +
                      expect(notices).to eql(['value mod_a::b (from mod_a)', 'value mod_a::b (from mod_a)'])
         | 
| 1295 | 
            +
                      expect(explanation).to match(/Found key: "mod_a::b".*Found key: "mod_a::b"/m)
         | 
| 1296 | 
            +
                      expect(explanation).to match(/returning value for mod_a::b/m)
         | 
| 1297 | 
            +
                      expect(explanation).not_to match(/returning value for mod_a::b.*returning value for mod_a::b/m)
         | 
| 1298 | 
            +
                    end
         | 
| 1299 | 
            +
             | 
| 1300 | 
            +
                    context 'and calling function via API' do
         | 
| 1301 | 
            +
                      it 'finds and delivers rich data' do
         | 
| 1302 | 
            +
                        collect_notices("notice('success')") do |scope|
         | 
| 1303 | 
            +
                          expect(lookup_func.call(scope, 'mod_a::sensitive')).to be_a(Puppet::Pops::Types::PSensitiveType::Sensitive)
         | 
| 1304 | 
            +
                          expect(lookup_func.call(scope, 'mod_a::type')).to be_a(Puppet::Pops::Types::PObjectType)
         | 
| 1305 | 
            +
                          expect(lookup_func.call(scope, 'mod_a::version')).to eql(SemanticPuppet::Version.parse('3.4.1'))
         | 
| 1306 | 
            +
                          expect(lookup_func.call(scope, 'mod_a::version_range')).to eql(SemanticPuppet::VersionRange.parse('>=3.4.1'))
         | 
| 1307 | 
            +
                          expect(lookup_func.call(scope, 'mod_a::timestamp')).to eql(Puppet::Pops::Time::Timestamp.parse('1994-03-25T19:30:00'))
         | 
| 1308 | 
            +
                          expect(lookup_func.call(scope, 'mod_a::timespan')).to eql(Puppet::Pops::Time::Timespan.parse('3-10:00:00'))
         | 
| 1309 | 
            +
                        end
         | 
| 1310 | 
            +
                        expect(notices).to eql(['success'])
         | 
| 1311 | 
            +
                      end
         | 
| 712 1312 | 
             
                    end
         | 
| 713 | 
            -
                    expect(lookup_invocation.explainer.to_s).to eq(<<EOS)
         | 
| 714 | 
            -
            Invalid key "lookup_options"
         | 
| 715 | 
            -
            EOS
         | 
| 716 1313 | 
             
                  end
         | 
| 717 | 
            -
                end
         | 
| 718 1314 |  | 
| 719 | 
            -
             | 
| 720 | 
            -
             | 
| 721 | 
            -
             | 
| 722 | 
            -
             | 
| 723 | 
            -
             | 
| 724 | 
            -
             | 
| 1315 | 
            +
                  context 'using a data_dig that is a ruby function' do
         | 
| 1316 | 
            +
                    let(:mod_a_files) do
         | 
| 1317 | 
            +
                      {
         | 
| 1318 | 
            +
                        'mod_a' => {
         | 
| 1319 | 
            +
                          'lib' => {
         | 
| 1320 | 
            +
                            'puppet' => {
         | 
| 1321 | 
            +
                              'functions' => {
         | 
| 1322 | 
            +
                                'mod_a' => {
         | 
| 1323 | 
            +
                                  'ruby_dig.rb' => <<-RUBY.unindent
         | 
| 1324 | 
            +
                                  Puppet::Functions.create_function(:'mod_a::ruby_dig') do
         | 
| 1325 | 
            +
                                    dispatch :ruby_dig do
         | 
| 1326 | 
            +
                                      param 'Array[String[1]]', :segments
         | 
| 1327 | 
            +
                                      param 'Hash[String,Any]', :options
         | 
| 1328 | 
            +
                                      param 'Puppet::LookupContext', :context
         | 
| 1329 | 
            +
                                    end
         | 
| 1330 | 
            +
             | 
| 1331 | 
            +
                                    def ruby_dig(segments, options, context)
         | 
| 1332 | 
            +
                                      sub_segments = segments.dup
         | 
| 1333 | 
            +
                                      root_key = sub_segments.shift
         | 
| 1334 | 
            +
                                      case root_key
         | 
| 1335 | 
            +
                                      when 'mod_a::options'
         | 
| 1336 | 
            +
                                        hash = { 'mod_a::options' => options }
         | 
| 1337 | 
            +
                                      when 'mod_a::lookup'
         | 
| 1338 | 
            +
                                        return call_function('lookup', segments.join('.'))
         | 
| 1339 | 
            +
                                      else
         | 
| 1340 | 
            +
                                        hash = {
         | 
| 1341 | 
            +
                                          'mod_a::a' => 'value mod_a::a (from mod_a)',
         | 
| 1342 | 
            +
                                          'mod_a::b' => 'value mod_a::b (from mod_a)',
         | 
| 1343 | 
            +
                                          'mod_a::hash_a' => {
         | 
| 1344 | 
            +
                                            'a' => 'value mod_a::hash_a.a (from mod_a)',
         | 
| 1345 | 
            +
                                            'b' => 'value mod_a::hash_a.b (from mod_a)'
         | 
| 1346 | 
            +
                                          },
         | 
| 1347 | 
            +
                                          'mod_a::hash_b' => {
         | 
| 1348 | 
            +
                                            'a' => 'value mod_a::hash_b.a (from mod_a)',
         | 
| 1349 | 
            +
                                            'b' => 'value mod_a::hash_b.b (from mod_a)'
         | 
| 1350 | 
            +
                                          },
         | 
| 1351 | 
            +
                                          'mod_a::interpolated' => "-- %{lookup('mod_a::a')} --",
         | 
| 1352 | 
            +
                                          'mod_a::really_interpolated' => "-- %{lookup('mod_a::a')} --",
         | 
| 1353 | 
            +
                                          'mod_a::a_a' => "-- %{lookup('mod_a::hash_a.a')} --",
         | 
| 1354 | 
            +
                                          'mod_a::a_b' => "-- %{lookup('mod_a::hash_a.b')} --",
         | 
| 1355 | 
            +
                                          'mod_a::b_a' => "-- %{lookup('mod_a::hash_b.a')} --",
         | 
| 1356 | 
            +
                                          'mod_a::b_b' => "-- %{lookup('mod_a::hash_b.b')} --",
         | 
| 1357 | 
            +
                                          'mod_a::bad_type' => :oops,
         | 
| 1358 | 
            +
                                          'mod_a::bad_type_in_hash' => { 'a' => :oops },
         | 
| 1359 | 
            +
                                        }
         | 
| 1360 | 
            +
                                        end
         | 
| 1361 | 
            +
                                      context.not_found unless hash.include?(root_key)
         | 
| 1362 | 
            +
                                      value = sub_segments.reduce(hash[root_key]) do |memo, segment|
         | 
| 1363 | 
            +
                                        context.not_found unless memo.is_a?(Hash) && memo.include?(segment)
         | 
| 1364 | 
            +
                                        memo[segment]
         | 
| 1365 | 
            +
                                      end
         | 
| 1366 | 
            +
                                      root_key == 'mod_a::really_interpolated' ? context.interpolate(value) : value
         | 
| 1367 | 
            +
                                    end
         | 
| 1368 | 
            +
                                  end
         | 
| 1369 | 
            +
                                RUBY
         | 
| 1370 | 
            +
                                }
         | 
| 1371 | 
            +
                              }
         | 
| 1372 | 
            +
                            }
         | 
| 1373 | 
            +
                          },
         | 
| 1374 | 
            +
                          'hiera.yaml' => <<-YAML.unindent,
         | 
| 1375 | 
            +
                          ---
         | 
| 1376 | 
            +
                          version: 5
         | 
| 1377 | 
            +
                          hierarchy:
         | 
| 1378 | 
            +
                            - name: "Common"
         | 
| 1379 | 
            +
                              data_dig: mod_a::ruby_dig
         | 
| 1380 | 
            +
                              uri: "http://www.example.com/passed/as/option"
         | 
| 1381 | 
            +
                              options:
         | 
| 1382 | 
            +
                                option_a: Option value a
         | 
| 1383 | 
            +
                                option_b:
         | 
| 1384 | 
            +
                                  x: Option value b.x
         | 
| 1385 | 
            +
                                  y: Option value b.y
         | 
| 1386 | 
            +
                        YAML
         | 
| 1387 | 
            +
                        }
         | 
| 1388 | 
            +
                      }
         | 
| 1389 | 
            +
                    end
         | 
| 1390 | 
            +
             | 
| 1391 | 
            +
                    it 'finds data in the module' do
         | 
| 1392 | 
            +
                      expect(lookup('mod_a::b')).to eql('value mod_a::b (from mod_a)')
         | 
| 1393 | 
            +
                    end
         | 
| 1394 | 
            +
             | 
| 1395 | 
            +
                    it 'environment data has higher priority than module data' do
         | 
| 1396 | 
            +
                      expect(lookup('mod_a::a')).to eql('value mod_a::a (from environment)')
         | 
| 1397 | 
            +
                    end
         | 
| 1398 | 
            +
             | 
| 1399 | 
            +
                    it 'will not resolve interpolated expressions' do
         | 
| 1400 | 
            +
                      expect(lookup('mod_a::interpolated')).to eql("-- %{lookup('mod_a::a')} --")
         | 
| 1401 | 
            +
                    end
         | 
| 1402 | 
            +
             | 
| 1403 | 
            +
                    it 'resolves interpolated expressions using Context#interpolate' do
         | 
| 1404 | 
            +
                      expect(lookup('mod_a::really_interpolated')).to eql("-- value mod_a::a (from environment) --")
         | 
| 1405 | 
            +
                    end
         | 
| 1406 | 
            +
             | 
| 1407 | 
            +
                    it 'does not accept return of runtime type from function' do
         | 
| 1408 | 
            +
                      expect(explain('mod_a::bad_type')).to include('Value returned from Hierarchy entry "Common" has wrong type')
         | 
| 1409 | 
            +
                    end
         | 
| 1410 | 
            +
             | 
| 1411 | 
            +
                    it 'does not accept return of runtime type embedded in hash from function' do
         | 
| 1412 | 
            +
                      expect(explain('mod_a::bad_type_in_hash')).to include('Value returned from Hierarchy entry "Common" has wrong type')
         | 
| 1413 | 
            +
                    end
         | 
| 1414 | 
            +
             | 
| 1415 | 
            +
                    it 'will not merge hashes from environment and module unless strategy hash is used' do
         | 
| 1416 | 
            +
                      expect(lookup('mod_a::hash_a')).to eql({'a' => 'value mod_a::hash_a.a (from environment)'})
         | 
| 1417 | 
            +
                    end
         | 
| 1418 | 
            +
             | 
| 1419 | 
            +
                    it 'hierarchy entry options are passed to the function' do
         | 
| 1420 | 
            +
                      expect(lookup('mod_a::options.option_b.x')).to eql('Option value b.x')
         | 
| 1421 | 
            +
                    end
         | 
| 1422 | 
            +
             | 
| 1423 | 
            +
                    it 'hierarchy entry "uri" is passed as location option to the function' do
         | 
| 1424 | 
            +
                      expect(lookup('mod_a::options.uri')).to eql('http://www.example.com/passed/as/option')
         | 
| 1425 | 
            +
                    end
         | 
| 1426 | 
            +
             | 
| 1427 | 
            +
                    it 'recursive lookup is trapped' do
         | 
| 1428 | 
            +
                      expect(explain('mod_a::lookup.mod_a::lookup')).to include('Recursive lookup detected')
         | 
| 1429 | 
            +
                    end
         | 
| 1430 | 
            +
             | 
| 1431 | 
            +
                    context 'with merge strategy hash' do
         | 
| 1432 | 
            +
                      it 'merges hashes from environment and module' do
         | 
| 1433 | 
            +
                        expect(lookup('mod_a::hash_a', :merge => 'hash')).to eql({'a' => 'value mod_a::hash_a.a (from environment)', 'b' => 'value mod_a::hash_a.b (from mod_a)'})
         | 
| 1434 | 
            +
                      end
         | 
| 1435 | 
            +
             | 
| 1436 | 
            +
                      it 'will "undig" value from data_dig function, merge root hashes, and then dig to get values by subkey' do
         | 
| 1437 | 
            +
                        expect(lookup(['mod_a::hash_a.a', 'mod_a::hash_a.b'], :merge => 'hash')).to eql(
         | 
| 1438 | 
            +
                          ['value mod_a::hash_a.a (from environment)', 'value mod_a::hash_a.b (from mod_a)'])
         | 
| 1439 | 
            +
                      end
         | 
| 725 1440 | 
             
                    end
         | 
| 726 | 
            -
                    expect(lookup_invocation.explainer.to_s).to eq(<<EOS)
         | 
| 727 | 
            -
            Invalid key "lookup_options"
         | 
| 728 | 
            -
            EOS
         | 
| 729 1441 | 
             
                  end
         | 
| 730 1442 | 
             
                end
         | 
| 731 | 
            -
             | 
| 732 1443 | 
             
              end
         | 
| 733 1444 | 
             
            end
         |