Merge pull request #227 from daniellawrence/file_perms_apt_ppa
authorHunter Haugen <hunter@puppetlabs.com>
Tue, 25 Feb 2014 17:30:37 +0000 (09:30 -0800)
committerHunter Haugen <hunter@puppetlabs.com>
Tue, 25 Feb 2014 17:30:37 +0000 (09:30 -0800)
Force owner and mode on ppa files

42 files changed:
.travis.yml
Gemfile
LICENSE
README.md
lib/puppet/provider/apt_key/apt_key.rb [new file with mode: 0644]
lib/puppet/type/apt_key.rb [new file with mode: 0644]
lib/puppet_x/apt_key/patch_openuri.rb [new file with mode: 0644]
manifests/init.pp
manifests/params.pp
manifests/ppa.pp
manifests/unattended_upgrades.pp
spec/acceptance/apt_builddep_spec.rb
spec/acceptance/apt_key_provider_spec.rb [new file with mode: 0644]
spec/acceptance/apt_key_spec.rb
spec/acceptance/apt_ppa_spec.rb
spec/acceptance/apt_source_spec.rb
spec/acceptance/apt_spec.rb
spec/acceptance/backports_spec.rb
spec/acceptance/class_spec.rb
spec/acceptance/conf_spec.rb
spec/acceptance/force_spec.rb
spec/acceptance/nodesets/ubuntu-server-10044-x64.yml [new file with mode: 0644]
spec/acceptance/pin_spec.rb
spec/acceptance/release_spec.rb
spec/acceptance/unattended_upgrade_spec.rb
spec/acceptance/unsupported_spec.rb [new file with mode: 0644]
spec/classes/apt_spec.rb
spec/classes/debian_testing_spec.rb
spec/classes/debian_unstable_spec.rb
spec/classes/params_spec.rb
spec/classes/release_spec.rb
spec/classes/unattended_upgrades_spec.rb
spec/defines/builddep_spec.rb
spec/defines/conf_spec.rb
spec/defines/force_spec.rb
spec/defines/key_spec.rb
spec/defines/pin_spec.rb
spec/defines/ppa_spec.rb
spec/defines/source_spec.rb
spec/spec_helper_acceptance.rb
spec/unit/puppet/type/apt_key_spec.rb [new file with mode: 0644]
templates/pin.pref.erb

index 582efdf70ad12aa3884d199fa386f45727ba3ba3..a6cfda65063509664d7ba457f06a67395506e14d 100644 (file)
@@ -15,9 +15,10 @@ rvm:
 env:
   matrix:
     - PUPPET_GEM_VERSION="~> 2.7.0"
-    - PUPPET_GEM_VERSION="~> 3.0.0"
     - PUPPET_GEM_VERSION="~> 3.1.0"
     - PUPPET_GEM_VERSION="~> 3.2.0"
+    - PUPPET_GEM_VERSION="~> 3.3.0"
+    - PUPPET_GEM_VERSION="~> 3.4.0"
   global:
   - PUBLISHER_LOGIN=puppetlabs
   - secure: |-
@@ -31,11 +32,7 @@ matrix:
       env: PUPPET_GEM_VERSION="~> 2.7.0"
     - rvm: 2.0.0
       env: PUPPET_GEM_VERSION="~> 2.7.0"
-    - rvm: 2.0.0
-      env: PUPPET_GEM_VERSION="~> 3.0.0"
     - rvm: 2.0.0
       env: PUPPET_GEM_VERSION="~> 3.1.0"
-    - rvm: 1.8.7
-      env: PUPPET_GEM_VERSION="~> 3.2.0"
 notifications:
   email: false
diff --git a/Gemfile b/Gemfile
index cd7fbc89b8b34018b9c9ac830299f7af65f9acd2..1e359d07b563e2c3d869945136c3ab01aa00b64e 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -2,6 +2,7 @@ source ENV['GEM_SOURCE'] || 'https://rubygems.org'
 
 group :development, :test do
   gem 'rake',                    :require => false
+  gem 'pry',                     :require => false
   gem 'rspec-puppet',            :require => false
   gem 'puppet-lint',             :require => false
   gem 'puppetlabs_spec_helper',  :require => false
diff --git a/LICENSE b/LICENSE
index 638c347b17382cfa59642a046d4a40ceda1f4af3..30ce036d5e0b1c677f62bc641f7b0d3120b00ce2 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -17,3 +17,18 @@ 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
+
+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.
index 3a7bc8ca0c2a061fc2d99266336cb041d9650f24..000d6599aa6dad045449cea5b2c981166262eb34 100644 (file)
--- a/README.md
+++ b/README.md
@@ -17,14 +17,14 @@ The APT module provides a simple interface for managing APT source, key, and def
 Module Description
 ------------------
 
-APT automates obtaining and installing software packages on *nix systems. 
+APT automates obtaining and installing software packages on \*nix systems.
 
 Setup
 -----
 
 **What APT affects:**
 
-* package/service/configuration files for APT 
+* package/service/configuration files for APT
 * your system's `sources.list` file and `sources.list.d` directory
     * NOTE: Setting the `purge_sources_list` and `purge_sources_list_d` parameters to 'true' will destroy any existing content that was not declared with Puppet. The default for these parameters is 'false'.
 * system repositories
@@ -36,14 +36,14 @@ Setup
 To begin using the APT module with default parameters, declare the class
 
     include apt
-Puppet code that uses anything from the APT module requires that the core apt class be declared
+
+Puppet code that uses anything from the APT module requires that the core apt class be declared/\s\+$//e
 
 Usage
 -----
 
-Using the APT module consists predominantly in declaring classes that provide desired functionality and features. 
+Using the APT module consists predominantly in declaring classes that provide desired functionality and features.
+
 ### apt
 
 `apt` provides a number of common resources and options that are shared by the various defined types in this module, so you MUST always include this class in your manifests.
@@ -61,9 +61,9 @@ The parameters for `apt` are not required in general and are predominantly for d
       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. 
+Puppet will manage your system's `sources.list` file and `sources.list.d` directory but will do its best to respect existing content.
 
-If you declare your apt class with `purge_sources_list` and `purge_sources_list_d` set to 'true', Puppet will unapologetically purge any existing content it finds that wasn't declared with Puppet. 
+If you declare your apt class with `purge_sources_list` and `purge_sources_list_d` set to 'true', Puppet will unapologetically purge any existing content it finds that wasn't declared with Puppet.
 
 ### apt::builddep
 
@@ -76,9 +76,9 @@ Installs the build depends of a specified package.
 Forces a package to be installed from a specific release.  This class is particularly useful when using repositories, like Debian, that are unstable in Ubuntu.
 
     apt::force { 'glusterfs-server':
-         release => 'unstable',
-         version => '3.0.3',
-         require => Apt::Source['debian_unstable'],
+      release => 'unstable',
+      version => '3.0.3',
+      require => Apt::Source['debian_unstable'],
     }
 
 ### apt::key
@@ -171,7 +171,7 @@ This test will set up a Puppet Labs apt repository. Start by creating a new smok
       key        => '4BD6EC30',
       key_server => 'pgp.mit.edu',
     }
-    
+
 This resource creates an apt source named puppetlabs and gives Puppet information about the repository's location and key used to sign its packages. Puppet leverages Facter to determine the appropriate release, but you can set it directly by adding the release type.
 
 Check your smoke test for syntax errors
@@ -185,7 +185,7 @@ If you receive no output from that command, it means nothing is wrong. Then appl
     info: /Stage[main]//Apt::Source[puppetlabs]/File[puppetlabs.list]: Scheduling refresh of Exec[puppetlabs apt update]
     notice: /Stage[main]//Apt::Source[puppetlabs]/Exec[puppetlabs apt update]: Triggered 'refresh' from 1 events>
 
