Separate apt::pin for apt::backports to allow pin by release instead of ...
.vagrant/
.bundle/
coverage/
+.idea/
+*.iml
* `autoclean`: How often, in days, to run `apt-get autoclean`.
* `randomsleep`: How long, in seconds, to randomly wait before applying upgrades.
+####apt::source
+
+* `comment`: Add a comment to the apt source file.
+* `ensure`: Allows you to remove the apt source file. Can be 'present' or 'absent'.
+* `location`: The URL of the apt repository.
+* `release`: The distribution of the apt repository. Defaults to fact 'lsbdistcodename'.
+* `repos`: The component of the apt repository. This defaults to 'main'.
+* `include_deb`: References a Debian distribution's binary package.
+* `include_src`: Enable the deb-src type, references a Debian distribution's source code in the same form as the include_deb type. A deb-src line is required to fetch source indexes.
+* `required_packages`: todo
+* `key`: See apt::key
+* `key_server`: See apt::key
+* `key_content`: See apt::key
+* `key_source`: See apt::key
+* `pin`: See apt::pin
+* `architecture`: can be used to specify for which architectures information should be downloaded. If this option is not set all architectures defined by the APT::Architectures option will be downloaded. Defaults to 'undef' which means all. Example values can be 'i386' or 'i386,alpha,powerpc'
+* `trusted_source` can be set to indicate that packages from this source are always authenticated even if the Release file is not signed or the signature can't be checked. Defaults to false. Can be 'true' or 'false'.
+
### Testing
The apt module is mostly a collection of defined resource types, which provide reusable logic for managing Apt. It provides smoke tests for testing functionality on a target system, as well as spec tests for checking a compiled catalog against an expected set of resources.
Facter.add("apt_has_updates") do
confine :osfamily => 'Debian'
if File.executable?("/usr/lib/update-notifier/apt-check")
- apt_package_updates = Facter::Util::Resolution.exec('/usr/lib/update-notifier/apt-check 2>/dev/null').split(';')
+ apt_check_result = Facter::Util::Resolution.exec('/usr/lib/update-notifier/apt-check 2>&1')
+ if not apt_check_result.nil? and apt_check_result =~ /^\d+;\d+$/
+ apt_package_updates = apt_check_result.split(';')
+ end
end
setcode do
- apt_package_updates != ['0', '0'] unless apt_package_updates.nil?
+ if not apt_package_updates.nil? and apt_package_updates.length == 2
+ apt_package_updates != ['0', '0']
+ end
end
end
Facter.add("apt_package_updates") do
confine :apt_has_updates => true
setcode do
- packages = Facter::Util::Resolution.exec('/usr/lib/update-notifier/apt-check -p 2>/dev/null').split("\n")
+ packages = Facter::Util::Resolution.exec('/usr/lib/update-notifier/apt-check -p 2>&1').split("\n")
if Facter.version < '2.0.0'
packages.join(',')
else
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
+ cli_args = ['adv','--list-keys', '--with-colons', '--fingerprint']
+
if RUBY_VERSION > '1.8.7'
- key_output = apt_key('list').encode('UTF-8', 'binary', :invalid => :replace, :undef => :replace, :replace => '')
+ key_output = apt_key(cli_args).encode('UTF-8', 'binary', :invalid => :replace, :undef => :replace, :replace => '')
else
- key_output = apt_key('list')
+ key_output = apt_key(cli_args)
end
+
+ pub_line, fpr_line = nil
+
key_array = key_output.split("\n").collect do |line|
- line_hash = key_line_hash(line)
- next unless line_hash
+ if line.start_with?('pub')
+ pub_line = line
+ elsif line.start_with?('fpr')
+ fpr_line = line
+ end
+
+ next unless (pub_line and fpr_line)
+
+ line_hash = key_line_hash(pub_line, fpr_line)
+
+ # reset everything
+ pub_line, fpr_line = nil
+
expired = false
if 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]
+ :name => line_hash[:key_fingerprint],
+ :id => line_hash[:key_long],
+ :fingerprint => line_hash[:key_fingerprint],
+ :short => line_hash[:key_short],
+ :long => line_hash[:key_long],
+ :ensure => :present,
+ :expired => expired,
+ :expiry => line_hash[:key_expiry],
+ :size => line_hash[:key_size],
+ :type => line_hash[:key_type],
+ :created => line_hash[:key_created]
)
end
key_array.compact!
def self.prefetch(resources)
apt_keys = instances
resources.keys.each do |name|
- if name.length == 16
- shortname=name[8..-1]
- else
- shortname=name
- end
- if provider = apt_keys.find{ |key| key.name == shortname }
- resources[name].provider = provider
+ if name.length == 40
+ if provider = apt_keys.find{ |key| key.fingerprint == name }
+ resources[name].provider = provider
+ end
+ elsif name.length == 16
+ if provider = apt_keys.find{ |key| key.long == name }
+ resources[name].provider = provider
+ end
+ elsif name.length == 8
+ if provider = apt_keys.find{ |key| key.short == name }
+ resources[name].provider = provider
+ end
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
+ def self.key_line_hash(pub_line, fpr_line)
+ pub_split = pub_line.split(':')
+ fpr_split = fpr_line.split(':')
+ fingerprint = fpr_split.last
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,
+ :key_fingerprint => fingerprint,
+ :key_long => fingerprint[-16..-1], # last 16 characters of fingerprint
+ :key_short => fingerprint[-8..-1], # last 8 characters of fingerprint
+ :key_size => pub_split[2],
+ :key_type => nil,
+ :key_created => pub_split[5],
+ :key_expiry => pub_split[6].empty? ? nil : pub_split[6],
}
- return_hash[:key_expiry] = line_array[7] if line_array.length == 8
- return return_hash
- end
+ # set key type based on types defined in /usr/share/doc/gnupg/DETAILS.gz
+ case pub_split[3]
+ when "1"
+ return_hash[:key_type] = :rsa
+ when "17"
+ return_hash[:key_type] = :dsa
+ when "18"
+ return_hash[:key_type] = :ecc
+ when "19"
+ return_hash[:key_type] = :ecdsa
+ 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
+ return return_hash
end
def source_to_file(value)
end
def destroy
- #Currently del only removes the first key, we need to recursively list and ensure all with id are absent.
- apt_key('del', resource[:id])
+ begin
+ apt_key('del', resource.provider.short)
+ r = execute(["#{command(:apt_key)} list | grep '/#{resource.provider.short}\s'"], :failonfail => false)
+ end while r.exitstatus == 0
@property_hash.clear
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/)
+ # and may start with the optional 0x, or they can be 40-digit key fingerprints
+ newvalues(/\A(0x)?[0-9a-fA-F]{8}\Z/, /\A(0x)?[0-9a-fA-F]{16}\Z/, /\A(0x)?[0-9a-fA-F]{40}\Z/)
munge do |value|
if value.start_with?('0x')
id = value.partition('0x').last.upcase
desc 'The key server to fetch the key from based on the ID. It can either be a domain name or url.'
defaultto :'keyserver.ubuntu.com'
- newvalues(/\A((hkp|http|https):\/\/)?([a-z\d])([a-z\d-]{0,61}\.)+[a-z\d]+(:\d{2,4})?$/)
+ newvalues(/\A((hkp|http|https):\/\/)?([a-z\d])([a-z\d-]{0,61}\.)+[a-z\d]+(:\d{2,5})?$/)
end
newparam(:keyserver_options) do
desc 'Additional options to pass to apt-key\'s --keyserver-options.'
end
+ newproperty(:fingerprint) do
+ desc <<-EOS
+ The 40-digit hexadecimal fingerprint of the specified GPG key.
+
+ This property is read-only.
+ EOS
+ end
+
+ newproperty(:long) do
+ desc <<-EOS
+ The 16-digit hexadecimal id of the specified GPG key.
+
+ This property is read-only.
+ EOS
+ end
+
+ newproperty(:short) do
+ desc <<-EOS
+ The 8-digit hexadecimal id of the specified GPG key.
+
+ This property is read-only.
+ EOS
+ end
+
newproperty(:expired) do
desc <<-EOS
Indicates if the key has expired.
newproperty(:type) do
desc <<-EOS
- The key type, either RSA or DSA.
+ The key type, one of: rsa, dsa, ecc, ecdsa
This property is read-only.
EOS
}
exec { "${provider} -y ${config_files} ${config_missing} ${release_string} install ${name}${version_string}":
- unless => $install_check,
- logoutput => 'on_failure',
- timeout => $timeout,
+ unless => $install_check,
+ environment => ['LC_ALL=C', 'LANG=C'],
+ logoutput => 'on_failure',
+ timeout => $timeout,
}
}
-# Class: apt
+# == Class: apt
#
# This module manages the initial configuration of apt.
#
-# Parameters:
-# The parameters listed here are not required in general and were
-# added for use cases related to development environments.
+# The parameters listed here are not required in general and were
+# added for use cases related to development environments.
#
-# disable_keys - disables the requirement for all packages to be signed
+# === Parameters
#
-# always_apt_update - rather apt should be updated on every run (intended
-# for development environments where package updates are frequent)
+# [*disable_keys*]
+# Disables the requirement for all packages to be signed
#
-# apt_update_frequency - *string* Supported values:
-# **always**: Will fire `apt-get update` at every puppet run. Intended to
+# [*always_apt_update*]
+# Rather apt should be updated on every run (intended
+# for development environments where package updates are frequent)
+#
+# [*apt_update_frequency*]
+# String: Supported values:
+# **always**: Will fire `apt-get update` at every puppet run. Intended to
# deprecate the `always_apt_update` parameter.
-# **daily**: Trigger `apt-get update` if the value of the fact
+# *daily**: Trigger `apt-get update` if the value of the fact
# `apt_update_last_success` is less than current epoch time - 86400.
# *notifying the apt_update exec will trigger apt-get update regardless*
-# **weekly**: Trigger `apt-get update` if the value of the fact
+# *weekly**: Trigger `apt-get update` if the value of the fact
# `apt_update_last_success` is less than current epoch time - 604800.
# *notifying the apt_update exec will trigger apt-get update regardless*
-# **reluctantly**: *Default* only run apt-get update if the exec resource `apt_update` is notified.
+# *reluctantly**: *Default* only run apt-get update if the exec resource `apt_update` is notified.
#
-# purge_sources_list - Accepts true or false. Defaults to false If set to
-# true, Puppet will purge all unmanaged entries from sources.list
+# [*purge_sources_list*]
+# Accepts true or false. Defaults to false If set to
+# 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
+# [*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)
+# [*update_timeout*]
+# Overrides the exec timeout in seconds for apt-get update.
+# If not set defaults to Exec's default (300)
#
-# update_tries - Number of times that `apt-get update` will be tried. Use this
-# to work around transient DNS and HTTP errors. By default, the command
-# will only be run once.
+# [*update_tries*]
+# Number of times that `apt-get update` will be tried. Use this
+# to work around transient DNS and HTTP errors. By default, the command
+# will only be run once.
#
-# Actions:
+# === Examples
+#
+# class { 'apt': }
+#
+# === Requires
+#
+# puppetlabs/stdlib >= 2.2.1
#
-# Requires:
-# puppetlabs/stdlib
-# Sample Usage:
-# class { 'apt': }
-
class apt(
$always_apt_update = false,
$apt_update_frequency = 'reluctantly',
# [*key*]
# _default_: +$title+, the title/name of the resource
#
-# Is a GPG key ID. This key ID is validated with a regex enforcing it
-# to only contain valid hexadecimal characters, be precisely 8 or 16
-# characters long and optionally prefixed with 0x.
+# Is a GPG key ID or full key fingerprint. This value is validated with
+# a regex enforcing it to only contain valid hexadecimal characters, be
+# precisely 8 or 16 hexadecimal characters long and optionally prefixed
+# with 0x for key IDs, or 40 hexadecimal characters long for key
+# fingerprints.
#
# [*ensure*]
# _default_: +present+
$key_options = undef,
) {
- validate_re($key, ['\A(0x)?[0-9a-fA-F]{8}\Z', '\A(0x)?[0-9a-fA-F]{16}\Z'])
+ validate_re($key, ['\A(0x)?[0-9a-fA-F]{8}\Z', '\A(0x)?[0-9a-fA-F]{16}\Z', '\A(0x)?[0-9a-fA-F]{40}\Z'])
validate_re($ensure, ['\Aabsent|present\Z',])
if $key_content {
}
if $key_server {
- validate_re($key_server,['\A((hkp|http|https):\/\/)?([a-z\d])([a-z\d-]{0,61}\.)+[a-z\d]+(:\d{2,4})?$'])
+ validate_re($key_server,['\A((hkp|http|https):\/\/)?([a-z\d])([a-z\d-]{0,61}\.)+[a-z\d]+(:\d{2,5})?$'])
}
if $key_options {
$legacy_origin = true
$origins = ['${distro_id} ${distro_codename}-security'] #lint:ignore:single_quote_string_with_variables
}
- 'precise', 'trusty', 'utopic': {
+ 'precise', 'trusty', 'utopic', 'vivid': {
$backports_location = 'http://us.archive.ubuntu.com/ubuntu'
$ppa_options = '-y'
$legacy_origin = true
$key_content = undef,
$key_source = undef,
$pin = false,
- $architecture = undef
+ $architecture = undef,
+ $trusted_source = false,
) {
include apt::params
include apt::update
+ validate_string($architecture)
+ validate_bool($trusted_source)
+
$sources_list_d = $apt::params::sources_list_d
$provider = $apt::params::provider
require 'spec_helper_acceptance'
-PUPPETLABS_GPG_KEY_ID = '4BD6EC30'
-PUPPETLABS_GPG_LONG_KEY_ID = '1054B7A24BD6EC30'
-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'
+PUPPETLABS_GPG_KEY_SHORT_ID = '4BD6EC30'
+PUPPETLABS_GPG_KEY_LONG_ID = '1054B7A24BD6EC30'
+PUPPETLABS_GPG_KEY_FINGERPRINT = '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30'
+PUPPETLABS_APT_URL = 'apt.puppetlabs.com'
+PUPPETLABS_GPG_KEY_FILE = 'pubkey.gpg'
+CENTOS_GPG_KEY_SHORT_ID = 'C105B9DE'
+CENTOS_GPG_KEY_LONG_ID = '0946FCA2C105B9DE'
+CENTOS_GPG_KEY_FINGERPRINT = 'C1DAC52D1664E8A4386DBA430946FCA2C105B9DE'
+CENTOS_REPO_URL = 'ftp.cvut.cz/centos'
+CENTOS_GPG_KEY_FILE = 'RPM-GPG-KEY-CentOS-6'
+
+SHOULD_NEVER_EXIST_ID = '4BD6EC30'
+
+KEY_CHECK_COMMAND = "apt-key adv --list-keys --with-colons --fingerprint | grep "
+PUPPETLABS_KEY_CHECK_COMMAND = "#{KEY_CHECK_COMMAND} #{PUPPETLABS_GPG_KEY_FINGERPRINT}"
+CENTOS_KEY_CHECK_COMMAND = "#{KEY_CHECK_COMMAND} #{CENTOS_GPG_KEY_FINGERPRINT}"
describe 'apt_key' do
before(:each) do
# Delete twice to make sure everything is cleaned
# up after the short key collision
- shell("apt-key del #{PUPPETLABS_GPG_KEY_ID}",
+ shell("apt-key del #{PUPPETLABS_GPG_KEY_SHORT_ID}",
:acceptable_exit_codes => [0,1,2])
- shell("apt-key del #{PUPPETLABS_GPG_KEY_ID}",
+ shell("apt-key del #{PUPPETLABS_GPG_KEY_SHORT_ID}",
:acceptable_exit_codes => [0,1,2])
end
key_versions = {
'32bit key id' => '4BD6EC30',
'64bit key id' => '1054B7A24BD6EC30',
+ '160bit key fingerprint' => '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30',
'32bit lowercase key id' => '4bd6ec30',
'64bit lowercase key id' => '1054b7a24bd6ec30',
+ '160bit lowercase key fingerprint' => '47b320eb4c7c375aa9dae1a01054b7a24bd6ec30',
'0x formatted 32bit key id' => '0x4BD6EC30',
'0x formatted 64bit key id' => '0x1054B7A24BD6EC30',
+ '0x formatted 160bit key fingerprint' => '0x47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30',
'0x formatted 32bit lowercase key id' => '0x4bd6ec30',
'0x formatted 64bit lowercase key id' => '0x1054b7a24bd6ec30',
+ '0x formatted 160bit lowercase key fingerprint' => '0x47b320eb4c7c375aa9dae1a01054b7a24bd6ec30',
}
key_versions.each do |key, value|
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
- shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+ shell(PUPPETLABS_KEY_CHECK_COMMAND)
end
end
end
it 'is removed' do
pp = <<-EOS
apt_key { 'centos':
- id => '#{CENTOS_GPG_KEY_ID}',
+ id => '#{CENTOS_GPG_KEY_LONG_ID}',
ensure => 'absent',
}
EOS
# Install the key first
shell("apt-key adv --keyserver keyserver.ubuntu.com \
- --recv-keys #{CENTOS_GPG_KEY_ID}")
- shell("apt-key list | grep #{CENTOS_GPG_KEY_ID}")
+ --recv-keys #{CENTOS_GPG_KEY_FINGERPRINT}")
+ shell(CENTOS_KEY_CHECK_COMMAND)
# Time to remove it using Puppet
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_failures => true)
- shell("apt-key list | grep #{CENTOS_GPG_KEY_ID}",
+ shell(CENTOS_KEY_CHECK_COMMAND,
:acceptable_exit_codes => [1])
shell("apt-key adv --keyserver keyserver.ubuntu.com \
- --recv-keys #{CENTOS_GPG_KEY_ID}")
+ --recv-keys #{CENTOS_GPG_KEY_FINGERPRINT}")
end
end
it 'is removed' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
ensure => 'absent',
}
EOS
# Install the key first
shell("apt-key adv --keyserver keyserver.ubuntu.com \
- --recv-keys #{PUPPETLABS_GPG_LONG_KEY_ID}")
- shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+ --recv-keys #{PUPPETLABS_GPG_KEY_LONG_ID}")
+ shell(PUPPETLABS_KEY_CHECK_COMMAND)
# Time to remove it using Puppet
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_failures => true)
- shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}",
+ shell(PUPPETLABS_KEY_CHECK_COMMAND,
:acceptable_exit_codes => [1])
end
end
it 'works' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_FINGERPRINT}',
ensure => 'present',
content => "-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.12 (GNU/Linux)
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_failures => true)
- shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+ shell(PUPPETLABS_KEY_CHECK_COMMAND)
end
end
it 'fails' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
ensure => 'present',
content => 'For posterity: such content, much bogus, wow',
}
it 'works' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
ensure => 'present',
server => 'pgp.mit.edu',
}
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_failures => true)
- shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+ shell(PUPPETLABS_KEY_CHECK_COMMAND)
end
end
it 'works' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_FINGERPRINT}',
ensure => 'present',
server => 'hkp://pgp.mit.edu:80',
}
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_failures => true)
- shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+ shell(PUPPETLABS_KEY_CHECK_COMMAND)
end
end
it 'fails' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
ensure => 'present',
server => 'nonexistant.key.server',
}
it 'fails' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
ensure => 'present',
server => '.pgp.key.server',
}
it 'works' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
ensure => 'present',
source => 'http://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}',
}
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_failures => true)
- shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+ shell(PUPPETLABS_KEY_CHECK_COMMAND)
end
it 'fails with a 404' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
ensure => 'present',
source => 'http://#{PUPPETLABS_APT_URL}/herpderp.gpg',
}
it 'fails with a socket error' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
ensure => 'present',
source => 'http://apt.puppetlabss.com/herpderp.gpg',
}
context 'ftp://' do
before(:each) do
- shell("apt-key del #{CENTOS_GPG_KEY_ID}",
+ shell("apt-key del #{CENTOS_GPG_KEY_LONG_ID}",
:acceptable_exit_codes => [0,1,2])
end
it 'works' do
pp = <<-EOS
apt_key { 'CentOS 6':
- id => '#{CENTOS_GPG_KEY_ID}',
+ id => '#{CENTOS_GPG_KEY_LONG_ID}',
ensure => 'present',
source => 'ftp://#{CENTOS_REPO_URL}/#{CENTOS_GPG_KEY_FILE}',
}
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_failures => true)
- shell("apt-key list | grep #{CENTOS_GPG_KEY_ID}")
+ shell(CENTOS_KEY_CHECK_COMMAND)
end
it 'fails with a 550' do
pp = <<-EOS
apt_key { 'CentOS 6':
- id => '#{CENTOS_GPG_KEY_ID}',
+ id => '#{SHOULD_NEVER_EXIST_ID}',
ensure => 'present',
source => 'ftp://#{CENTOS_REPO_URL}/herpderp.gpg',
}
it 'fails with a socket error' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
ensure => 'present',
source => 'ftp://apt.puppetlabss.com/herpderp.gpg',
}
it 'works' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
ensure => 'present',
source => 'https://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}',
}
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_failures => true)
- shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+ shell(PUPPETLABS_KEY_CHECK_COMMAND)
end
it 'fails with a 404' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '4BD6EC30',
+ id => '#{SHOULD_NEVER_EXIST_ID}',
ensure => 'present',
source => 'https://#{PUPPETLABS_APT_URL}/herpderp.gpg',
}
it 'fails with a socket error' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '4BD6EC30',
+ id => '#{SHOULD_NEVER_EXIST_ID}',
ensure => 'present',
source => 'https://apt.puppetlabss.com/herpderp.gpg',
}
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_failures => true)
- shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+ shell(PUPPETLABS_KEY_CHECK_COMMAND)
end
end
it 'fails' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
ensure => 'present',
source => '/tmp/totally_bogus.file',
}
it 'fails' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
ensure => 'present',
source => '/tmp/fake-key.gpg',
}
it 'works' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
ensure => 'present',
keyserver_options => 'debug',
}
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_failures => true)
- shell("apt-key list | grep #{PUPPETLABS_GPG_KEY_ID}")
+ shell(PUPPETLABS_KEY_CHECK_COMMAND)
end
it 'fails on invalid options' do
pp = <<-EOS
apt_key { 'puppetlabs':
- id => '#{PUPPETLABS_GPG_KEY_ID}',
+ id => '#{PUPPETLABS_GPG_KEY_LONG_ID}',
ensure => 'present',
keyserver_options => 'this is totally bonkers',
}
EOS
- shell("apt-key del #{PUPPETLABS_GPG_KEY_ID}", :acceptable_exit_codes => [0,1,2])
+ shell("apt-key del #{PUPPETLABS_GPG_KEY_FINGERPRINT}", :acceptable_exit_codes => [0,1,2])
apply_manifest(pp, :expect_failures => true) do |r|
expect(r.stderr).to match(/--keyserver-options this is totally/)
end
describe 'apt::key', :type => :define do
let(:facts) { { :lsbdistid => 'Debian' } }
- GPG_KEY_ID = '4BD6EC30'
+ GPG_KEY_ID = '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30'
let :title do
GPG_KEY_ID
require 'spec_helper'
describe 'apt::source', :type => :define do
- GPG_KEY_ID = '4BD6EC30'
+ GPG_KEY_ID = '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30'
+
let :title do
'my_source'
'key_source' => 'http://apt.puppetlabs.com/pubkey.gpg',
'pin' => '10',
'architecture' => 'x86_64',
+ 'trusted_source' => true,
}
end
'owner' => 'root',
'group' => 'root',
'mode' => '0644',
- }).with_content(/#file generated by puppet\n# foo\ndeb \[arch=x86_64\] http:\/\/debian\.mirror\.iweb\.ca\/debian\/ sid testing\n/).without_content(/deb-src/)
+ }).with_content(/#file generated by puppet\n# foo\ndeb \[arch=x86_64 trusted=yes\] http:\/\/debian\.mirror\.iweb\.ca\/debian\/ sid testing\n/).without_content(/deb-src/)
}
it { is_expected.to contain_apt__pin('my_source').that_comes_before('File[my_source.list]').with({
}
end
+ context 'trusted_source true' do
+ let :facts do
+ {
+ :lsbdistid => 'Debian',
+ :lsbdistcodename => 'wheezy',
+ :osfamily => 'Debian'
+ }
+ end
+ let :params do
+ {
+ 'include_src' => false,
+ 'trusted_source' => true,
+ }
+ end
+
+ it { is_expected.to contain_file('my_source.list').that_notifies('Exec[apt_update]').with({
+ 'ensure' => 'present',
+ 'path' => '/etc/apt/sources.list.d/my_source.list',
+ 'owner' => 'root',
+ 'group' => 'root',
+ 'mode' => '0644',
+ }).with_content(/#file generated by puppet\n# my_source\ndeb \[trusted=yes\] wheezy main\n/)
+ }
+ end
+
+ context 'architecture equals x86_64' do
+ let :facts do
+ {
+ :lsbdistid => 'Debian',
+ :lsbdistcodename => 'wheezy',
+ :osfamily => 'Debian'
+ }
+ end
+ let :params do
+ {
+ 'include_deb' => false,
+ 'architecture' => 'x86_64',
+ }
+ end
+
+ it { is_expected.to contain_file('my_source.list').that_notifies('Exec[apt_update]').with({
+ 'ensure' => 'present',
+ 'path' => '/etc/apt/sources.list.d/my_source.list',
+ 'owner' => 'root',
+ 'group' => 'root',
+ 'mode' => '0644',
+ }).with_content(/#file generated by puppet\n# my_source\ndeb-src \[arch=x86_64 \] wheezy main\n/)
+ }
+ end
+
context 'ensure => absent' do
let :facts do
{
describe 'on non-Debian distro' do
before {
- Facter.fact(:osfamily).expects(:value).returns 'RedHat'
+ Facter.fact(:osfamily).expects(:value).at_least(1).returns 'RedHat'
}
it { should be_nil }
end
describe 'on Debian based distro missing update-notifier-common' do
before {
- Facter.fact(:osfamily).expects(:value).returns 'Debian'
+ Facter.fact(:osfamily).expects(:value).at_least(1).returns 'Debian'
File.stubs(:executable?) # Stub all other calls
File.expects(:executable?).with('/usr/lib/update-notifier/apt-check').returns false
}
it { should be_nil }
end
+ describe 'on Debian based distro with broken packages' do
+ before {
+ Facter.fact(:osfamily).expects(:value).at_least(1).returns 'Debian'
+ File.stubs(:executable?) # Stub all other calls
+ Facter::Util::Resolution.stubs(:exec) # Catch all other calls
+ File.expects(:executable?).with('/usr/lib/update-notifier/apt-check').returns true
+ Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>&1').returns "E: Error: BrokenCount > 0"
+ }
+ it { should be_nil }
+ end
+
+ describe 'on Debian based distro with unknown error with semicolons' do
+ before {
+ Facter.fact(:osfamily).expects(:value).at_least(1).returns 'Debian'
+ File.stubs(:executable?) # Stub all other calls
+ Facter::Util::Resolution.stubs(:exec) # Catch all other calls
+ File.expects(:executable?).with('/usr/lib/update-notifier/apt-check').returns true
+ Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>&1').returns "E: Unknown Error: 'This error contains something that could be parsed like 4;3' (10)"
+ }
+ it { should be_nil }
+ end
+
describe 'on Debian based distro' do
before {
- Facter.fact(:osfamily).expects(:value).returns 'Debian'
+ Facter.fact(:osfamily).expects(:value).at_least(1).returns 'Debian'
File.stubs(:executable?) # Stub all other calls
Facter::Util::Resolution.stubs(:exec) # Catch all other calls
File.expects(:executable?).with('/usr/lib/update-notifier/apt-check').returns true
- Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>/dev/null').returns "4;3"
+ Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>&1').returns "4;3"
}
it { should be true }
end
File.stubs(:executable?) # Stub all other calls
Facter::Util::Resolution.stubs(:exec) # Catch all other calls
File.expects(:executable?).with('/usr/lib/update-notifier/apt-check').returns true
- Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>/dev/null').returns "1;2"
- Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check -p 2>/dev/null').returns "puppet-common\nlinux-generic\nlinux-image-generic"
+ Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>&1').returns "1;2"
+ Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check -p 2>&1').returns "puppet-common\nlinux-generic\nlinux-image-generic"
}
it {
if Facter.version < '2.0.0'
File.stubs(:executable?) # Stub all other calls
Facter::Util::Resolution.stubs(:exec) # Catch all other calls
File.expects(:executable?).with('/usr/lib/update-notifier/apt-check').returns true
- Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>/dev/null').returns "14;7"
+ Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>&1').returns "14;7"
}
it { should == 7 }
end
File.stubs(:executable?) # Stub all other calls
Facter::Util::Resolution.stubs(:exec) # Catch all other calls
File.expects(:executable?).with('/usr/lib/update-notifier/apt-check').returns true
- Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>/dev/null').returns "14;7"
+ Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>&1').returns "14;7"
}
it { should == 14 }
end
:source => '/path/to/a/file'
)}.to_not raise_error
end
+
+ it 'allows 5-digit ports' do
+ expect { Puppet::Type.type(:apt_key).new(
+ :id => '4BD6EC30',
+ :source => 'http://pgp.mit.edu:12345/key'
+ )}.to_not raise_error
+ end
+
+ it 'allows 5-digit ports when using key servers' do
+ expect { Puppet::Type.type(:apt_key).new(
+ :id => '4BD6EC30',
+ :server => 'http://pgp.mit.edu:12345'
+ )}.to_not raise_error
+ end
end
end
#file generated by puppet
# <%= @comment %>
<%- if @include_deb then -%>
-deb <% if @architecture %>[arch=<%= @architecture %>] <% end %><%= @location %> <%= @release_real %> <%= @repos %>
+deb <%- if @architecture or @trusted_source -%>
+[<%- if @architecture %>arch=<%= @architecture %> <% end %><% if @trusted_source %>trusted=yes<% end -%>
+] <%- end %><%= @location %> <%= @release_real %> <%= @repos %>
<%- end -%>
<%- if @include_src then -%>
-deb-src <% if @architecture %>[arch=<%= @architecture %>] <% end %><%= @location %> <%= @release_real %> <%= @repos %>
+deb-src <%- if @architecture or @trusted_source -%>
+[<%- if @architecture %>arch=<%= @architecture %> <% end %><% if @trusted_source %>trusted=yes<% end -%>
+] <%- end %><%= @location %> <%= @release_real %> <%= @repos %>
<%- end -%>