Add Fluentd::Agent::Common#parse_config

Signed-off-by: Kenji Okimoto <okimoto@clear-code.com>
This commit is contained in:
Kenji Okimoto 2018-09-13 12:20:37 +09:00
parent 7615eaeb0b
commit 5a31d9b9d0
No known key found for this signature in database
GPG Key ID: F9E3E329A5C5E4A1
3 changed files with 209 additions and 0 deletions

View File

@ -18,6 +18,8 @@
# - https://github.com/treasure-data/omnibus-td-agent/blob/master/templates/etc/systemd/td-agent.service.erb#L14
# fluentd: /etc/fluent/fluent.conf (created by fluentd -s)
require "strscan"
class Fluentd
class Agent
module Common
@ -142,6 +144,39 @@ class Fluentd
FileUtils.rm(file) if File.exist? file
end
end
def parse_config(config_content)
scanner = StringScanner.new(config_content)
contents = Hash.new {|h, k| h[k] = [] }
until scanner.eos? do
started = scanner.pos
header = scanner.scan_until(/^<(source|filter|match|label)/)
section_type = scanner[1]
break unless header
case section_type
when "source", "filter", "match"
current_source = header + scanner.scan_until(%r{^</(?:source|filter|match)>})
contents[section_type] << { pos: started, content: current_source.strip }
when "label"
scanner.scan(/ ([^\s]+?)>/)
label = scanner[1]
sections = Hash.new {|h, k| h[k] = [] }
loop do
break if scanner.match?(%r{\s+?</label>})
section_pos = scanner.pos
section_header = scanner.scan_until(/^\s*<(filter|match)/)
section_type = scanner[1]
section_source = section_header + scanner.scan_until(%r{^\s*</(?:filter|match)>})
sections[section_type] << { pos: section_pos ,content: section_source.sub(/\n/, "")}
end
scanner.scan_until(%r{^</label>})
contents["label:#{label}"] << { pos: started, sections: sections }
else
raise TypeError, "Unknown section: #{started}: #{section_type}"
end
end
contents
end
end
end
end

View File

@ -0,0 +1,170 @@
require "test_helper"
class Fluentd
class TestAgentCommon < ActiveSupport::TestCase
class DummyAgent
include ::Fluentd::Agent::Common
end
setup do
@agent = DummyAgent.new
end
sub_test_case "#parse_config" do
test "empty" do
actual = @agent.__send__(:parse_config, "")
assert_equal({}, actual)
end
test "simple" do
actual = @agent.__send__(:parse_config, fixture_content("config/simple.conf"))
source_section_content = <<-CONFIG.strip_heredoc.chomp
<source>
@type dummy
tag dummy
</source>
CONFIG
filter_section_content = <<-CONFIG.strip_heredoc.chomp
<filter dummy>
@type stdout
</filter>
CONFIG
match_section_content = <<-CONFIG.strip_heredoc.chomp
<match dummy>
@type stdout
</match>
CONFIG
expected = {
"source" => [
{ pos: 0, content: source_section_content }
],
"filter" => [
{ pos: 44, content: filter_section_content }
],
"match" => [
{ pos: 84, content: match_section_content }
]
}
assert_equal(expected, actual)
end
test "simple label" do
actual = @agent.__send__(:parse_config, fixture_content("config/label.conf"))
source_section_content = <<-CONFIG.strip_heredoc.chomp
<source>
@type dummy
tag dummy
@label @INPUT
</source>
CONFIG
filter_section_content = <<-CONFIG.chomp
<filter dummy>
@type stdout
</filter>
CONFIG
match_section_content = <<-CONFIG.chomp
<match dummy>
@type stdout
</match>
CONFIG
sections = {
"filter" => [
{ pos: 75, content: filter_section_content}
],
"match" => [
{ pos: 121, content: match_section_content}
]
}
expected = {
"source" => [
{ pos: 0, content: source_section_content }
],
"label:@INPUT" => [
{ pos: 60, sections: sections }
]
}
assert_equal(expected, actual)
end
test "multiple labels" do
actual = @agent.__send__(:parse_config, fixture_content("config/multi-label.conf"))
source_section_content1 = <<-CONFIG.strip_heredoc.chomp
<source>
@type dummy
tag dummy1
@label @INPUT
</source>
CONFIG
source_section_content2 = <<-CONFIG.strip_heredoc.chomp
<source>
@type dummy
tag dummy2
@label @INPUT
</source>
CONFIG
filter_section_content = <<-CONFIG.chomp
<filter dummy1>
@type stdout
</filter>
CONFIG
match_section_content = <<-CONFIG.chomp
<match dummy1>
@type relabel
@label @MAIN
</match>
CONFIG
input_sections = {
"filter" => [
{ pos: 140, content: filter_section_content }
],
"match" => [
{ pos: 187, content: match_section_content }
]
}
filter_secion_content1 = <<-CONFIG.chomp
<filter dummy1>
@type stdout
</filter>
CONFIG
filter_secion_content2 = <<-CONFIG.chomp
<filter dummy2>
@type stdout
</filter>
CONFIG
match_secion_content1 = <<-CONFIG.chomp
<match dummy1>
@type stdout
</match>
CONFIG
match_secion_content2 = <<-CONFIG.chomp
<match dummy2>
@type stdout
</match>
CONFIG
main_sections = {
"filter" => [
{ pos: 274, content: filter_secion_content1 },
{ pos: 321, content: filter_secion_content2 }
],
"match" => [
{ pos: 368, content: match_secion_content1 },
{ pos: 413, content: match_secion_content2 }
]
}
expected = {
"source" => [
{ pos: 0, content: source_section_content1 },
{ pos: 61, content: source_section_content2 },
],
"label:@INPUT" => [
{ pos: 124, sections: input_sections }
],
"label:@MAIN" => [
{ pos: 259, sections: main_sections }
]
}
assert_equal(expected, actual)
end
end
end
end

View File

@ -18,6 +18,10 @@ module FixturePath
def fixture_path(fixture_name)
Rails.root.join("test/fixtures", fixture_name).to_s
end
def fixture_content(fixture_name)
Rails.root.join("test/fixtures", fixture_name).read
end
end
class ActiveSupport::TestCase