From 515e3516b7cb0a40112a9a91a154002337e72216 Mon Sep 17 00:00:00 2001 From: Florian Dobener Date: Fri, 11 Apr 2025 11:49:20 +0000 Subject: [PATCH 1/2] Use relative path in out_file Signed-off-by: Florian Dobener --- lib/fluent/plugin/out_file.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/fluent/plugin/out_file.rb b/lib/fluent/plugin/out_file.rb index 1598cc7c3f..abce3a4a61 100644 --- a/lib/fluent/plugin/out_file.rb +++ b/lib/fluent/plugin/out_file.rb @@ -17,6 +17,7 @@ require 'fileutils' require 'zlib' require 'time' +require 'pathname' require 'fluent/plugin/output' require 'fluent/config/error' @@ -97,7 +98,8 @@ def generate_chunk(metadata) if chunk.metadata == @latest_metadata sym_path = @_output_plugin_for_symlink.extract_placeholders(@_symlink_path, chunk) FileUtils.mkdir_p(File.dirname(sym_path), mode: @_output_plugin_for_symlink.dir_perm) - FileUtils.ln_sf(chunk.path, sym_path) + relative_path = Pathname.new(chunk.path).relative_path_from(Pathname.new(File.dirname(sym_path))) + FileUtils.ln_sf(relative_path, sym_path) end chunk end From 71ca5ac409175392eb43546832a6b3b75863ae25 Mon Sep 17 00:00:00 2001 From: domna Date: Mon, 21 Apr 2025 13:01:50 +0200 Subject: [PATCH 2/2] out_file: add support for relative symlink paths in configuration Signed-off-by: domna --- lib/fluent/plugin/out_file.rb | 10 ++++++++-- test/plugin/test_out_file.rb | 28 ++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/lib/fluent/plugin/out_file.rb b/lib/fluent/plugin/out_file.rb index abce3a4a61..a5bed3ea61 100644 --- a/lib/fluent/plugin/out_file.rb +++ b/lib/fluent/plugin/out_file.rb @@ -55,6 +55,8 @@ class FileOutput < Output config_param :recompress, :bool, default: false desc "Create symlink to temporary buffered file when buffer_type is file (disabled on Windows)." config_param :symlink_path, :string, default: nil + desc "Use relative path for symlink target (default: false)" + config_param :symlink_path_use_relative, :bool, default: false config_section :format do config_set_default :@type, 'out_file' @@ -98,8 +100,12 @@ def generate_chunk(metadata) if chunk.metadata == @latest_metadata sym_path = @_output_plugin_for_symlink.extract_placeholders(@_symlink_path, chunk) FileUtils.mkdir_p(File.dirname(sym_path), mode: @_output_plugin_for_symlink.dir_perm) - relative_path = Pathname.new(chunk.path).relative_path_from(Pathname.new(File.dirname(sym_path))) - FileUtils.ln_sf(relative_path, sym_path) + if @_output_plugin_for_symlink.symlink_path_use_relative + relative_path = Pathname.new(chunk.path).relative_path_from(Pathname.new(File.dirname(sym_path))) + FileUtils.ln_sf(relative_path, sym_path) + else + FileUtils.ln_sf(chunk.path, sym_path) + end end chunk end diff --git a/test/plugin/test_out_file.rb b/test/plugin/test_out_file.rb index b78f8f62ce..d474ff5f4d 100644 --- a/test/plugin/test_out_file.rb +++ b/test/plugin/test_out_file.rb @@ -779,7 +779,24 @@ def parse_system(text) end end - def run_and_check(d, symlink_path) + test 'relative symlink' do + omit "Windows doesn't support symlinks" if Fluent.windows? + + conf = CONFIG + %[ + symlink_path #{SYMLINK_PATH} + symlink_path_use_relative true + ] + symlink_path = "#{SYMLINK_PATH}" + + d = create_driver(conf) + begin + run_and_check(d, symlink_path, relative_symlink=true) + ensure + FileUtils.rm_rf(symlink_path) + end + end + + def run_and_check(d, symlink_path, relative_symlink=false) d.run(default_tag: 'tag') do es = Fluent::OneEventStream.new(event_time("2011-01-02 13:14:15 UTC"), {"a"=>1}) d.feed(es) @@ -794,7 +811,14 @@ def run_and_check(d, symlink_path) assert File.exist?(symlink_path) meta = d.instance.metadata('tag', event_time("2011-01-03 14:15:16 UTC"), {}) - assert_equal d.instance.buffer.instance_eval{ @stage[meta].path }, File.readlink(symlink_path) + if relative_symlink + target_path = d.instance.buffer.instance_eval{ @stage[meta].path } + link_target = File.readlink(symlink_path) + expected_path = Pathname.new(target_path).relative_path_from(Pathname.new(File.dirname(symlink_path))).to_s + assert_equal expected_path, link_target + else + assert_equal d.instance.buffer.instance_eval{ @stage[meta].path }, File.readlink(symlink_path) + end end end end