diff --git a/logstash-core/lib/logstash/settings.rb b/logstash-core/lib/logstash/settings.rb index 20cf6bff9..c1250835d 100644 --- a/logstash-core/lib/logstash/settings.rb +++ b/logstash-core/lib/logstash/settings.rb @@ -489,6 +489,32 @@ module LogStash Util::TimeValue.from_value(value).to_nanos end end + + class ArrayCoercible < Coercible + def initialize(name, klass, default, strict=true, &validator_proc) + @element_class = klass + super(name, ::Array, default, strict, &validator_proc) + end + + def coerce(value) + Array(value) + end + + protected + def validate(input) + if !input.is_a?(@klass) + raise ArgumentError.new("Setting \"#{@name}\" must be a #{@klass}. Received: #{input} (#{input.class})") + end + + unless input.all? {|el| el.kind_of?(@element_class) } + raise ArgumentError.new("Values of setting \"#{@name}\" must be #{@element_class}. Received: #{input.map(&:class)}") + end + + if @validator_proc && !@validator_proc.call(input) + raise ArgumentError.new("Failed to validate setting \"#{@name}\" with value: #{input}") + end + end + end end diff --git a/logstash-core/spec/logstash/settings/array_coercible_spec.rb b/logstash-core/spec/logstash/settings/array_coercible_spec.rb new file mode 100644 index 000000000..7146ff095 --- /dev/null +++ b/logstash-core/spec/logstash/settings/array_coercible_spec.rb @@ -0,0 +1,46 @@ +# encoding: utf-8 +require "spec_helper" +require "logstash/settings" + +describe LogStash::Setting::ArrayCoercible do + subject { described_class.new("option", element_class, value) } + let(:value) { [ ] } + let(:element_class) { Object } + + context "when given a non array value" do + let(:value) { "test" } + describe "the value" do + it "is converted to an array with that single element" do + expect(subject.value).to eq(["test"]) + end + end + end + + context "when given an array value" do + let(:value) { ["test"] } + describe "the value" do + it "is not modified" do + expect(subject.value).to eq(value) + end + end + end + + describe "initialization" do + subject { described_class } + let(:element_class) { Fixnum } + context "when given values of incorrect element class" do + let(:value) { "test" } + + it "will raise an exception" do + expect { described_class.new("option", element_class, value) }.to raise_error(ArgumentError) + end + end + context "when given values of correct element class" do + let(:value) { 1 } + + it "will not raise an exception" do + expect { described_class.new("option", element_class, value) }.not_to raise_error + end + end + end +end