Class: Fluent::Config::ConfigureProxy

Inherits:
Object
  • Object
show all
Defined in:
lib/fluent/config/configure_proxy.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, root: false, param_name: nil, final: nil, init: nil, required: nil, multi: nil, alias: nil, type_lookup:) ⇒ ConfigureProxy

config_param :desc, :string, default: ‘.…’ config_set_default :buffer_type, :memory

config_section :default, required: true, multi: false do

config_argument :arg, :string
config_param :required, :bool, default: false
config_param :name, :string
config_param :power, :integer

end

config_section :child, param_name: ‘children’, required: false, multi: true, alias: ‘node’ do

config_param :name, :string
config_param :power, :integer, default: nil
config_section :item do
  config_param :name
end

end



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/fluent/config/configure_proxy.rb', line 40

def initialize(name, root: false, param_name: nil, final: nil, init: nil, required: nil, multi: nil, alias: nil, type_lookup:)
  @name = name.to_sym
  @final = final

  # For ConfigureProxy of root section, "@name" should be a class name of plugins.
  # Otherwise (like subsections), "@name" should be a name of section, like "buffer", "store".
  # For subsections, name will be used as parameter names (unless param_name exists), so overriding proxy's name
  #   should override "@name".
  @root_section = root

  @param_name = param_name && param_name.to_sym
  @init = init
  @required = required
  @multi = multi
  @alias = binding.local_variable_get(:alias)
  @type_lookup = type_lookup

  raise "init and required are exclusive" if @init && @required

  # specify section name for viewpoint of owner(parent) plugin
  # for buffer plugins: all params are in <buffer> section of owner
  # others: <storage>, <format> (formatter/parser), ...
  @configured_in_section = nil

  @argument = nil # nil: ignore argument
  @params = {}
  @defaults = {}
  @descriptions = {}
  @sections = {}
  @current_description = nil
end

Instance Attribute Details

#aliasObject

Returns the value of attribute alias.



20
21
22
# File 'lib/fluent/config/configure_proxy.rb', line 20

def alias
  @alias
end

#argumentObject

Returns the value of attribute argument.



21
22
23
# File 'lib/fluent/config/configure_proxy.rb', line 21

def argument
  @argument
end

#configured_in_sectionObject

Returns the value of attribute configured_in_section.



20
21
22
# File 'lib/fluent/config/configure_proxy.rb', line 20

def configured_in_section
  @configured_in_section
end

#defaultsObject

Returns the value of attribute defaults.



21
22
23
# File 'lib/fluent/config/configure_proxy.rb', line 21

def defaults
  @defaults
end

#descriptionsObject

Returns the value of attribute descriptions.



21
22
23
# File 'lib/fluent/config/configure_proxy.rb', line 21

def descriptions
  @descriptions
end

#finalObject

Returns the value of attribute final.



20
21
22
# File 'lib/fluent/config/configure_proxy.rb', line 20

def final
  @final
end

#initObject

Returns the value of attribute init.



20
21
22
# File 'lib/fluent/config/configure_proxy.rb', line 20

def init
  @init
end

#multiObject

Returns the value of attribute multi.



20
21
22
# File 'lib/fluent/config/configure_proxy.rb', line 20

def multi
  @multi
end

#nameObject

Returns the value of attribute name.



20
21
22
# File 'lib/fluent/config/configure_proxy.rb', line 20

def name
  @name
end

#param_nameObject

Returns the value of attribute param_name.



20
21
22
# File 'lib/fluent/config/configure_proxy.rb', line 20

def param_name
  @param_name
end

#paramsObject

Returns the value of attribute params.



21
22
23
# File 'lib/fluent/config/configure_proxy.rb', line 21

def params
  @params
end

#requiredObject

Returns the value of attribute required.



20
21
22
# File 'lib/fluent/config/configure_proxy.rb', line 20

def required
  @required
end

#sectionsObject

Returns the value of attribute sections.



21
22
23
# File 'lib/fluent/config/configure_proxy.rb', line 21

def sections
  @sections
end

Instance Method Details

#config_argument(name, type = nil, **kwargs, &block) ⇒ Object



307
308
309
310
311
312
313
314
315
# File 'lib/fluent/config/configure_proxy.rb', line 307