-The above example used a smoke test to easily lay out a resource declaration and apply it on your system. In production, you may want to declare your APT sources inside the classes where they’re needed. 
+The above example used a smoke test to easily lay out a resource declaration and apply it on your system. In production, you may want to declare your APT sources inside the classes where they’re needed.
 
 Implementation
 --------------
@@ -197,7 +197,7 @@ Adds the necessary components to get backports for Ubuntu and Debian. The releas
 Limitations
 -----------
 
-This module should work across all versions of Debian/Ubuntu and support all major APT repository management features. 
+This module should work across all versions of Debian/Ubuntu and support all major APT repository management features.
 
 Development
 ------------
@@ -208,6 +208,13 @@ We want to keep it as easy as possible to contribute changes so that our modules
 
 You can read the complete module contribution guide [on the Puppet Labs wiki.](http://projects.puppetlabs.com/projects/module-site/wiki/Module_contributing)
 
+License
+-------
+
+The original code for this module comes from Evolving Web and was licensed under the MIT license. Code added since the fork of this module is licensed under the Apache 2.0 License like the rest of the Puppet Labs products.
+
+The LICENSE contains both licenses.
+
 Contributors
 ------------
 
@@ -215,19 +222,19 @@ A lot of great people have contributed to this module. A somewhat current list f
 
 * Ben Godfrey <ben.godfrey@wonga.com>
 * Branan Purvine-Riley <branan@puppetlabs.com>
-* Christian G. Warden <cwarden@xerus.org>  
-* Dan Bode <bodepd@gmail.com> <dan@puppetlabs.com>  
-* Garrett Honeycutt <github@garretthoneycutt.com>  
-* Jeff Wallace <jeff@evolvingweb.ca> <jeff@tjwallace.ca>  
-* Ken Barber <ken@bob.sh>  
-* Matthaus Litteken <matthaus@puppetlabs.com> <mlitteken@gmail.com>  
-* Matthias Pigulla <mp@webfactory.de>  
-* Monty Taylor <mordred@inaugust.com>  
-* Peter Drake <pdrake@allplayers.com>  
-* Reid Vandewiele <marut@cat.pdx.edu>  
-* Robert Navarro <rnavarro@phiivo.com>  
-* Ryan Coleman <ryan@puppetlabs.com>  
-* Scott McLeod <scott.mcleod@theice.com>  
-* Spencer Krum <spencer@puppetlabs.com>  
-* William Van Hevelingen <blkperl@cat.pdx.edu> <wvan13@gmail.com>  
-* Zach Leslie <zach@puppetlabs.com>  
+* Christian G. Warden <cwarden@xerus.org>
+* Dan Bode <bodepd@gmail.com> <dan@puppetlabs.com>
+* Garrett Honeycutt <github@garretthoneycutt.com>
+* Jeff Wallace <jeff@evolvingweb.ca> <jeff@tjwallace.ca>
+* Ken Barber <ken@bob.sh>
+* Matthaus Litteken <matthaus@puppetlabs.com> <mlitteken@gmail.com>
+* Matthias Pigulla <mp@webfactory.de>
+* Monty Taylor <mordred@inaugust.com>
+* Peter Drake <pdrake@allplayers.com>
+* Reid Vandewiele <marut@cat.pdx.edu>
+* Robert Navarro <rnavarro@phiivo.com>
+* Ryan Coleman <ryan@puppetlabs.com>
+* Scott McLeod <scott.mcleod@theice.com>
+* Spencer Krum <spencer@puppetlabs.com>
+* William Van Hevelingen <blkperl@cat.pdx.edu> <wvan13@gmail.com>
+* Zach Leslie <zach@puppetlabs.com>
diff --git a/lib/puppet/provider/apt_key/apt_key.rb b/lib/puppet/provider/apt_key/apt_key.rb
new file mode 100644 (file)
index 0000000..51791d0
--- /dev/null
@@ -0,0 +1,178 @@
+require 'date'
+require 'open-uri'
+require 'net/ftp'
+require 'tempfile'
+
+if RUBY_VERSION == '1.8.7'
+  # Mothers cry, puppies die and Ruby 1.8.7's open-uri needs to be
+  # monkeypatched to support passing in :ftp_passive_mode.
+  require 'puppet_x/apt_key/patch_openuri'
+  OpenURI::Options.merge!({:ftp_active_mode => false,})
+end
+
+Puppet::Type.type(:apt_key).provide(:apt_key) do
+
+  KEY_LINE = {
+    :date     => '[0-9]{4}-[0-9]{2}-[0-9]{2}',
+    :key_type => '(R|D)',
+    :key_size => '\d{4}',
+    :key_id   => '[0-9a-fA-F]+',
+    :expires  => 'expire(d|s)',
+  }
+
+  confine    :osfamily => :debian
+  defaultfor :osfamily => :debian
+  commands   :apt_key  => 'apt-key'
+
+  def self.instances
+    key_array = apt_key('list').split("\n").collect do |line|
+      line_hash = key_line_hash(line)
+      next unless line_hash
+      expired = false
+
+      if line_hash[:key_expiry]
+        expired = Date.today > Date.parse(line_hash[:key_expiry])
+      end
+
+      new(
+        :name    => line_hash[:key_id],
+        :id      => line_hash[:key_id],
+        :ensure  => :present,
+        :expired => expired,
+        :expiry  => line_hash[:key_expiry],
+        :size    => line_hash[:key_size],
+        :type    => line_hash[:key_type] == 'R' ? :rsa : :dsa,
+        :created => line_hash[:key_created]
+      )
+    end
+    key_array.compact!
+  end
+
+  def self.prefetch(resources)
+    apt_keys = instances
+    resources.keys.each do |name|
+      if provider = apt_keys.find{ |key| key.name == name }
+        resources[name].provider = provider
+      end
+    end
+  end
+
+  def self.key_line_hash(line)
+    line_array = line.match(key_line_regexp).to_a
+    return nil if line_array.length < 5
+
+    return_hash = {
+      :key_id      => line_array[3],
+      :key_size    => line_array[1],
+      :key_type    => line_array[2],
+      :key_created => line_array[4],
+      :key_expiry  => nil,
+    }
+
+    return_hash[:key_expiry] = line_array[7] if line_array.length == 8
+    return return_hash
+  end
+
+  def self.key_line_regexp
+    # This regexp is trying to match the following output
+    # pub   4096R/4BD6EC30 2010-07-10 [expires: 2016-07-08]
+    # pub   1024D/CD2EFD2A 2009-12-15
+    regexp = /\A
+      pub  # match only the public key, not signatures
+      \s+  # bunch of spaces after that
+      (#{KEY_LINE[:key_size]})  # size of the key, usually a multiple of 1024
+      #{KEY_LINE[:key_type]}  # type of the key, usually R or D
+      \/  # separator between key_type and key_id
+      (#{KEY_LINE[:key_id]})  # hex id of the key
+      \s+  # bunch of spaces after that
+      (#{KEY_LINE[:date]})  # date the key was added to the keyring
+      # following an optional block which indicates if the key has an expiration
+      # date and if it has expired yet
+      (
+        \s+  # again with thes paces
+        \[  # we open with a square bracket
+        #{KEY_LINE[:expires]}  # expires or expired
+        \:  # a colon
+        \s+  # more spaces
+        (#{KEY_LINE[:date]})  # date indicating key expiry
+        \]  # we close with a square bracket
+      )?  # end of the optional block
+      \Z/x
+      regexp
+  end
+
+  def source_to_file(value)
+    if URI::parse(value).scheme.nil?
+      fail("The file #{value} does not exist") unless File.exists?(value)
+      value
+    else
+      begin
+        key = open(value, :ftp_active_mode => false).read
+      rescue OpenURI::HTTPError, Net::FTPPermError => e
+        fail("#{e.message} for #{resource[:source]}")
+      rescue SocketError
+        fail("could not resolve #{resource[:source]}")
+      else
+        tempfile(key)
+      end
+    end
+  end
+
+  def tempfile(content)
+    file = Tempfile.new('apt_key')
+    file.write content
+    file.close
+    file.path
+  end
+
+  def exists?
+    @property_hash[:ensure] == :present
+  end
+
+  def create
+    command = []
+    if resource[:source].nil? and resource[:content].nil?
+      # Breaking up the command like this is needed because it blows up
+      # if --recv-keys isn't the last argument.
+      command.push('adv', '--keyserver', resource[:server])
+      unless resource[:keyserver_options].nil?
+        command.push('--keyserver-options', resource[:keyserver_options])
+      end
+      command.push('--recv-keys', resource[:id])
+    elsif resource[:content]
+      command.push('add', tempfile(resource[:content]))
+    elsif resource[:source]
+      command.push('add', source_to_file(resource[:source]))
+    # In case we really screwed up, better safe than sorry.
+    else
+      fail("an unexpected condition occurred while trying to add the key: #{resource[:id]}")
+    end
+    apt_key(command)
+    @property_hash[:ensure] = :present
+  end
+
+  def destroy
+    apt_key('del', resource[:id])
+    @property_hash.clear
+  end
+
+  def read_only(value)
+    fail('This is a read-only property.')
+  end
+
+  mk_resource_methods
+
+  # Needed until PUP-1470 is fixed and we can drop support for Puppet versions
+  # before that.
+  def expired
+    @property_hash[:expired]
+  end
+
+  # Alias the setters of read-only properties
+  # to the read_only function.
+  alias :created= :read_only
+  alias :expired= :read_only
+  alias :expiry=  :read_only
+  alias :size=    :read_only
+  alias :type=    :read_only
+end
diff --git a/lib/puppet/type/apt_key.rb b/lib/puppet/type/apt_key.rb
new file mode 100644 (file)
index 0000000..fa7b0c6
--- /dev/null
@@ -0,0 +1,112 @@
+require 'pathname'
+
+Puppet::Type.newtype(:apt_key) do
+
+  @doc = <<-EOS
+    This type provides Puppet with the capabilities to manage GPG keys needed
+    by apt to perform package validation. Apt has it's own GPG keyring that can
+    be manipulated through the `apt-key` command.
+
+    apt_key { '4BD6EC30':
+      source => 'http://apt.puppetlabs.com/pubkey.gpg'
+    }
+
+    **Autorequires**:
+
+    If Puppet is given the location of a key file which looks like an absolute
+    path this type will autorequire that file.
+  EOS
+
+  ensurable
+
+  validate do
+    if self[:content] and self[:source]
+      fail('The properties content and source are mutually exclusive.')
+    end
+  end
+
+  newparam(:id, :namevar => true) do
+    desc 'The ID of the key you want to manage.'
+    # GPG key ID's should be either 32-bit (short) or 64-bit (long) key ID's
+    # and may start with the optional 0x
+    newvalues(/\A(0x)?[0-9a-fA-F]{8}\Z/, /\A(0x)?[0-9a-fA-F]{16}\Z/)
+    munge do |value|
+      if value.start_with?('0x')
+        id = value.partition('0x').last.upcase
+      else
+        id = value.upcase
+      end
+      if id.length == 16
+        id[8..-1]
+      else
+        id
+      end
+    end
+  end
+
+  newparam(:content) do
+    desc 'The content of, or string representing, a GPG key.'
+  end
+
+  newparam(:source) do
+    desc 'Location of a GPG key file, /path/to/file, ftp://, http:// or https://'
+    newvalues(/\Ahttps?:\/\//, /\Aftp:\/\//, /\A\/\w+/)
+  end
+
+  autorequire(:file) do
+    if self[:source] and Pathname.new(self[:source]).absolute?
+      self[:source]
+    end
+  end
+
+  newparam(:server) do
+    desc 'The key server to fetch the key from based on the ID.'
+    defaultto :'keyserver.ubuntu.com'
+    # Need to validate this, preferably through stdlib is_fqdn
+    # but still working on getting to that.
+  end
+
+  newparam(:keyserver_options) do
+    desc 'Additional options to pass to apt-key\'s --keyserver-options.'
+  end
+
+  newproperty(:expired) do
+    desc <<-EOS
+      Indicates if the key has expired.
+
+      This property is read-only.
+    EOS
+  end
+
+  newproperty(:expiry) do
+    desc <<-EOS
+      The date the key will expire, or nil if it has no expiry date.
+
+      This property is read-only.
+    EOS
+  end
+
+  newproperty(:size) do
+    desc <<-EOS
+      The key size, usually a multiple of 1024.
+
+      This property is read-only.
+    EOS
+  end
+
+  newproperty(:type) do
+    desc <<-EOS
+      The key type, either RSA or DSA.
+
+      This property is read-only.
+    EOS
+  end
+
+  newproperty(:created) do
+    desc <<-EOS
+      Date the key was created.
+
+      This property is read-only.
+    EOS
+  end
+end
diff --git a/lib/puppet_x/apt_key/patch_openuri.rb b/lib/puppet_x/apt_key/patch_openuri.rb
new file mode 100644 (file)
index 0000000..722c7bd
--- /dev/null
@@ -0,0 +1,63 @@
+require 'uri'
+require 'stringio'
+require 'time'
+
+module URI
+  class FTP
+    def buffer_open(buf, proxy, options) # :nodoc:
+      if proxy
+        OpenURI.open_http(buf, self, proxy, options)
+        return
+      end
+      require 'net/ftp'
+
+      directories = self.path.split(%r{/}, -1)
+      directories.shift if directories[0] == '' # strip a field before leading slash
+      directories.each {|d|
+        d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") }
+      }
+      unless filename = directories.pop
+        raise ArgumentError, "no filename: #{self.inspect}"
+      end
+      directories.each {|d|
+        if /[\r\n]/ =~ d
+          raise ArgumentError, "invalid directory: #{d.inspect}"
+        end
+      }
+      if /[\r\n]/ =~ filename
+        raise ArgumentError, "invalid filename: #{filename.inspect}"
+      end
+      typecode = self.typecode
+      if typecode && /\A[aid]\z/ !~ typecode
+        raise ArgumentError, "invalid typecode: #{typecode.inspect}"
+      end
+
+      # The access sequence is defined by RFC 1738
+      ftp = Net::FTP.open(self.host)
+      ftp.passive = true if !options[:ftp_active_mode]
+      # todo: extract user/passwd from .netrc.
+      user = 'anonymous'
+      passwd = nil
+      user, passwd = self.userinfo.split(/:/) if self.userinfo
+      ftp.login(user, passwd)
+      directories.each {|cwd|
+        ftp.voidcmd("CWD #{cwd}")
+      }
+      if typecode
+        # xxx: typecode D is not handled.
+        ftp.voidcmd("TYPE #{typecode.upcase}")
+      end
+      if options[:content_length_proc]
+        options[:content_length_proc].call(ftp.size(filename))
+      end
+      ftp.retrbinary("RETR #{filename}", 4096) { |str|
+        buf << str
+        options[:progress_proc].call(buf.size) if options[:progress_proc]
+      }
+      ftp.close
+      buf.io.rewind
+    end
+
+    include OpenURI::OpenRead
+  end
+end
index b106ad490979ce67522382eb02f54a9ce7a1a15d..2de6aa056ff24740e7588146251e95665643c1ef 100644 (file)
@@ -29,6 +29,7 @@ class apt(
   $proxy_port           = '8080',
   $purge_sources_list   = false,
   $purge_sources_list_d = false,
+  $purge_preferences    = false,
   $purge_preferences_d  = false,
   $update_timeout       = undef
 ) {
@@ -36,13 +37,21 @@ class apt(
   include apt::params
   include apt::update
 
-  validate_bool($purge_sources_list, $purge_sources_list_d, $purge_preferences_d)
+  validate_bool($purge_sources_list, $purge_sources_list_d,
+                $purge_preferences, $purge_preferences_d)
 
   $sources_list_content = $purge_sources_list ? {
     false => undef,
     true  => "# Repos managed by puppet.\n",
   }
 
+  $preferences_content = $purge_preferences ? {
+    false => undef,
+    true  => "Explanation: Preferences managed by Puppet\n
+Explanation: We need a bogus package line because of Debian Bug #732746\n
+Package: bogus-package\n",
+  }
+
   if $always_apt_update == true {
     Exec <| title=='apt_update' |> {
       refreshonly => false,
@@ -75,6 +84,15 @@ class apt(
     notify  => Exec['apt_update'],
   }
 
+  file { 'apt-preferences':
+    ensure  => present,
+    path    => "${root}/preferences",
+    owner   => root,
+    group   => root,
+    mode    => '0644',
+    content => $preferences_content,
+  }
+
   file { 'preferences.d':
     ensure  => directory,
     path    => $preferences_d,
index 955954fe89f65ea1e9e00f7aaaaf9fe5a5a610c5..b35bb1c8d91b0a667d2fbb3a2ae986628db86261 100644 (file)
@@ -21,13 +21,22 @@ class apt::params {
     }
     'ubuntu': {
       case $::lsbdistcodename {
-        'hardy','lucid','maverick','natty','oneiric','precise': {
+        'hardy','maverick','natty','oneiric','precise': {
           $backports_location = 'http://us.archive.ubuntu.com/ubuntu'
+          $ppa_options = '-y'
+        }
+        'lucid': {
+          $backports_location = 'http://us.archive.ubuntu.com/ubuntu'
+          $ppa_options = undef
         }
         default: {
           $backports_location = 'http://old-releases.ubuntu.com/ubuntu'
+          $ppa_options = '-y'
         }
       }
     }
+    default: {
+      fail("Unsupported osfamily (${::osfamily}) or lsbdistid (${::lsbdistid})")
+    }
   }
 }
index 3c4dc3194e9df8f88dcd5be400dc122a8e183339..8a3b6f5f594e136113d697f5e89e73eeb61213f0 100644 (file)
@@ -3,7 +3,7 @@
 define apt::ppa(
   $ensure  = 'present',
   $release = $::lsbdistcodename,
-  $options = '-y'
+  $options = $apt::params::ppa_options,
 ) {
   include apt::params
   include apt::update
index f006bd5289b2c21ff533a898b90411ca2f8d5700..b0bd8ab1e09d7a9dae7780b511012fd227d899f3 100644 (file)
@@ -37,6 +37,7 @@ class apt::unattended_upgrades (
   $download_delta = "0",
   $verbose = "0",
 ) {
+  include apt::params
 
   validate_bool(
     $auto_fix,
index b61fca29550196008fc31073eb55ae1e8ea5effb..1e35e4aa68d9530c16c0bbc559f520261cea0b5d 100644 (file)
@@ -1,10 +1,10 @@
 require 'spec_helper_acceptance'
 
-describe 'apt::builddep' do
+describe 'apt::builddep', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
 
   context 'reset' do
     it 'removes packages' do
-      shell('apt-get -y remove glusterfs-server')
+      shell('apt-get -y remove znc')
       shell('apt-get -y remove g++')
     end
   end
@@ -13,7 +13,7 @@ describe 'apt::builddep' do
     it 'should work with no errors' do
       pp = <<-EOS
       include '::apt'
-      apt::builddep { 'glusterfs-server': }
+      apt::builddep { 'znc': }
       EOS
 
       apply_manifest(pp, :catch_failures => true)
@@ -28,7 +28,7 @@ describe 'apt::builddep' do
 
   context 'reset' do
     it 'removes packages' do
-      shell('apt-get -y remove glusterfs-server')
+      shell('apt-get -y remove znc')
       shell('apt-get -y remove g++')
     end
   end
diff --git a/spec/acceptance/apt_key_provider_spec.rb b/spec/acceptance/apt_key_provider_spec.rb
new file mode 100644 (file)
index 0000000..1d39a97
--- /dev/null
@@ -0,0 +1,446 @@
+require 'spec_helper_acceptance'
+
+PUPPETLABS_GPG_KEY_ID   = '4BD6EC30'
+PUPPETLABS_APT_URL      = 'apt.puppetlabs.com'
+PUPPETLABS_GPG_KEY_FILE = 'pubkey.gpg'
+CENTOS_GPG_KEY_ID       = 'C105B9DE'
+CENTOS_REPO_URL         = 'ftp.cvut.cz/centos'
+CENTOS_GPG_KEY_FILE     = 'RPM-GPG-KEY-CentOS-6'
+
+describe 'apt_key' do
+  before(:each) do
+    shell("apt-key del #{PUPPETLABS_GPG_KEY_ID}",
+          :acceptable_exit_codes => [0,1,2])
+  end
+
+  describe 'default options' do
+    key_versions = {
+      '32bit key id'                        => '4BD6EC30',
+      '64bit key id'                        => '1054B7A24BD6EC30',
+      '32bit lowercase key id'              => '4bd6ec30',
+      '64bit lowercase key id'              => '1054b7a24bd6ec30',
+      '0x formatted 32bit key id'           => '0x4BD6EC30',
+      '0x formatted 64bit key id'           => '0x1054B7A24BD6EC30',
+      '0x formatted 32bit lowercase key id' => '0x4bd6ec30',
+      '0x formatted 64bit lowercase key id' => '0x1054b7a24bd6ec30',
+    }
+
+    key_versions.each do |key, value|
+      context "#{key}" do
+        it 'works' do
+          pp = <<-EOS
+          apt_key { 'puppetlabs':
+            id     => '#{value}',
+            ensure => 'present',
+          }
+          EOS
+
+          apply_manifest(pp, :catch_failures => true)
+          expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+          shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+        end
+      end
+    end
+
+    context 'invalid length key id' do
+      it 'fails' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id => '4B7A24BD6EC30',
+        }
+        EOS
+
+        apply_manifest(pp, :expect_failures => true) do |r|
+          expect(r.stderr).to match(/Valid values match/)
+        end
+      end
+    end
+  end
+
+  describe 'ensure =>' do
+    context 'absent' do
+      it 'is removed' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id     => '#{PUPPETLABS_GPG_KEY_ID}',
+          ensure => 'absent',
+        }
+        EOS
+
+        # Install the key first
+        shell("apt-key adv --keyserver keyserver.ubuntu.com \
+              --recv-keys #{PUPPETLABS_GPG_KEY_ID}")
+        shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+
+        # Time to remove it using Puppet
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+
+        shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}",
+              :acceptable_exit_codes => [1])
+      end
+    end
+  end
+
+  describe 'content =>' do
+    context 'puppetlabs gpg key' do
+      it 'works' do
+        pp = <<-EOS
+          apt_key { 'puppetlabs':
+            id      => '#{PUPPETLABS_GPG_KEY_ID}',
+            ensure  => 'present',
+            content => "-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.12 (GNU/Linux)
+Comment: GPGTools - http://gpgtools.org
+
+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
+=a34C
+-----END PGP PUBLIC KEY BLOCK-----",
+          }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+        shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+      end
+    end
+
+    context 'bogus key' do
+      it 'fails' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id      => '#{PUPPETLABS_GPG_KEY_ID}',
+          ensure  => 'present',
+          content => 'For posterity: such content, much bogus, wow',
+        }
+        EOS
+
+        apply_manifest(pp, :expect_failures => true) do |r|
+          expect(r.stderr).to match(/no valid OpenPGP data found/)
+        end
+      end
+    end
+  end
+
+  describe 'server =>' do
+    context 'pgp.mit.edu' do
+      it 'works' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id     => '#{PUPPETLABS_GPG_KEY_ID}',
+          ensure => 'present',
+          server => 'pgp.mit.edu',
+        }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+        shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+      end
+    end
+
+    context 'nonexistant.key.server' do
+      it 'fails' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id     => '#{PUPPETLABS_GPG_KEY_ID}',
+          ensure => 'present',
+          server => 'nonexistant.key.server',
+        }
+        EOS
+
+        apply_manifest(pp, :expect_failures => true) do |r|
+          expect(r.stderr).to match(/Host not found/)
+        end
+      end
+    end
+  end
+
+  describe 'source =>' do
+    context 'http://' do
+      it 'works' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id     => '#{PUPPETLABS_GPG_KEY_ID}',
+          ensure => 'present',
+          source => 'http://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}',
+        }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+        shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+      end
+
+      it 'fails with a 404' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id     => '#{PUPPETLABS_GPG_KEY_ID}',
+          ensure => 'present',
+          source => 'http://#{PUPPETLABS_APT_URL}/herpderp.gpg',
+        }
+        EOS
+
+        apply_manifest(pp, :expect_failures => true) do |r|
+          expect(r.stderr).to match(/404 Not Found/)
+        end
+      end
+
+      it 'fails with a socket error' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id     => '#{PUPPETLABS_GPG_KEY_ID}',
+          ensure => 'present',
+          source => 'http://apt.puppetlabss.com/herpderp.gpg',
+        }
+        EOS
+
+        apply_manifest(pp, :expect_failures => true) do |r|
+          expect(r.stderr).to match(/could not resolve/)
+        end
+      end
+    end
+
+    context 'ftp://' do
+      before(:each) do
+        shell("apt-key del #{CENTOS_GPG_KEY_ID}",
+              :acceptable_exit_codes => [0,1,2])
+      end
+
+      it 'works' do
+        pp = <<-EOS
+        apt_key { 'CentOS 6':
+          id     => '#{CENTOS_GPG_KEY_ID}',
+          ensure => 'present',
+          source => 'ftp://#{CENTOS_REPO_URL}/#{CENTOS_GPG_KEY_FILE}',
+        }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+        shell("apt-key list | grep #{CENTOS_GPG_KEY_ID}")
+      end
+
+      it 'fails with a 550' do
+        pp = <<-EOS
+        apt_key { 'CentOS 6':
+          id     => '#{CENTOS_GPG_KEY_ID}',
+          ensure => 'present',
+          source => 'ftp://#{CENTOS_REPO_URL}/herpderp.gpg',
+        }
+        EOS
+
+        apply_manifest(pp, :expect_failures => true) do |r|
+          expect(r.stderr).to match(/550 Failed to open/)
+        end
+      end
+
+      it 'fails with a socket error' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id     => '#{PUPPETLABS_GPG_KEY_ID}',
+          ensure => 'present',
+          source => 'ftp://apt.puppetlabss.com/herpderp.gpg',
+        }
+        EOS
+
+        apply_manifest(pp, :expect_failures => true) do |r|
+          expect(r.stderr).to match(/could not resolve/)
+        end
+      end
+    end
+
+    context 'https://' do
+      it 'works' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id     => '#{PUPPETLABS_GPG_KEY_ID}',
+          ensure => 'present',
+          source => 'https://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}',
+        }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+        shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+      end
+
+      it 'fails with a 404' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id     => '4BD6EC30',
+          ensure => 'present',
+          source => 'https://#{PUPPETLABS_APT_URL}/herpderp.gpg',
+        }
+        EOS
+
+        apply_manifest(pp, :expect_failures => true) do |r|
+          expect(r.stderr).to match(/404 Not Found/)
+        end
+      end
+
+      it 'fails with a socket error' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id     => '4BD6EC30',
+          ensure => 'present',
+          source => 'https://apt.puppetlabss.com/herpderp.gpg',
+        }
+        EOS
+
+        apply_manifest(pp, :expect_failures => true) do |r|
+          expect(r.stderr).to match(/could not resolve/)
+        end
+      end
+    end
+
+    context '/path/that/exists' do
+      before(:each) do
+        shell("curl -o /tmp/puppetlabs-pubkey.gpg \
+              http://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}")
+      end
+
+      after(:each) do
+        shell('rm /tmp/puppetlabs-pubkey.gpg')
+      end
+
+      it 'works' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id     => '4BD6EC30',
+          ensure => 'present',
+          source => '/tmp/puppetlabs-pubkey.gpg',
+        }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+        shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+      end
+    end
+
+    context '/path/that/does/not/exist' do
+      it 'fails' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id     => '#{PUPPETLABS_GPG_KEY_ID}',
+          ensure => 'present',
+          source => '/tmp/totally_bogus.file',
+        }
+        EOS
+
+        apply_manifest(pp, :expect_failures => true) do |r|
+          expect(r.stderr).to match(/does not exist/)
+        end
+      end
+    end
+
+    context '/path/that/exists/with/bogus/content' do
+      before(:each) do
+        shell('echo "here be dragons" > /tmp/fake-key.gpg')
+      end
+
+      after(:each) do
+        shell('rm /tmp/fake-key.gpg')
+      end
+      it 'fails' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id     => '#{PUPPETLABS_GPG_KEY_ID}',
+          ensure => 'present',
+          source => '/tmp/fake-key.gpg',
+        }
+        EOS
+
+        apply_manifest(pp, :expect_failures => true) do |r|
+          expect(r.stderr).to match(/no valid OpenPGP data found/)
+        end
+      end
+    end
+  end
+
+  describe 'keyserver_options =>' do
+    context 'debug' do
+      it 'works' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id                => '#{PUPPETLABS_GPG_KEY_ID}',
+          ensure            => 'present',
+          keyserver_options => 'debug',
+        }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+        shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+      end
+
+      it 'fails on invalid options' do
+        pp = <<-EOS
+        apt_key { 'puppetlabs':
+          id                => '#{PUPPETLABS_GPG_KEY_ID}',
+          ensure            => 'present',
+          keyserver_options => 'this is totally bonkers',
+        }
+        EOS
+
+        apply_manifest(pp, :expect_failures => true) do |r|
+          expect(r.stderr).to match(/--keyserver-options this is totally/)
+        end
+      end
+    end
+  end
+end
index 36cba5eeffae5d77e0b98e69027337367e58501e..9f2ba395ad5945a81593adc1bbd5d77aecb82afd 100644 (file)
@@ -1,6 +1,6 @@
 require 'spec_helper_acceptance'
 
