316 lines
12 KiB
Python
316 lines
12 KiB
Python
import subprocess
|
|
import os
|
|
|
|
from tests.helpers import patch_open
|
|
from testtools import TestCase
|
|
from mock import (
|
|
patch,
|
|
MagicMock,
|
|
call,
|
|
)
|
|
from charmhelpers.fetch import centos as fetch
|
|
|
|
|
|
def getenv(update=None):
|
|
# return a copy of os.environ with update applied.
|
|
# this was necessary because some modules modify os.environment directly
|
|
copy = os.environ.copy()
|
|
if update is not None:
|
|
copy.update(update)
|
|
return copy
|
|
|
|
|
|
class FetchTest(TestCase):
|
|
|
|
@patch("charmhelpers.fetch.log")
|
|
@patch('yum.YumBase.doPackageLists')
|
|
def test_filter_packages_missing_centos(self, yumBase, log):
|
|
|
|
class MockPackage:
|
|
def __init__(self, name):
|
|
self.base_package_name = name
|
|
|
|
yum_dict = {
|
|
'installed': {
|
|
MockPackage('vim')
|
|
},
|
|
'available': {
|
|
MockPackage('vim')
|
|
}
|
|
}
|
|
import yum
|
|
yum.YumBase.return_value.doPackageLists.return_value = yum_dict
|
|
result = fetch.filter_installed_packages(['vim', 'emacs'])
|
|
self.assertEquals(result, ['emacs'])
|
|
|
|
@patch("charmhelpers.fetch.log")
|
|
def test_filter_packages_none_missing_centos(self, log):
|
|
|
|
class MockPackage:
|
|
def __init__(self, name):
|
|
self.base_package_name = name
|
|
|
|
yum_dict = {
|
|
'installed': {
|
|
MockPackage('vim')
|
|
},
|
|
'available': {
|
|
MockPackage('vim')
|
|
}
|
|
}
|
|
import yum
|
|
yum.yumBase.return_value.doPackageLists.return_value = yum_dict
|
|
result = fetch.filter_installed_packages(['vim'])
|
|
self.assertEquals(result, [])
|
|
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
@patch('yum.YumBase.doPackageLists')
|
|
def test_filter_packages_not_available_centos(self, yumBase, log):
|
|
|
|
class MockPackage:
|
|
def __init__(self, name):
|
|
self.base_package_name = name
|
|
|
|
yum_dict = {
|
|
'installed': {
|
|
MockPackage('vim')
|
|
}
|
|
}
|
|
import yum
|
|
yum.YumBase.return_value.doPackageLists.return_value = yum_dict
|
|
|
|
result = fetch.filter_installed_packages(['vim', 'joe'])
|
|
self.assertEquals(result, ['joe'])
|
|
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
def test_add_source_none_centos(self, log):
|
|
fetch.add_source(source=None)
|
|
self.assertTrue(log.called)
|
|
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
@patch('os.listdir')
|
|
def test_add_source_http_centos(self, listdir, log):
|
|
source = "http://archive.ubuntu.com/ubuntu raring-backports main"
|
|
with patch_open() as (mock_open, mock_file):
|
|
fetch.add_source(source=source)
|
|
listdir.assert_called_with('/etc/yum.repos.d/')
|
|
mock_file.write.assert_has_calls([
|
|
call("[archive.ubuntu.com_ubuntu raring-backports main]\n"),
|
|
call("name=archive.ubuntu.com/ubuntu raring-backports main\n"),
|
|
call("baseurl=http://archive.ubuntu.com/ubuntu raring"
|
|
"-backports main\n\n")])
|
|
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
@patch('os.listdir')
|
|
@patch('subprocess.check_call')
|
|
def test_add_source_http_and_key_id_centos(self, check_call,
|
|
listdir, log):
|
|
source = "http://archive.ubuntu.com/ubuntu raring-backports main"
|
|
key_id = "akey"
|
|
with patch_open() as (mock_open, mock_file):
|
|
fetch.add_source(source=source, key=key_id)
|
|
listdir.assert_called_with('/etc/yum.repos.d/')
|
|
mock_file.write.assert_has_calls([
|
|
call("[archive.ubuntu.com_ubuntu raring-backports main]\n"),
|
|
call("name=archive.ubuntu.com/ubuntu raring-backports main\n"),
|
|
call("baseurl=http://archive.ubuntu.com/ubuntu raring"
|
|
"-backports main\n\n")])
|
|
check_call.assert_called_with(['rpm', '--import', key_id])
|
|
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
@patch('os.listdir')
|
|
@patch('subprocess.check_call')
|
|
def test_add_source_https_and_key_id_centos(self, check_call,
|
|
listdir, log):
|
|
source = "https://USER:PASS@private-ppa.launchpad.net/project/awesome"
|
|
key_id = "GPGPGP"
|
|
with patch_open() as (mock_open, mock_file):
|
|
fetch.add_source(source=source, key=key_id)
|
|
listdir.assert_called_with('/etc/yum.repos.d/')
|
|
mock_file.write.assert_has_calls([
|
|
call("[_USER:PASS@private-ppa.launchpad"
|
|
".net_project_awesome]\n"),
|
|
call("name=/USER:PASS@private-ppa.launchpad.net"
|
|
"/project/awesome\n"),
|
|
call("baseurl=https://USER:PASS@private-ppa.launchpad.net"
|
|
"/project/awesome\n\n")])
|
|
check_call.assert_called_with(['rpm', '--import', key_id])
|
|
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
@patch.object(fetch, 'NamedTemporaryFile')
|
|
@patch('os.listdir')
|
|
@patch('subprocess.check_call')
|
|
def test_add_source_http_and_key_centos(self, check_call,
|
|
listdir, temp_file, log):
|
|
source = "http://archive.ubuntu.com/ubuntu raring-backports main"
|
|
key = '''
|
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
|
[...]
|
|
-----END PGP PUBLIC KEY BLOCK-----
|
|
'''
|
|
file_mock = MagicMock()
|
|
file_mock.name = 'temporary_file'
|
|
temp_file.return_value.__enter__.return_value = file_mock
|
|
listdir.return_value = []
|
|
|
|
with patch_open() as (mock_open, mock_file):
|
|
fetch.add_source(source=source, key=key)
|
|
listdir.assert_called_with('/etc/yum.repos.d/')
|
|
self.assertTrue(log.called)
|
|
check_call.assert_called_with(['rpm', '--import', file_mock.name])
|
|
file_mock.write.assert_called_once_with(key)
|
|
file_mock.flush.assert_called_once_with()
|
|
file_mock.seek.assert_called_once_with(0)
|
|
|
|
|
|
class YumTests(TestCase):
|
|
|
|
@patch('subprocess.call')
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
def test_yum_upgrade_non_fatal(self, log, mock_call):
|
|
options = ['--foo', '--bar']
|
|
fetch.upgrade(options)
|
|
|
|
mock_call.assert_called_with(['yum', '--assumeyes',
|
|
'--foo', '--bar', 'upgrade'],
|
|
env=getenv())
|
|
|
|
@patch('subprocess.check_call')
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
def test_yum_upgrade_fatal(self, log, mock_call):
|
|
options = ['--foo', '--bar']
|
|
fetch.upgrade(options, fatal=True)
|
|
|
|
mock_call.assert_called_with(['yum', '--assumeyes',
|
|
'--foo', '--bar', 'upgrade'],
|
|
env=getenv())
|
|
|
|
@patch('subprocess.call')
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
def test_installs_yum_packages(self, log, mock_call):
|
|
packages = ['foo', 'bar']
|
|
options = ['--foo', '--bar']
|
|
|
|
fetch.install(packages, options)
|
|
|
|
mock_call.assert_called_with(['yum', '--assumeyes',
|
|
'--foo', '--bar', 'install',
|
|
'foo', 'bar'],
|
|
env=getenv())
|
|
|
|
@patch('subprocess.call')
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
def test_installs_yum_packages_without_options(self, log, mock_call):
|
|
packages = ['foo', 'bar']
|
|
fetch.install(packages)
|
|
|
|
mock_call.assert_called_with(['yum', '--assumeyes',
|
|
'install', 'foo', 'bar'],
|
|
env=getenv())
|
|
|
|
@patch('subprocess.call')
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
def test_installs_yum_packages_as_string(self, log, mock_call):
|
|
packages = 'foo bar'
|
|
fetch.install(packages)
|
|
|
|
mock_call.assert_called_with(['yum', '--assumeyes',
|
|
'install', 'foo bar'],
|
|
env=getenv())
|
|
|
|
@patch('subprocess.check_call')
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
def test_installs_yum_packages_with_possible_errors(self, log, mock_call):
|
|
packages = ['foo', 'bar']
|
|
options = ['--foo', '--bar']
|
|
|
|
fetch.install(packages, options, fatal=True)
|
|
|
|
mock_call.assert_called_with(['yum', '--assumeyes',
|
|
'--foo', '--bar',
|
|
'install', 'foo', 'bar'],
|
|
env=getenv())
|
|
|
|
@patch('subprocess.check_call')
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
def test_purges_yum_packages_as_string_fatal(self, log, mock_call):
|
|
packages = 'irrelevant names'
|
|
mock_call.side_effect = OSError('fail')
|
|
|
|
self.assertRaises(OSError, fetch.purge, packages, fatal=True)
|
|
self.assertTrue(log.called)
|
|
|
|
@patch('subprocess.check_call')
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
def test_purges_yum_packages_fatal(self, log, mock_call):
|
|
packages = ['irrelevant', 'names']
|
|
mock_call.side_effect = OSError('fail')
|
|
|
|
self.assertRaises(OSError, fetch.purge, packages, fatal=True)
|
|
self.assertTrue(log.called)
|
|
|
|
@patch('subprocess.call')
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
def test_purges_yum_packages_as_string_nofatal(self, log, mock_call):
|
|
packages = 'foo bar'
|
|
fetch.purge(packages)
|
|
|
|
self.assertTrue(log.called)
|
|
mock_call.assert_called_with(['yum', '--assumeyes',
|
|
'remove', 'foo bar'],
|
|
env=getenv())
|
|
|
|
@patch('subprocess.call')
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
def test_purges_yum_packages_nofatal(self, log, mock_call):
|
|
packages = ['foo', 'bar']
|
|
fetch.purge(packages)
|
|
|
|
self.assertTrue(log.called)
|
|
mock_call.assert_called_with(['yum', '--assumeyes',
|
|
'remove', 'foo', 'bar'],
|
|
env=getenv())
|
|
|
|
@patch('subprocess.check_call')
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
def test_yum_update_fatal(self, log, check_call):
|
|
fetch.update(fatal=True)
|
|
check_call.assert_called_with(['yum', '--assumeyes', 'update'],
|
|
env=getenv())
|
|
self.assertTrue(log.called)
|
|
|
|
@patch('subprocess.check_output')
|
|
@patch('charmhelpers.fetch.centos.log')
|
|
def test_yum_search(self, log, check_output):
|
|
package = ['irrelevant']
|
|
|
|
from charmhelpers.fetch.centos import yum_search
|
|
yum_search(package)
|
|
check_output.assert_called_with(['yum', 'search', 'irrelevant'])
|
|
self.assertTrue(log.called)
|
|
|
|
@patch('subprocess.check_call')
|
|
@patch('time.sleep')
|
|
def test_run_yum_command_retries_if_fatal(self, check_call, sleep):
|
|
"""The _run_yum_command function retries the command if it can't get
|
|
the YUM lock."""
|
|
self.called = False
|
|
|
|
def side_effect(*args, **kwargs):
|
|
"""
|
|
First, raise an exception (can't acquire lock), then return 0
|
|
(the lock is grabbed).
|
|
"""
|
|
if not self.called:
|
|
self.called = True
|
|
raise subprocess.CalledProcessError(
|
|
returncode=1, cmd="some command")
|
|
else:
|
|
return 0
|
|
|
|
check_call.side_effect = side_effect
|
|
check_call.return_value = 0
|
|
from charmhelpers.fetch.centos import _run_yum_command
|
|
_run_yum_command(["some", "command"], fatal=True)
|
|
self.assertTrue(sleep.called)
|