]> review.fuel-infra Code Review - puppet-modules/puppetlabs-apt.git/commitdiff
Merge pull request #140 from hunner/apt_force
authorAshley Penney <ashley.penney@puppetlabs.com>
Tue, 15 Oct 2013 17:45:17 +0000 (10:45 -0700)
committerAshley Penney <ashley.penney@puppetlabs.com>
Tue, 15 Oct 2013 17:45:17 +0000 (10:45 -0700)
Handling of release parameter and apt provider in force manifest

29 files changed:
.gitignore
.nodeset.yml [new file with mode: 0644]
CHANGELOG
Gemfile
Modulefile
README.md
Rakefile
manifests/init.pp
manifests/params.pp
manifests/pin.pp
manifests/ppa.pp
manifests/unattended_upgrades.pp [new file with mode: 0644]
manifests/update.pp
metadata.json [new file with mode: 0644]
spec/classes/unattended_upgrades_spec.rb [new file with mode: 0644]
spec/defines/ppa_spec.rb
spec/defines/source_spec.rb
spec/spec_helper_system.rb [new file with mode: 0644]
spec/system/apt_builddep_spec.rb [new file with mode: 0644]
spec/system/apt_key_spec.rb [new file with mode: 0644]
spec/system/apt_ppa_spec.rb [new file with mode: 0644]
spec/system/apt_source_spec.rb [new file with mode: 0644]
spec/system/basic_spec.rb [new file with mode: 0644]
spec/system/class_spec.rb [new file with mode: 0644]
templates/10periodic.erb [new file with mode: 0644]
templates/50unattended-upgrades.erb [new file with mode: 0644]
templates/source.list.erb
tests/key.pp
tests/unattended-upgrades.pp [new file with mode: 0644]

index 0485a727cb7e84e60542c3c943b3430b3f99a3df..b77434bea0792513cdff50c8759df47957f77965 100644 (file)
@@ -2,4 +2,3 @@
 pkg/
 Gemfile.lock
 spec/fixtures/manifests
-metadata.json
diff --git a/.nodeset.yml b/.nodeset.yml
new file mode 100644 (file)
index 0000000..ad056fe
--- /dev/null
@@ -0,0 +1,19 @@
+---
+default_set: 'ubuntu-server-12042-x64'
+sets:
+  'debian-607-x64':
+    nodes:
+      "main.foo.vm":
+        prefab: 'debian-607-x64'
+  'debian-70rc1-x64':
+    nodes:
+      "main.foo.vm":
+        prefab: 'debian-70rc1-x64'
+  'ubuntu-server-10044-x64':
+    nodes:
+      "main.foo.vm":
+        prefab: 'ubuntu-server-10044-x64'
+  'ubuntu-server-12042-x64':
+    nodes:
+      "main.foo.vm":
+        prefab: 'ubuntu-server-12042-x64'
index 44fa88abb22ff66cd0a16563a24e7feb2b16f6ba..0d321bc2990ea0ad1b7c4fbc5a1ca91242ed8365 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,61 @@
-## puppetlabs-apt changelog
+2013-10-08 1.4.0
+
+Summary:
+
+Minor bugfix and allow the timeout to be adjusted.
+
+Features:
+- Add an `updates_timeout` to apt::params
+
+Fixes:
+- Ensure apt::ppa can readd a ppa removed by hand.
+
+Summary
+
+1.3.0
+=====
+
+Summary:
+
+This major feature in this release is the new apt::unattended_upgrades class,
+allowing you to handle Ubuntu's unattended feature.  This allows you to select
+specific packages to automatically upgrade without any further user
+involvement.
+
+In addition we extend our Wheezy support, add proxy support to apt:ppa and do
+various cleanups and tweaks.
+
+Features:
+- Add apt::unattended_upgrades support for Ubuntu.
+- Add wheezy backports support.
+- Use the geoDNS http.debian.net instead of the main debian ftp server.
+- Add `options` parameter to apt::ppa in order to pass options to apt-add-repository command.
+- Add proxy support for apt::ppa (uses proxy_host and proxy_port from apt).
+
+Bugfixes:
+- Fix regsubst() calls to quote single letters (for future parser).
+- Fix lint warnings and other misc cleanup.
+
+1.2.0
+=====
+
+Features:
+- Add geppetto `.project` natures
+- Add GH auto-release
+- Add `apt::key::key_options` parameter
+- Add complex pin support using distribution properties for `apt::pin` via new properties:
+  - `apt::pin::codename`
+  - `apt::pin::release_version`
+  - `apt::pin::component`
+  - `apt::pin::originator`
+  - `apt::pin::label`
+- Add source architecture support to `apt::source::architecture`
+
+Bugfixes:
+- Use apt-get instead of aptitude in apt::force
+- Update default backports location
+- Add dependency for required packages before apt-get update
 
