# This file is part of cloud-init. See LICENSE file for license information.
""" test_apt_custom_sources_list
Test templating of custom sources list
"""
import logging
import os
import shutil
import tempfile
try:
from unittest import mock
except ImportError:
import mock
from mock import call
from cloudinit import cloud
from cloudinit import distros
from cloudinit import helpers
from cloudinit import util
from cloudinit.config import cc_apt_configure
from cloudinit.sources import DataSourceNone
from cloudinit.distros.debian import Distro
from cloudinit.tests import helpers as t_help
LOG = logging.getLogger(__name__)
TARGET = "/"
# Input and expected output for the custom template
YAML_TEXT_CUSTOM_SL = """
apt:
primary:
- arches: [default]
uri: http://test.ubuntu.com/ubuntu/
security:
- arches: [default]
uri: http://testsec.ubuntu.com/ubuntu/
sources_list: |
# Note, this file is written by cloud-init at install time. It should not
# end up on the installed system itself.
# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
# newer versions of the distribution.
deb $MIRROR $RELEASE main restricted
deb-src $MIRROR $RELEASE main restricted
deb $PRIMARY $RELEASE universe restricted
deb $SECURITY $RELEASE-security multiverse
# FIND_SOMETHING_SPECIAL
"""
EXPECTED_CONVERTED_CONTENT = """
# Note, this file is written by cloud-init at install time. It should not
# end up on the installed system itself.
# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
# newer versions of the distribution.
deb http://test.ubuntu.com/ubuntu/ fakerel main restricted
deb-src http://test.ubuntu.com/ubuntu/ fakerel main restricted
deb http://test.ubuntu.com/ubuntu/ fakerel universe restricted
deb http://testsec.ubuntu.com/ubuntu/ fakerel-security multiverse
# FIND_SOMETHING_SPECIAL
"""
# mocked to be independent to the unittest system
MOCKED_APT_SRC_LIST = """
deb http://test.ubuntu.com/ubuntu/ notouched main restricted
deb-src http://test.ubuntu.com/ubuntu/ notouched main restricted
deb http://test.ubuntu.com/ubuntu/ notouched-updates main restricted
deb http://testsec.ubuntu.com/ubuntu/ notouched-security main restricted
"""
EXPECTED_BASE_CONTENT = ("""
deb http://test.ubuntu.com/ubuntu/ notouched main restricted
deb-src http://test.ubuntu.com/ubuntu/ notouched main restricted
deb http://test.ubuntu.com/ubuntu/ notouched-updates main restricted
deb http://testsec.ubuntu.com/ubuntu/ notouched-security main restricted
""")
EXPECTED_MIRROR_CONTENT = ("""
deb http://test.ubuntu.com/ubuntu/ notouched main restricted
deb-src http://test.ubuntu.com/ubuntu/ notouched main restricted
deb http://test.ubuntu.com/ubuntu/ notouched-updates main restricted
deb http://test.ubuntu.com/ubuntu/ notouched-security main restricted
""")
EXPECTED_PRIMSEC_CONTENT = ("""
deb http://test.ubuntu.com/ubuntu/ notouched main restricted
deb-src http://test.ubuntu.com/ubuntu/ notouched main restricted
deb http://test.ubuntu.com/ubuntu/ notouched-updates main restricted
deb http://testsec.ubuntu.com/ubuntu/ notouched-security main restricted
""")
class TestAptSourceConfigSourceList(t_help.FilesystemMockingTestCase):
"""TestAptSourceConfigSourceList - Class to test sources list rendering"""
def setUp(self):
super(TestAptSourceConfigSourceList, self).setUp()
self.subp = util.subp
self.new_root = tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, self.new_root)
rpatcher = mock.patch("cloudinit.util.lsb_release")
get_rel = rpatcher.start()
get_rel.return_value = {'codename': "fakerel"}
self.addCleanup(rpatcher.stop)
apatcher = mock.patch("cloudinit.util.get_architecture")
get_arch = apatcher.start()
get_arch.return_value = 'amd64'
self.addCleanup(apatcher.stop)
def _get_cloud(self, distro, metadata=None):
self.patchUtils(self.new_root)
paths = helpers.Paths({})
cls = distros.fetch(distro)
mydist = cls(distro, {}, paths)
myds = DataSourceNone.DataSourceNone({}, mydist, paths)
if metadata:
myds.metadata.update(metadata)
return cloud.Cloud(myds, paths, {}, mydist, None)
def _apt_source_list(self, distro, cfg, cfg_on_empty=False):
"""_apt_source_list - Test rendering from template (generic)"""
# entry at top level now, wrap in 'apt' key
cfg = {'apt': cfg}
mycloud = self._get_cloud(distro)
with mock.patch.object(util, 'write_file') as mock_writefile:
with mock.patch.object(util, 'load_file',
return_value=MOCKED_APT_SRC_LIST
) as mock_loadfile:
with mock.patch.object(os.path, 'isfile',
return_value=True) as mock_isfile:
cfg_func = ('cloudinit.config.cc_apt_configure.' +
'_should_configure_on_empty_apt')
with mock.patch(cfg_func,
return_value=(cfg_on_empty, "test")
) as mock_shouldcfg:
cc_apt_configure.handle("test", cfg, mycloud, LOG,
None)
return mock_writefile, mock_loadfile, mock_isfile, mock_shouldcfg
def test_apt_v3_source_list_debian(self):
"""test_apt_v3_source_list_debian - without custom sources or parms"""
cfg = {}
distro = 'debian'
expected = EXPECTED_BASE_CONTENT
mock_writefile, mock_load_file, mock_isfile, mock_shouldcfg = (
self._apt_source_list(distro, cfg, cfg_on_empty=True))
template = '/etc/cloud/templates/sources.list.%s.tmpl' % distro
mock_writefile.assert_called_once_with('/etc/apt/sources.list',
expected, mode=0o644)
mock_load_file.assert_called_with(template)
mock_isfile.assert_any_call(template)
self.assertEqual(1, mock_shouldcfg.call_count)
def test_apt_v3_source_list_ubuntu(self):
"""test_apt_v3_source_list_ubuntu - without custom sources or parms"""
cfg = {}
distro = 'ubuntu'
expected = EXPECTED_BASE_CONTENT
mock_writefile, mock_load_file, mock_isfile, mock_shouldcfg = (
self._apt_source_list(distro, cfg, cfg_on_empty=True))
template = '/etc/cloud/templates/sources.list.%s.tmpl' % distro
mock_writefile.assert_called_once_with('/etc/apt/sources.list',
expected, mode=0o644)
mock_load_file.assert_called_with(template)
mock_isfile.assert_any_call(template)
self.assertEqual(1, mock_shouldcfg.call_count)
def test_apt_v3_source_list_ubuntu_snappy(self):
"""test_apt_v3_source_list_ubuntu_snappy - without custom sources or
parms"""
cfg = {'apt': {}}
mycloud = self._get_cloud('ubuntu')
with mock.patch.object(util, 'write_file') as mock_writefile:
with mock.patch.object(util, 'system_is_snappy',
return_value=True) as mock_issnappy:
cc_apt_configure.handle("test", cfg, mycloud, LOG, None)
self.assertEqual(0, mock_writefile.call_count)
self.assertEqual(1, mock_issnappy.call_count)
def test_apt_v3_source_list_centos(self):
"""test_apt_v3_source_list_centos - without custom sources or parms"""
cfg = {}
distro = 'rhel'
mock_writefile, _, _, _ = self._apt_source_list(distro, cfg)
self.assertEqual(0, mock_writefile.call_count)
def test_apt_v3_source_list_psm(self):
"""test_apt_v3_source_list_psm - Test specifying prim+sec mirrors"""
pm = 'http://test.ubuntu.com/ubuntu/'
sm = 'http://testsec.ubuntu.com/ubuntu/'
cfg = {'preserve_sources_list': False,
'primary': [{'arches': ["default"],
'uri': pm}],
'security': [{'arches': ["default"],
'uri': sm}]}
distro = 'ubuntu'
expected = EXPECTED_PRIMSEC_CONTENT
mock_writefile, mock_load_file, mock_isfile, _ = (
self._apt_source_list(distro, cfg, cfg_on_empty=True))
template = '/etc/cloud/templates/sources.list.%s.tmpl' % distro
mock_writefile.assert_called_once_with('/etc/apt/sources.list',
expected, mode=0o644)
mock_load_file.assert_called_with(template)
mock_isfile.assert_any_call(template)
def test_apt_v3_srcl_custom(self):
"""test_apt_v3_srcl_custom - Test rendering a custom source template"""
cfg = util.load_yaml(YAML_TEXT_CUSTOM_SL)
mycloud = self._get_cloud('ubuntu')
# the second mock restores the original subp
with mock.patch.object(util, 'write_file') as mockwrite:
with mock.patch.object(util, 'subp', self.subp):
with mock.patch.object(Distro, 'get_primary_arch',
return_value='amd64'):
cc_apt_configure.handle("notimportant", cfg, mycloud,
LOG, None)
calls = [call('/etc/apt/sources.list',
EXPECTED_CONVERTED_CONTENT,
mode=0o644)]
mockwrite.assert_has_calls(calls)
# vi: ts=4 expandtab