# # Fluentd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'json' require 'fluent/config' require 'fluent/config/element' module Fluent module Config module DSL module Parser def self.read(path) path = File.expand_path(path) data = File.read(path) parse(data, path) end def self.parse(source, source_path="config.rb") Proxy.new('ROOT', nil).eval(source, source_path).to_config_element end end class Proxy def initialize(name, arg) @element = Element.new(name, arg, self) end def element @element end def eval(source, source_path) @element.instance_eval(source, source_path) self end def to_config_element @element.instance_eval do Config::Element.new(@name, @arg, @attrs, @elements) end end def add_element(name, arg, block) ::Kernel.raise ::ArgumentError, "#{name} block must be specified" if block.nil? proxy = self.class.new(name.to_s, arg) proxy.element.instance_exec(&block) @element.instance_eval do @elements.push(proxy.to_config_element) end self end end class Element < BasicObject def initialize(name, arg, proxy) @name = name @arg = arg || '' @attrs = {} @elements = [] @proxy = proxy end def method_missing(name, *args, &block) ::Kernel.raise ::ArgumentError, "Configuration DSL Syntax Error: only one argument allowed" if args.size > 1 value = args.first if block proxy = Proxy.new(name.to_s, value) proxy.element.instance_exec(&block) @elements.push(proxy.to_config_element) else @attrs[name.to_s] = if value.is_a?(Array) || value.is_a?(Hash) JSON.dump(value) else value.to_s end end self end def source(&block) @proxy.add_element('source', nil, block) end def match(*args, &block) ::Kernel.raise ::ArgumentError, "#{name} block requires arguments for match pattern" if args.nil? || args.size != 1 @proxy.add_element('match', args.first, block) end def self.const_missing(name) return ::Kernel.const_get(name) if ::Kernel.const_defined?(name) if name.to_s =~ /^Fluent::Config::DSL::Element::(.*)$/ name = "#{$1}".to_sym return ::Kernel.const_get(name) if ::Kernel.const_defined?(name) end ::Kernel.eval("#{name}") end def ruby(&block) if block @proxy.instance_exec(&block) else ::Kernel end end end end end end