def config_argument(name, type = nil, **kwargs, &block)
  if @argument
    raise ArgumentError, "#{self.name}: config_argument called twice"
  end
  name, block, opts = parameter_configuration(name, type, **kwargs, &block)

  @argument = [name, block, opts]
  name
end

#config_param(name, type = nil, **kwargs, &block) ⇒ Object



317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/fluent/config/configure_proxy.rb', line 317

def config_param(name, type = nil, **kwargs, &block)
  name, block, opts = parameter_configuration(name, type, **kwargs, &block)

  if @current_description
    config_set_desc(name, @current_description)
    @current_description = nil
  end

  @sections.delete(name)
  @params[name] = [block, opts]
  name
end

#config_parameter_option_validate!(name, type, **kwargs, &block) ⇒ Object



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/fluent/config/configure_proxy.rb', line 229

def config_parameter_option_validate!(name, type, **kwargs, &block)
  if type.nil? && !block
    type = :string
  end
  kwargs.each_key do |key|
    case key
    when :default, :alias, :secret, :skip_accessor, :deprecated, :obsoleted, :desc
      # valid for all types
    when :list
      raise ArgumentError, ":list is valid only for :enum type, but #{type}: #{name}" if type != :enum
    when :value_type
      raise ArgumentError, ":value_type is valid only for :hash and :array, but #{type}: #{name}" if type != :hash && type != :array
    when :symbolize_keys
      raise ArgumentError, ":symbolize_keys is valid only for :hash, but #{type}: #{name}" if type != :hash
    else
      raise ArgumentError, "unknown option '#{key}' for configuration parameter: #{name}"
    end
  end
end

#config_section(name, **kwargs, &block) ⇒ Object



356
357
358
359
360
361
362
363
364
365
366
367
368
369
# File 'lib/fluent/config/configure_proxy.rb', line 356

def config_section(name, **kwargs, &block)
  unless block_given?
    raise ArgumentError, "#{name}: config_section requires block parameter"
  end
  name = name.to_sym

  sub_proxy = ConfigureProxy.new(name, type_lookup: @type_lookup, **kwargs)
  sub_proxy.instance_exec(&block)

  @params.delete(name)
  @sections[name] = sub_proxy

  name
end

#config_set_default(name, defval) ⇒ Object



330
331
332
333
334
335
336
337
338
339
# File 'lib/fluent/config/configure_proxy.rb', line 330

def config_set_default(name, defval)
  name = name.to_sym

  if @defaults.has_key?(name)
    raise ArgumentError, "#{self.name}: default value specified twice for #{name}"
  end

  @defaults[name] = defval
  nil
end

#config_set_desc(name, description) ⇒ Object



341
342
343
344
345
346
347
348
349
350
# File 'lib/fluent/config/configure_proxy.rb', line 341

def config_set_desc(name, description)
  name = name.to_sym

  if @descriptions.has_key?(name)
    raise ArgumentError, "#{self.name}: description specified twice for #{name}"
  end

  @descriptions[name] = description
  nil
end

#configured_in(section_name) ⇒ Object



300
301
302
303
304
305
# File 'lib/fluent/config/configure_proxy.rb', line 300

def configured_in(section_name)
  if @configured_in_section
    raise ArgumentError, "#{self.name}: configured_in called twice"
  end
  @configured_in_section = section_name.to_sym
end

#desc(description) ⇒ Object



352
353
354
# File 'lib/fluent/config/configure_proxy.rb', line 352

def desc(description)
  @current_description = description
end

#dump_config_definitionObject



371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
# File 'lib/fluent/config/configure_proxy.rb', line 371