-describe 'apt::key' do
+describe 'apt::key', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
   context 'apt::key' do
     it 'should work with no errors' do
       pp = <<-EOS
index c0d216107de96913cebfaae9de713df8eff30958..b665c5cf477a84a5d74590163ebe7ae1d6a0dc35 100644 (file)
@@ -1,7 +1,7 @@
 require 'spec_helper_acceptance'
 
 if fact('operatingsystem') == 'Ubuntu'
-  describe 'apt::ppa' do
+  describe 'apt::ppa', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
 
     context 'reset' do
       it 'removes ppa' do
@@ -27,14 +27,13 @@ if fact('operatingsystem') == 'Ubuntu'
       end
     end
 
-    context 'readding a removed ppa.' do
+    context 'reading 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')
+        shell('echo > /etc/apt/sources.list.d/raravena80-collectd5-$(lsb_release -c -s).list')
       end
 
-      it 'should readd it successfully' do
+      it 'should read it successfully' do
         pp = <<-EOS
         include '::apt'
         apt::ppa { 'ppa:raravena80/collectd5': }
@@ -111,7 +110,7 @@ if fact('operatingsystem') == 'Ubuntu'
     end
 
     context 'options' do
-      context '-y' do
+      context '-y', :unless => default[:platform].match(/10\.04/) do
         it 'works without failure' do
           pp = <<-EOS
           include '::apt'
