diff --git a/lib/fluent/config/types.rb b/lib/fluent/config/types.rb index 66ef37ad39..0ff2c2c475 100644 --- a/lib/fluent/config/types.rb +++ b/lib/fluent/config/types.rb @@ -20,6 +20,10 @@ module Fluent module Config + def self.reformatted_value(type, val, opts = {}, name = nil) + REFORMAT_VALUE.call(type, val, opts, name) + end + def self.size_value(str, opts = {}, name = nil) return nil if str.nil? @@ -104,6 +108,16 @@ def self.string_value(val, opts = {}, name = nil) Config.string_value(val, opts, name) } + def self.symbol_value(val, opts = {}, name = nil) + return nil if val.nil? + + val[0] == ":" ? val[1..-1].to_sym : val.to_sym + end + + SYMBOL_TYPE = Proc.new { |val, opts = {}, name = nil| + Config.symbol_value(val, opts, name) + } + def self.enum_value(val, opts = {}, name = nil) return nil if val.nil? @@ -130,7 +144,13 @@ def self.enum_value(val, opts = {}, name = nil) raise ConfigError, "#{name}: #{e.message}" end else - val.to_i + i = val.to_i + # string will convert to 0, return nil if not actually "0" + if i == 0 && val != "0" + nil + else + i + end end } @@ -176,6 +196,7 @@ def self.enum_value(val, opts = {}, name = nil) when :bool then Config.bool_value(value, opts, name) when :time then Config.time_value(value, opts, name) when :regexp then Config.regexp_value(value, opts, name) + when :symbol then SYMBOL_TYPE.call(value, opts, name) else raise "unknown type in REFORMAT: #{type}" end diff --git a/lib/fluent/env.rb b/lib/fluent/env.rb index 2b0bf5c8d7..7ac5e02f5e 100644 --- a/lib/fluent/env.rb +++ b/lib/fluent/env.rb @@ -15,13 +15,14 @@ # require 'serverengine/utils' +require 'fluent/env_utils' module Fluent DEFAULT_CONFIG_PATH = ENV['FLUENT_CONF'] || '/etc/fluent/fluent.conf' DEFAULT_PLUGIN_DIR = ENV['FLUENT_PLUGIN'] || '/etc/fluent/plugin' DEFAULT_SOCKET_PATH = ENV['FLUENT_SOCKET'] || '/var/run/fluent/fluent.sock' DEFAULT_BACKUP_DIR = ENV['FLUENT_BACKUP_DIR'] || '/tmp/fluent' - DEFAULT_OJ_OPTIONS = {bigdecimal_load: :float, mode: :compat, use_to_json: true} + DEFAULT_OJ_OPTIONS = Fluent::EnvUtils::OjOptions.new.get_options DEFAULT_DIR_PERMISSION = 0755 DEFAULT_FILE_PERMISSION = 0644 diff --git a/lib/fluent/env_utils.rb b/lib/fluent/env_utils.rb new file mode 100644 index 0000000000..bd605db4c5 --- /dev/null +++ b/lib/fluent/env_utils.rb @@ -0,0 +1,50 @@ +require 'fluent/config' + +module Fluent + module EnvUtils + def self.convert_env_var_to_type(value, type) + Fluent::Config.reformatted_value(type, value) + end + + class OjOptions + OJ_OPTIONS = { + 'bigdecimal_load': :symbol, + 'max_nesting': :integer, + 'mode': :symbol, + 'use_to_json': :bool + } + + OJ_OPTIONS_ALLOWED_VALUES = { + 'bigdecimal_load': %i[bigdecimal float auto], + 'mode': %i[strict null concat json rails object custom] + } + + OJ_OPTIONS_DEFAULTS = { + 'bigdecimal_load': :float, + 'mode': :concat, + 'use_to_json': true + } + + def initialize + @options = {} + OJ_OPTIONS_DEFAULTS.each { |key, value| @options[key] = value } + end + + def get_options + OJ_OPTIONS.each do |key, type| + env_value = ENV["FLUENT_OJ_OPTION_#{key.upcase}"] + next if env_value.nil? + + cast_value = Fluent::EnvUtils.convert_env_var_to_type(env_value, OJ_OPTIONS[key]) + next if cast_value.nil? + + next if OJ_OPTIONS_ALLOWED_VALUES[key] && !OJ_OPTIONS_ALLOWED_VALUES[key].include?(cast_value) + + @options[key.to_sym] = cast_value + end + + @options + end + end + end +end diff --git a/test/test_env_utils.rb b/test/test_env_utils.rb new file mode 100644 index 0000000000..c6ee35c15c --- /dev/null +++ b/test/test_env_utils.rb @@ -0,0 +1,41 @@ +require_relative 'helper' +require 'fluent/test' +require 'fluent/env_utils' + +class EnvUtilsTest < ::Test::Unit::TestCase + setup do + @oj = Fluent::EnvUtils::OjOptions.new + end + + sub_test_case "module methods" do + test "convert_env_var_to_type" do + assert_equal :conor, Fluent::EnvUtils.convert_env_var_to_type("conor", :symbol) + assert_equal 8933, Fluent::EnvUtils.convert_env_var_to_type("8933", :integer) + assert_equal nil, Fluent::EnvUtils.convert_env_var_to_type("conor", :integer) + assert_equal true, Fluent::EnvUtils.convert_env_var_to_type("true", :bool) + assert_equal nil, Fluent::EnvUtils.convert_env_var_to_type("conor", :bool) + end + end + + sub_test_case "OjOptions" do + test "when no env vars set, returns default options" do + ENV.clear + assert_equal Fluent::EnvUtils::OjOptions::OJ_OPTIONS_DEFAULTS, @oj.get_options + end + + test "valid env var passed with valid value, default is overridden" do + ENV["FLUENT_OJ_OPTION_BIGDECIMAL_LOAD"] = ":bigdecimal" + assert_equal :bigdecimal, @oj.get_options[:bigdecimal_load] + end + + test "valid env var passed with invalid value, default is not overriden" do + ENV["FLUENT_OJ_OPTION_BIGDECIMAL_LOAD"] = ":conor" + assert_equal :float, @oj.get_options[:bigdecimal_load] + end + + test "invalid env var passed, nothing done with it" do + ENV["FLUENT_OJ_OPTION_CONOR"] = ":conor" + assert_equal nil, @oj.get_options[:conor] + end + end +end \ No newline at end of file