def dump_config_definition
  dumped_config = {}
  if @argument
    argument_name, _block, options = @argument
    options[:required] = !@defaults.key?(argument_name)
    options[:argument] = true
    dumped_config[argument_name] = options
  end
  @params.each do |name, config|
    dumped_config[name] = config[1]
    dumped_config[name][:required] = !@defaults.key?(name)
    dumped_config[name][:default] = @defaults[name] if @defaults.key?(name)
    dumped_config[name][:desc] = @descriptions[name] if @descriptions.key?(name)
  end
  # Overwrite by config_set_default
  @defaults.each do |name, value|
    if @params.key?(name) || (@argument && @argument.first == name)
      dumped_config[name][:default] = value
    else
      dumped_config[name] = { default: value }
    end
  end
  # Overwrite by config_set_desc
  @descriptions.each do |name, value|
    if @params.key?(name)
      dumped_config[name][:desc] = value
    else
      dumped_config[name] = { desc: value }
    end
  end
  @sections.each do |section_name, sub_proxy|
    if dumped_config.key?(section_name)
      dumped_config[section_name].update(sub_proxy.dump_config_definition)
    else
      dumped_config[section_name] = sub_proxy.dump_config_definition
      dumped_config[section_name][:required] = sub_proxy.required?
      dumped_config[section_name][:multi] = sub_proxy.multi?
      dumped_config[section_name][:alias] = sub_proxy.alias
      dumped_config[section_name][:section] = true
    end
  end
  dumped_config
end

#final?Boolean

Returns:

  • (Boolean)


92
93
94
# File 'lib/fluent/config/configure_proxy.rb', line 92

def final?
  !!@final
end

#init?Boolean

Returns:

  • (Boolean)


80
81
82
# File 'lib/fluent/config/configure_proxy.rb', line 80

def init?
  @init.nil? ? false : @init
end

#merge(other) ⇒ Object

self is base class, other is subclass



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/fluent/config/configure_proxy.rb', line 96

def merge(other) # self is base class, other is subclass
  return merge_for_finalized(other) if self.final?

  [:param_name, :required, :multi, :alias, :configured_in_section].each do |prohibited_name|
    if overwrite?(other, prohibited_name)
      raise ConfigError, "BUG: subclass cannot overwrite base class's config_section: #{prohibited_name}"
    end
  end

  options = {}
  # param_name affects instance variable name, which is just "internal" of each plugins.
  # so it must not be changed. base class's name (or param_name) is always used.
  options[:param_name] = @param_name

  # subclass cannot overwrite base class's definition
  options[:init] = @init.nil? ? other.init : self.init
  options[:required] = @required.nil? ? other.required : self.required
  options[:multi] = @multi.nil? ? other.multi : self.multi
  options[:alias] = @alias.nil? ? other.alias : self.alias
  options[:final] = @final || other.final
  options[:type_lookup] = @type_lookup

  merged = if self.root?
             options[:root] = true
             self.class.new(other.name, **options)
           else
             self.class.new(@name, **options)
           end

  # configured_in MUST be kept
  merged.configured_in_section = self.configured_in_section || other.configured_in_section

  merged.argument = other.argument || self.argument
  merged.params = self.params.merge(other.params)
  merged.defaults = self.defaults.merge(other.defaults)
  merged.sections = {}
  (self.sections.keys + other.sections.keys).uniq.each do |section_key|
    self_section = self.sections[section_key]
    other_section = other.sections[section_key]
    merged_section = if self_section && other_section
                       self_section.merge(other_section)
                     elsif self_section || other_section
                       self_section || other_section
                     else
                       raise "BUG: both of self and other section are nil"
                     end
    merged.sections[section_key] = merged_section
  end

  merged
end

#merge_for_finalized(other) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/fluent/config/configure_proxy.rb', line 148

def merge_for_finalized(other)
  # list what subclass can do for finalized section
  #  * append params/defaults/sections which are missing in superclass
  #  * change default values of superclass
  #  * overwrite init to make it enable to instantiate section objects with added default values

  if other.final == false && overwrite?(other, :final)
    raise ConfigError, "BUG: subclass cannot overwrite finalized base class's config_section"
  end

  [:param_name, :required, :multi, :alias, :configured_in_section].each do |prohibited_name|
    if overwrite?(other, prohibited_name)
      raise ConfigError, "BUG: subclass cannot overwrite base class's config_section: #{prohibited_name}"
    end
  end

  options = {}
  options[:param_name] = @param_name
  options[:init] = @init || other.init
  options[:required] = @required.nil? ? other.required : self.required
  options[:multi] = @multi.nil? ? other.multi : self.multi
  options[:alias] = @alias.nil? ? other.alias : self.alias
  options[:final]  = true
  options[:type_lookup] = @type_lookup

  merged = if self.root?
             options[:root] = true
             self.class.new(other.name, **options)
           else
             self.class.new(@name, **options)
           end

  merged.configured_in_section = self.configured_in_section || other.configured_in_section

  merged.argument = self.argument || other.argument
  merged.params = other.params.merge(self.params)
  merged.defaults = self.defaults.merge(other.defaults)
  merged.sections = {}
  (self.sections.keys + other.sections.keys).uniq.each do |section_key|
    self_section = self.sections[section_key]
    other_section = other.sections[section_key]
    merged_section = if self_section && other_section
                       other_section.merge(self_section)
                     elsif self_section || other_section
                       self_section || other_section
                     else
                       raise "BUG: both of self and other section are nil"
                     end
    merged.sections[section_key] = merged_section
  end

  merged
