cookbooks/fb_fluentbit/spec/default_spec.rb (237 lines of code) (raw):
#
# Copyright (c) 2020-present, Facebook, Inc.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require './spec/spec_helper.rb'
recipe('fb_fluentbit::default') do |tc|
it 'should raise error when parser has no format' do
expect do
tc.chef_run.converge(described_recipe) do |node|
node.default['fb_fluentbit']['input']['tail']['foo'] = {
'Path' => '/var/log/messages',
}
node.default['fb_fluentbit']['output']['http']['bar'] = {
'Match' => '*',
'Host' => '192.168.0.1',
'Port' => 80,
'URI' => '/stuff',
}
# Note: no format
node.default['fb_fluentbit']['parser']['myparser'] = {
'Time_Key' => 'time',
}
end
end.to raise_error(RuntimeError)
end
it 'should raise error when using undefined parser' do
expect do
tc.chef_run.converge(described_recipe) do |node|
node.default['fb_fluentbit']['filter']['parser']['parse_stuff'] = {
'Match' => '*',
'Parser' => 'nonexistent_parser',
}
end
end.to raise_error(RuntimeError)
end
it 'should raise error when using undefined parser with mutliple parsers' do
expect do
tc.chef_run.converge(described_recipe) do |node|
node.default['fb_fluentbit']['parser']['my_parser'] = {
'Format' => 'regex',
'Regex' => '^.+$',
}
node.default['fb_fluentbit']['filter']['parser']['parse_stuff'] = {
'Match' => '*',
'Parser' => [
'my_parser',
'nonexistent_parser',
],
}
end
end.to raise_error(RuntimeError)
end
context 'external plugin with bad config' do
it 'should raise error when "package" is missing' do
expect do
tc.chef_run.converge(described_recipe) do |node|
node.default['fb_fluentbit']['external']['my_plugin'] = {
'path' => '/bin/true',
}
node.default['fb_fluentbit']['output']['my_plugin']['test'] = {
'key1' => 'value1',
}
end
end.to raise_error(RuntimeError)
end
it 'should raise error when "path" is missing' do
expect do
tc.chef_run.converge(described_recipe) do |node|
node.default['fb_fluentbit']['external']['my_plugin'] = {
'package' => 'fb-mypackage',
}
node.default['fb_fluentbit']['output']['my_plugin']['test'] = {
'key1' => 'value1',
}
end
end.to raise_error(RuntimeError)
end
end
context 'multiple external plugins' do
cached(:chef_run) do
tc.chef_run.converge(described_recipe) do |node|
node.default['fb_fluentbit']['input']['tail']['foo'] = {
'Path' => '/var/log/messages',
}
node.default['fb_fluentbit']['output']['http']['bar'] = {
'Match' => '*',
'Host' => '192.168.0.1',
'Port' => 80,
'URI' => '/stuff',
}
node.default['fb_fluentbit']['filter']['grep']['filter_stuff'] = {
'Match' => '*',
'Regex' => 'log aa',
}
node.default['fb_fluentbit']['filter']['grep']['filter_more_stuff'] = {
'Match' => '*',
'Regex' => 'log bb',
}
# Add a couple custom plugins.
node.default['fb_fluentbit']['external']['custom_plugin'] = {
'package' => 'my-custom-rpm',
'path' => '/usr/local/lib/custom_plugin/custom_plugin.so',
}
%w{category_1 category_2}.each do |category|
node.default['fb_fluentbit']['output']['custom_plugin'][category] = {
'Match' => '*',
'Category' => category,
}
end
# Now add a made-up external plugin.
node.default['fb_fluentbit']['external']['not_real'] = {
'package' => 'my-fake-package',
'path' => '/usr/local/lib/not_real/not_real.so',
}
node.default['fb_fluentbit']['input']['not_real']['foo'] = {
'Key1' => 'Value1',
'Key2' => 'Value2',
}
end
end
it 'should install external plugin packages' do
expect(chef_run).to upgrade_package('fluentbit external plugins').
with_package_name(['my-custom-rpm', 'my-fake-package'])
end
it 'should render plugins.conf' do
expect(chef_run).to render_file('/etc/td-agent-bit/plugins.conf').
with_content(tc.fixture('multiple_external_plugins_plugins.conf'))
end
it 'should render service conf' do
expect(chef_run).to render_file('/etc/td-agent-bit/td-agent-bit.conf').
with_content(tc.fixture('multiple_external_plugins_service.conf'))
end
end
context 'clean config setup' do
cached(:chef_run) do
tc.chef_run.converge(described_recipe) do |node|
# turn on automatic upgrades
node.default['fb_fluentbit']['manage_packages'] = true
# Modify some service settings
node.default['fb_fluentbit']['service_config']['Log_Level'] = 'debug'
node.default['fb_fluentbit']['service_config']['HTTP_Server'] = 'On'
# Set up input/output plugins + a filter.
node.default['fb_fluentbit']['input']['tail']['foo'] = {
'Path' => '/var/log/messages',
}
node.default['fb_fluentbit']['output']['http']['bar'] = {
'Match' => '*',
'Host' => '192.168.0.1',
'Port' => 80,
'URI' => '/stuff',
}
node.default['fb_fluentbit']['filter']['grep']['filter_stuff'] = {
'Match' => '*',
'Regex' => 'log aa',
}
node.default['fb_fluentbit']['filter']['parser']['parse_foo'] = {
'Match' => '*',
'Parser' => 'my_parser',
}
# Add an external plugin.
node.default['fb_fluentbit']['external']['custom_plugin'] = {
'package' => 'my-custom-rpm',
'path' => '/usr/local/lib/custom_plugin/custom_plugin.so',
}
node.default['fb_fluentbit']['output']['custom_plugin']['foo'] = {
'Match' => '*',
'Category' => 'some_category',
}
# Add some parsers.
node.default['fb_fluentbit']['parser']['my_parser'] = {
'Format' => 'regex',
'Time_Key' => 'time',
'Regex' => '^some line here$',
}
node.default['fb_fluentbit']['parser']['my_other_parser'] = {
'Format' => 'json',
'Time_Key' => 'time',
}
end
end
it 'should upgrade the package' do
expect(chef_run).to upgrade_package('td-agent-bit')
end
it 'should install external plugin packages' do
expect(chef_run).to upgrade_package('fluentbit external plugins').
with_package_name(['my-custom-rpm'])
end
it 'should render parsers.conf' do
expect(chef_run).to render_file('/etc/td-agent-bit/parsers.conf').
with_content(tc.fixture('clean_config_parsers.conf'))
end
it 'should render plugins.conf' do
expect(chef_run).to render_file('/etc/td-agent-bit/plugins.conf').
with_content(tc.fixture('clean_config_plugins.conf'))
end
it 'should render service conf' do
expect(chef_run).to render_file('/etc/td-agent-bit/td-agent-bit.conf').
with_content(tc.fixture('clean_config_service.conf'))
end
it 'should start the service' do
expect(chef_run).to enable_service('td-agent-bit')
expect(chef_run).to start_service('td-agent-bit')
end
end
context 'not installing packages' do
cached(:chef_run) do
tc.chef_run.converge(described_recipe) do |node|
# Add a external plugin
node.default['fb_fluentbit']['external']['custom_plugin'] = {
'package' => 'my-custom-rpm',
'path' => '/usr/local/lib/custom_plugin/custom_plugin.so',
}
# turn off automatic fluentbit upgrades
node.default['fb_fluentbit']['manage_packages'] = false
# turn off external plugin upgrades
node.default['fb_fluentbit']['plugin_manage_packages'] = false
end
end
it 'should not upgrade the fluentbit package' do
expect(chef_run).to_not upgrade_package('td-agent-bit')
end
it 'should not install external plugin packages' do
expect(chef_run).to_not upgrade_package('fluentbit external plugins').
with_package_name(['my-custom-rpm'])
end
end
context 'when defining plugins with multiple types' do
let(:chef_run) { tc.chef_run }
it 'should render key/value pairs properly' do
chef_run.converge(described_recipe) do |node|
node.default['fb_fluentbit']['input']['systemd']['tail_journal'] = {
'Tag' => 'my_journal_logs',
'Systemd_Filter' => {
'_SYSTEMD_UNIT' => ['unit1.service', 'unit2.service'],
'_KEY_ONE' => 'value',
},
}
end
expect(chef_run).to render_file('/etc/td-agent-bit/td-agent-bit.conf').
with_content(tc.fixture('systemd_duplicate_keys_service.conf'))
end
it 'should render multiple keys properly' do
chef_run.converge(described_recipe) do |node|
node.default['fb_fluentbit']['filter']['record_modifier']['a'] = {
'Whitelist_key' => ['foo', 'bar', 'baz'],
}
end
expect(chef_run).to render_file('/etc/td-agent-bit/td-agent-bit.conf').
with_content(tc.fixture('record_modifier_duplicate_keys_service.conf'))
end
end
end