From: Ashley Penney Date: Mon, 16 Sep 2013 23:18:41 +0000 (-0700) Subject: Merge pull request #153 from drbop/drbop_unattended_upgrades X-Git-Tag: 1.3.0~1 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=ef781c77fd4fd9fbee4050c1e868ea81985b84ce;hp=ec793355278ab509928b832c5f43a12736552912;p=puppet-modules%2Fpuppetlabs-apt.git Merge pull request #153 from drbop/drbop_unattended_upgrades Class for managing unattended-upgrades --- diff --git a/manifests/unattended_upgrades.pp b/manifests/unattended_upgrades.pp new file mode 100644 index 0000000..f006bd5 --- /dev/null +++ b/manifests/unattended_upgrades.pp @@ -0,0 +1,68 @@ +# Class: apt::unattended_upgrades +# +# This class manages the unattended-upgrades package and related configuration +# files for ubuntu +# +# origins are the repositories to automatically upgrade included packages +# blacklist is a list of packages to not automatically upgrade +# update is how often to run "apt-get update" in days +# download is how often to run "apt-get upgrade --download-only" in days +# upgrade is how often to upgrade packages included in the origins list in days +# autoclean is how often to run "apt-get autoclean" in days +# +# information on the other options can be found in the 50unattended-upgrades +# file and in /etc/cron.daily/apt +# +class apt::unattended_upgrades ( + $origins = ['${distro_id}:${distro_codename}-security'], + $blacklist = [], + $update = "1", + $download = "1", + $upgrade = "1", + $autoclean = "7", + $auto_fix = true, + $minimal_steps = false, + $install_on_shutdown = false, + $mail_to = "NONE", + $mail_only_on_error = false, + $remove_unused = true, + $auto_reboot = false, + $dl_limit = "NONE", + $enable = "1", + $backup_interval = "0", + $backup_level = "3", + $max_age = "0", + $min_age = "0", + $max_size = "0", + $download_delta = "0", + $verbose = "0", +) { + + validate_bool( + $auto_fix, + $minimal_steps, + $install_on_shutdown, + $mail_only_on_error, + $remove_unused, + $auto_reboot + ) + + package { 'unattended-upgrades': + ensure => present, + } + + File { + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + require => Package['unattended-upgrades'], + } + + file { + '/etc/apt/apt.conf.d/50unattended-upgrades': + content => template('apt/50unattended-upgrades.erb'); + '/etc/apt/apt.conf.d/10periodic': + content => template('apt/10periodic.erb'); + } +} diff --git a/spec/classes/unattended_upgrades_spec.rb b/spec/classes/unattended_upgrades_spec.rb new file mode 100644 index 0000000..8abc603 --- /dev/null +++ b/spec/classes/unattended_upgrades_spec.rb @@ -0,0 +1,204 @@ +require 'spec_helper' +describe 'apt::unattended_upgrades', :type => :class do + let(:file_unattended) { '/etc/apt/apt.conf.d/50unattended-upgrades' } + let(:file_periodic) { '/etc/apt/apt.conf.d/10periodic' } + + it { should contain_package("unattended-upgrades") } + + it { + should create_file("/etc/apt/apt.conf.d/50unattended-upgrades").with({ + "owner" => "root", + "group" => "root", + "mode" => "0644", + "require" => "Package[unattended-upgrades]", + }) + } + + it { + should create_file("/etc/apt/apt.conf.d/10periodic").with({ + "owner" => "root", + "group" => "root", + "mode" => "0644", + "require" => "Package[unattended-upgrades]", + }) + } + + describe "origins" do + describe "with param defaults" do + let(:params) {{ }} + it { should contain_file(file_unattended).with_content(/^Unattended-Upgrade::Allowed-Origins \{\n\t"\${distro_id}:\${distro_codename}-security";\n\};$/) } + end + + describe "with origins => ['ubuntu:precise-security']" do + let :params do + { :origins => ['ubuntu:precise-security'] } + end + it { should contain_file(file_unattended).with_content(/^Unattended-Upgrade::Allowed-Origins \{\n\t"ubuntu:precise-security";\n\};$/) } + end + end + + describe "blacklist" do + describe "with param defaults" do + let(:params) {{ }} + it { should contain_file(file_unattended).with_content(/^Unattended-Upgrade::Package-Blacklist \{\n\};$/) } + end + + describe "with blacklist => []" do + let :params do + { :blacklist => ['libc6', 'libc6-dev'] } + end + it { should contain_file(file_unattended).with_content(/^Unattended-Upgrade::Package-Blacklist \{\n\t"libc6";\n\t"libc6-dev";\n\};$/) } + end + end + + describe "with update => 2" do + let :params do + { :update => "2" } + end + it { should contain_file(file_periodic).with_content(/^APT::Periodic::Update-Package-Lists "2";$/) } + end + + describe "with download => 2" do + let :params do + { :download => "2" } + end + it { should contain_file(file_periodic).with_content(/^APT::Periodic::Download-Upgradeable-Packages "2";$/) } + end + + describe "with upgrade => 2" do + let :params do + { :upgrade => "2" } + end + it { should contain_file(file_periodic).with_content(/^APT::Periodic::Unattended-Upgrade "2";$/) } + end + + describe "with autoclean => 2" do + let :params do + { :autoclean => "2" } + end + it { should contain_file(file_periodic).with_content(/^APT::Periodic::AutocleanInterval "2";$/) } + end + + describe "with auto_fix => false" do + let :params do + { :auto_fix => false } + end + it { should contain_file(file_unattended).with_content(/^Unattended-Upgrade::AutoFixInterruptedDpkg "false";$/) } + end + + describe "with minimal_steps => true" do + let :params do + { :minimal_steps => true } + end + it { should contain_file(file_unattended).with_content(/^Unattended-Upgrade::MinimalSteps "true";$/) } + end + + describe "with install_on_shutdown => true" do + let :params do + { :install_on_shutdown => true } + end + it { should contain_file(file_unattended).with_content(/^Unattended-Upgrade::InstallOnShutdown "true";$/) } + end + + describe "mail_to" do + describe "param defaults" do + let(:params) {{ }} + it { should_not contain_file(file_unattended).with_content(/^Unattended-Upgrade::Mail /) } + it { should_not contain_file(file_unattended).with_content(/^Unattended-Upgrade::MailOnlyOnError /) } + end + + describe "with mail_to => user@website, mail_only_on_error => true" do + let :params do + { :mail_to => "user@website", + :mail_only_on_error => true } + end + it { should contain_file(file_unattended).with_content(/^Unattended-Upgrade::Mail "user@website";$/) } + it { should contain_file(file_unattended).with_content(/^Unattended-Upgrade::MailOnlyOnError "true";$/) } + end + end + + describe "with remove_unused => false" do + let :params do + { :remove_unused => false } + end + it { should contain_file(file_unattended).with_content(/^Unattended-Upgrade::Remove-Unused-Dependencies "false";$/) } + end + + describe "with auto_reboot => true" do + let :params do + { :auto_reboot => true } + end + it { should contain_file(file_unattended).with_content(/^Unattended-Upgrade::Automatic-Reboot "true";$/) } + end + + describe "dl_limit" do + describe "param defaults" do + let(:params) {{ }} + it { should_not contain_file(file_unattended).with_content(/^Acquire::http::Dl-Limit /) } + end + + describe "with dl_limit => 70" do + let :params do + { :dl_limit => "70" } + end + it { should contain_file(file_unattended).with_content(/^Acquire::http::Dl-Limit "70";$/) } + end + end + + describe "with enable => 0" do + let :params do + { :enable => "0" } + end + it { should contain_file(file_periodic).with_content(/^APT::Periodic::Enable "0";$/) } + end + + describe "with backup_interval => 1" do + let :params do + { :backup_interval => "1" } + end + it { should contain_file(file_periodic).with_content(/^APT::Periodic::BackUpArchiveInterval "1";$/) } + end + + describe "with backup_level => 0" do + let :params do + { :backup_level => "0" } + end + it { should contain_file(file_periodic).with_content(/^APT::Periodic::BackUpLevel "0";$/) } + end + + describe "with max_age => 1" do + let :params do + { :max_age => "1" } + end + it { should contain_file(file_periodic).with_content(/^APT::Periodic::MaxAge "1";$/) } + end + + describe "with min_age => 1" do + let :params do + { :min_age => "1" } + end + it { should contain_file(file_periodic).with_content(/^APT::Periodic::MinAge "1";$/) } + end + + describe "with max_size => 1" do + let :params do + { :max_size => "1" } + end + it { should contain_file(file_periodic).with_content(/^APT::Periodic::MaxSize "1";$/) } + end + + describe "with download_delta => 2" do + let :params do + { :download_delta => "2" } + end + it { should contain_file(file_periodic).with_content(/^APT::Periodic::Download-Upgradeable-Packages-Debdelta "2";$/) } + end + + describe "with verbose => 2" do + let :params do + { :verbose => "2" } + end + it { should contain_file(file_periodic).with_content(/^APT::Periodic::Verbose "2";$/) } + end + +end diff --git a/templates/10periodic.erb b/templates/10periodic.erb new file mode 100644 index 0000000..5737c9a --- /dev/null +++ b/templates/10periodic.erb @@ -0,0 +1,12 @@ +APT::Periodic::Enable "<%= @enable %>"; +APT::Periodic::BackUpArchiveInterval "<%= @backup_interval %>"; +APT::Periodic::BackUpLevel "<%= @backup_level %>"; +APT::Periodic::MaxAge "<%= @max_age %>"; +APT::Periodic::MinAge "<%= @min_age %>"; +APT::Periodic::MaxSize "<%= @max_size %>"; +APT::Periodic::Update-Package-Lists "<%= @update %>"; +APT::Periodic::Download-Upgradeable-Packages "<%= @download %>"; +APT::Periodic::Download-Upgradeable-Packages-Debdelta "<%= @download_delta %>"; +APT::Periodic::Unattended-Upgrade "<%= @upgrade %>"; +APT::Periodic::AutocleanInterval "<%= @autoclean %>"; +APT::Periodic::Verbose "<%= @verbose %>"; diff --git a/templates/50unattended-upgrades.erb b/templates/50unattended-upgrades.erb new file mode 100644 index 0000000..4df0f74 --- /dev/null +++ b/templates/50unattended-upgrades.erb @@ -0,0 +1,53 @@ +// Automatically upgrade packages from these (origin:archive) pairs +Unattended-Upgrade::Allowed-Origins { +<% @origins.each do |origin| -%> + "<%= origin %>"; +<% end -%> +}; + +// List of packages to not update +Unattended-Upgrade::Package-Blacklist { +<% @blacklist.each do |package| -%> + "<%= package %>"; +<% end -%> +}; + +// This option allows you to control if on a unclean dpkg exit +// unattended-upgrades will automatically run +// dpkg --force-confold --configure -a +// The default is true, to ensure updates keep getting installed +Unattended-Upgrade::AutoFixInterruptedDpkg "<%= @auto_fix %>"; + +// Split the upgrade into the smallest possible chunks so that +// they can be interrupted with SIGUSR1. This makes the upgrade +// a bit slower but it has the benefit that shutdown while a upgrade +// is running is possible (with a small delay) +Unattended-Upgrade::MinimalSteps "<%= @minimal_steps %>"; + +// Install all unattended-upgrades when the machine is shuting down +// instead of doing it in the background while the machine is running +// This will (obviously) make shutdown slower +Unattended-Upgrade::InstallOnShutdown "<%= @install_on_shutdown %>"; + +// Send email to this address for problems or packages upgrades +// If empty or unset then no email is sent, make sure that you +// have a working mail setup on your system. A package that provides +// 'mailx' must be installed. +<% if @mail_to != "NONE" %>Unattended-Upgrade::Mail "<%= @mail_to %>";<% end %> + +// Set this value to "true" to get emails only on errors. Default +// is to always send a mail if Unattended-Upgrade::Mail is set +<% if @mail_to != "NONE" %>Unattended-Upgrade::MailOnlyOnError "<%= @mail_only_on_error %>";<% end %> + +// Do automatic removal of new unused dependencies after the upgrade +// (equivalent to apt-get autoremove) +Unattended-Upgrade::Remove-Unused-Dependencies "<%= @remove_unused %>"; + +// Automatically reboot *WITHOUT CONFIRMATION* if a +// the file /var/run/reboot-required is found after the upgrade +Unattended-Upgrade::Automatic-Reboot "<%= @auto_reboot %>"; + + +// Use apt bandwidth limit feature, this example limits the download +// speed to 70kb/sec +<% if @dl_limit != "NONE" %>Acquire::http::Dl-Limit "<%= @dl_limit %>";<% end %> diff --git a/tests/unattended-upgrades.pp b/tests/unattended-upgrades.pp new file mode 100644 index 0000000..7f65ab4 --- /dev/null +++ b/tests/unattended-upgrades.pp @@ -0,0 +1 @@ +include apt::unattended-upgrades