From 075e89a8b32a2454de8c76b6a98d3a44194ea7ea Mon Sep 17 00:00:00 2001 From: TAGOMORI Satoshi Date: Wed, 30 Nov 2016 14:16:39 +0900 Subject: [PATCH] fix not to check tag and variable placeholders when configured as secondary out_file has been used as plugin to dump data in secondary for a long time, and that configuration looses consistency about chunk keys (even in v0.12). But increment placeholder of out_file can create another file name (by just numbering) for such cases. This change makes v0.14 to work with such configuration... --- lib/fluent/plugin/out_file.rb | 44 ++++++++++++++++++++++++----------- test/plugin/test_out_file.rb | 17 ++++++++++++++ 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/lib/fluent/plugin/out_file.rb b/lib/fluent/plugin/out_file.rb index bee41c658b..154143a46e 100644 --- a/lib/fluent/plugin/out_file.rb +++ b/lib/fluent/plugin/out_file.rb @@ -113,25 +113,41 @@ def configure(conf) end path_suffix = @add_path_suffix ? @path_suffix : '' - @path_template = generate_path_template(@path, @buffer_config.timekey, @append, @compress_method, path_suffix: path_suffix, time_slice_format: configured_time_slice_format) - - placeholder_validate!(:path, @path_template) - - max_tag_index = get_placeholders_tag(@path_template).max || 1 - max_tag_index = 1 if max_tag_index < 1 - dummy_tag = (['a'] * max_tag_index).join('.') - dummy_record_keys = get_placeholders_keys(@path_template) || ['message'] - dummy_record = Hash[dummy_record_keys.zip(['data'] * dummy_record_keys.size)] - - test_meta1 = metadata_for_test(dummy_tag, Fluent::Engine.now, dummy_record) - test_path = extract_placeholders(@path_template, test_meta1) - unless ::Fluent::FileUtil.writable_p?(test_path) - raise Fluent::ConfigError, "out_file: `#{test_path}` is not writable" + path_timekey = if @chunk_key_time + @as_secondary ? @primary_instance.buffer_config.timekey : @buffer_config.timekey + else + nil + end + @path_template = generate_path_template(@path, path_timekey, @append, @compress_method, path_suffix: path_suffix, time_slice_format: configured_time_slice_format) + + if @as_secondary + # When this plugin is configured as secondary & primary plugin has tag key, but this plugin may not have it. + # Increment placeholder can make another output file per chunk tag/keys even if original path doesn't include it. + placeholder_validators(:path, @path_template).select{|v| v.type == :time }.each do |v| + v.validate! + end + else + placeholder_validate!(:path, @path_template) + + max_tag_index = get_placeholders_tag(@path_template).max || 1 + max_tag_index = 1 if max_tag_index < 1 + dummy_tag = (['a'] * max_tag_index).join('.') + dummy_record_keys = get_placeholders_keys(@path_template) || ['message'] + dummy_record = Hash[dummy_record_keys.zip(['data'] * dummy_record_keys.size)] + + test_meta1 = metadata_for_test(dummy_tag, Fluent::Engine.now, dummy_record) + test_path = extract_placeholders(@path_template, test_meta1) + unless ::Fluent::FileUtil.writable_p?(test_path) + raise Fluent::ConfigError, "out_file: `#{test_path}` is not writable" + end end @formatter = formatter_create if @symlink_path && @buffer.respond_to?(:path) + if @as_secondary + raise Fluent::ConfigError, "symlink_path option is unavailable in : consider to use secondary_file plugin" + end if Fluent.windows? log.warn "symlink_path is unavailable on Windows platform. disabled." @symlink_path = nil diff --git a/test/plugin/test_out_file.rb b/test/plugin/test_out_file.rb index 5cdf0f3e5c..13e09f88dd 100644 --- a/test/plugin/test_out_file.rb +++ b/test/plugin/test_out_file.rb @@ -133,6 +133,23 @@ def create_driver(conf = CONFIG) create_driver(conf) end end + + test 'configured as secondary with primary using chunk_key_tag and not using chunk_key_time' do + require 'fluent/plugin/out_null' + port = unused_port + conf = config_element('match', '**', { + }, [ + config_element('buffer', 'tag', { + }), + config_element('secondary', '', { + '@type' => 'file', + 'path' => "#{TMP_DIR}/testing_to_dump_by_out_file", + }), + ]) + assert_nothing_raised do + Fluent::Test::Driver::Output.new(Fluent::Plugin::NullOutput).configure(conf) + end + end end sub_test_case 'fully configured output' do