-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Config validation + session management (#102)
- Loading branch information
Showing
9 changed files
with
298 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# frozen_string_literal: true | ||
|
||
module Karafka | ||
module Web | ||
module Contracts | ||
# Contract to validate Web-UI configuration | ||
class Config < Web::Contracts::Base | ||
configure | ||
|
||
# Use the same regexp as Karafka for topics validation | ||
TOPIC_REGEXP = ::Karafka::Contracts::TOPIC_REGEXP | ||
|
||
required(:ttl) { |val| val.is_a?(Numeric) && val.positive? } | ||
|
||
nested(:topics) do | ||
required(:errors) { |val| val.is_a?(String) && TOPIC_REGEXP.match?(val) } | ||
|
||
nested(:consumers) do | ||
required(:reports) { |val| val.is_a?(String) && TOPIC_REGEXP.match?(val) } | ||
required(:states) { |val| val.is_a?(String) && TOPIC_REGEXP.match?(val) } | ||
required(:metrics) { |val| val.is_a?(String) && TOPIC_REGEXP.match?(val) } | ||
end | ||
end | ||
|
||
nested(:tracking) do | ||
# Do not report more often then every second, this could overload the system | ||
required(:interval) { |val| val.is_a?(Integer) && val >= 1_000 } | ||
|
||
nested(:consumers) do | ||
required(:reporter) { |val| !val.nil? } | ||
required(:sampler) { |val| !val.nil? } | ||
required(:listeners) { |val| val.is_a?(Array) } | ||
end | ||
|
||
nested(:producers) do | ||
required(:reporter) { |val| !val.nil? } | ||
required(:sampler) { |val| !val.nil? } | ||
required(:listeners) { |val| val.is_a?(Array) } | ||
end | ||
end | ||
|
||
nested(:processing) do | ||
required(:active) { |val| [true, false].include?(val) } | ||
required(:consumer_group) { |val| val.is_a?(String) && TOPIC_REGEXP.match?(val) } | ||
# Do not update data more often not to overload and not to generate too much data | ||
required(:interval) { |val| val.is_a?(Integer) && val >= 1_000 } | ||
end | ||
|
||
nested(:ui) do | ||
nested(:sessions) do | ||
required(:key) { |val| val.is_a?(String) && !val.empty? } | ||
required(:secret) { |val| val.is_a?(String) && val.length >= 64 } | ||
end | ||
|
||
required(:cache) { |val| !val.nil? } | ||
required(:per_page) { |val| val.is_a?(Integer) && val >= 1 && val <= 100 } | ||
required(:visibility_filter) { |val| !val.nil? } | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe_current do | ||
subject(:contract) { described_class.new } | ||
|
||
let(:params) do | ||
{ | ||
ttl: 5000, | ||
topics: { | ||
errors: 'errors-topic', | ||
consumers: { | ||
reports: 'reports-topic', | ||
states: 'states-topic', | ||
metrics: 'metrics-topic' | ||
} | ||
}, | ||
tracking: { | ||
interval: 2_000, | ||
consumers: { | ||
reporter: Object.new, | ||
sampler: Object.new, | ||
listeners: [] | ||
}, | ||
producers: { | ||
reporter: Object.new, | ||
sampler: Object.new, | ||
listeners: [] | ||
} | ||
}, | ||
processing: { | ||
active: true, | ||
consumer_group: 'consumer-group-topic', | ||
interval: 3_000 | ||
}, | ||
ui: { | ||
sessions: { | ||
key: 'some_key', | ||
secret: 'a' * 64 | ||
}, | ||
cache: Object.new, | ||
per_page: 50, | ||
visibility_filter: Object.new | ||
} | ||
} | ||
end | ||
|
||
context 'when all values are valid' do | ||
it 'is valid' do | ||
expect(contract.call(params)).to be_success | ||
end | ||
end | ||
|
||
context 'when ttl is not numeric' do | ||
before { params[:ttl] = 'string_value' } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
|
||
context 'when validating topics topics' do | ||
context 'when errors topic does not match the regexp' do | ||
before { params[:topics][:errors] = 'invalid topic!' } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
|
||
context 'when validating consumer scoped fields' do | ||
%i[ | ||
reports | ||
states | ||
metrics | ||
].each do |field| | ||
context "when #{field} does not match the regexp" do | ||
before { params[:topics][:consumers][field] = 'invalid topic!' } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
end | ||
end | ||
end | ||
|
||
context 'when validating tracking related settings' do | ||
context 'when interval is less than 1000' do | ||
before { params[:tracking][:interval] = 999 } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
|
||
context 'when interval is not an integer' do | ||
before { params[:tracking][:interval] = 1000.5 } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
|
||
%i[consumers producers].each do |entity| | ||
context "when checking #{entity} scoped data" do | ||
%i[reporter sampler].each do |field| | ||
context "when #{field} is nil" do | ||
before { params[:tracking][entity][field] = nil } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
end | ||
|
||
context 'when listeners is not an array' do | ||
before { params[:tracking][entity][:listeners] = 'not_an_array' } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
end | ||
end | ||
end | ||
|
||
context 'when validating processing related settings' do | ||
context 'when active is not a boolean' do | ||
before { params[:processing][:active] = 'maybe' } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
|
||
context 'when consumer_group does not match the regexp' do | ||
before { params[:processing][:consumer_group] = 'invalid topic!' } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
|
||
context 'when interval is less than 1000' do | ||
before { params[:processing][:interval] = 999 } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
end | ||
|
||
context 'when validating ui related settings' do | ||
context 'when validating sessions related settings' do | ||
context 'when key is empty' do | ||
before { params[:ui][:sessions][:key] = '' } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
|
||
context 'when secret is less than 64 characters long' do | ||
before { params[:ui][:sessions][:secret] = 'short' } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
end | ||
|
||
context 'when cache is nil' do | ||
before { params[:ui][:cache] = nil } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
|
||
context 'when per_page is more than 100' do | ||
before { params[:ui][:per_page] = 101 } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
|
||
context 'when per_page is less than 1' do | ||
before { params[:ui][:per_page] = 0 } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
|
||
context 'when visibility_filter is nil' do | ||
before { params[:ui][:visibility_filter] = nil } | ||
|
||
it { expect(contract.call(params)).not_to be_success } | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters