diff --git a/README.md b/README.md index 3c9773a6..4ebd2ea1 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,13 @@ exceptions: * Instead of 'daily', 'weekly', 'monthly' or 'yearly', there is a `rotate_every` parameter (see documentation below). +## logrotate::conf + +You may, optionally, define logrotate defaults using this defined type. +Parameters are the same as those for logrotate::rule. +Using this type will automatically include a private class that will install +and configure logrotate for you. + ## logrotate::rule The only thing you'll need to deal with, this type configures a logrotate rule. @@ -32,7 +39,7 @@ compressext - The extention String to be appended to the rotated log files after they have been compressed (optional). compressoptions - A String of command line options to be passed to the compression program specified in `compresscmd` (optional). -copy - A Boolean specifying whether logrotate should just take a +copy - A Boolean specifying whether logrotate should just take a copy of the log file and not touch the original (optional). copytruncate - A Boolean specifying whether logrotate should truncate the original log file after taking a copy (optional). @@ -56,7 +63,7 @@ extension - Log files with this extension String are allowed to keep it after rotation (optional). ifempty - A Boolean specifying whether the log file should be rotated even if it is empty (optional). -mail - The email address String that logs that are about to be +mail - The email address String that logs that are about to be rotated out of existence are emailed to (optional). mailfirst - A Boolean that when used with `mail` has logrotate email the just rotated file rather than the about to expire file @@ -82,7 +89,7 @@ prerotate - A command String that should be executed by /bin/sh before firstaction - A command String that should be executed by /bin/sh once before all log files that match the wildcard pattern are rotated (optional). -lastaction - A command String that should be execute by /bin/sh once +lastaction - A command String that should be execute by /bin/sh once after all the log files that match the wildcard pattern are rotated (optional). rotate - The Integer number of rotated log files to keep on disk @@ -94,7 +101,7 @@ rotate_every - How often the log files should be rotated as a String. size - The String size a log file has to reach before it will be rotated (optional). The default units are bytes, append k, M or G for kilobytes, megabytes or gigabytes respectively. -sharedscripts - A Boolean specifying whether logrotate should run the +sharedscripts - A Boolean specifying whether logrotate should run the postrotate and prerotate scripts for each matching file or just once (optional). shred - A Boolean specifying whether logs should be deleted with @@ -112,6 +119,13 @@ Further details about these options can be found by reading `man 8 logrotate`. ### Examples ``` +logrotate::conf { '/etc/logrotate.conf': + rotate => 10, + rotate_every => 'week', + ifempty => true, + dateext => true, +} + logrotate::rule { 'messages': path => '/var/log/messages', rotate => 5, diff --git a/files/etc/logrotate.conf b/files/etc/logrotate.conf deleted file mode 100644 index 2cdc6f61..00000000 --- a/files/etc/logrotate.conf +++ /dev/null @@ -1,15 +0,0 @@ -# THIS FILE IS AUTOMATICALLY DISTRIBUTED BY PUPPET. ANY CHANGES WILL BE -# OVERWRITTEN. - -# Default values -# rotate log files weekly -weekly - -# keep 4 weeks worth of backlogs -rotate 4 - -# create new (empty) log files after rotating old ones -create - -# packages drop log rotation information into this directory -include /etc/logrotate.d diff --git a/manifests/base.pp b/manifests/base.pp deleted file mode 100644 index 706a0d43..00000000 --- a/manifests/base.pp +++ /dev/null @@ -1,43 +0,0 @@ -# Internal: Install logrotate and configure it to read from /etc/logrotate.d -# -# Examples -# -# include logrotate::base -class logrotate::base { - package { 'logrotate': - ensure => latest, - } - - File { - owner => 'root', - group => 'root', - require => Package['logrotate'], - } - - file { - '/etc/logrotate.conf': - ensure => file, - mode => '0444', - source => 'puppet:///modules/logrotate/etc/logrotate.conf'; - '/etc/logrotate.d': - ensure => directory, - mode => '0755'; - '/etc/cron.daily/logrotate': - ensure => file, - mode => '0555', - source => 'puppet:///modules/logrotate/etc/cron.daily/logrotate'; - } - - case $::osfamily { - 'Debian': { - include logrotate::defaults::debian - } - 'RedHat': { - include logrotate::defaults::redhat - } - 'SuSE': { - include logrotate::defaults::suse - } - default: { } - } -} diff --git a/manifests/conf.pp b/manifests/conf.pp new file mode 100644 index 00000000..1d0fff86 --- /dev/null +++ b/manifests/conf.pp @@ -0,0 +1,307 @@ +# Internal: Install and configure logrotate defaults file, usually +# /etc/logrotate.conf +# +# see logrotate::rule for description of options. +# +# Examples +# +# logrotate::conf{'/etc/logrotate.conf':} +# +define logrotate::conf ( + $ensure = 'present', + $compress = 'undef', + $compresscmd = 'undef', + $compressext = 'undef', + $compressoptions = 'undef', + $copy = 'undef', + $copytruncate = 'undef', + $create = true, + $create_mode = 'undef', + $create_owner = 'undef', + $create_group = 'undef', + $dateext = 'undef', + $dateformat = 'undef', + $delaycompress = 'undef', + $extension = 'undef', + $ifempty = 'undef', + $mail = 'undef', + $mailfirst = 'undef', + $maillast = 'undef', + $maxage = 'undef', + $minsize = 'undef', + $missingok = 'undef', + $olddir = 'undef', + $postrotate = 'undef', + $prerotate = 'undef', + $firstaction = 'undef', + $lastaction = 'undef', + $rotate = '4', + $rotate_every = 'weekly', + $size = 'undef', + $sharedscripts = 'undef', + $shred = 'undef', + $shredcycles = 'undef', + $start = 'undef', + $su_user = 'undef', + $su_group = 'undef', + $uncompresscmd = 'undef' +) { + +############################################################################# +# SANITY CHECK VALUES + + if $name !~ /^[a-zA-Z0-9\._\/-]+$/ { + fail("Logrotate::Rule[${name}]: namevar must be alphanumeric") + } + + case $ensure { + 'present','file': {} + 'absent': {} + default: { + fail("Logrotate::Rule[${name}]: invalid ensure value") + } + } + + case $compress { + 'undef': {} + true: { $_compress = 'compress' } + false: { $_compress = 'nocompress' } + default: { + fail("Logrotate::Rule[${name}]: compress must be a boolean") + } + } + + case $copy { + 'undef': {} + true: { $_copy = 'copy' } + false: { $_copy = 'nocopy' } + default: { + fail("Logrotate::Rule[${name}]: copy must be a boolean") + } + } + + case $copytruncate { + 'undef': {} + true: { $_copytruncate = 'copytruncate' } + false: { $_copytruncate = 'nocopytruncate' } + default: { + fail("Logrotate::Rule[${name}]: copytruncate must be a boolean") + } + } + + case $create { + 'undef': {} + true: { $_create = 'create' } + false: { $_create = 'nocreate' } + default: { + fail("Logrotate::Rule[${name}]: create must be a boolean") + } + } + + case $delaycompress { + 'undef': {} + true: { $_delaycompress = 'delaycompress' } + false: { $_delaycompress = 'nodelaycompress' } + default: { + fail("Logrotate::Rule[${name}]: delaycompress must be a boolean") + } + } + + case $dateext { + 'undef': {} + true: { $_dateext = 'dateext' } + false: { $_dateext = 'nodateext' } + default: { + fail("Logrotate::Rule[${name}]: dateext must be a boolean") + } + } + + case $mail { + 'undef': {} + false: { $_mail = 'nomail' } + default: { + $_mail = "mail ${mail}" + } + } + + case $missingok { + 'undef': {} + true: { $_missingok = 'missingok' } + false: { $_missingok = 'nomissingok' } + default: { + fail("Logrotate::Rule[${name}]: missingok must be a boolean") + } + } + + case $olddir { + 'undef': {} + false: { $_olddir = 'noolddir' } + default: { + $_olddir = "olddir ${olddir}" + } + } + + case $sharedscripts { + 'undef': {} + true: { $_sharedscripts = 'sharedscripts' } + false: { $_sharedscripts = 'nosharedscripts' } + default: { + fail("Logrotate::Rule[${name}]: sharedscripts must be a boolean") + } + } + + case $shred { + 'undef': {} + true: { $_shred = 'shred' } + false: { $_shred = 'noshred' } + default: { + fail("Logrotate::Rule[${name}]: shred must be a boolean") + } + } + + case $ifempty { + 'undef': {} + true: { $_ifempty = 'ifempty' } + false: { $_ifempty = 'notifempty' } + default: { + fail("Logrotate::Rule[${name}]: ifempty must be a boolean") + } + } + + case $rotate_every { + 'undef': {} + 'day': { $_rotate_every = 'daily' } + 'week': { $_rotate_every = 'weekly' } + 'month': { $_rotate_every = 'monthly' } + 'year': { $_rotate_every = 'yearly' } + 'daily', 'weekly','monthly','yearly': { $_rotate_every = $rotate_every } + default: { + fail("Logrotate::Rule[${name}]: invalid rotate_every value") + } + } + + case $maxage { + 'undef': {} + /^\d+$/: {} + default: { + fail("Logrotate::Rule[${name}]: maxage must be an integer") + } + } + + case $minsize { + 'undef': {} + /^\d+[kMG]?$/: {} + default: { + fail("Logrotate::Rule[${name}]: minsize must match /\\d+[kMG]?/") + } + } + + case $rotate { + 'undef': {} + /^\d+$/: {} + default: { + fail("Logrotate::Rule[${name}]: rotate must be an integer") + } + } + + case $size { + 'undef': {} + /^\d+[kMG]?$/: {} + default: { + fail("Logrotate::Rule[${name}]: size must match /\\d+[kMG]?/") + } + } + + case $shredcycles { + 'undef': {} + /^\d+$/: {} + default: { + fail("Logrotate::Rule[${name}]: shredcycles must be an integer") + } + } + + case $start { + 'undef': {} + /^\d+$/: {} + default: { + fail("Logrotate::Rule[${name}]: start must be an integer") + } + } + + case $su_user { + 'undef': {} + /[a-z_][a-z0-9_]{0,30}/: {} + default: { + fail("Logrotate::Rule[${name}]: su_user must match /[a-z_][a-z0-9_]{0,30}/") + } + } + + case $su_group { + 'undef': {} + /[a-z_][a-z0-9_]{0,30}/: {} + default: { + fail("Logrotate::Rule[${name}]: su_group must match /[a-z_][a-z0-9_]{0,30}/") + } + } + + case $mailfirst { + 'undef',false: {} + true: { + if $maillast == true { + fail("Logrotate::Rule[${name}]: Can't set both mailfirst and maillast") + } + + $_mailfirst = 'mailfirst' + } + default: { + fail("Logrotate::Rule[${name}]: mailfirst must be a boolean") + } + } + + case $maillast { + 'undef',false: {} + true: { + $_maillast = 'maillast' + } + default: { + fail("Logrotate::Rule[${name}]: maillast must be a boolean") + } + } + + if ($su_user != 'undef') and ($su_group == 'undef') { + $_su_user = $_su_user + $_su_group = 'root' + } elsif ($su_user == 'undef') and ($su_group != 'undef') { + $_su_user = 'root' + $_su_group = $su_group + } elsif ($su_user != 'undef') and ($su_group != 'undef') { + $_su_user = $_su_user + $_su_group = $_su_group + } + + if ($create_group != 'undef') and ($create_owner == 'undef') { + fail("Logrotate::Rule[${name}]: create_group requires create_owner") + } + + if ($create_owner != 'undef') and ($create_mode == 'undef') { + fail("Logrotate::Rule[${name}]: create_owner requires create_mode") + } + + if ($create_mode != 'undef') and ($create != true) { + fail("Logrotate::Rule[${name}]: create_mode requires create") + } + +# +#################################################################### + + include ::logrotate + + file { $name: + ensure => $ensure, + owner => 'root', + group => 'root', + mode => '0444', + content => template('logrotate/etc/logrotate.conf.erb'), + require => Package['logrotate'], + } +} diff --git a/manifests/defaults/debian.pp b/manifests/defaults/debian.pp index 802c977e..419f24ea 100644 --- a/manifests/defaults/debian.pp +++ b/manifests/defaults/debian.pp @@ -4,21 +4,34 @@ # # include logrotate::defaults::debian class logrotate::defaults::debian { - Logrotate::Rule { - missingok => true, - rotate_every => 'month', - create => true, - create_owner => 'root', - create_group => 'utmp', - rotate => 1, + + if !defined( Logrotate::Conf['/etc/logrotate.conf'] ) { + case $::lsbdistcodename { + 'trusty': { + logrotate::conf {'/etc/logrotate.conf': + su_group => 'syslog' + } + } + default: { + logrotate::conf {'/etc/logrotate.conf': } + } + } } logrotate::rule { 'wtmp': path => '/var/log/wtmp', - create_mode => '0664'; + missingok => true, + create => true, + create_mode => '0664 root utmp', + rotate => '1', + } + logrotate::rule { 'btmp': path => '/var/log/btmp', - create_mode => '0660'; + missingok => true, + create => true, + create_mode => '0664 root utmp', + rotate => '1', } } diff --git a/manifests/defaults/redhat.pp b/manifests/defaults/redhat.pp index 72ed1fc4..fb794a31 100644 --- a/manifests/defaults/redhat.pp +++ b/manifests/defaults/redhat.pp @@ -4,6 +4,11 @@ # # include logrotate::defaults::redhat class logrotate::defaults::redhat { + + if !defined( Logrotate::Conf['/etc/logrotate.conf'] ) { + logrotate::conf {'/etc/logrotate.conf': } + } + Logrotate::Rule { missingok => true, rotate_every => 'month', diff --git a/manifests/defaults/suse.pp b/manifests/defaults/suse.pp index 92634618..ae0f6337 100644 --- a/manifests/defaults/suse.pp +++ b/manifests/defaults/suse.pp @@ -4,6 +4,11 @@ # # include logrotate::defaults::suse class logrotate::defaults::suse { + + if !defined( Logrotate::Conf['/etc/logrotate.conf'] ) { + logrotate::conf {'/etc/logrotate.conf': } + } + Logrotate::Rule { missingok => true, rotate_every => 'month', diff --git a/manifests/init.pp b/manifests/init.pp index e69de29b..ef9189e9 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -0,0 +1,69 @@ +# +class logrotate ( + $ensure = 'latest', + $hieramerge = false, + $manage_cron_daily = true, + $package = 'logrotate', + $rules = {} +) { + + validate_string($ensure) + validate_bool($hieramerge) + validate_bool($manage_cron_daily) + validate_string($package) + validate_hash($rules) + + case $ensure { + 'latest': { $_ensure = 'latest' } + false,'absent': { $_ensure = 'absent' } + default: { $_ensure = 'presest' } + } + + package { $package: + ensure => $_ensure, + } + + File { + owner => 'root', + group => 'root', + require => Package[$package], + } + + file {'/etc/logrotate.d': + ensure => directory, + mode => '0755', + } + if $manage_cron_daily { + file {'/etc/cron.daily/logrotate': + ensure => file, + mode => '0555', + source => 'puppet:///modules/logrotate/etc/cron.daily/logrotate', + } + } + + case $::osfamily { + 'Debian': { + include logrotate::defaults::debian + } + 'RedHat': { + include logrotate::defaults::redhat + } + 'SuSE': { + include logrotate::defaults::suse + } + default: { + if !defined( Logrotate::Conf['/etc/logrotate.conf'] ) { + logrotate::conf {'/etc/logrotate.conf': } + } + } + } + + if $hieramerge { + $_rules = hiera_hash('logrotate::rules', $rules) + } else { + $_rules = $rules + } + + create_resources('logrotate::rule', $_rules) + +} diff --git a/manifests/rule.pp b/manifests/rule.pp index 321414d8..0aed9f13 100644 --- a/manifests/rule.pp +++ b/manifests/rule.pp @@ -370,11 +370,11 @@ ############################################################################# # - include logrotate::base + include ::logrotate case $rotate_every { 'hour', 'hourly': { - include logrotate::hourly + include ::logrotate::hourly $rule_path = "/etc/logrotate.d/hourly/${name}" } default: { @@ -388,6 +388,6 @@ group => 'root', mode => '0444', content => template('logrotate/etc/logrotate.d/rule.erb'), - require => Class['logrotate::base'], + require => Class['logrotate'], } } diff --git a/spec/classes/base_spec.rb b/spec/classes/base_spec.rb index 33cf7d8a..c07ef95b 100644 --- a/spec/classes/base_spec.rb +++ b/spec/classes/base_spec.rb @@ -4,14 +4,15 @@ it do should contain_package('logrotate').with_ensure('latest') - should contain_file('/etc/logrotate.conf').with({ - 'ensure' => 'file', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0444', - 'source' => 'puppet:///modules/logrotate/etc/logrotate.conf', - 'require' => 'Package[logrotate]', - }) +# should contain_file('/etc/logrotate.conf').with({ +# 'ensure' => 'file', +# 'owner' => 'root', +# 'group' => 'root', +# 'mode' => '0444', +# 'content' => 'template(\'logrotate/etc/logrotate.conf.erb\')', +# 'source' => 'puppet:///modules/logrotate/etc/logrotate.conf', +# 'require' => 'Package[logrotate]', +# }) should contain_file('/etc/logrotate.d').with({ 'ensure' => 'directory', diff --git a/spec/defines/conf_spec.rb b/spec/defines/conf_spec.rb new file mode 100644 index 00000000..51b54eef --- /dev/null +++ b/spec/defines/conf_spec.rb @@ -0,0 +1,978 @@ +require 'spec_helper' + +describe 'logrotate::conf' do + context 'with an alphanumeric title' do + let(:title) { '/etc/logrotate.conf' } + + context 'and ensure => absent' do + let(:params) { {:ensure => 'absent'} } + + it do + should contain_file('/etc/logrotate.conf').with_ensure('absent') + end + end + + it do + should include_class('logrotate::base') + should contain_file('/etc/logrotate.conf').with({ + 'owner' => 'root', + 'group' => 'root', + 'ensure' => 'present', + 'mode' => '0444', + }).with_content(/\ninclude \/etc\/logrotate.d\n/) + end + + ########################################################################### + # COMPRESS + context 'and compress => true' do + let(:params) { + { :compress => true} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^compress$/) + end + end + + context 'and compress => false' do + let(:params) { + { :compress => false} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^nocompress$/) + end + end + + context 'and compress => foo' do + let(:params) { + { :compress => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /compress must be a boolean/) + end + end + + ########################################################################### + # COMPRESSCMD + context 'and compresscmd => bzip2' do + let(:params) { + { :compresscmd => 'bzip2'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^compresscmd bzip2$/) + end + end + + ########################################################################### + # COMPRESSEXT + context 'and compressext => .bz2' do + let(:params) { + { :compressext => '.bz2'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^compressext .bz2$/) + end + end + + ########################################################################### + # COMPRESSOPTIONS + context 'and compressoptions => -9' do + let(:params) { + { :compressoptions => '-9'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^compressoptions -9$/) + end + end + + ########################################################################### + # COPY + context 'and copy => true' do + let(:params) { + { :copy => true} + } + + it do + should contain_file('/etc/logrotate.conf').with_content(/^copy$/) + end + end + + context 'and copy => false' do + let(:params) { + { :copy => false} + } + + it do + should contain_file('/etc/logrotate.conf').with_content(/^nocopy$/) + end + end + + context 'and copy => foo' do + let(:params) { + { :copy => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /copy must be a boolean/) + end + end + + ########################################################################### + # COPYTRUNCATE + context 'and copytruncate => true' do + let(:params) { + { :copytruncate => true} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^copytruncate$/) + end + end + + context 'and copytruncate => false' do + let(:params) { + { :copytruncate => false} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^nocopytruncate$/) + end + end + + context 'and copytruncate => foo' do + let(:params) { + { :copytruncate => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /copytruncate must be a boolean/) + end + end + + ########################################################################### + # CREATE / CREATE_MODE / CREATE_OWNER / CREATE_GROUP + context 'and create => true' do + let(:params) { + { :create => true} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^create$/) + end + + context 'and create_mode => 0777' do + let(:params) { + { + :create => true, + :create_mode => '0777', + } + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^create 0777$/) + end + + context 'and create_owner => www-data' do + let(:params) { + { + :create => true, + :create_mode => '0777', + :create_owner => 'www-data', + } + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^create 0777 www-data/) + end + + context 'and create_group => admin' do + let(:params) { + { + :create => true, + :create_mode => '0777', + :create_owner => 'www-data', + :create_group => 'admin', + } + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^create 0777 www-data admin$/) + end + end + end + + context 'and create_group => admin' do + let(:params) { + { + :create => true, + :create_mode => '0777', + :create_group => 'admin', + } + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /create_group requires create_owner/) + end + end + end + + context 'and create_owner => www-data' do + let(:params) { + { + :create => true, + :create_owner => 'www-data', + } + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /create_owner requires create_mode/) + end + end + end + + context 'and create => false' do + let(:params) { + { :create => false} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^nocreate$/) + end + + context 'and create_mode => 0777' do + let(:params) { + { + :create => false, + :create_mode => '0777', + } + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /create_mode requires create/) + end + end + end + + context 'and create => foo' do + let(:params) { + { :create => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /create must be a boolean/) + end + end + + ########################################################################### + # DATEEXT + context 'and dateext => true' do + let(:params) { + { :dateext => true} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^dateext$/) + end + end + + context 'and dateext => false' do + let(:params) { + { :dateext => false} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^nodateext$/) + end + end + + context 'and dateext => foo' do + let(:params) { + { :dateext => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /dateext must be a boolean/) + end + end + + ########################################################################### + # DATEFORMAT + context 'and dateformat => -%Y%m%d' do + let(:params) { + { :dateformat => '-%Y%m%d'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^dateformat -%Y%m%d$/) + end + end + + ########################################################################### + # DELAYCOMPRESS + context 'and delaycompress => true' do + let(:params) { + { :delaycompress => true} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^delaycompress$/) + end + end + + context 'and delaycompress => false' do + let(:params) { + { :delaycompress => false} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^nodelaycompress$/) + end + end + + context 'and delaycompress => foo' do + let(:params) { + { :delaycompress => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /delaycompress must be a boolean/) + end + end + + ########################################################################### + # EXTENSION + context 'and extension => foo' do + let(:params) { + { :extension => '.foo'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^extension \.foo$/) + end + end + + ########################################################################### + # IFEMPTY + context 'and ifempty => true' do + let(:params) { + { :ifempty => true} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^ifempty$/) + end + end + + context 'and ifempty => false' do + let(:params) { + { :ifempty => false} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^notifempty$/) + end + end + + context 'and ifempty => foo' do + let(:params) { + { :ifempty => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /ifempty must be a boolean/) + end + end + + ########################################################################### + # MAIL / MAILFIRST / MAILLAST + context 'and mail => test.example.com' do + let(:params) { + { :mail => 'test@example.com'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^mail test@example.com$/) + end + + context 'and mailfirst => true' do + let(:params) { + { + :mail => 'test@example.com', + :mailfirst => true, + } + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^mailfirst$/) + end + + context 'and maillast => true' do + let(:params) { + { + :mail => 'test@example.com', + :mailfirst => true, + :maillast => true, + } + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /set both mailfirst and maillast/) + end + end + end + + context 'and maillast => true' do + let(:params) { + { + :mail => 'test@example.com', + :maillast => true, + } + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^maillast$/) + end + end + end + + context 'and mail => false' do + let(:params) { + { :mail => false} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^nomail$/) + end + end + + ########################################################################### + # MAXAGE + context 'and maxage => 3' do + let(:params) { + { :maxage => 3} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^maxage 3$/) + end + end + + context 'and maxage => foo' do + let(:params) { + { :maxage => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /maxage must be an integer/) + end + end + + ########################################################################### + # MINSIZE + context 'and minsize => 100' do + let(:params) { + { :minsize => 100} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^minsize 100$/) + end + end + + context 'and minsize => 100k' do + let(:params) { + { :minsize => '100k'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^minsize 100k$/) + end + end + + context 'and minsize => 100M' do + let(:params) { + { :minsize => '100M'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^minsize 100M$/) + end + end + + context 'and minsize => 100G' do + let(:params) { + { :minsize => '100G'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^minsize 100G$/) + end + end + + context 'and minsize => foo' do + let(:params) { + { :minsize => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /minsize must match/) + end + end + + ########################################################################### + # MISSINGOK + context 'and missingok => true' do + let(:params) { + { :missingok => true} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^missingok$/) + end + end + + context 'and missingok => false' do + let(:params) { + { :missingok => false} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^nomissingok$/) + end + end + + context 'and missingok => foo' do + let(:params) { + { :missingok => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /missingok must be a boolean/) + end + end + + ########################################################################### + # OLDDIR + context 'and olddir => /var/log/old' do + let(:params) { + { :olddir => '/var/log/old'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^olddir \/var\/log\/old$/) + end + end + + context 'and olddir => false' do + let(:params) { + { :olddir => false} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^noolddir$/) + end + end + + ########################################################################### + # POSTROTATE + context 'and postrotate => /bin/true' do + let(:params) { + { :postrotate => '/bin/true'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/postrotate\n\s{2}\/bin\/true\nendscript/) + end + end + + ########################################################################### + # PREROTATE + context 'and prerotate => /bin/true' do + let(:params) { + { :prerotate => '/bin/true'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/prerotate\n\s{2}\/bin\/true\nendscript/) + end + end + + ########################################################################### + # FIRSTACTION + context 'and firstaction => /bin/true' do + let(:params) { + { :firstaction => '/bin/true'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/firstaction\n\s{2}\/bin\/true\nendscript/) + end + end + + ########################################################################### + # LASTACTION + context 'and lastaction => /bin/true' do + let(:params) { + { :lastaction => '/bin/true'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/lastaction\n\s{2}\/bin\/true\nendscript/) + end + end + + ########################################################################### + # ROTATE + context 'and rotate => 3' do + let(:params) { + { :rotate => 3} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^rotate 3$/) + end + end + + context 'and rotate => foo' do + let(:params) { + { :rotate => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /rotate must be an integer/) + end + end + + ########################################################################### + # ROTATE_EVERY + context 'and rotate_every => day' do + let(:params) { + { :rotate_every => 'day'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^daily$/) + end + end + + context 'and rotate_every => week' do + let(:params) { + { :rotate_every => 'week'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^weekly$/) + end + end + + context 'and rotate_every => month' do + let(:params) { + { :rotate_every => 'month'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^monthly$/) + end + end + + context 'and rotate_every => year' do + let(:params) { + { :rotate_every => 'year'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^yearly$/) + end + end + + context 'and rotate_every => foo' do + let(:params) { + { :rotate_every => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /invalid rotate_every value/) + end + end + + ########################################################################### + # SIZE + context 'and size => 100' do + let(:params) { + { :size => 100} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^size 100$/) + end + end + + context 'and size => 100k' do + let(:params) { + { :size => '100k'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^size 100k$/) + end + end + + context 'and size => 100M' do + let(:params) { + { :size => '100M'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^size 100M$/) + end + end + + context 'and size => 100G' do + let(:params) { + { :size => '100G'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^size 100G$/) + end + end + + context 'and size => foo' do + let(:params) { + { :size => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /size must match/) + end + end + + ########################################################################### + # SHAREDSCRIPTS + context 'and sharedscripts => true' do + let(:params) { + { :sharedscripts => true} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^sharedscripts$/) + end + end + + context 'and sharedscripts => false' do + let(:params) { + { :sharedscripts => false} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^nosharedscripts$/) + end + end + + context 'and sharedscripts => foo' do + let(:params) { + { :sharedscripts => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /sharedscripts must be a boolean/) + end + end + + ########################################################################### + # SHRED / SHREDCYCLES + context 'and shred => true' do + let(:params) { + { :shred => true} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^shred$/) + end + + context 'and shredcycles => 3' do + let(:params) { + { :shred => true, :shredcycles => 3} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^shredcycles 3$/) + end + end + + context 'and shredcycles => foo' do + let(:params) { + { :shred => true, :shredcycles => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /shredcycles must be an integer/) + end + end + end + + context 'and shred => false' do + let(:params) { + { :shred => false} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^noshred$/) + end + end + + context 'and shred => foo' do + let(:params) { + { :shred => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /shred must be a boolean/) + end + end + + ########################################################################### + # START + context 'and start => 0' do + let(:params) { + { :start => 0} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^start 0$/) + end + end + + context 'and start => foo' do + let(:params) { + { :start => 'foo'} + } + + it do + expect { + should contain_file('/etc/logrotate.conf') + }.to raise_error(Puppet::Error, /start must be an integer/) + end + end + + ########################################################################### + # UNCOMPRESSCMD + context 'and uncompresscmd => bunzip2' do + let(:params) { + { :uncompresscmd => 'bunzip2'} + } + + it do + should contain_file('/etc/logrotate.conf') \ + .with_content(/^uncompresscmd bunzip2$/) + end + end + end + + context 'with a non-alphanumeric title' do + let(:title) { 'foo bar' } + + it do + expect { + should contain_file('/etc/logrotate.d/foo bar') + }.to raise_error(Puppet::Error, /namevar must be alphanumeric/) + end + end +end diff --git a/templates/etc/logrotate.conf.erb b/templates/etc/logrotate.conf.erb new file mode 100644 index 00000000..d0447c98 --- /dev/null +++ b/templates/etc/logrotate.conf.erb @@ -0,0 +1,68 @@ +# THIS FILE IS AUTOMATICALLY DISTRIBUTED BY PUPPET. +# ANY CHANGES WILL BE OVERWRITTEN. +<% + opts = [] + + if @path.kind_of?(Array) + rpath = @path.join(' ') + else + rpath = @path + end + + if scope.to_hash.has_key?('_create') + if @_create == 'create' + opts << [@_create, @create_mode, @create_owner, @create_group].reject { |r| + r == 'undef' + }.join(' ') + else + opts << @_create + end + end + + [ + '_compress', '_copy', '_copytruncate', '_delaycompress', '_dateext', + '_mail', '_missingok', '_olddir', '_sharedscripts', '_ifempty', '_maillast', + '_mailfirst', '_shred', '_rotate_every' + ].each do |bool| + opts << scope.to_hash[bool] if scope.to_hash.has_key?(bool) + end + + [ + 'compresscmd', 'compressext', 'compressoptions', 'dateformat', 'extension', + 'maxage', 'minsize', 'rotate', 'size', 'shredcycles', 'start', + 'uncompresscmd' + ].each do |key| + value = scope.to_hash[key] + opts << "#{key} #{value}" if value != 'undef' + end +-%> + +<% opts.each do |opt| -%> +<%= opt %> +<% end -%> +<% if @_su_user != 'undef' and @_su_group != 'undef' -%> +su <%= @_su_user %> <%= @_su_group %> +<% end -%> +<% if @postrotate != 'undef' -%> +postrotate + <%= @postrotate %> +endscript +<% end -%> +<% if @prerotate != 'undef' -%> +prerotate + <%= @prerotate %> +endscript +<% end -%> +<% if @firstaction != 'undef' -%> +firstaction + <%= @firstaction %> +endscript +<% end -%> +<% if @lastaction != 'undef' -%> +lastaction + <%= @lastaction %> +endscript +<% end -%> + +# configurable file rotations +include /etc/logrotate.d