@@ -135,6 +134,5 @@ if fact('operatingsystem') == 'Ubuntu'
     context 'reset' do
       it { shell('rm -rf /etc/apt/sources.list.d/canonical-kernel-team-ppa*', :acceptable_exit_codes => [0,1,2]) }
     end
-
   end
 end
index 6b026b88c958ae918e7bf3b3ad26ccf5d2f14d91..c2d076cbff4468e8fc319918a1b943cbba97a4b5 100644 (file)
@@ -1,6 +1,6 @@
 require 'spec_helper_acceptance'
 
-describe 'apt::source' do
+describe 'apt::source', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
 
   context 'apt::source' do
     context 'ensure => present' do
index 35a0d3e70b20ae17f3ed1e26413da5f502ba8245..84b7f88281c1f6b7deda07779220f194ef4f200d 100644 (file)
@@ -1,6 +1,6 @@
 require 'spec_helper_acceptance'
 
-describe 'apt class' do
+describe 'apt class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
 
   context 'reset' do
     it 'fixes the sources.list' do
@@ -175,6 +175,50 @@ describe 'apt class' do
     end
   end
 
+  context 'purge_preferences' do
+    context 'false' do
+      it 'creates a preferences file' do
+        shell("echo 'original' > /etc/apt/preferences")
+      end
+
+      it 'should work with no errors' do
+        pp = <<-EOS
+        class { 'apt': purge_preferences => false }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      describe file('/etc/apt/preferences') do
+        it { should be_file }
+        it 'is not managed by Puppet' do
+          shell("grep 'original' /etc/apt/preferences", {:acceptable_exit_codes => 0})
+        end
+      end
+    end
+
+    context 'true' do
+      it 'creates a preferences file' do
+        shell('touch /etc/apt/preferences')
+      end
+
+      it 'should work with no errors' do
+        pp = <<-EOS
+        class { 'apt': purge_preferences => true }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      describe file('/etc/apt/preferences') do
+        it { should be_file }
+        it 'is managed by Puppet' do
+          shell("grep 'Explanation' /etc/apt/preferences", {:acceptable_exit_codes => 0})
+        end
+      end
+    end
+  end
+
   context 'purge_preferences_d' do
     context 'false' do
       it 'creates a preferences file' do