end

#multi?Boolean

Returns:

  • (Boolean)


88
89
90
# File 'lib/fluent/config/configure_proxy.rb', line 88

def multi?
  @multi.nil? ? true : @multi
end

#option_value_type!(name, opts, key, klass = nil, type: nil) ⇒ Object



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/fluent/config/configure_proxy.rb', line 211

def option_value_type!(name, opts, key, klass=nil, type: nil)
  if opts.has_key?(key)
    if klass && !opts[key].is_a?(klass)
      raise ArgumentError, "#{name}: #{key} must be a #{klass}, but #{opts[key].class}"
    end
    case type
    when :boolean
      unless opts[key].is_a?(TrueClass) || opts[key].is_a?(FalseClass)
        raise ArgumentError, "#{name}: #{key} must be true or false, but #{opts[key].class}"
      end
    when nil
      # ignore
    else
      raise "unknown type: #{type} for option #{key}"
    end
  end
end

#overwrite_defaults(other) ⇒ Object

other is owner plugin’s corresponding proxy



202
203
204
205
206
207
208
209
# File 'lib/fluent/config/configure_proxy.rb', line 202

def overwrite_defaults(other) # other is owner plugin's corresponding proxy
  self.defaults = self.defaults.merge(other.defaults)
  self.sections.each_key do |section_key|
    if other.sections.has_key?(section_key)
      self.sections[section_key].overwrite_defaults(other.sections[section_key])
    end
  end
end

#parameter_configuration(name, type = nil, **kwargs, &block) ⇒ Object



249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/fluent/config/configure_proxy.rb', line 249

def parameter_configuration(name, type = nil, **kwargs, &block)
  config_parameter_option_validate!(name, type, **kwargs, &block)

  name = name.to_sym

  if block && type
    raise ArgumentError, "#{name}: both of block and type cannot be specified"
  elsif !block && !type
    type = :string
  end
  opts = {}
  opts[:type] = type
  opts.merge!(kwargs)

  begin
    block ||= @type_lookup.call(type)
  rescue ConfigError
    # override error message
    raise ArgumentError, "#{name}: unknown config_argument type `#{type}'"
  end

  # options for config_param
  option_value_type!(name, opts, :desc, String)
  option_value_type!(name, opts, :alias, Symbol)
  option_value_type!(name, opts, :secret, type: :boolean)
  option_value_type!(name, opts, :deprecated, String)
  option_value_type!(name, opts, :obsoleted, String)
  if type == :enum
    if !opts.has_key?(:list) || !opts[:list].is_a?(Array) || opts[:list].empty? || !opts[:list].all?(Symbol)
      raise ArgumentError, "#{name}: enum parameter requires :list of Symbols"
    end
  end
  option_value_type!(name, opts, :symbolize_keys, type: :boolean)
  option_value_type!(name, opts, :value_type, Symbol) # hash, array
  option_value_type!(name, opts, :skip_accessor, type: :boolean)

  if opts.has_key?(:default)
    config_set_default(name, opts[:default])
  end

  if opts.has_key?(:desc)
    config_set_desc(name, opts[:desc])
  end

  if opts[:deprecated] && opts[:obsoleted]
    raise ArgumentError, "#{name}: both of deprecated and obsoleted cannot be specified at once"
  end

  [name, block, opts]
end

#required?Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/fluent/config/configure_proxy.rb', line 84

def required?
  @required.nil? ? false : @required
end

#root?Boolean

Returns:

  • (Boolean)


76
77
78
# File 'lib/fluent/config/configure_proxy.rb', line 76

def root?
  @root_section
end

#variable_nameObject



72
73
74
# File 'lib/fluent/config/configure_proxy.rb', line 72

def variable_name
  @param_name || @name
end