From 6f8d7945d03234f2d7f09721a53be51ac07daffe Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Wed, 14 Feb 2024 17:29:00 +0900 Subject: [PATCH 01/13] in_tail: Support bracket pattern on path parameter Signed-off-by: Hiroshi Hatake --- lib/fluent/plugin/in_tail.rb | 2 +- test/plugin/data/log_numeric/01.log | 0 test/plugin/data/log_numeric/02.log | 0 test/plugin/data/log_numeric/12.log | 0 test/plugin/data/log_numeric/14.log | 0 test/plugin/test_in_tail.rb | 25 +++++++++++++++++++++++++ 6 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 test/plugin/data/log_numeric/01.log create mode 100644 test/plugin/data/log_numeric/02.log create mode 100644 test/plugin/data/log_numeric/12.log create mode 100644 test/plugin/data/log_numeric/14.log diff --git a/lib/fluent/plugin/in_tail.rb b/lib/fluent/plugin/in_tail.rb index 44761b4061..31b6228218 100644 --- a/lib/fluent/plugin/in_tail.rb +++ b/lib/fluent/plugin/in_tail.rb @@ -292,7 +292,7 @@ def expand_paths else date.to_time.strftime(path) end - if path.include?('*') + if path.include?('*') || /\[.*\]/.match(path) paths += Dir.glob(path).select { |p| begin is_file = !File.directory?(p) diff --git a/test/plugin/data/log_numeric/01.log b/test/plugin/data/log_numeric/01.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/plugin/data/log_numeric/02.log b/test/plugin/data/log_numeric/02.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/plugin/data/log_numeric/12.log b/test/plugin/data/log_numeric/12.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/plugin/data/log_numeric/14.log b/test/plugin/data/log_numeric/14.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/plugin/test_in_tail.rb b/test/plugin/test_in_tail.rb index 8919866683..2cc035178e 100644 --- a/test/plugin/test_in_tail.rb +++ b/test/plugin/test_in_tail.rb @@ -1538,6 +1538,31 @@ def test_expand_paths assert_equal(ex_paths - [ex_paths.last], plugin.expand_paths.values.sort_by { |path_ino| path_ino.path }) end + def ex_config_with_brackets + config_element("", "", { + "tag" => "tail", + "path" => "test/plugin/data/log_numeric/[0-1][2-4].log", + "format" => "none", + "pos_file" => "#{@tmp_dir}/tail.pos", + "read_from_head" => true, + "refresh_interval" => 30, + "rotate_wait" => "#{EX_ROTATE_WAIT}s", + "follow_inodes" => "#{EX_FOLLOW_INODES}", + }) + end + + def test_expand_paths_with_brackets + expanded_paths = [ + create_target_info('test/plugin/data/log_numeric/01.log'), + create_target_info('test/plugin/data/log_numeric/02.log'), + create_target_info('test/plugin/data/log_numeric/12.log'), + create_target_info('test/plugin/data/log_numeric/14.log'), + ] + + plugin = create_driver(ex_config_with_brackets, false).instance + assert_equal(expanded_paths - [expanded_paths.first], plugin.expand_paths.values.sort_by { |path_ino| path_ino.path }) + end + def test_expand_paths_with_duplicate_configuration expanded_paths = [ create_target_info('test/plugin/data/log/foo/bar.log'), From 0e1707b29051ab366cf597d26d9da5c6e6703c4a Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 15 Feb 2024 11:39:28 +0900 Subject: [PATCH 02/13] in_tail: test: Expand glob capability Signed-off-by: Hiroshi Hatake --- lib/fluent/plugin/in_tail.rb | 8 +++++++- test/plugin/test_in_tail.rb | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/fluent/plugin/in_tail.rb b/lib/fluent/plugin/in_tail.rb index 31b6228218..c9138ed84b 100644 --- a/lib/fluent/plugin/in_tail.rb +++ b/lib/fluent/plugin/in_tail.rb @@ -283,6 +283,12 @@ def have_read_capability? @capability.have_capability?(:effective, :dac_override) 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) + path.include?('*') || path.include?('?') || /\[.*\]/.match(path) + end + def expand_paths date = Fluent::EventTime.now paths = [] @@ -292,7 +298,7 @@ def expand_paths else date.to_time.strftime(path) end - if path.include?('*') || /\[.*\]/.match(path) + if use_glob?(path) paths += Dir.glob(path).select { |p| begin is_file = !File.directory?(p) diff --git a/test/plugin/test_in_tail.rb b/test/plugin/test_in_tail.rb index 2cc035178e..d6cfb36902 100644 --- a/test/plugin/test_in_tail.rb +++ b/test/plugin/test_in_tail.rb @@ -1538,6 +1538,28 @@ def test_expand_paths assert_equal(ex_paths - [ex_paths.last], plugin.expand_paths.values.sort_by { |path_ino| path_ino.path }) end + sub_test_case "expand_paths with glob" do |data| + data("square brackets" => "test/plugin/data/log_numeric/[0-1][2-4].log", + "asterisk" => "test/plugin/data/log/*.log", + "one character matcher" => "test/plugin/data/log/tes?.log", + ) + def test_expand_paths_with_use_glob_p + path = data + config = config_element("", "", { + "tag" => "tail", + "path" => path, + "format" => "none", + "pos_file" => "#{@tmp_dir}/tail.pos", + "read_from_head" => true, + "refresh_interval" => 30, + "rotate_wait" => "#{EX_ROTATE_WAIT}s", + "follow_inodes" => "#{EX_FOLLOW_INODES}", + }) + plugin = create_driver(config, false).instance + assert_true(!!plugin.use_glob?(path)) + end + end + def ex_config_with_brackets config_element("", "", { "tag" => "tail", From 5f02c39c24453f09f0a09d022e3ba7ec6ece1ffb Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 15 Feb 2024 12:35:25 +0900 Subject: [PATCH 03/13] in_tail: Preserve backward compatiblity for glob This is because square brackets are permitted to use filename in macOS and Windows. So, we need to take care of. Signed-off-by: Hiroshi Hatake --- lib/fluent/plugin/in_tail.rb | 8 +++++++- test/plugin/test_in_tail.rb | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/fluent/plugin/in_tail.rb b/lib/fluent/plugin/in_tail.rb index c9138ed84b..a494b1befb 100644 --- a/lib/fluent/plugin/in_tail.rb +++ b/lib/fluent/plugin/in_tail.rb @@ -64,6 +64,8 @@ def initialize config_param :path, :string desc 'path delimiter used for spliting path config' config_param :path_delimiter, :string, default: ',' + desc 'Use extended glob patterns. Adding a capability to handle [] and ?.' + config_param :use_extended_glob, :bool, default: false desc 'The tag of the event.' config_param :tag, :string desc 'The paths to exclude the files from watcher list.' @@ -286,7 +288,11 @@ def have_read_capability? # 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) - path.include?('*') || path.include?('?') || /\[.*\]/.match(path) + if @use_extended_glob + path.include?('*') || path.include?('?') || /\[.*\]/.match(path) + else + path.include?('*') + end end def expand_paths diff --git a/test/plugin/test_in_tail.rb b/test/plugin/test_in_tail.rb index d6cfb36902..5e00df0f17 100644 --- a/test/plugin/test_in_tail.rb +++ b/test/plugin/test_in_tail.rb @@ -1552,6 +1552,7 @@ def test_expand_paths_with_use_glob_p "pos_file" => "#{@tmp_dir}/tail.pos", "read_from_head" => true, "refresh_interval" => 30, + "use_extended_glob" => true, "rotate_wait" => "#{EX_ROTATE_WAIT}s", "follow_inodes" => "#{EX_FOLLOW_INODES}", }) @@ -1568,6 +1569,7 @@ def ex_config_with_brackets "pos_file" => "#{@tmp_dir}/tail.pos", "read_from_head" => true, "refresh_interval" => 30, + "use_extended_glob" => true, "rotate_wait" => "#{EX_ROTATE_WAIT}s", "follow_inodes" => "#{EX_FOLLOW_INODES}", }) From b5a71848ef1143bf9fc04392b2660ed9cb330a39 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 15 Feb 2024 12:44:05 +0900 Subject: [PATCH 04/13] in_tail: Add test case for checking behavior of backward compatibility Signed-off-by: Hiroshi Hatake --- test/plugin/test_in_tail.rb | 63 ++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/test/plugin/test_in_tail.rb b/test/plugin/test_in_tail.rb index 5e00df0f17..d74876ae36 100644 --- a/test/plugin/test_in_tail.rb +++ b/test/plugin/test_in_tail.rb @@ -1539,25 +1539,50 @@ def test_expand_paths end sub_test_case "expand_paths with glob" do |data| - data("square brackets" => "test/plugin/data/log_numeric/[0-1][2-4].log", - "asterisk" => "test/plugin/data/log/*.log", - "one character matcher" => "test/plugin/data/log/tes?.log", - ) - def test_expand_paths_with_use_glob_p - path = data - config = config_element("", "", { - "tag" => "tail", - "path" => path, - "format" => "none", - "pos_file" => "#{@tmp_dir}/tail.pos", - "read_from_head" => true, - "refresh_interval" => 30, - "use_extended_glob" => true, - "rotate_wait" => "#{EX_ROTATE_WAIT}s", - "follow_inodes" => "#{EX_FOLLOW_INODES}", - }) - plugin = create_driver(config, false).instance - assert_true(!!plugin.use_glob?(path)) + sub_test_case "use_extended_glob" do + data("square brackets" => [true, "test/plugin/data/log_numeric/[0-1][2-4].log"], + "asterisk" => [true, "test/plugin/data/log/*.log"], + "one character matcher" => [true, "test/plugin/data/log/tes?.log"], + ) + def test_expand_paths_with_use_glob_p + result, path = data + config = config_element("", "", { + "tag" => "tail", + "path" => path, + "format" => "none", + "pos_file" => "#{@tmp_dir}/tail.pos", + "read_from_head" => true, + "refresh_interval" => 30, + "use_extended_glob" => true, + "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 + end + + sub_test_case "only_use_normal_glob" do + data("square brackets" => [false, "test/plugin/data/log_numeric/[0-1][2-4].log"], + "asterisk" => [true, "test/plugin/data/log/*.log"], + "one character matcher" => [false, "test/plugin/data/log/tes?.log"], + ) + def test_expand_paths_with_use_glob_p + result, path = data + config = config_element("", "", { + "tag" => "tail", + "path" => path, + "format" => "none", + "pos_file" => "#{@tmp_dir}/tail.pos", + "read_from_head" => true, + "refresh_interval" => 30, + "use_extended_glob" => false, + "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 end end From 63cf6af8cbc54fb30e8d1535e86dc39ed71cd3b6 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Mon, 25 Mar 2024 20:00:57 +0900 Subject: [PATCH 05/13] in_tail: test: Provide enable_glob parameter as enum type option Signed-off-by: Hiroshi Hatake --- lib/fluent/plugin/in_tail.rb | 9 ++++++--- test/plugin/test_in_tail.rb | 26 +++++++++++++------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/lib/fluent/plugin/in_tail.rb b/lib/fluent/plugin/in_tail.rb index a494b1befb..b600e611d9 100644 --- a/lib/fluent/plugin/in_tail.rb +++ b/lib/fluent/plugin/in_tail.rb @@ -65,7 +65,7 @@ def initialize desc 'path delimiter used for spliting path config' config_param :path_delimiter, :string, default: ',' desc 'Use extended glob patterns. Adding a capability to handle [] and ?.' - config_param :use_extended_glob, :bool, default: false + config_param :enable_glob, :enum, list: [:with_wildcards, :extended, :no], default: :with_wildcards desc 'The tag of the event.' config_param :tag, :string desc 'The paths to exclude the files from watcher list.' @@ -288,10 +288,13 @@ def have_read_capability? # 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 @use_extended_glob + if @enable_glob == :extended path.include?('*') || path.include?('?') || /\[.*\]/.match(path) - else + elsif @enable_glob == :with_wildcards path.include?('*') + elsif @enable_glob == :no + # Always return false when glob is turned off. + false end end diff --git a/test/plugin/test_in_tail.rb b/test/plugin/test_in_tail.rb index d74876ae36..7be51a1f39 100644 --- a/test/plugin/test_in_tail.rb +++ b/test/plugin/test_in_tail.rb @@ -1539,13 +1539,13 @@ def test_expand_paths end sub_test_case "expand_paths with glob" do |data| - sub_test_case "use_extended_glob" do - data("square brackets" => [true, "test/plugin/data/log_numeric/[0-1][2-4].log"], - "asterisk" => [true, "test/plugin/data/log/*.log"], - "one character matcher" => [true, "test/plugin/data/log/tes?.log"], + 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"], ) def test_expand_paths_with_use_glob_p - result, path = data + result, option, path = data config = config_element("", "", { "tag" => "tail", "path" => path, @@ -1553,7 +1553,7 @@ def test_expand_paths_with_use_glob_p "pos_file" => "#{@tmp_dir}/tail.pos", "read_from_head" => true, "refresh_interval" => 30, - "use_extended_glob" => true, + "enable_glob" => option, "rotate_wait" => "#{EX_ROTATE_WAIT}s", "follow_inodes" => "#{EX_FOLLOW_INODES}", }) @@ -1562,13 +1562,13 @@ def test_expand_paths_with_use_glob_p end end - sub_test_case "only_use_normal_glob" do - data("square brackets" => [false, "test/plugin/data/log_numeric/[0-1][2-4].log"], - "asterisk" => [true, "test/plugin/data/log/*.log"], - "one character matcher" => [false, "test/plugin/data/log/tes?.log"], + sub_test_case "only_use_with_wildcards" do + data("square brackets" => [false, "with_wildcards", "test/plugin/data/log_numeric/[0-1][2-4].log"], + "asterisk" => [true, "with_wildcards", "test/plugin/data/log/*.log"], + "one character matcher" => [false, "with_wildcards", "test/plugin/data/log/tes?.log"], ) def test_expand_paths_with_use_glob_p - result, path = data + result, option, path = data config = config_element("", "", { "tag" => "tail", "path" => path, @@ -1576,7 +1576,7 @@ def test_expand_paths_with_use_glob_p "pos_file" => "#{@tmp_dir}/tail.pos", "read_from_head" => true, "refresh_interval" => 30, - "use_extended_glob" => false, + "enable_glob" => option, "rotate_wait" => "#{EX_ROTATE_WAIT}s", "follow_inodes" => "#{EX_FOLLOW_INODES}", }) @@ -1594,7 +1594,7 @@ def ex_config_with_brackets "pos_file" => "#{@tmp_dir}/tail.pos", "read_from_head" => true, "refresh_interval" => 30, - "use_extended_glob" => true, + "enable_glob" => "extended", "rotate_wait" => "#{EX_ROTATE_WAIT}s", "follow_inodes" => "#{EX_FOLLOW_INODES}", }) From 926a700f445568b7393d6dd04fbcf6528ef80028 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Mon, 25 Mar 2024 20:24:55 +0900 Subject: [PATCH 06/13] in_tail: Handle specified glob patterns which set up by enable_glob in exclude paths Signed-off-by: Hiroshi Hatake --- lib/fluent/plugin/in_tail.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fluent/plugin/in_tail.rb b/lib/fluent/plugin/in_tail.rb index b600e611d9..3db4605065 100644 --- a/lib/fluent/plugin/in_tail.rb +++ b/lib/fluent/plugin/in_tail.rb @@ -342,7 +342,7 @@ def expand_paths else date.to_time.strftime(path) end - path.include?('*') ? Dir.glob(path) : path + use_glob?(path) ? Dir.glob(path) : path }.flatten.uniq # filter out non existing files, so in case pattern is without '*' we don't do unnecessary work hash = {} From 1b478b29c24072b5eda625275ede3ce7ee5803a9 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Tue, 26 Mar 2024 14:07:16 +0900 Subject: [PATCH 07/13] in_tail: Remove :no option from enable_glob Signed-off-by: Hiroshi Hatake --- lib/fluent/plugin/in_tail.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/fluent/plugin/in_tail.rb b/lib/fluent/plugin/in_tail.rb index 3db4605065..38ead3d13c 100644 --- a/lib/fluent/plugin/in_tail.rb +++ b/lib/fluent/plugin/in_tail.rb @@ -64,8 +64,8 @@ def initialize config_param :path, :string desc 'path delimiter used for spliting path config' config_param :path_delimiter, :string, default: ',' - desc 'Use extended glob patterns. Adding a capability to handle [] and ?.' - config_param :enable_glob, :enum, list: [:with_wildcards, :extended, :no], default: :with_wildcards + desc 'Choose using glob patterns. Adding whether a capability to handle [] and ? or not.' + config_param :enable_glob, :enum, list: [:with_wildcards, :extended], default: :with_wildcards desc 'The tag of the event.' config_param :tag, :string desc 'The paths to exclude the files from watcher list.' @@ -292,9 +292,6 @@ def use_glob?(path) path.include?('*') || path.include?('?') || /\[.*\]/.match(path) elsif @enable_glob == :with_wildcards path.include?('*') - elsif @enable_glob == :no - # Always return false when glob is turned off. - false end end From 2d6c6cfae3b79337a338ddb6d50abdf7d2b27198 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Tue, 26 Mar 2024 14:58:28 +0900 Subject: [PATCH 08/13] in_tail: Use always instead of extended to prepare future extending Signed-off-by: Hiroshi Hatake --- lib/fluent/plugin/in_tail.rb | 4 ++-- test/plugin/test_in_tail.rb | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/fluent/plugin/in_tail.rb b/lib/fluent/plugin/in_tail.rb index 38ead3d13c..e4b812ce70 100644 --- a/lib/fluent/plugin/in_tail.rb +++ b/lib/fluent/plugin/in_tail.rb @@ -65,7 +65,7 @@ def initialize desc 'path delimiter used for spliting path config' config_param :path_delimiter, :string, default: ',' desc 'Choose using glob patterns. Adding whether a capability to handle [] and ? or not.' - config_param :enable_glob, :enum, list: [:with_wildcards, :extended], default: :with_wildcards + config_param :enable_glob, :enum, list: [:with_wildcards, :always], default: :with_wildcards desc 'The tag of the event.' config_param :tag, :string desc 'The paths to exclude the files from watcher list.' @@ -288,7 +288,7 @@ def have_read_capability? # 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 @enable_glob == :extended + if @enable_glob == :always path.include?('*') || path.include?('?') || /\[.*\]/.match(path) elsif @enable_glob == :with_wildcards path.include?('*') diff --git a/test/plugin/test_in_tail.rb b/test/plugin/test_in_tail.rb index 7be51a1f39..7c48614d77 100644 --- a/test/plugin/test_in_tail.rb +++ b/test/plugin/test_in_tail.rb @@ -1540,9 +1540,9 @@ 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("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 result, option, path = data @@ -1594,7 +1594,7 @@ def ex_config_with_brackets "pos_file" => "#{@tmp_dir}/tail.pos", "read_from_head" => true, "refresh_interval" => 30, - "enable_glob" => "extended", + "enable_glob" => "always", "rotate_wait" => "#{EX_ROTATE_WAIT}s", "follow_inodes" => "#{EX_FOLLOW_INODES}", }) From 705d5eaa916ccb95aa5ed6012a6adfa8ca39d122 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Tue, 26 Mar 2024 18:30:32 +0900 Subject: [PATCH 09/13] in_tail: Address comments Signed-off-by: Hiroshi Hatake --- lib/fluent/plugin/in_tail.rb | 6 +++--- test/plugin/test_in_tail.rb | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/fluent/plugin/in_tail.rb b/lib/fluent/plugin/in_tail.rb index e4b812ce70..f3dcff4cf1 100644 --- a/lib/fluent/plugin/in_tail.rb +++ b/lib/fluent/plugin/in_tail.rb @@ -65,7 +65,7 @@ def initialize desc 'path delimiter used for spliting path config' config_param :path_delimiter, :string, default: ',' desc 'Choose using glob patterns. Adding whether a capability to handle [] and ? or not.' - config_param :enable_glob, :enum, list: [:with_wildcards, :always], default: :with_wildcards + config_param :glob_policy, :enum, list: [:backward_compatible, :extended], default: :backward_compatible desc 'The tag of the event.' config_param :tag, :string desc 'The paths to exclude the files from watcher list.' @@ -288,9 +288,9 @@ def have_read_capability? # 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 @enable_glob == :always + if @glob_policy == :extended path.include?('*') || path.include?('?') || /\[.*\]/.match(path) - elsif @enable_glob == :with_wildcards + elsif @glob_policy == :backward_compatible path.include?('*') end end diff --git a/test/plugin/test_in_tail.rb b/test/plugin/test_in_tail.rb index 7c48614d77..3e612ce55d 100644 --- a/test/plugin/test_in_tail.rb +++ b/test/plugin/test_in_tail.rb @@ -1540,9 +1540,9 @@ def test_expand_paths sub_test_case "expand_paths with glob" do |data| sub_test_case "extended_glob" do - data("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"], + 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"], ) def test_expand_paths_with_use_glob_p result, option, path = data @@ -1553,7 +1553,7 @@ def test_expand_paths_with_use_glob_p "pos_file" => "#{@tmp_dir}/tail.pos", "read_from_head" => true, "refresh_interval" => 30, - "enable_glob" => option, + "glob_policy" => option, "rotate_wait" => "#{EX_ROTATE_WAIT}s", "follow_inodes" => "#{EX_FOLLOW_INODES}", }) @@ -1562,10 +1562,10 @@ def test_expand_paths_with_use_glob_p end end - sub_test_case "only_use_with_wildcards" do - data("square brackets" => [false, "with_wildcards", "test/plugin/data/log_numeric/[0-1][2-4].log"], - "asterisk" => [true, "with_wildcards", "test/plugin/data/log/*.log"], - "one character matcher" => [false, "with_wildcards", "test/plugin/data/log/tes?.log"], + sub_test_case "only_use_backward_compatible" do + data("square brackets" => [false, "backward_compatible", "test/plugin/data/log_numeric/[0-1][2-4].log"], + "asterisk" => [true, "backward_compatible", "test/plugin/data/log/*.log"], + "one character matcher" => [false, "backward_compatible", "test/plugin/data/log/tes?.log"], ) def test_expand_paths_with_use_glob_p result, option, path = data @@ -1576,7 +1576,7 @@ def test_expand_paths_with_use_glob_p "pos_file" => "#{@tmp_dir}/tail.pos", "read_from_head" => true, "refresh_interval" => 30, - "enable_glob" => option, + "glob_policy" => option, "rotate_wait" => "#{EX_ROTATE_WAIT}s", "follow_inodes" => "#{EX_FOLLOW_INODES}", }) @@ -1594,7 +1594,7 @@ def ex_config_with_brackets "pos_file" => "#{@tmp_dir}/tail.pos", "read_from_head" => true, "refresh_interval" => 30, - "enable_glob" => "always", + "glob_policy" => "extended", "rotate_wait" => "#{EX_ROTATE_WAIT}s", "follow_inodes" => "#{EX_FOLLOW_INODES}", }) From 3ab56cc7d6c43969850a9f4da99e59dff3454030 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Tue, 26 Mar 2024 18:58:01 +0900 Subject: [PATCH 10/13] in_tail: Add always option for handle most of the glob patterns I'm, not sure this commit makes to be able to handle the all of the glob patterns but mostly seems OK. Signed-off-by: Hiroshi Hatake --- lib/fluent/plugin/in_tail.rb | 12 +++++++++--- test/plugin/test_in_tail.rb | 37 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/lib/fluent/plugin/in_tail.rb b/lib/fluent/plugin/in_tail.rb index f3dcff4cf1..63ec165b96 100644 --- a/lib/fluent/plugin/in_tail.rb +++ b/lib/fluent/plugin/in_tail.rb @@ -64,8 +64,8 @@ def initialize config_param :path, :string desc 'path delimiter used for spliting path config' config_param :path_delimiter, :string, default: ',' - desc 'Choose using glob patterns. Adding whether a capability to handle [] and ? or not.' - config_param :glob_policy, :enum, list: [:backward_compatible, :extended], default: :backward_compatible + desc 'Choose using glob patterns. Adding capabilities to handle [] and ?, and {}.' + config_param :glob_policy, :enum, list: [:backward_compatible, :extended, :always], default: :backward_compatible desc 'The tag of the event.' config_param :tag, :string desc 'The paths to exclude the files from watcher list.' @@ -142,6 +142,10 @@ def configure(conf) raise Fluent::ConfigError, "either of enable_watch_timer or enable_stat_watcher must be true" end + if @glob_policy == :always && @path_delimiter == ',' + raise Fluent::ConfigError, "cannot use glob_policy as always with the default path_delimitor: `,\"" + end + if RESERVED_CHARS.include?(@path_delimiter) rc = RESERVED_CHARS.join(', ') raise Fluent::ConfigError, "#{rc} are reserved words: #{@path_delimiter}" @@ -288,7 +292,9 @@ def have_read_capability? # 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 == :extended + if @glob_policy == :always + path.include?('*') || path.include?('?') || /\[.*\]/.match(path) || /\{.*,.*\}/.match(path) + elsif @glob_policy == :extended path.include?('*') || path.include?('?') || /\[.*\]/.match(path) elsif @glob_policy == :backward_compatible path.include?('*') diff --git a/test/plugin/test_in_tail.rb b/test/plugin/test_in_tail.rb index 3e612ce55d..296386ffc6 100644 --- a/test/plugin/test_in_tail.rb +++ b/test/plugin/test_in_tail.rb @@ -1600,6 +1600,43 @@ def ex_config_with_brackets }) end + def test_config_with_always_with_default_delimiter + assert_raise(Fluent::ConfigError) do + config = config_element("", "", { + "tag" => "tail", + "path" => "test/plugin/data/log_numeric/[0-1][2-4].log", + "format" => "none", + "pos_file" => "#{@tmp_dir}/tail.pos", + "read_from_head" => true, + "refresh_interval" => 30, + "glob_policy" => "always", + "rotate_wait" => "#{EX_ROTATE_WAIT}s", + "follow_inodes" => "#{EX_FOLLOW_INODES}", + }) + + create_driver(config, false).instance + end + end + + def test_config_with_always_with_custom_delimiter + assert_nothing_raised do + config = config_element("", "", { + "tag" => "tail", + "path" => "test/plugin/data/log_numeric/[0-1][2-4].log", + "format" => "none", + "pos_file" => "#{@tmp_dir}/tail.pos", + "read_from_head" => true, + "refresh_interval" => 30, + "glob_policy" => "always", + "path_delimiter" => "|", + "rotate_wait" => "#{EX_ROTATE_WAIT}s", + "follow_inodes" => "#{EX_FOLLOW_INODES}", + }) + + create_driver(config, false).instance + end + end + def test_expand_paths_with_brackets expanded_paths = [ create_target_info('test/plugin/data/log_numeric/01.log'), From be394fc41a305c539a2a63f4bd4478e86c35b4fd Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Tue, 26 Mar 2024 19:35:16 +0900 Subject: [PATCH 11/13] in_tail: test: Add more test cases for curly braces related Signed-off-by: Hiroshi Hatake --- lib/fluent/plugin/in_tail.rb | 12 ++++++++++-- test/plugin/test_in_tail.rb | 38 ++++++++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 6 deletions(-) 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 From 298a24b289f435ba77ae408720e9b75164f9af95 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 4 Apr 2024 18:35:04 +0900 Subject: [PATCH 12/13] in_tail: Add comments to describe why we don't return true when always option is chosen Signed-off-by: Hiroshi Hatake --- lib/fluent/plugin/in_tail.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/fluent/plugin/in_tail.rb b/lib/fluent/plugin/in_tail.rb index 0f9c3865dd..a13fec4ff3 100644 --- a/lib/fluent/plugin/in_tail.rb +++ b/lib/fluent/plugin/in_tail.rb @@ -301,6 +301,10 @@ def extended_glob_pattern(path) # This should be collided for wildcard pattern for curly braces. def use_glob?(path) if @glob_policy == :always + # For future extensions, we decided to use `always' term to handle + # regular expressions as much as possible. + # This is because not using `true' as a returning value + # when choosing :always here. extended_glob_pattern(path) || /\{.*,.*\}/.match(path) elsif @glob_policy == :extended extended_glob_pattern(path) From 68e168cfb8f0195c92b0c35172b410f413ce359c Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 4 Apr 2024 18:39:13 +0900 Subject: [PATCH 13/13] in_tail: Update comments for curly braces Because we can avoid the collisions for the tokens of comma usages. Signed-off-by: Hiroshi Hatake --- lib/fluent/plugin/in_tail.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/fluent/plugin/in_tail.rb b/lib/fluent/plugin/in_tail.rb index a13fec4ff3..f74ffdd8e6 100644 --- a/lib/fluent/plugin/in_tail.rb +++ b/lib/fluent/plugin/in_tail.rb @@ -297,8 +297,10 @@ 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. + # Curly braces is not supported with default path_delimiter + # because the default delimiter of path is ",". + # This should be collided for wildcard pattern for curly braces and + # be handled as an error on #configure. def use_glob?(path) if @glob_policy == :always # For future extensions, we decided to use `always' term to handle