mirror of
https://github.com/fluent/fluentd-ui.git
synced 2025-08-12 09:17:05 +02:00
Add concerns to define models for fluent-plugin
Signed-off-by: Kenji Okimoto <okimoto@clear-code.com>
This commit is contained in:
parent
ac8c1fa9f8
commit
4f2a06fd82
103
app/models/concerns/fluentd/setting/configurable.rb
Normal file
103
app/models/concerns/fluentd/setting/configurable.rb
Normal file
@ -0,0 +1,103 @@
|
||||
class Fluentd
|
||||
module Setting
|
||||
module Configurable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
class_attribute :_types, :_defaults, :_secrets, :_aliases, :_required
|
||||
class_attribute :_deprecated_params, :_obsoleted_params, :_descriptions
|
||||
class_attribute :_list, :_value_types, :_symbolize_keys
|
||||
class_attribute :_argument_name, :_built_in_params, :_sections, :_section_params
|
||||
self._types = {}
|
||||
self._defaults = {}
|
||||
self._secrets = {}
|
||||
self._aliases = {}
|
||||
self._required = {}
|
||||
self._deprecated_params = {}
|
||||
self._obsoleted_params = {}
|
||||
self._descriptions = {}
|
||||
self._list = {}
|
||||
self._value_types = {}
|
||||
self._symbolize_keys = {}
|
||||
self._argument_name = nil
|
||||
self._built_in_params = []
|
||||
self._sections = {}
|
||||
self._section_params = Hash.new {|h, k| h[k] = [] }
|
||||
end
|
||||
|
||||
def initialize(attributes = {})
|
||||
super rescue ActiveModel::UnknownAttributeError # the superclass does not know specific attributes of the model
|
||||
self.class._sections.each do |name, klass|
|
||||
klass.init
|
||||
if klass.multi
|
||||
next if attributes[name].nil?
|
||||
attributes[name].each do |attr|
|
||||
next unless attr
|
||||
attr.each do |index, _attr|
|
||||
self._section_params[name] << klass.new(_attr)
|
||||
end
|
||||
end
|
||||
else
|
||||
attr = attributes.dig(name, "0")
|
||||
self._section_params[name] << klass.new(attr) if attr
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
# config_param :name, :string, default: "value", secret: true
|
||||
def config_param(name, type = ActiveModel::Type::Value.new, **options)
|
||||
# NOTE: We cannot overwrite types defined by ActiveModel in config/initializers/types.rb
|
||||
if type == :time
|
||||
type = Fluentd::Setting::Type::Time.new
|
||||
end
|
||||
if name.to_s.start_with?("@")
|
||||
_name = name.to_s[1..-1]
|
||||
config_param(_name.to_sym, type, **options.merge(alias: name))
|
||||
self._built_in_params << _name
|
||||
elsif ["id", "type", "log_level"].include?(name.to_s)
|
||||
self._built_in_params << _name
|
||||
else
|
||||
attribute(name, type, **options.slice(:precision, :limit, :scale))
|
||||
validates(name, presence: true) if options[:required]
|
||||
end
|
||||
self._types[name] = type
|
||||
self._defaults[name] = options[:default] if options.key?(:default)
|
||||
self._secrets[name] = options[:secret] if options.key?(:secret)
|
||||
self._aliases[name] = options[:alias] if options.key?(:alias)
|
||||
self._required[name] = options[:required] if options.key?(:required)
|
||||
self._deprecated_params[name] = options[:deprecated] if options.key?(:deprecated)
|
||||
self._obsoleted_params[name] = options[:obsoleted] if options.key?(:obsoleted)
|
||||
self._list[name] = options[:list] if options.key?(:list)
|
||||
self._value_types[name] = options[:value_types] if options.key?(:value_types)
|
||||
self._symbolize_keys = options[:symbolize_keys] if options.key?(:symbolize_keys)
|
||||
end
|
||||
|
||||
def config_section(name, **options, &block)
|
||||
if self._sections.key?(name)
|
||||
self._sections[name].merge(**options, &block)
|
||||
else
|
||||
attribute(name, :section)
|
||||
section_class = Class.new(::Fluentd::Setting::Section)
|
||||
section_class.section_name = name
|
||||
section_class.required = options[:required]
|
||||
section_class.multi = options[:multi]
|
||||
section_class.alias = options[:alias]
|
||||
section_class._block = block
|
||||
self.const_set(name.to_s.classify, section_class)
|
||||
self._sections[name] = section_class
|
||||
end
|
||||
end
|
||||
|
||||
def config_argument(name, type = ActiveModel::Type::Value.new, **options)
|
||||
config_param(name, **options)
|
||||
self._argument_name = name
|
||||
end
|
||||
|
||||
def set_argument_name(name)
|
||||
self._argument_name = name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
11
app/models/concerns/fluentd/setting/pattern.rb
Normal file
11
app/models/concerns/fluentd/setting/pattern.rb
Normal file
@ -0,0 +1,11 @@
|
||||
class Fluentd
|
||||
module Setting
|
||||
module Pattern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
config_argument(:pattern, :string)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
75
app/models/concerns/fluentd/setting/plugin.rb
Normal file
75
app/models/concerns/fluentd/setting/plugin.rb
Normal file
@ -0,0 +1,75 @@
|
||||
require "fluent/plugin"
|
||||
|
||||
class Fluentd
|
||||
module Setting
|
||||
module Plugin
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
include ActiveModel::Model
|
||||
include ActiveModel::Attributes
|
||||
include Fluentd::Setting::Configurable
|
||||
include Fluentd::Setting::PluginConfig
|
||||
include Fluentd::Setting::SectionParser
|
||||
include Fluentd::Setting::PluginParameter
|
||||
include Fluentd::Setting::SectionValidator
|
||||
|
||||
included do
|
||||
cattr_accessor :plugin_type, :plugin_name, :config_definition
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def register_plugin(type, name)
|
||||
self.plugin_type = type
|
||||
self.plugin_name = name
|
||||
|
||||
if ["filter", "output"].include?(type)
|
||||
include Fluentd::Setting::Pattern
|
||||
end
|
||||
|
||||
self.load_plugin_config do |_name, params|
|
||||
params.each do |param_name, definition|
|
||||
if definition[:section]
|
||||
parse_section(param_name, definition)
|
||||
else
|
||||
config_param(param_name, definition[:type], **definition.except(:type))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def load_plugin_config
|
||||
dumped_config = {}
|
||||
plugin_class.ancestors.reverse_each do |klass|
|
||||
next unless klass.respond_to?(:dump_config_definition)
|
||||
dumped_config_definition = klass.dump_config_definition
|
||||
dumped_config[klass.name] = dumped_config_definition unless dumped_config_definition.empty?
|
||||
end
|
||||
self.config_definition = dumped_config
|
||||
dumped_config.each do |name, config|
|
||||
yield name, config
|
||||
end
|
||||
end
|
||||
|
||||
def plugin_instance
|
||||
@plugin_instance ||= Fluent::Plugin.__send__("new_#{plugin_type}", plugin_name)
|
||||
end
|
||||
|
||||
def plugin_class
|
||||
@plugin_class ||= plugin_instance.class
|
||||
end
|
||||
|
||||
def plugin_helpers
|
||||
@plugin_helpers ||= if plugin_instance.respond_to?(:plugin_helpers)
|
||||
plugin_instance.plugin_helpers
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
def section?
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
57
app/models/concerns/fluentd/setting/plugin_config.rb
Normal file
57
app/models/concerns/fluentd/setting/plugin_config.rb
Normal file
@ -0,0 +1,57 @@
|
||||
class Fluentd
|
||||
module Setting
|
||||
module PluginConfig
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def to_config
|
||||
name = case plugin_type
|
||||
when "input"
|
||||
"source"
|
||||
when "output"
|
||||
"match"
|
||||
when "filter"
|
||||
"filter"
|
||||
when "parser"
|
||||
"parse"
|
||||
when "formatter"
|
||||
"format"
|
||||
when "buffer"
|
||||
"buffer"
|
||||
end
|
||||
_attributes = { "@type" => self.plugin_name }.merge(attributes)
|
||||
_attributes["@log_level"] = _attributes.delete("log_level")
|
||||
argument = case plugin_type
|
||||
when "output", "filter", "buffer"
|
||||
_attributes.delete(self._argument_name.to_s) || ""
|
||||
else
|
||||
""
|
||||
end
|
||||
attrs, elements = parse_attributes(_attributes)
|
||||
config_element(name, argument, attrs, elements)
|
||||
end
|
||||
|
||||
def parse_attributes(attributes)
|
||||
base_klasses = config_definition.keys
|
||||
sections, params = attributes.partition do |key, _section_attributes|
|
||||
base_klasses.any? do |base_klass|
|
||||
config_definition.dig(base_klass, key.to_sym, :section) || config_definition.dig(key.to_sym, :section)
|
||||
end
|
||||
end
|
||||
elements = []
|
||||
sections.to_h.each do |key, section_params|
|
||||
next if section_params.blank?
|
||||
section_params.each do |index, _section_params|
|
||||
sub_attrs, sub_elements = parse_attributes(_section_params)
|
||||
elements << config_element(key, "", sub_attrs, sub_elements)
|
||||
end
|
||||
end
|
||||
return params.to_h.reject{|key, value| value.blank? }, elements
|
||||
end
|
||||
|
||||
# copy from Fluent::Test::Helpers#config_element
|
||||
def config_element(name = 'test', argument = '', params = {}, elements = [])
|
||||
Fluent::Config::Element.new(name, argument, params, elements)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
43
app/models/concerns/fluentd/setting/plugin_parameter.rb
Normal file
43
app/models/concerns/fluentd/setting/plugin_parameter.rb
Normal file
@ -0,0 +1,43 @@
|
||||
class Fluentd
|
||||
module Setting
|
||||
module PluginParameter
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
include Fluentd::Setting::Configurable
|
||||
|
||||
def column_type(name)
|
||||
self.class._types[name]
|
||||
end
|
||||
|
||||
def list_of(name)
|
||||
self.class._list[name]
|
||||
end
|
||||
|
||||
def common_options
|
||||
[]
|
||||
end
|
||||
|
||||
def advanced_options
|
||||
all_options - common_options - hidden_options
|
||||
end
|
||||
|
||||
def hidden_options
|
||||
[]
|
||||
end
|
||||
|
||||
def all_options
|
||||
self.class._types.keys + self.class._sections.keys
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def column_type(name)
|
||||
self._types[name]
|
||||
end
|
||||
|
||||
def list_of(name)
|
||||
self._list[name]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
21
app/models/concerns/fluentd/setting/section_parser.rb
Normal file
21
app/models/concerns/fluentd/setting/section_parser.rb
Normal file
@ -0,0 +1,21 @@
|
||||
class Fluentd
|
||||
module Setting
|
||||
module SectionParser
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
module ClassMethods
|
||||
def parse_section(name, definition)
|
||||
config_section(name, **definition.slice(:required, :multi, :alias)) do
|
||||
definition.except(:section, :argument, :required, :multi, :alias).each do |_param_name, _definition|
|
||||
if _definition[:section]
|
||||
parse_section(_param_name, _definition)
|
||||
else
|
||||
config_param(_param_name, _definition[:type], **_definition.except(:type))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
21
app/models/concerns/fluentd/setting/section_validator.rb
Normal file
21
app/models/concerns/fluentd/setting/section_validator.rb
Normal file
@ -0,0 +1,21 @@
|
||||
class Fluentd
|
||||
module Setting
|
||||
module SectionValidator
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
validate :validate_sections
|
||||
end
|
||||
|
||||
def validate_sections
|
||||
self._section_params.each do |name, sections|
|
||||
sections.each do |section|
|
||||
if section.invalid?
|
||||
errors.add(name, :invalid, message: section.errors.full_messages)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user