diff options
author | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2018-09-16 22:59:26 +0200 |
---|---|---|
committer | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2018-09-16 22:59:26 +0200 |
commit | 3f1bbf87bbcc3daa15cd7391b2949b5bf742781b (patch) | |
tree | e7c058c84b2d8aebb84db73bb00429cdf284fc13 /code/environments/production/modules/apt/spec | |
parent | 852be73c92e8a950dd0c3514cadd67058717b212 (diff) | |
download | puppet.FWSECK-3f1bbf87bbcc3daa15cd7391b2949b5bf742781b.tar.gz puppet.FWSECK-3f1bbf87bbcc3daa15cd7391b2949b5bf742781b.tar.bz2 puppet.FWSECK-3f1bbf87bbcc3daa15cd7391b2949b5bf742781b.zip |
modules/apt: Ship puppetlabs-apt module v4.5.1.
Diffstat (limited to 'code/environments/production/modules/apt/spec')
36 files changed, 4683 insertions, 0 deletions
diff --git a/code/environments/production/modules/apt/spec/acceptance/apt_key_provider_spec.rb b/code/environments/production/modules/apt/spec/acceptance/apt_key_provider_spec.rb new file mode 100644 index 0000000..08bf61f --- /dev/null +++ b/code/environments/production/modules/apt/spec/acceptance/apt_key_provider_spec.rb @@ -0,0 +1,836 @@ +require 'spec_helper_acceptance' + +PUPPETLABS_GPG_KEY_SHORT_ID = 'EF8D349F'.freeze +PUPPETLABS_GPG_KEY_LONG_ID = '7F438280EF8D349F'.freeze +PUPPETLABS_GPG_KEY_FINGERPRINT = '6F6B15509CF8E59E6E469F327F438280EF8D349F'.freeze +PUPPETLABS_APT_URL = 'apt.puppetlabs.com'.freeze +PUPPETLABS_GPG_KEY_FILE = 'DEB-GPG-KEY-puppet'.freeze +CENTOS_GPG_KEY_SHORT_ID = 'C105B9DE'.freeze +CENTOS_GPG_KEY_LONG_ID = '0946FCA2C105B9DE'.freeze +CENTOS_GPG_KEY_FINGERPRINT = 'C1DAC52D1664E8A4386DBA430946FCA2C105B9DE'.freeze +CENTOS_REPO_URL = 'ftp.cvut.cz/centos'.freeze +CENTOS_GPG_KEY_FILE = 'RPM-GPG-KEY-CentOS-6'.freeze + +SHOULD_NEVER_EXIST_ID = 'EF8D349F'.freeze + +KEY_CHECK_COMMAND = 'apt-key adv --list-keys --with-colons --fingerprint | grep '.freeze +PUPPETLABS_KEY_CHECK_COMMAND = "#{KEY_CHECK_COMMAND} #{PUPPETLABS_GPG_KEY_FINGERPRINT}".freeze +CENTOS_KEY_CHECK_COMMAND = "#{KEY_CHECK_COMMAND} #{CENTOS_GPG_KEY_FINGERPRINT}".freeze + +MAX_TIMEOUT_RETRY = 3 +TIMEOUT_RETRY_WAIT = 5 +TIMEOUT_ERROR_MATCHER = %r{no valid OpenPGP data found} + +def populate_default_options_pp(value) + default_options_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{value}', + ensure => 'present', + } + MANIFEST + default_options_pp +end + +def install_key(key) + retry_on_error_matching(MAX_TIMEOUT_RETRY, TIMEOUT_RETRY_WAIT, TIMEOUT_ERROR_MATCHER) do + shell("apt-key adv --keyserver hkps.pool.sks-keyservers.net \ + --recv-keys #{key}") + end +end + +def apply_manifest_twice(manifest_pp) + apply_manifest(manifest_pp, catch_failures: true) + apply_manifest(manifest_pp, catch_changes: true) +end + +invalid_key_length_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '8280EF8D349F', + } + MANIFEST + +ensure_absent_pp = <<-MANIFEST + apt_key { 'centos': + id => '#{CENTOS_GPG_KEY_LONG_ID}', + ensure => 'absent', + } + MANIFEST + +ensure_absent_long_key_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'absent', + } + MANIFEST + +gpg_key_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_FINGERPRINT}', + ensure => 'present', + content => "-----BEGIN PGP PUBLIC KEY BLOCK----- + + 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 + 3xJn + =mMjt + -----END PGP PUBLIC KEY BLOCK-----", + } + MANIFEST + +multiple_keys_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_FINGERPRINT}', + ensure => 'present', + content => "-----BEGIN PGP PUBLIC KEY BLOCK----- + Version: GnuPG v1 + + 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 + FPfZDNCu/TXoqyJk7434jJrcHgPryzrHFBLfEmc= + =TREp + -----END PGP PUBLIC KEY BLOCK----- ", + } + MANIFEST + +bogus_key_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + content => 'For posterity: such content, much bogus, wow', + } + MANIFEST + +hkps_pool_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + server => 'hkps.pool.sks-keyservers.net', + } + MANIFEST + +hkp_pool_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_FINGERPRINT}', + ensure => 'present', + server => 'hkp://hkps.pool.sks-keyservers.net:80', + } + MANIFEST + +nonexistant_key_server_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + server => 'nonexistant.key.server', + } + MANIFEST + +dot_server_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + server => '.pgp.key.server', + } + MANIFEST + +http_works_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + source => 'http://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}', + } + MANIFEST + +http_works_userinfo_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + source => 'http://dummyuser:dummypassword@#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}', + } + MANIFEST + +four_oh_four_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + source => 'http://#{PUPPETLABS_APT_URL}/herpderp.gpg', + } + MANIFEST + +socket_error_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + source => 'http://apt.puppetlabss.com/herpderp.gpg', + } + MANIFEST + +ftp_works_pp = <<-MANIFEST + apt_key { 'CentOS 6': + id => '#{CENTOS_GPG_KEY_LONG_ID}', + ensure => 'present', + source => 'ftp://#{CENTOS_REPO_URL}/#{CENTOS_GPG_KEY_FILE}', + } + MANIFEST + +ftp_550_pp = <<-MANIFEST + apt_key { 'CentOS 6': + id => '#{SHOULD_NEVER_EXIST_ID}', + ensure => 'present', + source => 'ftp://#{CENTOS_REPO_URL}/herpderp.gpg', + } + MANIFEST + +ftp_socket_error_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + source => 'ftp://apt.puppetlabss.com/herpderp.gpg', + } + MANIFEST + +https_works_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + source => 'https://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}', + } + MANIFEST + +https_userinfo_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + source => 'https://dummyuser:dummypassword@#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}', + } + MANIFEST + +https_404_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{SHOULD_NEVER_EXIST_ID}', + ensure => 'present', + source => 'https://#{PUPPETLABS_APT_URL}/herpderp.gpg', + } + MANIFEST + +https_socket_error_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{SHOULD_NEVER_EXIST_ID}', + ensure => 'present', + source => 'https://apt.puppetlabss.com/herpderp.gpg', + } + MANIFEST + +path_exists_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => 'EF8D349F', + ensure => 'present', + source => '/tmp/puppetlabs-pubkey.gpg', + } + MANIFEST + +path_does_not_exist_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + source => '/tmp/totally_bogus.file', + } + MANIFEST + +path_bogus_content_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + source => '/tmp/fake-key.gpg', + } + MANIFEST + +debug_works_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + options => 'debug', + } + MANIFEST + +fingerprint_match_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_FINGERPRINT}', + ensure => 'present', + source => 'https://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}', + } + MANIFEST + +fingerprint_does_not_match_pp = <<-MANIFEST + apt_key { 'puppetlabs': + id => '6F6B15509CF8E59E6E469F327F438280EF8D9999', + ensure => 'present', + source => 'https://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}', + } + MANIFEST + +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_SHORT_ID}", + acceptable_exit_codes: [0, 1, 2]) + shell("apt-key del #{PUPPETLABS_GPG_KEY_SHORT_ID}", + acceptable_exit_codes: [0, 1, 2]) + end + + describe 'default options' do + key_versions = { + '32bit key id' => PUPPETLABS_GPG_KEY_SHORT_ID.to_s, + '64bit key id' => PUPPETLABS_GPG_KEY_LONG_ID.to_s, + '160bit key fingerprint' => PUPPETLABS_GPG_KEY_FINGERPRINT.to_s, + '32bit lowercase key id' => PUPPETLABS_GPG_KEY_SHORT_ID.downcase.to_s, + '64bit lowercase key id' => PUPPETLABS_GPG_KEY_LONG_ID.downcase.to_s, + '160bit lowercase key fingerprint' => PUPPETLABS_GPG_KEY_FINGERPRINT.downcase.to_s, + '0x formatted 32bit key id' => "0x#{PUPPETLABS_GPG_KEY_SHORT_ID}", + '0x formatted 64bit key id' => "0x#{PUPPETLABS_GPG_KEY_LONG_ID}", + '0x formatted 160bit key fingerprint' => "0x#{PUPPETLABS_GPG_KEY_FINGERPRINT}", + '0x formatted 32bit lowercase key id' => "0x#{PUPPETLABS_GPG_KEY_SHORT_ID.downcase}", + '0x formatted 64bit lowercase key id' => "0x#{PUPPETLABS_GPG_KEY_LONG_ID.downcase}", + '0x formatted 160bit lowercase key fingerprint' => "0x#{PUPPETLABS_GPG_KEY_FINGERPRINT.downcase}", + } + + key_versions.each do |key, value| # rubocop:disable Lint/UnusedBlockArgument + context 'when key.to_s' do + it 'works' do + apply_manifest_twice(populate_default_options_pp(value)) + shell(PUPPETLABS_KEY_CHECK_COMMAND) + end + end + end + + context 'with invalid length key id' do + it 'fails' do + apply_manifest(invalid_key_length_pp, expect_failures: true) do |r| + expect(r.stderr).to match(%r{Valid values match}) + end + end + end + end + + describe 'ensure =>' do + context 'when absent' do + it 'is removed' do + # Install the key first (retry because key pool may timeout) + install_key(CENTOS_GPG_KEY_FINGERPRINT) + shell(CENTOS_KEY_CHECK_COMMAND) + + # Time to remove it using Puppet + apply_manifest_twice(ensure_absent_pp) + + shell(CENTOS_KEY_CHECK_COMMAND, acceptable_exit_codes: [1]) + + # Re-Install the key (retry because key pool may timeout) + install_key(CENTOS_GPG_KEY_FINGERPRINT) + end + end + + context 'when absent, added with long key', unless: (fact('operatingsystem') == 'Debian' && fact('operatingsystemmajrelease') == '6') do + it 'is removed' do + # Install the key first (retry because key pool may timeout) + install_key(PUPPETLABS_GPG_KEY_LONG_ID) + shell(PUPPETLABS_KEY_CHECK_COMMAND) + + # Time to remove it using Puppet + apply_manifest_twice(ensure_absent_long_key_pp) + + shell(PUPPETLABS_KEY_CHECK_COMMAND, acceptable_exit_codes: [1]) + end + end + end + + describe 'content =>' do + context 'with puppetlabs gpg key' do + it 'works' do + # Apply the manifest (Retry if timeout error is received from key pool) + retry_on_error_matching(MAX_TIMEOUT_RETRY, TIMEOUT_RETRY_WAIT, TIMEOUT_ERROR_MATCHER) do + apply_manifest(gpg_key_pp, catch_failures: true) + end + + apply_manifest(gpg_key_pp, catch_changes: true) + shell(PUPPETLABS_KEY_CHECK_COMMAND) + end + end + + context 'with multiple keys' do + it 'runs without errors' do + apply_manifest_twice(multiple_keys_pp) + shell(PUPPETLABS_KEY_CHECK_COMMAND) + end + end + + context 'with bogus key' do + it 'fails' do + apply_manifest(bogus_key_pp, expect_failures: true) do |r| + expect(r.stderr).to match(%r{no valid OpenPGP data found}) + end + end + end + end + + describe 'server =>' do + context 'with hkps.pool.sks-keyservers.net' do + it 'works' do + # Apply the manifest (Retry if timeout error is received from key pool) + retry_on_error_matching(MAX_TIMEOUT_RETRY, TIMEOUT_RETRY_WAIT, TIMEOUT_ERROR_MATCHER) do + apply_manifest(hkps_pool_pp, catch_failures: true) + end + + apply_manifest(hkps_pool_pp, catch_changes: true) + shell(PUPPETLABS_KEY_CHECK_COMMAND) + end + end + + context 'with hkp://hkps.pool.sks-keyservers.net:80' do + it 'works' do + retry_on_error_matching(MAX_TIMEOUT_RETRY, TIMEOUT_RETRY_WAIT, TIMEOUT_ERROR_MATCHER) do + apply_manifest(hkp_pool_pp, catch_failures: true) + end + + apply_manifest(hkp_pool_pp, catch_changes: true) + shell(PUPPETLABS_KEY_CHECK_COMMAND) + end + end + + context 'with nonexistant.key.server' do + it 'fails' do + apply_manifest(nonexistant_key_server_pp, expect_failures: true) do |r| + expect(r.stderr).to match(%r{(Host not found|Couldn't resolve host)}) + end + end + end + + context 'with key server start with dot' do + it 'fails' do + apply_manifest(dot_server_pp, expect_failures: true) do |r| + expect(r.stderr).to match(%r{Invalid value ".pgp.key.server"}) + end + end + end + end + + describe 'source =>' do + context 'with http://' do + it 'works' do + apply_manifest_twice(http_works_pp) + shell(PUPPETLABS_KEY_CHECK_COMMAND) + end + + it 'works with userinfo' do + apply_manifest_twice(http_works_userinfo_pp) + shell(PUPPETLABS_KEY_CHECK_COMMAND) + end + + it 'fails with a 404' do + apply_manifest(four_oh_four_pp, expect_failures: true) do |r| + expect(r.stderr).to match(%r{404 Not Found}) + end + end + + it 'fails with a socket error' do + apply_manifest(socket_error_pp, expect_failures: true) do |r| + expect(r.stderr).to match(%r{could not resolve}) + end + end + end + + context 'with ftp://' do + before(:each) do + shell("apt-key del #{CENTOS_GPG_KEY_LONG_ID}", + acceptable_exit_codes: [0, 1, 2]) + end + + it 'works' do + apply_manifest_twice(ftp_works_pp) + shell(CENTOS_KEY_CHECK_COMMAND) + end + + it 'fails with a 550' do + apply_manifest(ftp_550_pp, expect_failures: true) do |r| + expect(r.stderr).to match(%r{550 Failed to open}) + end + end + + it 'fails with a socket error' do + apply_manifest(ftp_socket_error_pp, expect_failures: true) do |r| + expect(r.stderr).to match(%r{could not resolve}) + end + end + end + + context 'with https://' do + it 'works' do + apply_manifest_twice(https_works_pp) + shell(PUPPETLABS_KEY_CHECK_COMMAND) + end + + it 'works with userinfo' do + apply_manifest_twice(https_userinfo_pp) + shell(PUPPETLABS_KEY_CHECK_COMMAND) + end + + it 'fails with a 404' do + apply_manifest(https_404_pp, expect_failures: true) do |r| + expect(r.stderr).to match(%r{404 Not Found}) + end + end + + it 'fails with a socket error' do + apply_manifest(https_socket_error_pp, expect_failures: true) do |r| + expect(r.stderr).to match(%r{could not resolve}) + end + end + end + + context 'with /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 + apply_manifest_twice(path_exists_pp) + shell(PUPPETLABS_KEY_CHECK_COMMAND) + end + end + + context 'with /path/that/does/not/exist' do + it 'fails' do + apply_manifest(path_does_not_exist_pp, expect_failures: true) do |r| + expect(r.stderr).to match(%r{does not exist}) + end + end + end + + context 'with /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 + apply_manifest(path_bogus_content_pp, expect_failures: true) do |r| + expect(r.stderr).to match(%r{no valid OpenPGP data found}) + end + end + end + end + + describe 'options =>' do + context 'with debug' do + it 'works' do + apply_manifest_twice(debug_works_pp) + shell(PUPPETLABS_KEY_CHECK_COMMAND) + end + end + end + + describe 'fingerprint validation against source/content' do + context 'with fingerprint in id matches fingerprint from remote key' do + it 'works' do + apply_manifest_twice(fingerprint_match_pp) + end + end + + context 'with fingerprint in id does NOT match fingerprint from remote key' do + it 'works' do + apply_manifest(fingerprint_does_not_match_pp, expect_failures: true) do |r| + expect(r.stderr).to match(%r{don't match}) + end + end + end + end +end diff --git a/code/environments/production/modules/apt/spec/acceptance/apt_spec.rb b/code/environments/production/modules/apt/spec/acceptance/apt_spec.rb new file mode 100644 index 0000000..5505748 --- /dev/null +++ b/code/environments/production/modules/apt/spec/acceptance/apt_spec.rb @@ -0,0 +1,66 @@ +require 'spec_helper_acceptance' + +MAX_TIMEOUT_RETRY = 3 +TIMEOUT_RETRY_WAIT = 5 +TIMEOUT_ERROR_MATCHER = %r{no valid OpenPGP data found} + +everything_everything_pp = <<-MANIFEST + if $::lsbdistcodename == 'lucid' { + $sources = undef + } else { + $sources = { + 'puppetlabs' => { + 'ensure' => present, + 'location' => 'http://apt.puppetlabs.com', + 'repos' => 'main', + 'key' => { + 'id' => '6F6B15509CF8E59E6E469F327F438280EF8D349F', + 'server' => 'hkps.pool.sks-keyservers.net', + }, + }, + } + } + class { 'apt': + update => { + 'frequency' => 'always', + 'timeout' => 400, + 'tries' => 3, + }, + purge => { + 'sources.list' => true, + 'sources.list.d' => true, + 'preferences' => true, + 'preferences.d' => true, + }, + sources => $sources, + } + MANIFEST + +describe 'apt class' do + context 'with reset' do + it 'fixes the sources.list' do + shell('cp /etc/apt/sources.list /tmp') + end + end + + context 'with all the things' do + it 'works with no errors' do + # Apply the manifest (Retry if timeout error is received from key pool) + retry_on_error_matching(MAX_TIMEOUT_RETRY, TIMEOUT_RETRY_WAIT, TIMEOUT_ERROR_MATCHER) do + apply_manifest(everything_everything_pp, catch_failures: true) + end + + apply_manifest(everything_everything_pp, catch_failures: true) + end + it 'stills work' do + shell('apt-get update') + shell('apt-get -y --force-yes upgrade') + end + end + + context 'with reset' do + it 'fixes the sources.list' do + shell('cp /tmp/sources.list /etc/apt') + end + end +end diff --git a/code/environments/production/modules/apt/spec/acceptance/class_spec.rb b/code/environments/production/modules/apt/spec/acceptance/class_spec.rb new file mode 100644 index 0000000..53d75f6 --- /dev/null +++ b/code/environments/production/modules/apt/spec/acceptance/class_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper_acceptance' + +describe 'apt class' do + context 'with default parameters' do + # Using puppet_apply as a helper + it 'works with no errors' do + pp = <<-MANIFEST + class { 'apt': } + MANIFEST + + # Run it twice and test for idempotency + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) + end + end +end diff --git a/code/environments/production/modules/apt/spec/acceptance/init_task_spec.rb b/code/environments/production/modules/apt/spec/acceptance/init_task_spec.rb new file mode 100644 index 0000000..58f3ca7 --- /dev/null +++ b/code/environments/production/modules/apt/spec/acceptance/init_task_spec.rb @@ -0,0 +1,11 @@ +# run a test task +require 'spec_helper_acceptance' + +describe 'apt tasks' do + describe 'update and upgrade', if: pe_install? && puppet_version =~ %r{(5\.\d\.\d)} && fact_on(master, 'osfamily') == 'Debian' do + it 'execute arbitary sql' do + result = run_task(task_name: 'apt', params: 'action=update') + expect_multiple_regexes(result: result, regexes: [%r{Reading package lists}, %r{Job completed. 1/1 nodes succeeded}]) + end + end +end diff --git a/code/environments/production/modules/apt/spec/acceptance/nodesets/centos-7-x64.yml b/code/environments/production/modules/apt/spec/acceptance/nodesets/centos-7-x64.yml new file mode 100644 index 0000000..5eebdef --- /dev/null +++ b/code/environments/production/modules/apt/spec/acceptance/nodesets/centos-7-x64.yml @@ -0,0 +1,10 @@ +HOSTS: + centos-7-x64: + roles: + - agent + - default + platform: el-7-x86_64 + hypervisor: vagrant + box: puppetlabs/centos-7.2-64-nocm +CONFIG: + type: foss diff --git a/code/environments/production/modules/apt/spec/acceptance/nodesets/debian-8-x64.yml b/code/environments/production/modules/apt/spec/acceptance/nodesets/debian-8-x64.yml new file mode 100644 index 0000000..fef6e63 --- /dev/null +++ b/code/environments/production/modules/apt/spec/acceptance/nodesets/debian-8-x64.yml @@ -0,0 +1,10 @@ +HOSTS: + debian-8-x64: + roles: + - agent + - default + platform: debian-8-amd64 + hypervisor: vagrant + box: puppetlabs/debian-8.2-64-nocm +CONFIG: + type: foss diff --git a/code/environments/production/modules/apt/spec/acceptance/nodesets/default.yml b/code/environments/production/modules/apt/spec/acceptance/nodesets/default.yml new file mode 100644 index 0000000..dba339c --- /dev/null +++ b/code/environments/production/modules/apt/spec/acceptance/nodesets/default.yml @@ -0,0 +1,10 @@ +HOSTS: + ubuntu-1404-x64: + roles: + - agent + - default + platform: ubuntu-14.04-amd64 + hypervisor: vagrant + box: puppetlabs/ubuntu-14.04-64-nocm +CONFIG: + type: foss diff --git a/code/environments/production/modules/apt/spec/acceptance/nodesets/docker/centos-7.yml b/code/environments/production/modules/apt/spec/acceptance/nodesets/docker/centos-7.yml new file mode 100644 index 0000000..a3333aa --- /dev/null +++ b/code/environments/production/modules/apt/spec/acceptance/nodesets/docker/centos-7.yml @@ -0,0 +1,12 @@ +HOSTS: + centos-7-x64: + platform: el-7-x86_64 + hypervisor: docker + image: centos:7 + docker_preserve_image: true + docker_cmd: '["/usr/sbin/init"]' + # install various tools required to get the image up to usable levels + docker_image_commands: + - 'yum install -y crontabs tar wget openssl sysvinit-tools iproute which initscripts' +CONFIG: + trace_limit: 200 diff --git a/code/environments/production/modules/apt/spec/acceptance/nodesets/docker/debian-8.yml b/code/environments/production/modules/apt/spec/acceptance/nodesets/docker/debian-8.yml new file mode 100644 index 0000000..df5c319 --- /dev/null +++ b/code/environments/production/modules/apt/spec/acceptance/nodesets/docker/debian-8.yml @@ -0,0 +1,11 @@ +HOSTS: + debian-8-x64: + platform: debian-8-amd64 + hypervisor: docker + image: debian:8 + docker_preserve_image: true + docker_cmd: '["/sbin/init"]' + docker_image_commands: + - 'apt-get update && apt-get install -y net-tools wget locales strace lsof && echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen' +CONFIG: + trace_limit: 200 diff --git a/code/environments/production/modules/apt/spec/acceptance/nodesets/docker/ubuntu-14.04.yml b/code/environments/production/modules/apt/spec/acceptance/nodesets/docker/ubuntu-14.04.yml new file mode 100644 index 0000000..b1efa58 --- /dev/null +++ b/code/environments/production/modules/apt/spec/acceptance/nodesets/docker/ubuntu-14.04.yml @@ -0,0 +1,12 @@ +HOSTS: + ubuntu-1404-x64: + platform: ubuntu-14.04-amd64 + hypervisor: docker + image: ubuntu:14.04 + docker_preserve_image: true + docker_cmd: '["/sbin/init"]' + docker_image_commands: + # ensure that upstart is booting correctly in the container + - 'rm /usr/sbin/policy-rc.d && rm /sbin/initctl && dpkg-divert --rename --remove /sbin/initctl && apt-get update && apt-get install -y net-tools wget && locale-gen en_US.UTF-8' +CONFIG: + trace_limit: 200 diff --git a/code/environments/production/modules/apt/spec/classes/apt_backports_spec.rb b/code/environments/production/modules/apt/spec/classes/apt_backports_spec.rb new file mode 100644 index 0000000..33022b9 --- /dev/null +++ b/code/environments/production/modules/apt/spec/classes/apt_backports_spec.rb @@ -0,0 +1,253 @@ +require 'spec_helper' + +describe 'apt::backports', type: :class do + let(:pre_condition) { "class{ '::apt': }" } + + describe 'debian/ubuntu tests' do + context 'with defaults on deb' do + let(:facts) do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + lsbdistcodename: 'wheezy', + puppetversion: Puppet.version, + } + end + + it { + is_expected.to contain_apt__source('backports').with(location: 'http://deb.debian.org/debian', + key: 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + repos: 'main contrib non-free', + release: 'wheezy-backports', + pin: { 'priority' => 200, 'release' => 'wheezy-backports' }) + } + end + context 'with defaults on ubuntu' do + let(:facts) do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '14', full: '14.04' } }, + lsbdistid: 'Ubuntu', + osfamily: 'Debian', + lsbdistcodename: 'trusty', + lsbdistrelease: '14.04', + puppetversion: Puppet.version, + } + 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: { 'priority' => 200, 'release' => 'trusty-backports' }) + } + end + context 'with everything set' do + let(:facts) do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '14', full: '14.04' } }, + lsbdistid: 'Ubuntu', + osfamily: 'Debian', + lsbdistcodename: 'trusty', + lsbdistrelease: '14.04', + puppetversion: Puppet.version, + } + 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: { 'priority' => 90, 'release' => 'vivid' }) + } + end + context 'when set things with hashes' do + let(:facts) do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '14', full: '14.04' } }, + lsbdistid: 'Ubuntu', + osfamily: 'Debian', + lsbdistcodename: 'trusty', + lsbdistrelease: '14.04', + puppetversion: Puppet.version, + } + 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 + { + os: { family: 'Debian', name: 'Linuxmint', release: { major: '17', full: '17' } }, + lsbdistid: 'linuxmint', + osfamily: 'Debian', + lsbdistcodename: 'qiana', + puppetversion: Puppet.version, + } + end + + context 'with all the needed things set' 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: { 'priority' => 200, 'release' => 'trusty-backports' }) + } + end + context 'with missing location' do + let(:params) do + { + release: 'trusty-backports', + repos: 'main universe multiverse restricted', + key: '630239CC130E1A7FD81A27B140976EAF437D05B5', + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{If not on Debian or Ubuntu, you must explicitly pass location, release, repos, and key}) + end + end + context 'with missing release' do + let(:params) do + { + location: 'http://archive.ubuntu.com/ubuntu', + repos: 'main universe multiverse restricted', + key: '630239CC130E1A7FD81A27B140976EAF437D05B5', + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{If not on Debian or Ubuntu, you must explicitly pass location, release, repos, and key}) + end + end + context 'with missing repos' do + let(:params) do + { + location: 'http://archive.ubuntu.com/ubuntu', + release: 'trusty-backports', + key: '630239CC130E1A7FD81A27B140976EAF437D05B5', + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{If not on Debian or Ubuntu, you must explicitly pass location, release, repos, and key}) + end + end + context 'with missing key' do + let(:params) do + { + location: 'http://archive.ubuntu.com/ubuntu', + release: 'trusty-backports', + repos: 'main universe multiverse restricted', + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{If not on Debian or Ubuntu, you must explicitly pass location, release, repos, and key}) + end + end + end + describe 'validation' do + let(:facts) do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '14', full: '14.04' } }, + lsbdistid: 'Ubuntu', + osfamily: 'Debian', + lsbdistcodename: 'trusty', + lsbdistrelease: '14.04', + puppetversion: Puppet.version, + } + end + + context 'with invalid location' do + let(:params) do + { + location: true, + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{expects a}) + end + end + context 'with invalid release' do + let(:params) do + { + release: true, + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{expects a}) + end + end + context 'with invalid repos' do + let(:params) do + { + repos: true, + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{expects a}) + end + end + context 'with invalid key' do + let(:params) do + { + key: true, + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{expects a}) + end + end + context 'with invalid pin' do + let(:params) do + { + pin: true, + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{expects a}) + end + end + end +end diff --git a/code/environments/production/modules/apt/spec/classes/apt_spec.rb b/code/environments/production/modules/apt/spec/classes/apt_spec.rb new file mode 100644 index 0000000..0c6333b --- /dev/null +++ b/code/environments/production/modules/apt/spec/classes/apt_spec.rb @@ -0,0 +1,387 @@ +require 'spec_helper' + +sources_list = { ensure: 'file', + path: '/etc/apt/sources.list', + owner: 'root', + group: 'root', + mode: '0644', + notify: 'Class[Apt::Update]' } + +sources_list_d = { ensure: 'directory', + path: '/etc/apt/sources.list.d', + owner: 'root', + group: 'root', + mode: '0644', + purge: false, + recurse: false, + notify: 'Class[Apt::Update]' } + +preferences = { ensure: 'file', + path: '/etc/apt/preferences', + owner: 'root', + group: 'root', + mode: '0644', + notify: 'Class[Apt::Update]' } + +preferences_d = { ensure: 'directory', + path: '/etc/apt/preferences.d', + owner: 'root', + group: 'root', + mode: '0644', + purge: false, + recurse: false, + notify: 'Class[Apt::Update]' } + +describe 'apt' do + let(:facts) do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + lsbdistcodename: 'wheezy', + puppetversion: Puppet.version, + } + end + + context 'with defaults' do + it { + is_expected.to contain_file('sources.list').that_notifies('Class[Apt::Update]').only_with(sources_list) + } + + it { + is_expected.to contain_file('sources.list.d').that_notifies('Class[Apt::Update]').only_with(sources_list_d) + } + + it { + is_expected.to contain_file('preferences').that_notifies('Class[Apt::Update]').only_with(preferences) + } + + it { + is_expected.to contain_file('preferences.d').that_notifies('Class[Apt::Update]').only_with(preferences_d) + } + + it 'lays down /etc/apt/apt.conf.d/15update-stamp' do + is_expected.to contain_file('/etc/apt/apt.conf.d/15update-stamp').with(group: 'root', + mode: '0644', + owner: 'root').with_content( + %r{APT::Update::Post-Invoke-Success {"touch /var/lib/apt/periodic/update-success-stamp 2>/dev/null || true";};}, + ) + end + + it { + is_expected.to contain_exec('apt_update').with(refreshonly: 'true') + } + + it { is_expected.not_to contain_apt__setting('conf-proxy') } + end + + describe 'proxy=' do + context 'when host=localhost' do + let(:params) { { proxy: { 'host' => 'localhost' } } } + + it { + is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content( + %r{Acquire::http::proxy "http://localhost:8080/";}, + ).without_content( + %r{Acquire::https::proxy}, + ) + } + end + + context 'when host=localhost and port=8180' do + let(:params) { { proxy: { 'host' => 'localhost', 'port' => 8180 } } } + + it { + is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content( + %r{Acquire::http::proxy "http://localhost:8180/";}, + ).without_content( + %r{Acquire::https::proxy}, + ) + } + end + + context 'when host=localhost and https=true' do + let(:params) { { proxy: { 'host' => 'localhost', 'https' => true } } } + + it { + is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content( + %r{Acquire::http::proxy "http://localhost:8080/";}, + ).with_content( + %r{Acquire::https::proxy "https://localhost:8080/";}, + ) + } + end + + context 'when host=localhost and direct=true' do + let(:params) { { proxy: { 'host' => 'localhost', 'direct' => true } } } + + it { + is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content( + %r{Acquire::http::proxy "http://localhost:8080/";}, + ).with_content( + %r{Acquire::https::proxy "DIRECT";}, + ) + } + end + + context 'when host=localhost and https=true and direct=true' do + let(:params) { { proxy: { 'host' => 'localhost', 'https' => true, 'direct' => true } } } + + it { + is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content( + %r{Acquire::http::proxy "http://localhost:8080/";}, + ).with_content( + %r{Acquire::https::proxy "https://localhost:8080/";}, + ) + } + it { + is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content( + %r{Acquire::http::proxy "http://localhost:8080/";}, + ).without_content( + %r{Acquire::https::proxy "DIRECT";}, + ) + } + end + + context 'when ensure=absent' do + let(:params) { { proxy: { 'ensure' => 'absent' } } } + + it { + is_expected.to contain_apt__setting('conf-proxy').with(ensure: 'absent', + priority: '01') + } + end + end + context 'with lots of non-defaults' do + let :params do + { + update: { 'frequency' => 'always', 'timeout' => 1, 'tries' => 3 }, + purge: { 'sources.list' => false, 'sources.list.d' => false, + 'preferences' => false, 'preferences.d' => false }, + } + end + + it { + is_expected.to contain_file('sources.list').with(content: nil) + } + + it { + is_expected.to contain_file('sources.list.d').with(purge: false, + recurse: false) + } + + it { + is_expected.to contain_file('preferences').with(ensure: 'file') + } + + it { + is_expected.to contain_file('preferences.d').with(purge: false, + recurse: false) + } + + it { + is_expected.to contain_exec('apt_update').with(refreshonly: false, + timeout: 1, + tries: 3) + } + end + + context 'with sources defined on valid osfamily' do + let :facts do + { os: { family: 'Debian', name: 'Ubuntu', release: { major: '12', full: '12.04' } }, + osfamily: 'Debian', + lsbdistcodename: 'precise', + lsbdistid: 'Ubuntu', + lsbdistrelease: '12.04', + puppetversion: Puppet.version } + end + let(:params) do + { sources: { + 'debian_unstable' => { + 'location' => 'http://debian.mirror.iweb.ca/debian/', + 'release' => 'unstable', + 'repos' => 'main contrib non-free', + 'key' => { 'id' => '150C8614919D8446E01E83AF9AA38DCD55BE302B', 'server' => 'subkeys.pgp.net' }, + 'pin' => '-10', + 'include' => { 'src' => true }, + }, + 'puppetlabs' => { + 'location' => 'http://apt.puppetlabs.com', + 'repos' => 'main', + 'key' => { 'id' => '6F6B15509CF8E59E6E469F327F438280EF8D349F', 'server' => 'pgp.mit.edu' }, + }, + } } + end + + it { + is_expected.to contain_apt__setting('list-debian_unstable').with(ensure: 'present') + } + + it { is_expected.to contain_file('/etc/apt/sources.list.d/debian_unstable.list').with_content(%r{^deb http://debian.mirror.iweb.ca/debian/ unstable main contrib non-free$}) } + it { is_expected.to contain_file('/etc/apt/sources.list.d/debian_unstable.list').with_content(%r{^deb-src http://debian.mirror.iweb.ca/debian/ unstable main contrib non-free$}) } + + it { + is_expected.to contain_apt__setting('list-puppetlabs').with(ensure: 'present') + } + + it { is_expected.to contain_file('/etc/apt/sources.list.d/puppetlabs.list').with_content(%r{^deb http://apt.puppetlabs.com precise main$}) } + end + + context 'with confs defined on valid osfamily' do + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '12', full: '12.04.5' } }, + osfamily: 'Debian', + lsbdistcodename: 'precise', + lsbdistid: 'Debian', + puppetversion: Puppet.version, + } + end + let(:params) do + { confs: { + 'foo' => { + 'content' => 'foo', + }, + 'bar' => { + 'content' => 'bar', + }, + } } + end + + it { + is_expected.to contain_apt__conf('foo').with(content: 'foo') + } + + it { + is_expected.to contain_apt__conf('bar').with(content: 'bar') + } + end + + context 'with keys defined on valid osfamily' do + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '12', full: '12.04.5' } }, + osfamily: 'Debian', + lsbdistcodename: 'precise', + lsbdistid: 'Debian', + puppetversion: Puppet.version, + } + end + let(:params) do + { keys: { + '55BE302B' => { + 'server' => 'subkeys.pgp.net', + }, + 'EF8D349F' => { + 'server' => 'pgp.mit.edu', + }, + } } + end + + it { + is_expected.to contain_apt__key('55BE302B').with(server: 'subkeys.pgp.net') + } + + it { + is_expected.to contain_apt__key('EF8D349F').with(server: 'pgp.mit.edu') + } + end + + context 'with ppas defined on valid osfamily' do + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '12', full: '12.04.5' } }, + osfamily: 'Debian', + lsbdistcodename: 'precise', + lsbdistid: 'ubuntu', + lsbdistrelease: '12.04', + puppetversion: Puppet.version, + } + end + let(:params) do + { ppas: { + 'ppa:drizzle-developers/ppa' => {}, + 'ppa:nginx/stable' => {}, + } } + end + + it { is_expected.to contain_apt__ppa('ppa:drizzle-developers/ppa') } + it { is_expected.to contain_apt__ppa('ppa:nginx/stable') } + end + + context 'with settings defined on valid osfamily' do + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '12', full: '12.04.5' } }, + osfamily: 'Debian', + lsbdistcodename: 'precise', + lsbdistid: 'Debian', + puppetversion: Puppet.version, + } + end + let(:params) do + { settings: { + 'conf-banana' => { 'content' => 'banana' }, + 'pref-banana' => { 'content' => 'banana' }, + } } + end + + it { is_expected.to contain_apt__setting('conf-banana') } + it { is_expected.to contain_apt__setting('pref-banana') } + end + + context 'with pins defined on valid osfamily' do + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '12', full: '12.04.5' } }, + osfamily: 'Debian', + lsbdistcodename: 'precise', + lsbdistid: 'Debian', + puppetversion: Puppet.version, + } + end + let(:params) do + { pins: { + 'stable' => { 'priority' => 600, 'order' => 50 }, + 'testing' => { 'priority' => 700, 'order' => 100 }, + } } + end + + it { is_expected.to contain_apt__pin('stable') } + it { is_expected.to contain_apt__pin('testing') } + end + + describe 'failing tests' do + context "with purge['sources.list']=>'banana'" do + let(:params) { { purge: { 'sources.list' => 'banana' } } } + + it do + is_expected.to raise_error(Puppet::Error) + end + end + + context "with purge['sources.list.d']=>'banana'" do + let(:params) { { purge: { 'sources.list.d' => 'banana' } } } + + it do + is_expected.to raise_error(Puppet::Error) + end + end + + context "with purge['preferences']=>'banana'" do + let(:params) { { purge: { 'preferences' => 'banana' } } } + + it do + is_expected.to raise_error(Puppet::Error) + end + end + + context "with purge['preferences.d']=>'banana'" do + let(:params) { { purge: { 'preferences.d' => 'banana' } } } + + it do + is_expected.to raise_error(Puppet::Error) + end + end + end +end diff --git a/code/environments/production/modules/apt/spec/classes/apt_update_spec.rb b/code/environments/production/modules/apt/spec/classes/apt_update_spec.rb new file mode 100644 index 0000000..675bbd2 --- /dev/null +++ b/code/environments/production/modules/apt/spec/classes/apt_update_spec.rb @@ -0,0 +1,152 @@ +require 'spec_helper' + +describe 'apt::update', type: :class do + context "when apt::update['frequency']='always'" do + { + 'a recent run' => Time.now.to_i, + 'we are due for a run' => 1_406_660_561, + 'the update-success-stamp file does not exist' => -1, + }.each_pair do |desc, factval| + context "when $::apt_update_last_success indicates #{desc}" do + let(:facts) do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + apt_update_last_success: factval, + lsbdistcodename: 'wheezy', + puppetversion: Puppet.version, + } + end + let(:pre_condition) do + "class{'::apt': update => {'frequency' => 'always' },}" + end + + it 'triggers an apt-get update run' do + # set the apt_update exec's refreshonly attribute to false + is_expected.to contain_exec('apt_update').with('refreshonly' => false) + end + end + end + context 'when $::apt_update_last_success is nil' do + let(:facts) do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + lsbdistcodename: 'wheezy', + puppetversion: Puppet.version, + } + end + let(:pre_condition) { "class{ '::apt': update => {'frequency' => 'always' },}" } + + it 'triggers an apt-get update run' do + # set the apt_update exec\'s refreshonly attribute to false + is_expected.to contain_exec('apt_update').with('refreshonly' => false) + end + end + end + context "when apt::update['frequency']='reluctantly'" do + { + 'a recent run' => Time.now.to_i, + 'we are due for a run' => 1_406_660_561, + 'the update-success-stamp file does not exist' => -1, + }.each_pair do |desc, factval| + context "when $::apt_update_last_success indicates #{desc}" do + let(:facts) do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + apt_update_last_success: factval, + lsbdistcodename: 'wheezy', + puppetversion: Puppet.version, + } + end + let(:pre_condition) { "class{ '::apt': update => {'frequency' => 'reluctantly' },}" } + + it 'does not trigger an apt-get update run' do + # don't change the apt_update exec's refreshonly attribute. (it should be true) + is_expected.to contain_exec('apt_update').with('refreshonly' => true) + end + end + end + context 'when $::apt_update_last_success is nil' do + let(:facts) do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + lsbdistcodename: 'wheezy', + puppetversion: Puppet.version, + } + end + let(:pre_condition) { "class{ '::apt': update => {'frequency' => 'reluctantly' },}" } + + it 'does not trigger an apt-get update run' do + # don't change the apt_update exec's refreshonly attribute. (it should be true) + is_expected.to contain_exec('apt_update').with('refreshonly' => true) + end + end + end + %w[daily weekly].each do |update_frequency| + context "when apt::update['frequency'] has the value of #{update_frequency}" do + { 'we are due for a run' => 1_406_660_561, 'the update-success-stamp file does not exist' => -1 }.each_pair do |desc, factval| + context "when $::apt_update_last_success indicates #{desc}" do + let(:facts) do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + apt_update_last_success: factval, + lsbdistcodename: 'wheezy', + puppetversion: Puppet.version, + } + end + let(:pre_condition) { "class{ '::apt': update => {'frequency' => '#{update_frequency}',} }" } + + it 'triggers an apt-get update run' do + # set the apt_update exec\'s refreshonly attribute to false + is_expected.to contain_exec('apt_update').with('refreshonly' => false) + end + end + end + context 'when the $::apt_update_last_success fact has a recent value' do + let(:facts) do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + lsbdistcodename: 'wheezy', + apt_update_last_success: Time.now.to_i, + puppetversion: Puppet.version, + } + end + let(:pre_condition) { "class{ '::apt': update => {'frequency' => '#{update_frequency}',} }" } + + it 'does not trigger an apt-get update run' do + # don't change the apt_update exec\'s refreshonly attribute. (it should be true) + is_expected.to contain_exec('apt_update').with('refreshonly' => true) + end + end + context 'when $::apt_update_last_success is nil' do + let(:facts) do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + lsbdistcodename: 'wheezy', + apt_update_last_success: nil, + puppetversion: Puppet.version, + } + end + let(:pre_condition) { "class{ '::apt': update => {'frequency' => '#{update_frequency}',} }" } + + it 'triggers an apt-get update run' do + # set the apt_update exec\'s refreshonly attribute to false + is_expected.to contain_exec('apt_update').with('refreshonly' => false) + end + end + end + end +end diff --git a/code/environments/production/modules/apt/spec/defines/conf_spec.rb b/code/environments/production/modules/apt/spec/defines/conf_spec.rb new file mode 100644 index 0000000..d79cb22 --- /dev/null +++ b/code/environments/production/modules/apt/spec/defines/conf_spec.rb @@ -0,0 +1,90 @@ +require 'spec_helper' +describe 'apt::conf', type: :define do + let :pre_condition do + 'class { "apt": }' + end + let(:facts) do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + lsbdistcodename: 'wheezy', + puppetversion: Puppet.version, + } + end + let :title do + 'norecommends' + end + + describe 'when creating an apt preference' do + let :default_params do + { + priority: '00', + content: "Apt::Install-Recommends 0;\nApt::AutoRemove::InstallRecommends 1;\n", + } + end + let :params do + default_params + end + + let :filename do + '/etc/apt/apt.conf.d/00norecommends' + end + + it { + is_expected.to contain_file(filename).with('ensure' => 'present', + 'content' => %r{Apt::Install-Recommends 0;\nApt::AutoRemove::InstallRecommends 1;}, + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644') + } + + context 'with notify_update = true (default)' do + let :params do + default_params + end + + it { is_expected.to contain_apt__setting("conf-#{title}").with_notify_update(true) } + end + + context 'with notify_update = false' do + let :params do + default_params.merge(notify_update: false) + end + + it { is_expected.to contain_apt__setting("conf-#{title}").with_notify_update(false) } + end + end + + describe 'when creating a preference without content' do + let :params do + { + priority: '00', + } + end + + it 'fails' do + is_expected.to raise_error(%r{pass in content}) + end + end + + describe 'when removing an apt preference' do + let :params do + { + ensure: 'absent', + priority: '00', + } + end + + let :filename do + '/etc/apt/apt.conf.d/00norecommends' + end + + it { + is_expected.to contain_file(filename).with('ensure' => 'absent', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644') + } + end +end diff --git a/code/environments/production/modules/apt/spec/defines/key_compat_spec.rb b/code/environments/production/modules/apt/spec/defines/key_compat_spec.rb new file mode 100644 index 0000000..43ccbbc --- /dev/null +++ b/code/environments/production/modules/apt/spec/defines/key_compat_spec.rb @@ -0,0 +1,360 @@ +require 'spec_helper' + +def contains_apt_key_example(title) + { id: title, + ensure: 'present', + source: 'http://apt.puppetlabs.com/pubkey.gpg', + server: 'pgp.mit.edu', + content: params[:content], + options: 'debug' } +end + +def apt_key_example(title) + { id: title, + ensure: 'present', + source: nil, + server: 'keyserver.ubuntu.com', + content: nil, + keyserver_options: nil } +end + +describe 'apt::key', type: :define do + GPG_KEY_ID = '6F6B15509CF8E59E6E469F327F438280EF8D349F'.freeze + + let(:facts) do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + + let :title do + GPG_KEY_ID + end + + let :pre_condition do + 'include apt' + end + + describe 'normal operation' do + describe 'default options' do + it { + is_expected.to contain_apt_key(title).with(id: title, + ensure: 'present', + source: nil, + server: 'keyserver.ubuntu.com', + content: nil) + } + it 'contains the apt_key present anchor' do + is_expected.to contain_anchor("apt_key #{title} present") + end + end + + describe 'title and key =>' do + let :title do + 'puppetlabs' + end + + let :params do + { + id: GPG_KEY_ID, + } + end + + it 'contains the apt_key' do + is_expected.to contain_apt_key(title).with(id: GPG_KEY_ID, + ensure: 'present', + source: nil, + server: 'keyserver.ubuntu.com', + content: nil) + end + it 'contains the apt_key present anchor' do + is_expected.to contain_anchor("apt_key #{GPG_KEY_ID} present") + end + end + + describe 'ensure => absent' do + let :params do + { + ensure: 'absent', + } + end + + it 'contains the apt_key' do + is_expected.to contain_apt_key(title).with(id: title, + ensure: 'absent', + source: nil, + server: 'keyserver.ubuntu.com', + content: nil) + end + it 'contains the apt_key absent anchor' do + is_expected.to contain_anchor("apt_key #{title} absent") + end + end + + describe 'set a bunch of things!' do + let :params do + { + content: 'GPG key content', + source: 'http://apt.puppetlabs.com/pubkey.gpg', + server: 'pgp.mit.edu', + options: 'debug', + } + end + + it 'contains the apt_key' do + is_expected.to contain_apt_key(title).with(contains_apt_key_example(title)) + end + it 'contains the apt_key present anchor' do + is_expected.to contain_anchor("apt_key #{title} present") + end + end + + context 'when domain has dash' do + let(:params) do + { + server: 'p-gp.m-it.edu', + } + end + + it 'contains the apt_key' do + is_expected.to contain_apt_key(title).with(id: title, + server: 'p-gp.m-it.edu') + end + end + + context 'with url' do + let :params do + { + server: 'hkp://pgp.mit.edu', + } + end + + it 'contains the apt_key' do + is_expected.to contain_apt_key(title).with(id: title, + server: 'hkp://pgp.mit.edu') + end + end + context 'with url and port number' do + let :params do + { + server: 'hkp://pgp.mit.edu:80', + } + end + + it 'contains the apt_key' do + is_expected.to contain_apt_key(title).with(id: title, + server: 'hkp://pgp.mit.edu:80') + end + end + end + + describe 'validation' do + context 'when domain begins with a dash' do + let(:params) do + { + server: '-pgp.mit.edu', + } + end + + it 'fails' do + is_expected .to raise_error(%r{expects a match}) + end + end + + context 'when domain begins with dot' do + let(:params) do + { + server: '.pgp.mit.edu', + } + end + + it 'fails' do + is_expected .to raise_error(%r{expects a match}) + end + end + + context 'when domain ends with dot' do + let(:params) do + { + server: 'pgp.mit.edu.', + } + end + + it 'fails' do + is_expected .to raise_error(%r{expects a match}) + end + end + context 'when url character limit is exceeded' do + let :params do + { + server: 'hkp://pgpiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.mit.edu', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + context 'with incorrect port number url' do + let :params do + { + server: 'hkp://pgp.mit.edu:8008080', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + context 'with incorrect protocol for url' do + let :params do + { + server: 'abc://pgp.mit.edu:80', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + context 'with missing port number url' do + let :params do + { + server: 'hkp://pgp.mit.edu:', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + context 'with url ending with a dot' do + let :params do + { + server: 'hkp://pgp.mit.edu.', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + context 'with url begin with a dash' do + let(:params) do + { + server: 'hkp://-pgp.mit.edu', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + context 'with invalid key' do + let :title do + 'Out of rum. Why? Why are we out of rum?' + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + + context 'with invalid source' do + let :params do + { + source: 'afp://puppetlabs.com/key.gpg', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + + context 'with invalid content' do + let :params do + { + content: [], + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a}) + end + end + + context 'with invalid server' do + let :params do + { + server: 'two bottles of rum', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + + context 'with invalid keyserver_options' do + let :params do + { + options: {}, + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a}) + end + end + + context 'with invalid ensure' do + let :params do + { + ensure: 'foo', + } + end + + it 'fails' do + is_expected.to raise_error(%r{Enum\['absent', 'present'\]}) + end + end + + describe 'duplication - two apt::key resources for same key, different titles' do + let :pre_condition do + "#{super()}\napt::key { 'duplicate': id => '#{title}', }" + end + + it 'contains the duplicate apt::key resource' do + is_expected.to contain_apt__key('duplicate').with(id: title, + ensure: 'present') + end + + it 'contains the original apt::key resource' do + is_expected.to contain_apt__key(title).with(id: title, + ensure: 'present') + end + + it 'contains the native apt_key' do + is_expected.to contain_apt_key('duplicate').with(apt_key_example(title)) + end + + it 'does not contain the original apt_key' do + is_expected.not_to contain_apt_key(title) + end + end + + describe 'duplication - two apt::key resources, different ensure' do + let :pre_condition do + "#{super()}\napt::key { 'duplicate': id => '#{title}', ensure => 'absent', }" + end + + it 'informs the user of the impossibility' do + is_expected.to raise_error(%r{already ensured as absent}) + end + end + end +end diff --git a/code/environments/production/modules/apt/spec/defines/key_spec.rb b/code/environments/production/modules/apt/spec/defines/key_spec.rb new file mode 100644 index 0000000..6a5a89f --- /dev/null +++ b/code/environments/production/modules/apt/spec/defines/key_spec.rb @@ -0,0 +1,367 @@ +require 'spec_helper' + +GPG_KEY_ID = '6F6B15509CF8E59E6E469F327F438280EF8D349F'.freeze + +title_key_example = { id: GPG_KEY_ID, + ensure: 'present', + source: nil, + server: 'keyserver.ubuntu.com', + content: nil, + options: nil } + +def default_apt_key_example(title) + { id: title, + ensure: 'present', + source: nil, + server: 'keyserver.ubuntu.com', + content: nil, + options: nil } +end + +def bunch_things_apt_key_example(title, params) + { id: title, + ensure: 'present', + source: 'http://apt.puppetlabs.com/pubkey.gpg', + server: 'pgp.mit.edu', + content: params[:content], + options: 'debug' } +end + +def absent_apt_key(title) + { id: title, + ensure: 'absent', + source: nil, + server: 'keyserver.ubuntu.com', + content: nil, + keyserver: nil } +end + +describe 'apt::key' do + let :pre_condition do + 'class { "apt": }' + end + + let(:facts) do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + lsbdistcodename: 'wheezy', + puppetversion: Puppet.version, + } + end + + let :title do + GPG_KEY_ID + end + + describe 'normal operation' do + describe 'default options' do + it 'contains the apt_key' do + is_expected.to contain_apt_key(title).with(default_apt_key_example(title)) + end + it 'contains the apt_key present anchor' do + is_expected.to contain_anchor("apt_key #{title} present") + end + end + + describe 'title and key =>' do + let :title do + 'puppetlabs' + end + + let :params do + { + id: GPG_KEY_ID, + } + end + + it 'contains the apt_key' do + is_expected.to contain_apt_key(title).with(title_key_example) + end + it 'contains the apt_key present anchor' do + is_expected.to contain_anchor("apt_key #{GPG_KEY_ID} present") + end + end + + describe 'ensure => absent' do + let :params do + { + ensure: 'absent', + } + end + + it 'contains the apt_key' do + is_expected.to contain_apt_key(title).with(absent_apt_key(title)) + end + it 'contains the apt_key absent anchor' do + is_expected.to contain_anchor("apt_key #{title} absent") + end + end + + describe 'set a bunch of things!' do + let :params do + { + content: 'GPG key content', + source: 'http://apt.puppetlabs.com/pubkey.gpg', + server: 'pgp.mit.edu', + options: 'debug', + } + end + + it 'contains the apt_key' do + is_expected.to contain_apt_key(title).with(bunch_things_apt_key_example(title, params)) + end + it 'contains the apt_key present anchor' do + is_expected.to contain_anchor("apt_key #{title} present") + end + end + + context 'when domain with dash' do + let(:params) do + { + server: 'p-gp.m-it.edu', + } + end + + it 'contains the apt_key' do + is_expected.to contain_apt_key(title).with(id: title, + server: 'p-gp.m-it.edu') + end + end + + context 'with url' do + let :params do + { + server: 'hkp://pgp.mit.edu', + } + end + + it 'contains the apt_key' do + is_expected.to contain_apt_key(title).with(id: title, + server: 'hkp://pgp.mit.edu') + end + end + context 'when url with port number' do + let :params do + { + server: 'hkp://pgp.mit.edu:80', + } + end + + it 'contains the apt_key' do + is_expected.to contain_apt_key(title).with(id: title, + server: 'hkp://pgp.mit.edu:80') + end + end + end + + describe 'validation' do + context 'when domain begin with dash' do + let(:params) do + { + server: '-pgp.mit.edu', + } + end + + it 'fails' do + is_expected .to raise_error(%r{expects a match}) + end + end + + context 'when domain begin with dot' do + let(:params) do + { + server: '.pgp.mit.edu', + } + end + + it 'fails' do + is_expected .to raise_error(%r{expects a match}) + end + end + + context 'when domain end with dot' do + let(:params) do + { + server: 'pgp.mit.edu.', + } + end + + it 'fails' do + is_expected .to raise_error(%r{expects a match}) + end + end + context 'when character url exceeded' do + let :params do + { + server: 'hkp://pgpiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.mit.edu', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + context 'with incorrect port number url' do + let :params do + { + server: 'hkp://pgp.mit.edu:8008080', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + context 'with incorrect protocol for url' do + let :params do + { + server: 'abc://pgp.mit.edu:80', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + context 'with missing port number url' do + let :params do + { + server: 'hkp://pgp.mit.edu:', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + context 'with url ending with a dot' do + let :params do + { + server: 'hkp://pgp.mit.edu.', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + context 'when url begins with a dash' do + let(:params) do + { + server: 'hkp://-pgp.mit.edu', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + context 'with invalid key' do + let :title do + 'Out of rum. Why? Why are we out of rum?' + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + + context 'with invalid source' do + let :params do + { + source: 'afp://puppetlabs.com/key.gpg', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + + context 'with invalid content' do + let :params do + { + content: [], + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a}) + end + end + + context 'with invalid server' do + let :params do + { + server: 'two bottles of rum', + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a match}) + end + end + + context 'with invalid options' do + let :params do + { + options: {}, + } + end + + it 'fails' do + is_expected.to raise_error(%r{expects a}) + end + end + + context 'with invalid ensure' do + %w[foo aabsent absenta apresent presenta].each do |param| + let :params do + { + ensure: param, + } + end + + it 'fails' do + is_expected.to raise_error(%r{for Enum\['absent', 'present'\], got}) + end + end + end + + describe 'duplication - two apt::key resources for same key, different titles' do + let :pre_condition do + "class { 'apt': } + apt::key { 'duplicate': id => '#{title}', }" + end + + it 'contains two apt::key resource - duplicate' do + is_expected.to contain_apt__key('duplicate').with(id: title, + ensure: 'present') + end + it 'contains two apt::key resource - title' do + is_expected.to contain_apt__key(title).with(id: title, + ensure: 'present') + end + + it 'contains only a single apt_key - duplicate' do + is_expected.to contain_apt_key('duplicate').with(default_apt_key_example(title)) + end + it 'contains only a single apt_key - no title' do + is_expected.not_to contain_apt_key(title) + end + end + + describe 'duplication - two apt::key resources, different ensure' do + let :pre_condition do + "class { 'apt': } + apt::key { 'duplicate': id => '#{title}', ensure => 'absent', }" + end + + it 'informs the user of the impossibility' do + is_expected.to raise_error(%r{already ensured as absent}) + end + end + end +end diff --git a/code/environments/production/modules/apt/spec/defines/pin_spec.rb b/code/environments/production/modules/apt/spec/defines/pin_spec.rb new file mode 100644 index 0000000..2329e9a --- /dev/null +++ b/code/environments/production/modules/apt/spec/defines/pin_spec.rb @@ -0,0 +1,148 @@ +require 'spec_helper' +describe 'apt::pin', type: :define do + let :pre_condition do + 'class { "apt": }' + end + let(:facts) do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + lsbdistcodename: 'wheezy', + puppetversion: Puppet.version, + } + end + let(:title) { 'my_pin' } + + context 'with defaults' do + it { is_expected.to contain_apt__setting('pref-my_pin').with_content(%r{Explanation: : my_pin\nPackage: \*\nPin: release a=my_pin\nPin-Priority: 0\n}) } + end + + context 'with set version' do + let :params do + { + 'packages' => 'vim', + 'version' => '1', + } + end + + it { is_expected.to contain_apt__setting('pref-my_pin').with_content(%r{Explanation: : my_pin\nPackage: vim\nPin: version 1\nPin-Priority: 0\n}) } + end + + context 'with set origin' do + let :params do + { + 'packages' => 'vim', + 'origin' => 'test', + } + end + + it { is_expected.to contain_apt__setting('pref-my_pin').with_content(%r{Explanation: : my_pin\nPackage: vim\nPin: origin test\nPin-Priority: 0\n}) } + end + + context 'without defaults' do + let :params do + { + 'explanation' => 'foo', + 'order' => 99, + 'release' => '1', + 'codename' => 'bar', + 'release_version' => '2', + 'component' => 'baz', + 'originator' => 'foobar', + 'label' => 'foobaz', + 'priority' => 10, + } + end + + it { is_expected.to contain_apt__setting('pref-my_pin').with_content(%r{Explanation: foo\nPackage: \*\nPin: release a=1, n=bar, v=2, c=baz, o=foobar, l=foobaz\nPin-Priority: 10\n}) } + it { + is_expected.to contain_apt__setting('pref-my_pin').with('priority' => 99) + } + end + + context 'with ensure absent' do + let :params do + { + 'ensure' => 'absent', + } + end + + it { + is_expected.to contain_apt__setting('pref-my_pin').with('ensure' => 'absent') + } + end + + context 'with bad characters' do + let(:title) { 'such bad && wow!' } + + it { is_expected.to contain_apt__setting('pref-such__bad____wow_') } + end + + describe 'validation' do + context 'with invalid order' do + let :params do + { + 'order' => 'foo', + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{expects an Integer value, got String}) + end + end + + context 'with packages == * and version' do + let :params do + { + 'version' => '1', + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{parameter version cannot be used in general form}) + end + end + + context 'with packages == * and release and origin' do + let :params do + { + 'origin' => 'test', + 'release' => 'foo', + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{parameters release and origin are mutually exclusive}) + end + end + + context 'with specific release and origin' do + let :params do + { + 'release' => 'foo', + 'origin' => 'test', + 'packages' => 'vim', + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{parameters release, origin, and version are mutually exclusive}) + end + end + + context 'with specific version and origin' do + let :params do + { + 'version' => '1', + 'origin' => 'test', + 'packages' => 'vim', + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{parameters release, origin, and version are mutually exclusive}) + end + end + end +end diff --git a/code/environments/production/modules/apt/spec/defines/ppa_spec.rb b/code/environments/production/modules/apt/spec/defines/ppa_spec.rb new file mode 100644 index 0000000..b534186 --- /dev/null +++ b/code/environments/production/modules/apt/spec/defines/ppa_spec.rb @@ -0,0 +1,379 @@ +require 'spec_helper' +describe 'apt::ppa' do + let :pre_condition do + 'class { "apt": }' + end + + describe 'defaults' do + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '11', full: '11.04' } }, + lsbdistrelease: '11.04', + lsbdistcodename: 'natty', + operatingsystem: 'Ubuntu', + osfamily: 'Debian', + lsbdistid: 'Ubuntu', + puppetversion: Puppet.version, + } + end + + let(:title) { 'ppa:needs/such.substitution/wow+type' } + + it { is_expected.not_to contain_package('python-software-properties') } + it { + is_expected.to contain_exec('add-apt-repository-ppa:needs/such.substitution/wow+type').that_notifies('Class[Apt::Update]').with(environment: [], + command: '/usr/bin/add-apt-repository -y ppa:needs/such.substitution/wow+type', # rubocop:disable Metrics/LineLength + unless: '/usr/bin/test -f /etc/apt/sources.list.d/needs-such_substitution-wow_type-natty.list', # rubocop:disable Metrics/LineLength + user: 'root', + logoutput: 'on_failure') + } + end + + describe 'Ubuntu 15.10 sources.list filename' do + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '15', full: '15.10' } }, + lsbdistrelease: '15.10', + lsbdistcodename: 'wily', + operatingsystem: 'Ubuntu', + osfamily: 'Debian', + lsbdistid: 'Ubuntu', + puppetversion: Puppet.version, + } + end + + let(:title) { 'ppa:user/foo' } + + it { + is_expected.to contain_exec('add-apt-repository-ppa:user/foo').that_notifies('Class[Apt::Update]').with(environment: [], + command: '/usr/bin/add-apt-repository -y ppa:user/foo', + unless: '/usr/bin/test -f /etc/apt/sources.list.d/user-ubuntu-foo-wily.list', + user: 'root', + logoutput: 'on_failure') + } + end + + describe 'package_name => software-properties-common' do + let :pre_condition do + 'class { "apt": }' + end + let :params do + { + package_name: 'software-properties-common', + package_manage: true, + } + end + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '11', full: '11.04' } }, + lsbdistrelease: '11.04', + lsbdistcodename: 'natty', + operatingsystem: 'Ubuntu', + osfamily: 'Debian', + lsbdistid: 'Ubuntu', + puppetversion: Puppet.version, + } + end + + let(:title) { 'ppa:needs/such.substitution/wow' } + + it { is_expected.to contain_package('software-properties-common') } + it { + is_expected.to contain_exec('add-apt-repository-ppa:needs/such.substitution/wow').that_notifies('Class[Apt::Update]').with('environment' => [], + 'command' => '/usr/bin/add-apt-repository -y ppa:needs/such.substitution/wow', # rubocop:disable Metrics/LineLength + 'unless' => '/usr/bin/test -f /etc/apt/sources.list.d/needs-such_substitution-wow-natty.list', # rubocop:disable Metrics/LineLength + 'user' => 'root', + 'logoutput' => 'on_failure') + } + + it { + is_expected.to contain_file('/etc/apt/sources.list.d/needs-such_substitution-wow-natty.list').that_requires('Exec[add-apt-repository-ppa:needs/such.substitution/wow]').with('ensure' => 'file') + } + end + + describe 'package_manage => true, multiple ppas, MODULES-2873' do + let :pre_condition do + 'class { "apt": } + apt::ppa {"ppa:user/foo": + package_manage => true + }' + end + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '11', full: '11.04' } }, + lsbdistrelease: '11.04', + lsbdistcodename: 'natty', + operatingsystem: 'Ubuntu', + osfamily: 'Debian', + lsbdistid: 'Ubuntu', + puppetversion: Puppet.version, + } + end + let :params do + { + package_manage: true, + } + end + + let(:title) { 'ppa:user/bar' } + + it { is_expected.to contain_package('python-software-properties') } + it { + is_expected.to contain_exec('add-apt-repository-ppa:user/bar').that_notifies('Class[Apt::Update]').with('environment' => [], + 'command' => '/usr/bin/add-apt-repository -y ppa:user/bar', + 'unless' => '/usr/bin/test -f /etc/apt/sources.list.d/user-bar-natty.list', + 'user' => 'root', + 'logoutput' => 'on_failure') + } + + it { + is_expected.to contain_file('/etc/apt/sources.list.d/user-bar-natty.list').that_requires('Exec[add-apt-repository-ppa:user/bar]').with('ensure' => 'file') + } + end + + describe 'package_manage => false' do + let :pre_condition do + 'class { "apt": }' + end + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '11', full: '11.04' } }, + lsbdistrelease: '11.04', + lsbdistcodename: 'natty', + operatingsystem: 'Ubuntu', + osfamily: 'Debian', + lsbdistid: 'Ubuntu', + puppetversion: Puppet.version, + } + end + let :params do + { + package_manage: false, + } + end + + let(:title) { 'ppa:needs/such.substitution/wow' } + + it { is_expected.not_to contain_package('python-software-properties') } + it { + is_expected.to contain_exec('add-apt-repository-ppa:needs/such.substitution/wow').that_notifies('Class[Apt::Update]').with('environment' => [], + 'command' => '/usr/bin/add-apt-repository -y ppa:needs/such.substitution/wow', # rubocop:disable Metrics/LineLength + 'unless' => '/usr/bin/test -f /etc/apt/sources.list.d/needs-such_substitution-wow-natty.list', # rubocop:disable Metrics/LineLength + 'user' => 'root', + 'logoutput' => 'on_failure') + } + + it { + is_expected.to contain_file('/etc/apt/sources.list.d/needs-such_substitution-wow-natty.list').that_requires('Exec[add-apt-repository-ppa:needs/such.substitution/wow]').with('ensure' => 'file') + } + end + + describe 'apt included, no proxy' do + let :pre_condition do + 'class { "apt": } + apt::ppa { "ppa:user/foo2": } + ' + end + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '14', full: '14.04' } }, + lsbdistrelease: '14.04', + lsbdistcodename: 'trusty', + operatingsystem: 'Ubuntu', + lsbdistid: 'Ubuntu', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + options: '', + package_manage: true, + require: 'Apt::Ppa[ppa:user/foo2]', + } + end + let(:title) { 'ppa:user/foo' } + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_package('software-properties-common') } + it { + is_expected.to contain_exec('add-apt-repository-ppa:user/foo').that_notifies('Class[Apt::Update]').with(environment: [], + command: '/usr/bin/add-apt-repository ppa:user/foo', + unless: '/usr/bin/test -f /etc/apt/sources.list.d/user-foo-trusty.list', + user: 'root', + logoutput: 'on_failure') + } + end + + describe 'apt included, proxy host' do + let :pre_condition do + 'class { "apt": + proxy => { "host" => "localhost" }, + }' + end + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '14', full: '14.04' } }, + lsbdistrelease: '14.04', + lsbdistcodename: 'trusty', + operatingsystem: 'Ubuntu', + lsbdistid: 'Ubuntu', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + 'options' => '', + 'package_manage' => true, + } + end + let(:title) { 'ppa:user/foo' } + + it { is_expected.to contain_package('software-properties-common') } + it { + is_expected.to contain_exec('add-apt-repository-ppa:user/foo').that_notifies('Class[Apt::Update]').with(environment: ['http_proxy=http://localhost:8080'], + command: '/usr/bin/add-apt-repository ppa:user/foo', + unless: '/usr/bin/test -f /etc/apt/sources.list.d/user-foo-trusty.list', + user: 'root', + logoutput: 'on_failure') + } + end + + describe 'apt included, proxy host and port' do + let :pre_condition do + 'class { "apt": + proxy => { "host" => "localhost", "port" => 8180 }, + }' + end + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '14', full: '14.04' } }, + lsbdistrelease: '14.04', + lsbdistcodename: 'trusty', + operatingsystem: 'Ubuntu', + lsbdistid: 'Ubuntu', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + options: '', + package_manage: true, + } + end + let(:title) { 'ppa:user/foo' } + + it { is_expected.to contain_package('software-properties-common') } + it { + is_expected.to contain_exec('add-apt-repository-ppa:user/foo').that_notifies('Class[Apt::Update]').with(environment: ['http_proxy=http://localhost:8180'], + command: '/usr/bin/add-apt-repository ppa:user/foo', + unless: '/usr/bin/test -f /etc/apt/sources.list.d/user-foo-trusty.list', + user: 'root', + logoutput: 'on_failure') + } + end + + describe 'apt included, proxy host and port and https' do + let :pre_condition do + 'class { "apt": + proxy => { "host" => "localhost", "port" => 8180, "https" => true }, + }' + end + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '14', full: '14.04' } }, + lsbdistrelease: '14.04', + lsbdistcodename: 'trusty', + operatingsystem: 'Ubuntu', + lsbdistid: 'Ubuntu', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + options: '', + package_manage: true, + } + end + let(:title) { 'ppa:user/foo' } + + it { is_expected.to contain_package('software-properties-common') } + it { + is_expected.to contain_exec('add-apt-repository-ppa:user/foo').that_notifies('Class[Apt::Update]').with(environment: ['http_proxy=http://localhost:8180', 'https_proxy=https://localhost:8180'], + command: '/usr/bin/add-apt-repository ppa:user/foo', + unless: '/usr/bin/test -f /etc/apt/sources.list.d/user-foo-trusty.list', + user: 'root', + logoutput: 'on_failure') + } + end + + describe 'ensure absent' do + let :pre_condition do + 'class { "apt": }' + end + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '14', full: '14.04' } }, + lsbdistrelease: '14.04', + lsbdistcodename: 'trusty', + operatingsystem: 'Ubuntu', + lsbdistid: 'Ubuntu', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let(:title) { 'ppa:user/foo' } + let :params do + { + ensure: 'absent', + } + end + + it { + is_expected.to contain_file('/etc/apt/sources.list.d/user-foo-trusty.list').that_notifies('Class[Apt::Update]').with(ensure: 'absent') + } + end + + context 'with validation' do + describe 'no release' do + let :facts do + { + os: { family: 'Debian', name: 'Ubuntu', release: { major: '14', full: '14.04' } }, + lsbdistrelease: '14.04', + operatingsystem: 'Ubuntu', + lsbdistid: 'Ubuntu', + osfamily: 'Debian', + lsbdistcodeanme: nil, + puppetversion: Puppet.version, + } + end + let(:title) { 'ppa:user/foo' } + + it do + is_expected.to raise_error(Puppet::Error, %r{lsbdistcodename fact not available: release parameter required}) + end + end + + describe 'not ubuntu' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '6', full: '6.0.7' } }, + lsbdistrelease: '6.0.7', + lsbdistcodename: 'wheezy', + operatingsystem: 'Debian', + lsbdistid: 'debian', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let(:title) { 'ppa:user/foo' } + + it do + is_expected.to raise_error(Puppet::Error, %r{not currently supported on Debian}) + end + end + end +end diff --git a/code/environments/production/modules/apt/spec/defines/setting_spec.rb b/code/environments/production/modules/apt/spec/defines/setting_spec.rb new file mode 100644 index 0000000..1a94de7 --- /dev/null +++ b/code/environments/production/modules/apt/spec/defines/setting_spec.rb @@ -0,0 +1,145 @@ +require 'spec_helper' + +describe 'apt::setting' do + let(:pre_condition) { 'class { "apt": }' } + let :facts do + { + os: { distro: { codename: 'wheezy' }, family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistrelease: '7.0', + lsbdistcodename: 'wheezy', + operatingsystem: 'Debian', + osfamily: 'Debian', + lsbdistid: 'Debian', + puppetversion: Puppet.version, + } + end + let(:title) { 'conf-teddybear' } + + let(:default_params) { { content: 'di' } } + + describe 'when using the defaults' do + context 'without source or content' do + it do + is_expected.to raise_error(Puppet::Error, %r{needs either of }) + end + end + + context 'with title=conf-teddybear ' do + let(:params) { default_params } + + it { is_expected.to contain_file('/etc/apt/apt.conf.d/50teddybear').that_notifies('Class[Apt::Update]') } + end + + context 'with title=pref-teddybear' do + let(:title) { 'pref-teddybear' } + let(:params) { default_params } + + it { is_expected.to contain_file('/etc/apt/preferences.d/teddybear.pref').that_notifies('Class[Apt::Update]') } + end + + context 'with title=list-teddybear' do + let(:title) { 'list-teddybear' } + let(:params) { default_params } + + it { is_expected.to contain_file('/etc/apt/sources.list.d/teddybear.list').that_notifies('Class[Apt::Update]') } + end + + context 'with source' do + let(:params) { { source: 'puppet:///la/die/dah' } } + + it { + is_expected.to contain_file('/etc/apt/apt.conf.d/50teddybear').that_notifies('Class[Apt::Update]').with(ensure: 'file', + owner: 'root', + group: 'root', + mode: '0644', + source: params[:source].to_s) + } + end + + context 'with content' do + let(:params) { default_params } + + it { + is_expected.to contain_file('/etc/apt/apt.conf.d/50teddybear').that_notifies('Class[Apt::Update]').with(ensure: 'file', + owner: 'root', + group: 'root', + mode: '0644', + content: params[:content].to_s) + } + end + end + + describe 'settings requiring settings, MODULES-769' do + let(:pre_condition) do + 'class { "apt": } + apt::setting { "list-teddybear": content => "foo" } + ' + end + let(:facts) do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + lsbdistcodename: 'wheezy', + puppetversion: Puppet.version, + } + end + let(:title) { 'conf-teddybear' } + let(:default_params) { { content: 'di' } } + + let(:params) { default_params.merge(require: 'Apt::Setting[list-teddybear]') } + + it { is_expected.to compile.with_all_deps } + end + + describe 'when trying to pull one over' do + context 'with source and content' do + let(:params) { default_params.merge(source: 'la') } + + it do + is_expected.to raise_error(Puppet::Error, %r{cannot have both }) + end + end + + context 'with title=ext-teddybear' do + let(:title) { 'ext-teddybear' } + let(:params) { default_params } + + it do + is_expected.to raise_error(Puppet::Error, %r{must start with either}) + end + end + + context 'with ensure=banana' do + let(:params) { default_params.merge(ensure: 'banana') } + + it do + is_expected.to raise_error(Puppet::Error, %r{Enum\['absent', 'file', 'present'\]}) + end + end + + context 'with priority=1.2' do + let(:params) { default_params.merge(priority: 1.2) } + + if Puppet::Util::Package.versioncmp(Puppet.version, '4.0') >= 0 || ENV['FUTURE_PARSER'] == 'yes' + it { is_expected.to compile.and_raise_error(%r{expects a value of type}) } + else + it { is_expected.to compile.and_raise_error(%r{priority must be an integer or a zero-padded integer}) } + end + end + end + + describe 'with priority=100' do + let(:params) { default_params.merge(priority: 100) } + + it { is_expected.to contain_file('/etc/apt/apt.conf.d/100teddybear').that_notifies('Class[Apt::Update]') } + end + + describe 'with ensure=absent' do + let(:params) { default_params.merge(ensure: 'absent') } + + it { + is_expected.to contain_file('/etc/apt/apt.conf.d/50teddybear').that_notifies('Class[Apt::Update]').with(ensure: 'absent') + } + end +end diff --git a/code/environments/production/modules/apt/spec/defines/source_compat_spec.rb b/code/environments/production/modules/apt/spec/defines/source_compat_spec.rb new file mode 100644 index 0000000..f89f4be --- /dev/null +++ b/code/environments/production/modules/apt/spec/defines/source_compat_spec.rb @@ -0,0 +1,154 @@ +require 'spec_helper' + +describe 'apt::source', type: :define do + GPG_KEY_ID = '6F6B15509CF8E59E6E469F327F438280EF8D349F'.freeze + + let :title do + 'my_source' + end + + context 'with mostly defaults' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + + let :params do + { + 'include' => { 'deb' => false, 'src' => true }, + 'location' => 'http://debian.mirror.iweb.ca/debian/', + } + end + + it { + is_expected.to contain_apt__setting('list-my_source').with_content(%r{# my_source\ndeb-src http://debian.mirror.iweb.ca/debian/ wheezy main\n}) + } + end + + context 'with no defaults' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + 'comment' => 'foo', + 'location' => 'http://debian.mirror.iweb.ca/debian/', + 'release' => 'sid', + 'repos' => 'testing', + 'include' => { 'src' => false }, + 'key' => GPG_KEY_ID, + 'pin' => '10', + 'architecture' => 'x86_64', + 'allow_unsigned' => true, + } + end + + it { + is_expected.to contain_apt__setting('list-my_source').with_content(%r{# foo\ndeb \[arch=x86_64 trusted=yes\] http://debian.mirror.iweb.ca/debian/ sid testing\n}) + .without_content(%r{deb-src}) + } + + it { + is_expected.to contain_apt__pin('my_source').that_comes_before('Apt::Setting[list-my_source]').with('ensure' => 'present', + 'priority' => '10', + 'origin' => 'debian.mirror.iweb.ca') + } + + it { + is_expected.to contain_apt__key("Add key: #{GPG_KEY_ID} from Apt::Source my_source").that_comes_before('Apt::Setting[list-my_source]').with('ensure' => 'present', + 'id' => GPG_KEY_ID) + } + end + + context 'when allow_unsigned true' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + 'include' => { 'src' => false }, + 'location' => 'http://debian.mirror.iweb.ca/debian/', + 'allow_unsigned' => true, + } + end + + it { is_expected.to contain_apt__setting('list-my_source').with_content(%r{# my_source\ndeb \[trusted=yes\] http://debian.mirror.iweb.ca/debian/ wheezy main\n}) } + end + + context 'with architecture equals x86_64' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + 'location' => 'http://debian.mirror.iweb.ca/debian/', + 'architecture' => 'x86_64', + } + end + + it { + is_expected.to contain_apt__setting('list-my_source').with_content(%r{# my_source\ndeb \[arch=x86_64\] http://debian.mirror.iweb.ca/debian/ wheezy main\n}) + } + end + + context 'with ensure => absent' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + 'ensure' => 'absent', + } + end + + it { + is_expected.to contain_apt__setting('list-my_source').with('ensure' => 'absent') + } + end + + describe 'validation' do + context 'with no release' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{lsbdistcodename fact not available: release parameter required}) + end + end + end +end diff --git a/code/environments/production/modules/apt/spec/defines/source_spec.rb b/code/environments/production/modules/apt/spec/defines/source_spec.rb new file mode 100644 index 0000000..a9077e9 --- /dev/null +++ b/code/environments/production/modules/apt/spec/defines/source_spec.rb @@ -0,0 +1,452 @@ +require 'spec_helper' + +describe 'apt::source' do + GPG_KEY_ID = '6F6B15509CF8E59E6E469F327F438280EF8D349F'.freeze + + let :pre_condition do + 'class { "apt": }' + end + + let :title do + 'my_source' + end + + context 'with defaults' do + context 'without location' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + osfamily: 'Debian', + lsbdistcodename: 'wheezy', + puppetversion: Puppet.version, + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{source entry without specifying a location}) + end + end + context 'with location' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let(:params) { { location: 'hello.there' } } + + it { + is_expected.to contain_apt__setting('list-my_source').with(ensure: 'present').without_content(%r{# my_source\ndeb-src hello.there wheezy main\n}) + } + end + end + + describe 'no defaults' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + operatingsystem: 'Debian', + lsbdistrelease: '7.0', + puppetversion: Puppet.version, + } + 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(%r{hello.there wheezy main\n}) + } + + it { is_expected.to contain_file('/etc/apt/sources.list.d/my_source.list').that_notifies('Class[Apt::Update]') } + + 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 + { + comment: 'foo', + location: 'http://debian.mirror.iweb.ca/debian/', + release: 'sid', + repos: 'testing', + key: GPG_KEY_ID, + pin: '10', + architecture: 'x86_64', + allow_unsigned: true, + } + end + + it { + is_expected.to contain_apt__setting('list-my_source').with(ensure: 'present').with_content(%r{# foo\ndeb \[arch=x86_64 trusted=yes\] http://debian.mirror.iweb.ca/debian/ sid testing\n}) + .without_content(%r{deb-src}) + } + + it { + is_expected.to contain_apt__pin('my_source').that_comes_before('Apt::Setting[list-my_source]').with(ensure: 'present', + priority: '10', + origin: 'debian.mirror.iweb.ca') + } + + it { + is_expected.to contain_apt__key("Add key: #{GPG_KEY_ID} from Apt::Source my_source").that_comes_before('Apt::Setting[list-my_source]').with(ensure: 'present', + id: GPG_KEY_ID) + } + end + + context 'with complex key' do + let :params do + { + comment: 'foo', + location: 'http://debian.mirror.iweb.ca/debian/', + release: 'sid', + repos: 'testing', + key: { 'id' => GPG_KEY_ID, 'server' => 'pgp.mit.edu', + 'content' => 'GPG key content', + 'source' => 'http://apt.puppetlabs.com/pubkey.gpg' }, + pin: '10', + architecture: 'x86_64', + allow_unsigned: true, + } + end + + it { + is_expected.to contain_apt__setting('list-my_source').with(ensure: 'present').with_content(%r{# foo\ndeb \[arch=x86_64 trusted=yes\] http://debian.mirror.iweb.ca/debian/ sid testing\n}) + .without_content(%r{deb-src}) + } + + it { + is_expected.to contain_apt__pin('my_source').that_comes_before('Apt::Setting[list-my_source]').with(ensure: 'present', + priority: '10', + origin: 'debian.mirror.iweb.ca') + } + + it { + is_expected.to contain_apt__key("Add key: #{GPG_KEY_ID} from Apt::Source my_source").that_comes_before('Apt::Setting[list-my_source]').with(ensure: 'present', + id: GPG_KEY_ID, + server: 'pgp.mit.edu', + content: 'GPG key content', + source: 'http://apt.puppetlabs.com/pubkey.gpg') + } + end + + context 'with simple key' do + let :params do + { + comment: 'foo', + location: 'http://debian.mirror.iweb.ca/debian/', + release: 'sid', + repos: 'testing', + key: GPG_KEY_ID, + pin: '10', + architecture: 'x86_64', + allow_unsigned: true, + } + end + + it { + is_expected.to contain_apt__setting('list-my_source').with(ensure: 'present').with_content(%r{# foo\ndeb \[arch=x86_64 trusted=yes\] http://debian.mirror.iweb.ca/debian/ sid testing\n}) + .without_content(%r{deb-src}) + } + + it { + is_expected.to contain_apt__pin('my_source').that_comes_before('Apt::Setting[list-my_source]').with(ensure: 'present', + priority: '10', + origin: 'debian.mirror.iweb.ca') + } + + it { + is_expected.to contain_apt__key("Add key: #{GPG_KEY_ID} from Apt::Source my_source").that_comes_before('Apt::Setting[list-my_source]').with(ensure: 'present', + id: GPG_KEY_ID) + } + end + end + + context 'with allow_unsigned true' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + location: 'hello.there', + allow_unsigned: true, + } + end + + it { + is_expected.to contain_apt__setting('list-my_source').with(ensure: 'present').with_content(%r{# my_source\ndeb \[trusted=yes\] hello.there wheezy main\n}) + } + end + + context 'with architecture equals x86_64' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + location: 'hello.there', + include: { 'deb' => false, 'src' => true }, + architecture: 'x86_64', + } + end + + it { + is_expected.to contain_apt__setting('list-my_source').with(ensure: 'present').with_content(%r{# my_source\ndeb-src \[arch=x86_64\] hello.there wheezy main\n}) + } + end + + context 'with architecture fact and unset architecture parameter' do + let :facts do + { + architecture: 'amd64', + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + location: 'hello.there', + include: { 'deb' => false, 'src' => true }, + } + end + + it { + is_expected.to contain_apt__setting('list-my_source').with(ensure: 'present').with_content(%r{# my_source\ndeb-src hello.there wheezy main\n}) + } + end + + context 'with include_src => true' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + location: 'hello.there', + include: { 'src' => true }, + } + end + + it { + is_expected.to contain_apt__setting('list-my_source').with(ensure: 'present').with_content(%r{# my_source\ndeb hello.there wheezy main\ndeb-src hello.there wheezy main\n}) + } + end + + context 'with include deb => false' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'debian', + lsbdistcodename: 'wheezy', + osfamily: 'debian', + puppetversion: Puppet.version, + } + end + let :params do + { + include: { 'deb' => false }, + location: 'hello.there', + } + end + + it { + is_expected.to contain_apt__setting('list-my_source').with(ensure: 'present').without_content(%r{deb-src hello.there wheezy main\n}) + } + it { is_expected.to contain_apt__setting('list-my_source').without_content(%r{deb hello.there wheezy main\n}) } + end + + context 'with include src => true and include deb => false' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'debian', + lsbdistcodename: 'wheezy', + osfamily: 'debian', + puppetversion: Puppet.version, + } + end + let :params do + { + include: { 'deb' => false, 'src' => true }, + location: 'hello.there', + } + end + + it { + is_expected.to contain_apt__setting('list-my_source').with(ensure: 'present').with_content(%r{deb-src hello.there wheezy main\n}) + } + it { is_expected.to contain_apt__setting('list-my_source').without_content(%r{deb hello.there wheezy main\n}) } + end + + context 'with ensure => absent' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + ensure: 'absent', + } + end + + it { + is_expected.to contain_apt__setting('list-my_source').with(ensure: 'absent') + } + end + + describe 'validation' do + context 'with no release' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let(:params) { { location: 'hello.there' } } + + it do + is_expected.to raise_error(Puppet::Error, %r{lsbdistcodename fact not available: release parameter required}) + end + end + + context 'with release is empty string' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let(:params) { { location: 'hello.there', release: '' } } + + it { is_expected.to contain_apt__setting('list-my_source').with_content(%r{hello\.there main}) } + end + + context 'with invalid pin' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + location: 'hello.there', + pin: true, + } + end + + it do + is_expected.to raise_error(Puppet::Error, %r{expects a value}) + end + end + + context 'with notify_update = undef (default)' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + location: 'hello.there', + } + end + + it { is_expected.to contain_apt__setting("list-#{title}").with_notify_update(true) } + end + + context 'with notify_update = true' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + location: 'hello.there', + notify_update: true, + } + end + + it { is_expected.to contain_apt__setting("list-#{title}").with_notify_update(true) } + end + + context 'with notify_update = false' do + let :facts do + { + os: { family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + lsbdistid: 'Debian', + lsbdistcodename: 'wheezy', + osfamily: 'Debian', + puppetversion: Puppet.version, + } + end + let :params do + { + location: 'hello.there', + notify_update: false, + } + end + + it { is_expected.to contain_apt__setting("list-#{title}").with_notify_update(false) } + end + end +end diff --git a/code/environments/production/modules/apt/spec/spec_helper.rb b/code/environments/production/modules/apt/spec/spec_helper.rb new file mode 100644 index 0000000..15266c2 --- /dev/null +++ b/code/environments/production/modules/apt/spec/spec_helper.rb @@ -0,0 +1,23 @@ +require 'puppetlabs_spec_helper/module_spec_helper' +require 'rspec-puppet-facts' +include RspecPuppetFacts + +default_facts = { + puppetversion: Puppet.version, + facterversion: Facter.version, +} + +default_facts_path = File.expand_path(File.join(File.dirname(__FILE__), 'default_facts.yml')) +default_module_facts_path = File.expand_path(File.join(File.dirname(__FILE__), 'default_module_facts.yml')) + +if File.exist?(default_facts_path) && File.readable?(default_facts_path) + default_facts.merge!(YAML.safe_load(File.read(default_facts_path))) +end + +if File.exist?(default_module_facts_path) && File.readable?(default_module_facts_path) + default_facts.merge!(YAML.safe_load(File.read(default_module_facts_path))) +end + +RSpec.configure do |c| + c.default_facts = default_facts +end diff --git a/code/environments/production/modules/apt/spec/spec_helper_acceptance.rb b/code/environments/production/modules/apt/spec/spec_helper_acceptance.rb new file mode 100644 index 0000000..2ec2dba --- /dev/null +++ b/code/environments/production/modules/apt/spec/spec_helper_acceptance.rb @@ -0,0 +1,90 @@ +require 'beaker-rspec' +require 'beaker/puppet_install_helper' +require 'beaker/module_install_helper' + +def install_bolt_on(hosts) + on(hosts, "/opt/puppetlabs/puppet/bin/gem install --source http://rubygems.delivery.puppetlabs.net bolt -v '> 0.0.1'", acceptable_exit_codes: [0, 1]).stdout +end + +def pe_install? + ENV['PUPPET_INSTALL_TYPE'] =~ %r{pe}i +end + +run_puppet_install_helper +install_bolt_on(hosts) unless pe_install? +install_module_on(hosts) +install_module_dependencies_on(hosts) + +UNSUPPORTED_PLATFORMS = %w[RedHat Suse windows AIX Solaris].freeze + +DEFAULT_PASSWORD = if default[:hypervisor] == 'vagrant' + 'vagrant' + elsif default[:hypervisor] == 'vcloud' + 'Qu@lity!' + end + +def puppet_version + (on default, puppet('--version')).output.chomp +end + +def run_puppet_access_login(user:, password: + '~!@#$%^*-/ aZ', lifetime: '5y') + on(master, puppet('access', 'login', '--username', user, '--lifetime', lifetime), stdin: password) +end + +def run_task(task_name:, params: nil, password: DEFAULT_PASSWORD) + if pe_install? + run_puppet_task(task_name: task_name, params: params) + else + run_bolt_task(task_name: task_name, params: params, password: password) + end +end + +def run_bolt_task(task_name:, params: nil, password: DEFAULT_PASSWORD) + on(master, "/opt/puppetlabs/puppet/bin/bolt task run #{task_name} --modules /etc/puppetlabs/code/modules/service --nodes localhost --password #{password} #{params}", acceptable_exit_codes: [0, 1]).stdout # rubocop:disable Metrics/LineLength +end + +def run_puppet_task(task_name:, params: nil) + on(master, puppet('task', 'run', task_name, '--nodes', fact_on(master, 'fqdn'), params.to_s), acceptable_exit_codes: [0, 1]).stdout +end + +def expect_multiple_regexes(result:, regexes:) + regexes.each do |regex| + expect(result).to match(regex) + end +end + +# This method allows a block to be passed in and if an exception is raised +# that matches the 'error_matcher' matcher, the block will wait a set number +# of seconds before retrying. +# Params: +# - max_retry_count - Max number of retries +# - retry_wait_interval_secs - Number of seconds to wait before retry +# - error_matcher - Matcher which the exception raised must match to allow retry +# Example Usage: +# retry_on_error_matching(3, 5, /OpenGPG Error/) do +# apply_manifest(pp, :catch_failures => true) +# end +def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, error_matcher = nil) + try = 0 + begin + try += 1 + yield + rescue StandardError => e + raise unless try < max_retry_count && (error_matcher.nil? || e.message =~ error_matcher) + sleep retry_wait_interval_secs + retry + end +end + +RSpec.configure do |c| + File.expand_path(File.join(File.dirname(__FILE__), '..')) + + # Readable test descriptions + c.formatter = :documentation + + # Configure all nodes in nodeset + c.before :suite do + run_puppet_access_login(user: 'admin') if pe_install? && puppet_version =~ %r{(5\.\d\.\d)} + end +end diff --git a/code/environments/production/modules/apt/spec/unit/facter/apt_dist_has_updates_spec.rb b/code/environments/production/modules/apt/spec/unit/facter/apt_dist_has_updates_spec.rb new file mode 100644 index 0000000..ae67bcf --- /dev/null +++ b/code/environments/production/modules/apt/spec/unit/facter/apt_dist_has_updates_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe 'apt_has_dist_updates fact' do + subject { Facter.fact(:apt_has_dist_updates).value } + + after(:each) { Facter.clear } + + describe 'on non-Debian distro' do + before(:each) do + Facter.fact(:osfamily).expects(:value).at_least(1).returns 'RedHat' + end + it { is_expected.to be_nil } + end + + describe 'on Debian based distro missing apt-get' do + before(:each) do + Facter.fact(:osfamily).expects(:value).at_least(1).returns 'Debian' + File.stubs(:executable?) # Stub all other calls + File.expects(:executable?).with('/usr/bin/apt-get').returns false + end + it { is_expected.to be_nil } + end + + describe 'on Debian based distro' do + before(:each) do + 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/bin/apt-get').returns true + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true upgrade 2>&1').returns 'test' + File.expects(:executable?).with('/usr/bin/apt-get').returns true + apt_output = "Inst extremetuxracer [2015f-0+deb8u1] (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Conf extremetuxracer (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Inst planet.rb [13-1.1] (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" \ + "Conf planet.rb (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true dist-upgrade 2>&1').returns apt_output + end + it { is_expected.to be true } + end +end diff --git a/code/environments/production/modules/apt/spec/unit/facter/apt_dist_package_security_updates_spec.rb b/code/environments/production/modules/apt/spec/unit/facter/apt_dist_package_security_updates_spec.rb new file mode 100644 index 0000000..7f4f16a --- /dev/null +++ b/code/environments/production/modules/apt/spec/unit/facter/apt_dist_package_security_updates_spec.rb @@ -0,0 +1,60 @@ +require 'spec_helper' + +describe 'apt_package_security_dist_updates fact' do + subject { Facter.fact(:apt_package_security_dist_updates).value } + + after(:each) { Facter.clear } + + describe 'when apt has no updates' do + before(:each) do + Facter.fact(:apt_has_dist_updates).stubs(:value).returns false + end + it { is_expected.to be nil } + end + + describe 'when apt has updates' do + before(:each) do + Facter.fact(:osfamily).stubs(:value).returns 'Debian' + File.stubs(:executable?) # Stub all other calls + Facter::Util::Resolution.stubs(:exec) # Catch all other calls + File.expects(:executable?).with('/usr/bin/apt-get').returns true + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true upgrade 2>&1').returns 'test' + File.expects(:executable?).with('/usr/bin/apt-get').returns true + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true dist-upgrade 2>&1').returns apt_get_upgrade_output + end + + describe 'on Debian' do + let(:apt_get_upgrade_output) do + "Inst extremetuxracer [2015f-0+deb8u1] (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Conf extremetuxracer (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Inst planet.rb [13-1.1] (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" \ + "Conf planet.rb (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" \ + "Inst vim [7.52.1-5] (7.52.1-5+deb9u2 Debian-Security:9/stable [amd64]) []\n" \ + "Conf vim (7.52.1-5+deb9u2 Debian-Security:9/stable [amd64])\n" \ + end + + if Facter.version < '2.0.0' + it { is_expected.to eq('vim') } + else + it { is_expected.to eq(['vim']) } + end + end + + describe 'on Ubuntu' do + let(:apt_get_upgrade_output) do + "Inst extremetuxracer [2016f-0ubuntu0.16.04] (2016j-0ubuntu0.16.04 Ubuntu:16.04/xenial-security, Ubuntu:16.04/xenial-updates [all])\n" \ + "Conf extremetuxracer (2016j-0ubuntu0.16.04 Ubuntu:16.04/xenial-security, Ubuntu:16.04/xenial-updates [all])\n" \ + "Inst vim [7.47.0-1ubuntu2] (7.47.0-1ubuntu2.2 Ubuntu:16.04/xenial-security [amd64]) []\n" \ + "Conf vim (7.47.0-1ubuntu2.2 Ubuntu:16.04/xenial-security [amd64])\n" \ + "Inst onioncircuits [2:3.3.10-4ubuntu2] (2:3.3.10-4ubuntu2.3 Ubuntu:16.04/xenial-updates [amd64])\n" \ + "Conf onioncircuits (2:3.3.10-4ubuntu2.3 Ubuntu:16.04/xenial-updates [amd64])\n" + end + + if Facter.version < '2.0.0' + it { is_expected.to eq('extremetuxracer,vim') } + else + it { is_expected.to eq(%w[extremetuxracer vim]) } + end + end + end +end diff --git a/code/environments/production/modules/apt/spec/unit/facter/apt_dist_package_updates_spec.rb b/code/environments/production/modules/apt/spec/unit/facter/apt_dist_package_updates_spec.rb new file mode 100644 index 0000000..080e21f --- /dev/null +++ b/code/environments/production/modules/apt/spec/unit/facter/apt_dist_package_updates_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe 'apt_package_dist_updates fact' do + subject { Facter.fact(:apt_package_dist_updates).value } + + after(:each) { Facter.clear } + + describe 'when apt has no updates' do + before(:each) do + Facter.fact(:apt_has_dist_updates).stubs(:value).returns false + end + it { is_expected.to be nil } + end + + describe 'when apt has updates' do + before(:each) do + Facter.fact(:osfamily).stubs(:value).returns 'Debian' + File.stubs(:executable?) # Stub all other calls + Facter::Util::Resolution.stubs(:exec) # Catch all other calls + File.expects(:executable?).with('/usr/bin/apt-get').returns true + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true upgrade 2>&1').returns 'test' + File.expects(:executable?).with('/usr/bin/apt-get').returns true + apt_output = "Inst extremetuxracer [2015f-0+deb8u1] (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Conf extremetuxracer (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Inst planet.rb [13-1.1] (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" \ + "Conf planet.rb (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true dist-upgrade 2>&1').returns apt_output + end + if Facter.version < '2.0.0' + it { is_expected.to eq('extremetuxracer,planet.rb') } + else + it { is_expected.to eq(['extremetuxracer', 'planet.rb']) } + end + end +end diff --git a/code/environments/production/modules/apt/spec/unit/facter/apt_dist_security_updates_spec.rb b/code/environments/production/modules/apt/spec/unit/facter/apt_dist_security_updates_spec.rb new file mode 100644 index 0000000..9b58b6e --- /dev/null +++ b/code/environments/production/modules/apt/spec/unit/facter/apt_dist_security_updates_spec.rb @@ -0,0 +1,52 @@ +require 'spec_helper' + +describe 'apt_security_updates fact' do + subject { Facter.fact(:apt_security_dist_updates).value } + + after(:each) { Facter.clear } + + describe 'when apt has no updates' do + before(:each) do + Facter.fact(:apt_has_dist_updates).stubs(:value).returns false + end + it { is_expected.to be nil } + end + + describe 'when apt has security updates' do + before(:each) do + Facter.fact(:osfamily).stubs(:value).returns 'Debian' + File.stubs(:executable?) # Stub all other calls + Facter::Util::Resolution.stubs(:exec) # Catch all other calls + File.expects(:executable?).with('/usr/bin/apt-get').returns true + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true upgrade 2>&1').returns 'test' + File.expects(:executable?).with('/usr/bin/apt-get').returns true + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true dist-upgrade 2>&1').returns apt_get_upgrade_output + end + + describe 'on Debian' do + let(:apt_get_upgrade_output) do + "Inst extremetuxracer [2015f-0+deb8u1] (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Conf extremetuxracer (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Inst planet.rb [13-1.1] (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" \ + "Conf planet.rb (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" \ + "Inst vim [7.52.1-5] (7.52.1-5+deb9u2 Debian-Security:9/stable [amd64]) []\n" \ + "Conf vim (7.52.1-5+deb9u2 Debian-Security:9/stable [amd64])\n" \ + end + + it { is_expected.to eq(1) } + end + + describe 'on Ubuntu' do + let(:apt_get_upgrade_output) do + "Inst extremetuxracer [2016f-0ubuntu0.16.04] (2016j-0ubuntu0.16.04 Ubuntu:16.04/xenial-security, Ubuntu:16.04/xenial-updates [all])\n" \ + "Conf extremetuxracer (2016j-0ubuntu0.16.04 Ubuntu:16.04/xenial-security, Ubuntu:16.04/xenial-updates [all])\n" \ + "Inst vim [7.47.0-1ubuntu2] (7.47.0-1ubuntu2.2 Ubuntu:16.04/xenial-security [amd64]) []\n" \ + "Conf vim (7.47.0-1ubuntu2.2 Ubuntu:16.04/xenial-security [amd64])\n" \ + "Inst onioncircuits [2:3.3.10-4ubuntu2] (2:3.3.10-4ubuntu2.3 Ubuntu:16.04/xenial-updates [amd64])\n" \ + "Conf onioncircuits (2:3.3.10-4ubuntu2.3 Ubuntu:16.04/xenial-updates [amd64])\n" + end + + it { is_expected.to eq(2) } + end + end +end diff --git a/code/environments/production/modules/apt/spec/unit/facter/apt_dist_updates_spec.rb b/code/environments/production/modules/apt/spec/unit/facter/apt_dist_updates_spec.rb new file mode 100644 index 0000000..737d1b6 --- /dev/null +++ b/code/environments/production/modules/apt/spec/unit/facter/apt_dist_updates_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe 'apt_updates fact' do + subject { Facter.fact(:apt_dist_updates).value } + + after(:each) { Facter.clear } + + describe 'when apt has no updates' do + before(:each) do + Facter.fact(:apt_has_dist_updates).stubs(:value).returns false + end + it { is_expected.to be nil } + end + + describe 'when apt has updates' do + before(:each) do + Facter.fact(:osfamily).stubs(:value).returns 'Debian' + File.stubs(:executable?) # Stub all other calls + Facter::Util::Resolution.stubs(:exec) # Catch all other calls + File.expects(:executable?).with('/usr/bin/apt-get').returns true + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true upgrade 2>&1').returns 'test' + File.expects(:executable?).with('/usr/bin/apt-get').returns true + apt_output = "Inst extremetuxracer [2015f-0+deb8u1] (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Conf extremetuxracer (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Inst planet.rb [13-1.1] (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" \ + "Conf planet.rb (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true dist-upgrade 2>&1').returns apt_output + end + it { is_expected.to eq(2) } + end +end diff --git a/code/environments/production/modules/apt/spec/unit/facter/apt_has_updates_spec.rb b/code/environments/production/modules/apt/spec/unit/facter/apt_has_updates_spec.rb new file mode 100644 index 0000000..5c06c2f --- /dev/null +++ b/code/environments/production/modules/apt/spec/unit/facter/apt_has_updates_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe 'apt_has_updates fact' do + subject { Facter.fact(:apt_has_updates).value } + + after(:each) { Facter.clear } + + describe 'on non-Debian distro' do + before(:each) do + Facter.fact(:osfamily).expects(:value).at_least(1).returns 'RedHat' + end + it { is_expected.to be_nil } + end + + describe 'on Debian based distro missing apt-get' do + before(:each) do + Facter.fact(:osfamily).expects(:value).at_least(1).returns 'Debian' + File.stubs(:executable?) # Stub all other calls + File.expects(:executable?).with('/usr/bin/apt-get').returns false + end + it { is_expected.to be_nil } + end + + describe 'on Debian based distro' do + before(:each) do + 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/bin/apt-get').returns true + apt_output = "Inst tzdata [2015f-0+deb8u1] (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Conf tzdata (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Inst unhide.rb [13-1.1] (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" \ + "Conf unhide.rb (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true upgrade 2>&1').returns apt_output + end + it { is_expected.to be true } + end +end diff --git a/code/environments/production/modules/apt/spec/unit/facter/apt_package_security_updates_spec.rb b/code/environments/production/modules/apt/spec/unit/facter/apt_package_security_updates_spec.rb new file mode 100644 index 0000000..1cd992d --- /dev/null +++ b/code/environments/production/modules/apt/spec/unit/facter/apt_package_security_updates_spec.rb @@ -0,0 +1,58 @@ +require 'spec_helper' + +describe 'apt_package_security_updates fact' do + subject { Facter.fact(:apt_package_security_updates).value } + + after(:each) { Facter.clear } + + describe 'when apt has no updates' do + before(:each) do + Facter.fact(:apt_has_updates).stubs(:value).returns false + end + it { is_expected.to be nil } + end + + describe 'when apt has updates' do + before(:each) do + Facter.fact(:osfamily).stubs(:value).returns 'Debian' + File.stubs(:executable?) # Stub all other calls + Facter::Util::Resolution.stubs(:exec) # Catch all other calls + File.expects(:executable?).with('/usr/bin/apt-get').returns true + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true upgrade 2>&1').returns apt_get_upgrade_output + end + + describe 'on Debian' do + let(:apt_get_upgrade_output) do + "Inst tzdata [2015f-0+deb8u1] (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Conf tzdata (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Inst unhide.rb [13-1.1] (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" \ + "Conf unhide.rb (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" \ + "Inst curl [7.52.1-5] (7.52.1-5+deb9u2 Debian-Security:9/stable [amd64]) []\n" \ + "Conf curl (7.52.1-5+deb9u2 Debian-Security:9/stable [amd64])\n" \ + end + + if Facter.version < '2.0.0' + it { is_expected.to eq('curl') } + else + it { is_expected.to eq(['curl']) } + end + end + + describe 'on Ubuntu' do + let(:apt_get_upgrade_output) do + "Inst tzdata [2016f-0ubuntu0.16.04] (2016j-0ubuntu0.16.04 Ubuntu:16.04/xenial-security, Ubuntu:16.04/xenial-updates [all])\n" \ + "Conf tzdata (2016j-0ubuntu0.16.04 Ubuntu:16.04/xenial-security, Ubuntu:16.04/xenial-updates [all])\n" \ + "Inst curl [7.47.0-1ubuntu2] (7.47.0-1ubuntu2.2 Ubuntu:16.04/xenial-security [amd64]) []\n" \ + "Conf curl (7.47.0-1ubuntu2.2 Ubuntu:16.04/xenial-security [amd64])\n" \ + "Inst procps [2:3.3.10-4ubuntu2] (2:3.3.10-4ubuntu2.3 Ubuntu:16.04/xenial-updates [amd64])\n" \ + "Conf procps (2:3.3.10-4ubuntu2.3 Ubuntu:16.04/xenial-updates [amd64])\n" + end + + if Facter.version < '2.0.0' + it { is_expected.to eq('tzdata,curl') } + else + it { is_expected.to eq(%w[tzdata curl]) } + end + end + end +end diff --git a/code/environments/production/modules/apt/spec/unit/facter/apt_package_updates_spec.rb b/code/environments/production/modules/apt/spec/unit/facter/apt_package_updates_spec.rb new file mode 100644 index 0000000..f24481a --- /dev/null +++ b/code/environments/production/modules/apt/spec/unit/facter/apt_package_updates_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe 'apt_package_updates fact' do + subject { Facter.fact(:apt_package_updates).value } + + after(:each) { Facter.clear } + + describe 'when apt has no updates' do + before(:each) do + Facter.fact(:apt_has_updates).stubs(:value).returns false + end + it { is_expected.to be nil } + end + + describe 'when apt has updates' do + before(:each) do + Facter.fact(:osfamily).stubs(:value).returns 'Debian' + File.stubs(:executable?) # Stub all other calls + Facter::Util::Resolution.stubs(:exec) # Catch all other calls + File.expects(:executable?).with('/usr/bin/apt-get').returns true + apt_output = "Inst tzdata [2015f-0+deb8u1] (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Conf tzdata (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Inst unhide.rb [13-1.1] (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" \ + "Conf unhide.rb (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true upgrade 2>&1').returns apt_output + end + if Facter.version < '2.0.0' + it { is_expected.to eq('tzdata,unhide.rb') } + else + it { is_expected.to eq(['tzdata', 'unhide.rb']) } + end + end +end diff --git a/code/environments/production/modules/apt/spec/unit/facter/apt_reboot_required_spec.rb b/code/environments/production/modules/apt/spec/unit/facter/apt_reboot_required_spec.rb new file mode 100644 index 0000000..356f36b --- /dev/null +++ b/code/environments/production/modules/apt/spec/unit/facter/apt_reboot_required_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe 'apt_reboot_required fact' do + subject { Facter.fact(:apt_reboot_required).value } + + after(:each) { Facter.clear } + + describe 'if a reboot is required' do + before(:each) do + Facter.fact(:osfamily).expects(:value).at_least(1).returns 'Debian' + File.stubs(:file?).returns true + File.expects(:file?).at_least(1).with('/var/run/reboot-required').returns true + end + it { is_expected.to eq true } + end + + describe 'if a reboot is not required' do + before(:each) do + Facter.fact(:osfamily).expects(:value).at_least(1).returns 'Debian' + File.stubs(:file?).returns true + File.expects(:file?).at_least(1).with('/var/run/reboot-required').returns false + end + it { is_expected.to eq false } + end +end diff --git a/code/environments/production/modules/apt/spec/unit/facter/apt_security_updates_spec.rb b/code/environments/production/modules/apt/spec/unit/facter/apt_security_updates_spec.rb new file mode 100644 index 0000000..fc93552 --- /dev/null +++ b/code/environments/production/modules/apt/spec/unit/facter/apt_security_updates_spec.rb @@ -0,0 +1,50 @@ +require 'spec_helper' + +describe 'apt_security_updates fact' do + subject { Facter.fact(:apt_security_updates).value } + + after(:each) { Facter.clear } + + describe 'when apt has no updates' do + before(:each) do + Facter.fact(:apt_has_updates).stubs(:value).returns false + end + it { is_expected.to be nil } + end + + describe 'when apt has security updates' do + before(:each) do + Facter.fact(:osfamily).stubs(:value).returns 'Debian' + File.stubs(:executable?) # Stub all other calls + Facter::Util::Resolution.stubs(:exec) # Catch all other calls + File.expects(:executable?).with('/usr/bin/apt-get').returns true + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true upgrade 2>&1').returns apt_get_upgrade_output + end + + describe 'on Debian' do + let(:apt_get_upgrade_output) do + "Inst tzdata [2015f-0+deb8u1] (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Conf tzdata (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Inst unhide.rb [13-1.1] (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" \ + "Conf unhide.rb (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" \ + "Inst curl [7.52.1-5] (7.52.1-5+deb9u2 Debian-Security:9/stable [amd64]) []\n" \ + "Conf curl (7.52.1-5+deb9u2 Debian-Security:9/stable [amd64])\n" \ + end + + it { is_expected.to eq(1) } + end + + describe 'on Ubuntu' do + let(:apt_get_upgrade_output) do + "Inst tzdata [2016f-0ubuntu0.16.04] (2016j-0ubuntu0.16.04 Ubuntu:16.04/xenial-security, Ubuntu:16.04/xenial-updates [all])\n" \ + "Conf tzdata (2016j-0ubuntu0.16.04 Ubuntu:16.04/xenial-security, Ubuntu:16.04/xenial-updates [all])\n" \ + "Inst curl [7.47.0-1ubuntu2] (7.47.0-1ubuntu2.2 Ubuntu:16.04/xenial-security [amd64]) []\n" \ + "Conf curl (7.47.0-1ubuntu2.2 Ubuntu:16.04/xenial-security [amd64])\n" \ + "Inst procps [2:3.3.10-4ubuntu2] (2:3.3.10-4ubuntu2.3 Ubuntu:16.04/xenial-updates [amd64])\n" \ + "Conf procps (2:3.3.10-4ubuntu2.3 Ubuntu:16.04/xenial-updates [amd64])\n" + end + + it { is_expected.to eq(2) } + end + end +end diff --git a/code/environments/production/modules/apt/spec/unit/facter/apt_update_last_success_spec.rb b/code/environments/production/modules/apt/spec/unit/facter/apt_update_last_success_spec.rb new file mode 100644 index 0000000..60d7273 --- /dev/null +++ b/code/environments/production/modules/apt/spec/unit/facter/apt_update_last_success_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe 'apt_update_last_success fact' do + subject { Facter.fact(:apt_update_last_success).value } + + before(:each) { Facter.clear } + after(:each) { Facter.clear } + + describe 'on Debian based distro which has not yet created the update-success-stamp file' do + it 'has a value of -1' do + Facter.fact(:osfamily).stubs(:value).returns 'Debian' + File.expects(:exist?).with('/var/lib/apt/periodic/update-success-stamp').returns false + is_expected.to eq(-1) + end + end + + describe 'on Debian based distro which has created the update-success-stamp' do + it 'has the value of the mtime of the file' do + Facter.fact(:osfamily).stubs(:value).returns 'Debian' + File.stubs(:exist?).returns true + File.stubs(:mtime).returns 1_407_660_561 + is_expected.to eq(1_407_660_561) + end + end +end diff --git a/code/environments/production/modules/apt/spec/unit/facter/apt_updates_spec.rb b/code/environments/production/modules/apt/spec/unit/facter/apt_updates_spec.rb new file mode 100644 index 0000000..d0a5dbb --- /dev/null +++ b/code/environments/production/modules/apt/spec/unit/facter/apt_updates_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe 'apt_updates fact' do + subject { Facter.fact(:apt_updates).value } + + after(:each) { Facter.clear } + + describe 'when apt has no updates' do + before(:each) do + Facter.fact(:apt_has_updates).stubs(:value).returns false + end + it { is_expected.to be nil } + end + + describe 'when apt has updates' do + before(:each) do + Facter.fact(:osfamily).stubs(:value).returns 'Debian' + File.stubs(:executable?) # Stub all other calls + Facter::Util::Resolution.stubs(:exec) # Catch all other calls + File.expects(:executable?).with('/usr/bin/apt-get').returns true + apt_output = "Inst tzdata [2015f-0+deb8u1] (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Conf tzdata (2015g-0+deb8u1 Debian:stable-updates [all])\n" \ + "Inst unhide.rb [13-1.1] (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" \ + "Conf unhide.rb (22-2~bpo8+1 Debian Backports:jessie-backports [all])\n" + puts apt_output + Facter::Util::Resolution.expects(:exec).with('/usr/bin/apt-get -s -o Debug::NoLocking=true upgrade 2>&1').returns apt_output + end + it { is_expected.to eq(2) } + end +end diff --git a/code/environments/production/modules/apt/spec/unit/puppet/type/apt_key_spec.rb b/code/environments/production/modules/apt/spec/unit/puppet/type/apt_key_spec.rb new file mode 100644 index 0000000..a25d827 --- /dev/null +++ b/code/environments/production/modules/apt/spec/unit/puppet/type/apt_key_spec.rb @@ -0,0 +1,212 @@ +require 'spec_helper' +require 'puppet' + +describe Puppet::Type.type(:apt_key) do + context 'with only namevar 32bit key id' do + let(:resource) do + Puppet::Type.type(:apt_key).new( + id: 'EF8D349F', + ) + end + + it 'id is set' do + expect(resource[:id]).to eq 'EF8D349F' + end + + it 'name is set to id' do + expect(resource[:name]).to eq 'EF8D349F' + end + + it 'keyserver is default' do + expect(resource[:server]).to eq :'keyserver.ubuntu.com' + end + + it 'source is not set' do + expect(resource[:source]).to eq nil + end + + it 'content is not set' do + expect(resource[:content]).to eq nil + end + end + + context 'with a lowercase 32bit key id' do + let(:resource) do + Puppet::Type.type(:apt_key).new( + id: 'ef8d349f', + ) + end + + it 'id is set' do + expect(resource[:id]).to eq 'EF8D349F' + end + end + + context 'with a 64bit key id' do + let(:resource) do + Puppet::Type.type(:apt_key).new( + id: 'FFFFFFFFEF8D349F', + ) + end + + it 'id is set' do + expect(resource[:id]).to eq 'FFFFFFFFEF8D349F' + end + end + + context 'with a 0x formatted key id' do + let(:resource) do + Puppet::Type.type(:apt_key).new( + id: '0xEF8D349F', + ) + end + + it 'id is set' do + expect(resource[:id]).to eq 'EF8D349F' + end + end + + context 'with a 0x formatted lowercase key id' do + let(:resource) do + Puppet::Type.type(:apt_key).new( + id: '0xef8d349f', + ) + end + + it 'id is set' do + expect(resource[:id]).to eq 'EF8D349F' + end + end + + context 'with a 0x formatted 64bit key id' do + let(:resource) do + Puppet::Type.type(:apt_key).new( + id: '0xFFFFFFFFEF8D349F', + ) + end + + it 'id is set' do + expect(resource[:id]).to eq 'FFFFFFFFEF8D349F' + end + end + + context 'with source' do + let(:resource) do + Puppet::Type.type(:apt_key).new( + id: 'EF8D349F', + source: 'http://apt.puppetlabs.com/pubkey.gpg', + ) + end + + it 'source is set to the URL' do + expect(resource[:source]).to eq 'http://apt.puppetlabs.com/pubkey.gpg' + end + end + + context 'with content' do + let(:resource) do + Puppet::Type.type(:apt_key).new( + id: 'EF8D349F', + content: 'http://apt.puppetlabs.com/pubkey.gpg', + ) + end + + it 'content is set to the string' do + expect(resource[:content]).to eq 'http://apt.puppetlabs.com/pubkey.gpg' + end + end + + context 'with keyserver' do + let(:resource) do + Puppet::Type.type(:apt_key).new( + id: 'EF8D349F', + server: 'http://keyring.debian.org', + ) + end + + it 'keyserver is set to Debian' do + expect(resource[:server]).to eq 'http://keyring.debian.org' + end + end + + context 'with validation' do + it 'raises an error if content and source are set' do + expect { + Puppet::Type.type(:apt_key).new(id: 'EF8D349F', + source: 'http://apt.puppetlabs.com/pubkey.gpg', + content: 'Completely invalid as a GPG key') + }.to raise_error(%r{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: 'FEF8D349F', + source: 'http://apt.puppetlabs.com/pubkey.gpg', + content: 'Completely invalid as a GPG key') + }.to raise_error(%r{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: 'EF8D349F', + source: 'hkp://pgp.mit.edu') + }.to raise_error(%r{Valid values match}) + end + + it 'allows the http URI scheme in source' do + expect { + Puppet::Type.type(:apt_key).new(id: 'EF8D349F', + source: 'http://pgp.mit.edu') + }.not_to raise_error + end + + it 'allows the http URI with username and password' do + expect { + Puppet::Type.type(:apt_key).new(id: '4BD6EC30', + source: 'http://testme:Password2@pgp.mit.edu') + }.not_to raise_error + end + + it 'allows the https URI scheme in source' do + expect { + Puppet::Type.type(:apt_key).new(id: 'EF8D349F', + source: 'https://pgp.mit.edu') + }.not_to raise_error + end + + it 'allows the https URI with username and password' do + expect { + Puppet::Type.type(:apt_key).new(id: 'EF8D349F', + source: 'https://testme:Password2@pgp.mit.edu') + }.not_to raise_error + end + + it 'allows the ftp URI scheme in source' do + expect { + Puppet::Type.type(:apt_key).new(id: 'EF8D349F', + source: 'ftp://pgp.mit.edu') + }.not_to raise_error + end + + it 'allows an absolute path in source' do + expect { + Puppet::Type.type(:apt_key).new(id: 'EF8D349F', + source: '/path/to/a/file') + }.not_to raise_error + end + + it 'allows 5-digit ports' do + expect { + Puppet::Type.type(:apt_key).new(id: 'EF8D349F', + source: 'http://pgp.mit.edu:12345/key') + }.not_to raise_error + end + + it 'allows 5-digit ports when using key servers' do + expect { + Puppet::Type.type(:apt_key).new(id: 'EF8D349F', + server: 'http://pgp.mit.edu:12345') + }.not_to raise_error + end + end +end |