diff --git a/lib/fluent/plugin/in_tail.rb b/lib/fluent/plugin/in_tail.rb index 63ec165b96..0f9c3865dd 100644 --- a/lib/fluent/plugin/in_tail.rb +++ b/lib/fluent/plugin/in_tail.rb @@ -146,6 +146,10 @@ def configure(conf) raise Fluent::ConfigError, "cannot use glob_policy as always with the default path_delimitor: `,\"" end + if @glob_policy == :extended && /\{.*,.*\}/.match(@path) && extended_glob_pattern(@path) + raise Fluent::ConfigError, "cannot include curly braces with glob patterns in `#{@path}\". Use glob_policy always instead." + end + if RESERVED_CHARS.include?(@path_delimiter) rc = RESERVED_CHARS.join(', ') raise Fluent::ConfigError, "#{rc} are reserved words: #{@path_delimiter}" @@ -289,13 +293,17 @@ def have_read_capability? @capability.have_capability?(:effective, :dac_override) end + def extended_glob_pattern(path) + path.include?('*') || path.include?('?') || /\[.*\]/.match(path) + end + # Curly braces is not supported for now because the default delimiter of path is ",". # This should be collided for wildcard pattern for curly braces. def use_glob?(path) if @glob_policy == :always - path.include?('*') || path.include?('?') || /\[.*\]/.match(path) || /\{.*,.*\}/.match(path) + extended_glob_pattern(path) || /\{.*,.*\}/.match(path) elsif @glob_policy == :extended - path.include?('*') || path.include?('?') || /\[.*\]/.match(path) + extended_glob_pattern(path) elsif @glob_policy == :backward_compatible path.include?('*') end diff --git a/test/plugin/test_in_tail.rb b/test/plugin/test_in_tail.rb index 296386ffc6..7b302ab595 100644 --- a/test/plugin/test_in_tail.rb +++ b/test/plugin/test_in_tail.rb @@ -1540,11 +1540,12 @@ def test_expand_paths sub_test_case "expand_paths with glob" do |data| sub_test_case "extended_glob" do - data("square brackets" => [true, "extended", "test/plugin/data/log_numeric/[0-1][2-4].log"], - "asterisk" => [true, "extended", "test/plugin/data/log/*.log"], - "one character matcher" => [true, "extended", "test/plugin/data/log/tes?.log"], + data("curly braces" => [true, "always", "test/plugin/data/log_numeric/{0,1}*.log"], + "square brackets" => [true, "always", "test/plugin/data/log_numeric/[0-1][2-4].log"], + "asterisk" => [true, "always", "test/plugin/data/log/*.log"], + "one character matcher" => [true, "always", "test/plugin/data/log/tes?.log"], ) - def test_expand_paths_with_use_glob_p + def test_expand_paths_with_use_glob_p_and_almost_set_of_patterns result, option, path = data config = config_element("", "", { "tag" => "tail", @@ -1554,12 +1555,41 @@ def test_expand_paths_with_use_glob_p "read_from_head" => true, "refresh_interval" => 30, "glob_policy" => option, + "path_delimiter" => "|", "rotate_wait" => "#{EX_ROTATE_WAIT}s", "follow_inodes" => "#{EX_FOLLOW_INODES}", }) plugin = create_driver(config, false).instance assert_equal(result, !!plugin.use_glob?(path)) end + + data("curly braces" => [true, false, "extended", "test/plugin/data/log_numeric/{0,1}*.log"], + "square brackets" => [false, true, "extended", "test/plugin/data/log_numeric/[0-1][2-4].log"], + "asterisk" => [false, true, "extended", "test/plugin/data/log/*.log"], + "one character matcher" => [false, true, "extended", "test/plugin/data/log/tes?.log"], + ) + def test_expand_paths_with_use_glob_p + emit_exception_p, result, option, path = data + config = config_element("", "", { + "tag" => "tail", + "path" => path, + "format" => "none", + "pos_file" => "#{@tmp_dir}/tail.pos", + "read_from_head" => true, + "refresh_interval" => 30, + "glob_policy" => option, + "rotate_wait" => "#{EX_ROTATE_WAIT}s", + "follow_inodes" => "#{EX_FOLLOW_INODES}", + }) + if emit_exception_p + assert_raise(Fluent::ConfigError) do + plugin = create_driver(config, false).instance + end + else + plugin = create_driver(config, false).instance + assert_equal(result, !!plugin.use_glob?(path)) + end + end end sub_test_case "only_use_backward_compatible" do