-Release notes for the puppetlabs-apt module.
 
 1.1.1
 =====
diff --git a/Gemfile b/Gemfile
index 881fc90e21cf98c7fe8994ca6ad6062d1632632a..15bd29daf026e8b89925e26d3e81074f0b8cfb48 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -1,9 +1,12 @@
 source 'https://rubygems.org'
 
 group :development, :test do
-  gem 'rake',                   :require => false
-  gem 'rspec-puppet',           :require => false
-  gem 'puppetlabs_spec_helper', :require => false
+  gem 'rake',                    :require => false
+  gem 'rspec-puppet',            :require => false
+  gem 'puppetlabs_spec_helper',  :require => false
+  gem 'rspec-system',            :require => false
+  gem 'rspec-system-puppet',     :require => false
+  gem 'rspec-system-serverspec', :require => false
 end
 
 if puppetversion = ENV['PUPPET_GEM_VERSION']
@@ -11,5 +14,3 @@ if puppetversion = ENV['PUPPET_GEM_VERSION']
 else
   gem 'puppet', :require => false
 end
-
-# vim:ft=ruby
index 2b1b21c3f83ba825dc747fd285184a6c1115b942..72aa142e5fe41018acadb8b312d6c9dccf52ae70 100644 (file)
@@ -1,5 +1,5 @@
 name    'puppetlabs-apt'
-version '1.1.1'
+version '1.4.0'
 source  'https://github.com/puppetlabs/puppetlabs-apt'
 author  'Evolving Web / Puppet Labs'
 license 'Apache License 2.0'
index 402d7ab021982244b61a07ab923405c536418cd3..2ce5340ab62dfd128e7db318019a046d2813ad1d 100644 (file)
--- a/README.md
+++ b/README.md
@@ -54,7 +54,8 @@ The parameters for `apt` are not required in general and are predominantly for d
       proxy_port           => '8080',
       purge_sources_list   => false,
       purge_sources_list_d => false,
-      purge_preferences_d  => false
+      purge_preferences_d  => false,
+      update_timeout       => undef
     }
 
 Puppet will manage your system's `sources.list` file and `sources.list.d` directory but will do its best to respect existing content. 
index cd3d379958947f18f5aad2ab7b3262686764d49f..bb60173e570583d99123f4de02db60001d9b77c3 100644 (file)
--- a/Rakefile
+++ b/Rakefile
@@ -1 +1,2 @@
 require 'puppetlabs_spec_helper/rake_tasks'
+require 'rspec-system/rake_task'
index 23197719500809e6b4d1e5c4b4aa5ad87fdf7feb..b106ad490979ce67522382eb02f54a9ce7a1a15d 100644 (file)
@@ -12,6 +12,8 @@
 #     true, Puppet will purge all unmanaged entries from sources.list
 #   purge_sources_list_d - Accepts true or false. Defaults to false. If set
 #     to true, Puppet will purge all unmanaged entries from sources.list.d
+#   update_timeout - Overrides the exec timeout in seconds for apt-get update.
+#     If not set defaults to Exec's default (300)
 #
 # Actions:
 #
@@ -27,7 +29,8 @@ class apt(
   $proxy_port           = '8080',
   $purge_sources_list   = false,
   $purge_sources_list_d = false,
-  $purge_preferences_d  = false
+  $purge_preferences_d  = false,
+  $update_timeout       = undef
 ) {
 
   include apt::params
@@ -105,10 +108,10 @@ class apt(
   }
 
   file { 'configure-apt-proxy':
+    ensure  => $proxy_set,
     path    => "${apt_conf_d}/proxy",
     content => "Acquire::http::Proxy \"http://${proxy_host}:${proxy_port}\";",
     notify  => Exec['apt_update'],
-    ensure  => $proxy_set,
   }
 
   # Need anchor to provide containment for dependencies.
index aa0f80d60c9d292e04545898ce972c303feaa97b..955954fe89f65ea1e9e00f7aaaaf9fe5a5a610c5 100644 (file)
@@ -11,9 +11,12 @@ class apt::params {
         'squeeze': {
           $backports_location = 'http://backports.debian.org/debian-backports'
         }
-        default: {
+        'wheezy': {
           $backports_location = 'http://ftp.debian.org/debian/'
         }
+        default: {
+          $backports_location = 'http://http.debian.net/debian/'
+        }
       }
     }
     'ubuntu': {
index 39de3d8f1f688bbf1f79b5903c094558923efb07..402e79ede7a813327ec956935e07a2d9ee4e15d0 100644 (file)
@@ -31,7 +31,7 @@ define apt::pin(
     $release_version,
     $component,
     $originator,
-    $label] 
+    $label]
   $pin_release = join($pin_release_array, '')
 
   # Read the manpage 'apt_preferences(5)', especially the chapter
index 725170d2dc39dfb9c8b51841b795a8d467cb480c..7cb88c8cd5a32ec8b591e6abb1f7bac03fef68df 100644 (file)
@@ -1,7 +1,8 @@
 # ppa.pp
 
 define apt::ppa(
-  $release = $::lsbdistcodename
+  $release = $::lsbdistcodename,
+  $options = '-y'
 ) {
   include apt::params
   include apt::update
@@ -12,9 +13,9 @@ define apt::ppa(
     fail('lsbdistcodename fact not available: release parameter required')
   }
 
-  $filename_without_slashes = regsubst($name, '/', '-', G)
-  $filename_without_dots    = regsubst($filename_without_slashes, '\.', '_', G)
-  $filename_without_ppa     = regsubst($filename_without_dots, '^ppa:', '', G)
+  $filename_without_slashes = regsubst($name, '/', '-', 'G')
+  $filename_without_dots    = regsubst($filename_without_slashes, '\.', '_', 'G')
+  $filename_without_ppa     = regsubst($filename_without_dots, '^ppa:', '', 'G')
   $sources_list_d_filename  = "${filename_without_ppa}-${release}.list"
 
   $package = $::lsbdistrelease ? {
@@ -26,15 +27,28 @@ define apt::ppa(
     package { $package: }
   }
 
+  if defined(Class[apt]) {
+    $proxy_host = getparam(Class[apt], 'proxy_host')
+    $proxy_port = getparam(Class[apt], 'proxy_port')
+    case  $proxy_host {
+      false, '': {
+        $proxy_env = []
+      }
+      default: {$proxy_env = ["http_proxy=http://${proxy_host}:${proxy_port}", "https_proxy=http://${proxy_host}:${proxy_port}"]}
+    }
+  } else {
+    $proxy_env = []
+  }
   exec { "add-apt-repository-${name}":
-    command   => "/usr/bin/add-apt-repository ${name}",
-    creates   => "${sources_list_d}/${sources_list_d_filename}",
-    logoutput => 'on_failure',
-    require   => [
+    environment  => $proxy_env,
+    command      => "/usr/bin/add-apt-repository ${options} ${name}",
+    unless       => "/usr/bin/test -s ${sources_list_d}/${sources_list_d_filename}",
+    logoutput    => 'on_failure',
+    notify       => Exec['apt_update'],
+    require      => [
       File[$sources_list_d],
-      Package["${package}"],
+      Package[$package],
     ],
-    notify    => Exec['apt_update'],
   }
 
   file { "${sources_list_d}/${sources_list_d_filename}":
diff --git a/manifests/unattended_upgrades.pp b/manifests/unattended_upgrades.pp
new file mode 100644 (file)
index 0000000..f006bd5
--- /dev/null
@@ -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');
+  }
+}
index e9b9ea9554b941bf0e1757ac034d9b3114108c89..ce0b78fbddbded8805ff4e56aa1a2ad9d24a9f18 100644 (file)
@@ -5,5 +5,6 @@ class apt::update {
     command     => "${apt::params::provider} update",
     logoutput   => 'on_failure',
     refreshonly => true,
+    timeout     => $apt::update_timeout,
   }
 }
diff --git a/metadata.json b/metadata.json
new file mode 100644 (file)
index 0000000..ccb4458
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    "name": "puppetlabs/apt",
+    "version": "1.3.0",
+    "summary": "Apt key and source management",
+    "source": "git@github.com/puppetlabs/puppetlabs-apt.git",
+    "project_page": "http://github.com/puppetlabs/puppetlabs-apt",
+    "author": "Puppet Labs",
+    "license": "Apache-2.0",
+    "operatingsystem_support": [
+        "Debian",
+        "Ubuntu"
+    ],
+    "puppet_version": [
+        2.7,
+        3.0,
+        3.1,
+        3.2,
+        3.3
+    ],
+    "dependencies": [
+        {
+            "name": "puppetlabs/stdlib",
+            "version_requirement": ">= 2.2.1"
+        }
+    ]
+}
diff --git a/spec/classes/unattended_upgrades_spec.rb b/spec/classes/unattended_upgrades_spec.rb
new file mode 100644 (file)
index 0000000..8abc603
--- /dev/null
@@ -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
index 6be9ab91426d5247dbf1544c03e828e7e64ce779..5b59f57776bc389e4f1c4bf7e9ef24ac09ab8e67 100644 (file)
@@ -20,6 +20,9 @@ describe 'apt::ppa', :type => :define do
       let :package do
         "#{platform[:package]}"
       end
+      let :options do
+        "-y"
+      end
       ['ppa:dans_ppa', 'dans_ppa','ppa:dans-daily/ubuntu'].each do |t|
         describe "with title #{t}" do
           let :pre_condition do
@@ -41,8 +44,8 @@ describe 'apt::ppa', :type => :define do
           }
 
           it { should contain_exec("add-apt-repository-#{t}").with(
-            'command' => "/usr/bin/add-apt-repository #{t}",
-            'creates' => "/etc/apt/sources.list.d/#{filename}",
+            'command' => "/usr/bin/add-apt-repository #{options} #{t}",
+            'unless'  => "/usr/bin/test -s /etc/apt/sources.list.d/#{filename}",
             'require' => ["File[/etc/apt/sources.list.d]", "Package[#{package}]"],
             'notify'  => "Exec[apt_update]"
             )
@@ -55,6 +58,54 @@ describe 'apt::ppa', :type => :define do
           }
         end
       end
+      describe 'without a proxy defined' do
+        let :title do
+          'rspec_ppa'
+        end
+        let :pre_condition do
+          'class { "apt":
+             proxy_host => false
+          }'
+        end
+        let :filename do
+          "#{title}-#{release}.list"
+        end
+
+        it { should contain_exec("add-apt-repository-#{title}").with(
+          'environment' => [],
+          'command'     => "/usr/bin/add-apt-repository #{options} #{title}",
+          'unless'      => "/usr/bin/test -s /etc/apt/sources.list.d/#{filename}",
+          'require'     => ["File[/etc/apt/sources.list.d]", "Package[#{package}]"],
+          'notify'      => "Exec[apt_update]"
+          )
+        }
+      end
+
+      describe 'behind a proxy' do
+        let :title do
+          'rspec_ppa'
+        end
+        let :pre_condition do
+          'class { "apt":
+            proxy_host => "user:pass@proxy",
+          }'
+        end
+          let :filename do
+            "#{title}-#{release}.list"
+          end
+
+        it { should contain_exec("add-apt-repository-#{title}").with(
+          'environment' => [
+            "http_proxy=http://user:pass@proxy:8080",
+            "https_proxy=http://user:pass@proxy:8080",
+          ],
+          'command'     => "/usr/bin/add-apt-repository #{options} #{title}",
+          'unless'      => "/usr/bin/test -s /etc/apt/sources.list.d/#{filename}",
+          'require'     => ["File[/etc/apt/sources.list.d]", "Package[#{package}]"],
+          'notify'      => "Exec[apt_update]"
+          )
+        }
+      end
     end
   end
 
