From 5da4674208563183e29e2753d5efeeb8a22de591 Mon Sep 17 00:00:00 2001 From: Mathieu Sauve-Frankel Date: Wed, 6 Aug 2014 07:21:49 +0900 Subject: [PATCH] first cut at apt::unattended-upgrades recipe --- .kitchen.yml | 12 ++++ attributes/default.rb | 13 ++++ recipes/unattended-upgrades.rb | 43 +++++++++++++ spec/unattended-upgrades_spec.rb | 24 +++++++ templates/default/20auto-upgrades.erb | 2 + templates/default/50unattended-upgrades.erb | 62 +++++++++++++++++++ .../default/unattended-upgrades.seed.erb | 1 + .../apt_test/recipes/unattended-upgrades.rb | 20 ++++++ 8 files changed, 177 insertions(+) create mode 100644 recipes/unattended-upgrades.rb create mode 100644 spec/unattended-upgrades_spec.rb create mode 100644 templates/default/20auto-upgrades.erb create mode 100644 templates/default/50unattended-upgrades.erb create mode 100644 templates/default/unattended-upgrades.seed.erb create mode 100644 test/cookbooks/apt_test/recipes/unattended-upgrades.rb diff --git a/.kitchen.yml b/.kitchen.yml index 39d527b7..13c3bc1a 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -12,6 +12,8 @@ platforms: run_list: apt::default - name: ubuntu-13.10 run_list: apt::default + - name: ubuntu-14.0.4 + run_list: apt::default suites: - name: default @@ -44,3 +46,13 @@ suites: run_list: - recipe[minitest-handler] - recipe[apt_test::lwrps] + + - name: unattended-upgrades + run_list: + - recipe[minitest-handler] + - recipe[apt_test::unattended-upgrades] + attributes: + apt: + unattended_upgrades: + enabled: true + diff --git a/attributes/default.rb b/attributes/default.rb index 394331db..ea8e6944 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -27,3 +27,16 @@ default['apt']['key_proxy'] = '' default['apt']['cache_bypass'] = {} default['apt']['periodic_update_min_delay'] = 86_400 +default['apt']['unattended_upgrades']['enable'] = false +default['apt']['unattended_upgrades']['update_package_lists'] = true +# this needs a good default +default['apt']['unattended_upgrades']['allowed_origins'] = [] +default['apt']['unattended_upgrades']['package_blacklist'] = [] +default['apt']['unattended_upgrades']['auto_fix_interrupted_dpkg'] = false +default['apt']['unattended_upgrades']['minimal_steps'] = false +default['apt']['unattended_upgrades']['install_on_shutdown'] = false +default['apt']['unattended_upgrades']['mail'] = nil +default['apt']['unattended_upgrades']['mail_only_on_error'] = true +default['apt']['unattended_upgrades']['remove_unused_dependencies'] = false +default['apt']['unattended_upgrades']['automatic_reboot'] = false +default['apt']['unattended_upgrades']['dl_limit'] = nil diff --git a/recipes/unattended-upgrades.rb b/recipes/unattended-upgrades.rb new file mode 100644 index 00000000..e4dfa279 --- /dev/null +++ b/recipes/unattended-upgrades.rb @@ -0,0 +1,43 @@ +# +# Cookbook Name:: apt +# Recipe:: unattended-upgrades +# +# Copyright 2014, Opscode, Inc. +# +# 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. +# + +# On systems where apt is not installed, the resources in this recipe are not +# executed. However, they _must_ still be present in the resource collection +# or other cookbooks which notify these resources will fail on non-apt-enabled +# systems. +# + +package 'unattended-upgrades' do + response_file 'unattended-upgrades.seed.erb' + action :install +end + +template '/etc/apt/apt.conf.d/20auto-upgrades' do + owner 'root' + group 'root' + mode '644' + source '20auto-upgrades.erb' +end + +template '/etc/apt/apt.conf.d/50unattended-upgrades' do + owner 'root' + group 'root' + mode '644' + source '50unattended-upgrades.erb' +end diff --git a/spec/unattended-upgrades_spec.rb b/spec/unattended-upgrades_spec.rb new file mode 100644 index 00000000..73e62c46 --- /dev/null +++ b/spec/unattended-upgrades_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe 'apt::unattended-upgrades' do + context 'default' do + let(:chef_run) do + runner = ChefSpec::Runner.new + runner.converge('apt::unattended-upgrades') + end + + it 'installs unattended-upgrades' do + # expect(chef_run).to install_package 'unattended-upgrades' + end + + it 'creates 20auto-upgrades file' do + # expect(chef_run).to render_file('/etc/apt/apt.conf.d/20auto-upgrades').with_content() + # expect(chef_run).to create_file_with_content('/etc/apt/apt.conf.d/20auto-upgrades', 'APT::Periodic::Update-Package-Lists "1";') + # expect(chef_run).to create_file_with_content('/etc/apt/apt.conf.d/20auto-upgrades', 'APT::Periodic::Unattended-Upgrade "0";') + end + + it 'creates 50unattended-upgrades file' do + # expect(chef_run).to render_file('/etc/apt/apt.conf.d/50auto-upgrades').with_content() + end + end +end diff --git a/templates/default/20auto-upgrades.erb b/templates/default/20auto-upgrades.erb new file mode 100644 index 00000000..e3e51355 --- /dev/null +++ b/templates/default/20auto-upgrades.erb @@ -0,0 +1,2 @@ +APT::Periodic::Update-Package-Lists "<%= node['apt']['unattended_upgrades']['update_package_lists'] ? 1 : 0 %>"; +APT::Periodic::Unattended-Upgrade "<%= node['apt']['unattended_upgrades']['enabled'] ? 1 : 0 %>"; diff --git a/templates/default/50unattended-upgrades.erb b/templates/default/50unattended-upgrades.erb new file mode 100644 index 00000000..eaa3fe33 --- /dev/null +++ b/templates/default/50unattended-upgrades.erb @@ -0,0 +1,62 @@ +// Automatically upgrade packages from these (origin:archive) pairs +Unattended-Upgrade::Allowed-Origins { +<% unless node['apt']['unattended_upgrades']['allowed_origins'].empty? -%> +<% node['apt']['unattended_upgrades']['allowed_origins'].each do |origin| -%> + <%= origin %> +<% end -%> +<% end -%> +}; + + +// List of packages to not update +Unattended-Upgrade::Package-Blacklist { +<% unless node['apt']['unattended_upgrades']['package_blacklist'].empty? -%> +<% node['apt']['unattended_upgrades']['package_blacklist'].each do |package| -%> + <%= package %> +<% end -%> +<% 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 "<%= node['apt']['unattended_upgrades']['auto_fix_interrupted_dpkg'] ? 'true' : 'false' %>"; + +// 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 "<%= node['apt']['unattended_upgrades']['minimal_steps'] ? 'true' : 'false' %>"; + +// 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 "<%= node['apt']['unattended_upgrades']['install_on_shutdown'] ? 'true' : 'false' %>"; + +// 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 node['apt']['unattended_upgrades']['mail'] -%> +Unattended-Upgrade::Mail "<%= node['apt']['unattended_upgrades']['mail'] %>"; +<% 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 +Unattended-Upgrade::MailOnlyOnError "<%= node['apt']['unattended_upgrades']['mail_only_on_error'] ? 'true' : 'false' %>"; + +// Do automatic removal of new unused dependencies after the upgrade +// (equivalent to apt-get autoremove) +Unattended-Upgrade::Remove-Unused-Dependencies "<%= node['apt']['unattended_upgrades']['remove_unused_dependencies'] ? 'true' : 'false' %>"; + +// Automatically reboot *WITHOUT CONFIRMATION* if a +// the file /var/run/reboot-required is found after the upgrade +Unattended-Upgrade::Automatic-Reboot "<%= node['apt']['unattended_upgrades']['automatic_reboot'] ? 'true' : 'false' %>"; + + +// Use apt bandwidth limit feature, this example limits the download +// speed to 70kb/sec +<% if node['apt']['unattended_upgrades']['dl_limit'] -%> +Acquire::http::Dl-Limit "<%= node['apt']['unattended_upgrades']['dl_limit'] %>"; +<% end -%> diff --git a/templates/default/unattended-upgrades.seed.erb b/templates/default/unattended-upgrades.seed.erb new file mode 100644 index 00000000..5ee5e939 --- /dev/null +++ b/templates/default/unattended-upgrades.seed.erb @@ -0,0 +1 @@ +unattended-upgrades unattended-upgrades/enable_auto_updates boolean <%= node['apt']['unattended_upgrades']['enable'] ? 'true' : 'false' %> diff --git a/test/cookbooks/apt_test/recipes/unattended-upgrades.rb b/test/cookbooks/apt_test/recipes/unattended-upgrades.rb new file mode 100644 index 00000000..29e144dc --- /dev/null +++ b/test/cookbooks/apt_test/recipes/unattended-upgrades.rb @@ -0,0 +1,20 @@ +# +# Cookbook Name:: apt_test +# Recipe:: unattended-upgrades +# +# Copyright 2014, Opscode, Inc. +# +# 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. +# + +include_recipe 'apt::unattended-upgrades'