class Puppet::Pops::Lookup::HieraConfigV5

@api private

Constants

DEFAULT_CONFIG_HASH
RESERVED_OPTION_KEYS

Public Class Methods

config_type() click to toggle source
    # File lib/puppet/pops/lookup/hiera_config.rb
543 def self.config_type
544   return @@CONFIG_TYPE if class_variable_defined?(:@@CONFIG_TYPE_V5)
545   tf = Types::TypeFactory
546   nes_t = Types::PStringType::NON_EMPTY
547 
548   # Validated using Ruby URI implementation
549   uri_t = Types::PStringType::NON_EMPTY
550 
551   # The option name must start with a letter and end with a letter or digit. May contain underscore and dash.
552   option_name_t = tf.pattern(/\A[A-Za-z](:?[0-9A-Za-z_-]*[0-9A-Za-z])?\z/)
553 
554   hierarchy_t = tf.array_of(tf.struct(
555     {
556       KEY_NAME => nes_t,
557       tf.optional(KEY_OPTIONS) => tf.hash_kv(option_name_t, tf.data),
558       tf.optional(KEY_DATA_HASH) => nes_t,
559       tf.optional(KEY_LOOKUP_KEY) => nes_t,
560       tf.optional(KEY_V3_BACKEND) => nes_t,
561       tf.optional(KEY_V4_DATA_HASH) => nes_t,
562       tf.optional(KEY_DATA_DIG) => nes_t,
563       tf.optional(KEY_PATH) => nes_t,
564       tf.optional(KEY_PATHS) => tf.array_of(nes_t, tf.range(1, :default)),
565       tf.optional(KEY_GLOB) => nes_t,
566       tf.optional(KEY_GLOBS) => tf.array_of(nes_t, tf.range(1, :default)),
567       tf.optional(KEY_URI) => uri_t,
568       tf.optional(KEY_URIS) => tf.array_of(uri_t, tf.range(1, :default)),
569       tf.optional(KEY_MAPPED_PATHS) => tf.array_of(nes_t, tf.range(3, 3)),
570       tf.optional(KEY_DATADIR) => nes_t
571     }))
572 
573   @@CONFIG_TYPE = tf.struct({
574     KEY_VERSION => tf.range(5, 5),
575     tf.optional(KEY_DEFAULTS) => tf.struct(
576       {
577         tf.optional(KEY_DATA_HASH) => nes_t,
578         tf.optional(KEY_LOOKUP_KEY) => nes_t,
579         tf.optional(KEY_DATA_DIG) => nes_t,
580         tf.optional(KEY_DATADIR) => nes_t,
581         tf.optional(KEY_OPTIONS) => tf.hash_kv(option_name_t, tf.data),
582       }),
583     tf.optional(KEY_HIERARCHY) => hierarchy_t,
584     tf.optional(KEY_PLAN_HIERARCHY) => hierarchy_t,
585     tf.optional(KEY_DEFAULT_HIERARCHY) => hierarchy_t
586   })
587 end

Public Instance Methods

create_configured_data_providers(lookup_invocation, parent_data_provider, use_default_hierarchy) click to toggle source
    # File lib/puppet/pops/lookup/hiera_config.rb