index 0a8da3d5a6a70b433536050f8796cb6ff1b7d419..9ad4d463e4939fde48a2eccd19a9b4ab1738bb13 100644 (file)
@@ -75,10 +75,10 @@ describe 'apt::source', :type => :define do
         if param_hash[:architecture]
           arch = "[arch=#{param_hash[:architecture]}]"
         end
-        content << "\ndeb #{arch} #{param_hash[:location]} #{param_hash[:release]} #{param_hash[:repos]}\n"
+        content << "\ndeb #{arch}#{param_hash[:location]} #{param_hash[:release]} #{param_hash[:repos]}\n"
 
         if param_hash[:include_src]
-          content << "deb-src #{arch} #{param_hash[:location]} #{param_hash[:release]} #{param_hash[:repos]}\n"
+          content << "deb-src #{arch}#{param_hash[:location]} #{param_hash[:release]} #{param_hash[:repos]}\n"
         end
         content
       end
diff --git a/spec/spec_helper_system.rb b/spec/spec_helper_system.rb
new file mode 100644 (file)
index 0000000..490a601
--- /dev/null
@@ -0,0 +1,30 @@
+require 'rspec-system/spec_helper'
+require 'rspec-system-puppet/helpers'
+require 'rspec-system-serverspec/helpers'
+
+include RSpecSystemPuppet::Helpers
+
+include Serverspec::Helper::RSpecSystem
+include Serverspec::Helper::DetectOS
+
+RSpec.configure do |c|
+  # Project root
+  proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+
+  # Enable colour
+  c.tty = true
+
+  c.include RSpecSystemPuppet::Helpers
+
+  # This is where we 'setup' the nodes before running our tests
+  c.before :suite do
+    # May as well update here as this can only run on apt-get machines.
+    shell('apt-get update')
+    # Install puppet
+    puppet_install
+
+    # Install modules and dependencies
+    puppet_module_install(:source => proj_root, :module_name => 'apt')
+    shell('puppet module install puppetlabs-stdlib')
+  end
+end
diff --git a/spec/system/apt_builddep_spec.rb b/spec/system/apt_builddep_spec.rb
new file mode 100644 (file)
index 0000000..fa16ab4
--- /dev/null
@@ -0,0 +1,38 @@
+require 'spec_helper_system'
+
+describe 'apt::builddep' do
+
+  context 'reset' do
+    it 'removes packages' do
+      shell('apt-get -y remove glusterfs-server')
+      shell('apt-get -y remove g++')
+    end
+  end
+
+  context 'apt::builddep' do
+    it 'should work with no errors' do
+      pp = <<-EOS
+      include '::apt'
+      apt::builddep { 'glusterfs-server': }
+      EOS
+
+      puppet_apply(pp) do |r|
+        r.exit_code.should_not == 1
+      end
+    end
+
+    describe 'should install g++ as a dependency' do
+      describe package('g++') do
+        it { should be_installed }
+      end
+    end
+  end
+
+  context 'reset' do
+    it 'removes packages' do
+      shell('apt-get -y remove glusterfs-server')
+      shell('apt-get -y remove g++')
+    end
+  end
+
+end
diff --git a/spec/system/apt_key_spec.rb b/spec/system/apt_key_spec.rb
new file mode 100644 (file)
index 0000000..4842cb5
--- /dev/null
@@ -0,0 +1,53 @@
+require 'spec_helper_system'
+
+describe 'apt::key' do
+
+  context 'reset' do
+    it 'clean up keys' do
+      shell('apt-key del 4BD6EC30')
+      shell('apt-key del D50582E6')
+    end
+  end
+
+  context 'apt::key' do
+    it 'should work with no errors' do
+      pp = <<-EOS
+      include '::apt'
+      apt::key { 'puppetlabs':
+        key        => '4BD6EC30',
+        key_server => 'pgp.mit.edu',
+      }
+
+      apt::key { 'jenkins':
+        key        => 'D50582E6',
+        key_source => 'http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key',
+      }
+      EOS
+
+      puppet_apply(pp) do |r|
+        r.exit_code.should_not == 1
+      end
+    end
+
+    describe 'keys should exist' do
+      it 'finds puppetlabs key' do
+        shell('apt-key list | grep 4BD6EC30') do |r|
+          r.exit_code.should be_zero
+        end
+      end
+      it 'finds jenkins key' do
+        shell('apt-key list | grep D50582E6') do |r|
+          r.exit_code.should be_zero
+        end
+      end
+    end
+  end
+
+  context 'reset' do
+    it 'clean up keys' do
+      shell('apt-key del 4BD6EC30')
+      shell('apt-key del D50582E6')
+    end
+  end
+
+end
diff --git a/spec/system/apt_ppa_spec.rb b/spec/system/apt_ppa_spec.rb
new file mode 100644 (file)
index 0000000..2e2baf5
--- /dev/null
@@ -0,0 +1,59 @@
+require 'spec_helper_system'
+
+describe 'apt::ppa' do
+
+  context 'reset' do
+    it 'removes ppa' do
+      shell('rm /etc/apt/sources.list.d/drizzle-developers-ppa*')
+      shell('rm /etc/apt/sources.list.d/raravena80-collectd5-*')
+    end
+  end
+
+  context 'adding a ppa that doesnt exist' do
+    it 'should work with no errors' do
+      pp = <<-EOS
+      include '::apt'
+      apt::ppa { 'ppa:drizzle-developers/ppa': }
+      EOS
+
+      puppet_apply(pp) do |r|
+        r.exit_code.should_not == 1
+      end
+    end
+
+    describe 'contains the source file' do
+      it 'contains a drizzle ppa source' do
+        shell('ls /etc/apt/sources.list.d/drizzle-developers-ppa-*.list') do |r|
+          r.exit_code.should be_zero
+        end
+      end
+    end
+  end
+
+  context 'readding a removed ppa.' do
+    it 'setup' do
+      shell('add-apt-repository -y ppa:raravena80/collectd5')
+      # This leaves a blank file
+      shell('add-apt-repository --remove ppa:raravena80/collectd5')
+    end
+
+    it 'should readd it successfully' do
+      pp = <<-EOS
+      include '::apt'
+      apt::ppa { 'ppa:raravena80/collectd5': }
+      EOS
+
+      puppet_apply(pp) do |r|
+        r.exit_code.should_not == 1
+      end
+    end
+  end
+
+  context 'reset' do
+    it 'removes added ppas' do
+      shell('rm /etc/apt/sources.list.d/drizzle-developers-ppa*')
+      shell('rm /etc/apt/sources.list.d/raravena80-collectd5-*')
+    end
+  end
+
+end
diff --git a/spec/system/apt_source_spec.rb b/spec/system/apt_source_spec.rb
new file mode 100644 (file)
index 0000000..6a445e1
--- /dev/null
@@ -0,0 +1,51 @@
+require 'spec_helper_system'
+
+describe 'apt::source' do
+
+  context 'reset' do
+    it 'clean up puppetlabs repo' do
+      shell('apt-key del 4BD6EC30')
+      shell('rm /etc/apt/sources.list.d/puppetlabs.list')
+    end
+  end
+
+  context 'apt::source' do
+    it 'should work with no errors' do
+      pp = <<-EOS
+      include '::apt'
+      apt::source { 'puppetlabs':
+        location   => 'http://apt.puppetlabs.com',
+        repos      => 'main',
+        key        => '4BD6EC30',
+        key_server => 'pgp.mit.edu',
+      }
+      EOS
+
+      puppet_apply(pp) do |r|
+        r.exit_code.should_not == 1
+      end
+    end
+
+    describe 'key should exist' do
+      it 'finds puppetlabs key' do
+        shell('apt-key list | grep 4BD6EC30') do |r|
+          r.exit_code.should be_zero
+        end
+      end
+    end
+
+    describe 'source should exist' do
+      describe file('/etc/apt/sources.list.d/puppetlabs.list') do
+        it { should be_file }
+      end
+    end
+  end
+
+  context 'reset' do
+    it 'clean up puppetlabs repo' do
+      shell('apt-key del 4BD6EC30')
+      shell('rm /etc/apt/sources.list.d/puppetlabs.list')
+    end
+  end
+
+end
diff --git a/spec/system/basic_spec.rb b/spec/system/basic_spec.rb
new file mode 100644 (file)
index 0000000..3008356
--- /dev/null
@@ -0,0 +1,10 @@
+require 'spec_helper_system'
+
+describe 'basic tests:' do
+  # Using puppet_apply as a subject
+  context puppet_apply 'notice("foo")' do
+    its(:stdout) { should =~ /foo/ }
+    its(:stderr) { should be_empty }
+    its(:exit_code) { should be_zero }
+  end
+end
diff --git a/spec/system/class_spec.rb b/spec/system/class_spec.rb
new file mode 100644 (file)
index 0000000..7bb6b8d
--- /dev/null
@@ -0,0 +1,20 @@
+require 'spec_helper_system'
+
+describe 'apt class' do
+
+  context 'default parameters' do
+    # Using puppet_apply as a helper
+    it 'should work with no errors' do
+      pp = <<-EOS
+      class { 'apt': }
+      EOS
+
+      # Run it twice and test for idempotency
+      puppet_apply(pp) do |r|
+        r.exit_code.should_not == 1
+        r.refresh
+        r.exit_code.should be_zero
+      end
+    end
+  end
+end
diff --git a/templates/10periodic.erb b/templates/10periodic.erb
new file mode 100644 (file)
index 0000000..5737c9a
--- /dev/null
@@ -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 (file)
index 0000000..4df0f74
--- /dev/null
@@ -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 %>
index 845b8ae161726ade3f617868362dfc9da975fec4..e8b68659406b256b27c991d9d6c53c3534001c65 100644 (file)
@@ -1,5 +1,5 @@
 # <%= @name %>
