From: Bryan Jen Date: Mon, 13 Apr 2015 17:21:12 +0000 (-0700) Subject: Merge pull request #494 from mhaskel/cleanup-backports X-Git-Tag: 2.0.0~6 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=75ac82ce6419af78f32adae6b50233cf90ac9319;hp=778aae8e13a8da0517a9a7deac4fc60a09ca4b89;p=puppet-modules%2Fpuppetlabs-apt.git Merge pull request #494 from mhaskel/cleanup-backports Cleanup backports --- diff --git a/README.md b/README.md index 26feda3..d461d05 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,12 @@ class { 'apt': } * `apt`: Main class, provides common resources and options. Allows Puppet to manage your system's sources.list file and sources.list.d directory. By default, it will purge any existing content it finds that wasn't declared with Puppet. + * `apt::backports`: This class adds the necessary components to get backports for Ubuntu and Debian. The release name defaults to "$lsbdistcodename-backports". Setting this manually can cause undefined and potentially serious behavior. + + By default, this class drops a pin-file for backports, pinning it to a priority of 200. This is lower than the normal Debian archive, which gets a priority of 500 to ensure that packages with `ensure => latest` don't get magically upgraded from backports without your explicit permission. + + If you raise the priority through the `pin` parameter to 500---identical to the rest of the Debian mirrors---normal policy goes into effect, and Apt installs or upgrades to the newest version. This means that if a package is available from backports, it and its dependencies are pulled in from backports unless you explicitly set the `ensure` attribute of the `package` resource to `installed`/`present` or a specific version. + * `apt::params`: Sets defaults for the apt module parameters. * `apt::update`: Runs `apt-get update`, updating the list of available packages and their versions without installing or upgrading any packages. The update runs on the first Puppet run after you include the class, then whenever `notify => Exec['apt_update']` occurs; i.e., whenever config files get updated or other relevant changes occur. If you set `update['frequency']` to `'always'`, the update runs on every Puppet run. @@ -178,7 +184,7 @@ apt::sources: ### Parameters -#### apt +####apt * `update`: Hash to configure various update settings. Valid keys are: * 'frequency': The run frequency for `apt-get update`. Defaults to 'reluctantly'. Accepts the following values: @@ -202,6 +208,14 @@ apt::sources: * `settings`: Passes a hash to `create\_resource` to make new `apt::setting` resources. * `sources`: Passes a hash to `create\_resource` to make new `apt::source` resources. +####apt::backports + +* `location`: The URL of the apt repository. OS-dependent defaults are specifed in `apt::params` for Ubuntu and Debian. Required parameter for other OSes. +* `release`: The distribution of the apt repository. Defaults to "${lsbdistcodename}-backports" for Ubuntu and Debian. Required parameter for other OSes. +* `repos`: The component of the apt repository. OS-dependent defaults are speicifed in `apt::params` for Ubuntu and Debian. Required parameter for other OSes. +* `key`: The key for the backports repository. Can either be a string or a hash. See apt::setting for details on passing key as a hash. OS-dependent defaults are specified in `apt::params` for Ubuntu and Debian. Required parameter for other OSes. +* `pin`: The pin priority for backports repository. Can either be a number, a string, or a hash that will be passed as parameters to `apt::pin`. Defaults to `200`. + ####apt::conf * `content`: The content of the configuration file. @@ -269,7 +283,7 @@ It is recommended to read the manpage 'apt_preferences(5)' * 'content': See `content` in `apt::key` * 'source': See `source` in `apt::key` * 'options': See `options` in `apt::key` -* `pin`: See apt::pin. Defaults to false. +* `pin`: See apt::pin. Defaults to undef. Can be a string, number, or a hash to be passed as parameters to `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'. * `allow\_unsigned`: 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`. diff --git a/examples/backports.pp b/examples/backports.pp index ed8213f..fe77da3 100644 --- a/examples/backports.pp +++ b/examples/backports.pp @@ -1,31 +1,10 @@ -$location = $::apt::distcodename ? { - 'squeeze' => 'http://backports.debian.org/debian-backports', - 'wheezy' => 'http://ftp.debian.org/debian/', - default => 'http://archive.ubuntu.com/ubuntu', -} - -if $::apt::distid == 'debian' { - $repos = 'main contrib non-free' - $key = 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553' - $release = $::apt::distcodename -} else { - $repos = 'main universe multiverse restricted' - $key = '630239CC130E1A7FD81A27B140976EAF437D05B5' - $release = $::apt::distcodename -} - -# set up the actual backports -apt::pin { 'backports': - release => "${release}-backports", - priority => 200, -} - -apt::source { 'backports': - location => $location, - release => "${release}-backports", - repos => $repos, +# Set up a backport for linuxmint qiana +apt::backports { 'qiana': + location => 'http://us.archive.ubuntu.com/ubuntu', + release => 'trusty-backports', + repos => 'main universe multiverse restricted', key => { - id => $key, + id => '630239CC130E1A7FD81A27B140976EAF437D05B5', server => 'pgp.mit.edu', }, } diff --git a/manifests/backports.pp b/manifests/backports.pp new file mode 100644 index 0000000..3cac0b5 --- /dev/null +++ b/manifests/backports.pp @@ -0,0 +1,59 @@ +class apt::backports ( + $location = undef, + $release = undef, + $repos = undef, + $key = undef, + $pin = 200, +){ + if $location { + validate_string($location) + $_location = $location + } + if $release { + validate_string($release) + $_release = $release + } + if $repos { + validate_string($repos) + $_repos = $repos + } + if $key { + unless is_hash($key) { + validate_string($key) + } + $_key = $key + } + unless is_hash($pin) { + unless (is_numeric($pin) or is_string($pin)) { + fail('pin must be either a string, number or hash') + } + } + + if ($::apt::xfacts['lsbdistid'] == 'debian' or $::apt::xfacts['lsbdistid'] == 'ubuntu') { + unless $location { + $_location = $::apt::backports['location'] + } + unless $release { + $_release = "${::apt::xfacts['lsbdistcodename']}-backports" + } + unless $repos { + $_repos = $::apt::backports['repos'] + } + unless $key { + $_key = $::apt::backports['key'] + } + } else { + unless $location and $release and $repos and $key { + fail('If not on Debian or Ubuntu, you must explicitly pass location, release, repos, and key') + } + } + + apt::source { 'backports': + location => $_location, + release => $_release, + repos => $_repos, + key => $_key, + pin => $pin, + } + +} diff --git a/manifests/params.pp b/manifests/params.pp index 57cee50..ef9904d 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -119,7 +119,31 @@ class apt::params { } } case $distid { + 'debian': { + case $distcodename { + 'squeeze': { + $backports = { + 'location' => 'http://backports.debian.org/debian-backports', + 'key' => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + 'repos' => 'main contrib non-free', + } + } + default: { + $backports = { + 'location' => 'http://ftp.debian.org/debian/', + 'key' => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + 'repos' => 'main contrib non-free', + } + } + } + } 'ubuntu': { + $backports = { + 'location' => 'http://archive.ubuntu.com/ubuntu', + 'key' => '630239CC130E1A7FD81A27B140976EAF437D05B5', + 'repos' => 'main universe multiverse restricted', + } + case $distcodename { 'lucid': { $ppa_options = undef @@ -142,6 +166,7 @@ class apt::params { '', default: { $ppa_options = undef $ppa_package = undef + $backports = undef } } } diff --git a/manifests/source.pp b/manifests/source.pp index 163a411..40fc015 100644 --- a/manifests/source.pp +++ b/manifests/source.pp @@ -8,7 +8,7 @@ define apt::source( $repos = 'main', $include = {}, $key = undef, - $pin = false, + $pin = undef, $architecture = undef, $allow_unsigned = false, ) { @@ -44,17 +44,22 @@ define apt::source( content => template('apt/_header.erb', 'apt/source.list.erb'), } - if ($pin != false) { - # Get the host portion out of the url so we can pin to origin - $url_split = split($location, '/') - $host = $url_split[2] - - apt::pin { $name: - ensure => $ensure, - priority => $pin, - before => $_before, - origin => $host, + if $pin { + if is_hash($pin) { + $_pin = merge($pin, { 'ensure' => $ensure, 'before' => $_before }) + } elsif (is_numeric($pin) or is_string($pin)) { + $url_split = split($location, '/') + $host = $url_split[2] + $_pin = { + 'ensure' => $ensure, + 'priority' => $pin, + 'before' => $_before, + 'origin' => $host, + } + } else { + fail('Received invalid value for pin parameter') } + create_resources('apt::pin', { "${name}" => $_pin }) } # We do not want to remove keys when the source is absent. diff --git a/spec/classes/apt_backports_spec.rb b/spec/classes/apt_backports_spec.rb new file mode 100644 index 0000000..b9077a6 --- /dev/null +++ b/spec/classes/apt_backports_spec.rb @@ -0,0 +1,261 @@ +#!/usr/bin/env rspec +require 'spec_helper' + +describe 'apt::backports', :type => :class do + let (:pre_condition) { "class{ '::apt': }" } + describe 'debian/ubuntu tests' do + context 'defaults on deb' do + let(:facts) do + { + :lsbdistid => 'Debian', + :osfamily => 'Debian', + :lsbdistcodename => 'wheezy', + } + end + it { is_expected.to contain_apt__source('backports').with({ + :location => 'http://ftp.debian.org/debian/', + :key => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + :repos => 'main contrib non-free', + :release => 'wheezy-backports', + :pin => 200, + }) + } + end + context 'defaults on squeeze' do + let(:facts) do + { + :lsbdistid => 'Debian', + :osfamily => 'Debian', + :lsbdistcodename => 'squeeze', + } + end + it { is_expected.to contain_apt__source('backports').with({ + :location => 'http://backports.debian.org/debian-backports', + :key => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + :repos => 'main contrib non-free', + :release => 'squeeze-backports', + :pin => 200, + }) + } + end + context 'defaults on ubuntu' do + let(:facts) do + { + :lsbdistid => 'Ubuntu', + :osfamily => 'Debian', + :lsbdistcodename => 'trusty', + } + end + it { is_expected.to contain_apt__source('backports').with({ + :location => 'http://archive.ubuntu.com/ubuntu', + :key => '630239CC130E1A7FD81A27B140976EAF437D05B5', + :repos => 'main universe multiverse restricted', + :release => 'trusty-backports', + :pin => 200, + }) + } + end + context 'set everything' do + let(:facts) do + { + :lsbdistid => 'Ubuntu', + :osfamily => 'Debian', + :lsbdistcodename => 'trusty', + } + end + let(:params) do + { + :location => 'http://archive.ubuntu.com/ubuntu-test', + :release => 'vivid', + :repos => 'main', + :key => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + :pin => '90', + } + end + it { is_expected.to contain_apt__source('backports').with({ + :location => 'http://archive.ubuntu.com/ubuntu-test', + :key => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + :repos => 'main', + :release => 'vivid', + :pin => 90, + }) + } + end + context 'set things with hashes' do + let(:facts) do + { + :lsbdistid => 'Ubuntu', + :osfamily => 'Debian', + :lsbdistcodename => 'trusty', + } + end + let(:params) do + { + :key => { + 'id' => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + }, + :pin => { + 'priority' => '90', + }, + } + end + it { is_expected.to contain_apt__source('backports').with({ + :key => { 'id' => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553' }, + :pin => { 'priority' => '90' }, + }) + } + end + end + describe 'mint tests' do + let(:facts) do + { + :lsbdistid => 'linuxmint', + :osfamily => 'Debian', + :lsbdistcodename => 'qiana', + } + end + context 'sets all the needed things' do + let(:params) do + { + :location => 'http://archive.ubuntu.com/ubuntu', + :release => 'trusty-backports', + :repos => 'main universe multiverse restricted', + :key => '630239CC130E1A7FD81A27B140976EAF437D05B5', + } + end + it { is_expected.to contain_apt__source('backports').with({ + :location => 'http://archive.ubuntu.com/ubuntu', + :key => '630239CC130E1A7FD81A27B140976EAF437D05B5', + :repos => 'main universe multiverse restricted', + :release => 'trusty-backports', + :pin => 200, + }) + } + end + context 'missing location' do + let(:params) do + { + :release => 'trusty-backports', + :repos => 'main universe multiverse restricted', + :key => '630239CC130E1A7FD81A27B140976EAF437D05B5', + } + end + it do + expect { + is_expected.to compile + }.to raise_error(Puppet::Error, /If not on Debian or Ubuntu, you must explicitly pass location, release, repos, and key/) + end + end + context 'missing release' do + let(:params) do + { + :location => 'http://archive.ubuntu.com/ubuntu', + :repos => 'main universe multiverse restricted', + :key => '630239CC130E1A7FD81A27B140976EAF437D05B5', + } + end + it do + expect { + is_expected.to compile + }.to raise_error(Puppet::Error, /If not on Debian or Ubuntu, you must explicitly pass location, release, repos, and key/) + end + end + context 'missing repos' do + let(:params) do + { + :location => 'http://archive.ubuntu.com/ubuntu', + :release => 'trusty-backports', + :key => '630239CC130E1A7FD81A27B140976EAF437D05B5', + } + end + it do + expect { + is_expected.to compile + }.to raise_error(Puppet::Error, /If not on Debian or Ubuntu, you must explicitly pass location, release, repos, and key/) + end + end + context 'missing key' do + let(:params) do + { + :location => 'http://archive.ubuntu.com/ubuntu', + :release => 'trusty-backports', + :repos => 'main universe multiverse restricted', + } + end + it do + expect { + is_expected.to compile + }.to raise_error(Puppet::Error, /If not on Debian or Ubuntu, you must explicitly pass location, release, repos, and key/) + end + end + end + describe 'validation' do + let(:facts) do + { + :lsbdistid => 'Ubuntu', + :osfamily => 'Debian', + :lsbdistcodename => 'trusty', + } + end + context 'invalid location' do + let(:params) do + { + :location => true + } + end + it do + expect { + is_expected.to compile + }.to raise_error(Puppet::Error, /is not a string/) + end + end + context 'invalid release' do + let(:params) do + { + :release => true + } + end + it do + expect { + is_expected.to compile + }.to raise_error(Puppet::Error, /is not a string/) + end + end + context 'invalid repos' do + let(:params) do + { + :repos => true + } + end + it do + expect { + is_expected.to compile + }.to raise_error(Puppet::Error, /is not a string/) + end + end + context 'invalid key' do + let(:params) do + { + :key => true + } + end + it do + expect { + is_expected.to compile + }.to raise_error(Puppet::Error, /is not a string/) + end + end + context 'invalid pin' do + let(:params) do + { + :pin => true + } + end + it do + expect { + is_expected.to compile + }.to raise_error(Puppet::Error, /pin must be either a string, number or hash/) + end + end + end +end diff --git a/spec/defines/source_spec.rb b/spec/defines/source_spec.rb index 7fd86b5..3900158 100644 --- a/spec/defines/source_spec.rb +++ b/spec/defines/source_spec.rb @@ -51,6 +51,31 @@ describe 'apt::source' do :osfamily => 'Debian' } end + + context 'with complex pin' do + let :params do + { + :location => 'hello.there', + :pin => { 'release' => 'wishwash', + 'explanation' => 'wishwash', + 'priority' => 1001, }, + } + end + + it { is_expected.to contain_apt__setting('list-my_source').with({ + :ensure => 'present', + }).with_content(/hello.there wheezy main\n/) + } + + it { is_expected.to contain_apt__pin('my_source').that_comes_before('Apt::Setting[list-my_source]').with({ + :ensure => 'present', + :priority => 1001, + :explanation => 'wishwash', + :release => 'wishwash', + }) + } + end + context 'with simple key' do let :params do { @@ -235,5 +260,28 @@ describe 'apt::source' do }.to raise_error(Puppet::Error, /lsbdistcodename fact not available: release parameter required/) end end + + context 'invalid pin' do + let :facts do + { + :lsbdistid => 'Debian', + :lsbdistcodename => 'wheezy', + :osfamily => 'Debian' + } + end + let :params do + { + :location => 'hello.there', + :pin => true, + } + end + + it do + expect { + is_expected.to compile + }.to raise_error(Puppet::Error, /invalid value for pin/) + end + end + end end