Commit 97377d57 authored by Chad Walstrom's avatar Chad Walstrom Committed by Lance Albertson
Browse files

Removed $ModLod from rsyslog_file_input resource



The file_input resource was incorrectly including the legacy `$ModLoad imfile`
declaration in each new config file created from template. Additionally, the
legacy style script prevented newer rsyslog daemons from using `inotify` method.
This commit adds:

  - Legacy configuration file support
  - Ranier style configuration file support
  - Ability to specify imfile module parameters
  - Ability to specify additional resource parameters for `rsyslog_file_input`
Signed-off-by: default avatarChad Walstrom <chad.walstrom@granicus.com>
parent 92ef06e8
......@@ -87,6 +87,8 @@ See `attributes/default.rb` for default values.
- `node['rsyslog']['default_conf_file']` - If false it skips the creation of default configuration file 50-default.conf
- `node['rsyslog']['server_per_host_template']` - Template to use in the `rsyslog::server` recipe when creating the `35-server-per-host.conf` file
- `node['rsyslog']['server_per_host_cookbook']` - Cookbook name to get the `node['rsyslog']['server_per_host_template']` template from
- `node['rsyslog']['use_imfile']` - Use the `imfile` module to import local log files into syslog
- `node['rsyslog']['imfile']['KEY']` - Set `imfile` module parameters of label `KEY` to value. e.g. `PollingInterval`. Consult rsyslog documentation for valid entries.
## Recipes
......@@ -159,20 +161,17 @@ At this time, the server can only listen on UDP _or_ TCP.
## file_input
Configures a [text file input monitor](http://www.rsyslog.com/doc/imfile.html) to push a log file into rsyslog. Rsyslog must be installed to use this custom resource either using your own wrapper cookbook or the rsyslog::default recipe
Configures a [text file input monitor](http://www.rsyslog.com/doc/imfile.html) to push a log file into rsyslog. Rsyslog must be installed to use this custom resource either using your own wrapper cookbook or the rsyslog::default recipe.
To enable, specify `node['rsyslog']['use_imfile'] = true` as a node attribute.
Properties:
- `name`: name of the resource, also used for the syslog tag. Required.
- `file`: file path for input file to monitor. Required.
- `priority`: config order priority. Defaults to `99`.
- `severity`: syslog severity. Must be one of `emergency`, `alert`,
- `critical`, `error`, `warning`, `notice`, `info` or `debug`. If
- undefined, rsyslog interprets this as `notice`.
- `facility`: syslog facility. Must be one of `auth`, `authpriv`,
- `daemon`, `cron`, `ftp`, `lpr`, `kern`, `mail`, `news`, `syslog`,
- `user`, `uucp`, `local0`, ... , `local7`. If undefined, rsyslog
- interprets this as `local0`.
- `severity`: syslog severity. Must be one of `emergency`, `alert`, `critical`, `error`, `warning`, `notice`, `info` or `debug`. If undefined, rsyslog interprets this as `notice`.
- `facility`: syslog facility. Must be one of `auth`, `authpriv`, `daemon`, `cron`, `ftp`, `lpr`, `kern`, `mail`, `news`, `syslog`, `user`, `uucp`, `local0`, ... , `local7`. If undefined, rsyslog interprets this as `local0`.
- `cookbook_source`: cookbook containing the template. Defaults to `rsyslog`.
- `template_source`: template file source. Defaults to `file-input.conf.erb`
......
......@@ -23,6 +23,7 @@ default['rsyslog']['log_dir'] = '/srv/rsyslog'
default['rsyslog']['working_dir'] = '/var/spool/rsyslog'
default['rsyslog']['working_dir_mode'] = '0700'
default['rsyslog']['server'] = false
default['rsyslog']['use_imfile'] = false
default['rsyslog']['use_relp'] = false
default['rsyslog']['relp_port'] = 20_514
default['rsyslog']['protocol'] = 'tcp'
......@@ -149,6 +150,9 @@ when 'rhel', 'fedora', 'amazon'
if node['init_package'] == 'systemd'
default['rsyslog']['modules'] = %w(imuxsock imjournal)
default['rsyslog']['additional_directives'] = { 'OmitLocalLogging' => 'on', 'IMJournalStateFile' => 'imjournal.state' }
else
# RainerScript is not well supported by default on older RHEL
default['rsyslog']['config_style'] = 'legacy'
end
else
# format { facility => destination }
......
......@@ -74,6 +74,11 @@ suites:
- name: rsyslog-default-integration-tests
path: test/integration/default
- name: input_file_resource
attributes:
rsyslog:
use_imfile: true
imfile:
PollingInterval: 10
run_list:
- recipe[rsyslog_test::input_file_resource]
verifier:
......
module Rsyslog
module Helper
# If `config_style` for the node is `legacy`, add a `-legacy` label prior
# to the final file suffix of an ERB template.
def labeled_template(path, style)
path.gsub(/^(.*)(\.conf\.erb)/, "\\1#{style === 'legacy' ? '-legacy' : ''}\\2")
end
end
end
......@@ -16,6 +16,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
::Chef::Resource::Template.send(:include, Rsyslog::Helper)
package node['rsyslog']['package_name']
package rsyslog_relp_package if node['rsyslog']['use_relp']
......@@ -63,6 +64,18 @@ template "#{node['rsyslog']['config_prefix']}/rsyslog.conf" do
notifies :restart, "service[#{node['rsyslog']['service_name']}]"
end
# Include imfile module
template "#{node['rsyslog']['config_prefix']}/rsyslog.d/35-imfile.conf" do
source labeled_template('35-imfile.conf.erb', node['rsyslog']['config_style'])
owner node['rsyslog']['config_files']['owner']
group node['rsyslog']['config_files']['group']
mode node['rsyslog']['config_files']['mode']
variables module_parameters: node['rsyslog']['imfile'] # Supported with Rainer script
notifies :run, 'execute[validate_config]'
notifies :restart, "service[#{node['rsyslog']['service_name']}]"
only_if { node['rsyslog']['use_imfile'] === true }
end
template "#{node['rsyslog']['config_prefix']}/rsyslog.d/50-default.conf" do
source '50-default.conf.erb'
owner node['rsyslog']['config_files']['owner']
......
......@@ -15,28 +15,34 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
extend Rsyslog::Helper
property :file, String, required: true
property :priority, Integer, default: 99
property :severity, String
property :facility, String
property :input_parameters, Hash, default: {}
property :cookbook_source, String, default: 'rsyslog'
property :template_source, String, default: 'file-input.conf.erb'
property :template_source, String, default: labeled_template('file-input.conf.erb', node['rsyslog']['config_style'])
action :create do
log_name = new_resource.name
vars = {
file_name: new_resource.file,
tag: new_resource.name,
severity: new_resource.severity,
facility: new_resource.facility,
input_parameters: new_resource.input_parameters
}
vars['state_file'] = new_resource.name if node['rsyslog']['config_style'] === 'legacy'
template "/etc/rsyslog.d/#{new_resource.priority}-#{new_resource.name}.conf" do
mode '0664'
owner node['rsyslog']['user']
group node['rsyslog']['group']
source new_resource.template_source
cookbook new_resource.cookbook_source
variables 'file_name' => new_resource.file,
'tag' => log_name,
'state_file' => log_name,
'severity' => new_resource.severity,
'facility' => new_resource.facility
variables vars
notifies :restart, "service[#{node['rsyslog']['service_name']}]", :delayed
only_if { node['rsyslog']['use_imfile'] }
end
service node['rsyslog']['service_name'] do
......
......@@ -256,4 +256,75 @@ describe 'rsyslog::default' do
expect(chef_run).to start_service('rsyslog')
end
end
context "when node['rsyslog']['use_imfile'] is true" do
context 'when on centos 6' do
let(:chef_run) do
ChefSpec::ServerRunner.new(platform: 'centos', version: '6') do |node|
node.normal['rsyslog']['use_imfile'] = true
node.normal['rsyslog']['imfile']['PollingInterval'] = 10
end.converge(described_recipe)
end
let(:template) { chef_run.template('/etc/rsyslog.d/35-imfile.conf')}
it "node['rsyslog']['config_style'] will be 'legacy' by default" do
expect(chef_run.node['rsyslog']['config_style']).to eq('legacy')
end
context '/etc/rsyslog.d/35-imfile.conf file' do
it 'will be create with legacy style syntax' do
expect(chef_run).to render_file(template.path).with_content('$ModLoad imfile')
end
it 'will NOT include module parameter PollingInterval' do
expect(chef_run).not_to render_file(template.path).with_content('PollingInterval')
end
it 'is owned by root:root' do
expect(template.owner).to eq('root')
expect(template.group).to eq('root')
end
it 'has 0644 permissions' do
expect(template.mode).to eq('0644')
end
it 'notifies restarting the service' do
expect(template).to notify(service_resource).to(:restart)
end
end
end
context 'when on ubuntu 16.04 ' do
let(:chef_run) do
ChefSpec::ServerRunner.new(platform: 'ubuntu', version: '16.04') do |node|
node.normal['rsyslog']['use_imfile'] = true
node.normal['rsyslog']['imfile']['PollingInterval'] = 10
end.converge(described_recipe)
end
let(:template) { chef_run.template('/etc/rsyslog.d/35-imfile.conf')}
it "node['rsyslog']['config_style'] will be nil by default" do
expect(chef_run.node['rsyslog']['config_style']).to eq(nil)
end
context '/etc/rsyslog.d/35-imfile.conf file' do
it 'will be created with Rainer style syntax' do
expect(chef_run).to render_file(template.path).with_content(/module\(load="imfile"/)
end
it 'will include module parameter PollingInterval' do
expect(chef_run).to render_file(template.path).with_content(/PollingInterval="10"/)
end
it 'is owned by root:root' do
expect(template.owner).to eq('root')
expect(template.group).to eq('root')
end
it 'has 0644 permissions' do
expect(template.mode).to eq('0644')
end
it 'notifies restarting the service' do
expect(template).to notify(service_resource).to(:restart)
end
end
end
end
end
# Config generated by Chef - manual edits will be overwritten
#
# /etc/rsyslog.d/35-imfile.conf
#
# Configure the imfile module.
#
<% if node['rsyslog']['use_imfile'] -%>
$ModLoad imfile
<% end %>
# Config generated by Chef - manual edits will be overwritten
#
# /etc/rsyslog.d/35-imfile.conf
#
# Configure the imfile module.
#
module(load="imfile"
<% @module_parameters.each do |key, value| -%>
<%= "#{key}=\"#{value}\"" %>
<% end %>
)
# <%= @tag %>.conf - Syslog file inputs for <%= @tag %>
#
# Auto-generated by Chef.
# Local modifications will be overwritten.
#
$InputFileName <%= @file_name %>
$InputFileTag <%= @tag %>:
<% if @severity -%>
$InputFileSeverity <%= @severity %>
<% end %>
<% if @facility -%>
$InputFileFacility <%= @facility %>
<% end %>
$InputFileStateFile <%= @state_file %>
<% @input_parameters.each do |key,value| -%>
<%= "$InputFile#{key} #{value}" %>
<% end %>
$InputRunFileMonitor
......@@ -3,14 +3,19 @@
# Auto-generated by Chef.
# Local modifications will be overwritten.
#
$ModLoad imfile
$InputFileName <%= @file_name %>
$InputFileTag <%= @tag %>:
$InputFileStateFile <%= @state_file %>
input(type="imfile"
File="<%= @file_name %>"
Tag="<%= @tag %>:"
<% if @severity %>
$InputFileSeverity <%= @severity %>
Severity="<%= @severity %>"
<% end %>
<% if @facility %>
$InputFileFacility <%= @facility %>
Facility="<%= @facility %>"
<% end %>
$InputRunFileMonitor
<% if @state_file %>
StateFile="<%= @state_file %>"
<% end %>
<% @input_parameters.each do |key,value| -%>
<%= "#{key}=\"#{value}\"" %>
<% end %>
)
......@@ -5,3 +5,7 @@ include_recipe 'rsyslog::default'
rsyslog_file_input 'test-file' do
file '/var/log/boot'
end
rsyslog_file_input 'foo-log' do
file '/var/log/foo.log'
end
require_relative './spec_helper'
describe service('rsyslog') do
it { should be_running }
end
describe file('/etc/rsyslog.d/35-imfile.conf') do
its(:content) { should match /imfile/ }
end
describe file('/etc/rsyslog.d/99-test-file.conf') do
it { should exist }
# Confirm that old behavior is corrected
its(:content) { should_not match /\$ModLoad imfile/ }
its(:content) { should match /\/var\/log\/boot/ }
its(:content) { should match /test-file:/ }
end
# Include a second file to verify that configuration validates correctly
describe file('/etc/rsyslog.d/99-foo-log.conf') do
it { should exist }
# Confirm that old behavior is corrected
its(:content) { should_not match /\$ModLoad imfile/ }
its(:content) { should match /\/var\/log\/foo\.log/ }
its(:content) { should match /foo-log:/ }
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment