diff --git a/manifests/params.pp b/manifests/params.pp index 0b7d91d..5241dbb 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -1,61 +1,61 @@ # class unattended_upgrades::params { if $facts['os']['family'] != 'Debian' { fail('This module only works on Debian or derivatives like Ubuntu') } $default_auto = { 'fix_interrupted_dpkg' => true, 'remove' => true, 'reboot' => false, 'clean' => 0, 'reboot_time' => 'now', } $default_mail = { 'only_on_error' => true, } $default_backup = { 'archive_interval' => 0, 'level' => 3, } $default_age = { 'min' => 2, 'max' => 0, } $default_upgradeable_packages = { 'download_only' => 0, 'debdelta' => 1, } # those are DEPRECATED and will be removed in a future releaseq $default_options = { 'force_confdef' => false, 'force_confold' => false, 'force_confnew' => false, 'force_confmiss' => false, } case fact('lsbdistid') { 'debian', 'raspbian': { case fact('lsbdistcodename') { 'bullseye': { $origins = [ 'origin=Debian,codename=${distro_codename},label=Debian', #lint:ignore:single_quote_string_with_variables 'origin=Debian,codename=${distro_codename}-security,label=Debian-Security', #lint:ignore:single_quote_string_with_variables ] } default: { $origins = [ 'origin=Debian,codename=${distro_codename},label=Debian', #lint:ignore:single_quote_string_with_variables 'origin=Debian,codename=${distro_codename},label=Debian-Security', #lint:ignore:single_quote_string_with_variables ] } } } 'ubuntu', 'neon': { # Ubuntu: https://ubuntu.com/about/release-cycle and https://wiki.ubuntu.com/Releases # Ubuntu 18.04 and up do allow the use of Origins-Pattern; 16.04 is out of support for Vox Pupuli. $origins = [ 'origin=${distro_id},suite=${distro_codename}', #lint:ignore:single_quote_string_with_variables 'origin=${distro_id},suite=${distro_codename}-security', #lint:ignore:single_quote_string_with_variables - 'origin=${distro_id},suite=${distro_codename}-apps-security', #lint:ignore:single_quote_string_with_variables + 'origin=${distro_id}ESMApps,suite=${distro_codename}-apps-security', #lint:ignore:single_quote_string_with_variables 'origin=${distro_id}ESM,suite=${distro_codename}-infra-security', #lint:ignore:single_quote_string_with_variables ] } 'LinuxMint': { case fact('lsbmajdistrelease') { # Linux Mint 18* is based on Ubuntu 16.04 default: { $origins = [ '${distro_id}:${distro_codename}-security', #lint:ignore:single_quote_string_with_variables ] } } } default: { $origins = undef } } } diff --git a/spec/classes/os_spec.rb b/spec/classes/os_spec.rb index 779f84e..99fa0f9 100644 --- a/spec/classes/os_spec.rb +++ b/spec/classes/os_spec.rb @@ -1,82 +1,82 @@ require 'spec_helper' describe 'unattended_upgrades' do on_supported_os.each do |os, os_facts| context "on #{os}" do let(:facts) { os_facts } let(:file_unattended) { '/etc/apt/apt.conf.d/50unattended-upgrades' } it { is_expected.to compile.with_all_deps } it do is_expected.to create_file('/etc/apt/apt.conf.d/10periodic'). with_owner('root'). with_group('root'). with_content(%r{APT::Periodic::Enable "1";}). with_content(%r{APT::Periodic::BackupArchiveInterval "0";}). with_content(%r{APT::Periodic::BackupLevel "3";}). with_content(%r{APT::Periodic::MaxAge "0";}). with_content(%r{APT::Periodic::MinAge "2";}). with_content(%r{APT::Periodic::MaxSize "0";}). with_content(%r{APT::Periodic::Update-Package-Lists "1";}). with_content(%r{APT::Periodic::Download-Upgradeable-Packages "0";}). with_content(%r{APT::Periodic::Download-Upgradeable-Packages-Debdelta "1";}). with_content(%r{APT::Periodic::Unattended-Upgrade "1";}). with_content(%r{APT::Periodic::AutocleanInterval "0";}). with_content(%r{APT::Periodic::Verbose "0";}) end it { is_expected.to contain_apt__conf('auto-upgrades').with_ensure('absent') } it do is_expected.to create_file('/etc/apt/apt.conf.d/10options'). with_owner('root'). with_group('root'). with_content(%r{^Dpkg::Options\s\{}). without_content(%r{^\s+\"--force-confdef\";}). without_content(%r{^\s+\"--force-confold\";}). without_content(%r{\"--force-confnew\";}). without_content(%r{\"--force-confmiss\";}) end it { is_expected.to create_file(file_unattended).with_owner('root').with_group('root') } # rubocop:disable Style/RegexpLiteral case os_facts[:operatingsystem] when 'Debian' case os_facts[:lsbdistcodename] when 'buster' it do is_expected.to create_file(file_unattended).with_content( /Unattended-Upgrade::Origins-Pattern\ {\n \t"origin=Debian,codename=\${distro_codename},label=Debian";\n \t"origin=Debian,codename=\${distro_codename},label=Debian-Security";\n };/x ) end when 'bullseye' it do is_expected.to create_file(file_unattended).with_content( /Unattended-Upgrade::Origins-Pattern\ {\n \t"origin=Debian,codename=\${distro_codename},label=Debian";\n \t"origin=Debian,codename=\${distro_codename}-security,label=Debian-Security";\n };/x ) end end when 'Ubuntu' it do is_expected.to create_file(file_unattended).with_content( - /Unattended-Upgrade::Allowed-Origins\ {\n - \t"\${distro_id}\:\${distro_codename}";\n - \t"\${distro_id}\:\${distro_codename}-security";\n - \t"\${distro_id}ESMApps\:\${distro_codename}-apps-security";\n - \t"\${distro_id}ESM\:\${distro_codename}-infra-security";\n + /Unattended-Upgrade::Origins-Pattern\ {\n + \t"origin=\${distro_id},suite=\${distro_codename}";\n + \t"origin=\${distro_id},suite=\${distro_codename}-security";\n + \t"origin=\${distro_id}ESMApps,suite=\${distro_codename}-apps-security";\n + \t"origin=\${distro_id}ESM,suite=\${distro_codename}-infra-security";\n };/x ) end end # rubocop:enable Style/RegexpLiteral end end end diff --git a/spec/classes/other_debians_spec.rb b/spec/classes/other_debians_spec.rb index b043465..93c5cf5 100644 --- a/spec/classes/other_debians_spec.rb +++ b/spec/classes/other_debians_spec.rb @@ -1,62 +1,31 @@ require 'spec_helper' describe 'unattended_upgrades' do let(:file_unattended) { '/etc/apt/apt.conf.d/50unattended-upgrades' } let(:file_periodic) { '/etc/apt/apt.conf.d/10periodic' } let(:file_options) { '/etc/apt/apt.conf.d/10options' } context 'with defaults on Raspbian' do let(:facts) do { os: { name: 'Raspbian', family: 'Debian', release: { full: '8.0' } }, osfamily: 'Debian', lsbdistid: 'Raspbian', lsbdistcodename: 'jessie', lsbrelease: '8.0' } end it do is_expected.to create_file(file_unattended).with( owner: 'root', group: 'root' ) end end - - context 'with defaults on Linux Mint 18 Sarah' do - let(:facts) do - { - os: { - name: 'LinuxMint', - family: 'Debian', - release: { - full: '18' - } - }, - osfamily: 'Debian', - lsbdistid: 'LinuxMint', - lsbdistcodename: 'sarah', - lsbdistrelease: '18', - lsbmajdistrelease: '18' - } - end - - it do - is_expected.to create_file(file_unattended).with( - 'owner' => 'root', - 'group' => 'root' - ).with_content( - # This is the only section that's different for Ubuntu compared to Debian - %r{\Unattended-Upgrade::Allowed-Origins\ {\n - \t"Ubuntu\:xenial-security";\n - };}x - ) - end - end end diff --git a/spec/classes/unattended_upgrades_spec.rb b/spec/classes/unattended_upgrades_spec.rb index e325d75..8930ab0 100644 --- a/spec/classes/unattended_upgrades_spec.rb +++ b/spec/classes/unattended_upgrades_spec.rb @@ -1,384 +1,384 @@ require 'spec_helper' # rubocop:disable Style/RegexpLiteral describe 'unattended_upgrades' do let(:file_unattended) { '/etc/apt/apt.conf.d/50unattended-upgrades' } let(:file_periodic) { '/etc/apt/apt.conf.d/10periodic' } let(:file_options) { '/etc/apt/apt.conf.d/10options' } shared_examples 'basic specs' do let(:params) { {} } context 'baseline specs' do it { is_expected.to compile.with_all_deps } it do is_expected.to contain_package('unattended-upgrades') is_expected.to compile.with_all_deps is_expected.to contain_class('unattended_upgrades::params') is_expected.to contain_class('unattended_upgrades') is_expected.to contain_class('apt') end it do is_expected.to contain_apt__conf('unattended-upgrades').with( require: 'Package[unattended-upgrades]', notify_update: false ) end it do is_expected.to contain_apt__conf('periodic').with( require: 'Package[unattended-upgrades]', notify_update: false ) end it do is_expected.to contain_apt__conf('options').with( require: 'Package[unattended-upgrades]', notify_update: false ) end it { is_expected.to create_file(file_unattended).without_content(/Unattended-Upgrade::Sender/) } end context 'set all the things' do let :params do { age: { 'min' => 1, 'max' => 20 }, size: 1000, update: 5, upgradeable_packages: { 'download_only' => 5, 'debdelta' => 5 }, upgrade: 5, days: %w[tuesday Thursday 5], auto: { 'clean' => 5, 'fix_interrupted_dpkg' => false, 'remove' => false, 'reboot' => true, 'reboot_time' => '03:00' }, verbose: 1, - origins: %w[bananas], + origins: %w[codename=bananas], blacklist: %w[foo bar], whitelist: %w[foo bar], minimal_steps: false, install_on_shutdown: true, mail: { 'to' => 'root@localhost', 'only_on_error' => true, 'report' => 'on-change' }, sender: 'root@server.example.com', dl_limit: 70, random_sleep: 300, notify_update: true, options: { 'force_confdef' => false, 'force_confold' => false, 'force_confnew' => true, 'force_confmiss' => true }, remove_new_unused_deps: false, syslog_enable: true, syslog_facility: 'daemon' } end it { is_expected.to contain_package('unattended-upgrades') } it do is_expected.to contain_apt__conf('unattended-upgrades').with( require: 'Package[unattended-upgrades]', notify_update: true ) end it do is_expected.to contain_apt__conf('periodic').with( require: 'Package[unattended-upgrades]', notify_update: true ) end it do is_expected.to contain_apt__conf('options').with( require: 'Package[unattended-upgrades]', notify_update: true ) end it do is_expected.to create_file(file_unattended).with( owner: 'root', group: 'root' ).with_content( - /Unattended-Upgrade::Allowed-Origins {\n\t"bananas";\n};/ + /Unattended-Upgrade::Origins-Pattern {\n\t"codename=bananas";\n};/ ).with_content( /Unattended-Upgrade::Package-Blacklist {\n\t"foo";\n\t"bar";\n};/ ).with_content( /Unattended-Upgrade::Package-Whitelist {\n\t"foo";\n\t"bar";\n};\n/ ).with_content( /Unattended-Upgrade::Update-Days {\n\t"Tuesday";\n\t"Thursday";\n\t"5";\n};/ ).with_content( /Unattended-Upgrade::AutoFixInterruptedDpkg "false";/ ).with_content( /Unattended-Upgrade::MinimalSteps "false";/ ).with_content( /Unattended-Upgrade::InstallOnShutdown "true";/ ).with_content( /Unattended-Upgrade::Remove-Unused-Dependencies "false";/ ).with_content( /Unattended-Upgrade::Automatic-Reboot "true";/ ).with_content( /Unattended-Upgrade::Automatic-Reboot-Time "03:00";/ ).with_content( /Unattended-Upgrade::Mail "root@localhost";/ ).with_content( /Unattended-Upgrade::Sender "root@server.example.com";/ ).with_content( /Unattended-Upgrade::MailOnlyOnError "true";/ ).with_content( /Unattended-Upgrade::MailReport "on-change";/ ).with_content( /Acquire::http::Dl-Limit "70";/ ).with_content( /Unattended-Upgrade::Remove-New-Unused-Dependencies "false";/ ).without_content( /Unattended-Upgrade::Remove-Unused-Kernel-Packages/ ).with_content( /Unattended-Upgrade::SyslogEnable "true";/ ).with_content( /Unattended-Upgrade::SyslogFacility "daemon";/ ) end it do is_expected.to create_file(file_periodic).with( owner: 'root', group: 'root' ).with_content( /APT::Periodic::Enable "1";/ ).with_content( /APT::Periodic::BackupArchiveInterval "0";/ ).with_content( /APT::Periodic::BackupLevel "3";/ ).with_content( /APT::Periodic::MaxAge "20";/ ).with_content( /APT::Periodic::MinAge "1";/ ).with_content( /APT::Periodic::MaxSize "1000";/ ).with_content( /APT::Periodic::Update-Package-Lists "5";/ ).with_content( /APT::Periodic::Download-Upgradeable-Packages "5";/ ).with_content( /APT::Periodic::Download-Upgradeable-Packages-Debdelta "5";/ ).with_content( /APT::Periodic::Unattended-Upgrade "5";/ ).with_content( /APT::Periodic::AutocleanInterval "5";/ ).with_content( /APT::Periodic::Verbose "1";/ ).with_content( /APT::Periodic::RandomSleep "300";/ ) end it do is_expected.to create_file(file_options).with( owner: 'root', group: 'root' ).with_content( /^Dpkg::Options\s{/ ).without_content( /"--force-confdef";/ ).without_content( /"--force-confold";/ ).with_content( /^\s+"--force-confnew";/ ).with_content( /^\s+"--force-confmiss";/ ) end it do is_expected.to contain_apt__conf('auto-upgrades').with( ensure: 'absent' ) end end describe 'validation tests' do context 'bad install_on_shutdown' do let :params do { install_on_shutdown: 'foo' } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad days' do let :params do { days: 'foo' } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad minimal_steps' do let :params do { minimal_steps: 'foo' } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad blacklist' do let :params do { blacklist: 'foo' } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad origins' do let :params do { origins: 'foo' } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad auto' do let :params do { auto: 'foo' } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad mail' do let :params do { mail: 'foo' } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad backup' do let :params do { backup: 'foo' } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad age' do let :params do { age: 'foo' } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad size' do let :params do { size: 'foo' } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad upgradeable_packages' do let :params do { upgradeable_packages: 'foo' } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad mail[\'only_on_error\']' do let :params do { mail: { 'only_on_error' => 'foo' } } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad options[\'force_confdef\']' do let :params do { options: { 'force_confdef' => 'foo' } } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad options[\'force_confold\']' do let :params do { options: { 'force_confold' => 'foo' } } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad options[\'force_confnew\']' do let :params do { options: { 'force_confnew' => 'foo' } } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad options[\'force_confmiss\']' do let :params do { options: { 'force_confmiss' => 'foo' } } end it { is_expected.to compile.and_raise_error(/got String/) } end context 'bad options[\'invalid_key\']' do let :params do { options: { 'invalid_key' => true } } end it { is_expected.to compile.and_raise_error(/unrecognized key 'invalid_key'/) } end end end on_supported_os.each do |os, facts| context "on #{os}" do let(:facts) do facts.merge(fqdn: 'unattended-upgrades.example.com', path: '/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/puppetlabs/bin:/root/bin') end it_behaves_like 'basic specs' end end end diff --git a/types/origin.pp b/types/origin.pp index 1fa46d1..9a3b169 100644 --- a/types/origin.pp +++ b/types/origin.pp @@ -1 +1 @@ -type Unattended_upgrades::Origin = Pattern[/^(origin|codename|label|site|suite|component|archive|[oalcn])=[^,]+(,?(origin|codename|label|site|suite|component|archive|[oalcn])=[^,]+)*/] +type Unattended_upgrades::Origin = Pattern[/^(origin|codename|label|site|suite|component|archive|[oalcn])=[^,]+(,(origin|codename|label|site|suite|component|archive|[oalcn])=[^,]+)*/]