-deb <% if @architecture %>[arch=<%= @architecture %>]<% end %> <%= @location %> <%= @release_real %> <%= @repos %>
+deb <% if @architecture %>[arch=<%= @architecture %>]<% end %><%= @location %> <%= @release_real %> <%= @repos %>
 <%- if @include_src then -%>
-deb-src <% if @architecture %>[arch=<%= @architecture %>]<% end %> <%= @location %> <%= @release_real %> <%= @repos %>
+deb-src <% if @architecture %>[arch=<%= @architecture %>]<% end %><%= @location %> <%= @release_real %> <%= @repos %>
 <%- end -%>
index cc90f909c091f2ee56700b6c91bcc3aae9a5ebea..79e0e1b749ab17bb853548ba8188fa665d8529ab 100644 (file)
@@ -1,6 +1,6 @@
 # Declare Apt key for apt.puppetlabs.com source
 apt::key { 'puppetlabs':
-  key        => '4BD6EC30',
-  key_server => 'pgp.mit.edu',
-  key_options => "http-proxy=\"http://proxyuser:proxypass@example.org:3128\"",
+  key         => '4BD6EC30',
+  key_server  => 'pgp.mit.edu',
+  key_options => 'http-proxy="http://proxyuser:proxypass@example.org:3128"',
 }
diff --git a/tests/unattended-upgrades.pp b/tests/unattended-upgrades.pp
new file mode 100644 (file)
index 0000000..7f65ab4
--- /dev/null
@@ -0,0 +1 @@
+include apt::unattended-upgrades