diff --git a/logstash-core/lib/logstash/settings.rb b/logstash-core/lib/logstash/settings.rb index 5bb1e649b..20cf6bff9 100644 --- a/logstash-core/lib/logstash/settings.rb +++ b/logstash-core/lib/logstash/settings.rb @@ -9,6 +9,11 @@ module LogStash def initialize @settings = {} + # Theses settings were loaded from the yaml file + # but we didn't find any settings to validate them, + # lets keep them around until we do `validate_all` at that + # time universal plugins could have added new settings. + @transient_settings = {} end def register(setting) @@ -52,8 +57,14 @@ module LogStash end alias_method :get, :get_value - def set_value(setting_name, value) + def set_value(setting_name, value, graceful = false) get_setting(setting_name).set(value) + rescue ArgumentError => e + if graceful + @transient_settings[setting_name] = value + else + raise e + end end alias_method :set, :set_value @@ -65,8 +76,8 @@ module LogStash hash end - def merge(hash) - hash.each {|key, value| set_value(key, value) } + def merge(hash, graceful = false) + hash.each {|key, value| set_value(key, value, graceful) } self end @@ -96,10 +107,13 @@ module LogStash def from_yaml(yaml_path) settings = read_yaml(::File.join(yaml_path, "logstash.yml")) - self.merge(flatten_hash(settings)) + self.merge(flatten_hash(settings), true) end def validate_all + # lets merge the transient_settings again to see if new setting were added. + self.merge(@transient_settings) + @settings.each do |name, setting| setting.validate_value end diff --git a/logstash-core/spec/logstash/settings_spec.rb b/logstash-core/spec/logstash/settings_spec.rb index 138040fa6..adfe3819f 100644 --- a/logstash-core/spec/logstash/settings_spec.rb +++ b/logstash-core/spec/logstash/settings_spec.rb @@ -1,6 +1,7 @@ # encoding: utf-8 require "spec_helper" require "logstash/settings" +require "fileutils" describe LogStash::Settings do let(:numeric_setting_name) { "number" } @@ -86,4 +87,42 @@ describe LogStash::Settings do end end end + + context "transient settings" do + subject do + settings = described_class.new + settings.register(LogStash::Setting::String.new("exist", "bonsoir")) + settings + end + + let(:values) { { "do.not.exist.on.boot" => true, "exist" => "bonjour" } } + let(:yaml_path) do + p = Stud::Temporary.pathname + FileUtils.mkdir_p(p) + + ::File.open(::File.join(p, "logstash.yml"), "w+") do |f| + f.write(YAML.dump(values)) + end + p + end + + it "allow to read yml file that contains unknown settings" do + expect { subject.from_yaml(yaml_path) }.not_to raise_error + end + + context "when running #validate_all" do + it "merge and validate all the registered setting" do + subject.from_yaml(yaml_path) + subject.register(LogStash::Setting::Boolean.new("do.not.exist.on.boot", false)) + + expect { subject.validate_all }.not_to raise_error + expect(subject.get("do.not.exist.on.boot")).to be_truthy + end + + it "raise an error when the settings doesn't exist" do + subject.from_yaml(yaml_path) + expect { subject.validate_all }.to raise_error(ArgumentError) + end + end + end end