index 80e2093848c6114ddd5676a8bd88befb713db97e..6d3f7f0e68713dfbf7d0c682e3a25d1730f132db 100644 (file)
@@ -8,7 +8,7 @@ when 'Debian'
   repos = 'main contrib non-free'
 end
 
-describe 'apt::backports class' do
+describe 'apt::backports class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
   context 'defaults' do
     it 'should work with no errors' do
       pp = <<-EOS
index f228e4c4565f7b8d825b52ca83a421d2c007c142..e5994498b903ffec47f075de8f17a9d157d1428a 100644 (file)
@@ -1,6 +1,6 @@
 require 'spec_helper_acceptance'
 
-describe 'apt class' do
+describe 'apt class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
 
   context 'default parameters' do
     # Using puppet_apply as a helper
index 98898c274989006b03d0f8fc4fdd9753f898f531..8a8ed63db4df2579061817c5460300265e9943b0 100644 (file)
@@ -1,6 +1,6 @@
 require 'spec_helper_acceptance'
 
-describe 'apt::conf define' do
+describe 'apt::conf define', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
   context 'defaults' do
     it 'should work with no errors' do
       pp = <<-EOS
index c364d5fe157fdb05ea4b7e2fa6ff235841e3ee8d..a43902300d7c0c1067db5660ee82396186eda631 100644 (file)
@@ -2,7 +2,7 @@ require 'spec_helper_acceptance'
 
 codename = fact('lsbdistcodename')
 
