summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniele Sluijters <daenney@users.noreply.github.com>2015-04-14 17:25:40 +0200
committerDaniele Sluijters <daenney@users.noreply.github.com>2015-04-14 17:25:40 +0200
commit886245f2cb7614a8c749d34e6f08ee17b92c970f (patch)
tree942f955f9ad8717c2b46aff8721e84f9b678af5d
Initial commit (this is not finished).
-rw-r--r--.fixtures.yml11
-rw-r--r--.gitignore9
-rw-r--r--.rspec2
-rw-r--r--Gemfile22
-rw-r--r--LICENSE35
-rw-r--r--README.md78
-rw-r--r--Rakefile56
-rw-r--r--manifests/init.pp69
-rw-r--r--manifests/params.pp50
-rw-r--r--spec/classes/unattended_upgrades_spec.rb32
-rw-r--r--spec/spec_helper.rb1
-rw-r--r--templates/periodic.erb47
-rw-r--r--templates/unattended-upgrades.erb60
13 files changed, 472 insertions, 0 deletions
diff --git a/.fixtures.yml b/.fixtures.yml
new file mode 100644
index 0000000..7566fe3
--- /dev/null
+++ b/.fixtures.yml
@@ -0,0 +1,11 @@
+fixtures:
+ forge_modules:
+ stdlib:
+ repo: "puppetlabs-stdlib"
+ ref: "4.5.1"
+ repositories:
+ apt:
+ repo: "https://github.com/puppetlabs/puppetlabs-apt.git"
+ ref: "2.0.x"
+ symlinks:
+ unattended_upgrades: "#{source_dir}"
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b5db85e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+pkg/
+Gemfile.lock
+vendor/
+spec/fixtures/
+.vagrant/
+.bundle/
+coverage/
+.idea/
+*.iml
diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..8c18f1a
--- /dev/null
+++ b/.rspec
@@ -0,0 +1,2 @@
+--format documentation
+--color
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..a2f968e
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,22 @@
+source "https://rubygems.org"
+
+group :test do
+ gem "rake"
+ gem "puppet", ENV['PUPPET_VERSION'] || '~> 3.7.0'
+ gem "rspec", '< 3.2.0'
+ gem "rspec-puppet", :git => 'https://github.com/rodjek/rspec-puppet.git'
+ gem "puppetlabs_spec_helper"
+ gem "metadata-json-lint"
+ gem "rspec-puppet-facts"
+end
+
+group :development do
+ gem "travis"
+ gem "travis-lint"
+ gem "puppet-blacksmith"
+end
+
+group :system_tests do
+ gem "beaker"
+ gem "beaker-rspec"
+end
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1807ab9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,35 @@
+Copyright (c) 2011 Evolving Web Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+Copyright 2014 Puppet Labs, 2015 Puppet Community
+
+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.
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6f56957
--- /dev/null
+++ b/README.md
@@ -0,0 +1,78 @@
+# unattended\_upgrades
+
+## Overview
+
+The unattended\_upgrades module allows for the installation and configuration of automatic security (and other) updates through apt.
+
+This functionality used to be part of the puppetlabs-apt module but was split off into its own module.
+
+## Module Description
+
+The unattended\_upgrades module automates the configuration of apt package updates.
+
+## Setup
+
+### What unattended\_upgrades affects:
+
+* Package/configuration for unattended\_upgrades
+
+### Beginning with unattended\_upgrades
+
+All you need to do is include the module `include unattended_upgrades`.
+
+## Usage
+
+Using unattended\_upgrades simply consists of including the module and if needed altering some of the default settings.
+
+## Reference
+
+### Classes
+
+* `unattended_upgrades`: Main class, installs the necessary packages and writes the configuration.
+
+### Parameters
+
+#### unattended\_upgrades
+
+* `auto`: A hash of settings with three possible keys:
+ * `fix_interrupted_dpkg`(`true`): Try to fix package installation state
+ * `reboot`(`false`): Reboot system after package update installation
+ * `remove`(`true`): Remove unneeded dependencies after update installation
+
+ Any of these keys can be specified and will be merged into the defaults, so if you only want to change the `reboot` behaviour the following is enough:
+
+ ```puppet
+ class { 'unattended_upgrades':
+ auto => { 'reboot' => true },
+ }
+ ```
+* `blacklist`(`[]`): A list of packages to **not** automatically upgrade. This list is empty by default.
+* `dl_limit`(`undef`): Use a bandwidth limit for downloading, specified in kb/sec.
+* `enable` (`1`): Enable the automatic installation of updates.
+* `install_on_shutdown` (`false`): Install updates on shutdown instead of in the background.
+* `legacy_origin` (`false`): Use the legacy `Unattended-Upgrade::Allowed-Origins` setting or the modern `Unattended-Upgrade::Origins-Pattern`.
+* `mail`: A hash to configure email behaviour. The possible keys are:
+ * `only_on_error` (`true`): Only send mail when something went wrong
+ * `to` (`undef`): Email address to send email too
+
+ If the default for `to` is kept you will not receive any mail at all. You'll likely want to set this parameter:
+
+ ```puppet
+ class { 'unattended_upgrades':
+ mail => { 'to' => 'admin@domain.tld', },
+ }
+ ```
+* `minimal_steps` (`true`): Split the upgrade process into sections to allow shutdown during upgrade.
+* `origins`: The repositories from which to automatically upgrade included packages.
+* `package_ensure` (`installed`): The ensure state for the 'unattended-upgrades' package.
+
+
+## Limitations
+
+This module should work across all versions of Debian/Ubuntu.
+
+## License
+
+The original code for this module comes from Evolving Web and was licensed under the MIT license. Code added since the fork of that module into puppetlabs-apt is covered under the Apache License version 2 as is any code added since it was split off into this separate unattended\_upgrades module.
+
+The LICENSE contains both licenses.
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..1778d2a
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,56 @@
+require 'puppetlabs_spec_helper/rake_tasks'
+require 'puppet/version'
+require 'puppet/vendor/semantic/lib/semantic' unless Puppet.version.to_f < 3.6
+require 'puppet-lint/tasks/puppet-lint'
+require 'puppet-syntax/tasks/puppet-syntax'
+
+# These gems aren't always present, for instance
+# on Travis with --without development
+begin
+ require 'puppet_blacksmith/rake_tasks'
+rescue LoadError
+end
+
+Rake::Task[:lint].clear
+
+PuppetLint.configuration.relative = true
+PuppetLint.configuration.send("disable_80chars")
+PuppetLint.configuration.log_format = "%{path}:%{linenumber}:%{check}:%{KIND}:%{message}"
+PuppetLint.configuration.fail_on_warnings = true
+
+# Forsake support for Puppet 2.6.2 for the benefit of cleaner code.
+# http://puppet-lint.com/checks/class_parameter_defaults/
+PuppetLint.configuration.send('disable_class_parameter_defaults')
+# http://puppet-lint.com/checks/class_inherits_from_params_class/
+PuppetLint.configuration.send('disable_class_inherits_from_params_class')
+
+exclude_paths = [
+ "bundle/**/*",
+ "pkg/**/*",
+ "vendor/**/*",
+ "spec/**/*",
+]
+PuppetLint.configuration.ignore_paths = exclude_paths
+PuppetSyntax.exclude_paths = exclude_paths
+
+desc "Run acceptance tests"
+RSpec::Core::RakeTask.new(:acceptance) do |t|
+ t.pattern = 'spec/acceptance'
+end
+
+desc "Populate CONTRIBUTORS file"
+task :contributors do
+ system("git log --format='%aN' | sort -u > CONTRIBUTORS")
+end
+
+task :metadata do
+ sh "metadata-json-lint metadata.json"
+end
+
+desc "Run syntax, lint, and spec tests."
+task :test => [
+ :syntax,
+ :lint,
+ :spec,
+ :metadata,
+]
diff --git a/manifests/init.pp b/manifests/init.pp
new file mode 100644
index 0000000..414abe2
--- /dev/null
+++ b/manifests/init.pp
@@ -0,0 +1,69 @@
+class unattended_upgrades (
+ $age = {},
+ $auto = {},
+ $backup = {},
+ $blacklist = [],
+ $dl_limit = undef,
+ $enable = 1,
+ $install_on_shutdown = false,
+ $legacy_origin = $::unattended_upgrades::params::legacy_origin,
+ $mail = {},
+ $minimal_steps = true,
+ $origins = $::unattended_upgrades::params::origins,
+ $package_ensure = installed,
+ $size = {},
+ $update = 1,
+ $upgrade = 1,
+ $upgradeable_packages = {},
+ $verbose = 0,
+) inherits ::unattended_upgrades::params {
+
+ include ::apt
+ Class['apt'] -> Class['unattended_upgrades']
+
+ validate_bool(
+ $install_on_shutdown,
+ $legacy_origin,
+ $minimal_steps,
+ )
+ validate_array($blacklist)
+ validate_array($origins)
+ validate_hash($auto)
+ $_auto = merge($auto, $::unattended_upgrades::default_auto)
+ validate_hash($mail)
+ if $mail['only_on_error'] {
+ validate_bool($mail['only_on_error'])
+ }
+ $_mail = merge($mail, $::unattended_upgrades::default_mail)
+ validate_hash($backup)
+ $_backup = merge($backup, $::unattended_upgrades::default_backup)
+ validate_hash($age)
+ $_age = merge($age, $::unattended_upgrades::default_age)
+ validate_hash($size)
+ $_size = merge($size, $::unattended_upgrades::default_size)
+ validate_hash($upgradeable_packages)
+ $_upgradeable_packages = merge($upgradeable_packages, $::unattended_upgrades::upgradeable_packages)
+
+ package { 'unattended-upgrades':
+ ensure => $package_ensure,
+ }
+
+ apt::conf { 'unattended-upgrades':
+ priority => 50,
+ content => template("${module_name}/unattended-upgrades.erb"),
+ require => Package['unattended-upgrades'],
+ }
+
+ apt::conf { 'periodic':
+ priority => 10,
+ content => template("${module_name}/periodic.erb"),
+ require => Package['unattended-upgrades'],
+ }
+
+ apt::conf { 'auto-upgrades':
+ ensure => absent,
+ priority => 20,
+ require => Package['unattended-upgrades'],
+ }
+
+}
diff --git a/manifests/params.pp b/manifests/params.pp
new file mode 100644
index 0000000..49aec20
--- /dev/null
+++ b/manifests/params.pp
@@ -0,0 +1,50 @@
+class unattended_upgrades::params {
+
+ if $::osfamily != 'Debian' {
+ fail('This module only works on Debian or derivatives like Ubuntu')
+ }
+
+ $default_auto = { 'fix_interrupted_dpkg' => true, 'remove' => true, 'reboot' => false, 'clean' => 0, }
+ $default_mail = { 'only_on_errors' => true, 'to' => undef, }
+ $default_backup = { 'archive_interval' => 0, 'level' => 3, }
+ $default_age = { 'min' => 2, 'max' => 0, }
+ $default_size = { 'max' => 0, }
+ $default_upgradeable_packages = { 'download_only' => 0, 'debdelta' => 1, }
+
+ # Strict variables facts lookup compatibility
+ $xfacts = {
+ 'lsbdistid' => defined('$lsbdistid') ? {
+ true => $::lsbdistid,
+ default => undef,
+ },
+ 'lsbdistcodename' => defined('$lsbdistcodename') ? {
+ true => $::lsbdistcodename,
+ default => undef,
+ },
+ }
+
+ case $xfacts['lsbdistid'] {
+ 'debian': {
+ case $xfacts['lsbdistcodename'] {
+ 'squeeze': {
+ $legacy_origin = true
+ $origins = ['${distro_id} oldstable', #lint:ignore:single_quote_string_with_variables
+ '${distro_id} ${distro_codename}-security', #lint:ignore:single_quote_string_with_variables
+ '${distro_id} ${distro_codename}-lts',] #lint:ignore:single_quote_string_with_variables
+ }
+ default: {
+ $legacy_origin = false
+ $origins = ['origin=Debian,archive=stable,label=Debian-Security']
+ }
+ }
+ }
+ 'ubuntu': {
+ $legacy_origin = true
+ $origins = ['${distro_id} {$distro_codename}-security', #lint:ignore:single_quote_string_with_variables
+ '${distro_id} {$distro_codename}-updates',] #lint:ignore:single_quote_string_with_variables
+ }
+ default: {
+ fail('Please explicitly specify unattended_upgrades::legacy_origin and unattended_upgrades::origins')
+ }
+ }
+}
diff --git a/spec/classes/unattended_upgrades_spec.rb b/spec/classes/unattended_upgrades_spec.rb
new file mode 100644
index 0000000..b31f3d7
--- /dev/null
+++ b/spec/classes/unattended_upgrades_spec.rb
@@ -0,0 +1,32 @@
+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(:facts) { {
+ :osfamily => 'Debian',
+ :lsbdistid => 'Debian',
+ :lsbistcodename => 'wheezy',
+ :lsbrelease => '7.0.3',
+ } }
+
+ it { should contain_package("unattended-upgrades") }
+
+ it {
+ should create_file(file_unattended).with({
+ "owner" => "root",
+ "group" => "root",
+ "mode" => "0644",
+ "require" => "Package[unattended-upgrades]",
+ })
+ }
+
+ it {
+ should create_file(file_periodic).with({
+ "owner" => "root",
+ "group" => "root",
+ "mode" => "0644",
+ "require" => "Package[unattended-upgrades]",
+ })
+ }
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..2c6f566
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1 @@
+require 'puppetlabs_spec_helper/module_spec_helper'
diff --git a/templates/periodic.erb b/templates/periodic.erb
new file mode 100644
index 0000000..8a581e0
--- /dev/null
+++ b/templates/periodic.erb
@@ -0,0 +1,47 @@
+APT::Periodic::Enable "<%= @enable %>";
+# - Enable the update/upgrade script (0=disable)
+#
+APT::Periodic::BackupArchiveInterval "<%= @_backup['archive_interval'] %>";
+# - Backup after n-days if archive contents changed.(0=disable)
+#
+APT::Periodic::BackupLevel "<%= @_backup['level'] %>";
+# - Backup level.(0=disable), 1 is invalid.
+#
+APT::Periodic::MaxAge "<%= @_age['max'] %>";
+# - Set maximum allowed age of a cache package file. If a cache
+# package file is older it is deleted (0=disable)
+#
+APT::Periodic::MinAge "<%= @_age['min'] %>";
+# - Set minimum age of a package file. If a file is younger it
+# will not be deleted (0=disable). Usefull to prevent races
+# and to keep backups of the packages for emergency.
+#
+APT::Periodic::MaxSize "<%= @_size['max'] %>";
+# - Set maximum size of the cache in MB (0=disable). If the cache
+# is bigger, cached package files are deleted until the size
+# requirement is met (the biggest packages will be deleted
+# first).
+#
+APT::Periodic::Update-Package-Lists "<%= @update %>";
+# - Do "apt-get update" automatically every n-days (0=disable)
+#
+APT::Periodic::Download-Upgradeable-Packages "<%= @_upgradeable_packages['downlaod_only'] %>";
+# - Do "apt-get upgrade --download-only" every n-days (0=disable)
+#
+# APT::Periodic::Download-Upgradeable-Packages-Debdelta "<%= @_upgradeable_packages['debdelta'] %>";
+# - Use debdelta-upgrade to download updates if available (0=disable)
+APT::Periodic::Unattended-Upgrade "<%= @upgrade %>";
+# - Run the "unattended-upgrade" security upgrade script
+# every n-days (0=disabled)
+# Requires the package "unattended-upgrades" and will write
+# a log in /var/log/unattended-upgrades
+#
+APT::Periodic::AutocleanInterval "<%= @_auto['clean'] %>";
+# - Do "apt-get autoclean" every n-days (0=disable)
+#
+APT::Periodic::Verbose "<%= @verbose %>";
+# - Send report mail to root
+# 0: no report (or null string)
+# 1: progress report (actually any string)
+# 2: + command outputs (remove -qq, remove 2>/dev/null, add -d)
+# 3: + trace on
diff --git a/templates/unattended-upgrades.erb b/templates/unattended-upgrades.erb
new file mode 100644
index 0000000..5007193
--- /dev/null
+++ b/templates/unattended-upgrades.erb
@@ -0,0 +1,60 @@
+// Automatically upgrade packages from these (origin:archive) pairs
+<%- if @legacy_origin -%>
+Unattended-Upgrade::Allowed-Origins {
+<%- else -%>
+Unattended-Upgrade::Origins-Pattern {
+<%- end -%>
+<% @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_interrupted_dpkg'].to_s %>";
+
+// 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.to_s %>";
+
+// 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.to_s %>";
+
+<% unless @mail_to.nil? %>
+// 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.
+Unattended-Upgrade::Mail "<%= @mail_to %>";
+
+// 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 "<%= @mail_only_on_error.to_s %>";
+<% end %>
+
+// Do automatic removal of new unused dependencies after the upgrade
+// (equivalent to apt-get autoremove)
+Unattended-Upgrade::Remove-Unused-Dependencies "<%= @_auto['remove'].to_s %>";
+
+// Automatically reboot *WITHOUT CONFIRMATION* if a
+// the file /var/run/reboot-required is found after the upgrade
+Unattended-Upgrade::Automatic-Reboot "<%= @_auto['reboot'].to_s %>";
+
+<% unless @dl_limit.nil? %>
+// Use apt bandwidth limit feature, this example limits the download
+// speed to 70kb/sec
+Acquire::http::Dl-Limit "<%= @dl_limit %>";
+<% end %>