module Fluent::Config::SectionGenerator

Public Class Methods

check_unused_section(proxy, conf, plugin_class) click to toggle source
# File lib/fluent/config/section.rb, line 252
def self.check_unused_section(proxy, conf, plugin_class)
  elems = conf.respond_to?(:elements) ? conf.elements : []
  elems.each { |e|
    next if plugin_class.nil? && Fluent::Config::V1Parser::ELEM_SYMBOLS.include?(e.name) # skip pre-defined non-plugin elements because it doesn't have proxy section
    next if e.unused_in && e.unused_in.empty? # the section is used at least once

    if proxy.sections.any? { |name, subproxy| e.name == subproxy.name.to_s || e.name == subproxy.alias.to_s }
      e.unused_in = []
    else
      parent_name = if conf.arg.empty?
                      conf.name
                    else
                      "#{conf.name} #{conf.arg}"
                    end
      e.unused_in = [parent_name, plugin_class]
    end
  }
end
generate(proxy, conf, logger, plugin_class, stack = [], strict_config_value = false) click to toggle source
# File lib/fluent/config/section.rb, line 118
def self.generate(proxy, conf, logger, plugin_class, stack = [], strict_config_value = false)
  return nil if conf.nil?

  section_stack = ""
  unless stack.empty?
    section_stack = ", in section " + stack.join(" > ")
  end

  section_params = {}

  proxy.defaults.each_pair do |name, defval|
    varname = name.to_sym
    section_params[varname] = (defval.dup rescue defval)
  end

  if proxy.argument
    unless conf.arg.nil? || conf.arg.empty?
      key, block, opts = proxy.argument
      opts = opts.merge(strict: true) if strict_config_value

      if conf.arg == :default
        unless section_params.has_key?(key)
          logger.error "config error in:\n#{conf}" if logger
          raise ConfigError, "'#{key}' doesn't have default value"
        end
      else
        begin
          section_params[key] = self.instance_exec(conf.arg, opts, key, &block)
        rescue ConfigError => e
          logger.error "config error in:\n#{conf}" if logger
          raise e
        end
      end
    end
    unless section_params.has_key?(proxy.argument.first)
      logger.error "config error in:\n#{conf}" if logger # logger should exist, but somethimes it's nil (e.g, in tests)
      raise ConfigError, "'<#{proxy.name} ARG>' section requires argument" + section_stack
    end
    # argument should NOT be deprecated... (argument always has a value: '')
  end

  proxy.params.each_pair do |name, defval|
    varname = name.to_sym
    block, opts = defval
    opts = opts.merge(strict: true) if strict_config_value

    if conf.has_key?(name.to_s) || opts[:alias] && conf.has_key?(opts[:alias].to_s)
      val = if conf.has_key?(name.to_s)
              conf[name.to_s]
            else
              conf[opts[:alias].to_s]
            end

      if val == :default
        # default value is already set if it exists
        unless section_params.has_key?(varname)
          logger.error "config error in:\n#{conf}" if logger
          raise ConfigError, "'#{varname}' doesn't have default value"
        end
      else
        begin
          section_params[varname] = self.instance_exec(val, opts, name, &block)
        rescue ConfigError => e
          logger.error "config error in:\n#{conf}" if logger
          raise e
        end
      end

      if section_params[varname].nil?
        unless proxy.defaults.has_key?(varname) && proxy.defaults[varname].nil?
          logger.error "config error in:\n#{conf}" if logger
          raise ConfigError, "'#{name}' parameter is required but nil is specified"
        end
      end

      # Source of definitions of deprecated/obsoleted:
      # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Deprecated_and_obsolete_features
      #
      # Deprecated: These deprecated features can still be used, but should be used with caution
      #             because they are expected to be removed entirely sometime in the future.
      # Obsoleted: These obsolete features have been entirely removed from JavaScript and can no longer be used.
      if opts[:deprecated]
        logger.warn "'#{name}' parameter is deprecated: #{opts[:deprecated]}" if logger
      end
      if opts[:obsoleted]
        logger.error "config error in:\n#{conf}" if logger
        raise ObsoletedParameterError, "'#{name}' parameter is already removed: #{opts[:obsoleted]}" + section_stack
      end
    end
    unless section_params.has_key?(varname)
      logger.error "config error in:\n#{conf}" if logger
      raise ConfigError, "'#{name}' parameter is required" + section_stack
    end
  end

  check_unused_section(proxy, conf, plugin_class)

  proxy.sections.each do |name, subproxy|
    varname = subproxy.variable_name
    elements = (conf.respond_to?(:elements) ? conf.elements : []).select{ |e| e.name == subproxy.name.to_s || e.name == subproxy.alias.to_s }
    if elements.empty? && subproxy.init?
      if subproxy.argument && !subproxy.defaults.has_key?(subproxy.argument.first)
        raise ArgumentError, "#{name}: init is specified, but default value of argument is missing"
      end
      missing_keys = subproxy.params.keys.select{|param_name| !subproxy.defaults.has_key?(param_name)}
      if !missing_keys.empty?
        raise ArgumentError, "#{name}: init is specified, but there're parameters without default values:#{missing_keys.join(',')}"
      end
      elements << Fluent::Config::Element.new(subproxy.name.to_s, '', {}, [])
    end

    # set subproxy for secret option
    elements.each { |element|
      element.corresponding_proxies << subproxy
    }

    if subproxy.required? && elements.size < 1
      logger.error "config error in:\n#{conf}" if logger
      raise ConfigError, "'<#{subproxy.name}>' sections are required" + section_stack
    end
    if subproxy.multi?
      section_params[varname] = elements.map{ |e| generate(subproxy, e, logger, plugin_class, stack + [subproxy.name], strict_config_value) }
    else
      if elements.size > 1
        logger.error "config error in:\n#{conf}" if logger
        raise ConfigError, "'<#{subproxy.name}>' section cannot be written twice or more" + section_stack
      end
      section_params[varname] = generate(subproxy, elements.first, logger, plugin_class, stack + [subproxy.name], strict_config_value)
    end
  end

  Section.new(section_params, conf)
end