-describe 'apt::force define' do
+describe 'apt::force define', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
   context 'defaults' do
     it 'should work with no errors' do
       pp = <<-EOS
diff --git a/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml b/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml
new file mode 100644 (file)
index 0000000..c1b8bdf
--- /dev/null
@@ -0,0 +1,11 @@
+HOSTS:
+  ubuntu-server-10044-x64:
+    roles:
+      - master
+    platform: ubuntu-10.04-amd64
+    box : ubuntu-server-10044-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-10044-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  log_level: debug
+  type: git
index a38dfa4b2702d0e3e2af33b4e4e7acb35b2d4360..09a8d18ea1bf72521dd5169f8f2f110755123e30 100644 (file)
@@ -1,6 +1,6 @@
 require 'spec_helper_acceptance'
 
-describe 'apt::pin define' do
+describe 'apt::pin define', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
   context 'defaults' do
     it 'should work with no errors' do
       pp = <<-EOS
index 81d7ca0c4d7c33eb241cfa7708f68e0b3b4126bf..e7467bf62de31707e685264cc23fb5642e372dde 100644 (file)
@@ -1,6 +1,6 @@
 require 'spec_helper_acceptance'
 
-describe 'apt::release class' do
+describe 'apt::release class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
   context 'release_id' do
     it 'should work with no errors' do
       pp = <<-EOS
index a0349d40d7ca303e48c4229e47ed7a0cfed64302..6a19f4e74e044c5efb5eaf352340241fabd047b1 100644 (file)
@@ -1,6 +1,6 @@
 require 'spec_helper_acceptance'
 
-describe 'apt::unattended_upgrades class' do
+describe 'apt::unattended_upgrades class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
   context 'defaults' do
     it 'should work with no errors' do
       pp = <<-EOS
diff --git a/spec/acceptance/unsupported_spec.rb b/spec/acceptance/unsupported_spec.rb
new file mode 100644 (file)
index 0000000..08dca76
--- /dev/null
@@ -0,0 +1,10 @@
+require 'spec_helper_acceptance'
+
+describe 'unsupported distributions and OSes', :if => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  it 'class apt fails' do
+    pp = <<-EOS
+      class { 'apt': }
+    EOS
+    expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/unsupported/i)
+  end
+end
index 6d87cc64dccecb4e5aa2071c89bcbfd300e27756..0da7d32db03088751687508d60e594e4f2843619 100644 (file)
@@ -1,5 +1,6 @@
 require 'spec_helper'
 describe 'apt', :type => :class do
+  let(:facts) { { :lsbdistid => 'Debian' } }
   let :default_params do
     {
       :disable_keys => :undef,
@@ -18,6 +19,10 @@ describe 'apt', :type => :class do
       :purge_sources_list => true,
       :purge_sources_list_d => true,
     },
+    {
+      :purge_preferences   => true,
+      :purge_preferences_d => true,
+    },
     {
       :disable_keys => false
     }
@@ -85,6 +90,49 @@ describe 'apt', :type => :class do
           })
         end
       }
