puppet 3.2.4 → 3.3.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/COMMITTERS.md +101 -42
- data/Gemfile +15 -4
- data/README.md +5 -1
- data/README_DEVELOPER.md +117 -54
- data/Rakefile +4 -0
- data/ext/build_defaults.yaml +3 -2
- data/ext/debian/puppet-common.manpages +33 -1
- data/ext/gentoo/init.d/puppet +1 -1
- data/ext/gentoo/init.d/puppetmaster +1 -1
- data/ext/redhat/puppet.spec.erb +0 -1
- data/install.rb +2 -1
- data/lib/hiera/backend/puppet_backend.rb +1 -1
- data/lib/puppet/application.rb +10 -9
- data/lib/puppet/application/agent.rb +87 -93
- data/lib/puppet/application/apply.rb +0 -2
- data/lib/puppet/application/device.rb +3 -3
- data/lib/puppet/application/kick.rb +2 -2
- data/lib/puppet/application/master.rb +41 -19
- data/lib/puppet/application/queue.rb +5 -3
- data/lib/puppet/bindings.rb +147 -0
- data/lib/puppet/configurer.rb +25 -15
- data/lib/puppet/configurer/fact_handler.rb +2 -9
- data/lib/puppet/daemon.rb +44 -33
- data/lib/puppet/defaults.rb +57 -26
- data/lib/puppet/error.rb +1 -1
- data/lib/puppet/external/dot.rb +2 -2
- data/lib/puppet/external/nagios/base.rb +1 -6
- data/lib/puppet/external/pson/common.rb +2 -2
- data/lib/puppet/external/pson/pure/generator.rb +2 -2
- data/lib/puppet/external/pson/pure/parser.rb +1 -1
- data/lib/puppet/face/ca.rb +1 -1
- data/lib/puppet/face/config.rb +1 -1
- data/lib/puppet/face/help.rb +2 -2
- data/lib/puppet/face/module/list.rb +2 -2
- data/lib/puppet/feature/rails.rb +1 -1
- data/lib/puppet/file_bucket/dipper.rb +0 -1
- data/lib/puppet/file_serving/base.rb +1 -1
- data/lib/puppet/file_serving/configuration/parser.rb +20 -14
- data/lib/puppet/forge.rb +0 -32
- data/lib/puppet/forge/cache.rb +1 -1
- data/lib/puppet/forge/errors.rb +3 -3
- data/lib/puppet/forge/repository.rb +7 -42
- data/lib/puppet/graph.rb +11 -0
- data/lib/puppet/graph/key.rb +26 -0
- data/lib/puppet/graph/prioritizer.rb +29 -0
- data/lib/puppet/graph/random_prioritizer.rb +16 -0
- data/lib/puppet/{rb_tree_map.rb → graph/rb_tree_map.rb} +3 -3
- data/lib/puppet/graph/relationship_graph.rb +246 -0
- data/lib/puppet/graph/sequential_prioritizer.rb +31 -0
- data/lib/puppet/{simple_graph.rb → graph/simple_graph.rb} +22 -3
- data/lib/puppet/graph/title_hash_prioritizer.rb +16 -0
- data/lib/puppet/indirector.rb +2 -2
- data/lib/puppet/indirector/catalog/compiler.rb +10 -7
- data/lib/puppet/indirector/catalog/static_compiler.rb +50 -0
- data/lib/puppet/indirector/certificate/rest.rb +1 -1
- data/lib/puppet/indirector/exec.rb +1 -1
- data/lib/puppet/indirector/facts/facter.rb +2 -2
- data/lib/puppet/indirector/facts/inventory_active_record.rb +0 -1
- data/lib/puppet/indirector/facts/network_device.rb +1 -1
- data/lib/puppet/indirector/file_bucket_file/file.rb +0 -1
- data/lib/puppet/indirector/indirection.rb +2 -2
- data/lib/puppet/indirector/memory.rb +9 -0
- data/lib/puppet/indirector/node/ldap.rb +2 -4
- data/lib/puppet/indirector/report/processor.rb +1 -2
- data/lib/puppet/indirector/report/rest.rb +1 -1
- data/lib/puppet/indirector/request.rb +32 -10
- data/lib/puppet/indirector/resource/rest.rb +1 -1
- data/lib/puppet/indirector/resource_type/parser.rb +31 -12
- data/lib/puppet/interface.rb +1 -1
- data/lib/puppet/interface/documentation.rb +7 -11
- data/lib/puppet/interface/option.rb +1 -1
- data/lib/puppet/interface/option_builder.rb +1 -1
- data/lib/puppet/metatype/manager.rb +2 -2
- data/lib/puppet/module.rb +7 -1
- data/lib/puppet/module_tool.rb +1 -1
- data/lib/puppet/module_tool/applications/application.rb +10 -0
- data/lib/puppet/module_tool/applications/installer.rb +6 -3
- data/lib/puppet/module_tool/dependency.rb +2 -0
- data/lib/puppet/module_tool/errors/upgrader.rb +1 -1
- data/lib/puppet/module_tool/metadata.rb +25 -13
- data/lib/puppet/module_tool/modulefile.rb +7 -7
- data/lib/puppet/module_tool/shared_behaviors.rb +4 -2
- data/lib/puppet/module_tool/skeleton.rb +1 -1
- data/lib/puppet/module_tool/skeleton/templates/generator/manifests/init.pp.erb +5 -5
- data/lib/puppet/module_tool/skeleton/templates/generator/tests/init.pp.erb +5 -4
- data/lib/puppet/network/auth_config_parser.rb +3 -0
- data/lib/puppet/network/authconfig.rb +0 -1
- data/lib/puppet/network/authorization.rb +1 -1
- data/lib/puppet/network/authstore.rb +2 -2
- data/lib/puppet/network/format_handler.rb +25 -114
- data/lib/puppet/network/format_support.rb +106 -0
- data/lib/puppet/network/formats.rb +10 -4
- data/lib/puppet/network/http/compression.rb +1 -1
- data/lib/puppet/network/http/connection.rb +76 -32
- data/lib/puppet/network/http/handler.rb +122 -61
- data/lib/puppet/network/http/rack/rest.rb +1 -1
- data/lib/puppet/network/http/webrick/rest.rb +9 -3
- data/lib/puppet/network/http_pool.rb +2 -2
- data/lib/puppet/network/resolver.rb +1 -0
- data/lib/puppet/network/server.rb +5 -81
- data/lib/puppet/node/environment.rb +256 -13
- data/lib/puppet/node/facts.rb +28 -2
- data/lib/puppet/parameter.rb +27 -18
- data/lib/puppet/parameter/boolean.rb +20 -0
- data/lib/puppet/parameter/path.rb +1 -1
- data/lib/puppet/parameter/value.rb +1 -1
- data/lib/puppet/parameter/value_collection.rb +1 -1
- data/lib/puppet/parser/ast/arithmetic_operator.rb +8 -0
- data/lib/puppet/parser/ast/casestatement.rb +0 -3
- data/lib/puppet/parser/ast/lambda.rb +25 -6
- data/lib/puppet/parser/ast/leaf.rb +10 -3
- data/lib/puppet/parser/ast/nop.rb +1 -1
- data/lib/puppet/parser/ast/resource_override.rb +0 -2
- data/lib/puppet/parser/compiler.rb +92 -34
- data/lib/puppet/parser/files.rb +0 -5
- data/lib/puppet/parser/functions/create_resources.rb +23 -46
- data/lib/puppet/parser/functions/each.rb +0 -2
- data/lib/puppet/parser/functions/extlookup.rb +2 -2
- data/lib/puppet/parser/functions/foreach.rb +0 -2
- data/lib/puppet/parser/functions/hiera_include.rb +1 -1
- data/lib/puppet/parser/functions/lookup.rb +44 -0
- data/lib/puppet/parser/functions/slice.rb +1 -1
- data/lib/puppet/parser/grammar.ra +0 -1
- data/lib/puppet/parser/lexer.rb +0 -1
- data/lib/puppet/parser/parser.rb +0 -1
- data/lib/puppet/parser/parser_factory.rb +3 -2
- data/lib/puppet/parser/parser_support.rb +1 -1
- data/lib/puppet/parser/relationship.rb +1 -1
- data/lib/puppet/parser/scope.rb +49 -24
- data/lib/puppet/parser/type_loader.rb +13 -18
- data/lib/puppet/pops.rb +45 -0
- data/lib/puppet/pops/adaptable.rb +2 -2
- data/lib/puppet/pops/adapters.rb +4 -0
- data/lib/puppet/pops/binder/binder.rb +421 -0
- data/lib/puppet/pops/binder/binder_issues.rb +142 -0
- data/lib/puppet/pops/binder/bindings_checker.rb +217 -0
- data/lib/puppet/pops/binder/bindings_composer.rb +241 -0
- data/lib/puppet/pops/binder/bindings_factory.rb +847 -0
- data/lib/puppet/pops/binder/bindings_label_provider.rb +46 -0
- data/lib/puppet/pops/binder/bindings_loader.rb +79 -0
- data/lib/puppet/pops/binder/bindings_model.rb +215 -0
- data/lib/puppet/pops/binder/bindings_model_dumper.rb +205 -0
- data/lib/puppet/pops/binder/bindings_validator_factory.rb +28 -0
- data/lib/puppet/pops/binder/config/binder_config.rb +139 -0
- data/lib/puppet/pops/binder/config/binder_config_checker.rb +183 -0
- data/lib/puppet/pops/binder/config/diagnostic_producer.rb +32 -0
- data/lib/puppet/pops/binder/config/issues.rb +106 -0
- data/lib/puppet/pops/binder/hiera2.rb +10 -0
- data/lib/puppet/pops/binder/hiera2/bindings_provider.rb +148 -0
- data/lib/puppet/pops/binder/hiera2/config.rb +69 -0
- data/lib/puppet/pops/binder/hiera2/config_checker.rb +68 -0
- data/lib/puppet/pops/binder/hiera2/diagnostic_producer.rb +36 -0
- data/lib/puppet/pops/binder/hiera2/issues.rb +67 -0
- data/lib/puppet/pops/binder/hiera2/json_backend.rb +18 -0
- data/lib/puppet/pops/binder/hiera2/yaml_backend.rb +21 -0
- data/lib/puppet/pops/binder/injector.rb +688 -0
- data/lib/puppet/pops/binder/injector_entry.rb +53 -0
- data/lib/puppet/pops/binder/key_factory.rb +61 -0
- data/lib/puppet/pops/binder/producers.rb +829 -0
- data/lib/puppet/pops/binder/scheme_handler/confdir_hiera_scheme.rb +67 -0
- data/lib/puppet/pops/binder/scheme_handler/confdir_scheme.rb +34 -0
- data/lib/puppet/pops/binder/scheme_handler/module_hiera_scheme.rb +92 -0
- data/lib/puppet/pops/binder/scheme_handler/module_scheme.rb +84 -0
- data/lib/puppet/pops/binder/scheme_handler/symbolic_scheme.rb +54 -0
- data/lib/puppet/pops/binder/system_bindings.rb +72 -0
- data/lib/puppet/pops/issue_reporter.rb +75 -0
- data/lib/puppet/pops/issues.rb +9 -5
- data/lib/puppet/pops/model/ast_transformer.rb +4 -4
- data/lib/puppet/pops/model/ast_tree_dumper.rb +1 -1
- data/lib/puppet/pops/model/factory.rb +25 -13
- data/lib/puppet/pops/model/model.rb +1 -1
- data/lib/puppet/pops/model/tree_dumper.rb +2 -2
- data/lib/puppet/pops/parser/egrammar.ra +0 -1
- data/lib/puppet/pops/parser/eparser.rb +1 -2
- data/lib/puppet/pops/parser/evaluating_parser.rb +162 -0
- data/lib/puppet/pops/parser/lexer.rb +8 -6
- data/lib/puppet/pops/types/class_loader.rb +118 -0
- data/lib/puppet/pops/types/type_calculator.rb +557 -0
- data/lib/puppet/pops/types/type_factory.rb +147 -0
- data/lib/puppet/pops/types/type_parser.rb +117 -0
- data/lib/puppet/pops/types/types.rb +132 -0
- data/lib/puppet/pops/validation.rb +146 -17
- data/lib/puppet/pops/validation/checker3_1.rb +1 -1
- data/lib/puppet/pops/validation/validator_factory_3_1.rb +6 -16
- data/lib/puppet/property.rb +3 -3
- data/lib/puppet/property/keyvalue.rb +1 -1
- data/lib/puppet/provider.rb +2 -2
- data/lib/puppet/provider/aixobject.rb +19 -21
- data/lib/puppet/provider/augeas/augeas.rb +3 -1
- data/lib/puppet/provider/command.rb +2 -2
- data/lib/puppet/provider/group/aix.rb +1 -1
- data/lib/puppet/provider/group/ldap.rb +1 -1
- data/lib/puppet/provider/macauthorization/macauthorization.rb +1 -1
- data/lib/puppet/provider/mailalias/aliases.rb +3 -8
- data/lib/puppet/provider/mcx/mcxcontent.rb +7 -1
- data/lib/puppet/provider/mount.rb +8 -3
- data/lib/puppet/provider/nameservice.rb +1 -1
- data/lib/puppet/provider/nameservice/directoryservice.rb +5 -5
- data/lib/puppet/provider/package/appdmg.rb +1 -1
- data/lib/puppet/provider/package/apt.rb +0 -1
- data/lib/puppet/provider/package/dpkg.rb +86 -32
- data/lib/puppet/provider/package/fink.rb +0 -2
- data/lib/puppet/provider/package/freebsd.rb +0 -2
- data/lib/puppet/provider/package/openbsd.rb +57 -10
- data/lib/puppet/provider/package/opkg.rb +0 -1
- data/lib/puppet/provider/package/pacman.rb +0 -1
- data/lib/puppet/provider/package/pip.rb +1 -1
- data/lib/puppet/provider/package/pkgdmg.rb +17 -6
- data/lib/puppet/provider/package/pkgutil.rb +1 -1
- data/lib/puppet/provider/package/portage.rb +9 -1
- data/lib/puppet/provider/package/ports.rb +2 -2
- data/lib/puppet/provider/package/rpm.rb +29 -12
- data/lib/puppet/provider/package/rug.rb +1 -1
- data/lib/puppet/provider/package/urpmi.rb +11 -15
- data/lib/puppet/provider/package/windows/exe_package.rb +1 -1
- data/lib/puppet/provider/package/windows/package.rb +1 -26
- data/lib/puppet/provider/package/yum.rb +1 -1
- data/lib/puppet/provider/package/zypper.rb +22 -3
- data/lib/puppet/provider/parsedfile.rb +1 -12
- data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +1 -1
- data/lib/puppet/provider/service/base.rb +1 -1
- data/lib/puppet/provider/service/daemontools.rb +3 -3
- data/lib/puppet/provider/service/debian.rb +1 -1
- data/lib/puppet/provider/service/init.rb +14 -20
- data/lib/puppet/provider/service/openrc.rb +3 -1
- data/lib/puppet/provider/service/redhat.rb +5 -8
- data/lib/puppet/provider/service/runit.rb +3 -2
- data/lib/puppet/provider/service/systemd.rb +1 -1
- data/lib/puppet/provider/ssh_authorized_key/parsed.rb +1 -1
- data/lib/puppet/provider/sshkey/parsed.rb +0 -2
- data/lib/puppet/provider/user/aix.rb +25 -12
- data/lib/puppet/provider/user/directoryservice.rb +4 -7
- data/lib/puppet/provider/user/ldap.rb +0 -1
- data/lib/puppet/provider/user/user_role_add.rb +2 -0
- data/lib/puppet/provider/user/useradd.rb +1 -1
- data/lib/puppet/provider/zone/solaris.rb +1 -2
- data/lib/puppet/reference/metaparameter.rb +1 -1
- data/lib/puppet/reference/type.rb +1 -1
- data/lib/puppet/reports/rrdgraph.rb +1 -1
- data/lib/puppet/reports/tagmail.rb +1 -1
- data/lib/puppet/resource.rb +16 -4
- data/lib/puppet/resource/catalog.rb +111 -173
- data/lib/puppet/resource/status.rb +42 -3
- data/lib/puppet/resource/type.rb +33 -46
- data/lib/puppet/resource/type_collection.rb +19 -15
- data/lib/puppet/run.rb +5 -1
- data/lib/puppet/scheduler/scheduler.rb +14 -15
- data/lib/puppet/settings.rb +78 -41
- data/lib/puppet/settings/boolean_setting.rb +0 -2
- data/lib/puppet/settings/config_file.rb +0 -2
- data/lib/puppet/settings/directory_setting.rb +0 -2
- data/lib/puppet/settings/duration_setting.rb +0 -2
- data/lib/puppet/settings/enum_setting.rb +16 -0
- data/lib/puppet/settings/file_setting.rb +0 -2
- data/lib/puppet/settings/path_setting.rb +0 -2
- data/lib/puppet/settings/string_setting.rb +0 -3
- data/lib/puppet/settings/terminus_setting.rb +0 -2
- data/lib/puppet/ssl/certificate_authority.rb +102 -9
- data/lib/puppet/test/test_helper.rb +1 -0
- data/lib/puppet/transaction.rb +130 -292
- data/lib/puppet/transaction/additional_resource_generator.rb +126 -0
- data/lib/puppet/transaction/event.rb +16 -1
- data/lib/puppet/transaction/report.rb +34 -14
- data/lib/puppet/transaction/resource_harness.rb +16 -19
- data/lib/puppet/type.rb +59 -53
- data/lib/puppet/type/component.rb +0 -2
- data/lib/puppet/type/cron.rb +13 -2
- data/lib/puppet/type/exec.rb +5 -7
- data/lib/puppet/type/file.rb +9 -32
- data/lib/puppet/type/file/content.rb +4 -1
- data/lib/puppet/type/file/ctime.rb +3 -1
- data/lib/puppet/type/file/ensure.rb +1 -1
- data/lib/puppet/type/file/mode.rb +0 -1
- data/lib/puppet/type/file/mtime.rb +2 -1
- data/lib/puppet/type/group.rb +7 -9
- data/lib/puppet/type/host.rb +1 -2
- data/lib/puppet/type/mcx.rb +0 -1
- data/lib/puppet/type/mount.rb +38 -6
- data/lib/puppet/type/package.rb +2 -2
- data/lib/puppet/type/resources.rb +5 -4
- data/lib/puppet/type/schedule.rb +1 -4
- data/lib/puppet/type/selmodule.rb +1 -1
- data/lib/puppet/type/service.rb +1 -3
- data/lib/puppet/type/tidy.rb +3 -3
- data/lib/puppet/type/user.rb +9 -13
- data/lib/puppet/type/yumrepo.rb +11 -7
- data/lib/puppet/util.rb +14 -7
- data/lib/puppet/util/autoload.rb +0 -1
- data/lib/puppet/util/backups.rb +1 -3
- data/lib/puppet/util/classgen.rb +1 -1
- data/lib/puppet/util/command_line/puppet_option_parser.rb +1 -3
- data/lib/puppet/util/command_line/trollop.rb +1 -1
- data/lib/puppet/util/constant_inflector.rb +1 -2
- data/lib/puppet/util/errors.rb +1 -0
- data/lib/puppet/util/file_watcher.rb +28 -0
- data/lib/puppet/util/fileparsing.rb +1 -3
- data/lib/puppet/util/filetype.rb +0 -1
- data/lib/puppet/util/http_proxy.rb +38 -0
- data/lib/puppet/util/ldap/manager.rb +1 -2
- data/lib/puppet/util/log.rb +31 -10
- data/lib/puppet/util/log/destinations.rb +0 -50
- data/lib/puppet/util/metric.rb +8 -1
- data/lib/puppet/util/monkey_patches.rb +14 -148
- data/lib/puppet/util/network_device/cisco/facts.rb +1 -1
- data/lib/puppet/util/network_device/config.rb +6 -9
- data/lib/puppet/util/network_device/transport/ssh.rb +1 -1
- data/lib/puppet/util/pidlock.rb +3 -0
- data/lib/puppet/util/posix.rb +1 -1
- data/lib/puppet/util/profiler.rb +1 -1
- data/lib/puppet/util/rdoc.rb +1 -1
- data/lib/puppet/util/rdoc/generators/puppet_generator.rb +0 -1
- data/lib/puppet/util/rdoc/generators/template/puppet/puppet.rb +50 -42
- data/lib/puppet/util/retryaction.rb +0 -1
- data/lib/puppet/util/symbolic_file_mode.rb +5 -1
- data/lib/puppet/util/tagging.rb +0 -2
- data/lib/puppet/util/warnings.rb +3 -0
- data/lib/puppet/util/watched_file.rb +37 -0
- data/lib/puppet/util/watcher.rb +17 -0
- data/lib/puppet/util/watcher/change_watcher.rb +33 -0
- data/lib/puppet/util/watcher/periodic_watcher.rb +37 -0
- data/lib/puppet/util/watcher/timer.rb +19 -0
- data/lib/puppet/util/windows/user.rb +1 -1
- data/lib/puppet/version.rb +1 -1
- data/lib/puppetx.rb +109 -0
- data/lib/puppetx/puppet/bindings_scheme_handler.rb +130 -0
- data/lib/puppetx/puppet/hiera2_backend.rb +31 -0
- data/lib/puppetx/puppet/syntax_checker.rb +91 -0
- data/lib/puppetx/puppetlabs/syntax_checkers/json.rb +39 -0
- data/lib/semver.rb +1 -1
- data/man/man8/puppet-kick.8 +1 -1
- data/spec/fixtures/integration/provider/cron/crontab/unspecialized +15 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/hiera1config/binder_config.yaml +18 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/hiera1config/hiera.yaml +8 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/hiera1config/modules/good/common.yaml +1 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/hiera1config/modules/good/hiera.yaml +10 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/ok/binder_config.yaml +19 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/ok/common.yaml +1 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/ok/hiera.yaml +11 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/ok/localhost.yaml +1 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/awesome/common.yaml +3 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/awesome/hiera.yaml +13 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/awesome/lib/puppet/bindings/awesome/default.rb +4 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/awesome/lib/puppetx/awesome/echo_backend.rb +11 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/awesome/lib/puppetx/awesome/echo_scheme_handler.rb +18 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/awesome/localhost.yaml +1 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/bad/common.yaml +3 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/bad/hiera_config.yaml +9 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/good/common.yaml +2 -0
- data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/good/hiera.yaml +11 -0
- data/spec/fixtures/unit/pops/binder/config/binder_config/ok/binder_config.yaml +9 -0
- data/spec/fixtures/unit/pops/binder/hiera2/bindings_provider/ok/hiera.yaml +9 -0
- data/spec/fixtures/unit/pops/binder/hiera2/bindings_provider/ok/node.example.com.json +9 -0
- data/spec/fixtures/unit/pops/binder/hiera2/bindings_provider/ok/node.example.com.yaml +5 -0
- data/spec/fixtures/unit/pops/binder/hiera2/config/bad_syntax/hiera.yaml +10 -0
- data/spec/fixtures/unit/pops/binder/hiera2/config/malformed_hierarchy/hiera.yaml +8 -0
- data/spec/fixtures/unit/pops/binder/hiera2/config/missing/foo.txt +1 -0
- data/spec/fixtures/unit/pops/binder/hiera2/config/no_backends/hiera.yaml +7 -0
- data/spec/fixtures/unit/pops/binder/hiera2/config/no_hierarchy/hiera.yaml +4 -0
- data/spec/fixtures/unit/pops/binder/hiera2/config/not_a_hash/hiera.yaml +2 -0
- data/spec/fixtures/unit/pops/binder/hiera2/config/ok/hiera.yaml +8 -0
- data/spec/fixtures/unit/pops/binder/hiera2/yaml_backend/empty/common.yaml +0 -0
- data/spec/fixtures/unit/pops/binder/hiera2/yaml_backend/invalid/common.yaml +1 -0
- data/spec/fixtures/unit/pops/binder/hiera2/yaml_backend/ok/common.yaml +2 -0
- data/spec/fixtures/unit/provider/package/openbsd/pkginfo_flavors.list +2 -0
- data/spec/integration/agent/logging_spec.rb +178 -0
- data/spec/integration/configurer_spec.rb +1 -1
- data/spec/integration/defaults_spec.rb +0 -6
- data/spec/integration/network/authconfig_spec.rb +19 -0
- data/spec/integration/network/server/webrick_spec.rb +10 -11
- data/spec/integration/parser/catalog_spec.rb +85 -0
- data/spec/integration/provider/cron/crontab_spec.rb +11 -0
- data/spec/integration/provider/mount_spec.rb +1 -0
- data/spec/integration/transaction_spec.rb +8 -8
- data/spec/integration/type/file_spec.rb +1 -1
- data/spec/integration/util/settings_spec.rb +58 -11
- data/spec/lib/matchers/include_in_order.rb +21 -0
- data/spec/lib/matchers/include_in_order_spec.rb +30 -0
- data/spec/lib/matchers/relationship_graph_matchers.rb +48 -0
- data/spec/lib/puppet_spec/compiler.rb +24 -0
- data/spec/lib/puppet_spec/pops.rb +16 -0
- data/spec/spec_helper.rb +0 -1
- data/spec/unit/application/agent_spec.rb +145 -145
- data/spec/unit/application/apply_spec.rb +1 -1
- data/spec/unit/application/doc_spec.rb +1 -1
- data/spec/unit/application/face_base_spec.rb +3 -3
- data/spec/unit/application/facts_spec.rb +1 -0
- data/spec/unit/application/master_spec.rb +0 -15
- data/spec/unit/application/queue_spec.rb +6 -12
- data/spec/unit/application/resource_spec.rb +1 -1
- data/spec/unit/configurer/fact_handler_spec.rb +19 -50
- data/spec/unit/configurer_spec.rb +23 -7
- data/spec/unit/daemon_spec.rb +97 -121
- data/spec/unit/defaults_spec.rb +44 -0
- data/spec/unit/face/node_spec.rb +2 -2
- data/spec/unit/file_serving/configuration/parser_spec.rb +23 -33
- data/spec/unit/file_serving/configuration_spec.rb +2 -2
- data/spec/unit/file_serving/mount/file_spec.rb +4 -4
- data/spec/unit/forge/repository_spec.rb +9 -29
- data/spec/unit/graph/key_spec.rb +41 -0
- data/spec/unit/{rb_tree_map_spec.rb → graph/rb_tree_map_spec.rb} +7 -7
- data/spec/unit/graph/relationship_graph_spec.rb +393 -0
- data/spec/unit/graph/sequential_prioritizer_spec.rb +32 -0
- data/spec/unit/{simple_graph_spec.rb → graph/simple_graph.rb} +42 -254
- data/spec/unit/graph/title_hash_prioritizer_spec.rb +49 -0
- data/spec/unit/hiera_puppet_spec.rb +1 -1
- data/spec/unit/indirector/catalog/active_record_spec.rb +4 -2
- data/spec/unit/indirector/catalog/compiler_spec.rb +20 -26
- data/spec/unit/indirector/face_spec.rb +1 -1
- data/spec/unit/indirector/facts/facter_spec.rb +11 -1
- data/spec/unit/indirector/facts/network_device_spec.rb +11 -1
- data/spec/unit/indirector/hiera_spec.rb +1 -1
- data/spec/unit/indirector/instrumentation_data/local_spec.rb +1 -1
- data/spec/unit/indirector/instrumentation_listener/local_spec.rb +1 -1
- data/spec/unit/indirector/request_spec.rb +92 -39
- data/spec/unit/indirector/rest_spec.rb +1 -0
- data/spec/unit/indirector_spec.rb +2 -2
- data/spec/unit/interface/option_builder_spec.rb +1 -0
- data/spec/unit/interface/option_spec.rb +1 -0
- data/spec/unit/interface_spec.rb +2 -2
- data/spec/unit/module_tool/applications/installer_spec.rb +49 -2
- data/spec/unit/module_tool/metadata_spec.rb +13 -0
- data/spec/unit/network/authstore_spec.rb +1 -1
- data/spec/unit/network/format_handler_spec.rb +33 -282
- data/spec/unit/network/format_support_spec.rb +199 -0
- data/spec/unit/network/formats_spec.rb +2 -2
- data/spec/unit/network/http/connection_spec.rb +88 -7
- data/spec/unit/network/http/handler_spec.rb +271 -249
- data/spec/unit/network/http/rack/rest_spec.rb +1 -1
- data/spec/unit/network/http/webrick/rest_spec.rb +73 -22
- data/spec/unit/network/http_pool_spec.rb +40 -0
- data/spec/unit/network/server_spec.rb +18 -207
- data/spec/unit/node/facts_spec.rb +68 -17
- data/spec/unit/other/selinux_spec.rb +24 -20
- data/spec/unit/parameter/boolean_spec.rb +25 -0
- data/spec/unit/parameter/value_collection_spec.rb +7 -7
- data/spec/unit/parameter_spec.rb +10 -13
- data/spec/unit/parser/ast/function_spec.rb +4 -4
- data/spec/unit/parser/ast/leaf_spec.rb +45 -6
- data/spec/unit/parser/collector_spec.rb +3 -3
- data/spec/unit/parser/compiler_spec.rb +4 -3
- data/spec/unit/parser/functions/create_resources_spec.rb +9 -25
- data/spec/unit/parser/functions/extlookup_spec.rb +2 -2
- data/spec/unit/parser/functions/hiera_include_spec.rb +12 -0
- data/spec/unit/parser/functions/lookup_spec.rb +96 -0
- data/spec/unit/parser/functions/regsubst_spec.rb +2 -2
- data/spec/unit/parser/functions/split_spec.rb +2 -2
- data/spec/unit/parser/functions/sprintf_spec.rb +1 -1
- data/spec/unit/parser/functions/versioncmp_spec.rb +2 -2
- data/spec/unit/parser/functions_spec.rb +7 -7
- data/spec/unit/parser/lexer_spec.rb +1 -1
- data/spec/unit/parser/methods/collect_spec.rb +43 -0
- data/spec/unit/parser/resource_spec.rb +9 -9
- data/spec/unit/parser/scope_spec.rb +45 -2
- data/spec/unit/parser/type_loader_spec.rb +159 -175
- data/spec/unit/pops/binder/binder_spec.rb +62 -0
- data/spec/unit/pops/binder/bindings_checker_spec.rb +196 -0
- data/spec/unit/pops/binder/bindings_composer_spec.rb +89 -0
- data/spec/unit/pops/binder/bindings_validator_factory_spec.rb +18 -0
- data/spec/unit/pops/binder/config/binder_config_spec.rb +48 -0
- data/spec/unit/pops/binder/hiera2/bindings_provider_spec.rb +74 -0
- data/spec/unit/pops/binder/hiera2/config_spec.rb +61 -0
- data/spec/unit/pops/binder/hiera2/yaml_backend_spec.rb +33 -0
- data/spec/unit/pops/binder/injector_spec.rb +789 -0
- data/spec/unit/pops/containment_spec.rb +1 -0
- data/spec/unit/pops/issues_spec.rb +1 -1
- data/spec/unit/pops/parser/evaluating_parser_spec.rb +88 -0
- data/spec/unit/pops/parser/lexer_spec.rb +1 -1
- data/spec/unit/pops/parser/parse_calls_spec.rb +4 -0
- data/spec/unit/pops/parser/parser_spec.rb +1 -1
- data/spec/unit/pops/types/type_calculator_spec.rb +484 -0
- data/spec/unit/pops/types/type_factory_spec.rb +65 -0
- data/spec/unit/pops/types/type_parser_spec.rb +93 -0
- data/spec/unit/property/list_spec.rb +1 -1
- data/spec/unit/property/ordered_list_spec.rb +1 -1
- data/spec/unit/provider/aixobject_spec.rb +101 -0
- data/spec/unit/provider/augeas/augeas_spec.rb +14 -3
- data/spec/unit/provider/mcx/mcxcontent_spec.rb +52 -16
- data/spec/unit/provider/mount/parsed_spec.rb +44 -56
- data/spec/unit/provider/mount_spec.rb +11 -2
- data/spec/unit/provider/naginator_spec.rb +8 -0
- data/spec/unit/provider/package/apt_spec.rb +5 -1
- data/spec/unit/provider/package/aptitude_spec.rb +9 -5
- data/spec/unit/provider/package/aptrpm_spec.rb +2 -2
- data/spec/unit/provider/package/dpkg_spec.rb +274 -99
- data/spec/unit/provider/package/openbsd_spec.rb +84 -1
- data/spec/unit/provider/package/opkg_spec.rb +3 -3
- data/spec/unit/provider/package/pip_spec.rb +16 -0
- data/spec/unit/provider/package/pkgdmg_spec.rb +62 -7
- data/spec/unit/provider/package/rpm_spec.rb +112 -21
- data/spec/unit/provider/package/urpmi.rb +80 -0
- data/spec/unit/provider/package/windows/exe_package_spec.rb +1 -1
- data/spec/unit/provider/package/yum_spec.rb +85 -0
- data/spec/unit/provider/package/zypper_spec.rb +25 -6
- data/spec/unit/provider/parsedfile_spec.rb +3 -2
- data/spec/unit/provider/service/init_spec.rb +10 -10
- data/spec/unit/provider/service/openrc_spec.rb +16 -0
- data/spec/unit/provider/service/openwrt_spec.rb +1 -1
- data/spec/unit/provider/service/redhat_spec.rb +7 -0
- data/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +2 -2
- data/spec/unit/provider/user/aix_spec.rb +89 -0
- data/spec/unit/provider/user/directoryservice_spec.rb +11 -4
- data/spec/unit/provider/user/user_role_add_spec.rb +18 -0
- data/spec/unit/provider_spec.rb +2 -13
- data/spec/unit/reports/http_spec.rb +1 -1
- data/spec/unit/resource/catalog_spec.rb +23 -97
- data/spec/unit/resource/resource_type.json +34 -0
- data/spec/unit/resource/status_spec.rb +56 -0
- data/spec/unit/resource/type_collection_spec.rb +6 -6
- data/spec/unit/resource/type_spec.rb +25 -5
- data/spec/unit/resource_spec.rb +68 -24
- data/spec/unit/run_spec.rb +16 -0
- data/spec/unit/scheduler/scheduler_spec.rb +14 -27
- data/spec/unit/semver_spec.rb +5 -0
- data/spec/unit/settings/enum_setting_spec.rb +27 -0
- data/spec/unit/settings_spec.rb +53 -44
- data/spec/unit/ssl/certificate_authority_spec.rb +155 -19
- data/spec/unit/transaction/additional_resource_generator_spec.rb +419 -0
- data/spec/unit/transaction/event_manager_spec.rb +2 -2
- data/spec/unit/transaction/event_spec.rb +57 -0
- data/spec/unit/transaction/report_spec.rb +66 -0
- data/spec/unit/transaction/resource_harness_spec.rb +27 -20
- data/spec/unit/transaction_spec.rb +182 -390
- data/spec/unit/type/augeas_spec.rb +3 -3
- data/spec/unit/type/component_spec.rb +0 -9
- data/spec/unit/type/computer_spec.rb +1 -1
- data/spec/unit/type/cron_spec.rb +2 -2
- data/spec/unit/type/exec_spec.rb +4 -2
- data/spec/unit/type/file/content_spec.rb +11 -0
- data/spec/unit/type/file/group_spec.rb +1 -1
- data/spec/unit/type/file_spec.rb +16 -8
- data/spec/unit/type/mount_spec.rb +445 -259
- data/spec/unit/type/package_spec.rb +4 -4
- data/spec/unit/type/resources_spec.rb +30 -1
- data/spec/unit/type/user_spec.rb +26 -3
- data/spec/unit/type/yumrepo_spec.rb +7 -27
- data/spec/unit/type/zone_spec.rb +4 -1
- data/spec/unit/type_spec.rb +66 -33
- data/spec/unit/util/backups_spec.rb +3 -3
- data/spec/unit/util/http_proxy_spec.rb +83 -0
- data/spec/unit/util/log_spec.rb +79 -8
- data/spec/unit/util/metric_spec.rb +12 -0
- data/spec/unit/util/monkey_patches_spec.rb +6 -0
- data/spec/unit/util/network_device/config_spec.rb +26 -64
- data/spec/unit/util/pidlock_spec.rb +4 -1
- data/spec/unit/util/tagging_spec.rb +5 -9
- data/spec/unit/util/warnings_spec.rb +1 -1
- data/spec/unit/util/watched_file_spec.rb +52 -0
- data/spec/unit/util/watcher/periodic_watcher_spec.rb +52 -0
- data/spec/unit/util/watcher_spec.rb +56 -0
- data/spec/unit/util_spec.rb +16 -0
- metadata +2767 -2576
- data/ext/debian/puppet.manpages +0 -32
- data/ext/osx/PackageInfo.plist +0 -36
- data/ext/osx/createpackage.sh +0 -187
- data/ext/redhat/rundir-perms.patch +0 -28
- data/lib/puppet/external/base64.rb +0 -19
- data/lib/puppet/util/graph.rb +0 -27
- data/lib/puppet/util/loadedfile.rb +0 -61
- data/lib/puppet/util/log_paths.rb +0 -22
- data/lib/puppet/util/subclass_loader.rb +0 -78
- data/spec/monkey_patches/publicize_methods.rb +0 -11
- data/spec/unit/util/loadedfile_spec.rb +0 -71
@@ -0,0 +1,10 @@
|
|
1
|
+
# The Hiera2 Module contains the classes needed to configure a bindings producer
|
2
|
+
# to read module specific data. The configuration is expected to be found in
|
3
|
+
# a hiera.yaml file in the root of each module
|
4
|
+
module Puppet::Pops::Binder::Hiera2
|
5
|
+
require 'puppet/pops/binder/hiera2/config_checker'
|
6
|
+
require 'puppet/pops/binder/hiera2/config'
|
7
|
+
require 'puppet/pops/binder/hiera2/diagnostic_producer'
|
8
|
+
require 'puppet/pops/binder/hiera2/bindings_provider'
|
9
|
+
require 'puppet/pops/binder/hiera2/issues'
|
10
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
module Puppet::Pops::Binder::Hiera2
|
2
|
+
Model = Puppet::Pops::Model
|
3
|
+
|
4
|
+
# A BindingsProvider instance is used for creating a bindings model from a module directory
|
5
|
+
# @api public
|
6
|
+
#
|
7
|
+
class BindingsProvider
|
8
|
+
# The resulting name of loaded bindings (given when initializing)
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
# Creates a new BindingsProvider by reading the hiera_conf.yaml configuration file. Problems
|
12
|
+
# with the configuration are reported propagated to the acceptor
|
13
|
+
#
|
14
|
+
# @param name [String] the name to assign to the result (and in error messages if there is no result)
|
15
|
+
# @param hiera_config_dir [String] Path to the directory containing a hiera_config
|
16
|
+
# @param acceptor [Puppet::Pops::Validation::Acceptor] Acceptor that will receive diagnostics
|
17
|
+
def initialize(name, hiera_config_dir, acceptor)
|
18
|
+
@name = name
|
19
|
+
@parser = Puppet::Pops::Parser::EvaluatingParser.new()
|
20
|
+
@diagnostics = DiagnosticProducer.new(acceptor)
|
21
|
+
@type_calculator = Puppet::Pops::Types::TypeCalculator.new()
|
22
|
+
@config = Config.new(hiera_config_dir, @diagnostics)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Loads a bindings model using the hierarchy and backends configured for this instance.
|
26
|
+
#
|
27
|
+
# @param scope [Puppet::Parser::Scope] The hash used when expanding
|
28
|
+
# @return [Puppet::Pops::Binder::Bindings::ContributedBindings] A bindings model with effective categories
|
29
|
+
def load_bindings(scope)
|
30
|
+
backends = BackendHelper.new(scope)
|
31
|
+
factory = Puppet::Pops::Binder::BindingsFactory
|
32
|
+
result = factory.named_bindings(name)
|
33
|
+
|
34
|
+
hierarchy = {}
|
35
|
+
precedence = []
|
36
|
+
|
37
|
+
@config.hierarchy.each do |key, value, path|
|
38
|
+
source_file = File.join(@config.module_dir, 'hiera.config.yaml')
|
39
|
+
category_value = @parser.evaluate_string(scope, @parser.quote(value), source_file)
|
40
|
+
|
41
|
+
hierarchy[key] = {
|
42
|
+
:bindings => result.when_in_category(key, category_value),
|
43
|
+
:path => @parser.evaluate_string(scope, @parser.quote(path)),
|
44
|
+
:unique_keys =>Set.new()}
|
45
|
+
|
46
|
+
precedence << [key, category_value]
|
47
|
+
end
|
48
|
+
|
49
|
+
@config.backends.each do |backend_key|
|
50
|
+
backend = backends[backend_key]
|
51
|
+
|
52
|
+
hierarchy.each_pair do |hier_key, hier_val|
|
53
|
+
bindings = hier_val[:bindings]
|
54
|
+
unique_keys = hier_val[:unique_keys]
|
55
|
+
|
56
|
+
hiera_data_file_path = hier_val[:path]
|
57
|
+
backend.read_data(@config.module_dir, hiera_data_file_path).each_pair do |key, value|
|
58
|
+
if unique_keys.add?(key)
|
59
|
+
b = bindings.bind().name(key)
|
60
|
+
# Transform value into a Model::Expression
|
61
|
+
expr = build_expr(value, hiera_data_file_path)
|
62
|
+
if is_constant?(expr)
|
63
|
+
# The value is constant so toss the expression
|
64
|
+
b.type(@type_calculator.infer(value)).to(value)
|
65
|
+
else
|
66
|
+
# Use an evaluating producer for the binding
|
67
|
+
b.to(expr)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
factory.contributed_bindings(name, result.model, factory.categories(precedence))
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# @return true unless the expression is a Model::ConcatenatedString or
|
80
|
+
# somehow contains one
|
81
|
+
def is_constant?(expr)
|
82
|
+
if expr.is_a?(Model::ConcatenatedString)
|
83
|
+
false
|
84
|
+
else
|
85
|
+
!expr.eAllContents.any? { |v| v.is_a?(Model::ConcatenatedString) }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Transform the value into a Model::Expression. Strings are parsed using
|
90
|
+
# the Pops::Parser::Parser to produce either Model::LiteralString or Model::ConcatenatedString
|
91
|
+
#
|
92
|
+
# @param value [Object] May be an String, Number, TrueClass, FalseClass, or NilClass nested to any depth using Hash or Array.
|
93
|
+
# @param hiera_data_file_path [String] The source_file used when reporting errors
|
94
|
+
# @return [Model::Expression] The expression that corresponds to the value
|
95
|
+
def build_expr(value, hiera_data_file_path)
|
96
|
+
case value
|
97
|
+
when Symbol
|
98
|
+
value.to_s
|
99
|
+
when String
|
100
|
+
@parser.parse_string(@parser.quote(value)).current
|
101
|
+
when Hash
|
102
|
+
value.inject(Model::LiteralHash.new) do |h,(k,v)|
|
103
|
+
e = Model::KeyedEntry.new
|
104
|
+
e.key = build_expr(k, hiera_data_file_path)
|
105
|
+
e.value = build_expr(v, hiera_data_file_path)
|
106
|
+
h.addEntries(e)
|
107
|
+
h
|
108
|
+
end
|
109
|
+
when Enumerable
|
110
|
+
value.inject(Model::LiteralList.new) {|a,v| a.addValues(build_expr(v, hiera_data_file_path)); a }
|
111
|
+
when Numeric
|
112
|
+
expr = Model::LiteralNumber.new
|
113
|
+
expr.value = value;
|
114
|
+
expr
|
115
|
+
when TrueClass, FalseClass
|
116
|
+
expr = Model::LiteralBoolean.new
|
117
|
+
expr.value = value;
|
118
|
+
expr
|
119
|
+
when NilClass
|
120
|
+
Model::Nop.new
|
121
|
+
else
|
122
|
+
@diagnostics.accept(Issues::UNABLE_TO_PARSE_INSTANCE, value.class.name)
|
123
|
+
nil
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# @api private
|
129
|
+
class BackendHelper
|
130
|
+
T = Puppet::Pops::Types::TypeFactory
|
131
|
+
HASH_OF_BACKENDS = T.hash_of(T.type_of('Puppetx::Puppet::Hiera2Backend'))
|
132
|
+
def initialize(scope)
|
133
|
+
@scope = scope
|
134
|
+
@cache = nil
|
135
|
+
end
|
136
|
+
|
137
|
+
def [] (backend_key)
|
138
|
+
load_backends unless @cache
|
139
|
+
@cache[backend_key]
|
140
|
+
end
|
141
|
+
|
142
|
+
def load_backends
|
143
|
+
@cache = @scope.compiler.boot_injector.lookup(@scope, HASH_OF_BACKENDS, Puppetx::HIERA2_BACKENDS) || {}
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Puppet::Pops::Binder::Hiera2
|
2
|
+
|
3
|
+
# Class holding the Hiera2 Configuration
|
4
|
+
# The configuration is obtained from the file 'hiera.yaml'
|
5
|
+
# that must reside in the root directory of the module
|
6
|
+
# @api public
|
7
|
+
#
|
8
|
+
class Puppet::Pops::Binder::Hiera2::Config
|
9
|
+
DEFAULT_HIERARCHY = [ ['osfamily', '${osfamily}', 'data/osfamily/${osfamily}'], ['common', 'true', 'data/common']]
|
10
|
+
DEFAULT_BACKENDS = ['yaml', 'json']
|
11
|
+
|
12
|
+
if defined?(::Psych::SyntaxError)
|
13
|
+
YamlLoadExceptions = [::StandardError, ::ArgumentError, ::Psych::SyntaxError]
|
14
|
+
else
|
15
|
+
YamlLoadExceptions = [::StandardError, ::ArgumentError]
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns a list of configured backends.
|
19
|
+
#
|
20
|
+
# @return [Array<String>] backend names
|
21
|
+
attr_reader :backends
|
22
|
+
|
23
|
+
# Root directory of the module holding the configuration
|
24
|
+
#
|
25
|
+
# @return [String] An absolute path
|
26
|
+
attr_reader :module_dir
|
27
|
+
|
28
|
+
# The bindings hierarchy is an array of categorizations where the
|
29
|
+
# array for each category has exactly three elements - the categorization name,
|
30
|
+
# category value, and the path that is later used by the backend to read
|
31
|
+
# the bindings for that category
|
32
|
+
#
|
33
|
+
# @return [Array<Array(String, String, String)>]
|
34
|
+
# @api public
|
35
|
+
attr_reader :hierarchy
|
36
|
+
|
37
|
+
# Creates a new Config. The configuration is loaded from the file 'hiera.yaml' which
|
38
|
+
# is expected to be found in the given module_dir.
|
39
|
+
#
|
40
|
+
# @param module_dir [String] The module directory
|
41
|
+
# @param diagnostics [DiagnosticProducer] collector of diagnostics
|
42
|
+
# @api public
|
43
|
+
#
|
44
|
+
def initialize(module_dir, diagnostics)
|
45
|
+
@module_dir = module_dir
|
46
|
+
config_file = File.join(module_dir, 'hiera.yaml')
|
47
|
+
validator = ConfigChecker.new(diagnostics)
|
48
|
+
begin
|
49
|
+
data = YAML.load_file(config_file)
|
50
|
+
validator.validate(data, config_file)
|
51
|
+
unless diagnostics.errors?
|
52
|
+
# if these are missing the result is nil, and they get default values later
|
53
|
+
@hierarchy = data['hierarchy']
|
54
|
+
@backends = data['backends']
|
55
|
+
end
|
56
|
+
rescue Errno::ENOENT
|
57
|
+
diagnostics.accept(Issues::CONFIG_FILE_NOT_FOUND, config_file)
|
58
|
+
rescue Errno::ENOTDIR
|
59
|
+
diagnostics.accept(Issues::CONFIG_FILE_NOT_FOUND, config_file)
|
60
|
+
rescue ::SyntaxError => e
|
61
|
+
diagnostics.accept(Issues::CONFIG_FILE_SYNTAX_ERROR, e)
|
62
|
+
rescue *YamlLoadExceptions => e
|
63
|
+
diagnostics.accept(Issues::CONFIG_FILE_SYNTAX_ERROR, e)
|
64
|
+
end
|
65
|
+
@hierarchy ||= DEFAULT_HIERARCHY
|
66
|
+
@backends ||= DEFAULT_BACKENDS
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Puppet::Pops::Binder::Hiera2
|
2
|
+
|
3
|
+
# Validates the consistency of a Hiera2::Config
|
4
|
+
class ConfigChecker
|
5
|
+
|
6
|
+
# Create an instance with a diagnostic producer that will receive the result during validation
|
7
|
+
# @param diangostics [DiagnosticProducer] The producer that will receive the diagnostic
|
8
|
+
def initialize(diagnostics)
|
9
|
+
@diagnostics = diagnostics
|
10
|
+
end
|
11
|
+
|
12
|
+
# Validate the consistency of the given data. Diagnostics will be emitted to the DiagnosticProducer
|
13
|
+
# that was set when this checker was created
|
14
|
+
#
|
15
|
+
# @param data [Object] The data read from the config file
|
16
|
+
# @param config_file [String] The full path of the file. Used in error messages
|
17
|
+
def validate(data, config_file)
|
18
|
+
if data.is_a?(Hash)
|
19
|
+
# If the version is missing, it is not meaningful to continue
|
20
|
+
return unless check_version(data['version'], config_file)
|
21
|
+
check_hierarchy(data['hierarchy'], config_file)
|
22
|
+
check_backends(data['backends'], config_file)
|
23
|
+
else
|
24
|
+
@diagnostics.accept(Issues::CONFIG_IS_NOT_HASH, config_file)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Version is required and must be >= 2. A warning is issued if version > 2 as this checker is
|
31
|
+
# for version 2 only.
|
32
|
+
# @return [Boolean] false if it is meaningless to continue checking
|
33
|
+
def check_version(version, config_file)
|
34
|
+
if version.nil?
|
35
|
+
# This is not hiera2 compatible
|
36
|
+
@diagnostics.accept(Issues::MISSING_VERSION, config_file)
|
37
|
+
return false
|
38
|
+
end
|
39
|
+
unless version >= 2
|
40
|
+
@diagnostics.accept(Issues::WRONG_VERSION, config_file, :expected => 2, :actual => version)
|
41
|
+
return false
|
42
|
+
end
|
43
|
+
unless version == 2
|
44
|
+
# it may have a sane subset, hence a different error (configured as warning)
|
45
|
+
@diagnostics.accept(Issues::LATER_VERSION, config_file, :expected => 2, :actual => version)
|
46
|
+
end
|
47
|
+
return true
|
48
|
+
end
|
49
|
+
|
50
|
+
def check_hierarchy(hierarchy, config_file)
|
51
|
+
if !hierarchy.is_a?(Array) || hierarchy.empty?
|
52
|
+
@diagnostics.accept(Issues::MISSING_HIERARCHY, config_file)
|
53
|
+
else
|
54
|
+
hierarchy.each do |value|
|
55
|
+
unless value.is_a?(Array) && value.length() == 3
|
56
|
+
@diagnostics.accept(Issues::CATEGORY_MUST_BE_THREE_ELEMENT_ARRAY, config_file)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def check_backends(backends, config_file)
|
63
|
+
if !backends.is_a?(Array) || backends.empty?
|
64
|
+
@diagnostics.accept(Issues::MISSING_BACKENDS, config_file)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Puppet::Pops::Binder::Hiera2
|
2
|
+
# Generates validation diagnostics
|
3
|
+
class Puppet::Pops::Binder::Hiera2::DiagnosticProducer
|
4
|
+
attr_reader :acceptor
|
5
|
+
def initialize(an_acceptor)
|
6
|
+
raise ArgumentError, "Not an acceptor" unless an_acceptor.is_a?(Puppet::Pops::Validation::Acceptor)
|
7
|
+
@acceptor = an_acceptor
|
8
|
+
@severity_producer = Puppet::Pops::Validation::SeverityProducer.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def accept(issue, semantic, arguments={})
|
12
|
+
arguments[:semantic] ||= semantic
|
13
|
+
severity = severity_producer.severity(issue)
|
14
|
+
acceptor.accept(Puppet::Pops::Validation::Diagnostic.new(severity, issue, nil, nil, arguments))
|
15
|
+
end
|
16
|
+
|
17
|
+
def errors?()
|
18
|
+
acceptor.errors?
|
19
|
+
end
|
20
|
+
|
21
|
+
def severity_producer
|
22
|
+
p = @severity_producer
|
23
|
+
p[Issues::UNRESOLVED_STRING_VARIABLE] = :warning
|
24
|
+
|
25
|
+
# Warning since if it does not blow up on anything else, a sane subset of later version was used
|
26
|
+
p[Issues::LATER_VERSION] = :warning
|
27
|
+
|
28
|
+
# Ignore MISSING_BACKENDS because a default will be provided
|
29
|
+
p[Issues::MISSING_BACKENDS] = :ignore
|
30
|
+
|
31
|
+
# Ignore MISSING_HIERARCHY because a default will be provided
|
32
|
+
p[Issues::MISSING_HIERARCHY] = :ignore
|
33
|
+
p
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Puppet::Pops::Binder::Hiera2::Issues
|
2
|
+
# (see Puppet::Pops::Issues#issue)
|
3
|
+
def self.issue (issue_code, *args, &block)
|
4
|
+
Puppet::Pops::Issues.issue(issue_code, *args, &block)
|
5
|
+
end
|
6
|
+
|
7
|
+
CONFIG_IS_NOT_HASH = issue :CONFIG_IS_NOT_HASH do
|
8
|
+
"The configuration file '#{semantic}' has no hash at the top level"
|
9
|
+
end
|
10
|
+
|
11
|
+
MISSING_HIERARCHY = issue :MISSING_HIERARCHY do
|
12
|
+
"The configuration file '#{semantic}' contains no hierarchy"
|
13
|
+
end
|
14
|
+
|
15
|
+
MISSING_BACKENDS = issue :MISSING_BACKENDS do
|
16
|
+
"The configuration file '#{semantic}' contains no backends"
|
17
|
+
end
|
18
|
+
|
19
|
+
CATEGORY_MUST_BE_THREE_ELEMENT_ARRAY = issue :CATEGORY_MUST_BE_THREE_ELEMENT_ARRAY do
|
20
|
+
"The configuration file '#{semantic}' has a malformed hierarchy (should consist of arrays with three string entries)"
|
21
|
+
end
|
22
|
+
|
23
|
+
CONFIG_FILE_NOT_FOUND = issue :CONFIG_FILE_NOT_FOUND do
|
24
|
+
"The configuration file '#{semantic}' does not exist"
|
25
|
+
end
|
26
|
+
|
27
|
+
CONFIG_FILE_SYNTAX_ERROR = issue :CONFIG_FILE_SYNTAX_ERROR do
|
28
|
+
"Unable to parse: #{semantic}"
|
29
|
+
end
|
30
|
+
|
31
|
+
CANNOT_LOAD_BACKEND = issue :CANNOT_LOAD_BACKEND, :key, :error do
|
32
|
+
"Backend '#{key}' in configuration file '#{semantic}' cannot be loaded: #{error}"
|
33
|
+
end
|
34
|
+
|
35
|
+
BACKEND_FILE_DOES_NOT_DEFINE_CLASS = issue :BACKEND_FILE_DOES_NOT_DEFINE_CLASS, :class_name do
|
36
|
+
"The file '#{semantic}' does not define class #{class_name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
NOT_A_BACKEND_CLASS = issue :NOT_A_BACKEND_CLASS, :key, :class_name do
|
40
|
+
"Class #{class_name}, loaded using key #{key} in file '#{semantic}' is not a subclass of Backend"
|
41
|
+
end
|
42
|
+
|
43
|
+
METADATA_JSON_NOT_FOUND = issue :METADATA_JSON_NOT_FOUND do
|
44
|
+
"The metadata file '#{semantic}' does not exist"
|
45
|
+
end
|
46
|
+
|
47
|
+
UNSUPPORTED_STRING_EXPRESSION = issue :UNSUPPORTED_STRING_EXPRESSION, :expr do
|
48
|
+
"String '#{semantic}' contains an unsupported expression (type was #{expr.class.name})"
|
49
|
+
end
|
50
|
+
|
51
|
+
UNRESOLVED_STRING_VARIABLE = issue :UNRESOLVED_STRING_VARIABLE, :key do
|
52
|
+
"Variable '#{key}' found in string '#{semantic}' cannot be resolved"
|
53
|
+
end
|
54
|
+
|
55
|
+
MISSING_VERSION = issue :MISSING_VERSION do
|
56
|
+
"The configuration file '#{semantic}' does not have a version."
|
57
|
+
end
|
58
|
+
|
59
|
+
WRONG_VERSION = issue :WRONG_VERSION do
|
60
|
+
"The configuration file '#{semantic}' has the wrong version, expected: #{expected}, actual: #{actual}"
|
61
|
+
end
|
62
|
+
|
63
|
+
LATER_VERSION = issue :LATER_VERSION do
|
64
|
+
"The configuration file '#{semantic}' has a version that is newer (features may not work), expected: #{expected}, actual: #{actual}"
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
# A Backend implementation capable of reading JSON syntax
|
4
|
+
class Puppet::Pops::Binder::Hiera2::JsonBackend < Puppetx::Puppet::Hiera2Backend
|
5
|
+
def read_data(module_dir, source)
|
6
|
+
begin
|
7
|
+
source_file = File.join(module_dir, "#{source}.json")
|
8
|
+
JSON.parse(File.read(source_file))
|
9
|
+
rescue Errno::ENOTDIR
|
10
|
+
# This is OK, the file doesn't need to be present. Return an empty hash
|
11
|
+
{}
|
12
|
+
rescue Errno::ENOENT
|
13
|
+
# This is OK, the file doesn't need to be present. Return an empty hash
|
14
|
+
{}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# A Backend implementation capable of reading YAML syntax
|
2
|
+
class Puppet::Pops::Binder::Hiera2::YamlBackend < Puppetx::Puppet::Hiera2Backend
|
3
|
+
def read_data(module_dir, source)
|
4
|
+
begin
|
5
|
+
source_file = File.join(module_dir, "#{source}.yaml")
|
6
|
+
# if file is present but empty or has only "---", YAML.load_file returns false,
|
7
|
+
# in which case fall back to returning an empty hash
|
8
|
+
YAML.load_file(source_file) || {}
|
9
|
+
rescue TypeError => e
|
10
|
+
# SafeYaml chokes when trying to load using utf-8 and the file is empty
|
11
|
+
raise e if File.size?(source_file)
|
12
|
+
{}
|
13
|
+
rescue Errno::ENOTDIR
|
14
|
+
# This is OK, the file doesn't need to be present. Return an empty hash
|
15
|
+
{}
|
16
|
+
rescue Errno::ENOENT
|
17
|
+
# This is OK, the file doesn't need to be present. Return an empty hash
|
18
|
+
{}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,688 @@
|
|
1
|
+
# The injector is the "lookup service" class
|
2
|
+
#
|
3
|
+
# Initialization
|
4
|
+
# --------------
|
5
|
+
# The injector is initialized with a configured {Puppet::Pops::Binder::Binder Binder}. The Binder instance contains a resolved set of
|
6
|
+
# `key => "binding information"` that is used to setup the injector.
|
7
|
+
#
|
8
|
+
# Lookup
|
9
|
+
# ------
|
10
|
+
# It is possible to lookup either the value, or a producer of the value. The {#lookup} method looks up a value, and the
|
11
|
+
# {#lookup_producer} looks up a producer.
|
12
|
+
# Both of these methods can be called with three different signatures; `lookup(key)`, `lookup(type, name)`, and `lookup(name)`,
|
13
|
+
# with the corresponding calls to obtain a producer; `lookup_producer(key)`, `lookup_producer(type, name)`, and `lookup_producer(name)`.
|
14
|
+
#
|
15
|
+
# It is possible to pass a block to {#lookup} and {#lookup_producer}, the block is passed the result of the lookup
|
16
|
+
# and the result of the block is returned as the value of the lookup. This is useful in order to provide a default value.
|
17
|
+
#
|
18
|
+
# @example Lookup with default value
|
19
|
+
# injector.lookup('favourite_food') {|x| x.nil? ? 'bacon' : x }
|
20
|
+
#
|
21
|
+
# Singleton or Not
|
22
|
+
# ----------------
|
23
|
+
# The lookup of a value is always based on the lookup of a producer. For *singleton producers* this means that the value is
|
24
|
+
# determined by the first value lookup. Subsequent lookups via `lookup` or `lookup_producer` will produce the same instance.
|
25
|
+
#
|
26
|
+
# *Non singleton producers* will produce a new instance on each request for a value. For constant value producers this
|
27
|
+
# means that a new deep-clone is produced for mutable objects (but not for immutable objects as this is not needed).
|
28
|
+
# Custom producers should have non singleton behavior, or if this is not possible ensure that the produced result is
|
29
|
+
# immutable. (The behavior if a custom producer hands out a mutable value and this is mutated is undefined).
|
30
|
+
#
|
31
|
+
# Custom bound producers capable of producing a series of objects when bound as a singleton means that the producer
|
32
|
+
# is a singleton, not the value it produces. If such a producer is bound as non singleton, each `lookup` will get a new
|
33
|
+
# producer (hence, typically, restarting the series). However, the producer returned from `lookup_producer` will not
|
34
|
+
# recreate the producer on each call to `produce`; i.e. each `lookup_producer` returns a producer capable of returning
|
35
|
+
# a series of objects.
|
36
|
+
#
|
37
|
+
# @see Puppet::Pops::Binder::Binder Binder, for details about how to bind keys to producers
|
38
|
+
# @see Puppet::Pops::Binder::BindingsFactory BindingsFactory, for a convenient way to create a Binder and bindings
|
39
|
+
#
|
40
|
+
# Assisted Inject
|
41
|
+
# ---------------
|
42
|
+
# The injector supports lookup of instances of classes *even if the requested class is not explicitly bound*.
|
43
|
+
# This is possible for classes that have a zero argument `initialize` method, or that has a class method called
|
44
|
+
# `inject` that takes two arguments; `injector`, and `scope`.
|
45
|
+
# This is useful in ruby logic as a class can then use the given injector to inject details.
|
46
|
+
# An `inject` class method wins over a zero argument `initialize` in all cases.
|
47
|
+
#
|
48
|
+
# @example Using assisted inject
|
49
|
+
# # Class with assisted inject support
|
50
|
+
# class Duck
|
51
|
+
# attr_reader :name, :year_of_birth
|
52
|
+
#
|
53
|
+
# def self.inject(injector, scope, binding, *args)
|
54
|
+
# # lookup default name and year of birth, and use defaults if not present
|
55
|
+
# name = injector.lookup(scope,'default-duck-name') {|x| x ? x : 'Donald Duck' }
|
56
|
+
# year_of_birth = injector.lookup(scope,'default-duck-year_of_birth') {|x| x ? x : 1934 }
|
57
|
+
# self.new(name, year_of_birth)
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# def initialize(name, year_of_birth)
|
61
|
+
# @name = name
|
62
|
+
# @year_of_birth = year_of_birth
|
63
|
+
# end
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# injector.lookup(scope, Duck)
|
67
|
+
# # Produces a Duck named 'Donald Duck' or named after the binding 'default-duck-name' (and with similar treatment of
|
68
|
+
# # year_of_birth).
|
69
|
+
# @see Puppet::Pops::Binder::Producers::AssistedInjectProducer AssistedInjectProducer, for more details on assisted injection
|
70
|
+
#
|
71
|
+
# Access to key factory and type calculator
|
72
|
+
# -----------------------------------------
|
73
|
+
# It is important to use the same key factory, and type calculator as the binder. It is therefor possible to obtaint
|
74
|
+
# these with the methods {#key_factory}, and {#type_calculator}.
|
75
|
+
#
|
76
|
+
# Special support for producers
|
77
|
+
# -----------------------------
|
78
|
+
# There is one method specially designed for producers. The {#get_contributions} method returns an array of all contributions
|
79
|
+
# to a given *contributions key*. This key is obtained from the {#key_factory} for a given multibinding. The returned set of
|
80
|
+
# contributed bindings is sorted in descending precedence order. Any conflicts, merges, etc. is performed by the multibinding
|
81
|
+
# producer configured for a multibinding.
|
82
|
+
#
|
83
|
+
# @api public
|
84
|
+
#
|
85
|
+
class Puppet::Pops::Binder::Injector
|
86
|
+
|
87
|
+
Producers = Puppet::Pops::Binder::Producers
|
88
|
+
|
89
|
+
# An Injector is initialized with a configured {Puppet::Pops::Binder::Binder Binder}.
|
90
|
+
#
|
91
|
+
# @param configured_binder [Puppet::Pops::Binder::Binder,nil] The configured binder containing effective bindings. A given value
|
92
|
+
# of nil creates an injector that returns or yields nil on all lookup requests.
|
93
|
+
# @raise ArgumentError if the given binder is not fully configured
|
94
|
+
#
|
95
|
+
# @api public
|
96
|
+
#
|
97
|
+
def initialize(configured_binder)
|
98
|
+
if configured_binder.nil?
|
99
|
+
@impl = Private::NullInjectorImpl.new()
|
100
|
+
else
|
101
|
+
@impl = Private::InjectorImpl.new(configured_binder)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# The KeyFactory used to produce keys in this injector.
|
106
|
+
# The factory is shared with the Binder to ensure consistent translation to keys.
|
107
|
+
# A compatible type calculator can also be obtained from the key factory.
|
108
|
+
# @return [Puppet::Pops::Binder::KeyFactory] the key factory in use
|
109
|
+
#
|
110
|
+
# @api public
|
111
|
+
#
|
112
|
+
def key_factory()
|
113
|
+
@impl.key_factory
|
114
|
+
end
|
115
|
+
|
116
|
+
# Returns the TypeCalculator in use for keys. The same calculator (as used for keys) should be used if there is a need
|
117
|
+
# to check type conformance, or infer the type of Ruby objects.
|
118
|
+
#
|
119
|
+
# @return [Puppet::Pops::Types::TypeCalculator] the type calculator that is in use for keys
|
120
|
+
# @api public
|
121
|
+
#
|
122
|
+
def type_calculator()
|
123
|
+
@impl.type_calculator()
|
124
|
+
end
|
125
|
+
|
126
|
+
# Lookup (a.k.a "inject") of a value given a key.
|
127
|
+
# The lookup may be called with different parameters. This method is a convenience method that
|
128
|
+
# dispatches to one of #lookup_key or #lookup_type depending on the arguments. It also provides
|
129
|
+
# the ability to use an optional block that is called with the looked up value, or scope and value if the
|
130
|
+
# block takes two parameters. This is useful to provide a default value or other transformations, calculations
|
131
|
+
# based on the result of the lookup.
|
132
|
+
#
|
133
|
+
# @overload lookup(scope, key)
|
134
|
+
# (see #lookup_key)
|
135
|
+
# @param scope [Puppet::Parser::Scope] the scope to use for evaluation
|
136
|
+
# @param key [Object] an opaque object being the full key
|
137
|
+
#
|
138
|
+
# @overload lookup(scope, type, name = '')
|
139
|
+
# (see #lookup_type)
|
140
|
+
# @param scope [Puppet::Parser::Scope] the scope to use for evaluation
|
141
|
+
# @param type [Puppet::Pops::Types::PObjectType] the type of what to lookup
|
142
|
+
# @param name [String] the name to use, defaults to empty string (for unnamed)
|
143
|
+
#
|
144
|
+
# @overload lookup(scope, name)
|
145
|
+
# Lookup of Data type with given name.
|
146
|
+
# @see #lookup_type
|
147
|
+
# @param scope [Puppet::Parser::Scope] the scope to use for evaluation
|
148
|
+
# @param name [String] the Data/name to lookup
|
149
|
+
#
|
150
|
+
# @yield [value] passes the looked up value to an optional block and returns what this block returns
|
151
|
+
# @yield [scope, value] passes scope and value to the block and returns what this block returns
|
152
|
+
# @yieldparam scope [Puppet::Parser::Scope] the scope given to lookup
|
153
|
+
# @yieldparam value [Object, nil] the looked up value or nil if nothing was found
|
154
|
+
#
|
155
|
+
# @raise [ArgumentError] if the block has an arity that is not 1 or 2
|
156
|
+
#
|
157
|
+
# @api public
|
158
|
+
#
|
159
|
+
def lookup(scope, *args, &block)
|
160
|
+
@impl.lookup(scope, *args, &block)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Looks up a (typesafe) value based on a type/name combination.
|
164
|
+
# Creates a key for the type/name combination using a KeyFactory. Specialization of the Data type are transformed
|
165
|
+
# to a Data key, and the result is type checked to conform with the given key.
|
166
|
+
#
|
167
|
+
# @param type [Puppet::Pops::Types::PObjectType] the type to lookup as defined by Puppet::Pops::Types::TypeFactory
|
168
|
+
# @param name [String] the (optional for non `Data` types) name of the entry to lookup.
|
169
|
+
# The name may be an empty String (the default), but not nil. The name is required for lookup for subtypes of
|
170
|
+
# `Data`.
|
171
|
+
# @return [Object, nil] the looked up bound object, or nil if not found (type conformance with given type is guaranteed)
|
172
|
+
# @raise [ArgumentError] if the produced value does not conform with the given type
|
173
|
+
#
|
174
|
+
# @api public
|
175
|
+
#
|
176
|
+
def lookup_type(scope, type, name='')
|
177
|
+
@impl.lookup_type(scope, type, name)
|
178
|
+
end
|
179
|
+
|
180
|
+
# Looks up the key and returns the entry, or nil if no entry is found.
|
181
|
+
# Produced type is checked for type conformance with its binding, but not with the lookup key.
|
182
|
+
# (This since all subtypes of PDataType are looked up using a key based on PDataType).
|
183
|
+
# Use the Puppet::Pops::Types::TypeCalculator#instance? method to check for conformance of the result
|
184
|
+
# if this is wanted, or use #lookup_type.
|
185
|
+
#
|
186
|
+
# @param key [Object] lookup of key as produced by the key factory
|
187
|
+
# @return [Object, nil] produced value of type that conforms with bound type (type conformance with key not guaranteed).
|
188
|
+
# @raise [ArgumentError] if the produced value does not conform with the bound type
|
189
|
+
#
|
190
|
+
# @api public
|
191
|
+
#
|
192
|
+
def lookup_key(scope, key)
|
193
|
+
@impl.lookup_key(scope, key)
|
194
|
+
end
|
195
|
+
|
196
|
+
# Lookup (a.k.a "inject") producer of a value given a key.
|
197
|
+
# The producer lookup may be called with different parameters. This method is a convenience method that
|
198
|
+
# dispatches to one of #lookup_producer_key or #lookup_producer_type depending on the arguments. It also provides
|
199
|
+
# the ability to use an optional block that is called with the looked up producer, or scope and producer if the
|
200
|
+
# block takes two parameters. This is useful to provide a default value, call a custom producer method,
|
201
|
+
# or other transformations, calculations based on the result of the lookup.
|
202
|
+
#
|
203
|
+
# @overload lookup_producer(scope, key)
|
204
|
+
# (see #lookup_proudcer_key)
|
205
|
+
# @param scope [Puppet::Parser::Scope] the scope to use for evaluation
|
206
|
+
# @param key [Object] an opaque object being the full key
|
207
|
+
#
|
208
|
+
# @overload lookup_producer(scope, type, name = '')
|
209
|
+
# (see #lookup_type)
|
210
|
+
# @param scope [Puppet::Parser::Scope] the scope to use for evaluation
|
211
|
+
# @param type [Puppet::Pops::Types::PObjectType], the type of what to lookup
|
212
|
+
# @param name [String], the name to use, defaults to empty string (for unnamed)
|
213
|
+
#
|
214
|
+
# @overload lookup_producer(scope, name)
|
215
|
+
# Lookup of Data type with given name.
|
216
|
+
# @see #lookup_type
|
217
|
+
# @param scope [Puppet::Parser::Scope] the scope to use for evaluation
|
218
|
+
# @param name [String], the Data/name to lookup
|
219
|
+
#
|
220
|
+
# @return [Puppet::Pops::Binder::Producers::Producer, Object, nil] a producer, or what the optional block returns
|
221
|
+
#
|
222
|
+
# @yield [producer] passes the looked up producer to an optional block and returns what this block returns
|
223
|
+
# @yield [scope, producer] passes scope and producer to the block and returns what this block returns
|
224
|
+
# @yieldparam producer [Puppet::Pops::Binder::Producers::Producer, nil] the looked up producer or nil if nothing was bound
|
225
|
+
# @yieldparam scope [Puppet::Parser::Scope] the scope given to lookup
|
226
|
+
#
|
227
|
+
# @raise [ArgumentError] if the block has an arity that is not 1 or 2
|
228
|
+
#
|
229
|
+
# @api public
|
230
|
+
#
|
231
|
+
def lookup_producer(scope, *args, &block)
|
232
|
+
@impl.lookup_producer(scope, *args, &block)
|
233
|
+
end
|
234
|
+
|
235
|
+
# Looks up a Producer given an opaque binder key.
|
236
|
+
# @return [Puppet::Pops::Binder::Producers::Producer, nil] the bound producer, or nil if no such producer was found.
|
237
|
+
#
|
238
|
+
# @api public
|
239
|
+
#
|
240
|
+
def lookup_producer_key(scope, key)
|
241
|
+
@impl.lookup_producer_key(scope, key)
|
242
|
+
end
|
243
|
+
|
244
|
+
# Looks up a Producer given a type/name key.
|
245
|
+
# @note The result is not type checked (it cannot be until the producer has produced an instance).
|
246
|
+
# @return [Puppet::Pops::Binder::Producers::Producer, nil] the bound producer, or nil if no such producer was found
|
247
|
+
#
|
248
|
+
# @api public
|
249
|
+
#
|
250
|
+
def lookup_producer_type(scope, type, name='')
|
251
|
+
@impl.lookup_producer_type(scope, type, name)
|
252
|
+
end
|
253
|
+
|
254
|
+
# Returns the contributions to a multibind given its contribution key (as produced by the KeyFactory).
|
255
|
+
# This method is typically used by multibind value producers, but may be used for introspection of the injector's state.
|
256
|
+
#
|
257
|
+
# @param scope [Puppet::Parser::Scope] the scope to use
|
258
|
+
# @param contributions_key [Object] Opaque key as produced by KeyFactory as the contributions key for a multibinding
|
259
|
+
# @return [Array<Puppet::Pops::Binder::InjectorEntry>] the contributions sorted in deecending order of precedence
|
260
|
+
#
|
261
|
+
# @api public
|
262
|
+
#
|
263
|
+
def get_contributions(scope, contributions_key)
|
264
|
+
@impl.get_contributions(scope, contributions_key)
|
265
|
+
end
|
266
|
+
|
267
|
+
# Returns an Injector that returns (or yields) nil on all lookups, and produces an empty structure for contributions
|
268
|
+
# This method is intended for testing purposes.
|
269
|
+
#
|
270
|
+
def self.null_injector
|
271
|
+
self.new(nil)
|
272
|
+
end
|
273
|
+
|
274
|
+
# The implementation of the Injector is private.
|
275
|
+
# @see Puppet::Pops::Binder::Injector The public API this module implements.
|
276
|
+
# @api private
|
277
|
+
#
|
278
|
+
module Private
|
279
|
+
|
280
|
+
# This is a mocking "Null" implementation of Injector. It never finds anything
|
281
|
+
# @api private
|
282
|
+
class NullInjectorImpl
|
283
|
+
attr_reader :entries
|
284
|
+
attr_reader :key_factory
|
285
|
+
attr_reader :type_calculator
|
286
|
+
|
287
|
+
def initialize
|
288
|
+
@entries = []
|
289
|
+
@key_factory = Puppet::Pops::Binder::KeyFactory.new()
|
290
|
+
@type_calculator = @key_factory.type_calculator
|
291
|
+
end
|
292
|
+
|
293
|
+
def lookup(scope, *args, &block)
|
294
|
+
raise ArgumentError, "lookup should be called with two or three arguments, got: #{args.size()+1}" unless args.size.between?(1,2)
|
295
|
+
# call block with result if given
|
296
|
+
if block
|
297
|
+
case block.arity
|
298
|
+
when 1
|
299
|
+
block.call(:undef)
|
300
|
+
when 2
|
301
|
+
block.call(scope, :undef)
|
302
|
+
else
|
303
|
+
raise ArgumentError, "The block should have arity 1 or 2"
|
304
|
+
end
|
305
|
+
else
|
306
|
+
val
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|
310
|
+
|
311
|
+
# @api private
|
312
|
+
def lookup_key(scope, key)
|
313
|
+
nil
|
314
|
+
end
|
315
|
+
|
316
|
+
# @api private
|
317
|
+
def lookup_producer(scope, *args, &block)
|
318
|
+
lookup(scope, *args, &block)
|
319
|
+
end
|
320
|
+
|
321
|
+
# @api private
|
322
|
+
def lookup_producer_key(scope, key)
|
323
|
+
nil
|
324
|
+
end
|
325
|
+
|
326
|
+
# @api private
|
327
|
+
def lookup_producer_type(scope, type, name='')
|
328
|
+
nil
|
329
|
+
end
|
330
|
+
|
331
|
+
def get_contributions()
|
332
|
+
[]
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
# @api private
|
337
|
+
#
|
338
|
+
class InjectorImpl
|
339
|
+
# Hash of key => InjectorEntry
|
340
|
+
# @api private
|
341
|
+
#
|
342
|
+
attr_reader :entries
|
343
|
+
|
344
|
+
attr_reader :key_factory
|
345
|
+
|
346
|
+
attr_reader :type_calculator
|
347
|
+
|
348
|
+
def initialize(configured_binder)
|
349
|
+
raise ArgumentError, "Given Binder is not configured" unless configured_binder && configured_binder.configured?()
|
350
|
+
@entries = configured_binder.injector_entries()
|
351
|
+
|
352
|
+
# It is essential that the injector uses the same key factory as the binder since keys must be
|
353
|
+
# represented the same (but still opaque) way.
|
354
|
+
#
|
355
|
+
@key_factory = configured_binder.key_factory()
|
356
|
+
@type_calculator = key_factory.type_calculator()
|
357
|
+
@@transform_visitor ||= Puppet::Pops::Visitor.new(nil,"transform", 2, 2)
|
358
|
+
@recursion_lock = [ ]
|
359
|
+
end
|
360
|
+
|
361
|
+
# @api private
|
362
|
+
def lookup(scope, *args, &block)
|
363
|
+
raise ArgumentError, "lookup should be called with two or three arguments, got: #{args.size()+1}" unless args.size.between?(1,2)
|
364
|
+
|
365
|
+
val = case args[ 0 ]
|
366
|
+
|
367
|
+
when Puppet::Pops::Types::PObjectType
|
368
|
+
lookup_type(scope, *args)
|
369
|
+
|
370
|
+
when String
|
371
|
+
raise ArgumentError, "lookup of name should only pass the name" unless args.size == 1
|
372
|
+
lookup_key(scope, key_factory.data_key(args[ 0 ]))
|
373
|
+
|
374
|
+
else
|
375
|
+
raise ArgumentError, 'lookup using a key should only pass a single key' unless args.size == 1
|
376
|
+
lookup_key(scope, args[ 0 ])
|
377
|
+
end
|
378
|
+
|
379
|
+
# call block with result if given
|
380
|
+
if block
|
381
|
+
case block.arity
|
382
|
+
when 1
|
383
|
+
block.call(val)
|
384
|
+
when 2
|
385
|
+
block.call(scope, val)
|
386
|
+
else
|
387
|
+
raise ArgumentError, "The block should have arity 1 or 2"
|
388
|
+
end
|
389
|
+
else
|
390
|
+
val
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
# Produces a key for a type/name combination.
|
395
|
+
# @api private
|
396
|
+
def named_key(type, name)
|
397
|
+
key_factory.named_key(type, name)
|
398
|
+
end
|
399
|
+
|
400
|
+
# Produces a key for a PDataType/name combination
|
401
|
+
# @api private
|
402
|
+
def data_key(name)
|
403
|
+
key_factory.data_key(name)
|
404
|
+
end
|
405
|
+
|
406
|
+
# @api private
|
407
|
+
def lookup_type(scope, type, name='')
|
408
|
+
val = lookup_key(scope, named_key(type, name))
|
409
|
+
unless key_factory.type_calculator.instance?(type, val)
|
410
|
+
raise ArgumentError, "Type error: incompatible type, #{type_error_detail(type, val)}"
|
411
|
+
end
|
412
|
+
val
|
413
|
+
end
|
414
|
+
|
415
|
+
# @api private
|
416
|
+
def type_error_detail(expected, actual)
|
417
|
+
actual_t = type_calculator.infer(actual)
|
418
|
+
"expected: #{type_calculator.string(expected)}, got: #{type_calculator.string(actual_t)}"
|
419
|
+
end
|
420
|
+
|
421
|
+
# @api private
|
422
|
+
def lookup_key(scope, key)
|
423
|
+
if @recursion_lock.include?(key)
|
424
|
+
raise ArgumentError, "Lookup loop detected for key: #{key}"
|
425
|
+
end
|
426
|
+
begin
|
427
|
+
@recursion_lock.push(key)
|
428
|
+
case entry = get_entry(key)
|
429
|
+
when NilClass
|
430
|
+
nil
|
431
|
+
when Puppet::Pops::Binder::InjectorEntry
|
432
|
+
val = produce(scope, entry)
|
433
|
+
return nil if val.nil?
|
434
|
+
unless key_factory.type_calculator.instance?(entry.binding.type, val)
|
435
|
+
raise "Type error: incompatible type returned by producer, #{type_error_detail(entry.binding.type, val)}"
|
436
|
+
end
|
437
|
+
val
|
438
|
+
when Producers::AssistedInjectProducer
|
439
|
+
entry.produce(scope)
|
440
|
+
else
|
441
|
+
# internal, direct entries
|
442
|
+
entry
|
443
|
+
end
|
444
|
+
ensure
|
445
|
+
@recursion_lock.pop()
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
# Should be used to get entries as it converts missing entries to NotFound entries or AssistedInject entries
|
450
|
+
#
|
451
|
+
# @api private
|
452
|
+
def get_entry(key)
|
453
|
+
case entry = entries[ key ]
|
454
|
+
when NilClass
|
455
|
+
# not found, is this an assisted inject?
|
456
|
+
if clazz = assistable_injected_class(key)
|
457
|
+
entry = Producers::AssistedInjectProducer.new(self, clazz)
|
458
|
+
entries[ key ] = entry
|
459
|
+
else
|
460
|
+
entries[ key ] = NotFound.new()
|
461
|
+
entry = nil
|
462
|
+
end
|
463
|
+
when NotFound
|
464
|
+
entry = nil
|
465
|
+
end
|
466
|
+
entry
|
467
|
+
end
|
468
|
+
|
469
|
+
# Returns contributions to a multibind in precedence order; highest first.
|
470
|
+
# Returns an Array on the form [ [key, entry], [key, entry]] where the key is intended to be used to lookup the value
|
471
|
+
# (or a producer) for that entry.
|
472
|
+
# @api private
|
473
|
+
def get_contributions(scope, contributions_key)
|
474
|
+
result = {}
|
475
|
+
return [] unless contributions = lookup_key(scope, contributions_key)
|
476
|
+
contributions.each { |k| result[k] = get_entry(k) }
|
477
|
+
result.sort {|a, b| a[0] <=> b[0] }
|
478
|
+
#result.sort_by {|key, entry| entry }
|
479
|
+
end
|
480
|
+
|
481
|
+
# Produces an injectable class given a key, or nil if key does not represent an injectable class
|
482
|
+
# @api private
|
483
|
+
#
|
484
|
+
def assistable_injected_class(key)
|
485
|
+
kt = key_factory.get_type(key)
|
486
|
+
return nil unless kt.is_a?(Puppet::Pops::Types::PRubyType) && !key_factory.is_named?(key)
|
487
|
+
type_calculator.injectable_class(kt)
|
488
|
+
end
|
489
|
+
|
490
|
+
def lookup_producer(scope, *args, &block)
|
491
|
+
raise ArgumentError, "lookup_producer should be called with two or three arguments, got: #{args.size()+1}" unless args.size <= 2
|
492
|
+
|
493
|
+
p = case args[ 0 ]
|
494
|
+
when Puppet::Pops::Types::PObjectType
|
495
|
+
lookup_producer_type(scope, *args)
|
496
|
+
|
497
|
+
when String
|
498
|
+
raise ArgumentError, "lookup_producer of name should only pass the name" unless args.size == 1
|
499
|
+
lookup_producer_key(scope, key_factory.data_key(args[ 0 ]))
|
500
|
+
|
501
|
+
else
|
502
|
+
raise ArgumentError, "lookup_producer using a key should only pass a single key" unless args.size == 1
|
503
|
+
lookup_producer_key(scope, args[ 0 ])
|
504
|
+
end
|
505
|
+
|
506
|
+
# call block with result if given
|
507
|
+
if block
|
508
|
+
case block.arity
|
509
|
+
when 1
|
510
|
+
block.call(p)
|
511
|
+
when 2
|
512
|
+
block.call(scope, p)
|
513
|
+
else
|
514
|
+
raise ArgumentError, "The block should have arity 1 or 2"
|
515
|
+
end
|
516
|
+
else
|
517
|
+
p
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
# @api private
|
522
|
+
def lookup_producer_key(scope, key)
|
523
|
+
if @recursion_lock.include?(key)
|
524
|
+
raise ArgumentError, "Lookup loop detected for key: #{key}"
|
525
|
+
end
|
526
|
+
begin
|
527
|
+
@recursion_lock.push(key)
|
528
|
+
producer(scope, get_entry(key), :multiple_use)
|
529
|
+
ensure
|
530
|
+
@recursion_lock.pop()
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
534
|
+
# @api private
|
535
|
+
def lookup_producer_type(scope, type, name='')
|
536
|
+
lookup_producer_key(scope, named_key(type, name))
|
537
|
+
end
|
538
|
+
|
539
|
+
# Returns the producer for the entry
|
540
|
+
# @return [Puppet::Pops::Binder::Producers::Producer] the entry's producer.
|
541
|
+
#
|
542
|
+
# @api private
|
543
|
+
#
|
544
|
+
def producer(scope, entry, use)
|
545
|
+
return nil unless entry # not found
|
546
|
+
return entry.producer(scope) if entry.is_a?(Producers::AssistedInjectProducer)
|
547
|
+
unless entry.cached_producer
|
548
|
+
entry.cached_producer = transform(entry.binding.producer, scope, entry)
|
549
|
+
end
|
550
|
+
unless entry.cached_producer
|
551
|
+
raise ArgumentError, "Injector entry without a producer #{format_binding(entry.binding)}"
|
552
|
+
end
|
553
|
+
entry.cached_producer.producer(scope)
|
554
|
+
end
|
555
|
+
|
556
|
+
# @api private
|
557
|
+
def transform(producer_descriptor, scope, entry)
|
558
|
+
@@transform_visitor.visit_this(self, producer_descriptor, scope, entry)
|
559
|
+
end
|
560
|
+
|
561
|
+
# Returns the produced instance
|
562
|
+
# @return [Object] the produced instance
|
563
|
+
# @api private
|
564
|
+
#
|
565
|
+
def produce(scope, entry)
|
566
|
+
return nil unless entry # not found
|
567
|
+
producer(scope, entry, :single_use).produce(scope)
|
568
|
+
end
|
569
|
+
|
570
|
+
# @api private
|
571
|
+
def named_arguments_to_hash(named_args)
|
572
|
+
nb = named_args.nil? ? [] : named_args
|
573
|
+
result = {}
|
574
|
+
nb.each {|arg| result[ :"#{arg.name}" ] = arg.value }
|
575
|
+
result
|
576
|
+
end
|
577
|
+
|
578
|
+
# @api private
|
579
|
+
def merge_producer_options(binding, options)
|
580
|
+
named_arguments_to_hash(binding.producer_args).merge(options)
|
581
|
+
end
|
582
|
+
|
583
|
+
# @api private
|
584
|
+
def format_binding(b)
|
585
|
+
Puppet::Pops::Binder::Binder.format_binding(b)
|
586
|
+
end
|
587
|
+
|
588
|
+
# Handles a missing producer (which is valid for a Multibinding where one is selected automatically)
|
589
|
+
# @api private
|
590
|
+
#
|
591
|
+
def transform_NilClass(descriptor, scope, entry)
|
592
|
+
unless entry.binding.is_a?(Puppet::Pops::Binder::Bindings::Multibinding)
|
593
|
+
raise ArgumentError, "Binding without producer detected, #{format_binding(entry.binding)}"
|
594
|
+
end
|
595
|
+
case entry.binding.type
|
596
|
+
when Puppet::Pops::Types::PArrayType
|
597
|
+
transform(Puppet::Pops::Binder::Bindings::ArrayMultibindProducerDescriptor.new(), scope, entry)
|
598
|
+
when Puppet::Pops::Types::PHashType
|
599
|
+
transform(Puppet::Pops::Binder::Bindings::HashMultibindProducerDescriptor.new(), scope, entry)
|
600
|
+
else
|
601
|
+
raise ArgumentError, "Unsupported multibind type, must be an array or hash type, #{format_binding(entry.binding)}"
|
602
|
+
end
|
603
|
+
end
|
604
|
+
|
605
|
+
# @api private
|
606
|
+
def transform_ArrayMultibindProducerDescriptor(descriptor, scope, entry)
|
607
|
+
make_producer(Producers::ArrayMultibindProducer, descriptor, scope, entry, named_arguments_to_hash(entry.binding.producer_args))
|
608
|
+
end
|
609
|
+
|
610
|
+
# @api private
|
611
|
+
def transform_HashMultibindProducerDescriptor(descriptor, scope, entry)
|
612
|
+
make_producer(Producers::HashMultibindProducer, descriptor, scope, entry, named_arguments_to_hash(entry.binding.producer_args))
|
613
|
+
end
|
614
|
+
|
615
|
+
# @api private
|
616
|
+
def transform_ConstantProducerDescriptor(descriptor, scope, entry)
|
617
|
+
producer_class = singleton?(descriptor) ? Producers::SingletonProducer : Producers::DeepCloningProducer
|
618
|
+
producer_class.new(self, entry.binding, scope, merge_producer_options(entry.binding, {:value => descriptor.value}))
|
619
|
+
end
|
620
|
+
|
621
|
+
# @api private
|
622
|
+
def transform_InstanceProducerDescriptor(descriptor, scope, entry)
|
623
|
+
make_producer(Producers::InstantiatingProducer, descriptor, scope, entry,
|
624
|
+
merge_producer_options(entry.binding, {:class_name => descriptor.class_name, :init_args => descriptor.arguments}))
|
625
|
+
end
|
626
|
+
|
627
|
+
# @api private
|
628
|
+
def transform_EvaluatingProducerDescriptor(descriptor, scope, entry)
|
629
|
+
make_producer(Producers::EvaluatingProducer, descriptor, scope, entry,
|
630
|
+
merge_producer_options(entry.binding, {:expression => descriptor.expression}))
|
631
|
+
end
|
632
|
+
|
633
|
+
# @api private
|
634
|
+
def make_producer(clazz, descriptor, scope, entry, options)
|
635
|
+
singleton_wrapped(descriptor, scope, entry, clazz.new(self, entry.binding, scope, options))
|
636
|
+
end
|
637
|
+
|
638
|
+
# @api private
|
639
|
+
def singleton_wrapped(descriptor, scope, entry, producer)
|
640
|
+
return producer unless singleton?(descriptor)
|
641
|
+
Producers::SingletonProducer.new(self, entry.binding, scope,
|
642
|
+
merge_producer_options(entry.binding, {:value => producer.produce(scope)}))
|
643
|
+
end
|
644
|
+
|
645
|
+
# @api private
|
646
|
+
def transform_ProducerProducerDescriptor(descriptor, scope, entry)
|
647
|
+
p = transform(descriptor.producer, scope, entry)
|
648
|
+
clazz = singleton?(descriptor) ? Producers::SingletonProducerProducer : Producers::ProducerProducer
|
649
|
+
clazz.new(self, entry.binding, scope, merge_producer_options(entry.binding,
|
650
|
+
merge_producer_options(entry.binding, { :producer_producer => p })))
|
651
|
+
end
|
652
|
+
|
653
|
+
# @api private
|
654
|
+
def transform_LookupProducerDescriptor(descriptor, scope, entry)
|
655
|
+
make_producer(Producers::LookupProducer, descriptor, scope, entry,
|
656
|
+
merge_producer_options(entry.binding, {:type => descriptor.type, :name => descriptor.name}))
|
657
|
+
end
|
658
|
+
|
659
|
+
# @api private
|
660
|
+
def transform_HashLookupProducerDescriptor(descriptor, scope, entry)
|
661
|
+
make_producer(Producers::LookupKeyProducer, descriptor, scope, entry,
|
662
|
+
merge_producer_options(entry.binding, {:type => descriptor.type, :name => descriptor.name, :key => descriptor.key}))
|
663
|
+
end
|
664
|
+
|
665
|
+
# @api private
|
666
|
+
def transform_NonCachingProducerDescriptor(descriptor, scope, entry)
|
667
|
+
# simply delegates to the wrapped producer
|
668
|
+
transform(descriptor.producer, scope, entry)
|
669
|
+
end
|
670
|
+
|
671
|
+
# @api private
|
672
|
+
def transform_FirstFoundProducerDescriptor(descriptor, scope, entry)
|
673
|
+
make_producer(Producers::FirstFoundProducer, descriptor, scope, entry,
|
674
|
+
merge_producer_options(entry.binding, {:producers => descriptor.producers.collect {|p| transform(p, scope, entry) }}))
|
675
|
+
end
|
676
|
+
|
677
|
+
# @api private
|
678
|
+
def singleton?(descriptor)
|
679
|
+
! descriptor.eContainer().is_a?(Puppet::Pops::Binder::Bindings::NonCachingProducerDescriptor)
|
680
|
+
end
|
681
|
+
|
682
|
+
# Special marker class used in entries
|
683
|
+
# @api private
|
684
|
+
class NotFound
|
685
|
+
end
|
686
|
+
end
|
687
|
+
end
|
688
|
+
end
|