589 def create_configured_data_providers(lookup_invocation, parent_data_provider, use_default_hierarchy)
590   defaults = @config[KEY_DEFAULTS] || EMPTY_HASH
591   datadir = defaults[KEY_DATADIR] || 'data'
592 
593   # Hashes enumerate their values in the order that the corresponding keys were inserted so it's safe to use
594   # a hash for the data_providers.
595   data_providers = {}
596 
597   if @config.include?(KEY_DEFAULT_HIERARCHY)
598     unless parent_data_provider.is_a?(ModuleDataProvider)
599       fail(Issues::HIERA_DEFAULT_HIERARCHY_NOT_IN_MODULE, EMPTY_HASH, find_line_matching(/\s+default_hierarchy:/))
600     end
601   elsif use_default_hierarchy
602     return data_providers
603   end
604 
605   compiler = Puppet.lookup(:pal_compiler) { nil }
606   config_key = if compiler.is_a?(Puppet::Pal::ScriptCompiler) && !@config[KEY_PLAN_HIERARCHY].nil?
607         KEY_PLAN_HIERARCHY
608       elsif use_default_hierarchy
609         KEY_DEFAULT_HIERARCHY
610       else
611         KEY_HIERARCHY
612       end
613   @config[config_key].each do |he|
614     name = he[KEY_NAME]
615     if data_providers.include?(name)
616       first_line = find_line_matching(/\s+name:\s+['"]?#{name}(?:[^\w]|$)/)
617       line = find_line_matching(/\s+name:\s+['"]?#{name}(?:[^\w]|$)/, first_line + 1) if first_line
618       unless line
619         line = first_line
620         first_line = nil
621       end
622       fail(Issues::HIERA_HIERARCHY_NAME_MULTIPLY_DEFINED, { :name => name, :first_line => first_line }, line)
623     end
624     function_kind = ALL_FUNCTION_KEYS.find { |key| he.include?(key) }
625     if function_kind.nil?
626       function_kind = FUNCTION_KEYS.find { |key| defaults.include?(key) }
627       function_name = defaults[function_kind]
628     else
629       function_name = he[function_kind]
630     end
631 
632     entry_datadir = @config_root + (he[KEY_DATADIR] || datadir)
633     entry_datadir = Pathname(interpolate(entry_datadir.to_s, lookup_invocation, false))
634     location_key = LOCATION_KEYS.find { |key| he.include?(key) }
635     locations = case location_key
636     when KEY_PATHS
637       resolve_paths(entry_datadir, he[location_key], lookup_invocation, @config_path.nil?)
638     when KEY_PATH
639       resolve_paths(entry_datadir, [he[location_key]], lookup_invocation, @config_path.nil?)
640     when KEY_GLOBS
641       expand_globs(entry_datadir, he[location_key], lookup_invocation)
642     when KEY_GLOB
643       expand_globs(entry_datadir, [he[location_key]], lookup_invocation)
644     when KEY_URIS
645       expand_uris(he[location_key], lookup_invocation)
646     when KEY_URI
647       expand_uris([he[location_key]], lookup_invocation)
648     when KEY_MAPPED_PATHS
649       expand_mapped_paths(entry_datadir, he[location_key], lookup_invocation)
650     else
651       nil
652     end
653     next if @config_path.nil? && !locations.nil? && locations.empty? # Default config and no existing paths found
654     options = he[KEY_OPTIONS] || defaults[KEY_OPTIONS]
655     options = options.nil? ? EMPTY_HASH : interpolate(options, lookup_invocation, false)
656     if(function_kind == KEY_V3_BACKEND)
657       v3options = { :datadir => entry_datadir.to_s }
658       options.each_pair { |k, v| v3options[k.to_sym] = v }
659       data_providers[name] = create_hiera3_backend_provider(name, function_name, parent_data_provider, entry_datadir, locations, {
660         :hierarchy =>
661           locations.nil? ? [] : locations.map do |loc|
662             path = loc.original_location
663             path.end_with?(".#{function_name}") ? path[0..-(function_name.length + 2)] : path
664           end,
665         function_name.to_sym => v3options,
666         :backends => [ function_name ],
667         :logger => 'puppet'
668       })
669     else
670       data_providers[name] = create_data_provider(name, parent_data_provider, function_kind, function_name, options, locations)
671     end
672   end
673   data_providers.values
674 end
has_default_hierarchy?() click to toggle source
    # File lib/puppet/pops/lookup/hiera_config.rb
676 def has_default_hierarchy?
677   @config.include?(KEY_DEFAULT_HIERARCHY)
678 end
validate_config(config, owner) click to toggle source
    # File lib/puppet/pops/lookup/hiera_config.rb
696 def validate_config(config, owner)
697   config[KEY_DEFAULTS] ||= DEFAULT_CONFIG_HASH[KEY_DEFAULTS]
698   config[KEY_HIERARCHY] ||= DEFAULT_CONFIG_HASH[KEY_HIERARCHY]
699 
700   Types::TypeAsserter.assert_instance_of(["The Lookup Configuration at '%s'", @config_path], self.class.config_type, config)
701   defaults = config[KEY_DEFAULTS]
702   validate_defaults(defaults) unless defaults.nil?
703   config[KEY_HIERARCHY].each { |he| validate_hierarchy(he, defaults, owner) }
704   if config.include?(KEY_PLAN_HIERARCHY)
705     config[KEY_PLAN_HIERARCHY].each { |he| validate_hierarchy(he, defaults, owner) }
706   end
707 
708   if config.include?(KEY_DEFAULT_HIERARCHY)
709     unless owner.is_a?(ModuleDataProvider)
710       fail(Issues::HIERA_DEFAULT_HIERARCHY_NOT_IN_MODULE, EMPTY_HASH, find_line_matching(/(?:^|\s+)#{KEY_DEFAULT_HIERARCHY}:/))
711     end
712     config[KEY_DEFAULT_HIERARCHY].each { |he| validate_hierarchy(he, defaults, owner) }
713   end
714   config
715 end
validate_defaults(defaults) click to toggle source
    # File lib/puppet/pops/lookup/hiera_config.rb
754 def validate_defaults(defaults)
755   case FUNCTION_KEYS.count { |key| defaults.include?(key) }
756   when 0, 1
757     # OK
758   else
759     fail(Issues::HIERA_MULTIPLE_DATA_PROVIDER_FUNCTIONS_IN_DEFAULT)
760   end
761 
762   options = defaults[KEY_OPTIONS]
763   unless options.nil?
764     RESERVED_OPTION_KEYS.each do |key|
765       fail(Issues::HIERA_DEFAULT_OPTION_RESERVED_BY_PUPPET, :key => key) if options.include?(key)
766     end
767   end
768 end
validate_hierarchy(he, defaults, owner) click to toggle source
    # File lib/puppet/pops/lookup/hiera_config.rb
717 def validate_hierarchy(he, defaults, owner)
718   name = he[KEY_NAME]
719   case ALL_FUNCTION_KEYS.count { |key| he.include?(key) }
720   when 0
721     if defaults.nil? || FUNCTION_KEYS.count { |key| defaults.include?(key) } == 0
722       fail(Issues::HIERA_MISSING_DATA_PROVIDER_FUNCTION, :name => name)
723     end
724   when 1
725     # OK
726   else
727     fail(Issues::HIERA_MULTIPLE_DATA_PROVIDER_FUNCTIONS, :name => name)
728   end
729 
730   v3_backend = he[KEY_V3_BACKEND]
731   unless v3_backend.nil?
732     unless owner.is_a?(GlobalDataProvider)
733       fail(Issues::HIERA_V3_BACKEND_NOT_GLOBAL, EMPTY_HASH, find_line_matching(/\s+#{KEY_V3_BACKEND}:/))
734     end
735     if v3_backend == 'json' || v3_backend == 'yaml' || v3_backend == 'hocon' &&  Puppet.features.hocon?
736       # Disallow use of backends that have corresponding "data_hash" functions in version 5
737       fail(Issues::HIERA_V3_BACKEND_REPLACED_BY_DATA_HASH, { :function_name => v3_backend },
738         find_line_matching(/\s+#{KEY_V3_BACKEND}:\s*['"]?#{v3_backend}(?:[^\w]|$)/))
739     end
740   end
741 
742   if LOCATION_KEYS.count { |key| he.include?(key) } > 1
743     fail(Issues::HIERA_MULTIPLE_LOCATION_SPECS, :name => name)
744   end
745 
746   options = he[KEY_OPTIONS]
747   unless options.nil?
748     RESERVED_OPTION_KEYS.each do |key|
749       fail(Issues::HIERA_OPTION_RESERVED_BY_PUPPET, :key => key, :name => name) if options.include?(key)
750     end
751   end
752 end
version() click to toggle source
    # File lib/puppet/pops/lookup/hiera_config.rb
770 def version
771   5
772 end