+      it {
+        if param_hash[:purge_preferences]
+          should create_file('apt-preferences').with({
+            :ensure  => 'present',
+            :path    => '/etc/apt/preferences',
+            :owner   => 'root',
+            :group   => 'root',
+            :mode    => '0644',
+            :content => /Explanation/,
+          })
+        else
+          should create_file('apt-preferences').with({
+            :ensure  => 'present',
+            :path    => '/etc/apt/preferences',
+            :owner   => 'root',
+            :group   => 'root',
+            :mode    => '0644',
+            :content => nil,
+          })
+        end
+      }
+
+      it {
+        if param_hash[:purge_preferences_d]
+          should create_file("preferences.d").with({
+            'path'    => "/etc/apt/preferences.d",
+            'ensure'  => "directory",
+            'owner'   => "root",
+            'group'   => "root",
+            'purge'   => true,
+            'recurse' => true,
+          })
+        else
+          should create_file("preferences.d").with({
+            'path'    => "/etc/apt/preferences.d",
+            'ensure'  => "directory",
+            'owner'   => "root",
+            'group'   => "root",
+            'purge'   => false,
+            'recurse' => false,
+          })
+        end
+      }
 
       it {
         should contain_exec("apt_update").with({
index 6006afb41801dbc7629ca18bb21cd0f0cc961c34..ca55ef687bd100c54cea2af8f2851ad28767471b 100644 (file)
@@ -1,5 +1,6 @@
 require 'spec_helper'
 describe 'apt::debian::testing', :type => :class do
+  let(:facts) { { :lsbdistid => 'Debian' } }
   it {
     should contain_apt__source("debian_testing").with({
       "location"            => "http://debian.mirror.iweb.ca/debian/",
index 411182df118e25964a1c6ddf9c1e9da866f5004f..f5ed4558a755df22882842a130870d1eccc59466 100644 (file)
@@ -1,5 +1,6 @@
 require 'spec_helper'
 describe 'apt::debian::unstable', :type => :class do
+  let(:facts) { { :lsbdistid => 'Debian' } }
   it {
     should contain_apt__source("debian_unstable").with({
       "location"          => "http://debian.mirror.iweb.ca/debian/",
index f2790b0adb25615cd525d64d6ee9ffd3f11135ff..2d3ec3c71aa8bf0e753e2565534ff9677d9267f8 100644 (file)
@@ -1,5 +1,6 @@
 require 'spec_helper'
 describe 'apt::params', :type => :class do
+  let(:facts) { { :lsbdistid => 'Debian' } }
   let (:title) { 'my_package' }
 
   it { should contain_apt__params }
index 31252b99a98048355a2401aee457e6d47bb22b6c..e43f449d62689907d63a6ea0e2a86e2414db4d1d 100644 (file)
@@ -1,5 +1,6 @@
 require 'spec_helper'
 describe 'apt::release', :type => :class do
+  let(:facts) { { :lsbdistid => 'Debian' } }
   let (:title) { 'my_package' }
 
   let :param_set do
index e83c6e4c3096d3a47c6d2c0844e353a930118188..f5cad53a5b6857f80a091e17549874206ac3ffe7 100644 (file)
@@ -2,6 +2,7 @@ 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' }
+  let(:facts) { { :lsbdistid => 'Debian' } }
 
   it { should contain_package("unattended-upgrades") }
 
index 4e2b698d93883b21043a0c18f9aed6e9ec9d598b..a0cbaa4cc098e80acde84a7951788d1f64d31698 100644 (file)
@@ -1,6 +1,7 @@
 require 'spec_helper'
 describe 'apt::builddep', :type => :define do
 
+  let(:facts) { { :lsbdistid => 'Debian' } }
   let(:title) { 'my_package' }
 
   describe "should require apt-get update" do
index 5a81b5148c7d7bf489dabdef47012abe8d58a995..cda5900c035a3174aa782d8d8e34d678534b6eb5 100644 (file)
@@ -1,5 +1,6 @@
 require 'spec_helper'
 describe 'apt::conf', :type => :define do
+  let(:facts) { { :lsbdistid => 'Debian' } }
   let :title do
     'norecommends'
   end
index 84231fa233b1082f42132f618680f95e767c78a8..0d3d6e594005be5e1005c66f399d66444ed31409 100644 (file)
@@ -1,5 +1,6 @@
 require 'spec_helper'
 describe 'apt::force', :type => :define do
+  let(:facts) { { :lsbdistid => 'Debian' } }
   let :pre_condition do
     'include apt::params'
   end
index aea197a7b2baf5c4a5668bb95ebe7278d75af404..4ba7b87eae6c777896d5de3c7a67948403060d66 100644 (file)
@@ -1,5 +1,6 @@
 require 'spec_helper'
 describe 'apt::key', :type => :define do
+  let(:facts) { { :lsbdistid => 'Debian' } }
   let :title do
     '8347A27F'
   end
index 179a2f3ac5bcf48e7bfc80b67c54334f76da093b..f1ca43733b592be67de179393c80249ae2b43f9b 100644 (file)
@@ -1,5 +1,6 @@
 require 'spec_helper'
 describe 'apt::pin', :type => :define do
+  let(:facts) { { :lsbdistid => 'Debian' } }
   let(:title) { 'my_pin' }
 
   let :default_params do
@@ -12,21 +13,21 @@ describe 'apt::pin', :type => :define do
     }
   end
 
-  [ 
+  [
     { :params  => {},
       :content => "# my_pin\nExplanation: : my_pin\nPackage: *\nPin: release a=my_pin\nPin-Priority: 0\n"
     },
     {
       :params => {
-        :packages => 'apache', 
+        :packages => 'apache',
         :priority => '1'
       },
       :content => "# my_pin\nExplanation: : my_pin\nPackage: apache\nPin: release a=my_pin\nPin-Priority: 1\n"
     },
     {
       :params => {
-        :order    => 50, 
-        :packages => 'apache', 
+        :order    => 50,
+        :packages => 'apache',
         :priority => '1'
       },
       :content => "# my_pin\nExplanation: : my_pin\nPackage: apache\nPin: release a=my_pin\nPin-Priority: 1\n"
@@ -60,7 +61,7 @@ describe 'apt::pin', :type => :define do
         :priority => '1',
         :origin   => 'ftp.de.debian.org'
       },
-      :content => "# my_pin\nExplanation: : my_pin\nPackage: *\nPin: origin \"ftp.de.debian.org\"\nPin-Priority: 1\n"
+      :content => "# my_pin\nExplanation: : my_pin\nPackage: *\nPin: origin ftp.de.debian.org\nPin-Priority: 1\n"
     },
     {
       :params => {
index dc1173b8970c3c88fc6cd8c01709c10dd6b5c917..0c3bd75ed779dc64c8a9807eac679c9143b4dccf 100644 (file)
@@ -1,20 +1,28 @@
 require 'spec_helper'
 describe 'apt::ppa', :type => :define do
-  [ { :lsbdistrelease => '11.04',
+  [
+    {
+      :lsbdistrelease  => '11.04',
       :lsbdistcodename => 'natty',
       :operatingsystem => 'Ubuntu',
-      :package => 'python-software-properties'},
-    { :lsbdistrelease => '12.10',
+      :lsbdistid       => 'Ubuntu',
+      :package         => 'python-software-properties'
+    },
+    {
+      :lsbdistrelease  => '12.10',
       :lsbdistcodename => 'quantal',
       :operatingsystem => 'Ubuntu',
-      :package => 'software-properties-common'},
+      :lsbdistid       => 'Ubuntu',
+      :package         => 'software-properties-common'
+    },
   ].each do |platform|
     context "on #{platform[:lsbdistcodename]}" do
       let :facts do
         {
-          :lsbdistrelease => platform[:lsbdistrelease],
+          :lsbdistrelease  => platform[:lsbdistrelease],
           :lsbdistcodename => platform[:lsbdistcodename],
           :operatingsystem => platform[:operatingsystem],
+          :lsbdistid       => platform[:lsbdistid],
         }
       end
       let :release do
@@ -125,7 +133,8 @@ describe 'apt::ppa', :type => :define do
         end
         let :facts do
           {:lsbdistcodename => '#{platform[:lsbdistcodename]}',
-           :operatingsystem => 'Ubuntu'}
+           :operatingsystem => 'Ubuntu',
+           :lsbdistid => 'Ubuntu'}
         end
         let(:title) { "ppa" }
         let(:release) { "#{platform[:lsbdistcodename]}" }
index 215d1e692f992c134c67f478f25b94e46bc2109f..9da8b235feff81e8623d255d8d2796ba7dc77454 100644 (file)
@@ -1,5 +1,6 @@
 require 'spec_helper'
 describe 'apt::source', :type => :define do
+  let(:facts) { { :lsbdistid => 'Debian' } }
   let :title do
     'my_source'
   end
@@ -59,7 +60,7 @@ describe 'apt::source', :type => :define do
       end
 
       let :facts do
-        {:lsbdistcodename => 'karmic'}
+        {:lsbdistcodename => 'karmic', :lsbdistid => 'Ubuntu'}
       end
 
       let :params do
@@ -160,7 +161,7 @@ describe 'apt::source', :type => :define do
     let(:default_params) { Hash.new }
     let(:facts) { Hash.new }
     it { expect { should raise_error(Puppet::Error) } }
-    let(:facts) { { :lsbdistcodename => 'lucid' } }
+    let(:facts) { { :lsbdistcodename => 'lucid', :lsbdistid => 'Ubuntu' } }
     it { should contain_apt__source(title) }
   end
 end
index a4fc1bd6a2073566a17b00ed0f3f50ec4ae02bc9..3352564ce7b553672fab7dafa8f277af232a065f 100644 (file)
@@ -1,12 +1,19 @@
 require 'beaker-rspec'
 
-hosts.each do |host|
-  # Install Puppet
-  install_package host, 'rubygems'
-  on host, 'gem install puppet --no-ri --no-rdoc'
-  on host, "mkdir -p #{host['distmoduledir']}"
+# Install Puppet
+unless ENV['RS_PROVISION'] == 'no'
+  hosts.each do |host|
+    if host.is_pe?
+      install_pe
+    else
+      install_puppet
+      on host, "mkdir -p #{host['distmoduledir']}"
+    end
+  end
 end
 
+UNSUPPORTED_PLATFORMS = ['RedHat','Suse','windows','AIX','Solaris']
+
 RSpec.configure do |c|
   # Project root
   proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
diff --git a/spec/unit/puppet/type/apt_key_spec.rb b/spec/unit/puppet/type/apt_key_spec.rb
new file mode 100644 (file)
index 0000000..c29f82b
--- /dev/null
@@ -0,0 +1,160 @@
+require 'spec_helper'
+require 'puppet'
+
+describe Puppet::Type::type(:apt_key) do
+  context 'only namevar 32bit key id' do
+    let(:resource) { Puppet::Type.type(:apt_key).new(
+      :id => '4BD6EC30'
+    )}
+    it 'id is set' do
+      resource[:id].should eq '4BD6EC30'
+    end
+
+    it 'name is set to id' do
+      resource[:name].should eq '4BD6EC30'
+    end
+
+    it 'keyserver is default' do
+      resource[:server].should eq :'keyserver.ubuntu.com'
+    end
+
+    it 'source is not set' do
+      resource[:source].should eq nil
+    end
+
+    it 'content is not set' do
+      resource[:content].should eq nil
+    end
+  end
+
+  context 'with a lowercase 32bit key id' do
+    let(:resource) { Puppet::Type.type(:apt_key).new(
+      :id => '4bd6ec30'
+    )}
+    it 'id is set' do
+      resource[:id].should eq '4BD6EC30'
+    end
+  end
+
+  context 'with a 64bit key id' do
+    let(:resource) { Puppet::Type.type(:apt_key).new(
+      :id => 'FFFFFFFF4BD6EC30'
+    )}
+    it 'id is set' do
+      resource[:id].should eq '4BD6EC30'
+    end
+  end
+
+  context 'with a 0x formatted key id' do
+    let(:resource) { Puppet::Type.type(:apt_key).new(
+      :id => '0x4BD6EC30'
+    )}
+    it 'id is set' do
+      resource[:id].should eq '4BD6EC30'
+    end
+  end
+
+  context 'with a 0x formatted lowercase key id' do
+    let(:resource) { Puppet::Type.type(:apt_key).new(
+      :id => '0x4bd6ec30'
+    )}
+    it 'id is set' do
+      resource[:id].should eq '4BD6EC30'
+    end
+  end
+
+  context 'with a 0x formatted 64bit key id' do
+    let(:resource) { Puppet::Type.type(:apt_key).new(
+      :id => '0xFFFFFFFF4BD6EC30'
+    )}
+    it 'id is set' do
+      resource[:id].should eq '4BD6EC30'
+    end
+  end
+
+  context 'with source' do
+    let(:resource) { Puppet::Type.type(:apt_key).new(
+      :id => '4BD6EC30',
+      :source => 'http://apt.puppetlabs.com/pubkey.gpg'
+    )}
+
+    it 'source is set to the URL' do
+      resource[:source].should eq 'http://apt.puppetlabs.com/pubkey.gpg'
+    end
+  end
+  
+  context 'with content' do
+    let(:resource) { Puppet::Type.type(:apt_key).new(
+      :id => '4BD6EC30',
+      :content => 'http://apt.puppetlabs.com/pubkey.gpg'
+    )}
+
+    it 'content is set to the string' do
+      resource[:content].should eq 'http://apt.puppetlabs.com/pubkey.gpg'
+    end
+  end
+  
+  context 'with keyserver' do
+    let(:resource) { Puppet::Type.type(:apt_key).new(
+      :id => '4BD6EC30',
+      :server => 'http://keyring.debian.org'
+    )}
+
+    it 'keyserver is set to Debian' do
+      resource[:server].should eq 'http://keyring.debian.org'
+    end
+  end
+
+  context 'validation' do
+    it 'raises an error if content and source are set' do
+      expect { Puppet::Type.type(:apt_key).new(
+        :id      => '4BD6EC30',
+        :source  => 'http://apt.puppetlabs.com/pubkey.gpg',
+        :content => 'Completely invalid as a GPG key'
+      )}.to raise_error(/content and source are mutually exclusive/)
+    end
+
+    it 'raises an error if a weird length key is used' do
+      expect { Puppet::Type.type(:apt_key).new(
+        :id      => 'F4BD6EC30',
+        :source  => 'http://apt.puppetlabs.com/pubkey.gpg',
+        :content => 'Completely invalid as a GPG key'
+      )}.to raise_error(/Valid values match/)
+    end
+
+    it 'raises an error when an invalid URI scheme is used in source' do
+      expect { Puppet::Type.type(:apt_key).new(
+        :id      => '4BD6EC30',
+        :source  => 'hkp://pgp.mit.edu'
+      )}.to raise_error(/Valid values match/)
+    end
+
+    it 'allows the http URI scheme in source' do
+      expect { Puppet::Type.type(:apt_key).new(
+        :id      => '4BD6EC30',
+        :source  => 'http://pgp.mit.edu'
+      )}.to_not raise_error
+    end
+
+    it 'allows the https URI scheme in source' do
+      expect { Puppet::Type.type(:apt_key).new(
+        :id      => '4BD6EC30',
+        :source  => 'https://pgp.mit.edu'
+      )}.to_not raise_error
+    end
+
+    it 'allows the ftp URI scheme in source' do
+      expect { Puppet::Type.type(:apt_key).new(
+        :id      => '4BD6EC30',
+        :source  => 'ftp://pgp.mit.edu'
+      )}.to_not raise_error
+    end
+
+    it 'allows an absolute path in source' do
+      expect { Puppet::Type.type(:apt_key).new(
+        :id      => '4BD6EC30',
+        :source  => '/path/to/a/file'
+      )}.to_not raise_error
+    end
+  end
+end
index 42e23c7edd2a1ec694fbc6265495d268dfb354d8..a19e2536fcb4db6d9bdd961ea56571d9a16bba87 100644 (file)
@@ -12,7 +12,7 @@ if @pin_release.length > 0
 elsif @version.length > 0
   @pin = "version #{@version}"
 elsif @origin.length > 0
-  @pin = "origin \"#{@origin}\""
+  @pin = "origin #{@origin}"
 end
 -%>
 # <%= @name %>