summaryrefslogtreecommitdiff
path: root/tests/unittests/config
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unittests/config')
-rw-r--r--tests/unittests/config/test_apt_conf_v1.py68
-rw-r--r--tests/unittests/config/test_apt_configure_sources_list_v1.py131
-rw-r--r--tests/unittests/config/test_apt_configure_sources_list_v3.py158
-rw-r--r--tests/unittests/config/test_apt_key.py117
-rw-r--r--tests/unittests/config/test_apt_source_v1.py765
-rw-r--r--tests/unittests/config/test_apt_source_v3.py1220
-rw-r--r--tests/unittests/config/test_cc_apk_configure.py148
-rw-r--r--tests/unittests/config/test_cc_apt_pipelining.py12
-rw-r--r--tests/unittests/config/test_cc_bootcmd.py100
-rw-r--r--tests/unittests/config/test_cc_ca_certs.py220
-rw-r--r--tests/unittests/config/test_cc_chef.py202
-rw-r--r--tests/unittests/config/test_cc_debug.py39
-rw-r--r--tests/unittests/config/test_cc_disable_ec2_metadata.py44
-rw-r--r--tests/unittests/config/test_cc_disk_setup.py270
-rw-r--r--tests/unittests/config/test_cc_growpart.py232
-rw-r--r--tests/unittests/config/test_cc_grub_dpkg.py121
-rw-r--r--tests/unittests/config/test_cc_install_hotplug.py58
-rw-r--r--tests/unittests/config/test_cc_keys_to_console.py18
-rw-r--r--tests/unittests/config/test_cc_landscape.py178
-rw-r--r--tests/unittests/config/test_cc_locale.py99
-rw-r--r--tests/unittests/config/test_cc_lxd.py250
-rw-r--r--tests/unittests/config/test_cc_mcollective.py104
-rw-r--r--tests/unittests/config/test_cc_mounts.py449
-rw-r--r--tests/unittests/config/test_cc_ntp.py682
-rw-r--r--tests/unittests/config/test_cc_power_state_change.py74
-rw-r--r--tests/unittests/config/test_cc_puppet.py432
-rw-r--r--tests/unittests/config/test_cc_refresh_rmc_and_interface.py162
-rw-r--r--tests/unittests/config/test_cc_resizefs.py436
-rw-r--r--tests/unittests/config/test_cc_resolv_conf.py76
-rw-r--r--tests/unittests/config/test_cc_rh_subscription.py366
-rw-r--r--tests/unittests/config/test_cc_rsyslog.py112
-rw-r--r--tests/unittests/config/test_cc_runcmd.py74
-rw-r--r--tests/unittests/config/test_cc_seed_random.py158
-rw-r--r--tests/unittests/config/test_cc_set_hostname.py185
-rw-r--r--tests/unittests/config/test_cc_set_passwords.py111
-rw-r--r--tests/unittests/config/test_cc_snap.py445
-rw-r--r--tests/unittests/config/test_cc_spacewalk.py36
-rw-r--r--tests/unittests/config/test_cc_ssh.py356
-rw-r--r--tests/unittests/config/test_cc_timezone.py31
-rw-r--r--tests/unittests/config/test_cc_ubuntu_advantage.py311
-rw-r--r--tests/unittests/config/test_cc_ubuntu_drivers.py213
-rw-r--r--tests/unittests/config/test_cc_update_etc_hosts.py63
-rw-r--r--tests/unittests/config/test_cc_users_groups.py264
-rw-r--r--tests/unittests/config/test_cc_write_files.py148
-rw-r--r--tests/unittests/config/test_cc_write_files_deferred.py62
-rw-r--r--tests/unittests/config/test_cc_yum_add_repo.py105
-rw-r--r--tests/unittests/config/test_cc_zypper_add_repo.py166
-rw-r--r--tests/unittests/config/test_schema.py301
48 files changed, 6070 insertions, 4302 deletions
diff --git a/tests/unittests/config/test_apt_conf_v1.py b/tests/unittests/config/test_apt_conf_v1.py
index 98d99945..5a75cf0a 100644
--- a/tests/unittests/config/test_apt_conf_v1.py
+++ b/tests/unittests/config/test_apt_conf_v1.py
@@ -1,16 +1,15 @@
# This file is part of cloud-init. See LICENSE file for license information.
-from cloudinit.config import cc_apt_configure
-from cloudinit import util
-
-from tests.unittests.helpers import TestCase
-
import copy
import os
import re
import shutil
import tempfile
+from cloudinit import util
+from cloudinit.config import cc_apt_configure
+from tests.unittests.helpers import TestCase
+
class TestAptProxyConfig(TestCase):
def setUp(self):
@@ -23,10 +22,12 @@ class TestAptProxyConfig(TestCase):
def _search_apt_config(self, contents, ptype, value):
return re.search(
r"acquire::%s::proxy\s+[\"']%s[\"'];\n" % (ptype, value),
- contents, flags=re.IGNORECASE)
+ contents,
+ flags=re.IGNORECASE,
+ )
def test_apt_proxy_written(self):
- cfg = {'proxy': 'myproxy'}
+ cfg = {"proxy": "myproxy"}
cc_apt_configure.apply_apt_config(cfg, self.pfile, self.cfile)
self.assertTrue(os.path.isfile(self.pfile))
@@ -36,7 +37,7 @@ class TestAptProxyConfig(TestCase):
self.assertTrue(self._search_apt_config(contents, "http", "myproxy"))
def test_apt_http_proxy_written(self):
- cfg = {'http_proxy': 'myproxy'}
+ cfg = {"http_proxy": "myproxy"}
cc_apt_configure.apply_apt_config(cfg, self.pfile, self.cfile)
self.assertTrue(os.path.isfile(self.pfile))
@@ -46,14 +47,17 @@ class TestAptProxyConfig(TestCase):
self.assertTrue(self._search_apt_config(contents, "http", "myproxy"))
def test_apt_all_proxy_written(self):
- cfg = {'http_proxy': 'myproxy_http_proxy',
- 'https_proxy': 'myproxy_https_proxy',
- 'ftp_proxy': 'myproxy_ftp_proxy'}
-
- values = {'http': cfg['http_proxy'],
- 'https': cfg['https_proxy'],
- 'ftp': cfg['ftp_proxy'],
- }
+ cfg = {
+ "http_proxy": "myproxy_http_proxy",
+ "https_proxy": "myproxy_https_proxy",
+ "ftp_proxy": "myproxy_ftp_proxy",
+ }
+
+ values = {
+ "http": cfg["http_proxy"],
+ "https": cfg["https_proxy"],
+ "ftp": cfg["ftp_proxy"],
+ }
cc_apt_configure.apply_apt_config(cfg, self.pfile, self.cfile)
@@ -73,15 +77,16 @@ class TestAptProxyConfig(TestCase):
def test_proxy_replaced(self):
util.write_file(self.cfile, "content doesnt matter")
- cc_apt_configure.apply_apt_config({'proxy': "foo"},
- self.pfile, self.cfile)
+ cc_apt_configure.apply_apt_config(
+ {"proxy": "foo"}, self.pfile, self.cfile
+ )
self.assertTrue(os.path.isfile(self.pfile))
contents = util.load_file(self.pfile)
self.assertTrue(self._search_apt_config(contents, "http", "foo"))
def test_config_written(self):
- payload = 'this is my apt config'
- cfg = {'conf': payload}
+ payload = "this is my apt config"
+ cfg = {"conf": payload}
cc_apt_configure.apply_apt_config(cfg, self.pfile, self.cfile)
@@ -92,8 +97,9 @@ class TestAptProxyConfig(TestCase):
def test_config_replaced(self):
util.write_file(self.pfile, "content doesnt matter")
- cc_apt_configure.apply_apt_config({'conf': "foo"},
- self.pfile, self.cfile)
+ cc_apt_configure.apply_apt_config(
+ {"conf": "foo"}, self.pfile, self.cfile
+ )
self.assertTrue(os.path.isfile(self.cfile))
self.assertEqual(util.load_file(self.cfile), "foo")
@@ -109,21 +115,23 @@ class TestConversion(TestCase):
def test_convert_with_apt_mirror_as_empty_string(self):
# an empty apt_mirror is the same as no apt_mirror
empty_m_found = cc_apt_configure.convert_to_v3_apt_format(
- {'apt_mirror': ''})
+ {"apt_mirror": ""}
+ )
default_found = cc_apt_configure.convert_to_v3_apt_format({})
self.assertEqual(default_found, empty_m_found)
def test_convert_with_apt_mirror(self):
- mirror = 'http://my.mirror/ubuntu'
- f = cc_apt_configure.convert_to_v3_apt_format({'apt_mirror': mirror})
- self.assertIn(mirror, set(m['uri'] for m in f['apt']['primary']))
+ mirror = "http://my.mirror/ubuntu"
+ f = cc_apt_configure.convert_to_v3_apt_format({"apt_mirror": mirror})
+ self.assertIn(mirror, set(m["uri"] for m in f["apt"]["primary"]))
def test_no_old_content(self):
- mirror = 'http://my.mirror/ubuntu'
- mydata = {'apt': {'primary': {'arches': ['default'], 'uri': mirror}}}
+ mirror = "http://my.mirror/ubuntu"
+ mydata = {"apt": {"primary": {"arches": ["default"], "uri": mirror}}}
expected = copy.deepcopy(mydata)
- self.assertEqual(expected,
- cc_apt_configure.convert_to_v3_apt_format(mydata))
+ self.assertEqual(
+ expected, cc_apt_configure.convert_to_v3_apt_format(mydata)
+ )
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_apt_configure_sources_list_v1.py b/tests/unittests/config/test_apt_configure_sources_list_v1.py
index 4aeaea24..d4ade106 100644
--- a/tests/unittests/config/test_apt_configure_sources_list_v1.py
+++ b/tests/unittests/config/test_apt_configure_sources_list_v1.py
@@ -9,14 +9,9 @@ import shutil
import tempfile
from unittest import mock
-from cloudinit import templater
-from cloudinit import subp
-from cloudinit import util
-
+from cloudinit import subp, templater, util
from cloudinit.config import cc_apt_configure
-
from cloudinit.distros.debian import Distro
-
from tests.unittests import helpers as t_help
from tests.unittests.util import get_cloud
@@ -41,8 +36,7 @@ apt_custom_sources_list: |
# FIND_SOMETHING_SPECIAL
"""
-EXPECTED_CONVERTED_CONTENT = (
- """## Note, this file is written by cloud-init on first boot of an instance
+EXPECTED_CONVERTED_CONTENT = """## Note, this file is written by cloud-init on first boot of an instance
## modifications made here will not survive a re-bundle.
## if you wish to make changes you can:
## a.) add 'apt_preserve_sources_list: true' to /etc/cloud/cloud.cfg
@@ -55,13 +49,14 @@ EXPECTED_CONVERTED_CONTENT = (
deb http://archive.ubuntu.com/ubuntu/ fakerelease main restricted
deb-src http://archive.ubuntu.com/ubuntu/ fakerelease main restricted
# FIND_SOMETHING_SPECIAL
-""")
+"""
class TestAptSourceConfigSourceList(t_help.FilesystemMockingTestCase):
"""TestAptSourceConfigSourceList
Main Class to test sources list rendering
"""
+
def setUp(self):
super(TestAptSourceConfigSourceList, self).setUp()
self.subp = subp.subp
@@ -70,11 +65,11 @@ class TestAptSourceConfigSourceList(t_help.FilesystemMockingTestCase):
rpatcher = mock.patch("cloudinit.util.lsb_release")
get_rel = rpatcher.start()
- get_rel.return_value = {'codename': "fakerelease"}
+ get_rel.return_value = {"codename": "fakerelease"}
self.addCleanup(rpatcher.stop)
apatcher = mock.patch("cloudinit.util.get_dpkg_architecture")
get_arch = apatcher.start()
- get_arch.return_value = 'amd64'
+ get_arch.return_value = "amd64"
self.addCleanup(apatcher.stop)
def apt_source_list(self, distro, mirror, mirrorcheck=None):
@@ -85,47 +80,57 @@ class TestAptSourceConfigSourceList(t_help.FilesystemMockingTestCase):
mirrorcheck = mirror
if isinstance(mirror, list):
- cfg = {'apt_mirror_search': mirror}
+ cfg = {"apt_mirror_search": mirror}
else:
- cfg = {'apt_mirror': mirror}
+ cfg = {"apt_mirror": mirror}
mycloud = get_cloud(distro)
- with mock.patch.object(util, 'write_file') as mockwf:
- with mock.patch.object(util, 'load_file',
- return_value="faketmpl") as mocklf:
- with mock.patch.object(os.path, 'isfile',
- return_value=True) as mockisfile:
+ with mock.patch.object(util, "write_file") as mockwf:
+ with mock.patch.object(
+ util, "load_file", return_value="faketmpl"
+ ) as mocklf:
+ with mock.patch.object(
+ os.path, "isfile", return_value=True
+ ) as mockisfile:
with mock.patch.object(
- templater, 'render_string',
- return_value='fake') as mockrnd:
- with mock.patch.object(util, 'rename'):
- cc_apt_configure.handle("test", cfg, mycloud,
- LOG, None)
+ templater, "render_string", return_value="fake"
+ ) as mockrnd:
+ with mock.patch.object(util, "rename"):
+ cc_apt_configure.handle(
+ "test", cfg, mycloud, LOG, None
+ )
mockisfile.assert_any_call(
- ('/etc/cloud/templates/sources.list.%s.tmpl' % distro))
+ "/etc/cloud/templates/sources.list.%s.tmpl" % distro
+ )
mocklf.assert_any_call(
- ('/etc/cloud/templates/sources.list.%s.tmpl' % distro))
- mockrnd.assert_called_once_with('faketmpl',
- {'RELEASE': 'fakerelease',
- 'PRIMARY': mirrorcheck,
- 'MIRROR': mirrorcheck,
- 'SECURITY': mirrorcheck,
- 'codename': 'fakerelease',
- 'primary': mirrorcheck,
- 'mirror': mirrorcheck,
- 'security': mirrorcheck})
- mockwf.assert_called_once_with('/etc/apt/sources.list', 'fake',
- mode=0o644)
+ "/etc/cloud/templates/sources.list.%s.tmpl" % distro
+ )
+ mockrnd.assert_called_once_with(
+ "faketmpl",
+ {
+ "RELEASE": "fakerelease",
+ "PRIMARY": mirrorcheck,
+ "MIRROR": mirrorcheck,
+ "SECURITY": mirrorcheck,
+ "codename": "fakerelease",
+ "primary": mirrorcheck,
+ "mirror": mirrorcheck,
+ "security": mirrorcheck,
+ },
+ )
+ mockwf.assert_called_once_with(
+ "/etc/apt/sources.list", "fake", mode=0o644
+ )
def test_apt_v1_source_list_debian(self):
"""Test rendering of a source.list from template for debian"""
- self.apt_source_list('debian', 'http://httpredir.debian.org/debian')
+ self.apt_source_list("debian", "http://httpredir.debian.org/debian")
def test_apt_v1_source_list_ubuntu(self):
"""Test rendering of a source.list from template for ubuntu"""
- self.apt_source_list('ubuntu', 'http://archive.ubuntu.com/ubuntu/')
+ self.apt_source_list("ubuntu", "http://archive.ubuntu.com/ubuntu/")
@staticmethod
def myresolve(name):
@@ -139,23 +144,30 @@ class TestAptSourceConfigSourceList(t_help.FilesystemMockingTestCase):
def test_apt_v1_srcl_debian_mirrorfail(self):
"""Test rendering of a source.list from template for debian"""
- with mock.patch.object(util, 'is_resolvable',
- side_effect=self.myresolve) as mockresolve:
- self.apt_source_list('debian',
- ['http://does.not.exist',
- 'http://httpredir.debian.org/debian'],
- 'http://httpredir.debian.org/debian')
+ with mock.patch.object(
+ util, "is_resolvable", side_effect=self.myresolve
+ ) as mockresolve:
+ self.apt_source_list(
+ "debian",
+ [
+ "http://does.not.exist",
+ "http://httpredir.debian.org/debian",
+ ],
+ "http://httpredir.debian.org/debian",
+ )
mockresolve.assert_any_call("does.not.exist")
mockresolve.assert_any_call("httpredir.debian.org")
def test_apt_v1_srcl_ubuntu_mirrorfail(self):
"""Test rendering of a source.list from template for ubuntu"""
- with mock.patch.object(util, 'is_resolvable',
- side_effect=self.myresolve) as mockresolve:
- self.apt_source_list('ubuntu',
- ['http://does.not.exist',
- 'http://archive.ubuntu.com/ubuntu/'],
- 'http://archive.ubuntu.com/ubuntu/')
+ with mock.patch.object(
+ util, "is_resolvable", side_effect=self.myresolve
+ ) as mockresolve:
+ self.apt_source_list(
+ "ubuntu",
+ ["http://does.not.exist", "http://archive.ubuntu.com/ubuntu/"],
+ "http://archive.ubuntu.com/ubuntu/",
+ )
mockresolve.assert_any_call("does.not.exist")
mockresolve.assert_any_call("archive.ubuntu.com")
@@ -165,17 +177,18 @@ class TestAptSourceConfigSourceList(t_help.FilesystemMockingTestCase):
mycloud = get_cloud()
# the second mock restores the original subp
- with mock.patch.object(util, 'write_file') as mockwrite:
- with mock.patch.object(subp, 'subp', self.subp):
- with mock.patch.object(Distro, 'get_primary_arch',
- return_value='amd64'):
- cc_apt_configure.handle("notimportant", cfg, mycloud,
- LOG, None)
+ with mock.patch.object(util, "write_file") as mockwrite:
+ with mock.patch.object(subp, "subp", self.subp):
+ with mock.patch.object(
+ Distro, "get_primary_arch", return_value="amd64"
+ ):
+ cc_apt_configure.handle(
+ "notimportant", cfg, mycloud, LOG, None
+ )
mockwrite.assert_called_once_with(
- '/etc/apt/sources.list',
- EXPECTED_CONVERTED_CONTENT,
- mode=420)
+ "/etc/apt/sources.list", EXPECTED_CONVERTED_CONTENT, mode=420
+ )
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_apt_configure_sources_list_v3.py b/tests/unittests/config/test_apt_configure_sources_list_v3.py
index a8087bd1..d9ec6f74 100644
--- a/tests/unittests/config/test_apt_configure_sources_list_v3.py
+++ b/tests/unittests/config/test_apt_configure_sources_list_v3.py
@@ -3,20 +3,18 @@
""" test_apt_custom_sources_list
Test templating of custom sources list
"""
-from contextlib import ExitStack
import logging
import os
import shutil
import tempfile
+from contextlib import ExitStack
from unittest import mock
from unittest.mock import call
-from cloudinit import subp
-from cloudinit import util
+from cloudinit import subp, util
from cloudinit.config import cc_apt_configure
from cloudinit.distros.debian import Distro
from tests.unittests import helpers as t_help
-
from tests.unittests.util import get_cloud
LOG = logging.getLogger(__name__)
@@ -65,30 +63,31 @@ deb http://test.ubuntu.com/ubuntu/ notouched-updates main restricted
deb http://testsec.ubuntu.com/ubuntu/ notouched-security main restricted
"""
-EXPECTED_BASE_CONTENT = ("""
+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 = ("""
+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 = ("""
+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 = subp.subp
@@ -97,33 +96,39 @@ class TestAptSourceConfigSourceList(t_help.FilesystemMockingTestCase):
rpatcher = mock.patch("cloudinit.util.lsb_release")
get_rel = rpatcher.start()
- get_rel.return_value = {'codename': "fakerel"}
+ get_rel.return_value = {"codename": "fakerel"}
self.addCleanup(rpatcher.stop)
apatcher = mock.patch("cloudinit.util.get_dpkg_architecture")
get_arch = apatcher.start()
- get_arch.return_value = 'amd64'
+ get_arch.return_value = "amd64"
self.addCleanup(apatcher.stop)
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}
+ cfg = {"apt": cfg}
mycloud = get_cloud(distro)
with ExitStack() as stack:
- mock_writefile = stack.enter_context(mock.patch.object(
- util, 'write_file'))
- mock_loadfile = stack.enter_context(mock.patch.object(
- util, 'load_file', return_value=MOCKED_APT_SRC_LIST))
- mock_isfile = stack.enter_context(mock.patch.object(
- os.path, 'isfile', return_value=True))
- stack.enter_context(mock.patch.object(
- util, 'del_file'))
- cfg_func = ('cloudinit.config.cc_apt_configure.'
- '_should_configure_on_empty_apt')
- mock_shouldcfg = stack.enter_context(mock.patch(
- cfg_func, return_value=(cfg_on_empty, 'test')
- ))
+ mock_writefile = stack.enter_context(
+ mock.patch.object(util, "write_file")
+ )
+ mock_loadfile = stack.enter_context(
+ mock.patch.object(
+ util, "load_file", return_value=MOCKED_APT_SRC_LIST
+ )
+ )
+ mock_isfile = stack.enter_context(
+ mock.patch.object(os.path, "isfile", return_value=True)
+ )
+ stack.enter_context(mock.patch.object(util, "del_file"))
+ cfg_func = (
+ "cloudinit.config.cc_apt_configure."
+ "_should_configure_on_empty_apt"
+ )
+ mock_shouldcfg = stack.enter_context(
+ mock.patch(cfg_func, return_value=(cfg_on_empty, "test"))
+ )
cc_apt_configure.handle("test", cfg, mycloud, LOG, None)
return mock_writefile, mock_loadfile, mock_isfile, mock_shouldcfg
@@ -131,15 +136,20 @@ class TestAptSourceConfigSourceList(t_help.FilesystemMockingTestCase):
def test_apt_v3_source_list_debian(self):
"""test_apt_v3_source_list_debian - without custom sources or parms"""
cfg = {}
- distro = 'debian'
+ 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_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)
@@ -147,15 +157,20 @@ class TestAptSourceConfigSourceList(t_help.FilesystemMockingTestCase):
def test_apt_v3_source_list_ubuntu(self):
"""test_apt_v3_source_list_ubuntu - without custom sources or parms"""
cfg = {}
- distro = 'ubuntu'
+ 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_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)
@@ -163,12 +178,13 @@ class TestAptSourceConfigSourceList(t_help.FilesystemMockingTestCase):
def test_apt_v3_source_list_ubuntu_snappy(self):
"""test_apt_v3_source_list_ubuntu_snappy - without custom sources or
parms"""
- cfg = {'apt': {}}
+ cfg = {"apt": {}}
mycloud = get_cloud()
- with mock.patch.object(util, 'write_file') as mock_writefile:
- with mock.patch.object(util, 'system_is_snappy',
- return_value=True) as mock_issnappy:
+ 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)
@@ -177,7 +193,7 @@ class TestAptSourceConfigSourceList(t_help.FilesystemMockingTestCase):
def test_apt_v3_source_list_centos(self):
"""test_apt_v3_source_list_centos - without custom sources or parms"""
cfg = {}
- distro = 'rhel'
+ distro = "rhel"
mock_writefile, _, _, _ = self._apt_source_list(distro, cfg)
@@ -185,22 +201,24 @@ class TestAptSourceConfigSourceList(t_help.FilesystemMockingTestCase):
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'
+ 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))
+ 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)
+ 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)
@@ -210,16 +228,20 @@ class TestAptSourceConfigSourceList(t_help.FilesystemMockingTestCase):
mycloud = get_cloud()
# the second mock restores the original subp
- with mock.patch.object(util, 'write_file') as mockwrite:
- with mock.patch.object(subp, '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)]
+ with mock.patch.object(util, "write_file") as mockwrite:
+ with mock.patch.object(subp, "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)
diff --git a/tests/unittests/config/test_apt_key.py b/tests/unittests/config/test_apt_key.py
index 00e5a38d..9fcf3039 100644
--- a/tests/unittests/config/test_apt_key.py
+++ b/tests/unittests/config/test_apt_key.py
@@ -1,11 +1,10 @@
import os
from unittest import mock
+from cloudinit import subp, util
from cloudinit.config import cc_apt_configure
-from cloudinit import subp
-from cloudinit import util
-TEST_KEY_HUMAN = '''
+TEST_KEY_HUMAN = """
/etc/apt/cloud-init.gpg.d/my_key.gpg
--------------------------------------------
pub rsa4096 2021-10-22 [SC]
@@ -13,9 +12,9 @@ pub rsa4096 2021-10-22 [SC]
uid [ unknown] Brett Holman <brett.holman@canonical.com>
sub rsa4096 2021-10-22 [A]
sub rsa4096 2021-10-22 [E]
-'''
+"""
-TEST_KEY_MACHINE = '''
+TEST_KEY_MACHINE = """
tru::1:1635129362:0:3:1:5
pub:-:4096:1:F83F77129A5EBD85:1634912922:::-:::scESCA::::::23::0:
fpr:::::::::3A3EF34DFDEDB3B7F3FDF603F83F77129A5EBD85:
@@ -25,113 +24,101 @@ sub:-:4096:1:544B39C9A9141F04:1634912922::::::a::::::23:
fpr:::::::::8BD901490D6EC986D03D6F0D544B39C9A9141F04:
sub:-:4096:1:F45D9443F0A87092:1634912922::::::e::::::23:
fpr:::::::::8CCCB332317324F030A45B19F45D9443F0A87092:
-'''
+"""
-TEST_KEY_FINGERPRINT_HUMAN = \
- '3A3E F34D FDED B3B7 F3FD F603 F83F 7712 9A5E BD85'
+TEST_KEY_FINGERPRINT_HUMAN = (
+ "3A3E F34D FDED B3B7 F3FD F603 F83F 7712 9A5E BD85"
+)
-TEST_KEY_FINGERPRINT_MACHINE = \
- '3A3EF34DFDEDB3B7F3FDF603F83F77129A5EBD85'
+TEST_KEY_FINGERPRINT_MACHINE = "3A3EF34DFDEDB3B7F3FDF603F83F77129A5EBD85"
class TestAptKey:
"""TestAptKey
Class to test apt-key commands
"""
- @mock.patch.object(subp, 'subp', return_value=('fakekey', ''))
- @mock.patch.object(util, 'write_file')
+
+ @mock.patch.object(subp, "subp", return_value=("fakekey", ""))
+ @mock.patch.object(util, "write_file")
def _apt_key_add_success_helper(self, directory, *args, hardened=False):
file = cc_apt_configure.apt_key(
- 'add',
- output_file='my-key',
- data='fakekey',
- hardened=hardened)
- assert file == directory + '/my-key.gpg'
+ "add", output_file="my-key", data="fakekey", hardened=hardened
+ )
+ assert file == directory + "/my-key.gpg"
def test_apt_key_add_success(self):
- """Verify the correct directory path gets returned for unhardened case
- """
- self._apt_key_add_success_helper('/etc/apt/trusted.gpg.d')
+ """Verify the right directory path gets returned for unhardened case"""
+ self._apt_key_add_success_helper("/etc/apt/trusted.gpg.d")
def test_apt_key_add_success_hardened(self):
- """Verify the correct directory path gets returned for hardened case
- """
+ """Verify the right directory path gets returned for hardened case"""
self._apt_key_add_success_helper(
- '/etc/apt/cloud-init.gpg.d',
- hardened=True)
+ "/etc/apt/cloud-init.gpg.d", hardened=True
+ )
def test_apt_key_add_fail_no_file_name(self):
- """Verify that null filename gets handled correctly
- """
- file = cc_apt_configure.apt_key(
- 'add',
- output_file=None,
- data='')
- assert '/dev/null' == file
+ """Verify that null filename gets handled correctly"""
+ file = cc_apt_configure.apt_key("add", output_file=None, data="")
+ assert "/dev/null" == file
def _apt_key_fail_helper(self):
file = cc_apt_configure.apt_key(
- 'add',
- output_file='my-key',
- data='fakekey')
- assert file == '/dev/null'
+ "add", output_file="my-key", data="fakekey"
+ )
+ assert file == "/dev/null"
- @mock.patch.object(subp, 'subp', side_effect=subp.ProcessExecutionError)
+ @mock.patch.object(subp, "subp", side_effect=subp.ProcessExecutionError)
def test_apt_key_add_fail_no_file_name_subproc(self, *args):
- """Verify that bad key value gets handled correctly
- """
+ """Verify that bad key value gets handled correctly"""
self._apt_key_fail_helper()
@mock.patch.object(
- subp, 'subp', side_effect=UnicodeDecodeError('test', b'', 1, 1, ''))
+ subp, "subp", side_effect=UnicodeDecodeError("test", b"", 1, 1, "")
+ )
def test_apt_key_add_fail_no_file_name_unicode(self, *args):
- """Verify that bad key encoding gets handled correctly
- """
+ """Verify that bad key encoding gets handled correctly"""
self._apt_key_fail_helper()
def _apt_key_list_success_helper(self, finger, key, human_output=True):
- @mock.patch.object(os, 'listdir', return_value=('/fake/dir/key.gpg',))
- @mock.patch.object(subp, 'subp', return_value=(key, ''))
+ @mock.patch.object(os, "listdir", return_value=("/fake/dir/key.gpg",))
+ @mock.patch.object(subp, "subp", return_value=(key, ""))
def mocked_list(*a):
- keys = cc_apt_configure.apt_key('list', human_output)
+ keys = cc_apt_configure.apt_key("list", human_output)
assert finger in keys
+
mocked_list()
def test_apt_key_list_success_human(self):
- """Verify expected key output, human
- """
+ """Verify expected key output, human"""
self._apt_key_list_success_helper(
- TEST_KEY_FINGERPRINT_HUMAN,
- TEST_KEY_HUMAN)
+ TEST_KEY_FINGERPRINT_HUMAN, TEST_KEY_HUMAN
+ )
def test_apt_key_list_success_machine(self):
- """Verify expected key output, machine
- """
+ """Verify expected key output, machine"""
self._apt_key_list_success_helper(
- TEST_KEY_FINGERPRINT_MACHINE,
- TEST_KEY_MACHINE, human_output=False)
+ TEST_KEY_FINGERPRINT_MACHINE, TEST_KEY_MACHINE, human_output=False
+ )
- @mock.patch.object(os, 'listdir', return_value=())
- @mock.patch.object(subp, 'subp', return_value=('', ''))
+ @mock.patch.object(os, "listdir", return_value=())
+ @mock.patch.object(subp, "subp", return_value=("", ""))
def test_apt_key_list_fail_no_keys(self, *args):
- """Ensure falsy output for no keys
- """
- keys = cc_apt_configure.apt_key('list')
+ """Ensure falsy output for no keys"""
+ keys = cc_apt_configure.apt_key("list")
assert not keys
- @mock.patch.object(os, 'listdir', return_value=('file_not_gpg_key.txt'))
- @mock.patch.object(subp, 'subp', return_value=('', ''))
+ @mock.patch.object(os, "listdir", return_value="file_not_gpg_key.txt")
+ @mock.patch.object(subp, "subp", return_value=("", ""))
def test_apt_key_list_fail_no_keys_file(self, *args):
"""Ensure non-gpg file is not returned.
apt-key used file extensions for this, so we do too
"""
- assert not cc_apt_configure.apt_key('list')
+ assert not cc_apt_configure.apt_key("list")
- @mock.patch.object(subp, 'subp', side_effect=subp.ProcessExecutionError)
- @mock.patch.object(os, 'listdir', return_value=('bad_gpg_key.gpg'))
+ @mock.patch.object(subp, "subp", side_effect=subp.ProcessExecutionError)
+ @mock.patch.object(os, "listdir", return_value="bad_gpg_key.gpg")
def test_apt_key_list_fail_bad_key_file(self, *args):
- """Ensure bad gpg key doesn't throw exeption.
- """
- assert not cc_apt_configure.apt_key('list')
+ """Ensure bad gpg key doesn't throw exeption."""
+ assert not cc_apt_configure.apt_key("list")
diff --git a/tests/unittests/config/test_apt_source_v1.py b/tests/unittests/config/test_apt_source_v1.py
index 684c2495..fbc2bf45 100644
--- a/tests/unittests/config/test_apt_source_v1.py
+++ b/tests/unittests/config/test_apt_source_v1.py
@@ -6,18 +6,15 @@ This calls all things with v1 format to stress the conversion code on top of
the actually tested code.
"""
import os
+import pathlib
import re
import shutil
import tempfile
-import pathlib
from unittest import mock
from unittest.mock import call
+from cloudinit import gpg, subp, util
from cloudinit.config import cc_apt_configure
-from cloudinit import gpg
-from cloudinit import subp
-from cloudinit import util
-
from tests.unittests.helpers import TestCase
EXPECTEDKEY = """-----BEGIN PGP PUBLIC KEY BLOCK-----
@@ -39,6 +36,7 @@ ADD_APT_REPO_MATCH = r"^[\w-]+:\w"
class FakeDistro(object):
"""Fake Distro helper object"""
+
def update_package_sources(self):
"""Fake update_package_sources helper method"""
return
@@ -46,12 +44,14 @@ class FakeDistro(object):
class FakeDatasource:
"""Fake Datasource helper object"""
+
def __init__(self):
- self.region = 'region'
+ self.region = "region"
class FakeCloud(object):
"""Fake Cloud helper object"""
+
def __init__(self):
self.distro = FakeDistro()
self.datasource = FakeDatasource()
@@ -61,6 +61,7 @@ class TestAptSourceConfig(TestCase):
"""TestAptSourceConfig
Main Class to test apt_source configs
"""
+
release = "fantastic"
def setUp(self):
@@ -73,18 +74,19 @@ class TestAptSourceConfig(TestCase):
self.join = os.path.join
self.matcher = re.compile(ADD_APT_REPO_MATCH).search
# mock fallback filename into writable tmp dir
- self.fallbackfn = os.path.join(self.tmp, "etc/apt/sources.list.d/",
- "cloud_config_sources.list")
+ self.fallbackfn = os.path.join(
+ self.tmp, "etc/apt/sources.list.d/", "cloud_config_sources.list"
+ )
self.fakecloud = FakeCloud()
rpatcher = mock.patch("cloudinit.util.lsb_release")
get_rel = rpatcher.start()
- get_rel.return_value = {'codename': self.release}
+ get_rel.return_value = {"codename": self.release}
self.addCleanup(rpatcher.stop)
apatcher = mock.patch("cloudinit.util.get_dpkg_architecture")
get_arch = apatcher.start()
- get_arch.return_value = 'amd64'
+ get_arch.return_value = "amd64"
self.addCleanup(apatcher.stop)
def _get_default_params(self):
@@ -92,23 +94,27 @@ class TestAptSourceConfig(TestCase):
Get the most basic default mrror and release info to be used in tests
"""
params = {}
- params['RELEASE'] = self.release
- params['MIRROR'] = "http://archive.ubuntu.com/ubuntu"
+ params["RELEASE"] = self.release
+ params["MIRROR"] = "http://archive.ubuntu.com/ubuntu"
return params
def wrapv1conf(self, cfg):
params = self._get_default_params()
# old v1 list format under old keys, but callabe to main handler
# disable source.list rendering and set mirror to avoid other code
- return {'apt_preserve_sources_list': True,
- 'apt_mirror': params['MIRROR'],
- 'apt_sources': cfg}
+ return {
+ "apt_preserve_sources_list": True,
+ "apt_mirror": params["MIRROR"],
+ "apt_sources": cfg,
+ }
def myjoin(self, *args, **kwargs):
"""myjoin - redir into writable tmpdir"""
- if (args[0] == "/etc/apt/sources.list.d/" and
- args[1] == "cloud_config_sources.list" and
- len(args) == 2):
+ if (
+ args[0] == "/etc/apt/sources.list.d/"
+ and args[1] == "cloud_config_sources.list"
+ and len(args) == 2
+ ):
return self.join(self.tmp, args[0].lstrip("/"), args[1])
else:
return self.join(*args, **kwargs)
@@ -124,26 +130,43 @@ class TestAptSourceConfig(TestCase):
self.assertTrue(os.path.isfile(filename))
contents = util.load_file(filename)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", "http://archive.ubuntu.com/ubuntu",
- "karmic-backports",
- "main universe multiverse restricted"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % (
+ "deb",
+ "http://archive.ubuntu.com/ubuntu",
+ "karmic-backports",
+ "main universe multiverse restricted",
+ ),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
def test_apt_src_basic(self):
"""Test deb source string, overwrite mirror and filename"""
- cfg = {'source': ('deb http://archive.ubuntu.com/ubuntu'
- ' karmic-backports'
- ' main universe multiverse restricted'),
- 'filename': self.aptlistfile}
+ cfg = {
+ "source": (
+ "deb http://archive.ubuntu.com/ubuntu"
+ " karmic-backports"
+ " main universe multiverse restricted"
+ ),
+ "filename": self.aptlistfile,
+ }
self.apt_src_basic(self.aptlistfile, [cfg])
def test_apt_src_basic_dict(self):
"""Test deb source string, overwrite mirror and filename (dict)"""
- cfg = {self.aptlistfile: {'source':
- ('deb http://archive.ubuntu.com/ubuntu'
- ' karmic-backports'
- ' main universe multiverse restricted')}}
+ cfg = {
+ self.aptlistfile: {
+ "source": (
+ "deb http://archive.ubuntu.com/ubuntu"
+ " karmic-backports"
+ " main universe multiverse restricted"
+ )
+ }
+ }
self.apt_src_basic(self.aptlistfile, cfg)
def apt_src_basic_tri(self, cfg):
@@ -156,56 +179,99 @@ class TestAptSourceConfig(TestCase):
# extra verify on two extra files of this test
contents = util.load_file(self.aptlistfile2)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", "http://archive.ubuntu.com/ubuntu",
- "precise-backports",
- "main universe multiverse restricted"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % (
+ "deb",
+ "http://archive.ubuntu.com/ubuntu",
+ "precise-backports",
+ "main universe multiverse restricted",
+ ),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
contents = util.load_file(self.aptlistfile3)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", "http://archive.ubuntu.com/ubuntu",
- "lucid-backports",
- "main universe multiverse restricted"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % (
+ "deb",
+ "http://archive.ubuntu.com/ubuntu",
+ "lucid-backports",
+ "main universe multiverse restricted",
+ ),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
def test_apt_src_basic_tri(self):
"""Test Fix three deb source string with filenames"""
- cfg1 = {'source': ('deb http://archive.ubuntu.com/ubuntu'
- ' karmic-backports'
- ' main universe multiverse restricted'),
- 'filename': self.aptlistfile}
- cfg2 = {'source': ('deb http://archive.ubuntu.com/ubuntu'
- ' precise-backports'
- ' main universe multiverse restricted'),
- 'filename': self.aptlistfile2}
- cfg3 = {'source': ('deb http://archive.ubuntu.com/ubuntu'
- ' lucid-backports'
- ' main universe multiverse restricted'),
- 'filename': self.aptlistfile3}
+ cfg1 = {
+ "source": (
+ "deb http://archive.ubuntu.com/ubuntu"
+ " karmic-backports"
+ " main universe multiverse restricted"
+ ),
+ "filename": self.aptlistfile,
+ }
+ cfg2 = {
+ "source": (
+ "deb http://archive.ubuntu.com/ubuntu"
+ " precise-backports"
+ " main universe multiverse restricted"
+ ),
+ "filename": self.aptlistfile2,
+ }
+ cfg3 = {
+ "source": (
+ "deb http://archive.ubuntu.com/ubuntu"
+ " lucid-backports"
+ " main universe multiverse restricted"
+ ),
+ "filename": self.aptlistfile3,
+ }
self.apt_src_basic_tri([cfg1, cfg2, cfg3])
def test_apt_src_basic_dict_tri(self):
"""Test Fix three deb source string with filenames (dict)"""
- cfg = {self.aptlistfile: {'source':
- ('deb http://archive.ubuntu.com/ubuntu'
- ' karmic-backports'
- ' main universe multiverse restricted')},
- self.aptlistfile2: {'source':
- ('deb http://archive.ubuntu.com/ubuntu'
- ' precise-backports'
- ' main universe multiverse restricted')},
- self.aptlistfile3: {'source':
- ('deb http://archive.ubuntu.com/ubuntu'
- ' lucid-backports'
- ' main universe multiverse restricted')}}
+ cfg = {
+ self.aptlistfile: {
+ "source": (
+ "deb http://archive.ubuntu.com/ubuntu"
+ " karmic-backports"
+ " main universe multiverse restricted"
+ )
+ },
+ self.aptlistfile2: {
+ "source": (
+ "deb http://archive.ubuntu.com/ubuntu"
+ " precise-backports"
+ " main universe multiverse restricted"
+ )
+ },
+ self.aptlistfile3: {
+ "source": (
+ "deb http://archive.ubuntu.com/ubuntu"
+ " lucid-backports"
+ " main universe multiverse restricted"
+ )
+ },
+ }
self.apt_src_basic_tri(cfg)
def test_apt_src_basic_nofn(self):
"""Test Fix three deb source string without filenames (dict)"""
- cfg = {'source': ('deb http://archive.ubuntu.com/ubuntu'
- ' karmic-backports'
- ' main universe multiverse restricted')}
- with mock.patch.object(os.path, 'join', side_effect=self.myjoin):
+ cfg = {
+ "source": (
+ "deb http://archive.ubuntu.com/ubuntu"
+ " karmic-backports"
+ " main universe multiverse restricted"
+ )
+ }
+ with mock.patch.object(os.path, "join", side_effect=self.myjoin):
self.apt_src_basic(self.fallbackfn, [cfg])
def apt_src_replacement(self, filename, cfg):
@@ -219,15 +285,21 @@ class TestAptSourceConfig(TestCase):
self.assertTrue(os.path.isfile(filename))
contents = util.load_file(filename)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", params['MIRROR'], params['RELEASE'],
- "multiverse"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % ("deb", params["MIRROR"], params["RELEASE"], "multiverse"),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
def test_apt_src_replace(self):
"""Test Autoreplacement of MIRROR and RELEASE in source specs"""
- cfg = {'source': 'deb $MIRROR $RELEASE multiverse',
- 'filename': self.aptlistfile}
+ cfg = {
+ "source": "deb $MIRROR $RELEASE multiverse",
+ "filename": self.aptlistfile,
+ }
self.apt_src_replacement(self.aptlistfile, [cfg])
def apt_src_replace_tri(self, cfg):
@@ -240,38 +312,56 @@ class TestAptSourceConfig(TestCase):
# extra verify on two extra files of this test
params = self._get_default_params()
contents = util.load_file(self.aptlistfile2)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", params['MIRROR'], params['RELEASE'],
- "main"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % ("deb", params["MIRROR"], params["RELEASE"], "main"),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
contents = util.load_file(self.aptlistfile3)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", params['MIRROR'], params['RELEASE'],
- "universe"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % ("deb", params["MIRROR"], params["RELEASE"], "universe"),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
def test_apt_src_replace_tri(self):
"""Test triple Autoreplacement of MIRROR and RELEASE in source specs"""
- cfg1 = {'source': 'deb $MIRROR $RELEASE multiverse',
- 'filename': self.aptlistfile}
- cfg2 = {'source': 'deb $MIRROR $RELEASE main',
- 'filename': self.aptlistfile2}
- cfg3 = {'source': 'deb $MIRROR $RELEASE universe',
- 'filename': self.aptlistfile3}
+ cfg1 = {
+ "source": "deb $MIRROR $RELEASE multiverse",
+ "filename": self.aptlistfile,
+ }
+ cfg2 = {
+ "source": "deb $MIRROR $RELEASE main",
+ "filename": self.aptlistfile2,
+ }
+ cfg3 = {
+ "source": "deb $MIRROR $RELEASE universe",
+ "filename": self.aptlistfile3,
+ }
self.apt_src_replace_tri([cfg1, cfg2, cfg3])
def test_apt_src_replace_dict_tri(self):
"""Test triple Autoreplacement in source specs (dict)"""
- cfg = {self.aptlistfile: {'source': 'deb $MIRROR $RELEASE multiverse'},
- 'notused': {'source': 'deb $MIRROR $RELEASE main',
- 'filename': self.aptlistfile2},
- self.aptlistfile3: {'source': 'deb $MIRROR $RELEASE universe'}}
+ cfg = {
+ self.aptlistfile: {"source": "deb $MIRROR $RELEASE multiverse"},
+ "notused": {
+ "source": "deb $MIRROR $RELEASE main",
+ "filename": self.aptlistfile2,
+ },
+ self.aptlistfile3: {"source": "deb $MIRROR $RELEASE universe"},
+ }
self.apt_src_replace_tri(cfg)
def test_apt_src_replace_nofn(self):
"""Test Autoreplacement of MIRROR and RELEASE in source specs nofile"""
- cfg = {'source': 'deb $MIRROR $RELEASE multiverse'}
- with mock.patch.object(os.path, 'join', side_effect=self.myjoin):
+ cfg = {"source": "deb $MIRROR $RELEASE multiverse"}
+ with mock.patch.object(os.path, "join", side_effect=self.myjoin):
self.apt_src_replacement(self.fallbackfn, [cfg])
def apt_src_keyid(self, filename, cfg, keynum):
@@ -280,12 +370,12 @@ class TestAptSourceConfig(TestCase):
"""
cfg = self.wrapv1conf(cfg)
- with mock.patch.object(cc_apt_configure, 'add_apt_key') as mockobj:
+ with mock.patch.object(cc_apt_configure, "add_apt_key") as mockobj:
cc_apt_configure.handle("test", cfg, self.fakecloud, None, None)
# check if it added the right number of keys
calls = []
- sources = cfg['apt']['sources']
+ sources = cfg["apt"]["sources"]
for src in sources:
print(sources[src])
calls.append(call(sources[src], None))
@@ -295,68 +385,109 @@ class TestAptSourceConfig(TestCase):
self.assertTrue(os.path.isfile(filename))
contents = util.load_file(filename)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb",
- ('http://ppa.launchpad.net/smoser/'
- 'cloud-init-test/ubuntu'),
- "xenial", "main"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % (
+ "deb",
+ "http://ppa.launchpad.net/smoser/cloud-init-test/ubuntu",
+ "xenial",
+ "main",
+ ),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
def test_apt_src_keyid(self):
"""Test specification of a source + keyid with filename being set"""
- cfg = {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial main'),
- 'keyid': "03683F77",
- 'filename': self.aptlistfile}
+ cfg = {
+ "source": (
+ "deb "
+ "http://ppa.launchpad.net/"
+ "smoser/cloud-init-test/ubuntu"
+ " xenial main"
+ ),
+ "keyid": "03683F77",
+ "filename": self.aptlistfile,
+ }
self.apt_src_keyid(self.aptlistfile, [cfg], 1)
def test_apt_src_keyid_tri(self):
"""Test 3x specification of a source + keyid with filename being set"""
- cfg1 = {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial main'),
- 'keyid': "03683F77",
- 'filename': self.aptlistfile}
- cfg2 = {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial universe'),
- 'keyid': "03683F77",
- 'filename': self.aptlistfile2}
- cfg3 = {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial multiverse'),
- 'keyid': "03683F77",
- 'filename': self.aptlistfile3}
+ cfg1 = {
+ "source": (
+ "deb "
+ "http://ppa.launchpad.net/"
+ "smoser/cloud-init-test/ubuntu"
+ " xenial main"
+ ),
+ "keyid": "03683F77",
+ "filename": self.aptlistfile,
+ }
+ cfg2 = {
+ "source": (
+ "deb "
+ "http://ppa.launchpad.net/"
+ "smoser/cloud-init-test/ubuntu"
+ " xenial universe"
+ ),
+ "keyid": "03683F77",
+ "filename": self.aptlistfile2,
+ }
+ cfg3 = {
+ "source": (
+ "deb "
+ "http://ppa.launchpad.net/"
+ "smoser/cloud-init-test/ubuntu"
+ " xenial multiverse"
+ ),
+ "keyid": "03683F77",
+ "filename": self.aptlistfile3,
+ }
self.apt_src_keyid(self.aptlistfile, [cfg1, cfg2, cfg3], 3)
contents = util.load_file(self.aptlistfile2)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb",
- ('http://ppa.launchpad.net/smoser/'
- 'cloud-init-test/ubuntu'),
- "xenial", "universe"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % (
+ "deb",
+ "http://ppa.launchpad.net/smoser/cloud-init-test/ubuntu",
+ "xenial",
+ "universe",
+ ),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
contents = util.load_file(self.aptlistfile3)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb",
- ('http://ppa.launchpad.net/smoser/'
- 'cloud-init-test/ubuntu'),
- "xenial", "multiverse"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % (
+ "deb",
+ "http://ppa.launchpad.net/smoser/cloud-init-test/ubuntu",
+ "xenial",
+ "multiverse",
+ ),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
def test_apt_src_keyid_nofn(self):
"""Test specification of a source + keyid without filename being set"""
- cfg = {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial main'),
- 'keyid': "03683F77"}
- with mock.patch.object(os.path, 'join', side_effect=self.myjoin):
+ cfg = {
+ "source": (
+ "deb "
+ "http://ppa.launchpad.net/"
+ "smoser/cloud-init-test/ubuntu"
+ " xenial main"
+ ),
+ "keyid": "03683F77",
+ }
+ with mock.patch.object(os.path, "join", side_effect=self.myjoin):
self.apt_src_keyid(self.fallbackfn, [cfg], 1)
def apt_src_key(self, filename, cfg):
@@ -365,11 +496,11 @@ class TestAptSourceConfig(TestCase):
"""
cfg = self.wrapv1conf([cfg])
- with mock.patch.object(cc_apt_configure, 'add_apt_key') as mockobj:
+ with mock.patch.object(cc_apt_configure, "add_apt_key") as mockobj:
cc_apt_configure.handle("test", cfg, self.fakecloud, None, None)
# check if it added the right amount of keys
- sources = cfg['apt']['sources']
+ sources = cfg["apt"]["sources"]
calls = []
for src in sources:
print(sources[src])
@@ -380,46 +511,63 @@ class TestAptSourceConfig(TestCase):
self.assertTrue(os.path.isfile(filename))
contents = util.load_file(filename)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb",
- ('http://ppa.launchpad.net/smoser/'
- 'cloud-init-test/ubuntu'),
- "xenial", "main"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % (
+ "deb",
+ "http://ppa.launchpad.net/smoser/cloud-init-test/ubuntu",
+ "xenial",
+ "main",
+ ),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
def test_apt_src_key(self):
"""Test specification of a source + key with filename being set"""
- cfg = {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial main'),
- 'key': "fakekey 4321",
- 'filename': self.aptlistfile}
+ cfg = {
+ "source": (
+ "deb "
+ "http://ppa.launchpad.net/"
+ "smoser/cloud-init-test/ubuntu"
+ " xenial main"
+ ),
+ "key": "fakekey 4321",
+ "filename": self.aptlistfile,
+ }
self.apt_src_key(self.aptlistfile, cfg)
def test_apt_src_key_nofn(self):
"""Test specification of a source + key without filename being set"""
- cfg = {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial main'),
- 'key': "fakekey 4321"}
- with mock.patch.object(os.path, 'join', side_effect=self.myjoin):
+ cfg = {
+ "source": (
+ "deb "
+ "http://ppa.launchpad.net/"
+ "smoser/cloud-init-test/ubuntu"
+ " xenial main"
+ ),
+ "key": "fakekey 4321",
+ }
+ with mock.patch.object(os.path, "join", side_effect=self.myjoin):
self.apt_src_key(self.fallbackfn, cfg)
def test_apt_src_keyonly(self):
"""Test specifying key without source"""
- cfg = {'key': "fakekey 4242",
- 'filename': self.aptlistfile}
+ cfg = {"key": "fakekey 4242", "filename": self.aptlistfile}
cfg = self.wrapv1conf([cfg])
- with mock.patch.object(cc_apt_configure, 'apt_key') as mockobj:
+ with mock.patch.object(cc_apt_configure, "apt_key") as mockobj:
cc_apt_configure.handle("test", cfg, self.fakecloud, None, None)
- calls = (call(
- 'add',
- output_file=pathlib.Path(self.aptlistfile).stem,
- data='fakekey 4242',
- hardened=False),)
+ calls = (
+ call(
+ "add",
+ output_file=pathlib.Path(self.aptlistfile).stem,
+ data="fakekey 4242",
+ hardened=False,
+ ),
+ )
mockobj.assert_has_calls(calls, any_order=True)
# filename should be ignored on key only
@@ -427,25 +575,25 @@ class TestAptSourceConfig(TestCase):
def test_apt_src_keyidonly(self):
"""Test specification of a keyid without source"""
- cfg = {'keyid': "03683F77",
- 'filename': self.aptlistfile}
+ cfg = {"keyid": "03683F77", "filename": self.aptlistfile}
cfg = self.wrapv1conf([cfg])
- with mock.patch.object(subp, 'subp',
- return_value=('fakekey 1212', '')):
- with mock.patch.object(cc_apt_configure, 'apt_key') as mockobj:
+ with mock.patch.object(
+ subp, "subp", return_value=("fakekey 1212", "")
+ ):
+ with mock.patch.object(cc_apt_configure, "apt_key") as mockobj:
cc_apt_configure.handle(
- "test",
- cfg,
- self.fakecloud,
- None,
- None)
-
- calls = (call(
- 'add',
- output_file=pathlib.Path(self.aptlistfile).stem,
- data='fakekey 1212',
- hardened=False),)
+ "test", cfg, self.fakecloud, None, None
+ )
+
+ calls = (
+ call(
+ "add",
+ output_file=pathlib.Path(self.aptlistfile).stem,
+ data="fakekey 1212",
+ hardened=False,
+ ),
+ )
mockobj.assert_has_calls(calls, any_order=True)
# filename should be ignored on key only
@@ -457,20 +605,21 @@ class TestAptSourceConfig(TestCase):
up to addition of the key (add_apt_key_raw mocked to keep the
environment as is)
"""
- key = cfg['keyid']
- keyserver = cfg.get('keyserver', 'keyserver.ubuntu.com')
+ key = cfg["keyid"]
+ keyserver = cfg.get("keyserver", "keyserver.ubuntu.com")
cfg = self.wrapv1conf([cfg])
- with mock.patch.object(cc_apt_configure, 'add_apt_key_raw') as mockkey:
- with mock.patch.object(gpg, 'getkeybyid',
- return_value=expectedkey) as mockgetkey:
- cc_apt_configure.handle("test", cfg, self.fakecloud,
- None, None)
+ with mock.patch.object(cc_apt_configure, "add_apt_key_raw") as mockkey:
+ with mock.patch.object(
+ gpg, "getkeybyid", return_value=expectedkey
+ ) as mockgetkey:
+ cc_apt_configure.handle(
+ "test", cfg, self.fakecloud, None, None
+ )
if is_hardened is not None:
mockkey.assert_called_with(
- expectedkey,
- self.aptlistfile,
- hardened=is_hardened)
+ expectedkey, self.aptlistfile, hardened=is_hardened
+ )
else:
mockkey.assert_called_with(expectedkey, self.aptlistfile)
mockgetkey.assert_called_with(key, keyserver)
@@ -481,62 +630,77 @@ class TestAptSourceConfig(TestCase):
def test_apt_src_keyid_real(self):
"""test_apt_src_keyid_real - Test keyid including key add"""
keyid = "03683F77"
- cfg = {'keyid': keyid,
- 'filename': self.aptlistfile}
+ cfg = {"keyid": keyid, "filename": self.aptlistfile}
self.apt_src_keyid_real(cfg, EXPECTEDKEY, is_hardened=False)
def test_apt_src_longkeyid_real(self):
"""test_apt_src_longkeyid_real - Test long keyid including key add"""
keyid = "B59D 5F15 97A5 04B7 E230 6DCA 0620 BBCF 0368 3F77"
- cfg = {'keyid': keyid,
- 'filename': self.aptlistfile}
+ cfg = {"keyid": keyid, "filename": self.aptlistfile}
self.apt_src_keyid_real(cfg, EXPECTEDKEY, is_hardened=False)
def test_apt_src_longkeyid_ks_real(self):
"""test_apt_src_longkeyid_ks_real - Test long keyid from other ks"""
keyid = "B59D 5F15 97A5 04B7 E230 6DCA 0620 BBCF 0368 3F77"
- cfg = {'keyid': keyid,
- 'keyserver': 'keys.gnupg.net',
- 'filename': self.aptlistfile}
+ cfg = {
+ "keyid": keyid,
+ "keyserver": "keys.gnupg.net",
+ "filename": self.aptlistfile,
+ }
self.apt_src_keyid_real(cfg, EXPECTEDKEY, is_hardened=False)
def test_apt_src_ppa(self):
"""Test adding a ppa"""
- cfg = {'source': 'ppa:smoser/cloud-init-test',
- 'filename': self.aptlistfile}
+ cfg = {
+ "source": "ppa:smoser/cloud-init-test",
+ "filename": self.aptlistfile,
+ }
cfg = self.wrapv1conf([cfg])
- with mock.patch.object(subp, 'subp') as mockobj:
+ with mock.patch.object(subp, "subp") as mockobj:
cc_apt_configure.handle("test", cfg, self.fakecloud, None, None)
- mockobj.assert_called_once_with(['add-apt-repository',
- 'ppa:smoser/cloud-init-test'],
- target=None)
+ mockobj.assert_called_once_with(
+ ["add-apt-repository", "ppa:smoser/cloud-init-test"], target=None
+ )
# adding ppa should ignore filename (uses add-apt-repository)
self.assertFalse(os.path.isfile(self.aptlistfile))
def test_apt_src_ppa_tri(self):
"""Test adding three ppa's"""
- cfg1 = {'source': 'ppa:smoser/cloud-init-test',
- 'filename': self.aptlistfile}
- cfg2 = {'source': 'ppa:smoser/cloud-init-test2',
- 'filename': self.aptlistfile2}
- cfg3 = {'source': 'ppa:smoser/cloud-init-test3',
- 'filename': self.aptlistfile3}
+ cfg1 = {
+ "source": "ppa:smoser/cloud-init-test",
+ "filename": self.aptlistfile,
+ }
+ cfg2 = {
+ "source": "ppa:smoser/cloud-init-test2",
+ "filename": self.aptlistfile2,
+ }
+ cfg3 = {
+ "source": "ppa:smoser/cloud-init-test3",
+ "filename": self.aptlistfile3,
+ }
cfg = self.wrapv1conf([cfg1, cfg2, cfg3])
- with mock.patch.object(subp, 'subp') as mockobj:
- cc_apt_configure.handle("test", cfg, self.fakecloud,
- None, None)
- calls = [call(['add-apt-repository', 'ppa:smoser/cloud-init-test'],
- target=None),
- call(['add-apt-repository', 'ppa:smoser/cloud-init-test2'],
- target=None),
- call(['add-apt-repository', 'ppa:smoser/cloud-init-test3'],
- target=None)]
+ with mock.patch.object(subp, "subp") as mockobj:
+ cc_apt_configure.handle("test", cfg, self.fakecloud, None, None)
+ calls = [
+ call(
+ ["add-apt-repository", "ppa:smoser/cloud-init-test"],
+ target=None,
+ ),
+ call(
+ ["add-apt-repository", "ppa:smoser/cloud-init-test2"],
+ target=None,
+ ),
+ call(
+ ["add-apt-repository", "ppa:smoser/cloud-init-test3"],
+ target=None,
+ ),
+ ]
mockobj.assert_has_calls(calls, any_order=True)
# adding ppa should ignore all filenames (uses add-apt-repository)
@@ -546,43 +710,59 @@ class TestAptSourceConfig(TestCase):
def test_convert_to_new_format(self):
"""Test the conversion of old to new format"""
- cfg1 = {'source': 'deb $MIRROR $RELEASE multiverse',
- 'filename': self.aptlistfile}
- cfg2 = {'source': 'deb $MIRROR $RELEASE main',
- 'filename': self.aptlistfile2}
- cfg3 = {'source': 'deb $MIRROR $RELEASE universe',
- 'filename': self.aptlistfile3}
- cfg = {'apt_sources': [cfg1, cfg2, cfg3]}
- checkcfg = {self.aptlistfile: {'filename': self.aptlistfile,
- 'source': 'deb $MIRROR $RELEASE '
- 'multiverse'},
- self.aptlistfile2: {'filename': self.aptlistfile2,
- 'source': 'deb $MIRROR $RELEASE main'},
- self.aptlistfile3: {'filename': self.aptlistfile3,
- 'source': 'deb $MIRROR $RELEASE '
- 'universe'}}
+ cfg1 = {
+ "source": "deb $MIRROR $RELEASE multiverse",
+ "filename": self.aptlistfile,
+ }
+ cfg2 = {
+ "source": "deb $MIRROR $RELEASE main",
+ "filename": self.aptlistfile2,
+ }
+ cfg3 = {
+ "source": "deb $MIRROR $RELEASE universe",
+ "filename": self.aptlistfile3,
+ }
+ cfg = {"apt_sources": [cfg1, cfg2, cfg3]}
+ checkcfg = {
+ self.aptlistfile: {
+ "filename": self.aptlistfile,
+ "source": "deb $MIRROR $RELEASE multiverse",
+ },
+ self.aptlistfile2: {
+ "filename": self.aptlistfile2,
+ "source": "deb $MIRROR $RELEASE main",
+ },
+ self.aptlistfile3: {
+ "filename": self.aptlistfile3,
+ "source": "deb $MIRROR $RELEASE universe",
+ },
+ }
newcfg = cc_apt_configure.convert_to_v3_apt_format(cfg)
- self.assertEqual(newcfg['apt']['sources'], checkcfg)
+ self.assertEqual(newcfg["apt"]["sources"], checkcfg)
# convert again, should stay the same
newcfg2 = cc_apt_configure.convert_to_v3_apt_format(newcfg)
- self.assertEqual(newcfg2['apt']['sources'], checkcfg)
+ self.assertEqual(newcfg2["apt"]["sources"], checkcfg)
# should work without raising an exception
cc_apt_configure.convert_to_v3_apt_format({})
with self.assertRaises(ValueError):
- cc_apt_configure.convert_to_v3_apt_format({'apt_sources': 5})
+ cc_apt_configure.convert_to_v3_apt_format({"apt_sources": 5})
def test_convert_to_new_format_collision(self):
"""Test the conversion of old to new format with collisions
- That matches e.g. the MAAS case specifying old and new config"""
- cfg_1_and_3 = {'apt': {'proxy': 'http://192.168.122.1:8000/'},
- 'apt_proxy': 'http://192.168.122.1:8000/'}
- cfg_3_only = {'apt': {'proxy': 'http://192.168.122.1:8000/'}}
- cfgconflict = {'apt': {'proxy': 'http://192.168.122.1:8000/'},
- 'apt_proxy': 'ftp://192.168.122.1:8000/'}
+ That matches e.g. the MAAS case specifying old and new config"""
+ cfg_1_and_3 = {
+ "apt": {"proxy": "http://192.168.122.1:8000/"},
+ "apt_proxy": "http://192.168.122.1:8000/",
+ }
+ cfg_3_only = {"apt": {"proxy": "http://192.168.122.1:8000/"}}
+ cfgconflict = {
+ "apt": {"proxy": "http://192.168.122.1:8000/"},
+ "apt_proxy": "ftp://192.168.122.1:8000/",
+ }
# collision (equal)
newcfg = cc_apt_configure.convert_to_v3_apt_format(cfg_1_and_3)
@@ -596,22 +776,34 @@ class TestAptSourceConfig(TestCase):
cc_apt_configure.convert_to_v3_apt_format(cfgconflict)
def test_convert_to_new_format_dict_collision(self):
- cfg1 = {'source': 'deb $MIRROR $RELEASE multiverse',
- 'filename': self.aptlistfile}
- cfg2 = {'source': 'deb $MIRROR $RELEASE main',
- 'filename': self.aptlistfile2}
- cfg3 = {'source': 'deb $MIRROR $RELEASE universe',
- 'filename': self.aptlistfile3}
- fullv3 = {self.aptlistfile: {'filename': self.aptlistfile,
- 'source': 'deb $MIRROR $RELEASE '
- 'multiverse'},
- self.aptlistfile2: {'filename': self.aptlistfile2,
- 'source': 'deb $MIRROR $RELEASE main'},
- self.aptlistfile3: {'filename': self.aptlistfile3,
- 'source': 'deb $MIRROR $RELEASE '
- 'universe'}}
- cfg_3_only = {'apt': {'sources': fullv3}}
- cfg_1_and_3 = {'apt_sources': [cfg1, cfg2, cfg3]}
+ cfg1 = {
+ "source": "deb $MIRROR $RELEASE multiverse",
+ "filename": self.aptlistfile,
+ }
+ cfg2 = {
+ "source": "deb $MIRROR $RELEASE main",
+ "filename": self.aptlistfile2,
+ }
+ cfg3 = {
+ "source": "deb $MIRROR $RELEASE universe",
+ "filename": self.aptlistfile3,
+ }
+ fullv3 = {
+ self.aptlistfile: {
+ "filename": self.aptlistfile,
+ "source": "deb $MIRROR $RELEASE multiverse",
+ },
+ self.aptlistfile2: {
+ "filename": self.aptlistfile2,
+ "source": "deb $MIRROR $RELEASE main",
+ },
+ self.aptlistfile3: {
+ "filename": self.aptlistfile3,
+ "source": "deb $MIRROR $RELEASE universe",
+ },
+ }
+ cfg_3_only = {"apt": {"sources": fullv3}}
+ cfg_1_and_3 = {"apt_sources": [cfg1, cfg2, cfg3]}
cfg_1_and_3.update(cfg_3_only)
# collision (equal, so ok to remove)
@@ -621,27 +813,36 @@ class TestAptSourceConfig(TestCase):
newcfg = cc_apt_configure.convert_to_v3_apt_format(cfg_3_only)
self.assertEqual(newcfg, cfg_3_only)
- diff = {self.aptlistfile: {'filename': self.aptlistfile,
- 'source': 'deb $MIRROR $RELEASE '
- 'DIFFERENTVERSE'},
- self.aptlistfile2: {'filename': self.aptlistfile2,
- 'source': 'deb $MIRROR $RELEASE main'},
- self.aptlistfile3: {'filename': self.aptlistfile3,
- 'source': 'deb $MIRROR $RELEASE '
- 'universe'}}
- cfg_3_only = {'apt': {'sources': diff}}
- cfg_1_and_3_different = {'apt_sources': [cfg1, cfg2, cfg3]}
+ diff = {
+ self.aptlistfile: {
+ "filename": self.aptlistfile,
+ "source": "deb $MIRROR $RELEASE DIFFERENTVERSE",
+ },
+ self.aptlistfile2: {
+ "filename": self.aptlistfile2,
+ "source": "deb $MIRROR $RELEASE main",
+ },
+ self.aptlistfile3: {
+ "filename": self.aptlistfile3,
+ "source": "deb $MIRROR $RELEASE universe",
+ },
+ }
+ cfg_3_only = {"apt": {"sources": diff}}
+ cfg_1_and_3_different = {"apt_sources": [cfg1, cfg2, cfg3]}
cfg_1_and_3_different.update(cfg_3_only)
# collision (unequal by dict having a different entry)
with self.assertRaises(ValueError):
cc_apt_configure.convert_to_v3_apt_format(cfg_1_and_3_different)
- missing = {self.aptlistfile: {'filename': self.aptlistfile,
- 'source': 'deb $MIRROR $RELEASE '
- 'multiverse'}}
- cfg_3_only = {'apt': {'sources': missing}}
- cfg_1_and_3_missing = {'apt_sources': [cfg1, cfg2, cfg3]}
+ missing = {
+ self.aptlistfile: {
+ "filename": self.aptlistfile,
+ "source": "deb $MIRROR $RELEASE multiverse",
+ }
+ }
+ cfg_3_only = {"apt": {"sources": missing}}
+ cfg_1_and_3_missing = {"apt_sources": [cfg1, cfg2, cfg3]}
cfg_1_and_3_missing.update(cfg_3_only)
# collision (unequal by dict missing an entry)
with self.assertRaises(ValueError):
diff --git a/tests/unittests/config/test_apt_source_v3.py b/tests/unittests/config/test_apt_source_v3.py
index 0b78037e..75adc647 100644
--- a/tests/unittests/config/test_apt_source_v3.py
+++ b/tests/unittests/config/test_apt_source_v3.py
@@ -6,21 +6,17 @@ This tries to call all in the new v3 format and cares about new features
"""
import glob
import os
+import pathlib
import re
import shutil
import socket
import tempfile
-import pathlib
-
from unittest import TestCase, mock
from unittest.mock import call
-from cloudinit import gpg
-from cloudinit import subp
-from cloudinit import util
+from cloudinit import gpg, subp, util
from cloudinit.config import cc_apt_configure
from tests.unittests import helpers as t_help
-
from tests.unittests.util import get_cloud
EXPECTEDKEY = """-----BEGIN PGP PUBLIC KEY BLOCK-----
@@ -42,18 +38,23 @@ ADD_APT_REPO_MATCH = r"^[\w-]+:\w"
TARGET = None
MOCK_LSB_RELEASE_DATA = {
- 'id': 'Ubuntu', 'description': 'Ubuntu 18.04.1 LTS',
- 'release': '18.04', 'codename': 'bionic'}
+ "id": "Ubuntu",
+ "description": "Ubuntu 18.04.1 LTS",
+ "release": "18.04",
+ "codename": "bionic",
+}
class FakeDatasource:
"""Fake Datasource helper object"""
+
def __init__(self):
- self.region = 'region'
+ self.region = "region"
class FakeCloud:
"""Fake Cloud helper object"""
+
def __init__(self):
self.datasource = FakeDatasource()
@@ -62,6 +63,7 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
"""TestAptSourceConfig
Main Class to test apt configs
"""
+
def setUp(self):
super(TestAptSourceConfig, self).setUp()
self.tmp = tempfile.mkdtemp()
@@ -74,12 +76,14 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
self.join = os.path.join
self.matcher = re.compile(ADD_APT_REPO_MATCH).search
self.add_patch(
- 'cloudinit.config.cc_apt_configure.util.lsb_release',
- 'm_lsb_release', return_value=MOCK_LSB_RELEASE_DATA.copy())
+ "cloudinit.config.cc_apt_configure.util.lsb_release",
+ "m_lsb_release",
+ return_value=MOCK_LSB_RELEASE_DATA.copy(),
+ )
@staticmethod
def _add_apt_sources(*args, **kwargs):
- with mock.patch.object(cc_apt_configure, 'update_packages'):
+ with mock.patch.object(cc_apt_configure, "update_packages"):
cc_apt_configure.add_apt_sources(*args, **kwargs)
@staticmethod
@@ -88,17 +92,20 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
Get the most basic default mrror and release info to be used in tests
"""
params = {}
- params['RELEASE'] = MOCK_LSB_RELEASE_DATA['release']
- arch = 'amd64'
- params['MIRROR'] = cc_apt_configure.\
- get_default_mirrors(arch)["PRIMARY"]
+ params["RELEASE"] = MOCK_LSB_RELEASE_DATA["release"]
+ arch = "amd64"
+ params["MIRROR"] = cc_apt_configure.get_default_mirrors(arch)[
+ "PRIMARY"
+ ]
return params
def _myjoin(self, *args, **kwargs):
"""_myjoin - redir into writable tmpdir"""
- if (args[0] == "/etc/apt/sources.list.d/" and
- args[1] == "cloud_config_sources.list" and
- len(args) == 2):
+ if (
+ args[0] == "/etc/apt/sources.list.d/"
+ and args[1] == "cloud_config_sources.list"
+ and len(args) == 2
+ ):
return self.join(self.tmp, args[0].lstrip("/"), args[1])
else:
return self.join(*args, **kwargs)
@@ -109,81 +116,131 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
"""
params = self._get_default_params()
- self._add_apt_sources(cfg, TARGET, template_params=params,
- aa_repo_match=self.matcher)
+ self._add_apt_sources(
+ cfg, TARGET, template_params=params, aa_repo_match=self.matcher
+ )
self.assertTrue(os.path.isfile(filename))
contents = util.load_file(filename)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", "http://test.ubuntu.com/ubuntu",
- "karmic-backports",
- "main universe multiverse restricted"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % (
+ "deb",
+ "http://test.ubuntu.com/ubuntu",
+ "karmic-backports",
+ "main universe multiverse restricted",
+ ),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
def test_apt_v3_src_basic(self):
"""test_apt_v3_src_basic - Test fix deb source string"""
- cfg = {self.aptlistfile: {'source':
- ('deb http://test.ubuntu.com/ubuntu'
- ' karmic-backports'
- ' main universe multiverse restricted')}}
+ cfg = {
+ self.aptlistfile: {
+ "source": (
+ "deb http://test.ubuntu.com/ubuntu"
+ " karmic-backports"
+ " main universe multiverse restricted"
+ )
+ }
+ }
self._apt_src_basic(self.aptlistfile, cfg)
def test_apt_v3_src_basic_tri(self):
"""test_apt_v3_src_basic_tri - Test multiple fix deb source strings"""
- cfg = {self.aptlistfile: {'source':
- ('deb http://test.ubuntu.com/ubuntu'
- ' karmic-backports'
- ' main universe multiverse restricted')},
- self.aptlistfile2: {'source':
- ('deb http://test.ubuntu.com/ubuntu'
- ' precise-backports'
- ' main universe multiverse restricted')},
- self.aptlistfile3: {'source':
- ('deb http://test.ubuntu.com/ubuntu'
- ' lucid-backports'
- ' main universe multiverse restricted')}}
+ cfg = {
+ self.aptlistfile: {
+ "source": (
+ "deb http://test.ubuntu.com/ubuntu"
+ " karmic-backports"
+ " main universe multiverse restricted"
+ )
+ },
+ self.aptlistfile2: {
+ "source": (
+ "deb http://test.ubuntu.com/ubuntu"
+ " precise-backports"
+ " main universe multiverse restricted"
+ )
+ },
+ self.aptlistfile3: {
+ "source": (
+ "deb http://test.ubuntu.com/ubuntu"
+ " lucid-backports"
+ " main universe multiverse restricted"
+ )
+ },
+ }
self._apt_src_basic(self.aptlistfile, cfg)
# extra verify on two extra files of this test
contents = util.load_file(self.aptlistfile2)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", "http://test.ubuntu.com/ubuntu",
- "precise-backports",
- "main universe multiverse restricted"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % (
+ "deb",
+ "http://test.ubuntu.com/ubuntu",
+ "precise-backports",
+ "main universe multiverse restricted",
+ ),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
contents = util.load_file(self.aptlistfile3)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", "http://test.ubuntu.com/ubuntu",
- "lucid-backports",
- "main universe multiverse restricted"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % (
+ "deb",
+ "http://test.ubuntu.com/ubuntu",
+ "lucid-backports",
+ "main universe multiverse restricted",
+ ),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
def _apt_src_replacement(self, filename, cfg):
"""apt_src_replace
Test Autoreplacement of MIRROR and RELEASE in source specs
"""
params = self._get_default_params()
- self._add_apt_sources(cfg, TARGET, template_params=params,
- aa_repo_match=self.matcher)
+ self._add_apt_sources(
+ cfg, TARGET, template_params=params, aa_repo_match=self.matcher
+ )
self.assertTrue(os.path.isfile(filename))
contents = util.load_file(filename)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", params['MIRROR'], params['RELEASE'],
- "multiverse"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % ("deb", params["MIRROR"], params["RELEASE"], "multiverse"),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
def test_apt_v3_src_replace(self):
"""test_apt_v3_src_replace - Test replacement of MIRROR & RELEASE"""
- cfg = {self.aptlistfile: {'source': 'deb $MIRROR $RELEASE multiverse'}}
+ cfg = {self.aptlistfile: {"source": "deb $MIRROR $RELEASE multiverse"}}
self._apt_src_replacement(self.aptlistfile, cfg)
def test_apt_v3_src_replace_fn(self):
"""test_apt_v3_src_replace_fn - Test filename overwritten in dict"""
- cfg = {'ignored': {'source': 'deb $MIRROR $RELEASE multiverse',
- 'filename': self.aptlistfile}}
+ cfg = {
+ "ignored": {
+ "source": "deb $MIRROR $RELEASE multiverse",
+ "filename": self.aptlistfile,
+ }
+ }
# second file should overwrite the dict key
self._apt_src_replacement(self.aptlistfile, cfg)
@@ -197,22 +254,34 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
# extra verify on two extra files of this test
params = self._get_default_params()
contents = util.load_file(self.aptlistfile2)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", params['MIRROR'], params['RELEASE'],
- "main"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % ("deb", params["MIRROR"], params["RELEASE"], "main"),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
contents = util.load_file(self.aptlistfile3)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb", params['MIRROR'], params['RELEASE'],
- "universe"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % ("deb", params["MIRROR"], params["RELEASE"], "universe"),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
def test_apt_v3_src_replace_tri(self):
"""test_apt_v3_src_replace_tri - Test multiple replace/overwrites"""
- cfg = {self.aptlistfile: {'source': 'deb $MIRROR $RELEASE multiverse'},
- 'notused': {'source': 'deb $MIRROR $RELEASE main',
- 'filename': self.aptlistfile2},
- self.aptlistfile3: {'source': 'deb $MIRROR $RELEASE universe'}}
+ cfg = {
+ self.aptlistfile: {"source": "deb $MIRROR $RELEASE multiverse"},
+ "notused": {
+ "source": "deb $MIRROR $RELEASE main",
+ "filename": self.aptlistfile2,
+ },
+ self.aptlistfile3: {"source": "deb $MIRROR $RELEASE universe"},
+ }
self._apt_src_replace_tri(cfg)
def _apt_src_keyid(self, filename, cfg, keynum, is_hardened=None):
@@ -221,9 +290,10 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
"""
params = self._get_default_params()
- with mock.patch.object(cc_apt_configure, 'add_apt_key') as mockobj:
- self._add_apt_sources(cfg, TARGET, template_params=params,
- aa_repo_match=self.matcher)
+ with mock.patch.object(cc_apt_configure, "add_apt_key") as mockobj:
+ self._add_apt_sources(
+ cfg, TARGET, template_params=params, aa_repo_match=self.matcher
+ )
# check if it added the right number of keys
calls = []
@@ -238,103 +308,165 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
self.assertTrue(os.path.isfile(filename))
contents = util.load_file(filename)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb",
- ('http://ppa.launchpad.net/smoser/'
- 'cloud-init-test/ubuntu'),
- "xenial", "main"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % (
+ "deb",
+ "http://ppa.launchpad.net/smoser/cloud-init-test/ubuntu",
+ "xenial",
+ "main",
+ ),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
def test_apt_v3_src_keyid(self):
"""test_apt_v3_src_keyid - Test source + keyid with filename"""
- cfg = {self.aptlistfile: {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial main'),
- 'filename': self.aptlistfile,
- 'keyid': "03683F77"}}
+ cfg = {
+ self.aptlistfile: {
+ "source": (
+ "deb "
+ "http://ppa.launchpad.net/"
+ "smoser/cloud-init-test/ubuntu"
+ " xenial main"
+ ),
+ "filename": self.aptlistfile,
+ "keyid": "03683F77",
+ }
+ }
self._apt_src_keyid(self.aptlistfile, cfg, 1)
def test_apt_v3_src_keyid_tri(self):
"""test_apt_v3_src_keyid_tri - Test multiple src+key+filen writes"""
- cfg = {self.aptlistfile: {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial main'),
- 'keyid': "03683F77"},
- 'ignored': {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial universe'),
- 'keyid': "03683F77",
- 'filename': self.aptlistfile2},
- self.aptlistfile3: {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial multiverse'),
- 'filename': self.aptlistfile3,
- 'keyid': "03683F77"}}
+ cfg = {
+ self.aptlistfile: {
+ "source": (
+ "deb "
+ "http://ppa.launchpad.net/"
+ "smoser/cloud-init-test/ubuntu"
+ " xenial main"
+ ),
+ "keyid": "03683F77",
+ },
+ "ignored": {
+ "source": (
+ "deb "
+ "http://ppa.launchpad.net/"
+ "smoser/cloud-init-test/ubuntu"
+ " xenial universe"
+ ),
+ "keyid": "03683F77",
+ "filename": self.aptlistfile2,
+ },
+ self.aptlistfile3: {
+ "source": (
+ "deb "
+ "http://ppa.launchpad.net/"
+ "smoser/cloud-init-test/ubuntu"
+ " xenial multiverse"
+ ),
+ "filename": self.aptlistfile3,
+ "keyid": "03683F77",
+ },
+ }
self._apt_src_keyid(self.aptlistfile, cfg, 3)
contents = util.load_file(self.aptlistfile2)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb",
- ('http://ppa.launchpad.net/smoser/'
- 'cloud-init-test/ubuntu'),
- "xenial", "universe"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % (
+ "deb",
+ "http://ppa.launchpad.net/smoser/cloud-init-test/ubuntu",
+ "xenial",
+ "universe",
+ ),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
contents = util.load_file(self.aptlistfile3)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb",
- ('http://ppa.launchpad.net/smoser/'
- 'cloud-init-test/ubuntu'),
- "xenial", "multiverse"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % (
+ "deb",
+ "http://ppa.launchpad.net/smoser/cloud-init-test/ubuntu",
+ "xenial",
+ "multiverse",
+ ),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
def test_apt_v3_src_key(self):
"""test_apt_v3_src_key - Test source + key"""
params = self._get_default_params()
- cfg = {self.aptlistfile: {'source': ('deb '
- 'http://ppa.launchpad.net/'
- 'smoser/cloud-init-test/ubuntu'
- ' xenial main'),
- 'filename': self.aptlistfile,
- 'key': "fakekey 4321"}}
-
- with mock.patch.object(cc_apt_configure, 'apt_key') as mockobj:
- self._add_apt_sources(cfg, TARGET, template_params=params,
- aa_repo_match=self.matcher)
-
- calls = (call(
- 'add',
- output_file=pathlib.Path(self.aptlistfile).stem,
- data='fakekey 4321',
- hardened=False),)
+ cfg = {
+ self.aptlistfile: {
+ "source": (
+ "deb "
+ "http://ppa.launchpad.net/"
+ "smoser/cloud-init-test/ubuntu"
+ " xenial main"
+ ),
+ "filename": self.aptlistfile,
+ "key": "fakekey 4321",
+ }
+ }
+
+ with mock.patch.object(cc_apt_configure, "apt_key") as mockobj:
+ self._add_apt_sources(
+ cfg, TARGET, template_params=params, aa_repo_match=self.matcher
+ )
+
+ calls = (
+ call(
+ "add",
+ output_file=pathlib.Path(self.aptlistfile).stem,
+ data="fakekey 4321",
+ hardened=False,
+ ),
+ )
mockobj.assert_has_calls(calls, any_order=True)
self.assertTrue(os.path.isfile(self.aptlistfile))
contents = util.load_file(self.aptlistfile)
- self.assertTrue(re.search(r"%s %s %s %s\n" %
- ("deb",
- ('http://ppa.launchpad.net/smoser/'
- 'cloud-init-test/ubuntu'),
- "xenial", "main"),
- contents, flags=re.IGNORECASE))
+ self.assertTrue(
+ re.search(
+ r"%s %s %s %s\n"
+ % (
+ "deb",
+ "http://ppa.launchpad.net/smoser/cloud-init-test/ubuntu",
+ "xenial",
+ "main",
+ ),
+ contents,
+ flags=re.IGNORECASE,
+ )
+ )
def test_apt_v3_src_keyonly(self):
"""test_apt_v3_src_keyonly - Test key without source"""
params = self._get_default_params()
- cfg = {self.aptlistfile: {'key': "fakekey 4242"}}
-
- with mock.patch.object(cc_apt_configure, 'apt_key') as mockobj:
- self._add_apt_sources(cfg, TARGET, template_params=params,
- aa_repo_match=self.matcher)
-
- calls = (call(
- 'add',
- output_file=pathlib.Path(self.aptlistfile).stem,
- data='fakekey 4242',
- hardened=False),)
+ cfg = {self.aptlistfile: {"key": "fakekey 4242"}}
+
+ with mock.patch.object(cc_apt_configure, "apt_key") as mockobj:
+ self._add_apt_sources(
+ cfg, TARGET, template_params=params, aa_repo_match=self.matcher
+ )
+
+ calls = (
+ call(
+ "add",
+ output_file=pathlib.Path(self.aptlistfile).stem,
+ data="fakekey 4242",
+ hardened=False,
+ ),
+ )
mockobj.assert_has_calls(calls, any_order=True)
# filename should be ignored on key only
@@ -343,18 +475,26 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
def test_apt_v3_src_keyidonly(self):
"""test_apt_v3_src_keyidonly - Test keyid without source"""
params = self._get_default_params()
- cfg = {self.aptlistfile: {'keyid': "03683F77"}}
- with mock.patch.object(subp, 'subp',
- return_value=('fakekey 1212', '')):
- with mock.patch.object(cc_apt_configure, 'apt_key') as mockobj:
- self._add_apt_sources(cfg, TARGET, template_params=params,
- aa_repo_match=self.matcher)
-
- calls = (call(
- 'add',
- output_file=pathlib.Path(self.aptlistfile).stem,
- data='fakekey 1212',
- hardened=False),)
+ cfg = {self.aptlistfile: {"keyid": "03683F77"}}
+ with mock.patch.object(
+ subp, "subp", return_value=("fakekey 1212", "")
+ ):
+ with mock.patch.object(cc_apt_configure, "apt_key") as mockobj:
+ self._add_apt_sources(
+ cfg,
+ TARGET,
+ template_params=params,
+ aa_repo_match=self.matcher,
+ )
+
+ calls = (
+ call(
+ "add",
+ output_file=pathlib.Path(self.aptlistfile).stem,
+ data="fakekey 1212",
+ hardened=False,
+ ),
+ )
mockobj.assert_has_calls(calls, any_order=True)
# filename should be ignored on key only
@@ -368,21 +508,25 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
"""
params = self._get_default_params()
- with mock.patch.object(cc_apt_configure, 'add_apt_key_raw') as mockkey:
- with mock.patch.object(gpg, 'getkeybyid',
- return_value=expectedkey) as mockgetkey:
- self._add_apt_sources(cfg, TARGET, template_params=params,
- aa_repo_match=self.matcher)
+ with mock.patch.object(cc_apt_configure, "add_apt_key_raw") as mockkey:
+ with mock.patch.object(
+ gpg, "getkeybyid", return_value=expectedkey
+ ) as mockgetkey:
+ self._add_apt_sources(
+ cfg,
+ TARGET,
+ template_params=params,
+ aa_repo_match=self.matcher,
+ )
keycfg = cfg[self.aptlistfile]
- mockgetkey.assert_called_with(keycfg['keyid'],
- keycfg.get('keyserver',
- 'keyserver.ubuntu.com'))
+ mockgetkey.assert_called_with(
+ keycfg["keyid"], keycfg.get("keyserver", "keyserver.ubuntu.com")
+ )
if is_hardened is not None:
mockkey.assert_called_with(
- expectedkey,
- keycfg['keyfile'],
- hardened=is_hardened)
+ expectedkey, keycfg["keyfile"], hardened=is_hardened
+ )
# filename should be ignored on key only
self.assertFalse(os.path.isfile(self.aptlistfile))
@@ -390,25 +534,27 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
def test_apt_v3_src_keyid_real(self):
"""test_apt_v3_src_keyid_real - Test keyid including key add"""
keyid = "03683F77"
- cfg = {self.aptlistfile: {'keyid': keyid,
- 'keyfile': self.aptlistfile}}
+ cfg = {self.aptlistfile: {"keyid": keyid, "keyfile": self.aptlistfile}}
self.apt_src_keyid_real(cfg, EXPECTEDKEY, is_hardened=False)
def test_apt_v3_src_longkeyid_real(self):
"""test_apt_v3_src_longkeyid_real Test long keyid including key add"""
keyid = "B59D 5F15 97A5 04B7 E230 6DCA 0620 BBCF 0368 3F77"
- cfg = {self.aptlistfile: {'keyid': keyid,
- 'keyfile': self.aptlistfile}}
+ cfg = {self.aptlistfile: {"keyid": keyid, "keyfile": self.aptlistfile}}
self.apt_src_keyid_real(cfg, EXPECTEDKEY, is_hardened=False)
def test_apt_v3_src_longkeyid_ks_real(self):
"""test_apt_v3_src_longkeyid_ks_real Test long keyid from other ks"""
keyid = "B59D 5F15 97A5 04B7 E230 6DCA 0620 BBCF 0368 3F77"
- cfg = {self.aptlistfile: {'keyid': keyid,
- 'keyfile': self.aptlistfile,
- 'keyserver': 'keys.gnupg.net'}}
+ cfg = {
+ self.aptlistfile: {
+ "keyid": keyid,
+ "keyfile": self.aptlistfile,
+ "keyserver": "keys.gnupg.net",
+ }
+ }
self.apt_src_keyid_real(cfg, EXPECTEDKEY)
@@ -416,21 +562,31 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
"""test_apt_v3_src_keyid_keyserver - Test custom keyserver"""
keyid = "03683F77"
params = self._get_default_params()
- cfg = {self.aptlistfile: {'keyid': keyid,
- 'keyfile': self.aptlistfile,
- 'keyserver': 'test.random.com'}}
+ cfg = {
+ self.aptlistfile: {
+ "keyid": keyid,
+ "keyfile": self.aptlistfile,
+ "keyserver": "test.random.com",
+ }
+ }
# in some test environments only *.ubuntu.com is reachable
# so mock the call and check if the config got there
- with mock.patch.object(gpg, 'getkeybyid',
- return_value="fakekey") as mockgetkey:
- with mock.patch.object(cc_apt_configure,
- 'add_apt_key_raw') as mockadd:
- self._add_apt_sources(cfg, TARGET, template_params=params,
- aa_repo_match=self.matcher)
-
- mockgetkey.assert_called_with('03683F77', 'test.random.com')
- mockadd.assert_called_with('fakekey', self.aptlistfile, hardened=False)
+ with mock.patch.object(
+ gpg, "getkeybyid", return_value="fakekey"
+ ) as mockgetkey:
+ with mock.patch.object(
+ cc_apt_configure, "add_apt_key_raw"
+ ) as mockadd:
+ self._add_apt_sources(
+ cfg,
+ TARGET,
+ template_params=params,
+ aa_repo_match=self.matcher,
+ )
+
+ mockgetkey.assert_called_with("03683F77", "test.random.com")
+ mockadd.assert_called_with("fakekey", self.aptlistfile, hardened=False)
# filename should be ignored on key only
self.assertFalse(os.path.isfile(self.aptlistfile))
@@ -438,13 +594,15 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
def test_apt_v3_src_ppa(self):
"""test_apt_v3_src_ppa - Test specification of a ppa"""
params = self._get_default_params()
- cfg = {self.aptlistfile: {'source': 'ppa:smoser/cloud-init-test'}}
+ cfg = {self.aptlistfile: {"source": "ppa:smoser/cloud-init-test"}}
with mock.patch("cloudinit.subp.subp") as mockobj:
- self._add_apt_sources(cfg, TARGET, template_params=params,
- aa_repo_match=self.matcher)
- mockobj.assert_any_call(['add-apt-repository',
- 'ppa:smoser/cloud-init-test'], target=TARGET)
+ self._add_apt_sources(
+ cfg, TARGET, template_params=params, aa_repo_match=self.matcher
+ )
+ mockobj.assert_any_call(
+ ["add-apt-repository", "ppa:smoser/cloud-init-test"], target=TARGET
+ )
# adding ppa should ignore filename (uses add-apt-repository)
self.assertFalse(os.path.isfile(self.aptlistfile))
@@ -452,19 +610,30 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
def test_apt_v3_src_ppa_tri(self):
"""test_apt_v3_src_ppa_tri - Test specification of multiple ppa's"""
params = self._get_default_params()
- cfg = {self.aptlistfile: {'source': 'ppa:smoser/cloud-init-test'},
- self.aptlistfile2: {'source': 'ppa:smoser/cloud-init-test2'},
- self.aptlistfile3: {'source': 'ppa:smoser/cloud-init-test3'}}
+ cfg = {
+ self.aptlistfile: {"source": "ppa:smoser/cloud-init-test"},
+ self.aptlistfile2: {"source": "ppa:smoser/cloud-init-test2"},
+ self.aptlistfile3: {"source": "ppa:smoser/cloud-init-test3"},
+ }
with mock.patch("cloudinit.subp.subp") as mockobj:
- self._add_apt_sources(cfg, TARGET, template_params=params,
- aa_repo_match=self.matcher)
- calls = [call(['add-apt-repository', 'ppa:smoser/cloud-init-test'],
- target=TARGET),
- call(['add-apt-repository', 'ppa:smoser/cloud-init-test2'],
- target=TARGET),
- call(['add-apt-repository', 'ppa:smoser/cloud-init-test3'],
- target=TARGET)]
+ self._add_apt_sources(
+ cfg, TARGET, template_params=params, aa_repo_match=self.matcher
+ )
+ calls = [
+ call(
+ ["add-apt-repository", "ppa:smoser/cloud-init-test"],
+ target=TARGET,
+ ),
+ call(
+ ["add-apt-repository", "ppa:smoser/cloud-init-test2"],
+ target=TARGET,
+ ),
+ call(
+ ["add-apt-repository", "ppa:smoser/cloud-init-test3"],
+ target=TARGET,
+ ),
+ ]
mockobj.assert_has_calls(calls, any_order=True)
# adding ppa should ignore all filenames (uses add-apt-repository)
@@ -478,34 +647,46 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
pre = "/var/lib/apt/lists"
# filenames are archive dependent
- arch = 's390x'
+ arch = "s390x"
m_get_dpkg_architecture.return_value = arch
component = "ubuntu-ports"
archive = "ports.ubuntu.com"
- cfg = {'primary': [{'arches': ["default"],
- 'uri':
- 'http://test.ubuntu.com/%s/' % component}],
- 'security': [{'arches': ["default"],
- 'uri':
- 'http://testsec.ubuntu.com/%s/' % component}]}
- post = ("%s_dists_%s-updates_InRelease" %
- (component, MOCK_LSB_RELEASE_DATA['codename']))
- fromfn = ("%s/%s_%s" % (pre, archive, post))
- tofn = ("%s/test.ubuntu.com_%s" % (pre, post))
+ cfg = {
+ "primary": [
+ {
+ "arches": ["default"],
+ "uri": "http://test.ubuntu.com/%s/" % component,
+ }
+ ],
+ "security": [
+ {
+ "arches": ["default"],
+ "uri": "http://testsec.ubuntu.com/%s/" % component,
+ }
+ ],
+ }
+ post = "%s_dists_%s-updates_InRelease" % (
+ component,
+ MOCK_LSB_RELEASE_DATA["codename"],
+ )
+ fromfn = "%s/%s_%s" % (pre, archive, post)
+ tofn = "%s/test.ubuntu.com_%s" % (pre, post)
mirrors = cc_apt_configure.find_apt_mirror_info(cfg, FakeCloud(), arch)
- self.assertEqual(mirrors['MIRROR'],
- "http://test.ubuntu.com/%s/" % component)
- self.assertEqual(mirrors['PRIMARY'],
- "http://test.ubuntu.com/%s/" % component)
- self.assertEqual(mirrors['SECURITY'],
- "http://testsec.ubuntu.com/%s/" % component)
+ self.assertEqual(
+ mirrors["MIRROR"], "http://test.ubuntu.com/%s/" % component
+ )
+ self.assertEqual(
+ mirrors["PRIMARY"], "http://test.ubuntu.com/%s/" % component
+ )
+ self.assertEqual(
+ mirrors["SECURITY"], "http://testsec.ubuntu.com/%s/" % component
+ )
- with mock.patch.object(os, 'rename') as mockren:
- with mock.patch.object(glob, 'glob',
- return_value=[fromfn]):
+ with mock.patch.object(os, "rename") as mockren:
+ with mock.patch.object(glob, "glob", return_value=[fromfn]):
cc_apt_configure.rename_apt_lists(mirrors, TARGET, arch)
mockren.assert_any_call(fromfn, tofn)
@@ -515,13 +696,13 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
target = os.path.join(self.tmp, "rename_non_slash")
apt_lists_d = os.path.join(target, "./" + cc_apt_configure.APT_LISTS)
- arch = 'amd64'
+ arch = "amd64"
m_get_dpkg_architecture.return_value = arch
mirror_path = "some/random/path/"
primary = "http://test.ubuntu.com/" + mirror_path
security = "http://test-security.ubuntu.com/" + mirror_path
- mirrors = {'PRIMARY': primary, 'SECURITY': security}
+ mirrors = {"PRIMARY": primary, "SECURITY": security}
# these match default archive prefixes
opri_pre = "archive.ubuntu.com_ubuntu_dists_xenial"
@@ -559,203 +740,226 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
@staticmethod
def test_apt_v3_proxy():
"""test_apt_v3_proxy - Test apt_*proxy configuration"""
- cfg = {"proxy": "foobar1",
- "http_proxy": "foobar2",
- "ftp_proxy": "foobar3",
- "https_proxy": "foobar4"}
+ cfg = {
+ "proxy": "foobar1",
+ "http_proxy": "foobar2",
+ "ftp_proxy": "foobar3",
+ "https_proxy": "foobar4",
+ }
- with mock.patch.object(util, 'write_file') as mockobj:
+ with mock.patch.object(util, "write_file") as mockobj:
cc_apt_configure.apply_apt_config(cfg, "proxyfn", "notused")
- mockobj.assert_called_with('proxyfn',
- ('Acquire::http::Proxy "foobar1";\n'
- 'Acquire::http::Proxy "foobar2";\n'
- 'Acquire::ftp::Proxy "foobar3";\n'
- 'Acquire::https::Proxy "foobar4";\n'))
+ mockobj.assert_called_with(
+ "proxyfn",
+ 'Acquire::http::Proxy "foobar1";\n'
+ 'Acquire::http::Proxy "foobar2";\n'
+ 'Acquire::ftp::Proxy "foobar3";\n'
+ 'Acquire::https::Proxy "foobar4";\n',
+ )
def test_apt_v3_mirror(self):
"""test_apt_v3_mirror - Test defining a mirror"""
pmir = "http://us.archive.ubuntu.com/ubuntu/"
smir = "http://security.ubuntu.com/ubuntu/"
- cfg = {"primary": [{'arches': ["default"],
- "uri": pmir}],
- "security": [{'arches': ["default"],
- "uri": smir}]}
+ cfg = {
+ "primary": [{"arches": ["default"], "uri": pmir}],
+ "security": [{"arches": ["default"], "uri": smir}],
+ }
mirrors = cc_apt_configure.find_apt_mirror_info(
- cfg, FakeCloud(), 'amd64')
+ cfg, FakeCloud(), "amd64"
+ )
- self.assertEqual(mirrors['MIRROR'],
- pmir)
- self.assertEqual(mirrors['PRIMARY'],
- pmir)
- self.assertEqual(mirrors['SECURITY'],
- smir)
+ self.assertEqual(mirrors["MIRROR"], pmir)
+ self.assertEqual(mirrors["PRIMARY"], pmir)
+ self.assertEqual(mirrors["SECURITY"], smir)
def test_apt_v3_mirror_default(self):
"""test_apt_v3_mirror_default - Test without defining a mirror"""
- arch = 'amd64'
+ arch = "amd64"
default_mirrors = cc_apt_configure.get_default_mirrors(arch)
pmir = default_mirrors["PRIMARY"]
smir = default_mirrors["SECURITY"]
mycloud = get_cloud()
mirrors = cc_apt_configure.find_apt_mirror_info({}, mycloud, arch)
- self.assertEqual(mirrors['MIRROR'],
- pmir)
- self.assertEqual(mirrors['PRIMARY'],
- pmir)
- self.assertEqual(mirrors['SECURITY'],
- smir)
+ self.assertEqual(mirrors["MIRROR"], pmir)
+ self.assertEqual(mirrors["PRIMARY"], pmir)
+ self.assertEqual(mirrors["SECURITY"], smir)
def test_apt_v3_mirror_arches(self):
"""test_apt_v3_mirror_arches - Test arches selection of mirror"""
pmir = "http://my-primary.ubuntu.com/ubuntu/"
smir = "http://my-security.ubuntu.com/ubuntu/"
- arch = 'ppc64el'
- cfg = {"primary": [{'arches': ["default"], "uri": "notthis-primary"},
- {'arches': [arch], "uri": pmir}],
- "security": [{'arches': ["default"], "uri": "nothis-security"},
- {'arches': [arch], "uri": smir}]}
+ arch = "ppc64el"
+ cfg = {
+ "primary": [
+ {"arches": ["default"], "uri": "notthis-primary"},
+ {"arches": [arch], "uri": pmir},
+ ],
+ "security": [
+ {"arches": ["default"], "uri": "nothis-security"},
+ {"arches": [arch], "uri": smir},
+ ],
+ }
mirrors = cc_apt_configure.find_apt_mirror_info(cfg, FakeCloud(), arch)
- self.assertEqual(mirrors['PRIMARY'], pmir)
- self.assertEqual(mirrors['MIRROR'], pmir)
- self.assertEqual(mirrors['SECURITY'], smir)
+ self.assertEqual(mirrors["PRIMARY"], pmir)
+ self.assertEqual(mirrors["MIRROR"], pmir)
+ self.assertEqual(mirrors["SECURITY"], smir)
def test_apt_v3_mirror_arches_default(self):
"""test_apt_v3_mirror_arches - Test falling back to default arch"""
pmir = "http://us.archive.ubuntu.com/ubuntu/"
smir = "http://security.ubuntu.com/ubuntu/"
- cfg = {"primary": [{'arches': ["default"],
- "uri": pmir},
- {'arches': ["thisarchdoesntexist"],
- "uri": "notthis"}],
- "security": [{'arches': ["thisarchdoesntexist"],
- "uri": "nothat"},
- {'arches': ["default"],
- "uri": smir}]}
+ cfg = {
+ "primary": [
+ {"arches": ["default"], "uri": pmir},
+ {"arches": ["thisarchdoesntexist"], "uri": "notthis"},
+ ],
+ "security": [
+ {"arches": ["thisarchdoesntexist"], "uri": "nothat"},
+ {"arches": ["default"], "uri": smir},
+ ],
+ }
mirrors = cc_apt_configure.find_apt_mirror_info(
- cfg, FakeCloud(), 'amd64')
+ cfg, FakeCloud(), "amd64"
+ )
- self.assertEqual(mirrors['MIRROR'],
- pmir)
- self.assertEqual(mirrors['PRIMARY'],
- pmir)
- self.assertEqual(mirrors['SECURITY'],
- smir)
+ self.assertEqual(mirrors["MIRROR"], pmir)
+ self.assertEqual(mirrors["PRIMARY"], pmir)
+ self.assertEqual(mirrors["SECURITY"], smir)
@mock.patch("cloudinit.config.cc_apt_configure.util.get_dpkg_architecture")
def test_apt_v3_get_def_mir_non_intel_no_arch(
self, m_get_dpkg_architecture
):
- arch = 'ppc64el'
+ arch = "ppc64el"
m_get_dpkg_architecture.return_value = arch
- expected = {'PRIMARY': 'http://ports.ubuntu.com/ubuntu-ports',
- 'SECURITY': 'http://ports.ubuntu.com/ubuntu-ports'}
+ expected = {
+ "PRIMARY": "http://ports.ubuntu.com/ubuntu-ports",
+ "SECURITY": "http://ports.ubuntu.com/ubuntu-ports",
+ }
self.assertEqual(expected, cc_apt_configure.get_default_mirrors())
def test_apt_v3_get_default_mirrors_non_intel_with_arch(self):
- found = cc_apt_configure.get_default_mirrors('ppc64el')
+ found = cc_apt_configure.get_default_mirrors("ppc64el")
- expected = {'PRIMARY': 'http://ports.ubuntu.com/ubuntu-ports',
- 'SECURITY': 'http://ports.ubuntu.com/ubuntu-ports'}
+ expected = {
+ "PRIMARY": "http://ports.ubuntu.com/ubuntu-ports",
+ "SECURITY": "http://ports.ubuntu.com/ubuntu-ports",
+ }
self.assertEqual(expected, found)
def test_apt_v3_mirror_arches_sysdefault(self):
"""test_apt_v3_mirror_arches - Test arches fallback to sys default"""
- arch = 'amd64'
+ arch = "amd64"
default_mirrors = cc_apt_configure.get_default_mirrors(arch)
pmir = default_mirrors["PRIMARY"]
smir = default_mirrors["SECURITY"]
mycloud = get_cloud()
- cfg = {"primary": [{'arches': ["thisarchdoesntexist_64"],
- "uri": "notthis"},
- {'arches': ["thisarchdoesntexist"],
- "uri": "notthiseither"}],
- "security": [{'arches': ["thisarchdoesntexist"],
- "uri": "nothat"},
- {'arches': ["thisarchdoesntexist_64"],
- "uri": "nothateither"}]}
+ cfg = {
+ "primary": [
+ {"arches": ["thisarchdoesntexist_64"], "uri": "notthis"},
+ {"arches": ["thisarchdoesntexist"], "uri": "notthiseither"},
+ ],
+ "security": [
+ {"arches": ["thisarchdoesntexist"], "uri": "nothat"},
+ {"arches": ["thisarchdoesntexist_64"], "uri": "nothateither"},
+ ],
+ }
mirrors = cc_apt_configure.find_apt_mirror_info(cfg, mycloud, arch)
- self.assertEqual(mirrors['MIRROR'], pmir)
- self.assertEqual(mirrors['PRIMARY'], pmir)
- self.assertEqual(mirrors['SECURITY'], smir)
+ self.assertEqual(mirrors["MIRROR"], pmir)
+ self.assertEqual(mirrors["PRIMARY"], pmir)
+ self.assertEqual(mirrors["SECURITY"], smir)
def test_apt_v3_mirror_search(self):
"""test_apt_v3_mirror_search - Test searching mirrors in a list
- mock checks to avoid relying on network connectivity"""
+ mock checks to avoid relying on network connectivity"""
pmir = "http://us.archive.ubuntu.com/ubuntu/"
smir = "http://security.ubuntu.com/ubuntu/"
- cfg = {"primary": [{'arches': ["default"],
- "search": ["pfailme", pmir]}],
- "security": [{'arches': ["default"],
- "search": ["sfailme", smir]}]}
-
- with mock.patch.object(cc_apt_configure.util, 'search_for_mirror',
- side_effect=[pmir, smir]) as mocksearch:
- mirrors = cc_apt_configure.find_apt_mirror_info(cfg, FakeCloud(),
- 'amd64')
-
- calls = [call(["pfailme", pmir]),
- call(["sfailme", smir])]
+ cfg = {
+ "primary": [{"arches": ["default"], "search": ["pfailme", pmir]}],
+ "security": [{"arches": ["default"], "search": ["sfailme", smir]}],
+ }
+
+ with mock.patch.object(
+ cc_apt_configure.util,
+ "search_for_mirror",
+ side_effect=[pmir, smir],
+ ) as mocksearch:
+ mirrors = cc_apt_configure.find_apt_mirror_info(
+ cfg, FakeCloud(), "amd64"
+ )
+
+ calls = [call(["pfailme", pmir]), call(["sfailme", smir])]
mocksearch.assert_has_calls(calls)
- self.assertEqual(mirrors['MIRROR'],
- pmir)
- self.assertEqual(mirrors['PRIMARY'],
- pmir)
- self.assertEqual(mirrors['SECURITY'],
- smir)
+ self.assertEqual(mirrors["MIRROR"], pmir)
+ self.assertEqual(mirrors["PRIMARY"], pmir)
+ self.assertEqual(mirrors["SECURITY"], smir)
def test_apt_v3_mirror_search_many2(self):
"""test_apt_v3_mirror_search_many3 - Test both mirrors specs at once"""
pmir = "http://us.archive.ubuntu.com/ubuntu/"
smir = "http://security.ubuntu.com/ubuntu/"
- cfg = {"primary": [{'arches': ["default"],
- "uri": pmir,
- "search": ["pfailme", "foo"]}],
- "security": [{'arches': ["default"],
- "uri": smir,
- "search": ["sfailme", "bar"]}]}
+ cfg = {
+ "primary": [
+ {
+ "arches": ["default"],
+ "uri": pmir,
+ "search": ["pfailme", "foo"],
+ }
+ ],
+ "security": [
+ {
+ "arches": ["default"],
+ "uri": smir,
+ "search": ["sfailme", "bar"],
+ }
+ ],
+ }
- arch = 'amd64'
+ arch = "amd64"
# should be called only once per type, despite two mirror configs
mycloud = None
- with mock.patch.object(cc_apt_configure, 'get_mirror',
- return_value="http://mocked/foo") as mockgm:
+ with mock.patch.object(
+ cc_apt_configure, "get_mirror", return_value="http://mocked/foo"
+ ) as mockgm:
mirrors = cc_apt_configure.find_apt_mirror_info(cfg, mycloud, arch)
- calls = [call(cfg, 'primary', arch, mycloud),
- call(cfg, 'security', arch, mycloud)]
+ calls = [
+ call(cfg, "primary", arch, mycloud),
+ call(cfg, "security", arch, mycloud),
+ ]
mockgm.assert_has_calls(calls)
# should not be called, since primary is specified
- with mock.patch.object(cc_apt_configure.util,
- 'search_for_mirror') as mockse:
+ with mock.patch.object(
+ cc_apt_configure.util, "search_for_mirror"
+ ) as mockse:
mirrors = cc_apt_configure.find_apt_mirror_info(
- cfg, FakeCloud(), arch)
+ cfg, FakeCloud(), arch
+ )
mockse.assert_not_called()
- self.assertEqual(mirrors['MIRROR'],
- pmir)
- self.assertEqual(mirrors['PRIMARY'],
- pmir)
- self.assertEqual(mirrors['SECURITY'],
- smir)
+ self.assertEqual(mirrors["MIRROR"], pmir)
+ self.assertEqual(mirrors["PRIMARY"], pmir)
+ self.assertEqual(mirrors["SECURITY"], smir)
def test_apt_v3_url_resolvable(self):
"""test_apt_v3_url_resolvable - Test resolving urls"""
- with mock.patch.object(util, 'is_resolvable') as mockresolve:
+ with mock.patch.object(util, "is_resolvable") as mockresolve:
util.is_resolvable_url("http://1.2.3.4/ubuntu")
mockresolve.assert_called_with("1.2.3.4")
- with mock.patch.object(util, 'is_resolvable') as mockresolve:
+ with mock.patch.object(util, "is_resolvable") as mockresolve:
util.is_resolvable_url("http://us.archive.ubuntu.com/ubuntu")
mockresolve.assert_called_with("us.archive.ubuntu.com")
@@ -764,25 +968,27 @@ class TestAptSourceConfig(t_help.FilesystemMockingTestCase):
util._DNS_REDIRECT_IP = None
bad = [(None, None, None, "badname", ["10.3.2.1"])]
good = [(None, None, None, "goodname", ["10.2.3.4"])]
- with mock.patch.object(socket, 'getaddrinfo',
- side_effect=[bad, bad, bad, good,
- good]) as mocksock:
+ with mock.patch.object(
+ socket, "getaddrinfo", side_effect=[bad, bad, bad, good, good]
+ ) as mocksock:
ret = util.is_resolvable_url("http://us.archive.ubuntu.com/ubuntu")
ret2 = util.is_resolvable_url("http://1.2.3.4/ubuntu")
- mocksock.assert_any_call('does-not-exist.example.com.', None,
- 0, 0, 1, 2)
- mocksock.assert_any_call('example.invalid.', None, 0, 0, 1, 2)
- mocksock.assert_any_call('us.archive.ubuntu.com', None)
- mocksock.assert_any_call('1.2.3.4', None)
+ mocksock.assert_any_call(
+ "does-not-exist.example.com.", None, 0, 0, 1, 2
+ )
+ mocksock.assert_any_call("example.invalid.", None, 0, 0, 1, 2)
+ mocksock.assert_any_call("us.archive.ubuntu.com", None)
+ mocksock.assert_any_call("1.2.3.4", None)
self.assertTrue(ret)
self.assertTrue(ret2)
# side effect need only bad ret after initial call
- with mock.patch.object(socket, 'getaddrinfo',
- side_effect=[bad]) as mocksock:
+ with mock.patch.object(
+ socket, "getaddrinfo", side_effect=[bad]
+ ) as mocksock:
ret3 = util.is_resolvable_url("http://failme.com/ubuntu")
- calls = [call('failme.com', None)]
+ calls = [call("failme.com", None)]
mocksock.assert_has_calls(calls)
self.assertFalse(ret3)
@@ -818,24 +1024,28 @@ deb http://ubuntu.com/ubuntu/ xenial-proposed main"""
# single disable other suite
disabled = ["$RELEASE-updates"]
- expect = ("""deb http://ubuntu.com//ubuntu xenial main
+ expect = (
+ """deb http://ubuntu.com//ubuntu xenial main
# suite disabled by cloud-init: deb http://ubuntu.com//ubuntu"""
- """ xenial-updates main
+ """ xenial-updates main
deb http://ubuntu.com//ubuntu xenial-security main
deb-src http://ubuntu.com//ubuntu universe multiverse
-deb http://ubuntu.com/ubuntu/ xenial-proposed main""")
+deb http://ubuntu.com/ubuntu/ xenial-proposed main"""
+ )
result = cc_apt_configure.disable_suites(disabled, orig, release)
self.assertEqual(expect, result)
# multi disable
disabled = ["$RELEASE-updates", "$RELEASE-security"]
- expect = ("""deb http://ubuntu.com//ubuntu xenial main
+ expect = (
+ """deb http://ubuntu.com//ubuntu xenial main
# suite disabled by cloud-init: deb http://ubuntu.com//ubuntu """
- """xenial-updates main
+ """xenial-updates main
# suite disabled by cloud-init: deb http://ubuntu.com//ubuntu """
- """xenial-security main
+ """xenial-security main
deb-src http://ubuntu.com//ubuntu universe multiverse
-deb http://ubuntu.com/ubuntu/ xenial-proposed main""")
+deb http://ubuntu.com/ubuntu/ xenial-proposed main"""
+ )
result = cc_apt_configure.disable_suites(disabled, orig, release)
self.assertEqual(expect, result)
@@ -848,17 +1058,19 @@ deb-src http://ubuntu.com//ubuntu universe multiverse
deb http://UBUNTU.com//ubuntu xenial-updates main
deb http://UBUNTU.COM//ubuntu xenial-updates main
deb http://ubuntu.com/ubuntu/ xenial-proposed main"""
- expect = ("""deb http://ubuntu.com//ubuntu xenial main
+ expect = (
+ """deb http://ubuntu.com//ubuntu xenial main
# suite disabled by cloud-init: deb http://ubuntu.com//ubuntu """
- """xenial-updates main
+ """xenial-updates main
# suite disabled by cloud-init: deb http://ubuntu.com//ubuntu """
- """xenial-security main
+ """xenial-security main
deb-src http://ubuntu.com//ubuntu universe multiverse
# suite disabled by cloud-init: deb http://UBUNTU.com//ubuntu """
- """xenial-updates main
+ """xenial-updates main
# suite disabled by cloud-init: deb http://UBUNTU.COM//ubuntu """
- """xenial-updates main
-deb http://ubuntu.com/ubuntu/ xenial-proposed main""")
+ """xenial-updates main
+deb http://ubuntu.com/ubuntu/ xenial-proposed main"""
+ )
result = cc_apt_configure.disable_suites(disabled, orig, release)
self.assertEqual(expect, result)
@@ -872,17 +1084,19 @@ deb-src http://ubuntu.com//ubuntu universe multiverse
#deb http://UBUNTU.com//ubuntu xenial-updates main
deb http://UBUNTU.COM//ubuntu xenial-updates main
deb http://ubuntu.com/ubuntu/ xenial-proposed main"""
- expect = ("""deb http://ubuntu.com//ubuntu xenial main
+ expect = (
+ """deb http://ubuntu.com//ubuntu xenial main
# suite disabled by cloud-init: deb http://ubuntu.com//ubuntu """
- """xenial-updates main
+ """xenial-updates main
# suite disabled by cloud-init: deb http://ubuntu.com//ubuntu """
- """xenial-security main
+ """xenial-security main
deb-src http://ubuntu.com//ubuntu universe multiverse
#foo
#deb http://UBUNTU.com//ubuntu xenial-updates main
# suite disabled by cloud-init: deb http://UBUNTU.COM//ubuntu """
- """xenial-updates main
-deb http://ubuntu.com/ubuntu/ xenial-proposed main""")
+ """xenial-updates main
+deb http://ubuntu.com/ubuntu/ xenial-proposed main"""
+ )
result = cc_apt_configure.disable_suites(disabled, orig, release)
self.assertEqual(expect, result)
@@ -919,12 +1133,14 @@ deb [a=b] http://ubu.com//ubu xenial-updates main
deb http://ubuntu.com//ubuntu xenial-security main
deb-src http://ubuntu.com//ubuntu universe multiverse
deb http://ubuntu.com/ubuntu/ xenial-proposed main"""
- expect = ("""deb http://ubuntu.com//ubuntu xenial main
+ expect = (
+ """deb http://ubuntu.com//ubuntu xenial main
# suite disabled by cloud-init: deb [a=b] http://ubu.com//ubu """
- """xenial-updates main
+ """xenial-updates main
deb http://ubuntu.com//ubuntu xenial-security main
deb-src http://ubuntu.com//ubuntu universe multiverse
-deb http://ubuntu.com/ubuntu/ xenial-proposed main""")
+deb http://ubuntu.com/ubuntu/ xenial-proposed main"""
+ )
result = cc_apt_configure.disable_suites(disabled, orig, release)
self.assertEqual(expect, result)
@@ -951,134 +1167,167 @@ deb [arch=foo] http://ubuntu.com//ubuntu xenial-updates main
deb http://ubuntu.com//ubuntu xenial-security main
deb-src http://ubuntu.com//ubuntu universe multiverse
deb http://ubuntu.com/ubuntu/ xenial-proposed main"""
- expect = ("""deb http://ubuntu.com//ubuntu xenial main
+ expect = (
+ """deb http://ubuntu.com//ubuntu xenial main
deb [arch=foo] http://ubuntu.com//ubuntu xenial-updates main
# suite disabled by cloud-init: deb http://ubuntu.com//ubuntu """
- """xenial-security main
+ """xenial-security main
deb-src http://ubuntu.com//ubuntu universe multiverse
-deb http://ubuntu.com/ubuntu/ xenial-proposed main""")
+deb http://ubuntu.com/ubuntu/ xenial-proposed main"""
+ )
result = cc_apt_configure.disable_suites(disabled, orig, release)
self.assertEqual(expect, result)
def test_disable_suites_blank_lines(self):
"""test_disable_suites_blank_lines - ensure blank lines allowed"""
- lines = ["deb %(repo)s %(rel)s main universe",
- "",
- "deb %(repo)s %(rel)s-updates main universe",
- " # random comment",
- "#comment here",
- ""]
+ lines = [
+ "deb %(repo)s %(rel)s main universe",
+ "",
+ "deb %(repo)s %(rel)s-updates main universe",
+ " # random comment",
+ "#comment here",
+ "",
+ ]
rel = "trusty"
- repo = 'http://example.com/mirrors/ubuntu'
- orig = "\n".join(lines) % {'repo': repo, 'rel': rel}
+ repo = "http://example.com/mirrors/ubuntu"
+ orig = "\n".join(lines) % {"repo": repo, "rel": rel}
self.assertEqual(
- orig, cc_apt_configure.disable_suites(["proposed"], orig, rel))
+ orig, cc_apt_configure.disable_suites(["proposed"], orig, rel)
+ )
- @mock.patch("cloudinit.util.get_hostname", return_value='abc.localdomain')
+ @mock.patch("cloudinit.util.get_hostname", return_value="abc.localdomain")
def test_apt_v3_mirror_search_dns(self, m_get_hostname):
"""test_apt_v3_mirror_search_dns - Test searching dns patterns"""
pmir = "phit"
smir = "shit"
- arch = 'amd64'
- mycloud = get_cloud('ubuntu')
- cfg = {"primary": [{'arches': ["default"],
- "search_dns": True}],
- "security": [{'arches': ["default"],
- "search_dns": True}]}
-
- with mock.patch.object(cc_apt_configure, 'get_mirror',
- return_value="http://mocked/foo") as mockgm:
+ arch = "amd64"
+ mycloud = get_cloud("ubuntu")
+ cfg = {
+ "primary": [{"arches": ["default"], "search_dns": True}],
+ "security": [{"arches": ["default"], "search_dns": True}],
+ }
+
+ with mock.patch.object(
+ cc_apt_configure, "get_mirror", return_value="http://mocked/foo"
+ ) as mockgm:
mirrors = cc_apt_configure.find_apt_mirror_info(cfg, mycloud, arch)
- calls = [call(cfg, 'primary', arch, mycloud),
- call(cfg, 'security', arch, mycloud)]
+ calls = [
+ call(cfg, "primary", arch, mycloud),
+ call(cfg, "security", arch, mycloud),
+ ]
mockgm.assert_has_calls(calls)
- with mock.patch.object(cc_apt_configure, 'search_for_mirror_dns',
- return_value="http://mocked/foo") as mocksdns:
+ with mock.patch.object(
+ cc_apt_configure,
+ "search_for_mirror_dns",
+ return_value="http://mocked/foo",
+ ) as mocksdns:
mirrors = cc_apt_configure.find_apt_mirror_info(cfg, mycloud, arch)
- calls = [call(True, 'primary', cfg, mycloud),
- call(True, 'security', cfg, mycloud)]
+ calls = [
+ call(True, "primary", cfg, mycloud),
+ call(True, "security", cfg, mycloud),
+ ]
mocksdns.assert_has_calls(calls)
# first return is for the non-dns call before
- with mock.patch.object(cc_apt_configure.util, 'search_for_mirror',
- side_effect=[None, pmir, None, smir]) as mockse:
+ with mock.patch.object(
+ cc_apt_configure.util,
+ "search_for_mirror",
+ side_effect=[None, pmir, None, smir],
+ ) as mockse:
mirrors = cc_apt_configure.find_apt_mirror_info(cfg, mycloud, arch)
- calls = [call(None),
- call(['http://ubuntu-mirror.localdomain/ubuntu',
- 'http://ubuntu-mirror/ubuntu']),
- call(None),
- call(['http://ubuntu-security-mirror.localdomain/ubuntu',
- 'http://ubuntu-security-mirror/ubuntu'])]
+ calls = [
+ call(None),
+ call(
+ [
+ "http://ubuntu-mirror.localdomain/ubuntu",
+ "http://ubuntu-mirror/ubuntu",
+ ]
+ ),
+ call(None),
+ call(
+ [
+ "http://ubuntu-security-mirror.localdomain/ubuntu",
+ "http://ubuntu-security-mirror/ubuntu",
+ ]
+ ),
+ ]
mockse.assert_has_calls(calls)
- self.assertEqual(mirrors['MIRROR'],
- pmir)
- self.assertEqual(mirrors['PRIMARY'],
- pmir)
- self.assertEqual(mirrors['SECURITY'],
- smir)
+ self.assertEqual(mirrors["MIRROR"], pmir)
+ self.assertEqual(mirrors["PRIMARY"], pmir)
+ self.assertEqual(mirrors["SECURITY"], smir)
def test_apt_v3_add_mirror_keys(self):
"""test_apt_v3_add_mirror_keys - Test adding key for mirrors"""
- arch = 'amd64'
+ arch = "amd64"
cfg = {
- 'primary': [
- {'arches': [arch],
- 'uri': 'http://test.ubuntu.com/',
- 'filename': 'primary',
- 'key': 'fakekey_primary'}],
- 'security': [
- {'arches': [arch],
- 'uri': 'http://testsec.ubuntu.com/',
- 'filename': 'security',
- 'key': 'fakekey_security'}]
+ "primary": [
+ {
+ "arches": [arch],
+ "uri": "http://test.ubuntu.com/",
+ "filename": "primary",
+ "key": "fakekey_primary",
+ }
+ ],
+ "security": [
+ {
+ "arches": [arch],
+ "uri": "http://testsec.ubuntu.com/",
+ "filename": "security",
+ "key": "fakekey_security",
+ }
+ ],
}
- with mock.patch.object(cc_apt_configure,
- 'add_apt_key_raw') as mockadd:
+ with mock.patch.object(cc_apt_configure, "add_apt_key_raw") as mockadd:
cc_apt_configure.add_mirror_keys(cfg, TARGET)
calls = [
- mock.call('fakekey_primary', 'primary', hardened=False),
- mock.call('fakekey_security', 'security', hardened=False),
+ mock.call("fakekey_primary", "primary", hardened=False),
+ mock.call("fakekey_security", "security", hardened=False),
]
mockadd.assert_has_calls(calls, any_order=True)
class TestDebconfSelections(TestCase):
-
@mock.patch("cloudinit.config.cc_apt_configure.subp.subp")
def test_set_sel_appends_newline_if_absent(self, m_subp):
"""Automatically append a newline to debconf-set-selections config."""
- selections = b'some/setting boolean true'
+ selections = b"some/setting boolean true"
cc_apt_configure.debconf_set_selections(selections=selections)
- cc_apt_configure.debconf_set_selections(selections=selections + b'\n')
+ cc_apt_configure.debconf_set_selections(selections=selections + b"\n")
m_call = mock.call(
- ['debconf-set-selections'], data=selections + b'\n', capture=True,
- target=None)
+ ["debconf-set-selections"],
+ data=selections + b"\n",
+ capture=True,
+ target=None,
+ )
self.assertEqual([m_call, m_call], m_subp.call_args_list)
@mock.patch("cloudinit.config.cc_apt_configure.debconf_set_selections")
def test_no_set_sel_if_none_to_set(self, m_set_sel):
- cc_apt_configure.apply_debconf_selections({'foo': 'bar'})
+ cc_apt_configure.apply_debconf_selections({"foo": "bar"})
m_set_sel.assert_not_called()
- @mock.patch("cloudinit.config.cc_apt_configure."
- "debconf_set_selections")
- @mock.patch("cloudinit.config.cc_apt_configure."
- "util.get_installed_packages")
+ @mock.patch("cloudinit.config.cc_apt_configure.debconf_set_selections")
+ @mock.patch(
+ "cloudinit.config.cc_apt_configure.util.get_installed_packages"
+ )
def test_set_sel_call_has_expected_input(self, m_get_inst, m_set_sel):
data = {
- 'set1': 'pkga pkga/q1 mybool false',
- 'set2': ('pkgb\tpkgb/b1\tstr\tthis is a string\n'
- 'pkgc\tpkgc/ip\tstring\t10.0.0.1')}
- lines = '\n'.join(data.values()).split('\n')
+ "set1": "pkga pkga/q1 mybool false",
+ "set2": (
+ "pkgb\tpkgb/b1\tstr\tthis is a string\n"
+ "pkgc\tpkgc/ip\tstring\t10.0.0.1"
+ ),
+ }
+ lines = "\n".join(data.values()).split("\n")
m_get_inst.return_value = ["adduser", "apparmor"]
m_set_sel.return_value = None
- cc_apt_configure.apply_debconf_selections({'debconf_selections': data})
+ cc_apt_configure.apply_debconf_selections({"debconf_selections": data})
self.assertTrue(m_get_inst.called)
self.assertEqual(m_set_sel.call_count, 1)
@@ -1092,43 +1341,59 @@ class TestDebconfSelections(TestCase):
@mock.patch("cloudinit.config.cc_apt_configure.dpkg_reconfigure")
@mock.patch("cloudinit.config.cc_apt_configure.debconf_set_selections")
- @mock.patch("cloudinit.config.cc_apt_configure."
- "util.get_installed_packages")
- def test_reconfigure_if_intersection(self, m_get_inst, m_set_sel,
- m_dpkg_r):
+ @mock.patch(
+ "cloudinit.config.cc_apt_configure.util.get_installed_packages"
+ )
+ def test_reconfigure_if_intersection(
+ self, m_get_inst, m_set_sel, m_dpkg_r
+ ):
data = {
- 'set1': 'pkga pkga/q1 mybool false',
- 'set2': ('pkgb\tpkgb/b1\tstr\tthis is a string\n'
- 'pkgc\tpkgc/ip\tstring\t10.0.0.1'),
- 'cloud-init': ('cloud-init cloud-init/datasources'
- 'multiselect MAAS')}
+ "set1": "pkga pkga/q1 mybool false",
+ "set2": (
+ "pkgb\tpkgb/b1\tstr\tthis is a string\n"
+ "pkgc\tpkgc/ip\tstring\t10.0.0.1"
+ ),
+ "cloud-init": "cloud-init cloud-init/datasourcesmultiselect MAAS",
+ }
m_set_sel.return_value = None
- m_get_inst.return_value = ["adduser", "apparmor", "pkgb",
- "cloud-init", 'zdog']
+ m_get_inst.return_value = [
+ "adduser",
+ "apparmor",
+ "pkgb",
+ "cloud-init",
+ "zdog",
+ ]
- cc_apt_configure.apply_debconf_selections({'debconf_selections': data})
+ cc_apt_configure.apply_debconf_selections({"debconf_selections": data})
# reconfigure should be called with the intersection
# of (packages in config, packages installed)
self.assertEqual(m_dpkg_r.call_count, 1)
# assumes called with *args (dpkg_reconfigure([a,b,c], target=))
packages = m_dpkg_r.call_args_list[0][0][0]
- self.assertEqual(set(['cloud-init', 'pkgb']), set(packages))
+ self.assertEqual(set(["cloud-init", "pkgb"]), set(packages))
@mock.patch("cloudinit.config.cc_apt_configure.dpkg_reconfigure")
@mock.patch("cloudinit.config.cc_apt_configure.debconf_set_selections")
- @mock.patch("cloudinit.config.cc_apt_configure."
- "util.get_installed_packages")
- def test_reconfigure_if_no_intersection(self, m_get_inst, m_set_sel,
- m_dpkg_r):
- data = {'set1': 'pkga pkga/q1 mybool false'}
-
- m_get_inst.return_value = ["adduser", "apparmor", "pkgb",
- "cloud-init", 'zdog']
+ @mock.patch(
+ "cloudinit.config.cc_apt_configure.util.get_installed_packages"
+ )
+ def test_reconfigure_if_no_intersection(
+ self, m_get_inst, m_set_sel, m_dpkg_r
+ ):
+ data = {"set1": "pkga pkga/q1 mybool false"}
+
+ m_get_inst.return_value = [
+ "adduser",
+ "apparmor",
+ "pkgb",
+ "cloud-init",
+ "zdog",
+ ]
m_set_sel.return_value = None
- cc_apt_configure.apply_debconf_selections({'debconf_selections': data})
+ cc_apt_configure.apply_debconf_selections({"debconf_selections": data})
self.assertTrue(m_get_inst.called)
self.assertEqual(m_dpkg_r.call_count, 0)
@@ -1141,19 +1406,25 @@ class TestDebconfSelections(TestCase):
# mocking clean_cloud_init directly does not work. So we mock
# the CONFIG_CLEANERS dictionary and assert our cleaner is called.
ci_cleaner = mock.MagicMock()
- with mock.patch.dict(("cloudinit.config.cc_apt_configure."
- "CONFIG_CLEANERS"),
- values={'cloud-init': ci_cleaner}, clear=True):
- cc_apt_configure.dpkg_reconfigure(['pkga', 'cloud-init'],
- target=target)
+ with mock.patch.dict(
+ "cloudinit.config.cc_apt_configure.CONFIG_CLEANERS",
+ values={"cloud-init": ci_cleaner},
+ clear=True,
+ ):
+ cc_apt_configure.dpkg_reconfigure(
+ ["pkga", "cloud-init"], target=target
+ )
# cloud-init is actually the only package we have a cleaner for
# so for now, its the only one that should reconfigured
self.assertTrue(m_subp.called)
ci_cleaner.assert_called_with(target)
self.assertEqual(m_subp.call_count, 1)
found = m_subp.call_args_list[0][0][0]
- expected = ['dpkg-reconfigure', '--frontend=noninteractive',
- 'cloud-init']
+ expected = [
+ "dpkg-reconfigure",
+ "--frontend=noninteractive",
+ "cloud-init",
+ ]
self.assertEqual(expected, found)
@mock.patch("cloudinit.config.cc_apt_configure.subp.subp")
@@ -1163,8 +1434,9 @@ class TestDebconfSelections(TestCase):
@mock.patch("cloudinit.config.cc_apt_configure.subp.subp")
def test_dpkg_reconfigure_not_done_if_no_cleaners(self, m_subp):
- cc_apt_configure.dpkg_reconfigure(['pkgfoo', 'pkgbar'])
+ cc_apt_configure.dpkg_reconfigure(["pkgfoo", "pkgbar"])
m_subp.assert_not_called()
+
#
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_apk_configure.py b/tests/unittests/config/test_cc_apk_configure.py
index 70139451..6fbc3dec 100644
--- a/tests/unittests/config/test_cc_apk_configure.py
+++ b/tests/unittests/config/test_cc_apk_configure.py
@@ -8,20 +8,19 @@ import logging
import os
import textwrap
-from cloudinit import (cloud, helpers, util)
-
+from cloudinit import cloud, helpers, util
from cloudinit.config import cc_apk_configure
-from tests.unittests.helpers import (FilesystemMockingTestCase, mock)
+from tests.unittests.helpers import FilesystemMockingTestCase, mock
REPO_FILE = "/etc/apk/repositories"
DEFAULT_MIRROR_URL = "https://alpine.global.ssl.fastly.net/alpine"
-CC_APK = 'cloudinit.config.cc_apk_configure'
+CC_APK = "cloudinit.config.cc_apk_configure"
class TestNoConfig(FilesystemMockingTestCase):
def setUp(self):
super(TestNoConfig, self).setUp()
- self.add_patch(CC_APK + '._write_repositories_file', 'm_write_repos')
+ self.add_patch(CC_APK + "._write_repositories_file", "m_write_repos")
self.name = "apk-configure"
self.cloud_init = None
self.log = logging.getLogger("TestNoConfig")
@@ -34,8 +33,9 @@ class TestNoConfig(FilesystemMockingTestCase):
"""
config = util.get_builtin_cfg()
- cc_apk_configure.handle(self.name, config, self.cloud_init,
- self.log, self.args)
+ cc_apk_configure.handle(
+ self.name, config, self.cloud_init, self.log, self.args
+ )
self.assertEqual(0, self.m_write_repos.call_count)
@@ -45,15 +45,15 @@ class TestConfig(FilesystemMockingTestCase):
super(TestConfig, self).setUp()
self.new_root = self.tmp_dir()
self.new_root = self.reRoot(root=self.new_root)
- for dirname in ['tmp', 'etc/apk']:
+ for dirname in ["tmp", "etc/apk"]:
util.ensure_dir(os.path.join(self.new_root, dirname))
- self.paths = helpers.Paths({'templates_dir': self.new_root})
+ self.paths = helpers.Paths({"templates_dir": self.new_root})
self.name = "apk-configure"
self.cloud = cloud.Cloud(None, self.paths, None, None, None)
self.log = logging.getLogger("TestNoConfig")
self.args = []
- @mock.patch(CC_APK + '._write_repositories_file')
+ @mock.patch(CC_APK + "._write_repositories_file")
def test_no_repo_settings(self, m_write_repos):
"""
Test that nothing is written if the 'alpine-repo' key
@@ -61,20 +61,22 @@ class TestConfig(FilesystemMockingTestCase):
"""
config = {"apk_repos": {}}
- cc_apk_configure.handle(self.name, config, self.cloud, self.log,
- self.args)
+ cc_apk_configure.handle(
+ self.name, config, self.cloud, self.log, self.args
+ )
self.assertEqual(0, m_write_repos.call_count)
- @mock.patch(CC_APK + '._write_repositories_file')
+ @mock.patch(CC_APK + "._write_repositories_file")
def test_empty_repo_settings(self, m_write_repos):
"""
Test that nothing is written if 'alpine_repo' list is empty.
"""
config = {"apk_repos": {"alpine_repo": []}}
- cc_apk_configure.handle(self.name, config, self.cloud, self.log,
- self.args)
+ cc_apk_configure.handle(
+ self.name, config, self.cloud, self.log, self.args
+ )
self.assertEqual(0, m_write_repos.call_count)
@@ -82,19 +84,15 @@ class TestConfig(FilesystemMockingTestCase):
"""
Test when only details of main repo is written to file.
"""
- alpine_version = 'v3.12'
- config = {
- "apk_repos": {
- "alpine_repo": {
- "version": alpine_version
- }
- }
- }
+ alpine_version = "v3.12"
+ config = {"apk_repos": {"alpine_repo": {"version": alpine_version}}}
- cc_apk_configure.handle(self.name, config, self.cloud, self.log,
- self.args)
+ cc_apk_configure.handle(
+ self.name, config, self.cloud, self.log, self.args
+ )
- expected_content = textwrap.dedent("""\
+ expected_content = textwrap.dedent(
+ """\
#
# Created by cloud-init
#
@@ -103,7 +101,10 @@ class TestConfig(FilesystemMockingTestCase):
{0}/{1}/main
- """.format(DEFAULT_MIRROR_URL, alpine_version))
+ """.format(
+ DEFAULT_MIRROR_URL, alpine_version
+ )
+ )
self.assertEqual(expected_content, util.load_file(REPO_FILE))
@@ -112,20 +113,22 @@ class TestConfig(FilesystemMockingTestCase):
Test when only details of main and community repos are
written to file.
"""
- alpine_version = 'edge'
+ alpine_version = "edge"
config = {
"apk_repos": {
"alpine_repo": {
"version": alpine_version,
- "community_enabled": True
+ "community_enabled": True,
}
}
}
- cc_apk_configure.handle(self.name, config, self.cloud, self.log,
- self.args)
+ cc_apk_configure.handle(
+ self.name, config, self.cloud, self.log, self.args
+ )
- expected_content = textwrap.dedent("""\
+ expected_content = textwrap.dedent(
+ """\
#
# Created by cloud-init
#
@@ -135,7 +138,10 @@ class TestConfig(FilesystemMockingTestCase):
{0}/{1}/main
{0}/{1}/community
- """.format(DEFAULT_MIRROR_URL, alpine_version))
+ """.format(
+ DEFAULT_MIRROR_URL, alpine_version
+ )
+ )
self.assertEqual(expected_content, util.load_file(REPO_FILE))
@@ -144,21 +150,23 @@ class TestConfig(FilesystemMockingTestCase):
Test when details of main, community and testing repos
are written to file.
"""
- alpine_version = 'v3.12'
+ alpine_version = "v3.12"
config = {
"apk_repos": {
"alpine_repo": {
"version": alpine_version,
"community_enabled": True,
- "testing_enabled": True
+ "testing_enabled": True,
}
}
}
- cc_apk_configure.handle(self.name, config, self.cloud, self.log,
- self.args)
+ cc_apk_configure.handle(
+ self.name, config, self.cloud, self.log, self.args
+ )
- expected_content = textwrap.dedent("""\
+ expected_content = textwrap.dedent(
+ """\
#
# Created by cloud-init
#
@@ -172,7 +180,10 @@ class TestConfig(FilesystemMockingTestCase):
#
{0}/edge/testing
- """.format(DEFAULT_MIRROR_URL, alpine_version))
+ """.format(
+ DEFAULT_MIRROR_URL, alpine_version
+ )
+ )
self.assertEqual(expected_content, util.load_file(REPO_FILE))
@@ -181,21 +192,23 @@ class TestConfig(FilesystemMockingTestCase):
Test when details of main, community and testing repos
for Edge version of Alpine are written to file.
"""
- alpine_version = 'edge'
+ alpine_version = "edge"
config = {
"apk_repos": {
"alpine_repo": {
"version": alpine_version,
"community_enabled": True,
- "testing_enabled": True
+ "testing_enabled": True,
}
}
}
- cc_apk_configure.handle(self.name, config, self.cloud, self.log,
- self.args)
+ cc_apk_configure.handle(
+ self.name, config, self.cloud, self.log, self.args
+ )
- expected_content = textwrap.dedent("""\
+ expected_content = textwrap.dedent(
+ """\
#
# Created by cloud-init
#
@@ -206,7 +219,10 @@ class TestConfig(FilesystemMockingTestCase):
{0}/{1}/community
{0}/{1}/testing
- """.format(DEFAULT_MIRROR_URL, alpine_version))
+ """.format(
+ DEFAULT_MIRROR_URL, alpine_version
+ )
+ )
self.assertEqual(expected_content, util.load_file(REPO_FILE))
@@ -215,23 +231,25 @@ class TestConfig(FilesystemMockingTestCase):
Test when details of main, community, testing and
local repos are written to file.
"""
- alpine_version = 'v3.12'
- local_repo_url = 'http://some.mirror/whereever'
+ alpine_version = "v3.12"
+ local_repo_url = "http://some.mirror/whereever"
config = {
"apk_repos": {
"alpine_repo": {
"version": alpine_version,
"community_enabled": True,
- "testing_enabled": True
+ "testing_enabled": True,
},
- "local_repo_base_url": local_repo_url
+ "local_repo_base_url": local_repo_url,
}
}
- cc_apk_configure.handle(self.name, config, self.cloud, self.log,
- self.args)
+ cc_apk_configure.handle(
+ self.name, config, self.cloud, self.log, self.args
+ )
- expected_content = textwrap.dedent("""\
+ expected_content = textwrap.dedent(
+ """\
#
# Created by cloud-init
#
@@ -250,7 +268,10 @@ class TestConfig(FilesystemMockingTestCase):
#
{2}/{1}
- """.format(DEFAULT_MIRROR_URL, alpine_version, local_repo_url))
+ """.format(
+ DEFAULT_MIRROR_URL, alpine_version, local_repo_url
+ )
+ )
self.assertEqual(expected_content, util.load_file(REPO_FILE))
@@ -259,23 +280,25 @@ class TestConfig(FilesystemMockingTestCase):
Test when details of main, community, testing and local repos
for Edge version of Alpine are written to file.
"""
- alpine_version = 'edge'
- local_repo_url = 'http://some.mirror/whereever'
+ alpine_version = "edge"
+ local_repo_url = "http://some.mirror/whereever"
config = {
"apk_repos": {
"alpine_repo": {
"version": alpine_version,
"community_enabled": True,
- "testing_enabled": True
+ "testing_enabled": True,
},
- "local_repo_base_url": local_repo_url
+ "local_repo_base_url": local_repo_url,
}
}
- cc_apk_configure.handle(self.name, config, self.cloud, self.log,
- self.args)
+ cc_apk_configure.handle(
+ self.name, config, self.cloud, self.log, self.args
+ )
- expected_content = textwrap.dedent("""\
+ expected_content = textwrap.dedent(
+ """\
#
# Created by cloud-init
#
@@ -291,7 +314,10 @@ class TestConfig(FilesystemMockingTestCase):
#
{2}/{1}
- """.format(DEFAULT_MIRROR_URL, alpine_version, local_repo_url))
+ """.format(
+ DEFAULT_MIRROR_URL, alpine_version, local_repo_url
+ )
+ )
self.assertEqual(expected_content, util.load_file(REPO_FILE))
diff --git a/tests/unittests/config/test_cc_apt_pipelining.py b/tests/unittests/config/test_cc_apt_pipelining.py
index d7589d35..b4497156 100644
--- a/tests/unittests/config/test_cc_apt_pipelining.py
+++ b/tests/unittests/config/test_cc_apt_pipelining.py
@@ -3,26 +3,26 @@
"""Tests cc_apt_pipelining handler"""
import cloudinit.config.cc_apt_pipelining as cc_apt_pipelining
-
from tests.unittests.helpers import CiTestCase, mock
class TestAptPipelining(CiTestCase):
-
- @mock.patch('cloudinit.config.cc_apt_pipelining.util.write_file')
+ @mock.patch("cloudinit.config.cc_apt_pipelining.util.write_file")
def test_not_disabled_by_default(self, m_write_file):
"""ensure that default behaviour is to not disable pipelining"""
- cc_apt_pipelining.handle('foo', {}, None, mock.MagicMock(), None)
+ cc_apt_pipelining.handle("foo", {}, None, mock.MagicMock(), None)
self.assertEqual(0, m_write_file.call_count)
- @mock.patch('cloudinit.config.cc_apt_pipelining.util.write_file')
+ @mock.patch("cloudinit.config.cc_apt_pipelining.util.write_file")
def test_false_disables_pipelining(self, m_write_file):
"""ensure that pipelining can be disabled with correct config"""
cc_apt_pipelining.handle(
- 'foo', {'apt_pipelining': 'false'}, None, mock.MagicMock(), None)
+ "foo", {"apt_pipelining": "false"}, None, mock.MagicMock(), None
+ )
self.assertEqual(1, m_write_file.call_count)
args, _ = m_write_file.call_args
self.assertEqual(cc_apt_pipelining.DEFAULT_FILE, args[0])
self.assertIn('Pipeline-Depth "0"', args[1])
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_bootcmd.py b/tests/unittests/config/test_cc_bootcmd.py
index 6f38f12a..6d8793b9 100644
--- a/tests/unittests/config/test_cc_bootcmd.py
+++ b/tests/unittests/config/test_cc_bootcmd.py
@@ -2,11 +2,14 @@
import logging
import tempfile
+from cloudinit import subp, util
from cloudinit.config.cc_bootcmd import handle, schema
-from cloudinit import (subp, util)
from tests.unittests.helpers import (
- CiTestCase, mock, SchemaTestCaseMixin, skipUnlessJsonSchema)
-
+ CiTestCase,
+ SchemaTestCaseMixin,
+ mock,
+ skipUnlessJsonSchema,
+)
from tests.unittests.util import get_cloud
LOG = logging.getLogger(__name__)
@@ -16,7 +19,8 @@ class FakeExtendedTempFile(object):
def __init__(self, suffix):
self.suffix = suffix
self.handle = tempfile.NamedTemporaryFile(
- prefix="ci-%s." % self.__class__.__name__, delete=False)
+ prefix="ci-%s." % self.__class__.__name__, delete=False
+ )
def __enter__(self):
return self.handle
@@ -30,8 +34,9 @@ class TestBootcmd(CiTestCase):
with_logs = True
- _etmpfile_path = ('cloudinit.config.cc_bootcmd.temp_utils.'
- 'ExtendedTemporaryFile')
+ _etmpfile_path = (
+ "cloudinit.config.cc_bootcmd.temp_utils.ExtendedTemporaryFile"
+ )
def setUp(self):
super(TestBootcmd, self).setUp()
@@ -42,21 +47,23 @@ class TestBootcmd(CiTestCase):
"""When the provided config doesn't contain bootcmd, skip it."""
cfg = {}
mycloud = get_cloud()
- handle('notimportant', cfg, mycloud, LOG, None)
+ handle("notimportant", cfg, mycloud, LOG, None)
self.assertIn(
"Skipping module named notimportant, no 'bootcmd' key",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
def test_handler_invalid_command_set(self):
"""Commands which can't be converted to shell will raise errors."""
- invalid_config = {'bootcmd': 1}
+ invalid_config = {"bootcmd": 1}
cc = get_cloud()
with self.assertRaises(TypeError) as context_manager:
- handle('cc_bootcmd', invalid_config, cc, LOG, [])
- self.assertIn('Failed to shellify bootcmd', self.logs.getvalue())
+ handle("cc_bootcmd", invalid_config, cc, LOG, [])
+ self.assertIn("Failed to shellify bootcmd", self.logs.getvalue())
self.assertEqual(
"Input to shellify was type 'int'. Expected list or tuple.",
- str(context_manager.exception))
+ str(context_manager.exception),
+ )
@skipUnlessJsonSchema()
def test_handler_schema_validation_warns_non_array_type(self):
@@ -65,14 +72,15 @@ class TestBootcmd(CiTestCase):
Schema validation is not strict, so bootcmd attempts to shellify the
invalid content.
"""
- invalid_config = {'bootcmd': 1}
+ invalid_config = {"bootcmd": 1}
cc = get_cloud()
with self.assertRaises(TypeError):
- handle('cc_bootcmd', invalid_config, cc, LOG, [])
+ handle("cc_bootcmd", invalid_config, cc, LOG, [])
self.assertIn(
- 'Invalid config:\nbootcmd: 1 is not of type \'array\'',
- self.logs.getvalue())
- self.assertIn('Failed to shellify', self.logs.getvalue())
+ "Invalid config:\nbootcmd: 1 is not of type 'array'",
+ self.logs.getvalue(),
+ )
+ self.assertIn("Failed to shellify", self.logs.getvalue())
@skipUnlessJsonSchema()
def test_handler_schema_validation_warns_non_array_item_type(self):
@@ -82,54 +90,58 @@ class TestBootcmd(CiTestCase):
invalid content.
"""
invalid_config = {
- 'bootcmd': ['ls /', 20, ['wget', 'http://stuff/blah'], {'a': 'n'}]}
+ "bootcmd": ["ls /", 20, ["wget", "http://stuff/blah"], {"a": "n"}]
+ }
cc = get_cloud()
with self.assertRaises(TypeError) as context_manager:
- handle('cc_bootcmd', invalid_config, cc, LOG, [])
+ handle("cc_bootcmd", invalid_config, cc, LOG, [])
expected_warnings = [
- 'bootcmd.1: 20 is not valid under any of the given schemas',
- 'bootcmd.3: {\'a\': \'n\'} is not valid under any of the given'
- ' schema'
+ "bootcmd.1: 20 is not valid under any of the given schemas",
+ "bootcmd.3: {'a': 'n'} is not valid under any of the given schema",
]
logs = self.logs.getvalue()
for warning in expected_warnings:
self.assertIn(warning, logs)
- self.assertIn('Failed to shellify', logs)
+ self.assertIn("Failed to shellify", logs)
self.assertEqual(
- ("Unable to shellify type 'int'. Expected list, string, tuple. "
- "Got: 20"),
- str(context_manager.exception))
+ "Unable to shellify type 'int'. Expected list, string, tuple. "
+ "Got: 20",
+ str(context_manager.exception),
+ )
def test_handler_creates_and_runs_bootcmd_script_with_instance_id(self):
"""Valid schema runs a bootcmd script with INSTANCE_ID in the env."""
cc = get_cloud()
- out_file = self.tmp_path('bootcmd.out', self.new_root)
+ out_file = self.tmp_path("bootcmd.out", self.new_root)
my_id = "b6ea0f59-e27d-49c6-9f87-79f19765a425"
- valid_config = {'bootcmd': [
- 'echo {0} $INSTANCE_ID > {1}'.format(my_id, out_file)]}
+ valid_config = {
+ "bootcmd": ["echo {0} $INSTANCE_ID > {1}".format(my_id, out_file)]
+ }
with mock.patch(self._etmpfile_path, FakeExtendedTempFile):
- with self.allow_subp(['/bin/sh']):
- handle('cc_bootcmd', valid_config, cc, LOG, [])
- self.assertEqual(my_id + ' iid-datasource-none\n',
- util.load_file(out_file))
+ with self.allow_subp(["/bin/sh"]):
+ handle("cc_bootcmd", valid_config, cc, LOG, [])
+ self.assertEqual(
+ my_id + " iid-datasource-none\n", util.load_file(out_file)
+ )
def test_handler_runs_bootcmd_script_with_error(self):
"""When a valid script generates an error, that error is raised."""
cc = get_cloud()
- valid_config = {'bootcmd': ['exit 1']} # Script with error
+ valid_config = {"bootcmd": ["exit 1"]} # Script with error
with mock.patch(self._etmpfile_path, FakeExtendedTempFile):
- with self.allow_subp(['/bin/sh']):
+ with self.allow_subp(["/bin/sh"]):
with self.assertRaises(subp.ProcessExecutionError) as ctxt:
- handle('does-not-matter', valid_config, cc, LOG, [])
+ handle("does-not-matter", valid_config, cc, LOG, [])
self.assertIn(
- 'Unexpected error while running command.\n'
- "Command: ['/bin/sh',",
- str(ctxt.exception))
+ "Unexpected error while running command.\nCommand: ['/bin/sh',",
+ str(ctxt.exception),
+ )
self.assertIn(
- 'Failed to run bootcmd module does-not-matter',
- self.logs.getvalue())
+ "Failed to run bootcmd module does-not-matter",
+ self.logs.getvalue(),
+ )
@skipUnlessJsonSchema()
@@ -141,12 +153,14 @@ class TestSchema(CiTestCase, SchemaTestCaseMixin):
def test_duplicates_are_fine_array_array(self):
"""Duplicated commands array/array entries are allowed."""
self.assertSchemaValid(
- ["byebye", "byebye"], 'command entries can be duplicate')
+ ["byebye", "byebye"], "command entries can be duplicate"
+ )
def test_duplicates_are_fine_array_string(self):
"""Duplicated commands array/string entries are allowed."""
self.assertSchemaValid(
- ["echo bye", "echo bye"], "command entries can be duplicate.")
+ ["echo bye", "echo bye"], "command entries can be duplicate."
+ )
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_ca_certs.py b/tests/unittests/config/test_cc_ca_certs.py
index 91b005d0..c49922e6 100644
--- a/tests/unittests/config/test_cc_ca_certs.py
+++ b/tests/unittests/config/test_cc_ca_certs.py
@@ -6,13 +6,9 @@ import unittest
from contextlib import ExitStack
from unittest import mock
-from cloudinit import distros
+from cloudinit import distros, helpers, subp, util
from cloudinit.config import cc_ca_certs
-from cloudinit import helpers
-from cloudinit import subp
-from cloudinit import util
from tests.unittests.helpers import TestCase
-
from tests.unittests.util import get_cloud
@@ -31,12 +27,15 @@ class TestNoConfig(unittest.TestCase):
config = util.get_builtin_cfg()
with ExitStack() as mocks:
util_mock = mocks.enter_context(
- mock.patch.object(util, 'write_file'))
+ mock.patch.object(util, "write_file")
+ )
certs_mock = mocks.enter_context(
- mock.patch.object(cc_ca_certs, 'update_ca_certs'))
+ mock.patch.object(cc_ca_certs, "update_ca_certs")
+ )
- cc_ca_certs.handle(self.name, config, self.cloud_init, self.log,
- self.args)
+ cc_ca_certs.handle(
+ self.name, config, self.cloud_init, self.log, self.args
+ )
self.assertEqual(util_mock.call_count, 0)
self.assertEqual(certs_mock.call_count, 0)
@@ -61,11 +60,14 @@ class TestConfig(TestCase):
# Mock out the functions that actually modify the system
self.mock_add = self.mocks.enter_context(
- mock.patch.object(cc_ca_certs, 'add_ca_certs'))
+ mock.patch.object(cc_ca_certs, "add_ca_certs")
+ )
self.mock_update = self.mocks.enter_context(
- mock.patch.object(cc_ca_certs, 'update_ca_certs'))
+ mock.patch.object(cc_ca_certs, "update_ca_certs")
+ )
self.mock_remove = self.mocks.enter_context(
- mock.patch.object(cc_ca_certs, 'remove_default_ca_certs'))
+ mock.patch.object(cc_ca_certs, "remove_default_ca_certs")
+ )
def test_no_trusted_list(self):
"""
@@ -106,7 +108,7 @@ class TestConfig(TestCase):
conf = cc_ca_certs._distro_ca_certs_configs(distro_name)
cc_ca_certs.handle(self.name, config, cloud, self.log, self.args)
- self.mock_add.assert_called_once_with(conf, ['CERT1'])
+ self.mock_add.assert_called_once_with(conf, ["CERT1"])
self.assertEqual(self.mock_update.call_count, 1)
self.assertEqual(self.mock_remove.call_count, 0)
@@ -120,7 +122,7 @@ class TestConfig(TestCase):
conf = cc_ca_certs._distro_ca_certs_configs(distro_name)
cc_ca_certs.handle(self.name, config, cloud, self.log, self.args)
- self.mock_add.assert_called_once_with(conf, ['CERT1', 'CERT2'])
+ self.mock_add.assert_called_once_with(conf, ["CERT1", "CERT2"])
self.assertEqual(self.mock_update.call_count, 1)
self.assertEqual(self.mock_remove.call_count, 0)
@@ -160,20 +162,21 @@ class TestConfig(TestCase):
conf = cc_ca_certs._distro_ca_certs_configs(distro_name)
cc_ca_certs.handle(self.name, config, cloud, self.log, self.args)
- self.mock_add.assert_called_once_with(conf, ['CERT1'])
+ self.mock_add.assert_called_once_with(conf, ["CERT1"])
self.assertEqual(self.mock_update.call_count, 1)
self.assertEqual(self.mock_remove.call_count, 1)
class TestAddCaCerts(TestCase):
-
def setUp(self):
super(TestAddCaCerts, self).setUp()
tmpdir = tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, tmpdir)
- self.paths = helpers.Paths({
- 'cloud_dir': tmpdir,
- })
+ self.paths = helpers.Paths(
+ {
+ "cloud_dir": tmpdir,
+ }
+ )
self.add_patch("cloudinit.config.cc_ca_certs.os.stat", "m_stat")
def _fetch_distro(self, kind):
@@ -185,7 +188,7 @@ class TestAddCaCerts(TestCase):
"""Test that no certificate are written if not provided."""
for distro_name in cc_ca_certs.distros:
conf = cc_ca_certs._distro_ca_certs_configs(distro_name)
- with mock.patch.object(util, 'write_file') as mockobj:
+ with mock.patch.object(util, "write_file") as mockobj:
cc_ca_certs.add_ca_certs(conf, [])
self.assertEqual(mockobj.call_count, 0)
@@ -204,21 +207,28 @@ class TestAddCaCerts(TestCase):
with ExitStack() as mocks:
mock_write = mocks.enter_context(
- mock.patch.object(util, 'write_file'))
+ mock.patch.object(util, "write_file")
+ )
mock_load = mocks.enter_context(
- mock.patch.object(util, 'load_file',
- return_value=ca_certs_content))
+ mock.patch.object(
+ util, "load_file", return_value=ca_certs_content
+ )
+ )
cc_ca_certs.add_ca_certs(conf, [cert])
- mock_write.assert_has_calls([
- mock.call(conf['ca_cert_full_path'],
- cert, mode=0o644)])
- if conf['ca_cert_config'] is not None:
- mock_write.assert_has_calls([
- mock.call(conf['ca_cert_config'],
- expected, omode="wb")])
- mock_load.assert_called_once_with(conf['ca_cert_config'])
+ mock_write.assert_has_calls(
+ [mock.call(conf["ca_cert_full_path"], cert, mode=0o644)]
+ )
+ if conf["ca_cert_config"] is not None:
+ mock_write.assert_has_calls(
+ [
+ mock.call(
+ conf["ca_cert_config"], expected, omode="wb"
+ )
+ ]
+ )
+ mock_load.assert_called_once_with(conf["ca_cert_config"])
def test_single_cert_no_trailing_cr(self):
"""Test adding a single certificate to the trusted CAs
@@ -234,24 +244,32 @@ class TestAddCaCerts(TestCase):
with ExitStack() as mocks:
mock_write = mocks.enter_context(
- mock.patch.object(util, 'write_file'))
+ mock.patch.object(util, "write_file")
+ )
mock_load = mocks.enter_context(
- mock.patch.object(util, 'load_file',
- return_value=ca_certs_content))
+ mock.patch.object(
+ util, "load_file", return_value=ca_certs_content
+ )
+ )
cc_ca_certs.add_ca_certs(conf, [cert])
- mock_write.assert_has_calls([
- mock.call(conf['ca_cert_full_path'],
- cert, mode=0o644)])
- if conf['ca_cert_config'] is not None:
- mock_write.assert_has_calls([
- mock.call(conf['ca_cert_config'],
- "%s\n%s\n" % (ca_certs_content,
- conf['ca_cert_filename']),
- omode="wb")])
-
- mock_load.assert_called_once_with(conf['ca_cert_config'])
+ mock_write.assert_has_calls(
+ [mock.call(conf["ca_cert_full_path"], cert, mode=0o644)]
+ )
+ if conf["ca_cert_config"] is not None:
+ mock_write.assert_has_calls(
+ [
+ mock.call(
+ conf["ca_cert_config"],
+ "%s\n%s\n"
+ % (ca_certs_content, conf["ca_cert_filename"]),
+ omode="wb",
+ )
+ ]
+ )
+
+ mock_load.assert_called_once_with(conf["ca_cert_config"])
def test_single_cert_to_empty_existing_ca_file(self):
"""Test adding a single certificate to the trusted CAs
@@ -264,18 +282,23 @@ class TestAddCaCerts(TestCase):
for distro_name in cc_ca_certs.distros:
conf = cc_ca_certs._distro_ca_certs_configs(distro_name)
- with mock.patch.object(util, 'write_file',
- autospec=True) as m_write:
+ with mock.patch.object(
+ util, "write_file", autospec=True
+ ) as m_write:
cc_ca_certs.add_ca_certs(conf, [cert])
- m_write.assert_has_calls([
- mock.call(conf['ca_cert_full_path'],
- cert, mode=0o644)])
- if conf['ca_cert_config'] is not None:
- m_write.assert_has_calls([
- mock.call(conf['ca_cert_config'],
- expected, omode="wb")])
+ m_write.assert_has_calls(
+ [mock.call(conf["ca_cert_full_path"], cert, mode=0o644)]
+ )
+ if conf["ca_cert_config"] is not None:
+ m_write.assert_has_calls(
+ [
+ mock.call(
+ conf["ca_cert_config"], expected, omode="wb"
+ )
+ ]
+ )
def test_multiple_certs(self):
"""Test adding multiple certificates to the trusted CAs."""
@@ -290,45 +313,61 @@ class TestAddCaCerts(TestCase):
with ExitStack() as mocks:
mock_write = mocks.enter_context(
- mock.patch.object(util, 'write_file'))
+ mock.patch.object(util, "write_file")
+ )
mock_load = mocks.enter_context(
- mock.patch.object(util, 'load_file',
- return_value=ca_certs_content))
+ mock.patch.object(
+ util, "load_file", return_value=ca_certs_content
+ )
+ )
cc_ca_certs.add_ca_certs(conf, certs)
- mock_write.assert_has_calls([
- mock.call(conf['ca_cert_full_path'],
- expected_cert_file, mode=0o644)])
- if conf['ca_cert_config'] is not None:
- mock_write.assert_has_calls([
- mock.call(conf['ca_cert_config'],
- "%s\n%s\n" % (ca_certs_content,
- conf['ca_cert_filename']),
- omode='wb')])
-
- mock_load.assert_called_once_with(conf['ca_cert_config'])
+ mock_write.assert_has_calls(
+ [
+ mock.call(
+ conf["ca_cert_full_path"],
+ expected_cert_file,
+ mode=0o644,
+ )
+ ]
+ )
+ if conf["ca_cert_config"] is not None:
+ mock_write.assert_has_calls(
+ [
+ mock.call(
+ conf["ca_cert_config"],
+ "%s\n%s\n"
+ % (ca_certs_content, conf["ca_cert_filename"]),
+ omode="wb",
+ )
+ ]
+ )
+
+ mock_load.assert_called_once_with(conf["ca_cert_config"])
class TestUpdateCaCerts(unittest.TestCase):
def test_commands(self):
for distro_name in cc_ca_certs.distros:
conf = cc_ca_certs._distro_ca_certs_configs(distro_name)
- with mock.patch.object(subp, 'subp') as mockobj:
+ with mock.patch.object(subp, "subp") as mockobj:
cc_ca_certs.update_ca_certs(conf)
mockobj.assert_called_once_with(
- conf['ca_cert_update_cmd'], capture=False)
+ conf["ca_cert_update_cmd"], capture=False
+ )
class TestRemoveDefaultCaCerts(TestCase):
-
def setUp(self):
super(TestRemoveDefaultCaCerts, self).setUp()
tmpdir = tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, tmpdir)
- self.paths = helpers.Paths({
- 'cloud_dir': tmpdir,
- })
+ self.paths = helpers.Paths(
+ {
+ "cloud_dir": tmpdir,
+ }
+ )
def test_commands(self):
for distro_name in cc_ca_certs.distros:
@@ -336,26 +375,35 @@ class TestRemoveDefaultCaCerts(TestCase):
with ExitStack() as mocks:
mock_delete = mocks.enter_context(
- mock.patch.object(util, 'delete_dir_contents'))
+ mock.patch.object(util, "delete_dir_contents")
+ )
mock_write = mocks.enter_context(
- mock.patch.object(util, 'write_file'))
+ mock.patch.object(util, "write_file")
+ )
mock_subp = mocks.enter_context(
- mock.patch.object(subp, 'subp'))
+ mock.patch.object(subp, "subp")
+ )
cc_ca_certs.remove_default_ca_certs(distro_name, conf)
- mock_delete.assert_has_calls([
- mock.call(conf['ca_cert_path']),
- mock.call(conf['ca_cert_system_path'])])
+ mock_delete.assert_has_calls(
+ [
+ mock.call(conf["ca_cert_path"]),
+ mock.call(conf["ca_cert_system_path"]),
+ ]
+ )
- if conf['ca_cert_config'] is not None:
+ if conf["ca_cert_config"] is not None:
mock_write.assert_called_once_with(
- conf['ca_cert_config'], "", mode=0o644)
+ conf["ca_cert_config"], "", mode=0o644
+ )
- if distro_name in ['debian', 'ubuntu']:
+ if distro_name in ["debian", "ubuntu"]:
mock_subp.assert_called_once_with(
- ('debconf-set-selections', '-'),
- "ca-certificates \
-ca-certificates/trust_new_crts select no")
+ ("debconf-set-selections", "-"),
+ "ca-certificates ca-certificates/trust_new_crts"
+ " select no",
+ )
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_chef.py b/tests/unittests/config/test_cc_chef.py
index 1c90a4fc..835974e5 100644
--- a/tests/unittests/config/test_cc_chef.py
+++ b/tests/unittests/config/test_cc_chef.py
@@ -1,21 +1,20 @@
# This file is part of cloud-init. See LICENSE file for license information.
-import httpretty
import json
import logging
import os
-from cloudinit.config import cc_chef
-from cloudinit import util
+import httpretty
+from cloudinit import util
+from cloudinit.config import cc_chef
from tests.unittests.helpers import (
- HttprettyTestCase,
FilesystemMockingTestCase,
+ HttprettyTestCase,
+ cloud_init_project_dir,
mock,
skipIf,
- cloud_init_project_dir,
)
-
from tests.unittests.util import get_cloud
LOG = logging.getLogger(__name__)
@@ -31,7 +30,6 @@ OMNIBUS_URL_HTTP = cc_chef.OMNIBUS_URL.replace("https:", "http:")
class TestInstallChefOmnibus(HttprettyTestCase):
-
def setUp(self):
super(TestInstallChefOmnibus, self).setUp()
self.new_root = self.tmp_dir()
@@ -41,70 +39,81 @@ class TestInstallChefOmnibus(HttprettyTestCase):
"""install_chef_from_omnibus calls subp_blob_in_tempfile."""
response = b'#!/bin/bash\necho "Hi Mom"'
httpretty.register_uri(
- httpretty.GET, cc_chef.OMNIBUS_URL, body=response, status=200)
+ httpretty.GET, cc_chef.OMNIBUS_URL, body=response, status=200
+ )
ret = (None, None) # stdout, stderr but capture=False
- with mock.patch("cloudinit.config.cc_chef.subp_blob_in_tempfile",
- return_value=ret) as m_subp_blob:
+ with mock.patch(
+ "cloudinit.config.cc_chef.subp_blob_in_tempfile", return_value=ret
+ ) as m_subp_blob:
cc_chef.install_chef_from_omnibus()
# admittedly whitebox, but assuming subp_blob_in_tempfile works
# this should be fine.
self.assertEqual(
- [mock.call(blob=response, args=[], basename='chef-omnibus-install',
- capture=False)],
- m_subp_blob.call_args_list)
-
- @mock.patch('cloudinit.config.cc_chef.url_helper.readurl')
- @mock.patch('cloudinit.config.cc_chef.subp_blob_in_tempfile')
+ [
+ mock.call(
+ blob=response,
+ args=[],
+ basename="chef-omnibus-install",
+ capture=False,
+ )
+ ],
+ m_subp_blob.call_args_list,
+ )
+
+ @mock.patch("cloudinit.config.cc_chef.url_helper.readurl")
+ @mock.patch("cloudinit.config.cc_chef.subp_blob_in_tempfile")
def test_install_chef_from_omnibus_retries_url(self, m_subp_blob, m_rdurl):
"""install_chef_from_omnibus retries OMNIBUS_URL upon failure."""
class FakeURLResponse(object):
contents = '#!/bin/bash\necho "Hi Mom" > {0}/chef.out'.format(
- self.new_root)
+ self.new_root
+ )
m_rdurl.return_value = FakeURLResponse()
cc_chef.install_chef_from_omnibus()
- expected_kwargs = {'retries': cc_chef.OMNIBUS_URL_RETRIES,
- 'url': cc_chef.OMNIBUS_URL}
+ expected_kwargs = {
+ "retries": cc_chef.OMNIBUS_URL_RETRIES,
+ "url": cc_chef.OMNIBUS_URL,
+ }
self.assertCountEqual(expected_kwargs, m_rdurl.call_args_list[0][1])
cc_chef.install_chef_from_omnibus(retries=10)
- expected_kwargs = {'retries': 10,
- 'url': cc_chef.OMNIBUS_URL}
+ expected_kwargs = {"retries": 10, "url": cc_chef.OMNIBUS_URL}
self.assertCountEqual(expected_kwargs, m_rdurl.call_args_list[1][1])
expected_subp_kwargs = {
- 'args': ['-v', '2.0'],
- 'basename': 'chef-omnibus-install',
- 'blob': m_rdurl.return_value.contents,
- 'capture': False
+ "args": ["-v", "2.0"],
+ "basename": "chef-omnibus-install",
+ "blob": m_rdurl.return_value.contents,
+ "capture": False,
}
self.assertCountEqual(
- expected_subp_kwargs,
- m_subp_blob.call_args_list[0][1])
+ expected_subp_kwargs, m_subp_blob.call_args_list[0][1]
+ )
@mock.patch("cloudinit.config.cc_chef.OMNIBUS_URL", OMNIBUS_URL_HTTP)
- @mock.patch('cloudinit.config.cc_chef.subp_blob_in_tempfile')
+ @mock.patch("cloudinit.config.cc_chef.subp_blob_in_tempfile")
def test_install_chef_from_omnibus_has_omnibus_version(self, m_subp_blob):
"""install_chef_from_omnibus provides version arg to OMNIBUS_URL."""
- chef_outfile = self.tmp_path('chef.out', self.new_root)
+ chef_outfile = self.tmp_path("chef.out", self.new_root)
response = '#!/bin/bash\necho "Hi Mom" > {0}'.format(chef_outfile)
httpretty.register_uri(
- httpretty.GET, cc_chef.OMNIBUS_URL, body=response)
- cc_chef.install_chef_from_omnibus(omnibus_version='2.0')
+ httpretty.GET, cc_chef.OMNIBUS_URL, body=response
+ )
+ cc_chef.install_chef_from_omnibus(omnibus_version="2.0")
called_kwargs = m_subp_blob.call_args_list[0][1]
expected_kwargs = {
- 'args': ['-v', '2.0'],
- 'basename': 'chef-omnibus-install',
- 'blob': response,
- 'capture': False
+ "args": ["-v", "2.0"],
+ "basename": "chef-omnibus-install",
+ "blob": response,
+ "capture": False,
}
self.assertCountEqual(expected_kwargs, called_kwargs)
class TestChef(FilesystemMockingTestCase):
-
def setUp(self):
super(TestChef, self).setUp()
self.tmp = self.tmp_dir()
@@ -114,12 +123,13 @@ class TestChef(FilesystemMockingTestCase):
self.patchOS(self.tmp)
cfg = {}
- cc_chef.handle('chef', cfg, get_cloud(), LOG, [])
+ cc_chef.handle("chef", cfg, get_cloud(), LOG, [])
for d in cc_chef.CHEF_DIRS:
self.assertFalse(os.path.isdir(d))
- @skipIf(not os.path.isfile(CLIENT_TEMPL),
- CLIENT_TEMPL + " is not available")
+ @skipIf(
+ not os.path.isfile(CLIENT_TEMPL), CLIENT_TEMPL + " is not available"
+ )
def test_basic_config(self):
"""
test basic config looks sane
@@ -147,26 +157,27 @@ class TestChef(FilesystemMockingTestCase):
self.patchUtils(self.tmp)
self.patchOS(self.tmp)
- util.write_file('/etc/cloud/templates/chef_client.rb.tmpl', tpl_file)
+ util.write_file("/etc/cloud/templates/chef_client.rb.tmpl", tpl_file)
cfg = {
- 'chef': {
- 'chef_license': "accept",
- 'server_url': 'localhost',
- 'validation_name': 'bob',
- 'validation_key': "/etc/chef/vkey.pem",
- 'validation_cert': "this is my cert",
- 'encrypted_data_bag_secret':
- '/etc/chef/encrypted_data_bag_secret'
+ "chef": {
+ "chef_license": "accept",
+ "server_url": "localhost",
+ "validation_name": "bob",
+ "validation_key": "/etc/chef/vkey.pem",
+ "validation_cert": "this is my cert",
+ "encrypted_data_bag_secret": (
+ "/etc/chef/encrypted_data_bag_secret"
+ ),
},
}
- cc_chef.handle('chef', cfg, get_cloud(), LOG, [])
+ cc_chef.handle("chef", cfg, get_cloud(), LOG, [])
for d in cc_chef.CHEF_DIRS:
self.assertTrue(os.path.isdir(d))
c = util.load_file(cc_chef.CHEF_RB_PATH)
# the content of these keys is not expected to be rendered to tmpl
- unrendered_keys = ('validation_cert',)
- for k, v in cfg['chef'].items():
+ unrendered_keys = ("validation_cert",)
+ for k, v in cfg["chef"].items():
if k in unrendered_keys:
continue
self.assertIn(v, c)
@@ -174,7 +185,7 @@ class TestChef(FilesystemMockingTestCase):
if k in unrendered_keys:
continue
# the value from the cfg overrides that in the default
- val = cfg['chef'].get(k, v)
+ val = cfg["chef"].get(k, v)
if isinstance(val, str):
self.assertIn(val, c)
c = util.load_file(cc_chef.CHEF_FB_PATH)
@@ -185,64 +196,68 @@ class TestChef(FilesystemMockingTestCase):
self.patchOS(self.tmp)
cfg = {
- 'chef': {
- 'server_url': 'localhost',
- 'validation_name': 'bob',
- 'run_list': ['a', 'b', 'c'],
- 'initial_attributes': {
- 'c': 'd',
- }
+ "chef": {
+ "server_url": "localhost",
+ "validation_name": "bob",
+ "run_list": ["a", "b", "c"],
+ "initial_attributes": {
+ "c": "d",
+ },
},
}
- cc_chef.handle('chef', cfg, get_cloud(), LOG, [])
+ cc_chef.handle("chef", cfg, get_cloud(), LOG, [])
c = util.load_file(cc_chef.CHEF_FB_PATH)
self.assertEqual(
{
- 'run_list': ['a', 'b', 'c'],
- 'c': 'd',
- }, json.loads(c))
+ "run_list": ["a", "b", "c"],
+ "c": "d",
+ },
+ json.loads(c),
+ )
- @skipIf(not os.path.isfile(CLIENT_TEMPL),
- CLIENT_TEMPL + " is not available")
+ @skipIf(
+ not os.path.isfile(CLIENT_TEMPL), CLIENT_TEMPL + " is not available"
+ )
def test_template_deletes(self):
tpl_file = util.load_file(CLIENT_TEMPL)
self.patchUtils(self.tmp)
self.patchOS(self.tmp)
- util.write_file('/etc/cloud/templates/chef_client.rb.tmpl', tpl_file)
+ util.write_file("/etc/cloud/templates/chef_client.rb.tmpl", tpl_file)
cfg = {
- 'chef': {
- 'server_url': 'localhost',
- 'validation_name': 'bob',
- 'json_attribs': None,
- 'show_time': None,
+ "chef": {
+ "server_url": "localhost",
+ "validation_name": "bob",
+ "json_attribs": None,
+ "show_time": None,
},
}
- cc_chef.handle('chef', cfg, get_cloud(), LOG, [])
+ cc_chef.handle("chef", cfg, get_cloud(), LOG, [])
c = util.load_file(cc_chef.CHEF_RB_PATH)
- self.assertNotIn('json_attribs', c)
- self.assertNotIn('Formatter.show_time', c)
+ self.assertNotIn("json_attribs", c)
+ self.assertNotIn("Formatter.show_time", c)
- @skipIf(not os.path.isfile(CLIENT_TEMPL),
- CLIENT_TEMPL + " is not available")
+ @skipIf(
+ not os.path.isfile(CLIENT_TEMPL), CLIENT_TEMPL + " is not available"
+ )
def test_validation_cert_and_validation_key(self):
# test validation_cert content is written to validation_key path
tpl_file = util.load_file(CLIENT_TEMPL)
self.patchUtils(self.tmp)
self.patchOS(self.tmp)
- util.write_file('/etc/cloud/templates/chef_client.rb.tmpl', tpl_file)
- v_path = '/etc/chef/vkey.pem'
- v_cert = 'this is my cert'
+ util.write_file("/etc/cloud/templates/chef_client.rb.tmpl", tpl_file)
+ v_path = "/etc/chef/vkey.pem"
+ v_cert = "this is my cert"
cfg = {
- 'chef': {
- 'server_url': 'localhost',
- 'validation_name': 'bob',
- 'validation_key': v_path,
- 'validation_cert': v_cert
+ "chef": {
+ "server_url": "localhost",
+ "validation_name": "bob",
+ "validation_key": v_path,
+ "validation_cert": v_cert,
},
}
- cc_chef.handle('chef', cfg, get_cloud(), LOG, [])
+ cc_chef.handle("chef", cfg, get_cloud(), LOG, [])
content = util.load_file(cc_chef.CHEF_RB_PATH)
self.assertIn(v_path, content)
util.load_file(v_path)
@@ -254,23 +269,24 @@ class TestChef(FilesystemMockingTestCase):
self.patchUtils(self.tmp)
self.patchOS(self.tmp)
- v_path = '/etc/chef/vkey.pem'
+ v_path = "/etc/chef/vkey.pem"
v_cert = "system"
expected_cert = "this is the system file certificate"
cfg = {
- 'chef': {
- 'server_url': 'localhost',
- 'validation_name': 'bob',
- 'validation_key': v_path,
- 'validation_cert': v_cert
+ "chef": {
+ "server_url": "localhost",
+ "validation_name": "bob",
+ "validation_key": v_path,
+ "validation_cert": v_cert,
},
}
- util.write_file('/etc/cloud/templates/chef_client.rb.tmpl', tpl_file)
+ util.write_file("/etc/cloud/templates/chef_client.rb.tmpl", tpl_file)
util.write_file(v_path, expected_cert)
- cc_chef.handle('chef', cfg, get_cloud(), LOG, [])
+ cc_chef.handle("chef", cfg, get_cloud(), LOG, [])
content = util.load_file(cc_chef.CHEF_RB_PATH)
self.assertIn(v_path, content)
util.load_file(v_path)
self.assertEqual(expected_cert, util.load_file(v_path))
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_debug.py b/tests/unittests/config/test_cc_debug.py
index 174f772f..79a88561 100644
--- a/tests/unittests/config/test_cc_debug.py
+++ b/tests/unittests/config/test_cc_debug.py
@@ -7,14 +7,13 @@ import tempfile
from cloudinit import util
from cloudinit.config import cc_debug
-from tests.unittests.helpers import (FilesystemMockingTestCase, mock)
-
+from tests.unittests.helpers import FilesystemMockingTestCase, mock
from tests.unittests.util import get_cloud
LOG = logging.getLogger(__name__)
-@mock.patch('cloudinit.distros.debian.read_system_locale')
+@mock.patch("cloudinit.distros.debian.read_system_locale")
class TestDebug(FilesystemMockingTestCase):
def setUp(self):
super(TestDebug, self).setUp()
@@ -23,37 +22,39 @@ class TestDebug(FilesystemMockingTestCase):
self.patchUtils(self.new_root)
def test_debug_write(self, m_locale):
- m_locale.return_value = 'en_US.UTF-8'
+ m_locale.return_value = "en_US.UTF-8"
cfg = {
- 'abc': '123',
- 'c': '\u20a0',
- 'debug': {
- 'verbose': True,
+ "abc": "123",
+ "c": "\u20a0",
+ "debug": {
+ "verbose": True,
# Does not actually write here due to mocking...
- 'output': '/var/log/cloud-init-debug.log',
+ "output": "/var/log/cloud-init-debug.log",
},
}
cc = get_cloud()
- cc_debug.handle('cc_debug', cfg, cc, LOG, [])
- contents = util.load_file('/var/log/cloud-init-debug.log')
+ cc_debug.handle("cc_debug", cfg, cc, LOG, [])
+ contents = util.load_file("/var/log/cloud-init-debug.log")
# Some basic sanity tests...
self.assertNotEqual(0, len(contents))
for k in cfg.keys():
self.assertIn(k, contents)
def test_debug_no_write(self, m_locale):
- m_locale.return_value = 'en_US.UTF-8'
+ m_locale.return_value = "en_US.UTF-8"
cfg = {
- 'abc': '123',
- 'debug': {
- 'verbose': False,
+ "abc": "123",
+ "debug": {
+ "verbose": False,
# Does not actually write here due to mocking...
- 'output': '/var/log/cloud-init-debug.log',
+ "output": "/var/log/cloud-init-debug.log",
},
}
cc = get_cloud()
- cc_debug.handle('cc_debug', cfg, cc, LOG, [])
- self.assertRaises(IOError,
- util.load_file, '/var/log/cloud-init-debug.log')
+ cc_debug.handle("cc_debug", cfg, cc, LOG, [])
+ self.assertRaises(
+ IOError, util.load_file, "/var/log/cloud-init-debug.log"
+ )
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_disable_ec2_metadata.py b/tests/unittests/config/test_cc_disable_ec2_metadata.py
index 7a794845..3c3313a7 100644
--- a/tests/unittests/config/test_cc_disable_ec2_metadata.py
+++ b/tests/unittests/config/test_cc_disable_ec2_metadata.py
@@ -2,47 +2,49 @@
"""Tests cc_disable_ec2_metadata handler"""
-import cloudinit.config.cc_disable_ec2_metadata as ec2_meta
+import logging
+import cloudinit.config.cc_disable_ec2_metadata as ec2_meta
from tests.unittests.helpers import CiTestCase, mock
-import logging
-
LOG = logging.getLogger(__name__)
-DISABLE_CFG = {'disable_ec2_metadata': 'true'}
+DISABLE_CFG = {"disable_ec2_metadata": "true"}
class TestEC2MetadataRoute(CiTestCase):
-
- @mock.patch('cloudinit.config.cc_disable_ec2_metadata.subp.which')
- @mock.patch('cloudinit.config.cc_disable_ec2_metadata.subp.subp')
+ @mock.patch("cloudinit.config.cc_disable_ec2_metadata.subp.which")
+ @mock.patch("cloudinit.config.cc_disable_ec2_metadata.subp.subp")
def test_disable_ifconfig(self, m_subp, m_which):
"""Set the route if ifconfig command is available"""
- m_which.side_effect = lambda x: x if x == 'ifconfig' else None
- ec2_meta.handle('foo', DISABLE_CFG, None, LOG, None)
+ m_which.side_effect = lambda x: x if x == "ifconfig" else None
+ ec2_meta.handle("foo", DISABLE_CFG, None, LOG, None)
m_subp.assert_called_with(
- ['route', 'add', '-host', '169.254.169.254', 'reject'],
- capture=False)
+ ["route", "add", "-host", "169.254.169.254", "reject"],
+ capture=False,
+ )
- @mock.patch('cloudinit.config.cc_disable_ec2_metadata.subp.which')
- @mock.patch('cloudinit.config.cc_disable_ec2_metadata.subp.subp')
+ @mock.patch("cloudinit.config.cc_disable_ec2_metadata.subp.which")
+ @mock.patch("cloudinit.config.cc_disable_ec2_metadata.subp.subp")
def test_disable_ip(self, m_subp, m_which):
"""Set the route if ip command is available"""
- m_which.side_effect = lambda x: x if x == 'ip' else None
- ec2_meta.handle('foo', DISABLE_CFG, None, LOG, None)
+ m_which.side_effect = lambda x: x if x == "ip" else None
+ ec2_meta.handle("foo", DISABLE_CFG, None, LOG, None)
m_subp.assert_called_with(
- ['ip', 'route', 'add', 'prohibit', '169.254.169.254'],
- capture=False)
+ ["ip", "route", "add", "prohibit", "169.254.169.254"],
+ capture=False,
+ )
- @mock.patch('cloudinit.config.cc_disable_ec2_metadata.subp.which')
- @mock.patch('cloudinit.config.cc_disable_ec2_metadata.subp.subp')
+ @mock.patch("cloudinit.config.cc_disable_ec2_metadata.subp.which")
+ @mock.patch("cloudinit.config.cc_disable_ec2_metadata.subp.subp")
def test_disable_no_tool(self, m_subp, m_which):
"""Log error when neither route nor ip commands are available"""
m_which.return_value = None # Find neither ifconfig nor ip
- ec2_meta.handle('foo', DISABLE_CFG, None, LOG, None)
+ ec2_meta.handle("foo", DISABLE_CFG, None, LOG, None)
self.assertEqual(
- [mock.call('ip'), mock.call('ifconfig')], m_which.call_args_list)
+ [mock.call("ip"), mock.call("ifconfig")], m_which.call_args_list
+ )
m_subp.assert_not_called()
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_disk_setup.py b/tests/unittests/config/test_cc_disk_setup.py
index fa565559..8a8d7195 100644
--- a/tests/unittests/config/test_cc_disk_setup.py
+++ b/tests/unittests/config/test_cc_disk_setup.py
@@ -3,19 +3,20 @@
import random
from cloudinit.config import cc_disk_setup
-from tests.unittests.helpers import CiTestCase, ExitStack, mock, TestCase
+from tests.unittests.helpers import CiTestCase, ExitStack, TestCase, mock
class TestIsDiskUsed(TestCase):
-
def setUp(self):
super(TestIsDiskUsed, self).setUp()
self.patches = ExitStack()
- mod_name = 'cloudinit.config.cc_disk_setup'
+ mod_name = "cloudinit.config.cc_disk_setup"
self.enumerate_disk = self.patches.enter_context(
- mock.patch('{0}.enumerate_disk'.format(mod_name)))
+ mock.patch("{0}.enumerate_disk".format(mod_name))
+ )
self.check_fs = self.patches.enter_context(
- mock.patch('{0}.check_fs'.format(mod_name)))
+ mock.patch("{0}.check_fs".format(mod_name))
+ )
def tearDown(self):
super(TestIsDiskUsed, self).tearDown()
@@ -29,7 +30,10 @@ class TestIsDiskUsed(TestCase):
def test_valid_filesystem_returns_true(self):
self.enumerate_disk.return_value = (mock.MagicMock() for _ in range(1))
self.check_fs.return_value = (
- mock.MagicMock(), 'ext4', mock.MagicMock())
+ mock.MagicMock(),
+ "ext4",
+ mock.MagicMock(),
+ )
self.assertTrue(cc_disk_setup.is_disk_used(mock.MagicMock()))
def test_one_child_nodes_and_no_fs_returns_false(self):
@@ -39,12 +43,12 @@ class TestIsDiskUsed(TestCase):
class TestGetMbrHddSize(TestCase):
-
def setUp(self):
super(TestGetMbrHddSize, self).setUp()
self.patches = ExitStack()
self.subp = self.patches.enter_context(
- mock.patch.object(cc_disk_setup.subp, 'subp'))
+ mock.patch.object(cc_disk_setup.subp, "subp")
+ )
def tearDown(self):
super(TestGetMbrHddSize, self).tearDown()
@@ -53,11 +57,11 @@ class TestGetMbrHddSize(TestCase):
def _configure_subp_mock(self, hdd_size_in_bytes, sector_size_in_bytes):
def _subp(cmd, *args, **kwargs):
self.assertEqual(3, len(cmd))
- if '--getsize64' in cmd:
+ if "--getsize64" in cmd:
return hdd_size_in_bytes, None
- elif '--getss' in cmd:
+ elif "--getss" in cmd:
return sector_size_in_bytes, None
- raise Exception('Unexpected blockdev command called')
+ raise Exception("Unexpected blockdev command called")
self.subp.side_effect = _subp
@@ -65,8 +69,9 @@ class TestGetMbrHddSize(TestCase):
size_in_bytes = random.randint(10000, 10000000) * 512
size_in_sectors = size_in_bytes / sector_size
self._configure_subp_mock(size_in_bytes, sector_size)
- self.assertEqual(size_in_sectors,
- cc_disk_setup.get_hdd_size('/dev/sda1'))
+ self.assertEqual(
+ size_in_sectors, cc_disk_setup.get_hdd_size("/dev/sda1")
+ )
def test_size_for_512_byte_sectors(self):
self._test_for_sector_size(512)
@@ -82,98 +87,116 @@ class TestGetMbrHddSize(TestCase):
class TestGetPartitionMbrLayout(TestCase):
-
def test_single_partition_using_boolean(self):
- self.assertEqual('0,',
- cc_disk_setup.get_partition_mbr_layout(1000, True))
+ self.assertEqual(
+ "0,", cc_disk_setup.get_partition_mbr_layout(1000, True)
+ )
def test_single_partition_using_list(self):
disk_size = random.randint(1000000, 1000000000000)
self.assertEqual(
- ',,83',
- cc_disk_setup.get_partition_mbr_layout(disk_size, [100]))
+ ",,83", cc_disk_setup.get_partition_mbr_layout(disk_size, [100])
+ )
def test_half_and_half(self):
disk_size = random.randint(1000000, 1000000000000)
expected_partition_size = int(float(disk_size) / 2)
self.assertEqual(
- ',{0},83\n,,83'.format(expected_partition_size),
- cc_disk_setup.get_partition_mbr_layout(disk_size, [50, 50]))
+ ",{0},83\n,,83".format(expected_partition_size),
+ cc_disk_setup.get_partition_mbr_layout(disk_size, [50, 50]),
+ )
def test_thirds_with_different_partition_type(self):
disk_size = random.randint(1000000, 1000000000000)
expected_partition_size = int(float(disk_size) * 0.33)
self.assertEqual(
- ',{0},83\n,,82'.format(expected_partition_size),
- cc_disk_setup.get_partition_mbr_layout(disk_size, [33, [66, 82]]))
+ ",{0},83\n,,82".format(expected_partition_size),
+ cc_disk_setup.get_partition_mbr_layout(disk_size, [33, [66, 82]]),
+ )
class TestUpdateFsSetupDevices(TestCase):
def test_regression_1634678(self):
# Cf. https://bugs.launchpad.net/cloud-init/+bug/1634678
fs_setup = {
- 'partition': 'auto',
- 'device': '/dev/xvdb1',
- 'overwrite': False,
- 'label': 'test',
- 'filesystem': 'ext4'
+ "partition": "auto",
+ "device": "/dev/xvdb1",
+ "overwrite": False,
+ "label": "test",
+ "filesystem": "ext4",
}
- cc_disk_setup.update_fs_setup_devices([fs_setup],
- lambda device: device)
+ cc_disk_setup.update_fs_setup_devices(
+ [fs_setup], lambda device: device
+ )
- self.assertEqual({
- '_origname': '/dev/xvdb1',
- 'partition': 'auto',
- 'device': '/dev/xvdb1',
- 'overwrite': False,
- 'label': 'test',
- 'filesystem': 'ext4'
- }, fs_setup)
+ self.assertEqual(
+ {
+ "_origname": "/dev/xvdb1",
+ "partition": "auto",
+ "device": "/dev/xvdb1",
+ "overwrite": False,
+ "label": "test",
+ "filesystem": "ext4",
+ },
+ fs_setup,
+ )
def test_dotted_devname(self):
fs_setup = {
- 'partition': 'auto',
- 'device': 'ephemeral0.0',
- 'label': 'test2',
- 'filesystem': 'xfs'
+ "partition": "auto",
+ "device": "ephemeral0.0",
+ "label": "test2",
+ "filesystem": "xfs",
}
- cc_disk_setup.update_fs_setup_devices([fs_setup],
- lambda device: device)
+ cc_disk_setup.update_fs_setup_devices(
+ [fs_setup], lambda device: device
+ )
- self.assertEqual({
- '_origname': 'ephemeral0.0',
- '_partition': 'auto',
- 'partition': '0',
- 'device': 'ephemeral0',
- 'label': 'test2',
- 'filesystem': 'xfs'
- }, fs_setup)
+ self.assertEqual(
+ {
+ "_origname": "ephemeral0.0",
+ "_partition": "auto",
+ "partition": "0",
+ "device": "ephemeral0",
+ "label": "test2",
+ "filesystem": "xfs",
+ },
+ fs_setup,
+ )
def test_dotted_devname_populates_partition(self):
fs_setup = {
- 'device': 'ephemeral0.1',
- 'label': 'test2',
- 'filesystem': 'xfs'
+ "device": "ephemeral0.1",
+ "label": "test2",
+ "filesystem": "xfs",
}
- cc_disk_setup.update_fs_setup_devices([fs_setup],
- lambda device: device)
- self.assertEqual({
- '_origname': 'ephemeral0.1',
- 'device': 'ephemeral0',
- 'partition': '1',
- 'label': 'test2',
- 'filesystem': 'xfs'
- }, fs_setup)
-
-
-@mock.patch('cloudinit.config.cc_disk_setup.assert_and_settle_device',
- return_value=None)
-@mock.patch('cloudinit.config.cc_disk_setup.find_device_node',
- return_value=('/dev/xdb1', False))
-@mock.patch('cloudinit.config.cc_disk_setup.device_type', return_value=None)
-@mock.patch('cloudinit.config.cc_disk_setup.subp.subp', return_value=('', ''))
+ cc_disk_setup.update_fs_setup_devices(
+ [fs_setup], lambda device: device
+ )
+ self.assertEqual(
+ {
+ "_origname": "ephemeral0.1",
+ "device": "ephemeral0",
+ "partition": "1",
+ "label": "test2",
+ "filesystem": "xfs",
+ },
+ fs_setup,
+ )
+
+
+@mock.patch(
+ "cloudinit.config.cc_disk_setup.assert_and_settle_device",
+ return_value=None,
+)
+@mock.patch(
+ "cloudinit.config.cc_disk_setup.find_device_node",
+ return_value=("/dev/xdb1", False),
+)
+@mock.patch("cloudinit.config.cc_disk_setup.device_type", return_value=None)
+@mock.patch("cloudinit.config.cc_disk_setup.subp.subp", return_value=("", ""))
class TestMkfsCommandHandling(CiTestCase):
with_logs = True
@@ -181,63 +204,84 @@ class TestMkfsCommandHandling(CiTestCase):
def test_with_cmd(self, subp, *args):
"""mkfs honors cmd and logs warnings when extra_opts or overwrite are
provided."""
- cc_disk_setup.mkfs({
- 'cmd': 'mkfs -t %(filesystem)s -L %(label)s %(device)s',
- 'filesystem': 'ext4',
- 'device': '/dev/xdb1',
- 'label': 'with_cmd',
- 'extra_opts': ['should', 'generate', 'warning'],
- 'overwrite': 'should generate warning too'
- })
+ cc_disk_setup.mkfs(
+ {
+ "cmd": "mkfs -t %(filesystem)s -L %(label)s %(device)s",
+ "filesystem": "ext4",
+ "device": "/dev/xdb1",
+ "label": "with_cmd",
+ "extra_opts": ["should", "generate", "warning"],
+ "overwrite": "should generate warning too",
+ }
+ )
self.assertIn(
- 'extra_opts ' +
- 'ignored because cmd was specified: mkfs -t ext4 -L with_cmd ' +
- '/dev/xdb1',
- self.logs.getvalue())
+ "extra_opts "
+ + "ignored because cmd was specified: mkfs -t ext4 -L with_cmd "
+ + "/dev/xdb1",
+ self.logs.getvalue(),
+ )
self.assertIn(
- 'overwrite ' +
- 'ignored because cmd was specified: mkfs -t ext4 -L with_cmd ' +
- '/dev/xdb1',
- self.logs.getvalue())
+ "overwrite "
+ + "ignored because cmd was specified: mkfs -t ext4 -L with_cmd "
+ + "/dev/xdb1",
+ self.logs.getvalue(),
+ )
subp.assert_called_once_with(
- 'mkfs -t ext4 -L with_cmd /dev/xdb1', shell=True)
+ "mkfs -t ext4 -L with_cmd /dev/xdb1", shell=True
+ )
- @mock.patch('cloudinit.config.cc_disk_setup.subp.which')
+ @mock.patch("cloudinit.config.cc_disk_setup.subp.which")
def test_overwrite_and_extra_opts_without_cmd(self, m_which, subp, *args):
"""mkfs observes extra_opts and overwrite settings when cmd is not
present."""
- m_which.side_effect = lambda p: {'mkfs.ext4': '/sbin/mkfs.ext4'}[p]
- cc_disk_setup.mkfs({
- 'filesystem': 'ext4',
- 'device': '/dev/xdb1',
- 'label': 'without_cmd',
- 'extra_opts': ['are', 'added'],
- 'overwrite': True
- })
+ m_which.side_effect = lambda p: {"mkfs.ext4": "/sbin/mkfs.ext4"}[p]
+ cc_disk_setup.mkfs(
+ {
+ "filesystem": "ext4",
+ "device": "/dev/xdb1",
+ "label": "without_cmd",
+ "extra_opts": ["are", "added"],
+ "overwrite": True,
+ }
+ )
subp.assert_called_once_with(
- ['/sbin/mkfs.ext4', '/dev/xdb1',
- '-L', 'without_cmd', '-F', 'are', 'added'],
- shell=False)
-
- @mock.patch('cloudinit.config.cc_disk_setup.subp.which')
+ [
+ "/sbin/mkfs.ext4",
+ "/dev/xdb1",
+ "-L",
+ "without_cmd",
+ "-F",
+ "are",
+ "added",
+ ],
+ shell=False,
+ )
+
+ @mock.patch("cloudinit.config.cc_disk_setup.subp.which")
def test_mkswap(self, m_which, subp, *args):
"""mkfs observes extra_opts and overwrite settings when cmd is not
present."""
- m_which.side_effect = iter([None, '/sbin/mkswap'])
- cc_disk_setup.mkfs({
- 'filesystem': 'swap',
- 'device': '/dev/xdb1',
- 'label': 'swap',
- 'overwrite': True,
- })
-
- self.assertEqual([mock.call('mkfs.swap'), mock.call('mkswap')],
- m_which.call_args_list)
+ m_which.side_effect = iter([None, "/sbin/mkswap"])
+ cc_disk_setup.mkfs(
+ {
+ "filesystem": "swap",
+ "device": "/dev/xdb1",
+ "label": "swap",
+ "overwrite": True,
+ }
+ )
+
+ self.assertEqual(
+ [mock.call("mkfs.swap"), mock.call("mkswap")],
+ m_which.call_args_list,
+ )
subp.assert_called_once_with(
- ['/sbin/mkswap', '/dev/xdb1', '-L', 'swap', '-f'], shell=False)
+ ["/sbin/mkswap", "/dev/xdb1", "-L", "swap", "-f"], shell=False
+ )
+
#
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_growpart.py b/tests/unittests/config/test_cc_growpart.py
index b007f24f..ba66f136 100644
--- a/tests/unittests/config/test_cc_growpart.py
+++ b/tests/unittests/config/test_cc_growpart.py
@@ -1,21 +1,18 @@
# This file is part of cloud-init. See LICENSE file for license information.
-from cloudinit import cloud
-from cloudinit.config import cc_growpart
-from cloudinit import subp
-from cloudinit import temp_utils
-
-from tests.unittests.helpers import TestCase
-
import errno
import logging
import os
-import shutil
import re
+import shutil
+import stat
import unittest
from contextlib import ExitStack
from unittest import mock
-import stat
+
+from cloudinit import cloud, subp, temp_utils
+from cloudinit.config import cc_growpart
+from tests.unittests.helpers import TestCase
# growpart:
# mode: auto # off, on, auto, 'growpart'
@@ -62,7 +59,8 @@ usage: gpart add -t type [-a alignment] [-b start] <SNIP> geom
class Dir:
- '''Stub object'''
+ """Stub object"""
+
def __init__(self, name):
self.name = name
self.st_mode = name
@@ -75,9 +73,13 @@ class Dir:
class Scanner:
- '''Stub object'''
+ """Stub object"""
+
def __enter__(self):
- return (Dir(''), Dir(''),)
+ return (
+ Dir(""),
+ Dir(""),
+ )
def __exit__(self, *args):
pass
@@ -97,11 +99,12 @@ class TestDisabled(unittest.TestCase):
# Test that nothing is done if mode is off.
# this really only verifies that resizer_factory isn't called
- config = {'growpart': {'mode': 'off'}}
+ config = {"growpart": {"mode": "off"}}
- with mock.patch.object(cc_growpart, 'resizer_factory') as mockobj:
- self.handle(self.name, config, self.cloud_init, self.log,
- self.args)
+ with mock.patch.object(cc_growpart, "resizer_factory") as mockobj:
+ self.handle(
+ self.name, config, self.cloud_init, self.log, self.args
+ )
self.assertEqual(mockobj.call_count, 0)
@@ -116,9 +119,9 @@ class TestConfig(TestCase):
self.cloud_init = None
self.handle = cc_growpart.handle
- self.tmppath = '/tmp/cloudinit-test-file'
- self.tmpdir = os.scandir('/tmp')
- self.tmpfile = open(self.tmppath, 'w')
+ self.tmppath = "/tmp/cloudinit-test-file"
+ self.tmpdir = os.scandir("/tmp")
+ self.tmpfile = open(self.tmppath, "w")
def tearDown(self):
self.tmpfile.close()
@@ -127,110 +130,143 @@ class TestConfig(TestCase):
@mock.patch.dict("os.environ", clear=True)
def test_no_resizers_auto_is_fine(self):
with mock.patch.object(
- subp, 'subp',
- return_value=(HELP_GROWPART_NO_RESIZE, "")) as mockobj:
-
- config = {'growpart': {'mode': 'auto'}}
- self.handle(self.name, config, self.cloud_init, self.log,
- self.args)
-
- mockobj.assert_has_calls([
- mock.call(['growpart', '--help'], env={'LANG': 'C'}),
- mock.call(['gpart', 'help'], env={'LANG': 'C'}, rcs=[0, 1])])
+ subp, "subp", return_value=(HELP_GROWPART_NO_RESIZE, "")
+ ) as mockobj:
+
+ config = {"growpart": {"mode": "auto"}}
+ self.handle(
+ self.name, config, self.cloud_init, self.log, self.args
+ )
+
+ mockobj.assert_has_calls(
+ [
+ mock.call(["growpart", "--help"], env={"LANG": "C"}),
+ mock.call(
+ ["gpart", "help"], env={"LANG": "C"}, rcs=[0, 1]
+ ),
+ ]
+ )
@mock.patch.dict("os.environ", clear=True)
def test_no_resizers_mode_growpart_is_exception(self):
with mock.patch.object(
- subp, 'subp',
- return_value=(HELP_GROWPART_NO_RESIZE, "")) as mockobj:
- config = {'growpart': {'mode': "growpart"}}
+ subp, "subp", return_value=(HELP_GROWPART_NO_RESIZE, "")
+ ) as mockobj:
+ config = {"growpart": {"mode": "growpart"}}
self.assertRaises(
- ValueError, self.handle, self.name, config,
- self.cloud_init, self.log, self.args)
+ ValueError,
+ self.handle,
+ self.name,
+ config,
+ self.cloud_init,
+ self.log,
+ self.args,
+ )
mockobj.assert_called_once_with(
- ['growpart', '--help'], env={'LANG': 'C'})
+ ["growpart", "--help"], env={"LANG": "C"}
+ )
@mock.patch.dict("os.environ", clear=True)
def test_mode_auto_prefers_growpart(self):
with mock.patch.object(
- subp, 'subp',
- return_value=(HELP_GROWPART_RESIZE, "")) as mockobj:
+ subp, "subp", return_value=(HELP_GROWPART_RESIZE, "")
+ ) as mockobj:
ret = cc_growpart.resizer_factory(mode="auto")
self.assertIsInstance(ret, cc_growpart.ResizeGrowPart)
mockobj.assert_called_once_with(
- ['growpart', '--help'], env={'LANG': 'C'})
-
- @mock.patch.dict("os.environ", {'LANG': 'cs_CZ.UTF-8'}, clear=True)
- @mock.patch.object(temp_utils, 'mkdtemp', return_value='/tmp/much-random')
- @mock.patch.object(stat, 'S_ISDIR', return_value=False)
- @mock.patch.object(os.path, 'samestat', return_value=True)
- @mock.patch.object(os.path, "join", return_value='/tmp')
- @mock.patch.object(os, 'scandir', return_value=Scanner())
- @mock.patch.object(os, 'mkdir')
- @mock.patch.object(os, 'unlink')
- @mock.patch.object(os, 'rmdir')
- @mock.patch.object(os, 'open', return_value=1)
- @mock.patch.object(os, 'close')
- @mock.patch.object(shutil, 'rmtree')
- @mock.patch.object(os, 'lseek', return_value=1024)
- @mock.patch.object(os, 'lstat', return_value='interesting metadata')
+ ["growpart", "--help"], env={"LANG": "C"}
+ )
+
+ @mock.patch.dict("os.environ", {"LANG": "cs_CZ.UTF-8"}, clear=True)
+ @mock.patch.object(temp_utils, "mkdtemp", return_value="/tmp/much-random")
+ @mock.patch.object(stat, "S_ISDIR", return_value=False)
+ @mock.patch.object(os.path, "samestat", return_value=True)
+ @mock.patch.object(os.path, "join", return_value="/tmp")
+ @mock.patch.object(os, "scandir", return_value=Scanner())
+ @mock.patch.object(os, "mkdir")
+ @mock.patch.object(os, "unlink")
+ @mock.patch.object(os, "rmdir")
+ @mock.patch.object(os, "open", return_value=1)
+ @mock.patch.object(os, "close")
+ @mock.patch.object(shutil, "rmtree")
+ @mock.patch.object(os, "lseek", return_value=1024)
+ @mock.patch.object(os, "lstat", return_value="interesting metadata")
def test_force_lang_check_tempfile(self, *args, **kwargs):
with mock.patch.object(
- subp,
- 'subp',
- return_value=(HELP_GROWPART_RESIZE, "")) as mockobj:
+ subp, "subp", return_value=(HELP_GROWPART_RESIZE, "")
+ ) as mockobj:
ret = cc_growpart.resizer_factory(mode="auto")
self.assertIsInstance(ret, cc_growpart.ResizeGrowPart)
- diskdev = '/dev/sdb'
+ diskdev = "/dev/sdb"
partnum = 1
- partdev = '/dev/sdb'
+ partdev = "/dev/sdb"
ret.resize(diskdev, partnum, partdev)
- mockobj.assert_has_calls([
- mock.call(
- ["growpart", '--dry-run', diskdev, partnum],
- env={'LANG': 'C', 'TMPDIR': '/tmp'}),
- mock.call(
- ["growpart", diskdev, partnum],
- env={'LANG': 'C', 'TMPDIR': '/tmp'}),
- ])
-
- @mock.patch.dict("os.environ", {'LANG': 'cs_CZ.UTF-8'}, clear=True)
+ mockobj.assert_has_calls(
+ [
+ mock.call(
+ ["growpart", "--dry-run", diskdev, partnum],
+ env={"LANG": "C", "TMPDIR": "/tmp"},
+ ),
+ mock.call(
+ ["growpart", diskdev, partnum],
+ env={"LANG": "C", "TMPDIR": "/tmp"},
+ ),
+ ]
+ )
+
+ @mock.patch.dict("os.environ", {"LANG": "cs_CZ.UTF-8"}, clear=True)
def test_mode_auto_falls_back_to_gpart(self):
with mock.patch.object(
- subp, 'subp',
- return_value=("", HELP_GPART)) as mockobj:
+ subp, "subp", return_value=("", HELP_GPART)
+ ) as mockobj:
ret = cc_growpart.resizer_factory(mode="auto")
self.assertIsInstance(ret, cc_growpart.ResizeGpart)
- mockobj.assert_has_calls([
- mock.call(['growpart', '--help'], env={'LANG': 'C'}),
- mock.call(['gpart', 'help'], env={'LANG': 'C'}, rcs=[0, 1])])
+ mockobj.assert_has_calls(
+ [
+ mock.call(["growpart", "--help"], env={"LANG": "C"}),
+ mock.call(
+ ["gpart", "help"], env={"LANG": "C"}, rcs=[0, 1]
+ ),
+ ]
+ )
def test_handle_with_no_growpart_entry(self):
# if no 'growpart' entry in config, then mode=auto should be used
myresizer = object()
- retval = (("/", cc_growpart.RESIZE.CHANGED, "my-message",),)
+ retval = (
+ (
+ "/",
+ cc_growpart.RESIZE.CHANGED,
+ "my-message",
+ ),
+ )
with ExitStack() as mocks:
factory = mocks.enter_context(
- mock.patch.object(cc_growpart, 'resizer_factory',
- return_value=myresizer))
+ mock.patch.object(
+ cc_growpart, "resizer_factory", return_value=myresizer
+ )
+ )
rsdevs = mocks.enter_context(
- mock.patch.object(cc_growpart, 'resize_devices',
- return_value=retval))
+ mock.patch.object(
+ cc_growpart, "resize_devices", return_value=retval
+ )
+ )
mocks.enter_context(
- mock.patch.object(cc_growpart, 'RESIZERS',
- (('mysizer', object),)
- ))
+ mock.patch.object(
+ cc_growpart, "RESIZERS", (("mysizer", object),)
+ )
+ )
self.handle(self.name, {}, self.cloud_init, self.log, self.args)
- factory.assert_called_once_with('auto')
- rsdevs.assert_called_once_with(myresizer, ['/'])
+ factory.assert_called_once_with("auto")
+ rsdevs.assert_called_once_with(myresizer, ["/"])
class TestResize(unittest.TestCase):
@@ -244,9 +280,18 @@ class TestResize(unittest.TestCase):
# this patches out devent2dev, os.stat, and device_part_info
# so in the end, doesn't test a lot
devs = ["/dev/XXda1", "/dev/YYda2"]
- devstat_ret = Bunch(st_mode=25008, st_ino=6078, st_dev=5,
- st_nlink=1, st_uid=0, st_gid=6, st_size=0,
- st_atime=0, st_mtime=0, st_ctime=0)
+ devstat_ret = Bunch(
+ st_mode=25008,
+ st_ino=6078,
+ st_dev=5,
+ st_nlink=1,
+ st_uid=0,
+ st_gid=6,
+ st_size=0,
+ st_atime=0,
+ st_mtime=0,
+ st_ctime=0,
+ )
enoent = ["/dev/NOENT"]
real_stat = os.stat
resize_calls = []
@@ -280,12 +325,15 @@ class TestResize(unittest.TestCase):
return f
return None
- self.assertEqual(cc_growpart.RESIZE.NOCHANGE,
- find("/dev/XXda1", resized)[1])
- self.assertEqual(cc_growpart.RESIZE.CHANGED,
- find("/dev/YYda2", resized)[1])
- self.assertEqual(cc_growpart.RESIZE.SKIPPED,
- find(enoent[0], resized)[1])
+ self.assertEqual(
+ cc_growpart.RESIZE.NOCHANGE, find("/dev/XXda1", resized)[1]
+ )
+ self.assertEqual(
+ cc_growpart.RESIZE.CHANGED, find("/dev/YYda2", resized)[1]
+ )
+ self.assertEqual(
+ cc_growpart.RESIZE.SKIPPED, find(enoent[0], resized)[1]
+ )
# self.assertEqual(resize_calls,
# [("/dev/XXda", "1", "/dev/XXda1"),
# ("/dev/YYda", "2", "/dev/YYda2")])
diff --git a/tests/unittests/config/test_cc_grub_dpkg.py b/tests/unittests/config/test_cc_grub_dpkg.py
index 99c05bb5..5151a7b5 100644
--- a/tests/unittests/config/test_cc_grub_dpkg.py
+++ b/tests/unittests/config/test_cc_grub_dpkg.py
@@ -1,11 +1,12 @@
# This file is part of cloud-init. See LICENSE file for license information.
+from logging import Logger
+from unittest import mock
+
import pytest
-from unittest import mock
-from logging import Logger
-from cloudinit.subp import ProcessExecutionError
from cloudinit.config.cc_grub_dpkg import fetch_idevs, handle
+from cloudinit.subp import ProcessExecutionError
class TestFetchIdevs:
@@ -21,73 +22,78 @@ class TestFetchIdevs:
ProcessExecutionError(reason=FileNotFoundError()),
False,
mock.call("'grub-probe' not found in $PATH"),
- '',
- '',
+ "",
+ "",
),
# Inside a container, grub installed
(
ProcessExecutionError(stderr="failed to get canonical path"),
False,
mock.call("grub-probe 'failed to get canonical path'"),
- '',
- '',
+ "",
+ "",
),
# KVM Instance
(
- ['/dev/vda'],
+ ["/dev/vda"],
True,
None,
(
- '/dev/disk/by-path/pci-0000:00:00.0 ',
- '/dev/disk/by-path/virtio-pci-0000:00:00.0 '
+ "/dev/disk/by-path/pci-0000:00:00.0 ",
+ "/dev/disk/by-path/virtio-pci-0000:00:00.0 ",
),
- '/dev/vda',
+ "/dev/vda",
),
# Xen Instance
(
- ['/dev/xvda'],
+ ["/dev/xvda"],
True,
None,
- '',
- '/dev/xvda',
+ "",
+ "/dev/xvda",
),
# NVMe Hardware Instance
(
- ['/dev/nvme1n1'],
+ ["/dev/nvme1n1"],
True,
None,
(
- '/dev/disk/by-id/nvme-Company_hash000 ',
- '/dev/disk/by-id/nvme-nvme.000-000-000-000-000 ',
- '/dev/disk/by-path/pci-0000:00:00.0-nvme-0 '
+ "/dev/disk/by-id/nvme-Company_hash000 ",
+ "/dev/disk/by-id/nvme-nvme.000-000-000-000-000 ",
+ "/dev/disk/by-path/pci-0000:00:00.0-nvme-0 ",
),
- '/dev/disk/by-id/nvme-Company_hash000',
+ "/dev/disk/by-id/nvme-Company_hash000",
),
# SCSI Hardware Instance
(
- ['/dev/sda'],
+ ["/dev/sda"],
True,
None,
(
- '/dev/disk/by-id/company-user-1 ',
- '/dev/disk/by-id/scsi-0Company_user-1 ',
- '/dev/disk/by-path/pci-0000:00:00.0-scsi-0:0:0:0 '
+ "/dev/disk/by-id/company-user-1 ",
+ "/dev/disk/by-id/scsi-0Company_user-1 ",
+ "/dev/disk/by-path/pci-0000:00:00.0-scsi-0:0:0:0 ",
),
- '/dev/disk/by-id/company-user-1',
+ "/dev/disk/by-id/company-user-1",
),
],
)
@mock.patch("cloudinit.config.cc_grub_dpkg.util.logexc")
@mock.patch("cloudinit.config.cc_grub_dpkg.os.path.exists")
@mock.patch("cloudinit.config.cc_grub_dpkg.subp.subp")
- def test_fetch_idevs(self, m_subp, m_exists, m_logexc, grub_output,
- path_exists, expected_log_call, udevadm_output,
- expected_idevs):
+ def test_fetch_idevs(
+ self,
+ m_subp,
+ m_exists,
+ m_logexc,
+ grub_output,
+ path_exists,
+ expected_log_call,
+ udevadm_output,
+ expected_idevs,
+ ):
"""Tests outputs from grub-probe and udevadm info against grub-dpkg"""
- m_subp.side_effect = [
- grub_output,
- ["".join(udevadm_output)]
- ]
+ m_subp.side_effect = [grub_output, ["".join(udevadm_output)]]
m_exists.return_value = path_exists
log = mock.Mock(spec=Logger)
idevs = fetch_idevs(log)
@@ -106,67 +112,72 @@ class TestHandle:
# No configuration
None,
None,
- '/dev/disk/by-id/nvme-Company_hash000',
+ "/dev/disk/by-id/nvme-Company_hash000",
(
"Setting grub debconf-set-selections with ",
- "'/dev/disk/by-id/nvme-Company_hash000','false'"
+ "'/dev/disk/by-id/nvme-Company_hash000','false'",
),
),
(
# idevs set, idevs_empty unset
- '/dev/sda',
+ "/dev/sda",
None,
- '/dev/sda',
+ "/dev/sda",
(
"Setting grub debconf-set-selections with ",
- "'/dev/sda','false'"
+ "'/dev/sda','false'",
),
),
(
# idevs unset, idevs_empty set
None,
- 'true',
- '/dev/xvda',
+ "true",
+ "/dev/xvda",
(
"Setting grub debconf-set-selections with ",
- "'/dev/xvda','true'"
+ "'/dev/xvda','true'",
),
),
(
# idevs set, idevs_empty set
- '/dev/vda',
- 'false',
- '/dev/disk/by-id/company-user-1',
+ "/dev/vda",
+ "false",
+ "/dev/disk/by-id/company-user-1",
(
"Setting grub debconf-set-selections with ",
- "'/dev/vda','false'"
+ "'/dev/vda','false'",
),
),
(
# idevs set, idevs_empty set
# Respect what the user defines, even if its logically wrong
- '/dev/nvme0n1',
- 'true',
- '',
+ "/dev/nvme0n1",
+ "true",
+ "",
(
"Setting grub debconf-set-selections with ",
- "'/dev/nvme0n1','true'"
+ "'/dev/nvme0n1','true'",
),
- )
+ ),
],
)
@mock.patch("cloudinit.config.cc_grub_dpkg.fetch_idevs")
@mock.patch("cloudinit.config.cc_grub_dpkg.util.get_cfg_option_str")
@mock.patch("cloudinit.config.cc_grub_dpkg.util.logexc")
@mock.patch("cloudinit.config.cc_grub_dpkg.subp.subp")
- def test_handle(self, m_subp, m_logexc, m_get_cfg_str, m_fetch_idevs,
- cfg_idevs, cfg_idevs_empty, fetch_idevs_output,
- expected_log_output):
+ def test_handle(
+ self,
+ m_subp,
+ m_logexc,
+ m_get_cfg_str,
+ m_fetch_idevs,
+ cfg_idevs,
+ cfg_idevs_empty,
+ fetch_idevs_output,
+ expected_log_output,
+ ):
"""Test setting of correct debconf database entries"""
- m_get_cfg_str.side_effect = [
- cfg_idevs,
- cfg_idevs_empty
- ]
+ m_get_cfg_str.side_effect = [cfg_idevs, cfg_idevs_empty]
m_fetch_idevs.return_value = fetch_idevs_output
log = mock.Mock(spec=Logger)
handle(mock.Mock(), mock.Mock(), mock.Mock(), log, mock.Mock())
diff --git a/tests/unittests/config/test_cc_install_hotplug.py b/tests/unittests/config/test_cc_install_hotplug.py
index 5d6b1e77..3bd44aba 100644
--- a/tests/unittests/config/test_cc_install_hotplug.py
+++ b/tests/unittests/config/test_cc_install_hotplug.py
@@ -5,28 +5,31 @@ from unittest import mock
import pytest
from cloudinit.config.cc_install_hotplug import (
- handle,
HOTPLUG_UDEV_PATH,
HOTPLUG_UDEV_RULES_TEMPLATE,
+ handle,
)
from cloudinit.event import EventScope, EventType
@pytest.yield_fixture()
def mocks():
- m_update_enabled = mock.patch('cloudinit.stages.update_event_enabled')
- m_write = mock.patch('cloudinit.util.write_file', autospec=True)
- m_del = mock.patch('cloudinit.util.del_file', autospec=True)
- m_subp = mock.patch('cloudinit.subp.subp')
- m_which = mock.patch('cloudinit.subp.which', return_value=None)
- m_path_exists = mock.patch('os.path.exists', return_value=False)
+ m_update_enabled = mock.patch("cloudinit.stages.update_event_enabled")
+ m_write = mock.patch("cloudinit.util.write_file", autospec=True)
+ m_del = mock.patch("cloudinit.util.del_file", autospec=True)
+ m_subp = mock.patch("cloudinit.subp.subp")
+ m_which = mock.patch("cloudinit.subp.which", return_value=None)
+ m_path_exists = mock.patch("os.path.exists", return_value=False)
yield namedtuple(
- 'Mocks',
- 'm_update_enabled m_write m_del m_subp m_which m_path_exists'
+ "Mocks", "m_update_enabled m_write m_del m_subp m_which m_path_exists"
)(
- m_update_enabled.start(), m_write.start(), m_del.start(),
- m_subp.start(), m_which.start(), m_path_exists.start()
+ m_update_enabled.start(),
+ m_write.start(),
+ m_del.start(),
+ m_subp.start(),
+ m_which.start(),
+ m_path_exists.start(),
)
m_update_enabled.stop()
@@ -38,11 +41,11 @@ def mocks():
class TestInstallHotplug:
- @pytest.mark.parametrize('libexec_exists', [True, False])
+ @pytest.mark.parametrize("libexec_exists", [True, False])
def test_rules_installed_when_supported_and_enabled(
self, mocks, libexec_exists
):
- mocks.m_which.return_value = 'udevadm'
+ mocks.m_which.return_value = "udevadm"
mocks.m_update_enabled.return_value = True
m_cloud = mock.MagicMock()
m_cloud.datasource.get_supported_events.return_value = {
@@ -53,16 +56,23 @@ class TestInstallHotplug:
libexecdir = "/usr/libexec/cloud-init"
else:
libexecdir = "/usr/lib/cloud-init"
- with mock.patch('os.path.exists', return_value=libexec_exists):
+ with mock.patch("os.path.exists", return_value=libexec_exists):
handle(None, {}, m_cloud, mock.Mock(), None)
mocks.m_write.assert_called_once_with(
filename=HOTPLUG_UDEV_PATH,
content=HOTPLUG_UDEV_RULES_TEMPLATE.format(
- libexecdir=libexecdir),
+ libexecdir=libexecdir
+ ),
)
- assert mocks.m_subp.call_args_list == [mock.call([
- 'udevadm', 'control', '--reload-rules',
- ])]
+ assert mocks.m_subp.call_args_list == [
+ mock.call(
+ [
+ "udevadm",
+ "control",
+ "--reload-rules",
+ ]
+ )
+ ]
assert mocks.m_del.call_args_list == []
def test_rules_not_installed_when_unsupported(self, mocks):
@@ -95,9 +105,15 @@ class TestInstallHotplug:
handle(None, {}, m_cloud, mock.Mock(), None)
mocks.m_del.assert_called_with(HOTPLUG_UDEV_PATH)
- assert mocks.m_subp.call_args_list == [mock.call([
- 'udevadm', 'control', '--reload-rules',
- ])]
+ assert mocks.m_subp.call_args_list == [
+ mock.call(
+ [
+ "udevadm",
+ "control",
+ "--reload-rules",
+ ]
+ )
+ ]
assert mocks.m_write.call_args_list == []
def test_rules_not_installed_when_no_udevadm(self, mocks):
diff --git a/tests/unittests/config/test_cc_keys_to_console.py b/tests/unittests/config/test_cc_keys_to_console.py
index 4083fc54..9efc2b48 100644
--- a/tests/unittests/config/test_cc_keys_to_console.py
+++ b/tests/unittests/config/test_cc_keys_to_console.py
@@ -16,12 +16,18 @@ class TestHandle:
@mock.patch("cloudinit.config.cc_keys_to_console.util.multi_log")
@mock.patch("cloudinit.config.cc_keys_to_console.os.path.exists")
@mock.patch("cloudinit.config.cc_keys_to_console.subp.subp")
- @pytest.mark.parametrize("cfg,subp_called", [
- ({}, True), # Default to emitting keys
- ({"ssh": {}}, True), # Default even if we have the parent key
- ({"ssh": {"emit_keys_to_console": True}}, True), # Explicitly enabled
- ({"ssh": {"emit_keys_to_console": False}}, False), # Disabled
- ])
+ @pytest.mark.parametrize(
+ "cfg,subp_called",
+ [
+ ({}, True), # Default to emitting keys
+ ({"ssh": {}}, True), # Default even if we have the parent key
+ (
+ {"ssh": {"emit_keys_to_console": True}},
+ True,
+ ), # Explicitly enabled
+ ({"ssh": {"emit_keys_to_console": False}}, False), # Disabled
+ ],
+ )
def test_emit_keys_to_console_config(
self, m_subp, m_path_exists, _m_multi_log, cfg, subp_called
):
diff --git a/tests/unittests/config/test_cc_landscape.py b/tests/unittests/config/test_cc_landscape.py
index 07b3f899..efddc1b6 100644
--- a/tests/unittests/config/test_cc_landscape.py
+++ b/tests/unittests/config/test_cc_landscape.py
@@ -1,12 +1,15 @@
# This file is part of cloud-init. See LICENSE file for license information.
import logging
+
from configobj import ConfigObj
-from cloudinit.config import cc_landscape
from cloudinit import util
-from tests.unittests.helpers import (FilesystemMockingTestCase, mock,
- wrap_and_call)
-
+from cloudinit.config import cc_landscape
+from tests.unittests.helpers import (
+ FilesystemMockingTestCase,
+ mock,
+ wrap_and_call,
+)
from tests.unittests.util import get_cloud
LOG = logging.getLogger(__name__)
@@ -19,108 +22,149 @@ class TestLandscape(FilesystemMockingTestCase):
def setUp(self):
super(TestLandscape, self).setUp()
self.new_root = self.tmp_dir()
- self.conf = self.tmp_path('client.conf', self.new_root)
- self.default_file = self.tmp_path('default_landscape', self.new_root)
+ self.conf = self.tmp_path("client.conf", self.new_root)
+ self.default_file = self.tmp_path("default_landscape", self.new_root)
self.patchUtils(self.new_root)
self.add_patch(
- 'cloudinit.distros.ubuntu.Distro.install_packages',
- 'm_install_packages'
+ "cloudinit.distros.ubuntu.Distro.install_packages",
+ "m_install_packages",
)
def test_handler_skips_empty_landscape_cloudconfig(self):
"""Empty landscape cloud-config section does no work."""
- mycloud = get_cloud('ubuntu')
+ mycloud = get_cloud("ubuntu")
mycloud.distro = mock.MagicMock()
- cfg = {'landscape': {}}
- cc_landscape.handle('notimportant', cfg, mycloud, LOG, None)
+ cfg = {"landscape": {}}
+ cc_landscape.handle("notimportant", cfg, mycloud, LOG, None)
self.assertFalse(mycloud.distro.install_packages.called)
def test_handler_error_on_invalid_landscape_type(self):
"""Raise an error when landscape configuraiton option is invalid."""
- mycloud = get_cloud('ubuntu')
- cfg = {'landscape': 'wrongtype'}
+ mycloud = get_cloud("ubuntu")
+ cfg = {"landscape": "wrongtype"}
with self.assertRaises(RuntimeError) as context_manager:
- cc_landscape.handle('notimportant', cfg, mycloud, LOG, None)
+ cc_landscape.handle("notimportant", cfg, mycloud, LOG, None)
self.assertIn(
"'landscape' key existed in config, but not a dict",
- str(context_manager.exception))
+ str(context_manager.exception),
+ )
- @mock.patch('cloudinit.config.cc_landscape.subp')
+ @mock.patch("cloudinit.config.cc_landscape.subp")
def test_handler_restarts_landscape_client(self, m_subp):
"""handler restarts lansdscape-client after install."""
- mycloud = get_cloud('ubuntu')
- cfg = {'landscape': {'client': {}}}
+ mycloud = get_cloud("ubuntu")
+ cfg = {"landscape": {"client": {}}}
wrap_and_call(
- 'cloudinit.config.cc_landscape',
- {'LSC_CLIENT_CFG_FILE': {'new': self.conf}},
- cc_landscape.handle, 'notimportant', cfg, mycloud, LOG, None)
+ "cloudinit.config.cc_landscape",
+ {"LSC_CLIENT_CFG_FILE": {"new": self.conf}},
+ cc_landscape.handle,
+ "notimportant",
+ cfg,
+ mycloud,
+ LOG,
+ None,
+ )
self.assertEqual(
- [mock.call(['service', 'landscape-client', 'restart'])],
- m_subp.subp.call_args_list)
+ [mock.call(["service", "landscape-client", "restart"])],
+ m_subp.subp.call_args_list,
+ )
def test_handler_installs_client_and_creates_config_file(self):
"""Write landscape client.conf and install landscape-client."""
- mycloud = get_cloud('ubuntu')
- cfg = {'landscape': {'client': {}}}
- expected = {'client': {
- 'log_level': 'info',
- 'url': 'https://landscape.canonical.com/message-system',
- 'ping_url': 'http://landscape.canonical.com/ping',
- 'data_path': '/var/lib/landscape/client'}}
+ mycloud = get_cloud("ubuntu")
+ cfg = {"landscape": {"client": {}}}
+ expected = {
+ "client": {
+ "log_level": "info",
+ "url": "https://landscape.canonical.com/message-system",
+ "ping_url": "http://landscape.canonical.com/ping",
+ "data_path": "/var/lib/landscape/client",
+ }
+ }
mycloud.distro = mock.MagicMock()
wrap_and_call(
- 'cloudinit.config.cc_landscape',
- {'LSC_CLIENT_CFG_FILE': {'new': self.conf},
- 'LS_DEFAULT_FILE': {'new': self.default_file}},
- cc_landscape.handle, 'notimportant', cfg, mycloud, LOG, None)
+ "cloudinit.config.cc_landscape",
+ {
+ "LSC_CLIENT_CFG_FILE": {"new": self.conf},
+ "LS_DEFAULT_FILE": {"new": self.default_file},
+ },
+ cc_landscape.handle,
+ "notimportant",
+ cfg,
+ mycloud,
+ LOG,
+ None,
+ )
self.assertEqual(
- [mock.call('landscape-client')],
- mycloud.distro.install_packages.call_args)
+ [mock.call("landscape-client")],
+ mycloud.distro.install_packages.call_args,
+ )
self.assertEqual(expected, dict(ConfigObj(self.conf)))
self.assertIn(
- 'Wrote landscape config file to {0}'.format(self.conf),
- self.logs.getvalue())
+ "Wrote landscape config file to {0}".format(self.conf),
+ self.logs.getvalue(),
+ )
default_content = util.load_file(self.default_file)
- self.assertEqual('RUN=1\n', default_content)
+ self.assertEqual("RUN=1\n", default_content)
def test_handler_writes_merged_client_config_file_with_defaults(self):
"""Merge and write options from LSC_CLIENT_CFG_FILE with defaults."""
# Write existing sparse client.conf file
- util.write_file(self.conf, '[client]\ncomputer_title = My PC\n')
- mycloud = get_cloud('ubuntu')
- cfg = {'landscape': {'client': {}}}
- expected = {'client': {
- 'log_level': 'info',
- 'url': 'https://landscape.canonical.com/message-system',
- 'ping_url': 'http://landscape.canonical.com/ping',
- 'data_path': '/var/lib/landscape/client',
- 'computer_title': 'My PC'}}
+ util.write_file(self.conf, "[client]\ncomputer_title = My PC\n")
+ mycloud = get_cloud("ubuntu")
+ cfg = {"landscape": {"client": {}}}
+ expected = {
+ "client": {
+ "log_level": "info",
+ "url": "https://landscape.canonical.com/message-system",
+ "ping_url": "http://landscape.canonical.com/ping",
+ "data_path": "/var/lib/landscape/client",
+ "computer_title": "My PC",
+ }
+ }
wrap_and_call(
- 'cloudinit.config.cc_landscape',
- {'LSC_CLIENT_CFG_FILE': {'new': self.conf}},
- cc_landscape.handle, 'notimportant', cfg, mycloud, LOG, None)
+ "cloudinit.config.cc_landscape",
+ {"LSC_CLIENT_CFG_FILE": {"new": self.conf}},
+ cc_landscape.handle,
+ "notimportant",
+ cfg,
+ mycloud,
+ LOG,
+ None,
+ )
self.assertEqual(expected, dict(ConfigObj(self.conf)))
self.assertIn(
- 'Wrote landscape config file to {0}'.format(self.conf),
- self.logs.getvalue())
+ "Wrote landscape config file to {0}".format(self.conf),
+ self.logs.getvalue(),
+ )
def test_handler_writes_merged_provided_cloudconfig_with_defaults(self):
"""Merge and write options from cloud-config options with defaults."""
# Write empty sparse client.conf file
- util.write_file(self.conf, '')
- mycloud = get_cloud('ubuntu')
- cfg = {'landscape': {'client': {'computer_title': 'My PC'}}}
- expected = {'client': {
- 'log_level': 'info',
- 'url': 'https://landscape.canonical.com/message-system',
- 'ping_url': 'http://landscape.canonical.com/ping',
- 'data_path': '/var/lib/landscape/client',
- 'computer_title': 'My PC'}}
+ util.write_file(self.conf, "")
+ mycloud = get_cloud("ubuntu")
+ cfg = {"landscape": {"client": {"computer_title": "My PC"}}}
+ expected = {
+ "client": {
+ "log_level": "info",
+ "url": "https://landscape.canonical.com/message-system",
+ "ping_url": "http://landscape.canonical.com/ping",
+ "data_path": "/var/lib/landscape/client",
+ "computer_title": "My PC",
+ }
+ }
wrap_and_call(
- 'cloudinit.config.cc_landscape',
- {'LSC_CLIENT_CFG_FILE': {'new': self.conf}},
- cc_landscape.handle, 'notimportant', cfg, mycloud, LOG, None)
+ "cloudinit.config.cc_landscape",
+ {"LSC_CLIENT_CFG_FILE": {"new": self.conf}},
+ cc_landscape.handle,
+ "notimportant",
+ cfg,
+ mycloud,
+ LOG,
+ None,
+ )
self.assertEqual(expected, dict(ConfigObj(self.conf)))
self.assertIn(
- 'Wrote landscape config file to {0}'.format(self.conf),
- self.logs.getvalue())
+ "Wrote landscape config file to {0}".format(self.conf),
+ self.logs.getvalue(),
+ )
diff --git a/tests/unittests/config/test_cc_locale.py b/tests/unittests/config/test_cc_locale.py
index 6cd95a29..7190bc68 100644
--- a/tests/unittests/config/test_cc_locale.py
+++ b/tests/unittests/config/test_cc_locale.py
@@ -8,21 +8,19 @@ import os
import shutil
import tempfile
from io import BytesIO
-from configobj import ConfigObj
from unittest import mock
+from configobj import ConfigObj
+
from cloudinit import util
from cloudinit.config import cc_locale
from tests.unittests import helpers as t_help
-
from tests.unittests.util import get_cloud
-
LOG = logging.getLogger(__name__)
class TestLocale(t_help.FilesystemMockingTestCase):
-
def setUp(self):
super(TestLocale, self).setUp()
self.new_root = tempfile.mkdtemp()
@@ -30,35 +28,37 @@ class TestLocale(t_help.FilesystemMockingTestCase):
self.patchUtils(self.new_root)
def test_set_locale_arch(self):
- locale = 'en_GB.UTF-8'
- locale_configfile = '/etc/invalid-locale-path'
+ locale = "en_GB.UTF-8"
+ locale_configfile = "/etc/invalid-locale-path"
cfg = {
- 'locale': locale,
- 'locale_configfile': locale_configfile,
+ "locale": locale,
+ "locale_configfile": locale_configfile,
}
- cc = get_cloud('arch')
-
- with mock.patch('cloudinit.distros.arch.subp.subp') as m_subp:
- with mock.patch('cloudinit.distros.arch.LOG.warning') as m_LOG:
- cc_locale.handle('cc_locale', cfg, cc, LOG, [])
- m_LOG.assert_called_with('Invalid locale_configfile %s, '
- 'only supported value is '
- '/etc/locale.conf',
- locale_configfile)
+ cc = get_cloud("arch")
+
+ with mock.patch("cloudinit.distros.arch.subp.subp") as m_subp:
+ with mock.patch("cloudinit.distros.arch.LOG.warning") as m_LOG:
+ cc_locale.handle("cc_locale", cfg, cc, LOG, [])
+ m_LOG.assert_called_with(
+ "Invalid locale_configfile %s, "
+ "only supported value is "
+ "/etc/locale.conf",
+ locale_configfile,
+ )
contents = util.load_file(cc.distro.locale_gen_fn)
- self.assertIn('%s UTF-8' % locale, contents)
- m_subp.assert_called_with(['localectl',
- 'set-locale',
- locale], capture=False)
+ self.assertIn("%s UTF-8" % locale, contents)
+ m_subp.assert_called_with(
+ ["localectl", "set-locale", locale], capture=False
+ )
def test_set_locale_sles(self):
cfg = {
- 'locale': 'My.Locale',
+ "locale": "My.Locale",
}
- cc = get_cloud('sles')
- cc_locale.handle('cc_locale', cfg, cc, LOG, [])
+ cc = get_cloud("sles")
+ cc_locale.handle("cc_locale", cfg, cc, LOG, [])
if cc.distro.uses_systemd():
locale_conf = cc.distro.systemd_locale_conf_fn
else:
@@ -66,51 +66,58 @@ class TestLocale(t_help.FilesystemMockingTestCase):
contents = util.load_file(locale_conf, decode=False)
n_cfg = ConfigObj(BytesIO(contents))
if cc.distro.uses_systemd():
- self.assertEqual({'LANG': cfg['locale']}, dict(n_cfg))
+ self.assertEqual({"LANG": cfg["locale"]}, dict(n_cfg))
else:
- self.assertEqual({'RC_LANG': cfg['locale']}, dict(n_cfg))
+ self.assertEqual({"RC_LANG": cfg["locale"]}, dict(n_cfg))
def test_set_locale_sles_default(self):
cfg = {}
- cc = get_cloud('sles')
- cc_locale.handle('cc_locale', cfg, cc, LOG, [])
+ cc = get_cloud("sles")
+ cc_locale.handle("cc_locale", cfg, cc, LOG, [])
if cc.distro.uses_systemd():
locale_conf = cc.distro.systemd_locale_conf_fn
- keyname = 'LANG'
+ keyname = "LANG"
else:
locale_conf = cc.distro.locale_conf_fn
- keyname = 'RC_LANG'
+ keyname = "RC_LANG"
contents = util.load_file(locale_conf, decode=False)
n_cfg = ConfigObj(BytesIO(contents))
- self.assertEqual({keyname: 'en_US.UTF-8'}, dict(n_cfg))
+ self.assertEqual({keyname: "en_US.UTF-8"}, dict(n_cfg))
def test_locale_update_config_if_different_than_default(self):
"""Test cc_locale writes updates conf if different than default"""
locale_conf = os.path.join(self.new_root, "etc/default/locale")
util.write_file(locale_conf, 'LANG="en_US.UTF-8"\n')
- cfg = {'locale': 'C.UTF-8'}
- cc = get_cloud('ubuntu')
- with mock.patch('cloudinit.distros.debian.subp.subp') as m_subp:
- with mock.patch('cloudinit.distros.debian.LOCALE_CONF_FN',
- locale_conf):
- cc_locale.handle('cc_locale', cfg, cc, LOG, [])
- m_subp.assert_called_with(['update-locale',
- '--locale-file=%s' % locale_conf,
- 'LANG=C.UTF-8'], capture=False)
+ cfg = {"locale": "C.UTF-8"}
+ cc = get_cloud("ubuntu")
+ with mock.patch("cloudinit.distros.debian.subp.subp") as m_subp:
+ with mock.patch(
+ "cloudinit.distros.debian.LOCALE_CONF_FN", locale_conf
+ ):
+ cc_locale.handle("cc_locale", cfg, cc, LOG, [])
+ m_subp.assert_called_with(
+ [
+ "update-locale",
+ "--locale-file=%s" % locale_conf,
+ "LANG=C.UTF-8",
+ ],
+ capture=False,
+ )
def test_locale_rhel_defaults_en_us_utf8(self):
"""Test cc_locale gets en_US.UTF-8 from distro get_locale fallback"""
cfg = {}
- cc = get_cloud('rhel')
- update_sysconfig = 'cloudinit.distros.rhel_util.update_sysconfig_file'
- with mock.patch.object(cc.distro, 'uses_systemd') as m_use_sd:
+ cc = get_cloud("rhel")
+ update_sysconfig = "cloudinit.distros.rhel_util.update_sysconfig_file"
+ with mock.patch.object(cc.distro, "uses_systemd") as m_use_sd:
m_use_sd.return_value = True
with mock.patch(update_sysconfig) as m_update_syscfg:
- cc_locale.handle('cc_locale', cfg, cc, LOG, [])
- m_update_syscfg.assert_called_with('/etc/locale.conf',
- {'LANG': 'en_US.UTF-8'})
+ cc_locale.handle("cc_locale", cfg, cc, LOG, [])
+ m_update_syscfg.assert_called_with(
+ "/etc/locale.conf", {"LANG": "en_US.UTF-8"}
+ )
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_lxd.py b/tests/unittests/config/test_cc_lxd.py
index 887987c0..720274d6 100644
--- a/tests/unittests/config/test_cc_lxd.py
+++ b/tests/unittests/config/test_cc_lxd.py
@@ -3,7 +3,6 @@ from unittest import mock
from cloudinit.config import cc_lxd
from tests.unittests import helpers as t_help
-
from tests.unittests.util import get_cloud
@@ -12,11 +11,11 @@ class TestLxd(t_help.CiTestCase):
with_logs = True
lxd_cfg = {
- 'lxd': {
- 'init': {
- 'network_address': '0.0.0.0',
- 'storage_backend': 'zfs',
- 'storage_pool': 'poolname',
+ "lxd": {
+ "init": {
+ "network_address": "0.0.0.0",
+ "storage_backend": "zfs",
+ "storage_pool": "poolname",
}
}
}
@@ -27,16 +26,26 @@ class TestLxd(t_help.CiTestCase):
cc = get_cloud()
mock_subp.which.return_value = True
m_maybe_clean.return_value = None
- cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, self.logger, [])
+ cc_lxd.handle("cc_lxd", self.lxd_cfg, cc, self.logger, [])
self.assertTrue(mock_subp.which.called)
# no bridge config, so maybe_cleanup should not be called.
self.assertFalse(m_maybe_clean.called)
self.assertEqual(
- [mock.call(['lxd', 'waitready', '--timeout=300']),
- mock.call(
- ['lxd', 'init', '--auto', '--network-address=0.0.0.0',
- '--storage-backend=zfs', '--storage-pool=poolname'])],
- mock_subp.subp.call_args_list)
+ [
+ mock.call(["lxd", "waitready", "--timeout=300"]),
+ mock.call(
+ [
+ "lxd",
+ "init",
+ "--auto",
+ "--network-address=0.0.0.0",
+ "--storage-backend=zfs",
+ "--storage-pool=poolname",
+ ]
+ ),
+ ],
+ mock_subp.subp.call_args_list,
+ )
@mock.patch("cloudinit.config.cc_lxd.maybe_cleanup_default")
@mock.patch("cloudinit.config.cc_lxd.subp")
@@ -44,20 +53,20 @@ class TestLxd(t_help.CiTestCase):
cc = get_cloud()
cc.distro = mock.MagicMock()
mock_subp.which.return_value = None
- cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, self.logger, [])
- self.assertNotIn('WARN', self.logs.getvalue())
+ cc_lxd.handle("cc_lxd", self.lxd_cfg, cc, self.logger, [])
+ self.assertNotIn("WARN", self.logs.getvalue())
self.assertTrue(cc.distro.install_packages.called)
- cc_lxd.handle('cc_lxd', self.lxd_cfg, cc, self.logger, [])
+ cc_lxd.handle("cc_lxd", self.lxd_cfg, cc, self.logger, [])
self.assertFalse(m_maybe_clean.called)
install_pkg = cc.distro.install_packages.call_args_list[0][0][0]
- self.assertEqual(sorted(install_pkg), ['lxd', 'zfsutils-linux'])
+ self.assertEqual(sorted(install_pkg), ["lxd", "zfsutils-linux"])
@mock.patch("cloudinit.config.cc_lxd.maybe_cleanup_default")
@mock.patch("cloudinit.config.cc_lxd.subp")
def test_no_init_does_nothing(self, mock_subp, m_maybe_clean):
cc = get_cloud()
cc.distro = mock.MagicMock()
- cc_lxd.handle('cc_lxd', {'lxd': {}}, cc, self.logger, [])
+ cc_lxd.handle("cc_lxd", {"lxd": {}}, cc, self.logger, [])
self.assertFalse(cc.distro.install_packages.called)
self.assertFalse(mock_subp.subp.called)
self.assertFalse(m_maybe_clean.called)
@@ -67,118 +76,150 @@ class TestLxd(t_help.CiTestCase):
def test_no_lxd_does_nothing(self, mock_subp, m_maybe_clean):
cc = get_cloud()
cc.distro = mock.MagicMock()
- cc_lxd.handle('cc_lxd', {'package_update': True}, cc, self.logger, [])
+ cc_lxd.handle("cc_lxd", {"package_update": True}, cc, self.logger, [])
self.assertFalse(cc.distro.install_packages.called)
self.assertFalse(mock_subp.subp.called)
self.assertFalse(m_maybe_clean.called)
def test_lxd_debconf_new_full(self):
- data = {"mode": "new",
- "name": "testbr0",
- "ipv4_address": "10.0.8.1",
- "ipv4_netmask": "24",
- "ipv4_dhcp_first": "10.0.8.2",
- "ipv4_dhcp_last": "10.0.8.254",
- "ipv4_dhcp_leases": "250",
- "ipv4_nat": "true",
- "ipv6_address": "fd98:9e0:3744::1",
- "ipv6_netmask": "64",
- "ipv6_nat": "true",
- "domain": "lxd"}
+ data = {
+ "mode": "new",
+ "name": "testbr0",
+ "ipv4_address": "10.0.8.1",
+ "ipv4_netmask": "24",
+ "ipv4_dhcp_first": "10.0.8.2",
+ "ipv4_dhcp_last": "10.0.8.254",
+ "ipv4_dhcp_leases": "250",
+ "ipv4_nat": "true",
+ "ipv6_address": "fd98:9e0:3744::1",
+ "ipv6_netmask": "64",
+ "ipv6_nat": "true",
+ "domain": "lxd",
+ }
self.assertEqual(
cc_lxd.bridge_to_debconf(data),
- {"lxd/setup-bridge": "true",
- "lxd/bridge-name": "testbr0",
- "lxd/bridge-ipv4": "true",
- "lxd/bridge-ipv4-address": "10.0.8.1",
- "lxd/bridge-ipv4-netmask": "24",
- "lxd/bridge-ipv4-dhcp-first": "10.0.8.2",
- "lxd/bridge-ipv4-dhcp-last": "10.0.8.254",
- "lxd/bridge-ipv4-dhcp-leases": "250",
- "lxd/bridge-ipv4-nat": "true",
- "lxd/bridge-ipv6": "true",
- "lxd/bridge-ipv6-address": "fd98:9e0:3744::1",
- "lxd/bridge-ipv6-netmask": "64",
- "lxd/bridge-ipv6-nat": "true",
- "lxd/bridge-domain": "lxd"})
+ {
+ "lxd/setup-bridge": "true",
+ "lxd/bridge-name": "testbr0",
+ "lxd/bridge-ipv4": "true",
+ "lxd/bridge-ipv4-address": "10.0.8.1",
+ "lxd/bridge-ipv4-netmask": "24",
+ "lxd/bridge-ipv4-dhcp-first": "10.0.8.2",
+ "lxd/bridge-ipv4-dhcp-last": "10.0.8.254",
+ "lxd/bridge-ipv4-dhcp-leases": "250",
+ "lxd/bridge-ipv4-nat": "true",
+ "lxd/bridge-ipv6": "true",
+ "lxd/bridge-ipv6-address": "fd98:9e0:3744::1",
+ "lxd/bridge-ipv6-netmask": "64",
+ "lxd/bridge-ipv6-nat": "true",
+ "lxd/bridge-domain": "lxd",
+ },
+ )
def test_lxd_debconf_new_partial(self):
- data = {"mode": "new",
- "ipv6_address": "fd98:9e0:3744::1",
- "ipv6_netmask": "64",
- "ipv6_nat": "true"}
+ data = {
+ "mode": "new",
+ "ipv6_address": "fd98:9e0:3744::1",
+ "ipv6_netmask": "64",
+ "ipv6_nat": "true",
+ }
self.assertEqual(
cc_lxd.bridge_to_debconf(data),
- {"lxd/setup-bridge": "true",
- "lxd/bridge-ipv6": "true",
- "lxd/bridge-ipv6-address": "fd98:9e0:3744::1",
- "lxd/bridge-ipv6-netmask": "64",
- "lxd/bridge-ipv6-nat": "true"})
+ {
+ "lxd/setup-bridge": "true",
+ "lxd/bridge-ipv6": "true",
+ "lxd/bridge-ipv6-address": "fd98:9e0:3744::1",
+ "lxd/bridge-ipv6-netmask": "64",
+ "lxd/bridge-ipv6-nat": "true",
+ },
+ )
def test_lxd_debconf_existing(self):
- data = {"mode": "existing",
- "name": "testbr0"}
+ data = {"mode": "existing", "name": "testbr0"}
self.assertEqual(
cc_lxd.bridge_to_debconf(data),
- {"lxd/setup-bridge": "false",
- "lxd/use-existing-bridge": "true",
- "lxd/bridge-name": "testbr0"})
+ {
+ "lxd/setup-bridge": "false",
+ "lxd/use-existing-bridge": "true",
+ "lxd/bridge-name": "testbr0",
+ },
+ )
def test_lxd_debconf_none(self):
data = {"mode": "none"}
self.assertEqual(
cc_lxd.bridge_to_debconf(data),
- {"lxd/setup-bridge": "false",
- "lxd/bridge-name": ""})
+ {"lxd/setup-bridge": "false", "lxd/bridge-name": ""},
+ )
def test_lxd_cmd_new_full(self):
- data = {"mode": "new",
- "name": "testbr0",
- "ipv4_address": "10.0.8.1",
- "ipv4_netmask": "24",
- "ipv4_dhcp_first": "10.0.8.2",
- "ipv4_dhcp_last": "10.0.8.254",
- "ipv4_dhcp_leases": "250",
- "ipv4_nat": "true",
- "ipv6_address": "fd98:9e0:3744::1",
- "ipv6_netmask": "64",
- "ipv6_nat": "true",
- "domain": "lxd"}
+ data = {
+ "mode": "new",
+ "name": "testbr0",
+ "ipv4_address": "10.0.8.1",
+ "ipv4_netmask": "24",
+ "ipv4_dhcp_first": "10.0.8.2",
+ "ipv4_dhcp_last": "10.0.8.254",
+ "ipv4_dhcp_leases": "250",
+ "ipv4_nat": "true",
+ "ipv6_address": "fd98:9e0:3744::1",
+ "ipv6_netmask": "64",
+ "ipv6_nat": "true",
+ "domain": "lxd",
+ }
self.assertEqual(
cc_lxd.bridge_to_cmd(data),
- (["network", "create", "testbr0",
- "ipv4.address=10.0.8.1/24", "ipv4.nat=true",
- "ipv4.dhcp.ranges=10.0.8.2-10.0.8.254",
- "ipv6.address=fd98:9e0:3744::1/64",
- "ipv6.nat=true", "dns.domain=lxd"],
- ["network", "attach-profile",
- "testbr0", "default", "eth0"]))
+ (
+ [
+ "network",
+ "create",
+ "testbr0",
+ "ipv4.address=10.0.8.1/24",
+ "ipv4.nat=true",
+ "ipv4.dhcp.ranges=10.0.8.2-10.0.8.254",
+ "ipv6.address=fd98:9e0:3744::1/64",
+ "ipv6.nat=true",
+ "dns.domain=lxd",
+ ],
+ ["network", "attach-profile", "testbr0", "default", "eth0"],
+ ),
+ )
def test_lxd_cmd_new_partial(self):
- data = {"mode": "new",
- "ipv6_address": "fd98:9e0:3744::1",
- "ipv6_netmask": "64",
- "ipv6_nat": "true"}
+ data = {
+ "mode": "new",
+ "ipv6_address": "fd98:9e0:3744::1",
+ "ipv6_netmask": "64",
+ "ipv6_nat": "true",
+ }
self.assertEqual(
cc_lxd.bridge_to_cmd(data),
- (["network", "create", "lxdbr0", "ipv4.address=none",
- "ipv6.address=fd98:9e0:3744::1/64", "ipv6.nat=true"],
- ["network", "attach-profile",
- "lxdbr0", "default", "eth0"]))
+ (
+ [
+ "network",
+ "create",
+ "lxdbr0",
+ "ipv4.address=none",
+ "ipv6.address=fd98:9e0:3744::1/64",
+ "ipv6.nat=true",
+ ],
+ ["network", "attach-profile", "lxdbr0", "default", "eth0"],
+ ),
+ )
def test_lxd_cmd_existing(self):
- data = {"mode": "existing",
- "name": "testbr0"}
+ data = {"mode": "existing", "name": "testbr0"}
self.assertEqual(
cc_lxd.bridge_to_cmd(data),
- (None, ["network", "attach-profile",
- "testbr0", "default", "eth0"]))
+ (
+ None,
+ ["network", "attach-profile", "testbr0", "default", "eth0"],
+ ),
+ )
def test_lxd_cmd_none(self):
data = {"mode": "none"}
- self.assertEqual(
- cc_lxd.bridge_to_cmd(data),
- (None, None))
+ self.assertEqual(cc_lxd.bridge_to_cmd(data), (None, None))
class TestLxdMaybeCleanupDefault(t_help.CiTestCase):
@@ -190,21 +231,24 @@ class TestLxdMaybeCleanupDefault(t_help.CiTestCase):
def test_network_other_than_default_not_deleted(self, m_lxc):
"""deletion or removal should only occur if bridge is default."""
cc_lxd.maybe_cleanup_default(
- net_name="lxdbr1", did_init=True, create=True, attach=True)
+ net_name="lxdbr1", did_init=True, create=True, attach=True
+ )
m_lxc.assert_not_called()
@mock.patch("cloudinit.config.cc_lxd._lxc")
def test_did_init_false_does_not_delete(self, m_lxc):
"""deletion or removal should only occur if did_init is True."""
cc_lxd.maybe_cleanup_default(
- net_name=self.defnet, did_init=False, create=True, attach=True)
+ net_name=self.defnet, did_init=False, create=True, attach=True
+ )
m_lxc.assert_not_called()
@mock.patch("cloudinit.config.cc_lxd._lxc")
def test_network_deleted_if_create_true(self, m_lxc):
"""deletion of network should occur if create is True."""
cc_lxd.maybe_cleanup_default(
- net_name=self.defnet, did_init=True, create=True, attach=False)
+ net_name=self.defnet, did_init=True, create=True, attach=False
+ )
m_lxc.assert_called_with(["network", "delete", self.defnet])
@mock.patch("cloudinit.config.cc_lxd._lxc")
@@ -213,10 +257,16 @@ class TestLxdMaybeCleanupDefault(t_help.CiTestCase):
nic_name = "my_nic"
profile = "my_profile"
cc_lxd.maybe_cleanup_default(
- net_name=self.defnet, did_init=True, create=False, attach=True,
- profile=profile, nic_name=nic_name)
+ net_name=self.defnet,
+ did_init=True,
+ create=False,
+ attach=True,
+ profile=profile,
+ nic_name=nic_name,
+ )
m_lxc.assert_called_once_with(
- ["profile", "device", "remove", profile, nic_name])
+ ["profile", "device", "remove", profile, nic_name]
+ )
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_mcollective.py b/tests/unittests/config/test_cc_mcollective.py
index fff777b6..5cbdeb76 100644
--- a/tests/unittests/config/test_cc_mcollective.py
+++ b/tests/unittests/config/test_cc_mcollective.py
@@ -1,15 +1,15 @@
# This file is part of cloud-init. See LICENSE file for license information.
-import configobj
import logging
import os
import shutil
import tempfile
from io import BytesIO
-from cloudinit import (util)
+import configobj
+
+from cloudinit import util
from cloudinit.config import cc_mcollective
from tests.unittests import helpers as t_help
-
from tests.unittests.util import get_cloud
LOG = logging.getLogger(__name__)
@@ -47,83 +47,92 @@ class TestConfig(t_help.FilesystemMockingTestCase):
self.addCleanup(shutil.rmtree, self.tmp)
# "./": make os.path.join behave correctly with abs path as second arg
self.server_cfg = os.path.join(
- self.tmp, "./" + cc_mcollective.SERVER_CFG)
+ self.tmp, "./" + cc_mcollective.SERVER_CFG
+ )
self.pubcert_file = os.path.join(
- self.tmp, "./" + cc_mcollective.PUBCERT_FILE)
+ self.tmp, "./" + cc_mcollective.PUBCERT_FILE
+ )
self.pricert_file = os.path.join(
- self.tmp, self.tmp, "./" + cc_mcollective.PRICERT_FILE)
+ self.tmp, self.tmp, "./" + cc_mcollective.PRICERT_FILE
+ )
def test_basic_config(self):
cfg = {
- 'mcollective': {
- 'conf': {
- 'loglevel': 'debug',
- 'connector': 'rabbitmq',
- 'logfile': '/var/log/mcollective.log',
- 'ttl': '4294957',
- 'collectives': 'mcollective',
- 'main_collective': 'mcollective',
- 'securityprovider': 'psk',
- 'daemonize': '1',
- 'factsource': 'yaml',
- 'direct_addressing': '1',
- 'plugin.psk': 'unset',
- 'libdir': '/usr/share/mcollective/plugins',
- 'identity': '1',
+ "mcollective": {
+ "conf": {
+ "loglevel": "debug",
+ "connector": "rabbitmq",
+ "logfile": "/var/log/mcollective.log",
+ "ttl": "4294957",
+ "collectives": "mcollective",
+ "main_collective": "mcollective",
+ "securityprovider": "psk",
+ "daemonize": "1",
+ "factsource": "yaml",
+ "direct_addressing": "1",
+ "plugin.psk": "unset",
+ "libdir": "/usr/share/mcollective/plugins",
+ "identity": "1",
},
},
}
- expected = cfg['mcollective']['conf']
+ expected = cfg["mcollective"]["conf"]
self.patchUtils(self.tmp)
- cc_mcollective.configure(cfg['mcollective']['conf'])
+ cc_mcollective.configure(cfg["mcollective"]["conf"])
contents = util.load_file(cc_mcollective.SERVER_CFG, decode=False)
contents = configobj.ConfigObj(BytesIO(contents))
self.assertEqual(expected, dict(contents))
def test_existing_config_is_saved(self):
- cfg = {'loglevel': 'warn'}
+ cfg = {"loglevel": "warn"}
util.write_file(self.server_cfg, STOCK_CONFIG)
cc_mcollective.configure(config=cfg, server_cfg=self.server_cfg)
self.assertTrue(os.path.exists(self.server_cfg))
self.assertTrue(os.path.exists(self.server_cfg + ".old"))
- self.assertEqual(util.load_file(self.server_cfg + ".old"),
- STOCK_CONFIG)
+ self.assertEqual(
+ util.load_file(self.server_cfg + ".old"), STOCK_CONFIG
+ )
def test_existing_updated(self):
- cfg = {'loglevel': 'warn'}
+ cfg = {"loglevel": "warn"}
util.write_file(self.server_cfg, STOCK_CONFIG)
cc_mcollective.configure(config=cfg, server_cfg=self.server_cfg)
cfgobj = configobj.ConfigObj(self.server_cfg)
- self.assertEqual(cfg['loglevel'], cfgobj['loglevel'])
+ self.assertEqual(cfg["loglevel"], cfgobj["loglevel"])
def test_certificats_written(self):
# check public-cert and private-cert keys in config get written
- cfg = {'loglevel': 'debug',
- 'public-cert': "this is my public-certificate",
- 'private-cert': "secret private certificate"}
+ cfg = {
+ "loglevel": "debug",
+ "public-cert": "this is my public-certificate",
+ "private-cert": "secret private certificate",
+ }
cc_mcollective.configure(
- config=cfg, server_cfg=self.server_cfg,
- pricert_file=self.pricert_file, pubcert_file=self.pubcert_file)
+ config=cfg,
+ server_cfg=self.server_cfg,
+ pricert_file=self.pricert_file,
+ pubcert_file=self.pubcert_file,
+ )
found = configobj.ConfigObj(self.server_cfg)
# make sure these didnt get written in
- self.assertFalse('public-cert' in found)
- self.assertFalse('private-cert' in found)
+ self.assertFalse("public-cert" in found)
+ self.assertFalse("private-cert" in found)
# these need updating to the specified paths
- self.assertEqual(found['plugin.ssl_server_public'], self.pubcert_file)
- self.assertEqual(found['plugin.ssl_server_private'], self.pricert_file)
+ self.assertEqual(found["plugin.ssl_server_public"], self.pubcert_file)
+ self.assertEqual(found["plugin.ssl_server_private"], self.pricert_file)
# and the security provider should be ssl
- self.assertEqual(found['securityprovider'], 'ssl')
+ self.assertEqual(found["securityprovider"], "ssl")
self.assertEqual(
- util.load_file(self.pricert_file), cfg['private-cert'])
- self.assertEqual(
- util.load_file(self.pubcert_file), cfg['public-cert'])
+ util.load_file(self.pricert_file), cfg["private-cert"]
+ )
+ self.assertEqual(util.load_file(self.pubcert_file), cfg["public-cert"])
class TestHandler(t_help.TestCase):
@@ -133,14 +142,17 @@ class TestHandler(t_help.TestCase):
cc = get_cloud()
cc.distro = t_help.mock.MagicMock()
mock_util.load_file.return_value = b""
- mycfg = {'mcollective': {'conf': {'loglevel': 'debug'}}}
- cc_mcollective.handle('cc_mcollective', mycfg, cc, LOG, [])
+ mycfg = {"mcollective": {"conf": {"loglevel": "debug"}}}
+ cc_mcollective.handle("cc_mcollective", mycfg, cc, LOG, [])
self.assertTrue(cc.distro.install_packages.called)
install_pkg = cc.distro.install_packages.call_args_list[0][0][0]
- self.assertEqual(install_pkg, ('mcollective',))
+ self.assertEqual(install_pkg, ("mcollective",))
self.assertTrue(mock_subp.subp.called)
- self.assertEqual(mock_subp.subp.call_args_list[0][0][0],
- ['service', 'mcollective', 'restart'])
+ self.assertEqual(
+ mock_subp.subp.call_args_list[0][0][0],
+ ["service", "mcollective", "restart"],
+ )
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_mounts.py b/tests/unittests/config/test_cc_mounts.py
index fc65f108..084faacd 100644
--- a/tests/unittests/config/test_cc_mounts.py
+++ b/tests/unittests/config/test_cc_mounts.py
@@ -1,302 +1,363 @@
# This file is part of cloud-init. See LICENSE file for license information.
-import pytest
import os.path
from unittest import mock
-from tests.unittests import helpers as test_helpers
+import pytest
+
from cloudinit.config import cc_mounts
from cloudinit.config.cc_mounts import create_swapfile
from cloudinit.subp import ProcessExecutionError
+from tests.unittests import helpers as test_helpers
-M_PATH = 'cloudinit.config.cc_mounts.'
+M_PATH = "cloudinit.config.cc_mounts."
class TestSanitizeDevname(test_helpers.FilesystemMockingTestCase):
-
def setUp(self):
super(TestSanitizeDevname, self).setUp()
self.new_root = self.tmp_dir()
self.patchOS(self.new_root)
def _touch(self, path):
- path = os.path.join(self.new_root, path.lstrip('/'))
+ path = os.path.join(self.new_root, path.lstrip("/"))
basedir = os.path.dirname(path)
if not os.path.exists(basedir):
os.makedirs(basedir)
- open(path, 'a').close()
+ open(path, "a").close()
def _makedirs(self, directory):
- directory = os.path.join(self.new_root, directory.lstrip('/'))
+ directory = os.path.join(self.new_root, directory.lstrip("/"))
if not os.path.exists(directory):
os.makedirs(directory)
def mock_existence_of_disk(self, disk_path):
self._touch(disk_path)
- self._makedirs(os.path.join('/sys/block', disk_path.split('/')[-1]))
+ self._makedirs(os.path.join("/sys/block", disk_path.split("/")[-1]))
def mock_existence_of_partition(self, disk_path, partition_number):
self.mock_existence_of_disk(disk_path)
self._touch(disk_path + str(partition_number))
- disk_name = disk_path.split('/')[-1]
- self._makedirs(os.path.join('/sys/block',
- disk_name,
- disk_name + str(partition_number)))
+ disk_name = disk_path.split("/")[-1]
+ self._makedirs(
+ os.path.join(
+ "/sys/block", disk_name, disk_name + str(partition_number)
+ )
+ )
def test_existent_full_disk_path_is_returned(self):
- disk_path = '/dev/sda'
+ disk_path = "/dev/sda"
self.mock_existence_of_disk(disk_path)
- self.assertEqual(disk_path,
- cc_mounts.sanitize_devname(disk_path,
- lambda x: None,
- mock.Mock()))
+ self.assertEqual(
+ disk_path,
+ cc_mounts.sanitize_devname(disk_path, lambda x: None, mock.Mock()),
+ )
def test_existent_disk_name_returns_full_path(self):
- disk_name = 'sda'
- disk_path = '/dev/' + disk_name
+ disk_name = "sda"
+ disk_path = "/dev/" + disk_name
self.mock_existence_of_disk(disk_path)
- self.assertEqual(disk_path,
- cc_mounts.sanitize_devname(disk_name,
- lambda x: None,
- mock.Mock()))
+ self.assertEqual(
+ disk_path,
+ cc_mounts.sanitize_devname(disk_name, lambda x: None, mock.Mock()),
+ )
def test_existent_meta_disk_is_returned(self):
- actual_disk_path = '/dev/sda'
+ actual_disk_path = "/dev/sda"
self.mock_existence_of_disk(actual_disk_path)
self.assertEqual(
actual_disk_path,
- cc_mounts.sanitize_devname('ephemeral0',
- lambda x: actual_disk_path,
- mock.Mock()))
+ cc_mounts.sanitize_devname(
+ "ephemeral0", lambda x: actual_disk_path, mock.Mock()
+ ),
+ )
def test_existent_meta_partition_is_returned(self):
- disk_name, partition_part = '/dev/sda', '1'
+ disk_name, partition_part = "/dev/sda", "1"
actual_partition_path = disk_name + partition_part
self.mock_existence_of_partition(disk_name, partition_part)
self.assertEqual(
actual_partition_path,
- cc_mounts.sanitize_devname('ephemeral0.1',
- lambda x: disk_name,
- mock.Mock()))
+ cc_mounts.sanitize_devname(
+ "ephemeral0.1", lambda x: disk_name, mock.Mock()
+ ),
+ )
def test_existent_meta_partition_with_p_is_returned(self):
- disk_name, partition_part = '/dev/sda', 'p1'
+ disk_name, partition_part = "/dev/sda", "p1"
actual_partition_path = disk_name + partition_part
self.mock_existence_of_partition(disk_name, partition_part)
self.assertEqual(
actual_partition_path,
- cc_mounts.sanitize_devname('ephemeral0.1',
- lambda x: disk_name,
- mock.Mock()))
+ cc_mounts.sanitize_devname(
+ "ephemeral0.1", lambda x: disk_name, mock.Mock()
+ ),
+ )
def test_first_partition_returned_if_existent_disk_is_partitioned(self):
- disk_name, partition_part = '/dev/sda', '1'
+ disk_name, partition_part = "/dev/sda", "1"
actual_partition_path = disk_name + partition_part
self.mock_existence_of_partition(disk_name, partition_part)
self.assertEqual(
actual_partition_path,
- cc_mounts.sanitize_devname('ephemeral0',
- lambda x: disk_name,
- mock.Mock()))
+ cc_mounts.sanitize_devname(
+ "ephemeral0", lambda x: disk_name, mock.Mock()
+ ),
+ )
def test_nth_partition_returned_if_requested(self):
- disk_name, partition_part = '/dev/sda', '3'
+ disk_name, partition_part = "/dev/sda", "3"
actual_partition_path = disk_name + partition_part
self.mock_existence_of_partition(disk_name, partition_part)
self.assertEqual(
actual_partition_path,
- cc_mounts.sanitize_devname('ephemeral0.3',
- lambda x: disk_name,
- mock.Mock()))
+ cc_mounts.sanitize_devname(
+ "ephemeral0.3", lambda x: disk_name, mock.Mock()
+ ),
+ )
def test_transformer_returning_none_returns_none(self):
self.assertIsNone(
cc_mounts.sanitize_devname(
- 'ephemeral0', lambda x: None, mock.Mock()))
+ "ephemeral0", lambda x: None, mock.Mock()
+ )
+ )
def test_missing_device_returns_none(self):
self.assertIsNone(
- cc_mounts.sanitize_devname('/dev/sda', None, mock.Mock()))
+ cc_mounts.sanitize_devname("/dev/sda", None, mock.Mock())
+ )
def test_missing_sys_returns_none(self):
- disk_path = '/dev/sda'
+ disk_path = "/dev/sda"
self._makedirs(disk_path)
self.assertIsNone(
- cc_mounts.sanitize_devname(disk_path, None, mock.Mock()))
+ cc_mounts.sanitize_devname(disk_path, None, mock.Mock())
+ )
def test_existent_disk_but_missing_partition_returns_none(self):
- disk_path = '/dev/sda'
+ disk_path = "/dev/sda"
self.mock_existence_of_disk(disk_path)
self.assertIsNone(
cc_mounts.sanitize_devname(
- 'ephemeral0.1', lambda x: disk_path, mock.Mock()))
+ "ephemeral0.1", lambda x: disk_path, mock.Mock()
+ )
+ )
def test_network_device_returns_network_device(self):
- disk_path = 'netdevice:/path'
+ disk_path = "netdevice:/path"
self.assertEqual(
- disk_path,
- cc_mounts.sanitize_devname(disk_path, None, mock.Mock()))
+ disk_path, cc_mounts.sanitize_devname(disk_path, None, mock.Mock())
+ )
def test_device_aliases_remapping(self):
- disk_path = '/dev/sda'
+ disk_path = "/dev/sda"
self.mock_existence_of_disk(disk_path)
- self.assertEqual(disk_path,
- cc_mounts.sanitize_devname('mydata',
- lambda x: None,
- mock.Mock(),
- {'mydata': disk_path}))
+ self.assertEqual(
+ disk_path,
+ cc_mounts.sanitize_devname(
+ "mydata", lambda x: None, mock.Mock(), {"mydata": disk_path}
+ ),
+ )
class TestSwapFileCreation(test_helpers.FilesystemMockingTestCase):
-
def setUp(self):
super(TestSwapFileCreation, self).setUp()
self.new_root = self.tmp_dir()
self.patchOS(self.new_root)
- self.fstab_path = os.path.join(self.new_root, 'etc/fstab')
- self.swap_path = os.path.join(self.new_root, 'swap.img')
- self._makedirs('/etc')
+ self.fstab_path = os.path.join(self.new_root, "etc/fstab")
+ self.swap_path = os.path.join(self.new_root, "swap.img")
+ self._makedirs("/etc")
- self.add_patch('cloudinit.config.cc_mounts.FSTAB_PATH',
- 'mock_fstab_path',
- self.fstab_path,
- autospec=False)
-
- self.add_patch('cloudinit.config.cc_mounts.subp.subp',
- 'm_subp_subp')
+ self.add_patch(
+ "cloudinit.config.cc_mounts.FSTAB_PATH",
+ "mock_fstab_path",
+ self.fstab_path,
+ autospec=False,
+ )
- self.add_patch('cloudinit.config.cc_mounts.util.mounts',
- 'mock_util_mounts',
- return_value={
- '/dev/sda1': {'fstype': 'ext4',
- 'mountpoint': '/',
- 'opts': 'rw,relatime,discard'
- }})
+ self.add_patch("cloudinit.config.cc_mounts.subp.subp", "m_subp_subp")
+
+ self.add_patch(
+ "cloudinit.config.cc_mounts.util.mounts",
+ "mock_util_mounts",
+ return_value={
+ "/dev/sda1": {
+ "fstype": "ext4",
+ "mountpoint": "/",
+ "opts": "rw,relatime,discard",
+ }
+ },
+ )
self.mock_cloud = mock.Mock()
self.mock_log = mock.Mock()
self.mock_cloud.device_name_to_device = self.device_name_to_device
self.cc = {
- 'swap': {
- 'filename': self.swap_path,
- 'size': '512',
- 'maxsize': '512'}}
+ "swap": {
+ "filename": self.swap_path,
+ "size": "512",
+ "maxsize": "512",
+ }
+ }
def _makedirs(self, directory):
- directory = os.path.join(self.new_root, directory.lstrip('/'))
+ directory = os.path.join(self.new_root, directory.lstrip("/"))
if not os.path.exists(directory):
os.makedirs(directory)
def device_name_to_device(self, path):
- if path == 'swap':
+ if path == "swap":
return self.swap_path
else:
dev = None
return dev
- @mock.patch('cloudinit.util.get_mount_info')
- @mock.patch('cloudinit.util.kernel_version')
- def test_swap_creation_method_fallocate_on_xfs(self, m_kernel_version,
- m_get_mount_info):
+ @mock.patch("cloudinit.util.get_mount_info")
+ @mock.patch("cloudinit.util.kernel_version")
+ def test_swap_creation_method_fallocate_on_xfs(
+ self, m_kernel_version, m_get_mount_info
+ ):
m_kernel_version.return_value = (4, 20)
m_get_mount_info.return_value = ["", "xfs"]
cc_mounts.handle(None, self.cc, self.mock_cloud, self.mock_log, [])
- self.m_subp_subp.assert_has_calls([
- mock.call(['fallocate', '-l', '0M', self.swap_path], capture=True),
- mock.call(['mkswap', self.swap_path]),
- mock.call(['swapon', '-a'])])
-
- @mock.patch('cloudinit.util.get_mount_info')
- @mock.patch('cloudinit.util.kernel_version')
- def test_swap_creation_method_xfs(self, m_kernel_version,
- m_get_mount_info):
+ self.m_subp_subp.assert_has_calls(
+ [
+ mock.call(
+ ["fallocate", "-l", "0M", self.swap_path], capture=True
+ ),
+ mock.call(["mkswap", self.swap_path]),
+ mock.call(["swapon", "-a"]),
+ ]
+ )
+
+ @mock.patch("cloudinit.util.get_mount_info")
+ @mock.patch("cloudinit.util.kernel_version")
+ def test_swap_creation_method_xfs(
+ self, m_kernel_version, m_get_mount_info
+ ):
m_kernel_version.return_value = (3, 18)
m_get_mount_info.return_value = ["", "xfs"]
cc_mounts.handle(None, self.cc, self.mock_cloud, self.mock_log, [])
- self.m_subp_subp.assert_has_calls([
- mock.call(['dd', 'if=/dev/zero',
- 'of=' + self.swap_path,
- 'bs=1M', 'count=0'], capture=True),
- mock.call(['mkswap', self.swap_path]),
- mock.call(['swapon', '-a'])])
-
- @mock.patch('cloudinit.util.get_mount_info')
- @mock.patch('cloudinit.util.kernel_version')
- def test_swap_creation_method_btrfs(self, m_kernel_version,
- m_get_mount_info):
+ self.m_subp_subp.assert_has_calls(
+ [
+ mock.call(
+ [
+ "dd",
+ "if=/dev/zero",
+ "of=" + self.swap_path,
+ "bs=1M",
+ "count=0",
+ ],
+ capture=True,
+ ),
+ mock.call(["mkswap", self.swap_path]),
+ mock.call(["swapon", "-a"]),
+ ]
+ )
+
+ @mock.patch("cloudinit.util.get_mount_info")
+ @mock.patch("cloudinit.util.kernel_version")
+ def test_swap_creation_method_btrfs(
+ self, m_kernel_version, m_get_mount_info
+ ):
m_kernel_version.return_value = (4, 20)
m_get_mount_info.return_value = ["", "btrfs"]
cc_mounts.handle(None, self.cc, self.mock_cloud, self.mock_log, [])
- self.m_subp_subp.assert_has_calls([
- mock.call(['dd', 'if=/dev/zero',
- 'of=' + self.swap_path,
- 'bs=1M', 'count=0'], capture=True),
- mock.call(['mkswap', self.swap_path]),
- mock.call(['swapon', '-a'])])
-
- @mock.patch('cloudinit.util.get_mount_info')
- @mock.patch('cloudinit.util.kernel_version')
- def test_swap_creation_method_ext4(self, m_kernel_version,
- m_get_mount_info):
+ self.m_subp_subp.assert_has_calls(
+ [
+ mock.call(
+ [
+ "dd",
+ "if=/dev/zero",
+ "of=" + self.swap_path,
+ "bs=1M",
+ "count=0",
+ ],
+ capture=True,
+ ),
+ mock.call(["mkswap", self.swap_path]),
+ mock.call(["swapon", "-a"]),
+ ]
+ )
+
+ @mock.patch("cloudinit.util.get_mount_info")
+ @mock.patch("cloudinit.util.kernel_version")
+ def test_swap_creation_method_ext4(
+ self, m_kernel_version, m_get_mount_info
+ ):
m_kernel_version.return_value = (5, 14)
m_get_mount_info.return_value = ["", "ext4"]
cc_mounts.handle(None, self.cc, self.mock_cloud, self.mock_log, [])
- self.m_subp_subp.assert_has_calls([
- mock.call(['fallocate', '-l', '0M', self.swap_path], capture=True),
- mock.call(['mkswap', self.swap_path]),
- mock.call(['swapon', '-a'])])
+ self.m_subp_subp.assert_has_calls(
+ [
+ mock.call(
+ ["fallocate", "-l", "0M", self.swap_path], capture=True
+ ),
+ mock.call(["mkswap", self.swap_path]),
+ mock.call(["swapon", "-a"]),
+ ]
+ )
class TestFstabHandling(test_helpers.FilesystemMockingTestCase):
- swap_path = '/dev/sdb1'
+ swap_path = "/dev/sdb1"
def setUp(self):
super(TestFstabHandling, self).setUp()
self.new_root = self.tmp_dir()
self.patchOS(self.new_root)
- self.fstab_path = os.path.join(self.new_root, 'etc/fstab')
- self._makedirs('/etc')
-
- self.add_patch('cloudinit.config.cc_mounts.FSTAB_PATH',
- 'mock_fstab_path',
- self.fstab_path,
- autospec=False)
+ self.fstab_path = os.path.join(self.new_root, "etc/fstab")
+ self._makedirs("/etc")
- self.add_patch('cloudinit.config.cc_mounts._is_block_device',
- 'mock_is_block_device',
- return_value=True)
+ self.add_patch(
+ "cloudinit.config.cc_mounts.FSTAB_PATH",
+ "mock_fstab_path",
+ self.fstab_path,
+ autospec=False,
+ )
- self.add_patch('cloudinit.config.cc_mounts.subp.subp',
- 'm_subp_subp')
+ self.add_patch(
+ "cloudinit.config.cc_mounts._is_block_device",
+ "mock_is_block_device",
+ return_value=True,
+ )
- self.add_patch('cloudinit.config.cc_mounts.util.mounts',
- 'mock_util_mounts',
- return_value={
- '/dev/sda1': {'fstype': 'ext4',
- 'mountpoint': '/',
- 'opts': 'rw,relatime,discard'
- }})
+ self.add_patch("cloudinit.config.cc_mounts.subp.subp", "m_subp_subp")
+
+ self.add_patch(
+ "cloudinit.config.cc_mounts.util.mounts",
+ "mock_util_mounts",
+ return_value={
+ "/dev/sda1": {
+ "fstype": "ext4",
+ "mountpoint": "/",
+ "opts": "rw,relatime,discard",
+ }
+ },
+ )
self.mock_cloud = mock.Mock()
self.mock_log = mock.Mock()
self.mock_cloud.device_name_to_device = self.device_name_to_device
def _makedirs(self, directory):
- directory = os.path.join(self.new_root, directory.lstrip('/'))
+ directory = os.path.join(self.new_root, directory.lstrip("/"))
if not os.path.exists(directory):
os.makedirs(directory)
def device_name_to_device(self, path):
- if path == 'swap':
+ if path == "swap":
return self.swap_path
else:
dev = None
@@ -304,127 +365,126 @@ class TestFstabHandling(test_helpers.FilesystemMockingTestCase):
return dev
def test_no_fstab(self):
- """ Handle images which do not include an fstab. """
+ """Handle images which do not include an fstab."""
self.assertFalse(os.path.exists(cc_mounts.FSTAB_PATH))
fstab_expected_content = (
- '%s\tnone\tswap\tsw,comment=cloudconfig\t'
- '0\t0\n' % (self.swap_path,)
+ "%s\tnone\tswap\tsw,comment=cloudconfig\t0\t0\n"
+ % (self.swap_path,)
)
cc_mounts.handle(None, {}, self.mock_cloud, self.mock_log, [])
- with open(cc_mounts.FSTAB_PATH, 'r') as fd:
+ with open(cc_mounts.FSTAB_PATH, "r") as fd:
fstab_new_content = fd.read()
self.assertEqual(fstab_expected_content, fstab_new_content)
def test_swap_integrity(self):
- '''Ensure that the swap file is correctly created and can
+ """Ensure that the swap file is correctly created and can
swapon successfully. Fixing the corner case of:
- kernel: swapon: swapfile has holes'''
+ kernel: swapon: swapfile has holes"""
- fstab = '/swap.img swap swap defaults 0 0\n'
+ fstab = "/swap.img swap swap defaults 0 0\n"
- with open(cc_mounts.FSTAB_PATH, 'w') as fd:
+ with open(cc_mounts.FSTAB_PATH, "w") as fd:
fd.write(fstab)
- cc = {'swap': ['filename: /swap.img', 'size: 512', 'maxsize: 512']}
+ cc = {"swap": ["filename: /swap.img", "size: 512", "maxsize: 512"]}
cc_mounts.handle(None, cc, self.mock_cloud, self.mock_log, [])
def test_fstab_no_swap_device(self):
- '''Ensure that cloud-init adds a discovered swap partition
- to /etc/fstab.'''
+ """Ensure that cloud-init adds a discovered swap partition
+ to /etc/fstab."""
- fstab_original_content = ''
+ fstab_original_content = ""
fstab_expected_content = (
- '%s\tnone\tswap\tsw,comment=cloudconfig\t'
- '0\t0\n' % (self.swap_path,)
+ "%s\tnone\tswap\tsw,comment=cloudconfig\t0\t0\n"
+ % (self.swap_path,)
)
- with open(cc_mounts.FSTAB_PATH, 'w') as fd:
+ with open(cc_mounts.FSTAB_PATH, "w") as fd:
fd.write(fstab_original_content)
cc_mounts.handle(None, {}, self.mock_cloud, self.mock_log, [])
- with open(cc_mounts.FSTAB_PATH, 'r') as fd:
+ with open(cc_mounts.FSTAB_PATH, "r") as fd:
fstab_new_content = fd.read()
self.assertEqual(fstab_expected_content, fstab_new_content)
def test_fstab_same_swap_device_already_configured(self):
- '''Ensure that cloud-init will not add a swap device if the same
- device already exists in /etc/fstab.'''
+ """Ensure that cloud-init will not add a swap device if the same
+ device already exists in /etc/fstab."""
- fstab_original_content = '%s swap swap defaults 0 0\n' % (
- self.swap_path,)
+ fstab_original_content = "%s swap swap defaults 0 0\n" % (
+ self.swap_path,
+ )
fstab_expected_content = fstab_original_content
- with open(cc_mounts.FSTAB_PATH, 'w') as fd:
+ with open(cc_mounts.FSTAB_PATH, "w") as fd:
fd.write(fstab_original_content)
cc_mounts.handle(None, {}, self.mock_cloud, self.mock_log, [])
- with open(cc_mounts.FSTAB_PATH, 'r') as fd:
+ with open(cc_mounts.FSTAB_PATH, "r") as fd:
fstab_new_content = fd.read()
self.assertEqual(fstab_expected_content, fstab_new_content)
def test_fstab_alternate_swap_device_already_configured(self):
- '''Ensure that cloud-init will add a discovered swap device to
+ """Ensure that cloud-init will add a discovered swap device to
/etc/fstab even when there exists a swap definition on another
- device.'''
+ device."""
- fstab_original_content = '/dev/sdc1 swap swap defaults 0 0\n'
+ fstab_original_content = "/dev/sdc1 swap swap defaults 0 0\n"
fstab_expected_content = (
- fstab_original_content +
- '%s\tnone\tswap\tsw,comment=cloudconfig\t'
- '0\t0\n' % (self.swap_path,)
+ fstab_original_content
+ + "%s\tnone\tswap\tsw,comment=cloudconfig\t0\t0\n"
+ % (self.swap_path,)
)
- with open(cc_mounts.FSTAB_PATH, 'w') as fd:
+ with open(cc_mounts.FSTAB_PATH, "w") as fd:
fd.write(fstab_original_content)
cc_mounts.handle(None, {}, self.mock_cloud, self.mock_log, [])
- with open(cc_mounts.FSTAB_PATH, 'r') as fd:
+ with open(cc_mounts.FSTAB_PATH, "r") as fd:
fstab_new_content = fd.read()
self.assertEqual(fstab_expected_content, fstab_new_content)
def test_no_change_fstab_sets_needs_mount_all(self):
- '''verify unchanged fstab entries are mounted if not call mount -a'''
+ """verify unchanged fstab entries are mounted if not call mount -a"""
fstab_original_content = (
- 'LABEL=cloudimg-rootfs / ext4 defaults 0 0\n'
- 'LABEL=UEFI /boot/efi vfat defaults 0 0\n'
- '/dev/vdb /mnt auto defaults,noexec,comment=cloudconfig 0 2\n'
+ "LABEL=cloudimg-rootfs / ext4 defaults 0 0\n"
+ "LABEL=UEFI /boot/efi vfat defaults 0 0\n"
+ "/dev/vdb /mnt auto defaults,noexec,comment=cloudconfig 0 2\n"
)
fstab_expected_content = fstab_original_content
- cc = {
- 'mounts': [
- ['/dev/vdb', '/mnt', 'auto', 'defaults,noexec']
- ]
- }
- with open(cc_mounts.FSTAB_PATH, 'w') as fd:
+ cc = {"mounts": [["/dev/vdb", "/mnt", "auto", "defaults,noexec"]]}
+ with open(cc_mounts.FSTAB_PATH, "w") as fd:
fd.write(fstab_original_content)
- with open(cc_mounts.FSTAB_PATH, 'r') as fd:
+ with open(cc_mounts.FSTAB_PATH, "r") as fd:
fstab_new_content = fd.read()
self.assertEqual(fstab_expected_content, fstab_new_content)
cc_mounts.handle(None, cc, self.mock_cloud, self.mock_log, [])
- self.m_subp_subp.assert_has_calls([
- mock.call(['mount', '-a']),
- mock.call(['systemctl', 'daemon-reload'])])
+ self.m_subp_subp.assert_has_calls(
+ [
+ mock.call(["mount", "-a"]),
+ mock.call(["systemctl", "daemon-reload"]),
+ ]
+ )
class TestCreateSwapfile:
-
- @pytest.mark.parametrize('fstype', ('xfs', 'btrfs', 'ext4', 'other'))
- @mock.patch(M_PATH + 'util.get_mount_info')
- @mock.patch(M_PATH + 'subp.subp')
+ @pytest.mark.parametrize("fstype", ("xfs", "btrfs", "ext4", "other"))
+ @mock.patch(M_PATH + "util.get_mount_info")
+ @mock.patch(M_PATH + "subp.subp")
def test_happy_path(self, m_subp, m_get_mount_info, fstype, tmpdir):
swap_file = tmpdir.join("swap-file")
fname = str(swap_file)
# Some of the calls to subp.subp should create the swap file; this
# roughly approximates that
- m_subp.side_effect = lambda *args, **kwargs: swap_file.write('')
+ m_subp.side_effect = lambda *args, **kwargs: swap_file.write("")
m_get_mount_info.return_value = (mock.ANY, fstype)
- create_swapfile(fname, '')
- assert mock.call(['mkswap', fname]) in m_subp.call_args_list
+ create_swapfile(fname, "")
+ assert mock.call(["mkswap", fname]) in m_subp.call_args_list
@mock.patch(M_PATH + "util.get_mount_info")
@mock.patch(M_PATH + "subp.subp")
@@ -458,4 +518,5 @@ class TestCreateSwapfile:
msg = "fallocate swap creation failed, will attempt with dd"
assert msg in caplog.text
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_ntp.py b/tests/unittests/config/test_cc_ntp.py
index 3426533a..7da82cee 100644
--- a/tests/unittests/config/test_cc_ntp.py
+++ b/tests/unittests/config/test_cc_ntp.py
@@ -5,14 +5,16 @@ import shutil
from functools import partial
from os.path import dirname
-from cloudinit import (helpers, util)
+from cloudinit import helpers, util
from cloudinit.config import cc_ntp
from tests.unittests.helpers import (
- CiTestCase, FilesystemMockingTestCase, mock, skipUnlessJsonSchema)
-
+ CiTestCase,
+ FilesystemMockingTestCase,
+ mock,
+ skipUnlessJsonSchema,
+)
from tests.unittests.util import get_cloud
-
NTP_TEMPLATE = """\
## template: jinja
servers {{servers}}
@@ -35,18 +37,18 @@ class TestNtp(FilesystemMockingTestCase):
def setUp(self):
super(TestNtp, self).setUp()
self.new_root = self.tmp_dir()
- self.add_patch('cloudinit.util.system_is_snappy', 'm_snappy')
+ self.add_patch("cloudinit.util.system_is_snappy", "m_snappy")
self.m_snappy.return_value = False
self.new_root = self.reRoot()
self._get_cloud = partial(
- get_cloud,
- paths=helpers.Paths({'templates_dir': self.new_root})
+ get_cloud, paths=helpers.Paths({"templates_dir": self.new_root})
)
def _get_template_path(self, template_name, distro, basepath=None):
# ntp.conf.{distro} -> ntp.conf.debian.tmpl
- template_fn = '{0}.tmpl'.format(
- template_name.replace('{distro}', distro))
+ template_fn = "{0}.tmpl".format(
+ template_name.replace("{distro}", distro)
+ )
if not basepath:
basepath = self.new_root
path = os.path.join(basepath, template_fn)
@@ -55,25 +57,25 @@ class TestNtp(FilesystemMockingTestCase):
def _generate_template(self, template=None):
if not template:
template = NTP_TEMPLATE
- confpath = os.path.join(self.new_root, 'client.conf')
- template_fn = os.path.join(self.new_root, 'client.conf.tmpl')
+ confpath = os.path.join(self.new_root, "client.conf")
+ template_fn = os.path.join(self.new_root, "client.conf.tmpl")
util.write_file(template_fn, content=template)
return (confpath, template_fn)
def _mock_ntp_client_config(self, client=None, distro=None):
if not client:
- client = 'ntp'
+ client = "ntp"
if not distro:
- distro = 'ubuntu'
+ distro = "ubuntu"
dcfg = cc_ntp.distro_ntp_client_configs(distro)
- if client == 'systemd-timesyncd':
+ if client == "systemd-timesyncd":
template = TIMESYNCD_TEMPLATE
else:
template = NTP_TEMPLATE
(confpath, _template_fn) = self._generate_template(template=template)
ntpconfig = copy.deepcopy(dcfg[client])
- ntpconfig['confpath'] = confpath
- ntpconfig['template_name'] = os.path.basename(confpath)
+ ntpconfig["confpath"] = confpath
+ ntpconfig["template_name"] = os.path.basename(confpath)
return ntpconfig
@mock.patch("cloudinit.config.cc_ntp.subp")
@@ -81,19 +83,21 @@ class TestNtp(FilesystemMockingTestCase):
"""ntp_install_client runs install_func when check_exe is absent."""
mock_subp.which.return_value = None # check_exe not found.
install_func = mock.MagicMock()
- cc_ntp.install_ntp_client(install_func,
- packages=['ntpx'], check_exe='ntpdx')
- mock_subp.which.assert_called_with('ntpdx')
- install_func.assert_called_once_with(['ntpx'])
+ cc_ntp.install_ntp_client(
+ install_func, packages=["ntpx"], check_exe="ntpdx"
+ )
+ mock_subp.which.assert_called_with("ntpdx")
+ install_func.assert_called_once_with(["ntpx"])
@mock.patch("cloudinit.config.cc_ntp.subp")
def test_ntp_install_not_needed(self, mock_subp):
"""ntp_install_client doesn't install when check_exe is found."""
- client = 'chrony'
+ client = "chrony"
mock_subp.which.return_value = [client] # check_exe found.
install_func = mock.MagicMock()
- cc_ntp.install_ntp_client(install_func, packages=[client],
- check_exe=client)
+ cc_ntp.install_ntp_client(
+ install_func, packages=[client], check_exe=client
+ )
install_func.assert_not_called()
@mock.patch("cloudinit.config.cc_ntp.subp")
@@ -101,8 +105,9 @@ class TestNtp(FilesystemMockingTestCase):
"""ntp_install_client runs install_func with empty list"""
mock_subp.which.return_value = None # check_exe not found
install_func = mock.MagicMock()
- cc_ntp.install_ntp_client(install_func, packages=[],
- check_exe='timesyncd')
+ cc_ntp.install_ntp_client(
+ install_func, packages=[], check_exe="timesyncd"
+ )
install_func.assert_called_once_with([])
def test_ntp_rename_ntp_conf(self):
@@ -124,18 +129,22 @@ class TestNtp(FilesystemMockingTestCase):
def test_write_ntp_config_template_uses_ntp_conf_distro_no_servers(self):
"""write_ntp_config_template reads from $client.conf.distro.tmpl"""
servers = []
- pools = ['10.0.0.1', '10.0.0.2']
+ pools = ["10.0.0.1", "10.0.0.2"]
(confpath, template_fn) = self._generate_template()
- mock_path = 'cloudinit.config.cc_ntp.temp_utils._TMPDIR'
+ mock_path = "cloudinit.config.cc_ntp.temp_utils._TMPDIR"
with mock.patch(mock_path, self.new_root):
- cc_ntp.write_ntp_config_template('ubuntu',
- servers=servers, pools=pools,
- path=confpath,
- template_fn=template_fn,
- template=None)
+ cc_ntp.write_ntp_config_template(
+ "ubuntu",
+ servers=servers,
+ pools=pools,
+ path=confpath,
+ template_fn=template_fn,
+ template=None,
+ )
self.assertEqual(
"servers []\npools ['10.0.0.1', '10.0.0.2']\n",
- util.load_file(confpath))
+ util.load_file(confpath),
+ )
def test_write_ntp_config_template_defaults_pools_w_empty_lists(self):
"""write_ntp_config_template defaults pools servers upon empty config.
@@ -143,20 +152,23 @@ class TestNtp(FilesystemMockingTestCase):
When both pools and servers are empty, default NR_POOL_SERVERS get
configured.
"""
- distro = 'ubuntu'
+ distro = "ubuntu"
pools = cc_ntp.generate_server_names(distro)
servers = []
(confpath, template_fn) = self._generate_template()
- mock_path = 'cloudinit.config.cc_ntp.temp_utils._TMPDIR'
+ mock_path = "cloudinit.config.cc_ntp.temp_utils._TMPDIR"
with mock.patch(mock_path, self.new_root):
- cc_ntp.write_ntp_config_template(distro,
- servers=servers, pools=pools,
- path=confpath,
- template_fn=template_fn,
- template=None)
+ cc_ntp.write_ntp_config_template(
+ distro,
+ servers=servers,
+ pools=pools,
+ path=confpath,
+ template_fn=template_fn,
+ template=None,
+ )
self.assertEqual(
- "servers []\npools {0}\n".format(pools),
- util.load_file(confpath))
+ "servers []\npools {0}\n".format(pools), util.load_file(confpath)
+ )
def test_defaults_pools_empty_lists_sles(self):
"""write_ntp_config_template defaults opensuse pools upon empty config.
@@ -164,39 +176,50 @@ class TestNtp(FilesystemMockingTestCase):
When both pools and servers are empty, default NR_POOL_SERVERS get
configured.
"""
- distro = 'sles'
+ distro = "sles"
default_pools = cc_ntp.generate_server_names(distro)
(confpath, template_fn) = self._generate_template()
- cc_ntp.write_ntp_config_template(distro,
- servers=[], pools=[],
- path=confpath,
- template_fn=template_fn,
- template=None)
+ cc_ntp.write_ntp_config_template(
+ distro,
+ servers=[],
+ pools=[],
+ path=confpath,
+ template_fn=template_fn,
+ template=None,
+ )
for pool in default_pools:
- self.assertIn('opensuse', pool)
+ self.assertIn("opensuse", pool)
self.assertEqual(
"servers []\npools {0}\n".format(default_pools),
- util.load_file(confpath))
+ util.load_file(confpath),
+ )
self.assertIn(
"Adding distro default ntp pool servers: {0}".format(
- ",".join(default_pools)),
- self.logs.getvalue())
+ ",".join(default_pools)
+ ),
+ self.logs.getvalue(),
+ )
def test_timesyncd_template(self):
"""Test timesycnd template is correct"""
- pools = ['0.mycompany.pool.ntp.org', '3.mycompany.pool.ntp.org']
- servers = ['192.168.23.3', '192.168.23.4']
+ pools = ["0.mycompany.pool.ntp.org", "3.mycompany.pool.ntp.org"]
+ servers = ["192.168.23.3", "192.168.23.4"]
(confpath, template_fn) = self._generate_template(
- template=TIMESYNCD_TEMPLATE)
- cc_ntp.write_ntp_config_template('ubuntu',
- servers=servers, pools=pools,
- path=confpath,
- template_fn=template_fn,
- template=None)
+ template=TIMESYNCD_TEMPLATE
+ )
+ cc_ntp.write_ntp_config_template(
+ "ubuntu",
+ servers=servers,
+ pools=pools,
+ path=confpath,
+ template_fn=template_fn,
+ template=None,
+ )
self.assertEqual(
"[Time]\nNTP=%s %s \n" % (" ".join(servers), " ".join(pools)),
- util.load_file(confpath))
+ util.load_file(confpath),
+ )
def test_distro_ntp_client_configs(self):
"""Test we have updated ntp client configs on different distros"""
@@ -213,55 +236,62 @@ class TestNtp(FilesystemMockingTestCase):
result = cc_ntp.distro_ntp_client_configs(distro)
for client in delta[distro].keys():
for key in delta[distro][client].keys():
- self.assertEqual(delta[distro][client][key],
- result[client][key])
+ self.assertEqual(
+ delta[distro][client][key], result[client][key]
+ )
def _get_expected_pools(self, pools, distro, client):
- if client in ['ntp', 'chrony']:
- if client == 'ntp' and distro == 'alpine':
+ if client in ["ntp", "chrony"]:
+ if client == "ntp" and distro == "alpine":
# NTP for Alpine Linux is Busybox's ntp which does not
# support 'pool' lines in its configuration file.
expected_pools = []
else:
expected_pools = [
- 'pool {0} iburst'.format(pool) for pool in pools]
- elif client == 'systemd-timesyncd':
+ "pool {0} iburst".format(pool) for pool in pools
+ ]
+ elif client == "systemd-timesyncd":
expected_pools = " ".join(pools)
return expected_pools
def _get_expected_servers(self, servers, distro, client):
- if client in ['ntp', 'chrony']:
- if client == 'ntp' and distro == 'alpine':
+ if client in ["ntp", "chrony"]:
+ if client == "ntp" and distro == "alpine":
# NTP for Alpine Linux is Busybox's ntp which only supports
# 'server' lines without iburst option.
expected_servers = [
- 'server {0}'.format(srv) for srv in servers]
+ "server {0}".format(srv) for srv in servers
+ ]
else:
expected_servers = [
- 'server {0} iburst'.format(srv) for srv in servers]
- elif client == 'systemd-timesyncd':
+ "server {0} iburst".format(srv) for srv in servers
+ ]
+ elif client == "systemd-timesyncd":
expected_servers = " ".join(servers)
return expected_servers
def test_ntp_handler_real_distro_ntp_templates(self):
"""Test ntp handler renders the shipped distro ntp client templates."""
- pools = ['0.mycompany.pool.ntp.org', '3.mycompany.pool.ntp.org']
- servers = ['192.168.23.3', '192.168.23.4']
- for client in ['ntp', 'systemd-timesyncd', 'chrony']:
+ pools = ["0.mycompany.pool.ntp.org", "3.mycompany.pool.ntp.org"]
+ servers = ["192.168.23.3", "192.168.23.4"]
+ for client in ["ntp", "systemd-timesyncd", "chrony"]:
for distro in cc_ntp.distros:
distro_cfg = cc_ntp.distro_ntp_client_configs(distro)
ntpclient = distro_cfg[client]
- confpath = (
- os.path.join(self.new_root, ntpclient.get('confpath')[1:]))
- template = ntpclient.get('template_name')
+ confpath = os.path.join(
+ self.new_root, ntpclient.get("confpath")[1:]
+ )
+ template = ntpclient.get("template_name")
# find sourcetree template file
root_dir = (
- dirname(dirname(os.path.realpath(util.__file__))) +
- '/templates')
- source_fn = self._get_template_path(template, distro,
- basepath=root_dir)
+ dirname(dirname(os.path.realpath(util.__file__)))
+ + "/templates"
+ )
+ source_fn = self._get_template_path(
+ template, distro, basepath=root_dir
+ )
template_fn = self._get_template_path(template, distro)
# don't fail if cloud-init doesn't have a template for
# a distro,client pair
@@ -269,64 +299,77 @@ class TestNtp(FilesystemMockingTestCase):
continue
# Create a copy in our tmp_dir
shutil.copy(source_fn, template_fn)
- cc_ntp.write_ntp_config_template(distro, servers=servers,
- pools=pools, path=confpath,
- template_fn=template_fn)
+ cc_ntp.write_ntp_config_template(
+ distro,
+ servers=servers,
+ pools=pools,
+ path=confpath,
+ template_fn=template_fn,
+ )
content = util.load_file(confpath)
- if client in ['ntp', 'chrony']:
+ if client in ["ntp", "chrony"]:
content_lines = content.splitlines()
- expected_servers = self._get_expected_servers(servers,
- distro,
- client)
- print('distro=%s client=%s' % (distro, client))
+ expected_servers = self._get_expected_servers(
+ servers, distro, client
+ )
+ print("distro=%s client=%s" % (distro, client))
for sline in expected_servers:
- self.assertIn(sline, content_lines,
- ('failed to render {0} conf'
- ' for distro:{1}'.format(client,
- distro)))
- expected_pools = self._get_expected_pools(pools, distro,
- client)
+ self.assertIn(
+ sline,
+ content_lines,
+ "failed to render {0} conf for distro:{1}".format(
+ client, distro
+ ),
+ )
+ expected_pools = self._get_expected_pools(
+ pools, distro, client
+ )
if expected_pools != []:
for pline in expected_pools:
- self.assertIn(pline, content_lines,
- ('failed to render {0} conf'
- ' for distro:{1}'.format(client,
- distro)))
- elif client == 'systemd-timesyncd':
- expected_servers = self._get_expected_servers(servers,
- distro,
- client)
- expected_pools = self._get_expected_pools(pools,
- distro,
- client)
+ self.assertIn(
+ pline,
+ content_lines,
+ "failed to render {0} conf"
+ " for distro:{1}".format(client, distro),
+ )
+ elif client == "systemd-timesyncd":
+ expected_servers = self._get_expected_servers(
+ servers, distro, client
+ )
+ expected_pools = self._get_expected_pools(
+ pools, distro, client
+ )
expected_content = (
- "# cloud-init generated file\n" +
- "# See timesyncd.conf(5) for details.\n\n" +
- "[Time]\nNTP=%s %s \n" % (expected_servers,
- expected_pools))
+ "# cloud-init generated file\n"
+ + "# See timesyncd.conf(5) for details.\n\n"
+ + "[Time]\nNTP=%s %s \n"
+ % (expected_servers, expected_pools)
+ )
self.assertEqual(expected_content, content)
def test_no_ntpcfg_does_nothing(self):
"""When no ntp section is defined handler logs a warning and noops."""
- cc_ntp.handle('cc_ntp', {}, None, None, [])
+ cc_ntp.handle("cc_ntp", {}, None, None, [])
self.assertEqual(
- 'DEBUG: Skipping module named cc_ntp, '
- 'not present or disabled by cfg\n',
- self.logs.getvalue())
+ "DEBUG: Skipping module named cc_ntp, "
+ "not present or disabled by cfg\n",
+ self.logs.getvalue(),
+ )
- @mock.patch('cloudinit.config.cc_ntp.select_ntp_client')
- def test_ntp_handler_schema_validation_allows_empty_ntp_config(self,
- m_select):
+ @mock.patch("cloudinit.config.cc_ntp.select_ntp_client")
+ def test_ntp_handler_schema_validation_allows_empty_ntp_config(
+ self, m_select
+ ):
"""Ntp schema validation allows for an empty ntp: configuration."""
- valid_empty_configs = [{'ntp': {}}, {'ntp': None}]
+ valid_empty_configs = [{"ntp": {}}, {"ntp": None}]
for valid_empty_config in valid_empty_configs:
for distro in cc_ntp.distros:
mycloud = self._get_cloud(distro)
ntpconfig = self._mock_ntp_client_config(distro=distro)
- confpath = ntpconfig['confpath']
+ confpath = ntpconfig["confpath"]
m_select.return_value = ntpconfig
- cc_ntp.handle('cc_ntp', valid_empty_config, mycloud, None, [])
- if distro == 'alpine':
+ cc_ntp.handle("cc_ntp", valid_empty_config, mycloud, None, [])
+ if distro == "alpine":
# _mock_ntp_client_config call above did not specify a
# client value and so it defaults to "ntp" which on
# Alpine Linux only supports servers and not pools.
@@ -334,217 +377,240 @@ class TestNtp(FilesystemMockingTestCase):
servers = cc_ntp.generate_server_names(mycloud.distro.name)
self.assertEqual(
"servers {0}\npools []\n".format(servers),
- util.load_file(confpath))
+ util.load_file(confpath),
+ )
else:
pools = cc_ntp.generate_server_names(mycloud.distro.name)
self.assertEqual(
"servers []\npools {0}\n".format(pools),
- util.load_file(confpath))
- self.assertNotIn('Invalid config:', self.logs.getvalue())
+ util.load_file(confpath),
+ )
+ self.assertNotIn("Invalid config:", self.logs.getvalue())
@skipUnlessJsonSchema()
- @mock.patch('cloudinit.config.cc_ntp.select_ntp_client')
- def test_ntp_handler_schema_validation_warns_non_string_item_type(self,
- m_sel):
+ @mock.patch("cloudinit.config.cc_ntp.select_ntp_client")
+ def test_ntp_handler_schema_validation_warns_non_string_item_type(
+ self, m_sel
+ ):
"""Ntp schema validation warns of non-strings in pools or servers.
Schema validation is not strict, so ntp config is still be rendered.
"""
- invalid_config = {'ntp': {'pools': [123], 'servers': ['valid', None]}}
+ invalid_config = {"ntp": {"pools": [123], "servers": ["valid", None]}}
for distro in cc_ntp.distros:
mycloud = self._get_cloud(distro)
ntpconfig = self._mock_ntp_client_config(distro=distro)
- confpath = ntpconfig['confpath']
+ confpath = ntpconfig["confpath"]
m_sel.return_value = ntpconfig
- cc_ntp.handle('cc_ntp', invalid_config, mycloud, None, [])
+ cc_ntp.handle("cc_ntp", invalid_config, mycloud, None, [])
self.assertIn(
"Invalid config:\nntp.pools.0: 123 is not of type 'string'\n"
"ntp.servers.1: None is not of type 'string'",
- self.logs.getvalue())
- self.assertEqual("servers ['valid', None]\npools [123]\n",
- util.load_file(confpath))
+ self.logs.getvalue(),
+ )
+ self.assertEqual(
+ "servers ['valid', None]\npools [123]\n",
+ util.load_file(confpath),
+ )
@skipUnlessJsonSchema()
- @mock.patch('cloudinit.config.cc_ntp.select_ntp_client')
- def test_ntp_handler_schema_validation_warns_of_non_array_type(self,
- m_select):
+ @mock.patch("cloudinit.config.cc_ntp.select_ntp_client")
+ def test_ntp_handler_schema_validation_warns_of_non_array_type(
+ self, m_select
+ ):
"""Ntp schema validation warns of non-array pools or servers types.
Schema validation is not strict, so ntp config is still be rendered.
"""
- invalid_config = {'ntp': {'pools': 123, 'servers': 'non-array'}}
+ invalid_config = {"ntp": {"pools": 123, "servers": "non-array"}}
for distro in cc_ntp.distros:
mycloud = self._get_cloud(distro)
ntpconfig = self._mock_ntp_client_config(distro=distro)
- confpath = ntpconfig['confpath']
+ confpath = ntpconfig["confpath"]
m_select.return_value = ntpconfig
- cc_ntp.handle('cc_ntp', invalid_config, mycloud, None, [])
+ cc_ntp.handle("cc_ntp", invalid_config, mycloud, None, [])
self.assertIn(
"Invalid config:\nntp.pools: 123 is not of type 'array'\n"
"ntp.servers: 'non-array' is not of type 'array'",
- self.logs.getvalue())
- self.assertEqual("servers non-array\npools 123\n",
- util.load_file(confpath))
+ self.logs.getvalue(),
+ )
+ self.assertEqual(
+ "servers non-array\npools 123\n", util.load_file(confpath)
+ )
@skipUnlessJsonSchema()
- @mock.patch('cloudinit.config.cc_ntp.select_ntp_client')
- def test_ntp_handler_schema_validation_warns_invalid_key_present(self,
- m_select):
+ @mock.patch("cloudinit.config.cc_ntp.select_ntp_client")
+ def test_ntp_handler_schema_validation_warns_invalid_key_present(
+ self, m_select
+ ):
"""Ntp schema validation warns of invalid keys present in ntp config.
Schema validation is not strict, so ntp config is still be rendered.
"""
invalid_config = {
- 'ntp': {'invalidkey': 1, 'pools': ['0.mycompany.pool.ntp.org']}}
+ "ntp": {"invalidkey": 1, "pools": ["0.mycompany.pool.ntp.org"]}
+ }
for distro in cc_ntp.distros:
- if distro != 'alpine':
+ if distro != "alpine":
mycloud = self._get_cloud(distro)
ntpconfig = self._mock_ntp_client_config(distro=distro)
- confpath = ntpconfig['confpath']
+ confpath = ntpconfig["confpath"]
m_select.return_value = ntpconfig
- cc_ntp.handle('cc_ntp', invalid_config, mycloud, None, [])
+ cc_ntp.handle("cc_ntp", invalid_config, mycloud, None, [])
self.assertIn(
"Invalid config:\nntp: Additional properties are not "
"allowed ('invalidkey' was unexpected)",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
self.assertEqual(
"servers []\npools ['0.mycompany.pool.ntp.org']\n",
- util.load_file(confpath))
+ util.load_file(confpath),
+ )
@skipUnlessJsonSchema()
- @mock.patch('cloudinit.config.cc_ntp.select_ntp_client')
+ @mock.patch("cloudinit.config.cc_ntp.select_ntp_client")
def test_ntp_handler_schema_validation_warns_of_duplicates(self, m_select):
"""Ntp schema validation warns of duplicates in servers or pools.
Schema validation is not strict, so ntp config is still be rendered.
"""
invalid_config = {
- 'ntp': {'pools': ['0.mypool.org', '0.mypool.org'],
- 'servers': ['10.0.0.1', '10.0.0.1']}}
+ "ntp": {
+ "pools": ["0.mypool.org", "0.mypool.org"],
+ "servers": ["10.0.0.1", "10.0.0.1"],
+ }
+ }
for distro in cc_ntp.distros:
mycloud = self._get_cloud(distro)
ntpconfig = self._mock_ntp_client_config(distro=distro)
- confpath = ntpconfig['confpath']
+ confpath = ntpconfig["confpath"]
m_select.return_value = ntpconfig
- cc_ntp.handle('cc_ntp', invalid_config, mycloud, None, [])
+ cc_ntp.handle("cc_ntp", invalid_config, mycloud, None, [])
self.assertIn(
"Invalid config:\nntp.pools: ['0.mypool.org', '0.mypool.org']"
" has non-unique elements\nntp.servers: "
"['10.0.0.1', '10.0.0.1'] has non-unique elements",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
self.assertEqual(
"servers ['10.0.0.1', '10.0.0.1']\n"
"pools ['0.mypool.org', '0.mypool.org']\n",
- util.load_file(confpath))
+ util.load_file(confpath),
+ )
- @mock.patch('cloudinit.config.cc_ntp.select_ntp_client')
+ @mock.patch("cloudinit.config.cc_ntp.select_ntp_client")
def test_ntp_handler_timesyncd(self, m_select):
"""Test ntp handler configures timesyncd"""
- servers = ['192.168.2.1', '192.168.2.2']
- pools = ['0.mypool.org']
- cfg = {'ntp': {'servers': servers, 'pools': pools}}
- client = 'systemd-timesyncd'
+ servers = ["192.168.2.1", "192.168.2.2"]
+ pools = ["0.mypool.org"]
+ cfg = {"ntp": {"servers": servers, "pools": pools}}
+ client = "systemd-timesyncd"
for distro in cc_ntp.distros:
mycloud = self._get_cloud(distro)
- ntpconfig = self._mock_ntp_client_config(distro=distro,
- client=client)
- confpath = ntpconfig['confpath']
+ ntpconfig = self._mock_ntp_client_config(
+ distro=distro, client=client
+ )
+ confpath = ntpconfig["confpath"]
m_select.return_value = ntpconfig
- cc_ntp.handle('cc_ntp', cfg, mycloud, None, [])
+ cc_ntp.handle("cc_ntp", cfg, mycloud, None, [])
self.assertEqual(
"[Time]\nNTP=192.168.2.1 192.168.2.2 0.mypool.org \n",
- util.load_file(confpath))
+ util.load_file(confpath),
+ )
- @mock.patch('cloudinit.config.cc_ntp.select_ntp_client')
+ @mock.patch("cloudinit.config.cc_ntp.select_ntp_client")
def test_ntp_handler_enabled_false(self, m_select):
- """Test ntp handler does not run if enabled: false """
- cfg = {'ntp': {'enabled': False}}
+ """Test ntp handler does not run if enabled: false"""
+ cfg = {"ntp": {"enabled": False}}
for distro in cc_ntp.distros:
mycloud = self._get_cloud(distro)
- cc_ntp.handle('notimportant', cfg, mycloud, None, None)
+ cc_ntp.handle("notimportant", cfg, mycloud, None, None)
self.assertEqual(0, m_select.call_count)
@mock.patch("cloudinit.distros.subp")
@mock.patch("cloudinit.config.cc_ntp.subp")
- @mock.patch('cloudinit.config.cc_ntp.select_ntp_client')
+ @mock.patch("cloudinit.config.cc_ntp.select_ntp_client")
@mock.patch("cloudinit.distros.Distro.uses_systemd")
def test_ntp_the_whole_package(self, m_sysd, m_select, m_subp, m_dsubp):
- """Test enabled config renders template, and restarts service """
- cfg = {'ntp': {'enabled': True}}
+ """Test enabled config renders template, and restarts service"""
+ cfg = {"ntp": {"enabled": True}}
for distro in cc_ntp.distros:
mycloud = self._get_cloud(distro)
ntpconfig = self._mock_ntp_client_config(distro=distro)
- confpath = ntpconfig['confpath']
- service_name = ntpconfig['service_name']
+ confpath = ntpconfig["confpath"]
+ service_name = ntpconfig["service_name"]
m_select.return_value = ntpconfig
hosts = cc_ntp.generate_server_names(mycloud.distro.name)
uses_systemd = True
- expected_service_call = ['systemctl', 'reload-or-restart',
- service_name]
+ expected_service_call = [
+ "systemctl",
+ "reload-or-restart",
+ service_name,
+ ]
expected_content = "servers []\npools {0}\n".format(hosts)
- if distro == 'alpine':
+ if distro == "alpine":
uses_systemd = False
- expected_service_call = ['rc-service', service_name, 'restart']
+ expected_service_call = ["rc-service", service_name, "restart"]
# _mock_ntp_client_config call above did not specify a client
# value and so it defaults to "ntp" which on Alpine Linux only
# supports servers and not pools.
expected_content = "servers {0}\npools []\n".format(hosts)
m_sysd.return_value = uses_systemd
- with mock.patch('cloudinit.config.cc_ntp.util') as m_util:
+ with mock.patch("cloudinit.config.cc_ntp.util") as m_util:
# allow use of util.mergemanydict
m_util.mergemanydict.side_effect = util.mergemanydict
# default client is present
m_subp.which.return_value = True
# use the config 'enabled' value
m_util.is_false.return_value = util.is_false(
- cfg['ntp']['enabled'])
- cc_ntp.handle('notimportant', cfg, mycloud, None, None)
+ cfg["ntp"]["enabled"]
+ )
+ cc_ntp.handle("notimportant", cfg, mycloud, None, None)
m_dsubp.subp.assert_called_with(
- expected_service_call, capture=True)
+ expected_service_call, capture=True
+ )
self.assertEqual(expected_content, util.load_file(confpath))
- @mock.patch('cloudinit.util.system_info')
+ @mock.patch("cloudinit.util.system_info")
def test_opensuse_picks_chrony(self, m_sysinfo):
"""Test opensuse picks chrony or ntp on certain distro versions"""
# < 15.0 => ntp
- m_sysinfo.return_value = {
- 'dist': ('openSUSE', '13.2', 'Harlequin')
- }
- mycloud = self._get_cloud('opensuse')
+ m_sysinfo.return_value = {"dist": ("openSUSE", "13.2", "Harlequin")}
+ mycloud = self._get_cloud("opensuse")
expected_client = mycloud.distro.preferred_ntp_clients[0]
- self.assertEqual('ntp', expected_client)
+ self.assertEqual("ntp", expected_client)
# >= 15.0 and not openSUSE => chrony
m_sysinfo.return_value = {
- 'dist': ('SLES', '15.0', 'SUSE Linux Enterprise Server 15')
+ "dist": ("SLES", "15.0", "SUSE Linux Enterprise Server 15")
}
- mycloud = self._get_cloud('sles')
+ mycloud = self._get_cloud("sles")
expected_client = mycloud.distro.preferred_ntp_clients[0]
- self.assertEqual('chrony', expected_client)
+ self.assertEqual("chrony", expected_client)
# >= 15.0 and openSUSE and ver != 42 => chrony
m_sysinfo.return_value = {
- 'dist': ('openSUSE Tumbleweed', '20180326', 'timbleweed')
+ "dist": ("openSUSE Tumbleweed", "20180326", "timbleweed")
}
- mycloud = self._get_cloud('opensuse')
+ mycloud = self._get_cloud("opensuse")
expected_client = mycloud.distro.preferred_ntp_clients[0]
- self.assertEqual('chrony', expected_client)
+ self.assertEqual("chrony", expected_client)
- @mock.patch('cloudinit.util.system_info')
+ @mock.patch("cloudinit.util.system_info")
def test_ubuntu_xenial_picks_ntp(self, m_sysinfo):
"""Test Ubuntu picks ntp on xenial release"""
- m_sysinfo.return_value = {'dist': ('Ubuntu', '16.04', 'xenial')}
- mycloud = self._get_cloud('ubuntu')
+ m_sysinfo.return_value = {"dist": ("Ubuntu", "16.04", "xenial")}
+ mycloud = self._get_cloud("ubuntu")
expected_client = mycloud.distro.preferred_ntp_clients[0]
- self.assertEqual('ntp', expected_client)
+ self.assertEqual("ntp", expected_client)
- @mock.patch('cloudinit.config.cc_ntp.subp.which')
+ @mock.patch("cloudinit.config.cc_ntp.subp.which")
def test_snappy_system_picks_timesyncd(self, m_which):
"""Test snappy systems prefer installed clients"""
@@ -552,26 +618,27 @@ class TestNtp(FilesystemMockingTestCase):
self.m_snappy.return_value = True
# ubuntu core systems will have timesyncd installed
- m_which.side_effect = iter([None, '/lib/systemd/systemd-timesyncd',
- None, None, None])
- distro = 'ubuntu'
+ m_which.side_effect = iter(
+ [None, "/lib/systemd/systemd-timesyncd", None, None, None]
+ )
+ distro = "ubuntu"
mycloud = self._get_cloud(distro)
distro_configs = cc_ntp.distro_ntp_client_configs(distro)
- expected_client = 'systemd-timesyncd'
+ expected_client = "systemd-timesyncd"
expected_cfg = distro_configs[expected_client]
expected_calls = []
# we only get to timesyncd
for client in mycloud.distro.preferred_ntp_clients[0:2]:
cfg = distro_configs[client]
- expected_calls.append(mock.call(cfg['check_exe']))
+ expected_calls.append(mock.call(cfg["check_exe"]))
result = cc_ntp.select_ntp_client(None, mycloud.distro)
m_which.assert_has_calls(expected_calls)
self.assertEqual(sorted(expected_cfg), sorted(cfg))
self.assertEqual(sorted(expected_cfg), sorted(result))
- @mock.patch('cloudinit.config.cc_ntp.subp.which')
+ @mock.patch("cloudinit.config.cc_ntp.subp.which")
def test_ntp_distro_searches_all_preferred_clients(self, m_which):
- """Test select_ntp_client search all distro perferred clients """
+ """Test select_ntp_client search all distro perferred clients"""
# nothing is installed
m_which.return_value = None
for distro in cc_ntp.distros:
@@ -582,12 +649,12 @@ class TestNtp(FilesystemMockingTestCase):
expected_calls = []
for client in mycloud.distro.preferred_ntp_clients:
cfg = distro_configs[client]
- expected_calls.append(mock.call(cfg['check_exe']))
+ expected_calls.append(mock.call(cfg["check_exe"]))
cc_ntp.select_ntp_client({}, mycloud.distro)
m_which.assert_has_calls(expected_calls)
self.assertEqual(sorted(expected_cfg), sorted(cfg))
- @mock.patch('cloudinit.config.cc_ntp.subp.which')
+ @mock.patch("cloudinit.config.cc_ntp.subp.which")
def test_user_cfg_ntp_client_auto_uses_distro_clients(self, m_which):
"""Test user_cfg.ntp_client='auto' defaults to distro search"""
# nothing is installed
@@ -600,34 +667,36 @@ class TestNtp(FilesystemMockingTestCase):
expected_calls = []
for client in mycloud.distro.preferred_ntp_clients:
cfg = distro_configs[client]
- expected_calls.append(mock.call(cfg['check_exe']))
- cc_ntp.select_ntp_client('auto', mycloud.distro)
+ expected_calls.append(mock.call(cfg["check_exe"]))
+ cc_ntp.select_ntp_client("auto", mycloud.distro)
m_which.assert_has_calls(expected_calls)
self.assertEqual(sorted(expected_cfg), sorted(cfg))
- @mock.patch('cloudinit.config.cc_ntp.write_ntp_config_template')
- @mock.patch('cloudinit.cloud.Cloud.get_template_filename')
- @mock.patch('cloudinit.config.cc_ntp.subp.which')
- def test_ntp_custom_client_overrides_installed_clients(self, m_which,
- m_tmpfn, m_write):
- """Test user client is installed despite other clients present """
- client = 'ntpdate'
- cfg = {'ntp': {'ntp_client': client}}
+ @mock.patch("cloudinit.config.cc_ntp.write_ntp_config_template")
+ @mock.patch("cloudinit.cloud.Cloud.get_template_filename")
+ @mock.patch("cloudinit.config.cc_ntp.subp.which")
+ def test_ntp_custom_client_overrides_installed_clients(
+ self, m_which, m_tmpfn, m_write
+ ):
+ """Test user client is installed despite other clients present"""
+ client = "ntpdate"
+ cfg = {"ntp": {"ntp_client": client}}
for distro in cc_ntp.distros:
# client is not installed
m_which.side_effect = iter([None])
mycloud = self._get_cloud(distro)
- with mock.patch.object(mycloud.distro,
- 'install_packages') as m_install:
- cc_ntp.handle('notimportant', cfg, mycloud, None, None)
+ with mock.patch.object(
+ mycloud.distro, "install_packages"
+ ) as m_install:
+ cc_ntp.handle("notimportant", cfg, mycloud, None, None)
m_install.assert_called_with([client])
m_which.assert_called_with(client)
- @mock.patch('cloudinit.config.cc_ntp.subp.which')
+ @mock.patch("cloudinit.config.cc_ntp.subp.which")
def test_ntp_system_config_overrides_distro_builtin_clients(self, m_which):
"""Test distro system_config overrides builtin preferred ntp clients"""
- system_client = 'chrony'
- sys_cfg = {'ntp_client': system_client}
+ system_client = "chrony"
+ sys_cfg = {"ntp_client": system_client}
# no clients installed
m_which.return_value = None
for distro in cc_ntp.distros:
@@ -638,12 +707,12 @@ class TestNtp(FilesystemMockingTestCase):
self.assertEqual(sorted(expected_cfg), sorted(result))
m_which.assert_has_calls([])
- @mock.patch('cloudinit.config.cc_ntp.subp.which')
+ @mock.patch("cloudinit.config.cc_ntp.subp.which")
def test_ntp_user_config_overrides_system_cfg(self, m_which):
"""Test user-data overrides system_config ntp_client"""
- system_client = 'chrony'
- sys_cfg = {'ntp_client': system_client}
- user_client = 'systemd-timesyncd'
+ system_client = "chrony"
+ sys_cfg = {"ntp_client": system_client}
+ user_client = "systemd-timesyncd"
# no clients installed
m_which.return_value = None
for distro in cc_ntp.distros:
@@ -654,112 +723,145 @@ class TestNtp(FilesystemMockingTestCase):
self.assertEqual(sorted(expected_cfg), sorted(result))
m_which.assert_has_calls([])
- @mock.patch('cloudinit.config.cc_ntp.install_ntp_client')
+ @mock.patch("cloudinit.config.cc_ntp.install_ntp_client")
def test_ntp_user_provided_config_with_template(self, m_install):
- custom = r'\n#MyCustomTemplate'
+ custom = r"\n#MyCustomTemplate"
user_template = NTP_TEMPLATE + custom
- confpath = os.path.join(self.new_root, 'etc/myntp/myntp.conf')
+ confpath = os.path.join(self.new_root, "etc/myntp/myntp.conf")
cfg = {
- 'ntp': {
- 'pools': ['mypool.org'],
- 'ntp_client': 'myntpd',
- 'config': {
- 'check_exe': 'myntpd',
- 'confpath': confpath,
- 'packages': ['myntp'],
- 'service_name': 'myntp',
- 'template': user_template,
- }
+ "ntp": {
+ "pools": ["mypool.org"],
+ "ntp_client": "myntpd",
+ "config": {
+ "check_exe": "myntpd",
+ "confpath": confpath,
+ "packages": ["myntp"],
+ "service_name": "myntp",
+ "template": user_template,
+ },
}
}
for distro in cc_ntp.distros:
mycloud = self._get_cloud(distro)
- mock_path = 'cloudinit.config.cc_ntp.temp_utils._TMPDIR'
+ mock_path = "cloudinit.config.cc_ntp.temp_utils._TMPDIR"
with mock.patch(mock_path, self.new_root):
- cc_ntp.handle('notimportant', cfg, mycloud, None, None)
+ cc_ntp.handle("notimportant", cfg, mycloud, None, None)
self.assertEqual(
"servers []\npools ['mypool.org']\n%s" % custom,
- util.load_file(confpath))
-
- @mock.patch('cloudinit.config.cc_ntp.supplemental_schema_validation')
- @mock.patch('cloudinit.config.cc_ntp.install_ntp_client')
- @mock.patch('cloudinit.config.cc_ntp.select_ntp_client')
- def test_ntp_user_provided_config_template_only(self, m_select, m_install,
- m_schema):
+ util.load_file(confpath),
+ )
+
+ @mock.patch("cloudinit.config.cc_ntp.supplemental_schema_validation")
+ @mock.patch("cloudinit.config.cc_ntp.install_ntp_client")
+ @mock.patch("cloudinit.config.cc_ntp.select_ntp_client")
+ def test_ntp_user_provided_config_template_only(
+ self, m_select, m_install, m_schema
+ ):
"""Test custom template for default client"""
- custom = r'\n#MyCustomTemplate'
+ custom = r"\n#MyCustomTemplate"
user_template = NTP_TEMPLATE + custom
- client = 'chrony'
+ client = "chrony"
cfg = {
- 'pools': ['mypool.org'],
- 'ntp_client': client,
- 'config': {
- 'template': user_template,
- }
+ "pools": ["mypool.org"],
+ "ntp_client": client,
+ "config": {
+ "template": user_template,
+ },
}
expected_merged_cfg = {
- 'check_exe': 'chronyd',
- 'confpath': '{tmpdir}/client.conf'.format(tmpdir=self.new_root),
- 'template_name': 'client.conf', 'template': user_template,
- 'service_name': 'chrony', 'packages': ['chrony']}
+ "check_exe": "chronyd",
+ "confpath": "{tmpdir}/client.conf".format(tmpdir=self.new_root),
+ "template_name": "client.conf",
+ "template": user_template,
+ "service_name": "chrony",
+ "packages": ["chrony"],
+ }
for distro in cc_ntp.distros:
mycloud = self._get_cloud(distro)
- ntpconfig = self._mock_ntp_client_config(client=client,
- distro=distro)
- confpath = ntpconfig['confpath']
+ ntpconfig = self._mock_ntp_client_config(
+ client=client, distro=distro
+ )
+ confpath = ntpconfig["confpath"]
m_select.return_value = ntpconfig
- mock_path = 'cloudinit.config.cc_ntp.temp_utils._TMPDIR'
+ mock_path = "cloudinit.config.cc_ntp.temp_utils._TMPDIR"
with mock.patch(mock_path, self.new_root):
- cc_ntp.handle('notimportant',
- {'ntp': cfg}, mycloud, None, None)
+ cc_ntp.handle(
+ "notimportant", {"ntp": cfg}, mycloud, None, None
+ )
self.assertEqual(
"servers []\npools ['mypool.org']\n%s" % custom,
- util.load_file(confpath))
+ util.load_file(confpath),
+ )
m_schema.assert_called_with(expected_merged_cfg)
class TestSupplementalSchemaValidation(CiTestCase):
-
def test_error_on_missing_keys(self):
"""ValueError raised reporting any missing required ntp:config keys"""
cfg = {}
- match = (r'Invalid ntp configuration:\\nMissing required ntp:config'
- ' keys: check_exe, confpath, packages, service_name')
+ match = (
+ r"Invalid ntp configuration:\\nMissing required ntp:config"
+ " keys: check_exe, confpath, packages, service_name"
+ )
with self.assertRaisesRegex(ValueError, match):
cc_ntp.supplemental_schema_validation(cfg)
def test_error_requiring_either_template_or_template_name(self):
"""ValueError raised if both template not template_name are None."""
- cfg = {'confpath': 'someconf', 'check_exe': '', 'service_name': '',
- 'template': None, 'template_name': None, 'packages': []}
- match = (r'Invalid ntp configuration:\\nEither ntp:config:template'
- ' or ntp:config:template_name values are required')
+ cfg = {
+ "confpath": "someconf",
+ "check_exe": "",
+ "service_name": "",
+ "template": None,
+ "template_name": None,
+ "packages": [],
+ }
+ match = (
+ r"Invalid ntp configuration:\\nEither ntp:config:template"
+ " or ntp:config:template_name values are required"
+ )
with self.assertRaisesRegex(ValueError, match):
cc_ntp.supplemental_schema_validation(cfg)
def test_error_on_non_list_values(self):
"""ValueError raised when packages is not of type list."""
- cfg = {'confpath': 'someconf', 'check_exe': '', 'service_name': '',
- 'template': 'asdf', 'template_name': None, 'packages': 'NOPE'}
- match = (r'Invalid ntp configuration:\\nExpected a list of required'
- ' package names for ntp:config:packages. Found \\(NOPE\\)')
+ cfg = {
+ "confpath": "someconf",
+ "check_exe": "",
+ "service_name": "",
+ "template": "asdf",
+ "template_name": None,
+ "packages": "NOPE",
+ }
+ match = (
+ r"Invalid ntp configuration:\\nExpected a list of required"
+ " package names for ntp:config:packages. Found \\(NOPE\\)"
+ )
with self.assertRaisesRegex(ValueError, match):
cc_ntp.supplemental_schema_validation(cfg)
def test_error_on_non_string_values(self):
"""ValueError raised for any values expected as string type."""
- cfg = {'confpath': 1, 'check_exe': 2, 'service_name': 3,
- 'template': 4, 'template_name': 5, 'packages': []}
+ cfg = {
+ "confpath": 1,
+ "check_exe": 2,
+ "service_name": 3,
+ "template": 4,
+ "template_name": 5,
+ "packages": [],
+ }
errors = [
- 'Expected a config file path ntp:config:confpath. Found (1)',
- 'Expected a string type for ntp:config:check_exe. Found (2)',
- 'Expected a string type for ntp:config:service_name. Found (3)',
- 'Expected a string type for ntp:config:template. Found (4)',
- 'Expected a string type for ntp:config:template_name. Found (5)']
+ "Expected a config file path ntp:config:confpath. Found (1)",
+ "Expected a string type for ntp:config:check_exe. Found (2)",
+ "Expected a string type for ntp:config:service_name. Found (3)",
+ "Expected a string type for ntp:config:template. Found (4)",
+ "Expected a string type for ntp:config:template_name. Found (5)",
+ ]
with self.assertRaises(ValueError) as context_mgr:
cc_ntp.supplemental_schema_validation(cfg)
error_msg = str(context_mgr.exception)
for error in errors:
self.assertIn(error, error_msg)
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_power_state_change.py b/tests/unittests/config/test_cc_power_state_change.py
index e699f424..47eb0d58 100644
--- a/tests/unittests/config/test_cc_power_state_change.py
+++ b/tests/unittests/config/test_cc_power_state_change.py
@@ -2,11 +2,8 @@
import sys
+from cloudinit import distros, helpers
from cloudinit.config import cc_power_state_change as psc
-
-from cloudinit import distros
-from cloudinit import helpers
-
from tests.unittests import helpers as t_help
from tests.unittests.helpers import mock
@@ -14,9 +11,9 @@ from tests.unittests.helpers import mock
class TestLoadPowerState(t_help.TestCase):
def setUp(self):
super(TestLoadPowerState, self).setUp()
- cls = distros.fetch('ubuntu')
+ cls = distros.fetch("ubuntu")
paths = helpers.Paths({})
- self.dist = cls('ubuntu', {}, paths)
+ self.dist = cls("ubuntu", {}, paths)
def test_no_config(self):
# completely empty config should mean do nothing
@@ -25,85 +22,86 @@ class TestLoadPowerState(t_help.TestCase):
def test_irrelevant_config(self):
# no power_state field in config should return None for cmd
- (cmd, _timeout, _condition) = psc.load_power_state({'foo': 'bar'},
- self.dist)
+ (cmd, _timeout, _condition) = psc.load_power_state(
+ {"foo": "bar"}, self.dist
+ )
self.assertIsNone(cmd)
def test_invalid_mode(self):
- cfg = {'power_state': {'mode': 'gibberish'}}
+ cfg = {"power_state": {"mode": "gibberish"}}
self.assertRaises(TypeError, psc.load_power_state, cfg, self.dist)
- cfg = {'power_state': {'mode': ''}}
+ cfg = {"power_state": {"mode": ""}}
self.assertRaises(TypeError, psc.load_power_state, cfg, self.dist)
def test_empty_mode(self):
- cfg = {'power_state': {'message': 'goodbye'}}
+ cfg = {"power_state": {"message": "goodbye"}}
self.assertRaises(TypeError, psc.load_power_state, cfg, self.dist)
def test_valid_modes(self):
- cfg = {'power_state': {}}
- for mode in ('halt', 'poweroff', 'reboot'):
- cfg['power_state']['mode'] = mode
+ cfg = {"power_state": {}}
+ for mode in ("halt", "poweroff", "reboot"):
+ cfg["power_state"]["mode"] = mode
check_lps_ret(psc.load_power_state(cfg, self.dist), mode=mode)
def test_invalid_delay(self):
- cfg = {'power_state': {'mode': 'poweroff', 'delay': 'goodbye'}}
+ cfg = {"power_state": {"mode": "poweroff", "delay": "goodbye"}}
self.assertRaises(TypeError, psc.load_power_state, cfg, self.dist)
def test_valid_delay(self):
- cfg = {'power_state': {'mode': 'poweroff', 'delay': ''}}
+ cfg = {"power_state": {"mode": "poweroff", "delay": ""}}
for delay in ("now", "+1", "+30"):
- cfg['power_state']['delay'] = delay
+ cfg["power_state"]["delay"] = delay
check_lps_ret(psc.load_power_state(cfg, self.dist))
def test_message_present(self):
- cfg = {'power_state': {'mode': 'poweroff', 'message': 'GOODBYE'}}
+ cfg = {"power_state": {"mode": "poweroff", "message": "GOODBYE"}}
ret = psc.load_power_state(cfg, self.dist)
check_lps_ret(psc.load_power_state(cfg, self.dist))
- self.assertIn(cfg['power_state']['message'], ret[0])
+ self.assertIn(cfg["power_state"]["message"], ret[0])
def test_no_message(self):
# if message is not present, then no argument should be passed for it
- cfg = {'power_state': {'mode': 'poweroff'}}
+ cfg = {"power_state": {"mode": "poweroff"}}
(cmd, _timeout, _condition) = psc.load_power_state(cfg, self.dist)
self.assertNotIn("", cmd)
check_lps_ret(psc.load_power_state(cfg, self.dist))
self.assertTrue(len(cmd) == 3)
def test_condition_null_raises(self):
- cfg = {'power_state': {'mode': 'poweroff', 'condition': None}}
+ cfg = {"power_state": {"mode": "poweroff", "condition": None}}
self.assertRaises(TypeError, psc.load_power_state, cfg, self.dist)
def test_condition_default_is_true(self):
- cfg = {'power_state': {'mode': 'poweroff'}}
+ cfg = {"power_state": {"mode": "poweroff"}}
_cmd, _timeout, cond = psc.load_power_state(cfg, self.dist)
self.assertEqual(cond, True)
def test_freebsd_poweroff_uses_lowercase_p(self):
- cls = distros.fetch('freebsd')
+ cls = distros.fetch("freebsd")
paths = helpers.Paths({})
- freebsd = cls('freebsd', {}, paths)
- cfg = {'power_state': {'mode': 'poweroff'}}
+ freebsd = cls("freebsd", {}, paths)
+ cfg = {"power_state": {"mode": "poweroff"}}
ret = psc.load_power_state(cfg, freebsd)
- self.assertIn('-p', ret[0])
+ self.assertIn("-p", ret[0])
def test_alpine_delay(self):
# alpine takes delay in seconds.
- cls = distros.fetch('alpine')
+ cls = distros.fetch("alpine")
paths = helpers.Paths({})
- alpine = cls('alpine', {}, paths)
- cfg = {'power_state': {'mode': 'poweroff', 'delay': ''}}
- for delay, value in (('now', 0), ("+1", 60), ("+30", 1800)):
- cfg['power_state']['delay'] = delay
+ alpine = cls("alpine", {}, paths)
+ cfg = {"power_state": {"mode": "poweroff", "delay": ""}}
+ for delay, value in (("now", 0), ("+1", 60), ("+30", 1800)):
+ cfg["power_state"]["delay"] = delay
ret = psc.load_power_state(cfg, alpine)
- self.assertEqual('-d', ret[0][1])
+ self.assertEqual("-d", ret[0][1])
self.assertEqual(str(value), ret[0][2])
class TestCheckCondition(t_help.TestCase):
def cmd_with_exit(self, rc):
- return([sys.executable, '-c', 'import sys; sys.exit(%s)' % rc])
+ return [sys.executable, "-c", "import sys; sys.exit(%s)" % rc]
def test_true_is_true(self):
self.assertEqual(psc.check_condition(True), True)
@@ -120,7 +118,8 @@ class TestCheckCondition(t_help.TestCase):
def test_cmd_exit_nonzero_warns(self):
mocklog = mock.Mock()
self.assertEqual(
- psc.check_condition(self.cmd_with_exit(2), mocklog), False)
+ psc.check_condition(self.cmd_with_exit(2), mocklog), False
+ )
self.assertEqual(mocklog.warning.call_count, 1)
@@ -133,14 +132,14 @@ def check_lps_ret(psc_return, mode=None):
timeout = psc_return[1]
condition = psc_return[2]
- if 'shutdown' not in psc_return[0][0]:
+ if "shutdown" not in psc_return[0][0]:
errs.append("string 'shutdown' not in cmd")
if condition is None:
errs.append("condition was not returned")
if mode is not None:
- opt = {'halt': '-H', 'poweroff': '-P', 'reboot': '-r'}[mode]
+ opt = {"halt": "-H", "poweroff": "-P", "reboot": "-r"}[mode]
if opt not in psc_return[0]:
errs.append("opt '%s' not in cmd: %s" % (opt, cmd))
@@ -154,6 +153,7 @@ def check_lps_ret(psc_return, mode=None):
if len(errs):
lines = ["Errors in result: %s" % str(psc_return)] + errs
- raise Exception('\n'.join(lines))
+ raise Exception("\n".join(lines))
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_puppet.py b/tests/unittests/config/test_cc_puppet.py
index 1f67dc4c..2c4481da 100644
--- a/tests/unittests/config/test_cc_puppet.py
+++ b/tests/unittests/config/test_cc_puppet.py
@@ -2,58 +2,71 @@
import logging
import textwrap
-from cloudinit.config import cc_puppet
from cloudinit import util
+from cloudinit.config import cc_puppet
from tests.unittests.helpers import CiTestCase, HttprettyTestCase, mock
-
from tests.unittests.util import get_cloud
LOG = logging.getLogger(__name__)
-@mock.patch('cloudinit.config.cc_puppet.subp.subp')
-@mock.patch('cloudinit.config.cc_puppet.os')
+@mock.patch("cloudinit.config.cc_puppet.subp.subp")
+@mock.patch("cloudinit.config.cc_puppet.os")
class TestAutostartPuppet(CiTestCase):
-
def test_wb_autostart_puppet_updates_puppet_default(self, m_os, m_subp):
"""Update /etc/default/puppet to autostart if it exists."""
def _fake_exists(path):
- return path == '/etc/default/puppet'
+ return path == "/etc/default/puppet"
m_os.path.exists.side_effect = _fake_exists
cc_puppet._autostart_puppet(LOG)
self.assertEqual(
- [mock.call(['sed', '-i', '-e', 's/^START=.*/START=yes/',
- '/etc/default/puppet'], capture=False)],
- m_subp.call_args_list)
+ [
+ mock.call(
+ [
+ "sed",
+ "-i",
+ "-e",
+ "s/^START=.*/START=yes/",
+ "/etc/default/puppet",
+ ],
+ capture=False,
+ )
+ ],
+ m_subp.call_args_list,
+ )
def test_wb_autostart_pupppet_enables_puppet_systemctl(self, m_os, m_subp):
"""If systemctl is present, enable puppet via systemctl."""
def _fake_exists(path):
- return path == '/bin/systemctl'
+ return path == "/bin/systemctl"
m_os.path.exists.side_effect = _fake_exists
cc_puppet._autostart_puppet(LOG)
- expected_calls = [mock.call(
- ['/bin/systemctl', 'enable', 'puppet.service'], capture=False)]
+ expected_calls = [
+ mock.call(
+ ["/bin/systemctl", "enable", "puppet.service"], capture=False
+ )
+ ]
self.assertEqual(expected_calls, m_subp.call_args_list)
def test_wb_autostart_pupppet_enables_puppet_chkconfig(self, m_os, m_subp):
"""If chkconfig is present, enable puppet via checkcfg."""
def _fake_exists(path):
- return path == '/sbin/chkconfig'
+ return path == "/sbin/chkconfig"
m_os.path.exists.side_effect = _fake_exists
cc_puppet._autostart_puppet(LOG)
- expected_calls = [mock.call(
- ['/sbin/chkconfig', 'puppet', 'on'], capture=False)]
+ expected_calls = [
+ mock.call(["/sbin/chkconfig", "puppet", "on"], capture=False)
+ ]
self.assertEqual(expected_calls, m_subp.call_args_list)
-@mock.patch('cloudinit.config.cc_puppet._autostart_puppet')
+@mock.patch("cloudinit.config.cc_puppet._autostart_puppet")
class TestPuppetHandle(CiTestCase):
with_logs = True
@@ -61,145 +74,164 @@ class TestPuppetHandle(CiTestCase):
def setUp(self):
super(TestPuppetHandle, self).setUp()
self.new_root = self.tmp_dir()
- self.conf = self.tmp_path('puppet.conf')
- self.csr_attributes_path = self.tmp_path(
- 'csr_attributes.yaml')
+ self.conf = self.tmp_path("puppet.conf")
+ self.csr_attributes_path = self.tmp_path("csr_attributes.yaml")
self.cloud = get_cloud()
def test_skips_missing_puppet_key_in_cloudconfig(self, m_auto):
"""Cloud-config containing no 'puppet' key is skipped."""
cfg = {}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
- self.assertIn(
- "no 'puppet' configuration found", self.logs.getvalue())
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
+ self.assertIn("no 'puppet' configuration found", self.logs.getvalue())
self.assertEqual(0, m_auto.call_count)
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
def test_puppet_config_starts_puppet_service(self, m_subp, m_auto):
"""Cloud-config 'puppet' configuration starts puppet."""
- cfg = {'puppet': {'install': False}}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
+ cfg = {"puppet": {"install": False}}
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
self.assertEqual(1, m_auto.call_count)
self.assertIn(
- [mock.call(['service', 'puppet', 'start'], capture=False)],
- m_subp.call_args_list)
+ [mock.call(["service", "puppet", "start"], capture=False)],
+ m_subp.call_args_list,
+ )
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
def test_empty_puppet_config_installs_puppet(self, m_subp, m_auto):
"""Cloud-config empty 'puppet' configuration installs latest puppet."""
self.cloud.distro = mock.MagicMock()
- cfg = {'puppet': {}}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
+ cfg = {"puppet": {}}
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
self.assertEqual(
- [mock.call(('puppet', None))],
- self.cloud.distro.install_packages.call_args_list)
+ [mock.call(("puppet", None))],
+ self.cloud.distro.install_packages.call_args_list,
+ )
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
def test_puppet_config_installs_puppet_on_true(self, m_subp, _):
"""Cloud-config with 'puppet' key installs when 'install' is True."""
self.cloud.distro = mock.MagicMock()
- cfg = {'puppet': {'install': True}}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
+ cfg = {"puppet": {"install": True}}
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
self.assertEqual(
- [mock.call(('puppet', None))],
- self.cloud.distro.install_packages.call_args_list)
+ [mock.call(("puppet", None))],
+ self.cloud.distro.install_packages.call_args_list,
+ )
- @mock.patch('cloudinit.config.cc_puppet.install_puppet_aio', autospec=True)
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
+ @mock.patch("cloudinit.config.cc_puppet.install_puppet_aio", autospec=True)
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
def test_puppet_config_installs_puppet_aio(self, m_subp, m_aio, _):
"""Cloud-config with 'puppet' key installs
when 'install_type' is 'aio'."""
self.cloud.distro = mock.MagicMock()
- cfg = {'puppet': {'install': True, 'install_type': 'aio'}}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
- m_aio.assert_called_with(
- cc_puppet.AIO_INSTALL_URL,
- None, None, True)
-
- @mock.patch('cloudinit.config.cc_puppet.install_puppet_aio', autospec=True)
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
- def test_puppet_config_installs_puppet_aio_with_version(self,
- m_subp, m_aio, _):
+ cfg = {"puppet": {"install": True, "install_type": "aio"}}
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
+ m_aio.assert_called_with(cc_puppet.AIO_INSTALL_URL, None, None, True)
+
+ @mock.patch("cloudinit.config.cc_puppet.install_puppet_aio", autospec=True)
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
+ def test_puppet_config_installs_puppet_aio_with_version(
+ self, m_subp, m_aio, _
+ ):
"""Cloud-config with 'puppet' key installs
when 'install_type' is 'aio' and 'version' is specified."""
self.cloud.distro = mock.MagicMock()
- cfg = {'puppet': {'install': True,
- 'version': '6.24.0', 'install_type': 'aio'}}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
+ cfg = {
+ "puppet": {
+ "install": True,
+ "version": "6.24.0",
+ "install_type": "aio",
+ }
+ }
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
m_aio.assert_called_with(
- cc_puppet.AIO_INSTALL_URL,
- '6.24.0', None, True)
-
- @mock.patch('cloudinit.config.cc_puppet.install_puppet_aio', autospec=True)
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
- def test_puppet_config_installs_puppet_aio_with_collection(self,
- m_subp,
- m_aio, _):
+ cc_puppet.AIO_INSTALL_URL, "6.24.0", None, True
+ )
+
+ @mock.patch("cloudinit.config.cc_puppet.install_puppet_aio", autospec=True)
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
+ def test_puppet_config_installs_puppet_aio_with_collection(
+ self, m_subp, m_aio, _
+ ):
"""Cloud-config with 'puppet' key installs
when 'install_type' is 'aio' and 'collection' is specified."""
self.cloud.distro = mock.MagicMock()
- cfg = {'puppet': {'install': True,
- 'collection': 'puppet6', 'install_type': 'aio'}}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
+ cfg = {
+ "puppet": {
+ "install": True,
+ "collection": "puppet6",
+ "install_type": "aio",
+ }
+ }
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
m_aio.assert_called_with(
- cc_puppet.AIO_INSTALL_URL,
- None, 'puppet6', True)
-
- @mock.patch('cloudinit.config.cc_puppet.install_puppet_aio', autospec=True)
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
- def test_puppet_config_installs_puppet_aio_with_custom_url(self,
- m_subp,
- m_aio, _):
+ cc_puppet.AIO_INSTALL_URL, None, "puppet6", True
+ )
+
+ @mock.patch("cloudinit.config.cc_puppet.install_puppet_aio", autospec=True)
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
+ def test_puppet_config_installs_puppet_aio_with_custom_url(
+ self, m_subp, m_aio, _
+ ):
"""Cloud-config with 'puppet' key installs
when 'install_type' is 'aio' and 'aio_install_url' is specified."""
self.cloud.distro = mock.MagicMock()
- cfg = {'puppet':
- {'install': True,
- 'aio_install_url': 'http://test.url/path/to/script.sh',
- 'install_type': 'aio'}}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
+ cfg = {
+ "puppet": {
+ "install": True,
+ "aio_install_url": "http://test.url/path/to/script.sh",
+ "install_type": "aio",
+ }
+ }
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
m_aio.assert_called_with(
- 'http://test.url/path/to/script.sh', None, None, True)
-
- @mock.patch('cloudinit.config.cc_puppet.install_puppet_aio', autospec=True)
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
- def test_puppet_config_installs_puppet_aio_without_cleanup(self,
- m_subp,
- m_aio, _):
+ "http://test.url/path/to/script.sh", None, None, True
+ )
+
+ @mock.patch("cloudinit.config.cc_puppet.install_puppet_aio", autospec=True)
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
+ def test_puppet_config_installs_puppet_aio_without_cleanup(
+ self, m_subp, m_aio, _
+ ):
"""Cloud-config with 'puppet' key installs
when 'install_type' is 'aio' and no cleanup."""
self.cloud.distro = mock.MagicMock()
- cfg = {'puppet': {'install': True,
- 'cleanup': False, 'install_type': 'aio'}}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
- m_aio.assert_called_with(
- cc_puppet.AIO_INSTALL_URL,
- None, None, False)
+ cfg = {
+ "puppet": {
+ "install": True,
+ "cleanup": False,
+ "install_type": "aio",
+ }
+ }
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
+ m_aio.assert_called_with(cc_puppet.AIO_INSTALL_URL, None, None, False)
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
def test_puppet_config_installs_puppet_version(self, m_subp, _):
"""Cloud-config 'puppet' configuration can specify a version."""
self.cloud.distro = mock.MagicMock()
- cfg = {'puppet': {'version': '3.8'}}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
+ cfg = {"puppet": {"version": "3.8"}}
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
self.assertEqual(
- [mock.call(('puppet', '3.8'))],
- self.cloud.distro.install_packages.call_args_list)
-
- @mock.patch('cloudinit.config.cc_puppet.get_config_value')
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
- def test_puppet_config_updates_puppet_conf(self,
- m_subp, m_default, m_auto):
+ [mock.call(("puppet", "3.8"))],
+ self.cloud.distro.install_packages.call_args_list,
+ )
+
+ @mock.patch("cloudinit.config.cc_puppet.get_config_value")
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
+ def test_puppet_config_updates_puppet_conf(
+ self, m_subp, m_default, m_auto
+ ):
"""When 'conf' is provided update values in PUPPET_CONF_PATH."""
def _fake_get_config_value(puppet_bin, setting):
@@ -208,22 +240,24 @@ class TestPuppetHandle(CiTestCase):
m_default.side_effect = _fake_get_config_value
cfg = {
- 'puppet': {
- 'conf': {'agent': {'server': 'puppetserver.example.org'}}}}
- util.write_file(
- self.conf, '[agent]\nserver = origpuppet\nother = 3')
+ "puppet": {
+ "conf": {"agent": {"server": "puppetserver.example.org"}}
+ }
+ }
+ util.write_file(self.conf, "[agent]\nserver = origpuppet\nother = 3")
self.cloud.distro = mock.MagicMock()
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
content = util.load_file(self.conf)
- expected = '[agent]\nserver = puppetserver.example.org\nother = 3\n\n'
+ expected = "[agent]\nserver = puppetserver.example.org\nother = 3\n\n"
self.assertEqual(expected, content)
- @mock.patch('cloudinit.config.cc_puppet.get_config_value')
- @mock.patch('cloudinit.config.cc_puppet.subp.subp')
- def test_puppet_writes_csr_attributes_file(self,
- m_subp, m_default, m_auto):
+ @mock.patch("cloudinit.config.cc_puppet.get_config_value")
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp")
+ def test_puppet_writes_csr_attributes_file(
+ self, m_subp, m_default, m_auto
+ ):
"""When csr_attributes is provided
- creates file in PUPPET_CSR_ATTRIBUTES_PATH."""
+ creates file in PUPPET_CSR_ATTRIBUTES_PATH."""
def _fake_get_config_value(puppet_bin, setting):
return self.csr_attributes_path
@@ -232,105 +266,131 @@ class TestPuppetHandle(CiTestCase):
self.cloud.distro = mock.MagicMock()
cfg = {
- 'puppet': {
- 'csr_attributes': {
- 'custom_attributes': {
- '1.2.840.113549.1.9.7':
- '342thbjkt82094y0uthhor289jnqthpc2290'
+ "puppet": {
+ "csr_attributes": {
+ "custom_attributes": {
+ "1.2.840.113549.1.9.7": (
+ "342thbjkt82094y0uthhor289jnqthpc2290"
+ )
+ },
+ "extension_requests": {
+ "pp_uuid": "ED803750-E3C7-44F5-BB08-41A04433FE2E",
+ "pp_image_name": "my_ami_image",
+ "pp_preshared_key": (
+ "342thbjkt82094y0uthhor289jnqthpc2290"
+ ),
},
- 'extension_requests': {
- 'pp_uuid': 'ED803750-E3C7-44F5-BB08-41A04433FE2E',
- 'pp_image_name': 'my_ami_image',
- 'pp_preshared_key':
- '342thbjkt82094y0uthhor289jnqthpc2290'
- }
}
}
}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
content = util.load_file(self.csr_attributes_path)
- expected = textwrap.dedent("""\
+ expected = textwrap.dedent(
+ """\
custom_attributes:
1.2.840.113549.1.9.7: 342thbjkt82094y0uthhor289jnqthpc2290
extension_requests:
pp_image_name: my_ami_image
pp_preshared_key: 342thbjkt82094y0uthhor289jnqthpc2290
pp_uuid: ED803750-E3C7-44F5-BB08-41A04433FE2E
- """)
+ """
+ )
self.assertEqual(expected, content)
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
def test_puppet_runs_puppet_if_requested(self, m_subp, m_auto):
"""Run puppet with default args if 'exec' is set to True."""
- cfg = {'puppet': {'exec': True}}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
+ cfg = {"puppet": {"exec": True}}
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
self.assertEqual(1, m_auto.call_count)
self.assertIn(
- [mock.call(['puppet', 'agent', '--test'], capture=False)],
- m_subp.call_args_list)
+ [mock.call(["puppet", "agent", "--test"], capture=False)],
+ m_subp.call_args_list,
+ )
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
def test_puppet_starts_puppetd(self, m_subp, m_auto):
"""Run puppet with default args if 'exec' is set to True."""
- cfg = {'puppet': {}}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
+ cfg = {"puppet": {}}
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
self.assertEqual(1, m_auto.call_count)
self.assertIn(
- [mock.call(['service', 'puppet', 'start'], capture=False)],
- m_subp.call_args_list)
+ [mock.call(["service", "puppet", "start"], capture=False)],
+ m_subp.call_args_list,
+ )
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
def test_puppet_skips_puppetd(self, m_subp, m_auto):
"""Run puppet with default args if 'exec' is set to True."""
- cfg = {'puppet': {'start_service': False}}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
+ cfg = {"puppet": {"start_service": False}}
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
self.assertEqual(0, m_auto.call_count)
self.assertNotIn(
- [mock.call(['service', 'puppet', 'start'], capture=False)],
- m_subp.call_args_list)
-
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
- def test_puppet_runs_puppet_with_args_list_if_requested(self,
- m_subp, m_auto):
+ [mock.call(["service", "puppet", "start"], capture=False)],
+ m_subp.call_args_list,
+ )
+
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
+ def test_puppet_runs_puppet_with_args_list_if_requested(
+ self, m_subp, m_auto
+ ):
"""Run puppet with 'exec_args' list if 'exec' is set to True."""
- cfg = {'puppet': {'exec': True, 'exec_args': [
- '--onetime', '--detailed-exitcodes']}}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
+ cfg = {
+ "puppet": {
+ "exec": True,
+ "exec_args": ["--onetime", "--detailed-exitcodes"],
+ }
+ }
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
self.assertEqual(1, m_auto.call_count)
self.assertIn(
- [mock.call(
- ['puppet', 'agent', '--onetime', '--detailed-exitcodes'],
- capture=False)],
- m_subp.call_args_list)
-
- @mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=("", ""))
- def test_puppet_runs_puppet_with_args_string_if_requested(self,
- m_subp, m_auto):
+ [
+ mock.call(
+ ["puppet", "agent", "--onetime", "--detailed-exitcodes"],
+ capture=False,
+ )
+ ],
+ m_subp.call_args_list,
+ )
+
+ @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", ""))
+ def test_puppet_runs_puppet_with_args_string_if_requested(
+ self, m_subp, m_auto
+ ):
"""Run puppet with 'exec_args' string if 'exec' is set to True."""
- cfg = {'puppet': {'exec': True,
- 'exec_args': '--onetime --detailed-exitcodes'}}
- cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None)
+ cfg = {
+ "puppet": {
+ "exec": True,
+ "exec_args": "--onetime --detailed-exitcodes",
+ }
+ }
+ cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None)
self.assertEqual(1, m_auto.call_count)
self.assertIn(
- [mock.call(
- ['puppet', 'agent', '--onetime', '--detailed-exitcodes'],
- capture=False)],
- m_subp.call_args_list)
+ [
+ mock.call(
+ ["puppet", "agent", "--onetime", "--detailed-exitcodes"],
+ capture=False,
+ )
+ ],
+ m_subp.call_args_list,
+ )
URL_MOCK = mock.Mock()
URL_MOCK.contents = b'#!/bin/bash\necho "Hi Mom"'
-@mock.patch('cloudinit.config.cc_puppet.subp.subp', return_value=(None, None))
+@mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=(None, None))
@mock.patch(
- 'cloudinit.config.cc_puppet.url_helper.readurl',
- return_value=URL_MOCK, autospec=True,
+ "cloudinit.config.cc_puppet.url_helper.readurl",
+ return_value=URL_MOCK,
+ autospec=True,
)
class TestInstallPuppetAio(HttprettyTestCase):
def test_install_with_default_arguments(self, m_readurl, m_subp):
@@ -338,43 +398,53 @@ class TestInstallPuppetAio(HttprettyTestCase):
cc_puppet.install_puppet_aio()
self.assertEqual(
- [mock.call([mock.ANY, '--cleanup'], capture=False)],
- m_subp.call_args_list)
+ [mock.call([mock.ANY, "--cleanup"], capture=False)],
+ m_subp.call_args_list,
+ )
def test_install_with_custom_url(self, m_readurl, m_subp):
"""Install AIO from custom URL"""
- cc_puppet.install_puppet_aio('http://custom.url/path/to/script.sh')
+ cc_puppet.install_puppet_aio("http://custom.url/path/to/script.sh")
m_readurl.assert_called_with(
- url='http://custom.url/path/to/script.sh',
- retries=5)
+ url="http://custom.url/path/to/script.sh", retries=5
+ )
self.assertEqual(
- [mock.call([mock.ANY, '--cleanup'], capture=False)],
- m_subp.call_args_list)
+ [mock.call([mock.ANY, "--cleanup"], capture=False)],
+ m_subp.call_args_list,
+ )
def test_install_with_version(self, m_readurl, m_subp):
"""Install AIO with specific version"""
- cc_puppet.install_puppet_aio(cc_puppet.AIO_INSTALL_URL, '7.6.0')
+ cc_puppet.install_puppet_aio(cc_puppet.AIO_INSTALL_URL, "7.6.0")
self.assertEqual(
- [mock.call([mock.ANY, '-v', '7.6.0', '--cleanup'], capture=False)],
- m_subp.call_args_list)
+ [mock.call([mock.ANY, "-v", "7.6.0", "--cleanup"], capture=False)],
+ m_subp.call_args_list,
+ )
def test_install_with_collection(self, m_readurl, m_subp):
"""Install AIO with specific collection"""
cc_puppet.install_puppet_aio(
- cc_puppet.AIO_INSTALL_URL, None, 'puppet6-nightly')
+ cc_puppet.AIO_INSTALL_URL, None, "puppet6-nightly"
+ )
self.assertEqual(
- [mock.call([mock.ANY, '-c', 'puppet6-nightly', '--cleanup'],
- capture=False)],
- m_subp.call_args_list)
+ [
+ mock.call(
+ [mock.ANY, "-c", "puppet6-nightly", "--cleanup"],
+ capture=False,
+ )
+ ],
+ m_subp.call_args_list,
+ )
def test_install_with_no_cleanup(self, m_readurl, m_subp):
"""Install AIO with no cleanup"""
cc_puppet.install_puppet_aio(
- cc_puppet.AIO_INSTALL_URL, None, None, False)
+ cc_puppet.AIO_INSTALL_URL, None, None, False
+ )
self.assertEqual(
- [mock.call([mock.ANY], capture=False)],
- m_subp.call_args_list)
+ [mock.call([mock.ANY], capture=False)], m_subp.call_args_list
+ )
diff --git a/tests/unittests/config/test_cc_refresh_rmc_and_interface.py b/tests/unittests/config/test_cc_refresh_rmc_and_interface.py
index 522de23d..e038f814 100644
--- a/tests/unittests/config/test_cc_refresh_rmc_and_interface.py
+++ b/tests/unittests/config/test_cc_refresh_rmc_and_interface.py
@@ -1,51 +1,83 @@
-from cloudinit.config import cc_refresh_rmc_and_interface as ccrmci
+import logging
+from textwrap import dedent
from cloudinit import util
-
+from cloudinit.config import cc_refresh_rmc_and_interface as ccrmci
from tests.unittests import helpers as t_help
from tests.unittests.helpers import mock
-from textwrap import dedent
-import logging
-
LOG = logging.getLogger(__name__)
MPATH = "cloudinit.config.cc_refresh_rmc_and_interface"
NET_INFO = {
- 'lo': {'ipv4': [{'ip': '127.0.0.1',
- 'bcast': '', 'mask': '255.0.0.0',
- 'scope': 'host'}],
- 'ipv6': [{'ip': '::1/128',
- 'scope6': 'host'}], 'hwaddr': '',
- 'up': 'True'},
- 'env2': {'ipv4': [{'ip': '8.0.0.19',
- 'bcast': '8.0.0.255', 'mask': '255.255.255.0',
- 'scope': 'global'}],
- 'ipv6': [{'ip': 'fe80::f896:c2ff:fe81:8220/64',
- 'scope6': 'link'}], 'hwaddr': 'fa:96:c2:81:82:20',
- 'up': 'True'},
- 'env3': {'ipv4': [{'ip': '90.0.0.14',
- 'bcast': '90.0.0.255', 'mask': '255.255.255.0',
- 'scope': 'global'}],
- 'ipv6': [{'ip': 'fe80::f896:c2ff:fe81:8221/64',
- 'scope6': 'link'}], 'hwaddr': 'fa:96:c2:81:82:21',
- 'up': 'True'},
- 'env4': {'ipv4': [{'ip': '9.114.23.7',
- 'bcast': '9.114.23.255', 'mask': '255.255.255.0',
- 'scope': 'global'}],
- 'ipv6': [{'ip': 'fe80::f896:c2ff:fe81:8222/64',
- 'scope6': 'link'}], 'hwaddr': 'fa:96:c2:81:82:22',
- 'up': 'True'},
- 'env5': {'ipv4': [],
- 'ipv6': [{'ip': 'fe80::9c26:c3ff:fea4:62c8/64',
- 'scope6': 'link'}], 'hwaddr': '42:20:86:df:fa:4c',
- 'up': 'True'}}
+ "lo": {
+ "ipv4": [
+ {
+ "ip": "127.0.0.1",
+ "bcast": "",
+ "mask": "255.0.0.0",
+ "scope": "host",
+ }
+ ],
+ "ipv6": [{"ip": "::1/128", "scope6": "host"}],
+ "hwaddr": "",
+ "up": "True",
+ },
+ "env2": {
+ "ipv4": [
+ {
+ "ip": "8.0.0.19",
+ "bcast": "8.0.0.255",
+ "mask": "255.255.255.0",
+ "scope": "global",
+ }
+ ],
+ "ipv6": [{"ip": "fe80::f896:c2ff:fe81:8220/64", "scope6": "link"}],
+ "hwaddr": "fa:96:c2:81:82:20",
+ "up": "True",
+ },
+ "env3": {
+ "ipv4": [
+ {
+ "ip": "90.0.0.14",
+ "bcast": "90.0.0.255",
+ "mask": "255.255.255.0",
+ "scope": "global",
+ }
+ ],
+ "ipv6": [{"ip": "fe80::f896:c2ff:fe81:8221/64", "scope6": "link"}],
+ "hwaddr": "fa:96:c2:81:82:21",
+ "up": "True",
+ },
+ "env4": {
+ "ipv4": [
+ {
+ "ip": "9.114.23.7",
+ "bcast": "9.114.23.255",
+ "mask": "255.255.255.0",
+ "scope": "global",
+ }
+ ],
+ "ipv6": [{"ip": "fe80::f896:c2ff:fe81:8222/64", "scope6": "link"}],
+ "hwaddr": "fa:96:c2:81:82:22",
+ "up": "True",
+ },
+ "env5": {
+ "ipv4": [],
+ "ipv6": [{"ip": "fe80::9c26:c3ff:fea4:62c8/64", "scope6": "link"}],
+ "hwaddr": "42:20:86:df:fa:4c",
+ "up": "True",
+ },
+}
class TestRsctNodeFile(t_help.CiTestCase):
def test_disable_ipv6_interface(self):
"""test parsing of iface files."""
fname = self.tmp_path("iface-eth5")
- util.write_file(fname, dedent("""\
+ util.write_file(
+ fname,
+ dedent(
+ """\
BOOTPROTO=static
DEVICE=eth5
HWADDR=42:20:86:df:fa:4c
@@ -57,10 +89,14 @@ class TestRsctNodeFile(t_help.CiTestCase):
STARTMODE=auto
TYPE=Ethernet
USERCTL=no
- """))
+ """
+ ),
+ )
ccrmci.disable_ipv6(fname)
- self.assertEqual(dedent("""\
+ self.assertEqual(
+ dedent(
+ """\
BOOTPROTO=static
DEVICE=eth5
HWADDR=42:20:86:df:fa:4c
@@ -69,41 +105,53 @@ class TestRsctNodeFile(t_help.CiTestCase):
TYPE=Ethernet
USERCTL=no
NM_CONTROLLED=no
- """), util.load_file(fname))
+ """
+ ),
+ util.load_file(fname),
+ )
- @mock.patch(MPATH + '.refresh_rmc')
- @mock.patch(MPATH + '.restart_network_manager')
- @mock.patch(MPATH + '.disable_ipv6')
- @mock.patch(MPATH + '.refresh_ipv6')
- @mock.patch(MPATH + '.netinfo.netdev_info')
- @mock.patch(MPATH + '.subp.which')
- def test_handle(self, m_refresh_rmc,
- m_netdev_info, m_refresh_ipv6, m_disable_ipv6,
- m_restart_nm, m_which):
+ @mock.patch(MPATH + ".refresh_rmc")
+ @mock.patch(MPATH + ".restart_network_manager")
+ @mock.patch(MPATH + ".disable_ipv6")
+ @mock.patch(MPATH + ".refresh_ipv6")
+ @mock.patch(MPATH + ".netinfo.netdev_info")
+ @mock.patch(MPATH + ".subp.which")
+ def test_handle(
+ self,
+ m_refresh_rmc,
+ m_netdev_info,
+ m_refresh_ipv6,
+ m_disable_ipv6,
+ m_restart_nm,
+ m_which,
+ ):
"""Basic test of handle."""
m_netdev_info.return_value = NET_INFO
- m_which.return_value = '/opt/rsct/bin/rmcctrl'
- ccrmci.handle(
- "refresh_rmc_and_interface", None, None, None, None)
+ m_which.return_value = "/opt/rsct/bin/rmcctrl"
+ ccrmci.handle("refresh_rmc_and_interface", None, None, None, None)
self.assertEqual(1, m_netdev_info.call_count)
- m_refresh_ipv6.assert_called_with('env5')
+ m_refresh_ipv6.assert_called_with("env5")
m_disable_ipv6.assert_called_with(
- '/etc/sysconfig/network-scripts/ifcfg-env5')
+ "/etc/sysconfig/network-scripts/ifcfg-env5"
+ )
self.assertEqual(1, m_restart_nm.call_count)
self.assertEqual(1, m_refresh_rmc.call_count)
- @mock.patch(MPATH + '.netinfo.netdev_info')
+ @mock.patch(MPATH + ".netinfo.netdev_info")
def test_find_ipv6(self, m_netdev_info):
"""find_ipv6_ifaces parses netdev_info returning those with ipv6"""
m_netdev_info.return_value = NET_INFO
found = ccrmci.find_ipv6_ifaces()
- self.assertEqual(['env5'], found)
+ self.assertEqual(["env5"], found)
- @mock.patch(MPATH + '.subp.subp')
+ @mock.patch(MPATH + ".subp.subp")
def test_refresh_ipv6(self, m_subp):
"""refresh_ipv6 should ip down and up the interface."""
iface = "myeth0"
ccrmci.refresh_ipv6(iface)
- m_subp.assert_has_calls([
- mock.call(['ip', 'link', 'set', iface, 'down']),
- mock.call(['ip', 'link', 'set', iface, 'up'])])
+ m_subp.assert_has_calls(
+ [
+ mock.call(["ip", "link", "set", iface, "down"]),
+ mock.call(["ip", "link", "set", iface, "up"]),
+ ]
+ )
diff --git a/tests/unittests/config/test_cc_resizefs.py b/tests/unittests/config/test_cc_resizefs.py
index 1f9e24da..228f1e45 100644
--- a/tests/unittests/config/test_cc_resizefs.py
+++ b/tests/unittests/config/test_cc_resizefs.py
@@ -1,16 +1,26 @@
# This file is part of cloud-init. See LICENSE file for license information.
-from cloudinit.config.cc_resizefs import (
- can_skip_resize, handle, maybe_get_writable_device_path, _resize_btrfs,
- _resize_zfs, _resize_xfs, _resize_ext, _resize_ufs)
-
-from collections import namedtuple
import logging
+from collections import namedtuple
+from cloudinit.config.cc_resizefs import (
+ _resize_btrfs,
+ _resize_ext,
+ _resize_ufs,
+ _resize_xfs,
+ _resize_zfs,
+ can_skip_resize,
+ handle,
+ maybe_get_writable_device_path,
+)
from cloudinit.subp import ProcessExecutionError
from tests.unittests.helpers import (
- CiTestCase, mock, skipUnlessJsonSchema, util, wrap_and_call)
-
+ CiTestCase,
+ mock,
+ skipUnlessJsonSchema,
+ util,
+ wrap_and_call,
+)
LOG = logging.getLogger(__name__)
@@ -22,32 +32,34 @@ class TestResizefs(CiTestCase):
super(TestResizefs, self).setUp()
self.name = "resizefs"
- @mock.patch('cloudinit.subp.subp')
+ @mock.patch("cloudinit.subp.subp")
def test_skip_ufs_resize(self, m_subp):
fs_type = "ufs"
resize_what = "/"
devpth = "/dev/da0p2"
- err = ("growfs: requested size 2.0GB is not larger than the "
- "current filesystem size 2.0GB\n")
+ err = (
+ "growfs: requested size 2.0GB is not larger than the "
+ "current filesystem size 2.0GB\n"
+ )
exception = ProcessExecutionError(stderr=err, exit_code=1)
m_subp.side_effect = exception
res = can_skip_resize(fs_type, resize_what, devpth)
self.assertTrue(res)
- @mock.patch('cloudinit.subp.subp')
+ @mock.patch("cloudinit.subp.subp")
def test_cannot_skip_ufs_resize(self, m_subp):
fs_type = "ufs"
resize_what = "/"
devpth = "/dev/da0p2"
m_subp.return_value = (
- ("stdout: super-block backups (for fsck_ffs -b #) at:\n\n"),
- ("growfs: no room to allocate last cylinder group; "
- "leaving 364KB unused\n")
+ "stdout: super-block backups (for fsck_ffs -b #) at:\n\n",
+ "growfs: no room to allocate last cylinder group; "
+ "leaving 364KB unused\n",
)
res = can_skip_resize(fs_type, resize_what, devpth)
self.assertFalse(res)
- @mock.patch('cloudinit.subp.subp')
+ @mock.patch("cloudinit.subp.subp")
def test_cannot_skip_ufs_growfs_exception(self, m_subp):
fs_type = "ufs"
resize_what = "/"
@@ -59,15 +71,16 @@ class TestResizefs(CiTestCase):
can_skip_resize(fs_type, resize_what, devpth)
def test_can_skip_resize_ext(self):
- self.assertFalse(can_skip_resize('ext', '/', '/dev/sda1'))
+ self.assertFalse(can_skip_resize("ext", "/", "/dev/sda1"))
def test_handle_noops_on_disabled(self):
"""The handle function logs when the configuration disables resize."""
- cfg = {'resize_rootfs': False}
- handle('cc_resizefs', cfg, _cloud=None, log=LOG, args=[])
+ cfg = {"resize_rootfs": False}
+ handle("cc_resizefs", cfg, _cloud=None, log=LOG, args=[])
self.assertIn(
- 'DEBUG: Skipping module named cc_resizefs, resizing disabled\n',
- self.logs.getvalue())
+ "DEBUG: Skipping module named cc_resizefs, resizing disabled\n",
+ self.logs.getvalue(),
+ )
@skipUnlessJsonSchema()
def test_handle_schema_validation_logs_invalid_resize_rootfs_value(self):
@@ -75,164 +88,189 @@ class TestResizefs(CiTestCase):
Invalid values for resize_rootfs result in disabling the module.
"""
- cfg = {'resize_rootfs': 'junk'}
- handle('cc_resizefs', cfg, _cloud=None, log=LOG, args=[])
+ cfg = {"resize_rootfs": "junk"}
+ handle("cc_resizefs", cfg, _cloud=None, log=LOG, args=[])
logs = self.logs.getvalue()
self.assertIn(
"WARNING: Invalid config:\nresize_rootfs: 'junk' is not one of"
" [True, False, 'noblock']",
- logs)
+ logs,
+ )
self.assertIn(
- 'DEBUG: Skipping module named cc_resizefs, resizing disabled\n',
- logs)
+ "DEBUG: Skipping module named cc_resizefs, resizing disabled\n",
+ logs,
+ )
- @mock.patch('cloudinit.config.cc_resizefs.util.get_mount_info')
+ @mock.patch("cloudinit.config.cc_resizefs.util.get_mount_info")
def test_handle_warns_on_unknown_mount_info(self, m_get_mount_info):
"""handle warns when get_mount_info sees unknown filesystem for /."""
m_get_mount_info.return_value = None
- cfg = {'resize_rootfs': True}
- handle('cc_resizefs', cfg, _cloud=None, log=LOG, args=[])
+ cfg = {"resize_rootfs": True}
+ handle("cc_resizefs", cfg, _cloud=None, log=LOG, args=[])
logs = self.logs.getvalue()
self.assertNotIn("WARNING: Invalid config:\nresize_rootfs:", logs)
self.assertIn(
- 'WARNING: Could not determine filesystem type of /\n',
- logs)
+ "WARNING: Could not determine filesystem type of /\n", logs
+ )
self.assertEqual(
- [mock.call('/', LOG)],
- m_get_mount_info.call_args_list)
+ [mock.call("/", LOG)], m_get_mount_info.call_args_list
+ )
def test_handle_warns_on_undiscoverable_root_path_in_commandline(self):
"""handle noops when the root path is not found on the commandline."""
- cfg = {'resize_rootfs': True}
- exists_mock_path = 'cloudinit.config.cc_resizefs.os.path.exists'
+ cfg = {"resize_rootfs": True}
+ exists_mock_path = "cloudinit.config.cc_resizefs.os.path.exists"
def fake_mount_info(path, log):
- self.assertEqual('/', path)
+ self.assertEqual("/", path)
self.assertEqual(LOG, log)
- return ('/dev/root', 'ext4', '/')
+ return ("/dev/root", "ext4", "/")
with mock.patch(exists_mock_path) as m_exists:
m_exists.return_value = False
wrap_and_call(
- 'cloudinit.config.cc_resizefs.util',
- {'is_container': {'return_value': False},
- 'get_mount_info': {'side_effect': fake_mount_info},
- 'get_cmdline': {'return_value': 'BOOT_IMAGE=/vmlinuz.efi'}},
- handle, 'cc_resizefs', cfg, _cloud=None, log=LOG,
- args=[])
+ "cloudinit.config.cc_resizefs.util",
+ {
+ "is_container": {"return_value": False},
+ "get_mount_info": {"side_effect": fake_mount_info},
+ "get_cmdline": {"return_value": "BOOT_IMAGE=/vmlinuz.efi"},
+ },
+ handle,
+ "cc_resizefs",
+ cfg,
+ _cloud=None,
+ log=LOG,
+ args=[],
+ )
logs = self.logs.getvalue()
self.assertIn("WARNING: Unable to find device '/dev/root'", logs)
def test_resize_zfs_cmd_return(self):
- zpool = 'zroot'
- devpth = 'gpt/system'
- self.assertEqual(('zpool', 'online', '-e', zpool, devpth),
- _resize_zfs(zpool, devpth))
+ zpool = "zroot"
+ devpth = "gpt/system"
+ self.assertEqual(
+ ("zpool", "online", "-e", zpool, devpth),
+ _resize_zfs(zpool, devpth),
+ )
def test_resize_xfs_cmd_return(self):
- mount_point = '/mnt/test'
- devpth = '/dev/sda1'
- self.assertEqual(('xfs_growfs', mount_point),
- _resize_xfs(mount_point, devpth))
+ mount_point = "/mnt/test"
+ devpth = "/dev/sda1"
+ self.assertEqual(
+ ("xfs_growfs", mount_point), _resize_xfs(mount_point, devpth)
+ )
def test_resize_ext_cmd_return(self):
- mount_point = '/'
- devpth = '/dev/sdb1'
- self.assertEqual(('resize2fs', devpth),
- _resize_ext(mount_point, devpth))
+ mount_point = "/"
+ devpth = "/dev/sdb1"
+ self.assertEqual(
+ ("resize2fs", devpth), _resize_ext(mount_point, devpth)
+ )
def test_resize_ufs_cmd_return(self):
- mount_point = '/'
- devpth = '/dev/sda2'
- self.assertEqual(('growfs', '-y', mount_point),
- _resize_ufs(mount_point, devpth))
-
- @mock.patch('cloudinit.util.is_container', return_value=False)
- @mock.patch('cloudinit.util.parse_mount')
- @mock.patch('cloudinit.util.get_device_info_from_zpool')
- @mock.patch('cloudinit.util.get_mount_info')
- def test_handle_zfs_root(self, mount_info, zpool_info, parse_mount,
- is_container):
- devpth = 'vmzroot/ROOT/freebsd'
- disk = 'gpt/system'
- fs_type = 'zfs'
- mount_point = '/'
+ mount_point = "/"
+ devpth = "/dev/sda2"
+ self.assertEqual(
+ ("growfs", "-y", mount_point), _resize_ufs(mount_point, devpth)
+ )
+
+ @mock.patch("cloudinit.util.is_container", return_value=False)
+ @mock.patch("cloudinit.util.parse_mount")
+ @mock.patch("cloudinit.util.get_device_info_from_zpool")
+ @mock.patch("cloudinit.util.get_mount_info")
+ def test_handle_zfs_root(
+ self, mount_info, zpool_info, parse_mount, is_container
+ ):
+ devpth = "vmzroot/ROOT/freebsd"
+ disk = "gpt/system"
+ fs_type = "zfs"
+ mount_point = "/"
mount_info.return_value = (devpth, fs_type, mount_point)
zpool_info.return_value = disk
parse_mount.return_value = (devpth, fs_type, mount_point)
- cfg = {'resize_rootfs': True}
+ cfg = {"resize_rootfs": True}
- with mock.patch('cloudinit.config.cc_resizefs.do_resize') as dresize:
- handle('cc_resizefs', cfg, _cloud=None, log=LOG, args=[])
+ with mock.patch("cloudinit.config.cc_resizefs.do_resize") as dresize:
+ handle("cc_resizefs", cfg, _cloud=None, log=LOG, args=[])
ret = dresize.call_args[0][0]
- self.assertEqual(('zpool', 'online', '-e', 'vmzroot', disk), ret)
+ self.assertEqual(("zpool", "online", "-e", "vmzroot", disk), ret)
- @mock.patch('cloudinit.util.is_container', return_value=False)
- @mock.patch('cloudinit.util.get_mount_info')
- @mock.patch('cloudinit.util.get_device_info_from_zpool')
- @mock.patch('cloudinit.util.parse_mount')
- def test_handle_modern_zfsroot(self, mount_info, zpool_info, parse_mount,
- is_container):
- devpth = 'zroot/ROOT/default'
- disk = 'da0p3'
- fs_type = 'zfs'
- mount_point = '/'
+ @mock.patch("cloudinit.util.is_container", return_value=False)
+ @mock.patch("cloudinit.util.get_mount_info")
+ @mock.patch("cloudinit.util.get_device_info_from_zpool")
+ @mock.patch("cloudinit.util.parse_mount")
+ def test_handle_modern_zfsroot(
+ self, mount_info, zpool_info, parse_mount, is_container
+ ):
+ devpth = "zroot/ROOT/default"
+ disk = "da0p3"
+ fs_type = "zfs"
+ mount_point = "/"
mount_info.return_value = (devpth, fs_type, mount_point)
zpool_info.return_value = disk
parse_mount.return_value = (devpth, fs_type, mount_point)
- cfg = {'resize_rootfs': True}
+ cfg = {"resize_rootfs": True}
def fake_stat(devpath):
if devpath == disk:
raise OSError("not here")
FakeStat = namedtuple(
- 'FakeStat', ['st_mode', 'st_size', 'st_mtime']) # minimal stat
+ "FakeStat", ["st_mode", "st_size", "st_mtime"]
+ ) # minimal stat
return FakeStat(25008, 0, 1) # fake char block device
- with mock.patch('cloudinit.config.cc_resizefs.do_resize') as dresize:
- with mock.patch('cloudinit.config.cc_resizefs.os.stat') as m_stat:
+ with mock.patch("cloudinit.config.cc_resizefs.do_resize") as dresize:
+ with mock.patch("cloudinit.config.cc_resizefs.os.stat") as m_stat:
m_stat.side_effect = fake_stat
- handle('cc_resizefs', cfg, _cloud=None, log=LOG, args=[])
+ handle("cc_resizefs", cfg, _cloud=None, log=LOG, args=[])
- self.assertEqual(('zpool', 'online', '-e', 'zroot', '/dev/' + disk),
- dresize.call_args[0][0])
+ self.assertEqual(
+ ("zpool", "online", "-e", "zroot", "/dev/" + disk),
+ dresize.call_args[0][0],
+ )
class TestRootDevFromCmdline(CiTestCase):
-
def test_rootdev_from_cmdline_with_no_root(self):
"""Return None from rootdev_from_cmdline when root is not present."""
invalid_cases = [
- 'BOOT_IMAGE=/adsf asdfa werasef root adf', 'BOOT_IMAGE=/adsf', '']
+ "BOOT_IMAGE=/adsf asdfa werasef root adf",
+ "BOOT_IMAGE=/adsf",
+ "",
+ ]
for case in invalid_cases:
self.assertIsNone(util.rootdev_from_cmdline(case))
def test_rootdev_from_cmdline_with_root_startswith_dev(self):
"""Return the cmdline root when the path starts with /dev."""
self.assertEqual(
- '/dev/this', util.rootdev_from_cmdline('asdf root=/dev/this'))
+ "/dev/this", util.rootdev_from_cmdline("asdf root=/dev/this")
+ )
def test_rootdev_from_cmdline_with_root_without_dev_prefix(self):
"""Add /dev prefix to cmdline root when the path lacks the prefix."""
self.assertEqual(
- '/dev/this', util.rootdev_from_cmdline('asdf root=this'))
+ "/dev/this", util.rootdev_from_cmdline("asdf root=this")
+ )
def test_rootdev_from_cmdline_with_root_with_label(self):
"""When cmdline root contains a LABEL, our root is disk/by-label."""
self.assertEqual(
- '/dev/disk/by-label/unique',
- util.rootdev_from_cmdline('asdf root=LABEL=unique'))
+ "/dev/disk/by-label/unique",
+ util.rootdev_from_cmdline("asdf root=LABEL=unique"),
+ )
def test_rootdev_from_cmdline_with_root_with_uuid(self):
"""When cmdline root contains a UUID, our root is disk/by-uuid."""
self.assertEqual(
- '/dev/disk/by-uuid/adsfdsaf-adsf',
- util.rootdev_from_cmdline('asdf root=UUID=adsfdsaf-adsf'))
+ "/dev/disk/by-uuid/adsfdsaf-adsf",
+ util.rootdev_from_cmdline("asdf root=UUID=adsfdsaf-adsf"),
+ )
class TestMaybeGetDevicePathAsWritableBlock(CiTestCase):
@@ -241,158 +279,210 @@ class TestMaybeGetDevicePathAsWritableBlock(CiTestCase):
def test_maybe_get_writable_device_path_none_on_overlayroot(self):
"""When devpath is overlayroot (on MAAS), is_dev_writable is False."""
- info = 'does not matter'
+ info = "does not matter"
devpath = wrap_and_call(
- 'cloudinit.config.cc_resizefs.util',
- {'is_container': {'return_value': False}},
- maybe_get_writable_device_path, 'overlayroot', info, LOG)
+ "cloudinit.config.cc_resizefs.util",
+ {"is_container": {"return_value": False}},
+ maybe_get_writable_device_path,
+ "overlayroot",
+ info,
+ LOG,
+ )
self.assertIsNone(devpath)
self.assertIn(
"Not attempting to resize devpath 'overlayroot'",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
def test_maybe_get_writable_device_path_warns_missing_cmdline_root(self):
"""When root does not exist isn't in the cmdline, log warning."""
- info = 'does not matter'
+ info = "does not matter"
def fake_mount_info(path, log):
- self.assertEqual('/', path)
+ self.assertEqual("/", path)
self.assertEqual(LOG, log)
- return ('/dev/root', 'ext4', '/')
+ return ("/dev/root", "ext4", "/")
- exists_mock_path = 'cloudinit.config.cc_resizefs.os.path.exists'
+ exists_mock_path = "cloudinit.config.cc_resizefs.os.path.exists"
with mock.patch(exists_mock_path) as m_exists:
m_exists.return_value = False
devpath = wrap_and_call(
- 'cloudinit.config.cc_resizefs.util',
- {'is_container': {'return_value': False},
- 'get_mount_info': {'side_effect': fake_mount_info},
- 'get_cmdline': {'return_value': 'BOOT_IMAGE=/vmlinuz.efi'}},
- maybe_get_writable_device_path, '/dev/root', info, LOG)
+ "cloudinit.config.cc_resizefs.util",
+ {
+ "is_container": {"return_value": False},
+ "get_mount_info": {"side_effect": fake_mount_info},
+ "get_cmdline": {"return_value": "BOOT_IMAGE=/vmlinuz.efi"},
+ },
+ maybe_get_writable_device_path,
+ "/dev/root",
+ info,
+ LOG,
+ )
self.assertIsNone(devpath)
logs = self.logs.getvalue()
self.assertIn("WARNING: Unable to find device '/dev/root'", logs)
def test_maybe_get_writable_device_path_does_not_exist(self):
"""When devpath does not exist, a warning is logged."""
- info = 'dev=/dev/I/dont/exist mnt_point=/ path=/dev/none'
+ info = "dev=/dev/I/dont/exist mnt_point=/ path=/dev/none"
devpath = wrap_and_call(
- 'cloudinit.config.cc_resizefs.util',
- {'is_container': {'return_value': False}},
- maybe_get_writable_device_path, '/dev/I/dont/exist', info, LOG)
+ "cloudinit.config.cc_resizefs.util",
+ {"is_container": {"return_value": False}},
+ maybe_get_writable_device_path,
+ "/dev/I/dont/exist",
+ info,
+ LOG,
+ )
self.assertIsNone(devpath)
self.assertIn(
"WARNING: Device '/dev/I/dont/exist' did not exist."
- ' cannot resize: %s' % info,
- self.logs.getvalue())
+ " cannot resize: %s" % info,
+ self.logs.getvalue(),
+ )
def test_maybe_get_writable_device_path_does_not_exist_in_container(self):
"""When devpath does not exist in a container, log a debug message."""
- info = 'dev=/dev/I/dont/exist mnt_point=/ path=/dev/none'
+ info = "dev=/dev/I/dont/exist mnt_point=/ path=/dev/none"
devpath = wrap_and_call(
- 'cloudinit.config.cc_resizefs.util',
- {'is_container': {'return_value': True}},
- maybe_get_writable_device_path, '/dev/I/dont/exist', info, LOG)
+ "cloudinit.config.cc_resizefs.util",
+ {"is_container": {"return_value": True}},
+ maybe_get_writable_device_path,
+ "/dev/I/dont/exist",
+ info,
+ LOG,
+ )
self.assertIsNone(devpath)
self.assertIn(
"DEBUG: Device '/dev/I/dont/exist' did not exist in container."
- ' cannot resize: %s' % info,
- self.logs.getvalue())
+ " cannot resize: %s" % info,
+ self.logs.getvalue(),
+ )
def test_maybe_get_writable_device_path_raises_oserror(self):
"""When unexpected OSError is raises by os.stat it is reraised."""
- info = 'dev=/dev/I/dont/exist mnt_point=/ path=/dev/none'
+ info = "dev=/dev/I/dont/exist mnt_point=/ path=/dev/none"
with self.assertRaises(OSError) as context_manager:
wrap_and_call(
- 'cloudinit.config.cc_resizefs',
- {'util.is_container': {'return_value': True},
- 'os.stat': {'side_effect': OSError('Something unexpected')}},
- maybe_get_writable_device_path, '/dev/I/dont/exist', info, LOG)
+ "cloudinit.config.cc_resizefs",
+ {
+ "util.is_container": {"return_value": True},
+ "os.stat": {
+ "side_effect": OSError("Something unexpected")
+ },
+ },
+ maybe_get_writable_device_path,
+ "/dev/I/dont/exist",
+ info,
+ LOG,
+ )
self.assertEqual(
- 'Something unexpected', str(context_manager.exception))
+ "Something unexpected", str(context_manager.exception)
+ )
def test_maybe_get_writable_device_path_non_block(self):
"""When device is not a block device, emit warning return False."""
- fake_devpath = self.tmp_path('dev/readwrite')
- util.write_file(fake_devpath, '', mode=0o600) # read-write
- info = 'dev=/dev/root mnt_point=/ path={0}'.format(fake_devpath)
+ fake_devpath = self.tmp_path("dev/readwrite")
+ util.write_file(fake_devpath, "", mode=0o600) # read-write
+ info = "dev=/dev/root mnt_point=/ path={0}".format(fake_devpath)
devpath = wrap_and_call(
- 'cloudinit.config.cc_resizefs.util',
- {'is_container': {'return_value': False}},
- maybe_get_writable_device_path, fake_devpath, info, LOG)
+ "cloudinit.config.cc_resizefs.util",
+ {"is_container": {"return_value": False}},
+ maybe_get_writable_device_path,
+ fake_devpath,
+ info,
+ LOG,
+ )
self.assertIsNone(devpath)
self.assertIn(
"WARNING: device '{0}' not a block device. cannot resize".format(
- fake_devpath),
- self.logs.getvalue())
+ fake_devpath
+ ),
+ self.logs.getvalue(),
+ )
def test_maybe_get_writable_device_path_non_block_on_container(self):
"""When device is non-block device in container, emit debug log."""
- fake_devpath = self.tmp_path('dev/readwrite')
- util.write_file(fake_devpath, '', mode=0o600) # read-write
- info = 'dev=/dev/root mnt_point=/ path={0}'.format(fake_devpath)
+ fake_devpath = self.tmp_path("dev/readwrite")
+ util.write_file(fake_devpath, "", mode=0o600) # read-write
+ info = "dev=/dev/root mnt_point=/ path={0}".format(fake_devpath)
devpath = wrap_and_call(
- 'cloudinit.config.cc_resizefs.util',
- {'is_container': {'return_value': True}},
- maybe_get_writable_device_path, fake_devpath, info, LOG)
+ "cloudinit.config.cc_resizefs.util",
+ {"is_container": {"return_value": True}},
+ maybe_get_writable_device_path,
+ fake_devpath,
+ info,
+ LOG,
+ )
self.assertIsNone(devpath)
self.assertIn(
"DEBUG: device '{0}' not a block device in container."
- ' cannot resize'.format(fake_devpath),
- self.logs.getvalue())
+ " cannot resize".format(fake_devpath),
+ self.logs.getvalue(),
+ )
def test_maybe_get_writable_device_path_returns_cmdline_root(self):
"""When root device is UUID in kernel commandline, update devpath."""
# XXX Long-term we want to use FilesystemMocking test to avoid
# touching os.stat.
FakeStat = namedtuple(
- 'FakeStat', ['st_mode', 'st_size', 'st_mtime']) # minimal def.
- info = 'dev=/dev/root mnt_point=/ path=/does/not/matter'
+ "FakeStat", ["st_mode", "st_size", "st_mtime"]
+ ) # minimal def.
+ info = "dev=/dev/root mnt_point=/ path=/does/not/matter"
devpath = wrap_and_call(
- 'cloudinit.config.cc_resizefs',
- {'util.get_cmdline': {'return_value': 'asdf root=UUID=my-uuid'},
- 'util.is_container': False,
- 'os.path.exists': False, # /dev/root doesn't exist
- 'os.stat': {
- 'return_value': FakeStat(25008, 0, 1)} # char block device
- },
- maybe_get_writable_device_path, '/dev/root', info, LOG)
- self.assertEqual('/dev/disk/by-uuid/my-uuid', devpath)
+ "cloudinit.config.cc_resizefs",
+ {
+ "util.get_cmdline": {"return_value": "asdf root=UUID=my-uuid"},
+ "util.is_container": False,
+ "os.path.exists": False, # /dev/root doesn't exist
+ "os.stat": {
+ "return_value": FakeStat(25008, 0, 1)
+ }, # char block device
+ },
+ maybe_get_writable_device_path,
+ "/dev/root",
+ info,
+ LOG,
+ )
+ self.assertEqual("/dev/disk/by-uuid/my-uuid", devpath)
self.assertIn(
"DEBUG: Converted /dev/root to '/dev/disk/by-uuid/my-uuid'"
" per kernel cmdline",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
- @mock.patch('cloudinit.util.mount_is_read_write')
- @mock.patch('cloudinit.config.cc_resizefs.os.path.isdir')
+ @mock.patch("cloudinit.util.mount_is_read_write")
+ @mock.patch("cloudinit.config.cc_resizefs.os.path.isdir")
def test_resize_btrfs_mount_is_ro(self, m_is_dir, m_is_rw):
"""Do not resize / directly if it is read-only. (LP: #1734787)."""
m_is_rw.return_value = False
m_is_dir.return_value = True
self.assertEqual(
- ('btrfs', 'filesystem', 'resize', 'max', '//.snapshots'),
- _resize_btrfs("/", "/dev/sda1"))
+ ("btrfs", "filesystem", "resize", "max", "//.snapshots"),
+ _resize_btrfs("/", "/dev/sda1"),
+ )
- @mock.patch('cloudinit.util.mount_is_read_write')
- @mock.patch('cloudinit.config.cc_resizefs.os.path.isdir')
+ @mock.patch("cloudinit.util.mount_is_read_write")
+ @mock.patch("cloudinit.config.cc_resizefs.os.path.isdir")
def test_resize_btrfs_mount_is_rw(self, m_is_dir, m_is_rw):
"""Do not resize / directly if it is read-only. (LP: #1734787)."""
m_is_rw.return_value = True
m_is_dir.return_value = True
self.assertEqual(
- ('btrfs', 'filesystem', 'resize', 'max', '/'),
- _resize_btrfs("/", "/dev/sda1"))
+ ("btrfs", "filesystem", "resize", "max", "/"),
+ _resize_btrfs("/", "/dev/sda1"),
+ )
- @mock.patch('cloudinit.util.is_container', return_value=True)
- @mock.patch('cloudinit.util.is_FreeBSD')
- def test_maybe_get_writable_device_path_zfs_freebsd(self, freebsd,
- m_is_container):
+ @mock.patch("cloudinit.util.is_container", return_value=True)
+ @mock.patch("cloudinit.util.is_FreeBSD")
+ def test_maybe_get_writable_device_path_zfs_freebsd(
+ self, freebsd, m_is_container
+ ):
freebsd.return_value = True
- info = 'dev=gpt/system mnt_point=/ path=/'
- devpth = maybe_get_writable_device_path('gpt/system', info, LOG)
- self.assertEqual('gpt/system', devpth)
+ info = "dev=gpt/system mnt_point=/ path=/"
+ devpth = maybe_get_writable_device_path("gpt/system", info, LOG)
+ self.assertEqual("gpt/system", devpth)
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_resolv_conf.py b/tests/unittests/config/test_cc_resolv_conf.py
index ab2de17a..8896a4e8 100644
--- a/tests/unittests/config/test_cc_resolv_conf.py
+++ b/tests/unittests/config/test_cc_resolv_conf.py
@@ -4,19 +4,16 @@ import logging
import os
import shutil
import tempfile
-import pytest
from copy import deepcopy
from unittest import mock
-from cloudinit import cloud
-from cloudinit import distros
-from cloudinit import helpers
-from cloudinit import util
+import pytest
-from tests.unittests import helpers as t_help
-from tests.unittests.util import MockDistro
+from cloudinit import cloud, distros, helpers, util
from cloudinit.config import cc_resolv_conf
from cloudinit.config.cc_resolv_conf import generate_resolv_conf
+from tests.unittests import helpers as t_help
+from tests.unittests.util import MockDistro
LOG = logging.getLogger(__name__)
EXPECTED_HEADER = """\
@@ -29,17 +26,17 @@ EXPECTED_HEADER = """\
class TestResolvConf(t_help.FilesystemMockingTestCase):
with_logs = True
- cfg = {'manage_resolv_conf': True, 'resolv_conf': {}}
+ cfg = {"manage_resolv_conf": True, "resolv_conf": {}}
def setUp(self):
super(TestResolvConf, self).setUp()
self.tmp = tempfile.mkdtemp()
- util.ensure_dir(os.path.join(self.tmp, 'data'))
+ util.ensure_dir(os.path.join(self.tmp, "data"))
self.addCleanup(shutil.rmtree, self.tmp)
def _fetch_distro(self, kind, conf=None):
cls = distros.fetch(kind)
- paths = helpers.Paths({'cloud_dir': self.tmp})
+ paths = helpers.Paths({"cloud_dir": self.tmp})
conf = {} if conf is None else conf
return cls(kind, conf, paths)
@@ -47,67 +44,73 @@ class TestResolvConf(t_help.FilesystemMockingTestCase):
if not cc:
ds = None
distro = self._fetch_distro(distro_name, conf)
- paths = helpers.Paths({'cloud_dir': self.tmp})
+ paths = helpers.Paths({"cloud_dir": self.tmp})
cc = cloud.Cloud(ds, paths, {}, distro, None)
- cc_resolv_conf.handle('cc_resolv_conf', conf, cc, LOG, [])
+ cc_resolv_conf.handle("cc_resolv_conf", conf, cc, LOG, [])
@mock.patch("cloudinit.config.cc_resolv_conf.templater.render_to_file")
def test_resolv_conf_systemd_resolved(self, m_render_to_file):
- self.call_resolv_conf_handler('photon', self.cfg)
+ self.call_resolv_conf_handler("photon", self.cfg)
assert [
- mock.call(mock.ANY, '/etc/systemd/resolved.conf', mock.ANY)
+ mock.call(mock.ANY, "/etc/systemd/resolved.conf", mock.ANY)
] == m_render_to_file.call_args_list
@mock.patch("cloudinit.config.cc_resolv_conf.templater.render_to_file")
def test_resolv_conf_no_param(self, m_render_to_file):
tmp = deepcopy(self.cfg)
self.logs.truncate(0)
- tmp.pop('resolv_conf')
- self.call_resolv_conf_handler('photon', tmp)
+ tmp.pop("resolv_conf")
+ self.call_resolv_conf_handler("photon", tmp)
- self.assertIn('manage_resolv_conf True but no parameters provided',
- self.logs.getvalue())
+ self.assertIn(
+ "manage_resolv_conf True but no parameters provided",
+ self.logs.getvalue(),
+ )
assert [
- mock.call(mock.ANY, '/etc/systemd/resolved.conf', mock.ANY)
+ mock.call(mock.ANY, "/etc/systemd/resolved.conf", mock.ANY)
] not in m_render_to_file.call_args_list
@mock.patch("cloudinit.config.cc_resolv_conf.templater.render_to_file")
def test_resolv_conf_manage_resolv_conf_false(self, m_render_to_file):
tmp = deepcopy(self.cfg)
self.logs.truncate(0)
- tmp['manage_resolv_conf'] = False
- self.call_resolv_conf_handler('photon', tmp)
- self.assertIn("'manage_resolv_conf' present but set to False",
- self.logs.getvalue())
+ tmp["manage_resolv_conf"] = False
+ self.call_resolv_conf_handler("photon", tmp)
+ self.assertIn(
+ "'manage_resolv_conf' present but set to False",
+ self.logs.getvalue(),
+ )
assert [
- mock.call(mock.ANY, '/etc/systemd/resolved.conf', mock.ANY)
+ mock.call(mock.ANY, "/etc/systemd/resolved.conf", mock.ANY)
] not in m_render_to_file.call_args_list
@mock.patch("cloudinit.config.cc_resolv_conf.templater.render_to_file")
def test_resolv_conf_etc_resolv_conf(self, m_render_to_file):
- self.call_resolv_conf_handler('rhel', self.cfg)
+ self.call_resolv_conf_handler("rhel", self.cfg)
assert [
- mock.call(mock.ANY, '/etc/resolv.conf', mock.ANY)
+ mock.call(mock.ANY, "/etc/resolv.conf", mock.ANY)
] == m_render_to_file.call_args_list
@mock.patch("cloudinit.config.cc_resolv_conf.templater.render_to_file")
def test_resolv_conf_invalid_resolve_conf_fn(self, m_render_to_file):
ds = None
- distro = self._fetch_distro('rhel', self.cfg)
- paths = helpers.Paths({'cloud_dir': self.tmp})
+ distro = self._fetch_distro("rhel", self.cfg)
+ paths = helpers.Paths({"cloud_dir": self.tmp})
cc = cloud.Cloud(ds, paths, {}, distro, None)
- cc.distro.resolve_conf_fn = 'bla'
+ cc.distro.resolve_conf_fn = "bla"
self.logs.truncate(0)
- self.call_resolv_conf_handler('rhel', self.cfg, cc)
+ self.call_resolv_conf_handler("rhel", self.cfg, cc)
- self.assertIn('No template found, not rendering resolve configs',
- self.logs.getvalue())
+ self.assertIn(
+ "No template found, not rendering resolve configs",
+ self.logs.getvalue(),
+ )
assert [
- mock.call(mock.ANY, '/etc/resolv.conf', mock.ANY)
+ mock.call(mock.ANY, "/etc/resolv.conf", mock.ANY)
] not in m_render_to_file.call_args_list
@@ -119,9 +122,9 @@ class TestGenerateResolvConf:
@mock.patch("cloudinit.config.cc_resolv_conf.templater.render_to_file")
def test_dist_resolv_conf_fn(self, m_render_to_file):
self.dist.resolve_conf_fn = "/tmp/resolv-test.conf"
- generate_resolv_conf(self.tmpl_fn,
- mock.MagicMock(),
- self.dist.resolve_conf_fn)
+ generate_resolv_conf(
+ self.tmpl_fn, mock.MagicMock(), self.dist.resolve_conf_fn
+ )
assert [
mock.call(mock.ANY, self.dist.resolve_conf_fn, mock.ANY)
@@ -190,4 +193,5 @@ class TestGenerateResolvConf:
mock.call(mock.ANY, expected_content, mode=mock.ANY)
] == m_write_file.call_args_list
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_rh_subscription.py b/tests/unittests/config/test_cc_rh_subscription.py
index bd7ebc98..fcc7db34 100644
--- a/tests/unittests/config/test_cc_rh_subscription.py
+++ b/tests/unittests/config/test_cc_rh_subscription.py
@@ -5,13 +5,12 @@
import copy
import logging
-from cloudinit.config import cc_rh_subscription
from cloudinit import subp
-
+from cloudinit.config import cc_rh_subscription
from tests.unittests.helpers import CiTestCase, mock
SUBMGR = cc_rh_subscription.SubscriptionManager
-SUB_MAN_CLI = 'cloudinit.config.cc_rh_subscription._sub_man_cli'
+SUB_MAN_CLI = "cloudinit.config.cc_rh_subscription._sub_man_cli"
@mock.patch(SUB_MAN_CLI)
@@ -26,87 +25,115 @@ class GoodTests(CiTestCase):
self.args = []
self.handle = cc_rh_subscription.handle
- self.config = {'rh_subscription':
- {'username': 'scooby@do.com',
- 'password': 'scooby-snacks'
- }}
- self.config_full = {'rh_subscription':
- {'username': 'scooby@do.com',
- 'password': 'scooby-snacks',
- 'auto-attach': True,
- 'service-level': 'self-support',
- 'add-pool': ['pool1', 'pool2', 'pool3'],
- 'enable-repo': ['repo1', 'repo2', 'repo3'],
- 'disable-repo': ['repo4', 'repo5']
- }}
+ self.config = {
+ "rh_subscription": {
+ "username": "scooby@do.com",
+ "password": "scooby-snacks",
+ }
+ }
+ self.config_full = {
+ "rh_subscription": {
+ "username": "scooby@do.com",
+ "password": "scooby-snacks",
+ "auto-attach": True,
+ "service-level": "self-support",
+ "add-pool": ["pool1", "pool2", "pool3"],
+ "enable-repo": ["repo1", "repo2", "repo3"],
+ "disable-repo": ["repo4", "repo5"],
+ }
+ }
def test_already_registered(self, m_sman_cli):
- '''
+ """
Emulates a system that is already registered. Ensure it gets
a non-ProcessExecution error from is_registered()
- '''
- self.handle(self.name, self.config, self.cloud_init,
- self.log, self.args)
+ """
+ self.handle(
+ self.name, self.config, self.cloud_init, self.log, self.args
+ )
self.assertEqual(m_sman_cli.call_count, 1)
- self.assertIn('System is already registered', self.logs.getvalue())
+ self.assertIn("System is already registered", self.logs.getvalue())
def test_simple_registration(self, m_sman_cli):
- '''
+ """
Simple registration with username and password
- '''
- reg = "The system has been registered with ID:" \
- " 12345678-abde-abcde-1234-1234567890abc"
- m_sman_cli.side_effect = [subp.ProcessExecutionError, (reg, 'bar')]
- self.handle(self.name, self.config, self.cloud_init,
- self.log, self.args)
- self.assertIn(mock.call(['identity']), m_sman_cli.call_args_list)
- self.assertIn(mock.call(['register', '--username=scooby@do.com',
- '--password=scooby-snacks'],
- logstring_val=True),
- m_sman_cli.call_args_list)
- self.assertIn('rh_subscription plugin completed successfully',
- self.logs.getvalue())
+ """
+ reg = (
+ "The system has been registered with ID:"
+ " 12345678-abde-abcde-1234-1234567890abc"
+ )
+ m_sman_cli.side_effect = [subp.ProcessExecutionError, (reg, "bar")]
+ self.handle(
+ self.name, self.config, self.cloud_init, self.log, self.args
+ )
+ self.assertIn(mock.call(["identity"]), m_sman_cli.call_args_list)
+ self.assertIn(
+ mock.call(
+ [
+ "register",
+ "--username=scooby@do.com",
+ "--password=scooby-snacks",
+ ],
+ logstring_val=True,
+ ),
+ m_sman_cli.call_args_list,
+ )
+ self.assertIn(
+ "rh_subscription plugin completed successfully",
+ self.logs.getvalue(),
+ )
self.assertEqual(m_sman_cli.call_count, 2)
@mock.patch.object(cc_rh_subscription.SubscriptionManager, "_getRepos")
def test_update_repos_disable_with_none(self, m_get_repos, m_sman_cli):
cfg = copy.deepcopy(self.config)
- m_get_repos.return_value = ([], ['repo1'])
- cfg['rh_subscription'].update(
- {'enable-repo': ['repo1'], 'disable-repo': None})
+ m_get_repos.return_value = ([], ["repo1"])
+ cfg["rh_subscription"].update(
+ {"enable-repo": ["repo1"], "disable-repo": None}
+ )
mysm = cc_rh_subscription.SubscriptionManager(cfg)
self.assertEqual(True, mysm.update_repos())
m_get_repos.assert_called_with()
- self.assertEqual(m_sman_cli.call_args_list,
- [mock.call(['repos', '--enable=repo1'])])
+ self.assertEqual(
+ m_sman_cli.call_args_list, [mock.call(["repos", "--enable=repo1"])]
+ )
def test_full_registration(self, m_sman_cli):
- '''
+ """
Registration with auto-attach, service-level, adding pools,
and enabling and disabling yum repos
- '''
+ """
call_lists = []
- call_lists.append(['attach', '--pool=pool1', '--pool=pool3'])
- call_lists.append(['repos', '--disable=repo5', '--enable=repo2',
- '--enable=repo3'])
- call_lists.append(['attach', '--auto', '--servicelevel=self-support'])
- reg = "The system has been registered with ID:" \
- " 12345678-abde-abcde-1234-1234567890abc"
+ call_lists.append(["attach", "--pool=pool1", "--pool=pool3"])
+ call_lists.append(
+ ["repos", "--disable=repo5", "--enable=repo2", "--enable=repo3"]
+ )
+ call_lists.append(["attach", "--auto", "--servicelevel=self-support"])
+ reg = (
+ "The system has been registered with ID:"
+ " 12345678-abde-abcde-1234-1234567890abc"
+ )
m_sman_cli.side_effect = [
subp.ProcessExecutionError,
- (reg, 'bar'),
- ('Service level set to: self-support', ''),
- ('pool1\npool3\n', ''), ('pool2\n', ''), ('', ''),
- ('Repo ID: repo1\nRepo ID: repo5\n', ''),
- ('Repo ID: repo2\nRepo ID: repo3\nRepo ID: repo4', ''),
- ('', '')]
- self.handle(self.name, self.config_full, self.cloud_init,
- self.log, self.args)
+ (reg, "bar"),
+ ("Service level set to: self-support", ""),
+ ("pool1\npool3\n", ""),
+ ("pool2\n", ""),
+ ("", ""),
+ ("Repo ID: repo1\nRepo ID: repo5\n", ""),
+ ("Repo ID: repo2\nRepo ID: repo3\nRepo ID: repo4", ""),
+ ("", ""),
+ ]
+ self.handle(
+ self.name, self.config_full, self.cloud_init, self.log, self.args
+ )
self.assertEqual(m_sman_cli.call_count, 9)
for call in call_lists:
self.assertIn(mock.call(call), m_sman_cli.call_args_list)
- self.assertIn("rh_subscription plugin completed successfully",
- self.logs.getvalue())
+ self.assertIn(
+ "rh_subscription plugin completed successfully",
+ self.logs.getvalue(),
+ )
@mock.patch(SUB_MAN_CLI)
@@ -117,38 +144,48 @@ class TestBadInput(CiTestCase):
log = logging.getLogger("bad_tests")
args = []
SM = cc_rh_subscription.SubscriptionManager
- reg = "The system has been registered with ID:" \
- " 12345678-abde-abcde-1234-1234567890abc"
-
- config_no_password = {'rh_subscription':
- {'username': 'scooby@do.com'
- }}
-
- config_no_key = {'rh_subscription':
- {'activation-key': '1234abcde',
- }}
-
- config_service = {'rh_subscription':
- {'username': 'scooby@do.com',
- 'password': 'scooby-snacks',
- 'service-level': 'self-support'
- }}
-
- config_badpool = {'rh_subscription':
- {'username': 'scooby@do.com',
- 'password': 'scooby-snacks',
- 'add-pool': 'not_a_list'
- }}
- config_badrepo = {'rh_subscription':
- {'username': 'scooby@do.com',
- 'password': 'scooby-snacks',
- 'enable-repo': 'not_a_list'
- }}
- config_badkey = {'rh_subscription':
- {'activation-key': 'abcdef1234',
- 'fookey': 'bar',
- 'org': '123',
- }}
+ reg = (
+ "The system has been registered with ID:"
+ " 12345678-abde-abcde-1234-1234567890abc"
+ )
+
+ config_no_password = {"rh_subscription": {"username": "scooby@do.com"}}
+
+ config_no_key = {
+ "rh_subscription": {
+ "activation-key": "1234abcde",
+ }
+ }
+
+ config_service = {
+ "rh_subscription": {
+ "username": "scooby@do.com",
+ "password": "scooby-snacks",
+ "service-level": "self-support",
+ }
+ }
+
+ config_badpool = {
+ "rh_subscription": {
+ "username": "scooby@do.com",
+ "password": "scooby-snacks",
+ "add-pool": "not_a_list",
+ }
+ }
+ config_badrepo = {
+ "rh_subscription": {
+ "username": "scooby@do.com",
+ "password": "scooby-snacks",
+ "enable-repo": "not_a_list",
+ }
+ }
+ config_badkey = {
+ "rh_subscription": {
+ "activation-key": "abcdef1234",
+ "fookey": "bar",
+ "org": "123",
+ }
+ }
def setUp(self):
super(TestBadInput, self).setUp()
@@ -160,75 +197,124 @@ class TestBadInput(CiTestCase):
self.assertEqual([], missing, "Missing expected warnings.")
def test_no_password(self, m_sman_cli):
- '''Attempt to register without the password key/value.'''
- m_sman_cli.side_effect = [subp.ProcessExecutionError,
- (self.reg, 'bar')]
- self.handle(self.name, self.config_no_password, self.cloud_init,
- self.log, self.args)
+ """Attempt to register without the password key/value."""
+ m_sman_cli.side_effect = [
+ subp.ProcessExecutionError,
+ (self.reg, "bar"),
+ ]
+ self.handle(
+ self.name,
+ self.config_no_password,
+ self.cloud_init,
+ self.log,
+ self.args,
+ )
self.assertEqual(m_sman_cli.call_count, 0)
def test_no_org(self, m_sman_cli):
- '''Attempt to register without the org key/value.'''
+ """Attempt to register without the org key/value."""
m_sman_cli.side_effect = [subp.ProcessExecutionError]
- self.handle(self.name, self.config_no_key, self.cloud_init,
- self.log, self.args)
- m_sman_cli.assert_called_with(['identity'])
+ self.handle(
+ self.name, self.config_no_key, self.cloud_init, self.log, self.args
+ )
+ m_sman_cli.assert_called_with(["identity"])
self.assertEqual(m_sman_cli.call_count, 1)
- self.assert_logged_warnings((
- 'Unable to register system due to incomplete information.',
- 'Use either activationkey and org *or* userid and password',
- 'Registration failed or did not run completely',
- 'rh_subscription plugin did not complete successfully'))
+ self.assert_logged_warnings(
+ (
+ "Unable to register system due to incomplete information.",
+ "Use either activationkey and org *or* userid and password",
+ "Registration failed or did not run completely",
+ "rh_subscription plugin did not complete successfully",
+ )
+ )
def test_service_level_without_auto(self, m_sman_cli):
- '''Attempt to register using service-level without auto-attach key.'''
- m_sman_cli.side_effect = [subp.ProcessExecutionError,
- (self.reg, 'bar')]
- self.handle(self.name, self.config_service, self.cloud_init,
- self.log, self.args)
+ """Attempt to register using service-level without auto-attach key."""
+ m_sman_cli.side_effect = [
+ subp.ProcessExecutionError,
+ (self.reg, "bar"),
+ ]
+ self.handle(
+ self.name,
+ self.config_service,
+ self.cloud_init,
+ self.log,
+ self.args,
+ )
self.assertEqual(m_sman_cli.call_count, 1)
- self.assert_logged_warnings((
- 'The service-level key must be used in conjunction with ',
- 'rh_subscription plugin did not complete successfully'))
+ self.assert_logged_warnings(
+ (
+ "The service-level key must be used in conjunction with ",
+ "rh_subscription plugin did not complete successfully",
+ )
+ )
def test_pool_not_a_list(self, m_sman_cli):
- '''
+ """
Register with pools that are not in the format of a list
- '''
- m_sman_cli.side_effect = [subp.ProcessExecutionError,
- (self.reg, 'bar')]
- self.handle(self.name, self.config_badpool, self.cloud_init,
- self.log, self.args)
+ """
+ m_sman_cli.side_effect = [
+ subp.ProcessExecutionError,
+ (self.reg, "bar"),
+ ]
+ self.handle(
+ self.name,
+ self.config_badpool,
+ self.cloud_init,
+ self.log,
+ self.args,
+ )
self.assertEqual(m_sman_cli.call_count, 2)
- self.assert_logged_warnings((
- 'Pools must in the format of a list',
- 'rh_subscription plugin did not complete successfully'))
+ self.assert_logged_warnings(
+ (
+ "Pools must in the format of a list",
+ "rh_subscription plugin did not complete successfully",
+ )
+ )
def test_repo_not_a_list(self, m_sman_cli):
- '''
+ """
Register with repos that are not in the format of a list
- '''
- m_sman_cli.side_effect = [subp.ProcessExecutionError,
- (self.reg, 'bar')]
- self.handle(self.name, self.config_badrepo, self.cloud_init,
- self.log, self.args)
+ """
+ m_sman_cli.side_effect = [
+ subp.ProcessExecutionError,
+ (self.reg, "bar"),
+ ]
+ self.handle(
+ self.name,
+ self.config_badrepo,
+ self.cloud_init,
+ self.log,
+ self.args,
+ )
self.assertEqual(m_sman_cli.call_count, 2)
- self.assert_logged_warnings((
- 'Repo IDs must in the format of a list.',
- 'Unable to add or remove repos',
- 'rh_subscription plugin did not complete successfully'))
+ self.assert_logged_warnings(
+ (
+ "Repo IDs must in the format of a list.",
+ "Unable to add or remove repos",
+ "rh_subscription plugin did not complete successfully",
+ )
+ )
def test_bad_key_value(self, m_sman_cli):
- '''
+ """
Attempt to register with a key that we don't know
- '''
- m_sman_cli.side_effect = [subp.ProcessExecutionError,
- (self.reg, 'bar')]
- self.handle(self.name, self.config_badkey, self.cloud_init,
- self.log, self.args)
+ """
+ m_sman_cli.side_effect = [
+ subp.ProcessExecutionError,
+ (self.reg, "bar"),
+ ]
+ self.handle(
+ self.name, self.config_badkey, self.cloud_init, self.log, self.args
+ )
self.assertEqual(m_sman_cli.call_count, 1)
- self.assert_logged_warnings((
- 'fookey is not a valid key for rh_subscription. Valid keys are:',
- 'rh_subscription plugin did not complete successfully'))
+ self.assert_logged_warnings(
+ (
+ "fookey is not a valid key for rh_subscription. Valid keys"
+ " are:",
+ "rh_subscription plugin did not complete successfully",
+ )
+ )
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_rsyslog.py b/tests/unittests/config/test_cc_rsyslog.py
index bc147dac..e5d06ca2 100644
--- a/tests/unittests/config/test_cc_rsyslog.py
+++ b/tests/unittests/config/test_cc_rsyslog.py
@@ -4,11 +4,16 @@ import os
import shutil
import tempfile
-from cloudinit.config.cc_rsyslog import (
- apply_rsyslog_changes, DEF_DIR, DEF_FILENAME, DEF_RELOAD, load_config,
- parse_remotes_line, remotes_to_rsyslog_cfg)
from cloudinit import util
-
+from cloudinit.config.cc_rsyslog import (
+ DEF_DIR,
+ DEF_FILENAME,
+ DEF_RELOAD,
+ apply_rsyslog_changes,
+ load_config,
+ parse_remotes_line,
+ remotes_to_rsyslog_cfg,
+)
from tests.unittests import helpers as t_help
@@ -16,43 +21,46 @@ class TestLoadConfig(t_help.TestCase):
def setUp(self):
super(TestLoadConfig, self).setUp()
self.basecfg = {
- 'config_filename': DEF_FILENAME,
- 'config_dir': DEF_DIR,
- 'service_reload_command': DEF_RELOAD,
- 'configs': [],
- 'remotes': {},
+ "config_filename": DEF_FILENAME,
+ "config_dir": DEF_DIR,
+ "service_reload_command": DEF_RELOAD,
+ "configs": [],
+ "remotes": {},
}
def test_legacy_full(self):
- found = load_config({
- 'rsyslog': ['*.* @192.168.1.1'],
- 'rsyslog_dir': "mydir",
- 'rsyslog_filename': "myfilename"})
- self.basecfg.update({
- 'configs': ['*.* @192.168.1.1'],
- 'config_dir': "mydir",
- 'config_filename': 'myfilename',
- 'service_reload_command': 'auto'}
+ found = load_config(
+ {
+ "rsyslog": ["*.* @192.168.1.1"],
+ "rsyslog_dir": "mydir",
+ "rsyslog_filename": "myfilename",
+ }
+ )
+ self.basecfg.update(
+ {
+ "configs": ["*.* @192.168.1.1"],
+ "config_dir": "mydir",
+ "config_filename": "myfilename",
+ "service_reload_command": "auto",
+ }
)
self.assertEqual(found, self.basecfg)
def test_legacy_defaults(self):
- found = load_config({
- 'rsyslog': ['*.* @192.168.1.1']})
- self.basecfg.update({
- 'configs': ['*.* @192.168.1.1']})
+ found = load_config({"rsyslog": ["*.* @192.168.1.1"]})
+ self.basecfg.update({"configs": ["*.* @192.168.1.1"]})
self.assertEqual(found, self.basecfg)
def test_new_defaults(self):
self.assertEqual(load_config({}), self.basecfg)
def test_new_configs(self):
- cfgs = ['*.* myhost', '*.* my2host']
- self.basecfg.update({'configs': cfgs})
+ cfgs = ["*.* myhost", "*.* my2host"]
+ self.basecfg.update({"configs": cfgs})
self.assertEqual(
- load_config({'rsyslog': {'configs': cfgs}}),
- self.basecfg)
+ load_config({"rsyslog": {"configs": cfgs}}), self.basecfg
+ )
class TestApplyChanges(t_help.TestCase):
@@ -63,27 +71,29 @@ class TestApplyChanges(t_help.TestCase):
def test_simple(self):
cfgline = "*.* foohost"
changed = apply_rsyslog_changes(
- configs=[cfgline], def_fname="foo.cfg", cfg_dir=self.tmp)
+ configs=[cfgline], def_fname="foo.cfg", cfg_dir=self.tmp
+ )
fname = os.path.join(self.tmp, "foo.cfg")
self.assertEqual([fname], changed)
- self.assertEqual(
- util.load_file(fname), cfgline + "\n")
+ self.assertEqual(util.load_file(fname), cfgline + "\n")
def test_multiple_files(self):
configs = [
- '*.* foohost',
- {'content': 'abc', 'filename': 'my.cfg'},
- {'content': 'filefoo-content',
- 'filename': os.path.join(self.tmp, 'mydir/mycfg')},
+ "*.* foohost",
+ {"content": "abc", "filename": "my.cfg"},
+ {
+ "content": "filefoo-content",
+ "filename": os.path.join(self.tmp, "mydir/mycfg"),
+ },
]
changed = apply_rsyslog_changes(
- configs=configs, def_fname="default.cfg", cfg_dir=self.tmp)
+ configs=configs, def_fname="default.cfg", cfg_dir=self.tmp
+ )
expected = [
- (os.path.join(self.tmp, "default.cfg"),
- "*.* foohost\n"),
+ (os.path.join(self.tmp, "default.cfg"), "*.* foohost\n"),
(os.path.join(self.tmp, "my.cfg"), "abc\n"),
(os.path.join(self.tmp, "mydir/mycfg"), "filefoo-content\n"),
]
@@ -91,30 +101,37 @@ class TestApplyChanges(t_help.TestCase):
actual = []
for fname, _content in expected:
util.load_file(fname)
- actual.append((fname, util.load_file(fname),))
+ actual.append(
+ (
+ fname,
+ util.load_file(fname),
+ )
+ )
self.assertEqual(expected, actual)
def test_repeat_def(self):
- configs = ['*.* foohost', "*.warn otherhost"]
+ configs = ["*.* foohost", "*.warn otherhost"]
changed = apply_rsyslog_changes(
- configs=configs, def_fname="default.cfg", cfg_dir=self.tmp)
+ configs=configs, def_fname="default.cfg", cfg_dir=self.tmp
+ )
fname = os.path.join(self.tmp, "default.cfg")
self.assertEqual([fname], changed)
- expected_content = '\n'.join([c for c in configs]) + '\n'
+ expected_content = "\n".join([c for c in configs]) + "\n"
found_content = util.load_file(fname)
self.assertEqual(expected_content, found_content)
def test_multiline_content(self):
- configs = ['line1', 'line2\nline3\n']
+ configs = ["line1", "line2\nline3\n"]
apply_rsyslog_changes(
- configs=configs, def_fname="default.cfg", cfg_dir=self.tmp)
+ configs=configs, def_fname="default.cfg", cfg_dir=self.tmp
+ )
fname = os.path.join(self.tmp, "default.cfg")
- expected_content = '\n'.join([c for c in configs])
+ expected_content = "\n".join([c for c in configs])
found_content = util.load_file(fname)
self.assertEqual(expected_content, found_content)
@@ -152,7 +169,7 @@ class TestRemotesToSyslog(t_help.TestCase):
# str rendered line must appear in remotes_to_ryslog_cfg return
mycfg = "*.* myhost"
myline = str(parse_remotes_line(mycfg, name="myname"))
- r = remotes_to_rsyslog_cfg({'myname': mycfg})
+ r = remotes_to_rsyslog_cfg({"myname": mycfg})
lines = r.splitlines()
self.assertEqual(1, len(lines))
self.assertTrue(myline in r.splitlines())
@@ -161,7 +178,8 @@ class TestRemotesToSyslog(t_help.TestCase):
header = "#foo head"
footer = "#foo foot"
r = remotes_to_rsyslog_cfg(
- {'myname': "*.* myhost"}, header=header, footer=footer)
+ {"myname": "*.* myhost"}, header=header, footer=footer
+ )
lines = r.splitlines()
self.assertTrue(header, lines[0])
self.assertTrue(footer, lines[-1])
@@ -170,9 +188,11 @@ class TestRemotesToSyslog(t_help.TestCase):
mycfg = "*.* myhost"
myline = str(parse_remotes_line(mycfg, name="myname"))
r = remotes_to_rsyslog_cfg(
- {'myname': mycfg, 'removed': None, 'removed2': ""})
+ {"myname": mycfg, "removed": None, "removed2": ""}
+ )
lines = r.splitlines()
self.assertEqual(1, len(lines))
self.assertTrue(myline in r.splitlines())
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_runcmd.py b/tests/unittests/config/test_cc_runcmd.py
index 01de6af0..34b3fb77 100644
--- a/tests/unittests/config/test_cc_runcmd.py
+++ b/tests/unittests/config/test_cc_runcmd.py
@@ -4,12 +4,14 @@ import os
import stat
from unittest.mock import patch
+from cloudinit import helpers, subp, util
from cloudinit.config.cc_runcmd import handle, schema
-from cloudinit import (helpers, subp, util)
from tests.unittests.helpers import (
- CiTestCase, FilesystemMockingTestCase, SchemaTestCaseMixin,
- skipUnlessJsonSchema)
-
+ CiTestCase,
+ FilesystemMockingTestCase,
+ SchemaTestCaseMixin,
+ skipUnlessJsonSchema,
+)
from tests.unittests.util import get_cloud
LOG = logging.getLogger(__name__)
@@ -24,38 +26,40 @@ class TestRuncmd(FilesystemMockingTestCase):
self.subp = subp.subp
self.new_root = self.tmp_dir()
self.patchUtils(self.new_root)
- self.paths = helpers.Paths({'scripts': self.new_root})
+ self.paths = helpers.Paths({"scripts": self.new_root})
def test_handler_skip_if_no_runcmd(self):
"""When the provided config doesn't contain runcmd, skip it."""
cfg = {}
mycloud = get_cloud(paths=self.paths)
- handle('notimportant', cfg, mycloud, LOG, None)
+ handle("notimportant", cfg, mycloud, LOG, None)
self.assertIn(
"Skipping module named notimportant, no 'runcmd' key",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
- @patch('cloudinit.util.shellify')
+ @patch("cloudinit.util.shellify")
def test_runcmd_shellify_fails(self, cls):
"""When shellify fails throw exception"""
cls.side_effect = TypeError("patched shellify")
- valid_config = {'runcmd': ['echo 42']}
+ valid_config = {"runcmd": ["echo 42"]}
cc = get_cloud(paths=self.paths)
with self.assertRaises(TypeError) as cm:
- with self.allow_subp(['/bin/sh']):
- handle('cc_runcmd', valid_config, cc, LOG, None)
+ with self.allow_subp(["/bin/sh"]):
+ handle("cc_runcmd", valid_config, cc, LOG, None)
self.assertIn("Failed to shellify", str(cm.exception))
def test_handler_invalid_command_set(self):
"""Commands which can't be converted to shell will raise errors."""
- invalid_config = {'runcmd': 1}
+ invalid_config = {"runcmd": 1}
cc = get_cloud(paths=self.paths)
with self.assertRaises(TypeError) as cm:
- handle('cc_runcmd', invalid_config, cc, LOG, [])
+ handle("cc_runcmd", invalid_config, cc, LOG, [])
self.assertIn(
- 'Failed to shellify 1 into file'
- ' /var/lib/cloud/instances/iid-datasource-none/scripts/runcmd',
- str(cm.exception))
+ "Failed to shellify 1 into file"
+ " /var/lib/cloud/instances/iid-datasource-none/scripts/runcmd",
+ str(cm.exception),
+ )
@skipUnlessJsonSchema()
def test_handler_schema_validation_warns_non_array_type(self):
@@ -64,14 +68,15 @@ class TestRuncmd(FilesystemMockingTestCase):
Schema validation is not strict, so runcmd attempts to shellify the
invalid content.
"""
- invalid_config = {'runcmd': 1}
+ invalid_config = {"runcmd": 1}
cc = get_cloud(paths=self.paths)
with self.assertRaises(TypeError) as cm:
- handle('cc_runcmd', invalid_config, cc, LOG, [])
+ handle("cc_runcmd", invalid_config, cc, LOG, [])
self.assertIn(
- 'Invalid config:\nruncmd: 1 is not of type \'array\'',
- self.logs.getvalue())
- self.assertIn('Failed to shellify', str(cm.exception))
+ "Invalid config:\nruncmd: 1 is not of type 'array'",
+ self.logs.getvalue(),
+ )
+ self.assertIn("Failed to shellify", str(cm.exception))
@skipUnlessJsonSchema()
def test_handler_schema_validation_warns_non_array_item_type(self):
@@ -81,28 +86,29 @@ class TestRuncmd(FilesystemMockingTestCase):
invalid content.
"""
invalid_config = {
- 'runcmd': ['ls /', 20, ['wget', 'http://stuff/blah'], {'a': 'n'}]}
+ "runcmd": ["ls /", 20, ["wget", "http://stuff/blah"], {"a": "n"}]
+ }
cc = get_cloud(paths=self.paths)
with self.assertRaises(TypeError) as cm:
- handle('cc_runcmd', invalid_config, cc, LOG, [])
+ handle("cc_runcmd", invalid_config, cc, LOG, [])
expected_warnings = [
- 'runcmd.1: 20 is not valid under any of the given schemas',
- 'runcmd.3: {\'a\': \'n\'} is not valid under any of the given'
- ' schema'
+ "runcmd.1: 20 is not valid under any of the given schemas",
+ "runcmd.3: {'a': 'n'} is not valid under any of the given schema",
]
logs = self.logs.getvalue()
for warning in expected_warnings:
self.assertIn(warning, logs)
- self.assertIn('Failed to shellify', str(cm.exception))
+ self.assertIn("Failed to shellify", str(cm.exception))
def test_handler_write_valid_runcmd_schema_to_file(self):
"""Valid runcmd schema is written to a runcmd shell script."""
- valid_config = {'runcmd': [['ls', '/']]}
+ valid_config = {"runcmd": [["ls", "/"]]}
cc = get_cloud(paths=self.paths)
- handle('cc_runcmd', valid_config, cc, LOG, [])
+ handle("cc_runcmd", valid_config, cc, LOG, [])
runcmd_file = os.path.join(
self.new_root,
- 'var/lib/cloud/instances/iid-datasource-none/scripts/runcmd')
+ "var/lib/cloud/instances/iid-datasource-none/scripts/runcmd",
+ )
self.assertEqual("#!/bin/sh\n'ls' '/'\n", util.load_file(runcmd_file))
file_stat = os.stat(runcmd_file)
self.assertEqual(0o700, stat.S_IMODE(file_stat.st_mode))
@@ -118,12 +124,14 @@ class TestSchema(CiTestCase, SchemaTestCaseMixin):
"""Duplicated commands array/array entries are allowed."""
self.assertSchemaValid(
[["echo", "bye"], ["echo", "bye"]],
- "command entries can be duplicate.")
+ "command entries can be duplicate.",
+ )
def test_duplicates_are_fine_array_string(self):
"""Duplicated commands array/string entries are allowed."""
self.assertSchemaValid(
- ["echo bye", "echo bye"],
- "command entries can be duplicate.")
+ ["echo bye", "echo bye"], "command entries can be duplicate."
+ )
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_seed_random.py b/tests/unittests/config/test_cc_seed_random.py
index cfd67dce..8b2fdcdd 100644
--- a/tests/unittests/config/test_cc_seed_random.py
+++ b/tests/unittests/config/test_cc_seed_random.py
@@ -12,11 +12,9 @@ import logging
import tempfile
from io import BytesIO
-from cloudinit import subp
-from cloudinit import util
+from cloudinit import subp, util
from cloudinit.config import cc_seed_random
from tests.unittests import helpers as t_help
-
from tests.unittests.util import get_cloud
LOG = logging.getLogger(__name__)
@@ -29,8 +27,8 @@ class TestRandomSeed(t_help.TestCase):
self.unapply = []
# by default 'which' has nothing in its path
- self.apply_patches([(subp, 'which', self._which)])
- self.apply_patches([(subp, 'subp', self._subp)])
+ self.apply_patches([(subp, "which", self._which)])
+ self.apply_patches([(subp, "subp", self._subp)])
self.subp_called = []
self.whichdata = {}
@@ -47,149 +45,166 @@ class TestRandomSeed(t_help.TestCase):
def _subp(self, *args, **kwargs):
# supports subp calling with cmd as args or kwargs
- if 'args' not in kwargs:
- kwargs['args'] = args[0]
+ if "args" not in kwargs:
+ kwargs["args"] = args[0]
self.subp_called.append(kwargs)
return
def _compress(self, text):
contents = BytesIO()
- gz_fh = gzip.GzipFile(mode='wb', fileobj=contents)
+ gz_fh = gzip.GzipFile(mode="wb", fileobj=contents)
gz_fh.write(text)
gz_fh.close()
return contents.getvalue()
def test_append_random(self):
cfg = {
- 'random_seed': {
- 'file': self._seed_file,
- 'data': 'tiny-tim-was-here',
+ "random_seed": {
+ "file": self._seed_file,
+ "data": "tiny-tim-was-here",
}
}
- cc_seed_random.handle('test', cfg, get_cloud('ubuntu'), LOG, [])
+ cc_seed_random.handle("test", cfg, get_cloud("ubuntu"), LOG, [])
contents = util.load_file(self._seed_file)
self.assertEqual("tiny-tim-was-here", contents)
def test_append_random_unknown_encoding(self):
data = self._compress(b"tiny-toe")
cfg = {
- 'random_seed': {
- 'file': self._seed_file,
- 'data': data,
- 'encoding': 'special_encoding',
+ "random_seed": {
+ "file": self._seed_file,
+ "data": data,
+ "encoding": "special_encoding",
}
}
- self.assertRaises(IOError, cc_seed_random.handle, 'test', cfg,
- get_cloud('ubuntu'), LOG, [])
+ self.assertRaises(
+ IOError,
+ cc_seed_random.handle,
+ "test",
+ cfg,
+ get_cloud("ubuntu"),
+ LOG,
+ [],
+ )
def test_append_random_gzip(self):
data = self._compress(b"tiny-toe")
cfg = {
- 'random_seed': {
- 'file': self._seed_file,
- 'data': data,
- 'encoding': 'gzip',
+ "random_seed": {
+ "file": self._seed_file,
+ "data": data,
+ "encoding": "gzip",
}
}
- cc_seed_random.handle('test', cfg, get_cloud('ubuntu'), LOG, [])
+ cc_seed_random.handle("test", cfg, get_cloud("ubuntu"), LOG, [])
contents = util.load_file(self._seed_file)
self.assertEqual("tiny-toe", contents)
def test_append_random_gz(self):
data = self._compress(b"big-toe")
cfg = {
- 'random_seed': {
- 'file': self._seed_file,
- 'data': data,
- 'encoding': 'gz',
+ "random_seed": {
+ "file": self._seed_file,
+ "data": data,
+ "encoding": "gz",
}
}
- cc_seed_random.handle('test', cfg, get_cloud('ubuntu'), LOG, [])
+ cc_seed_random.handle("test", cfg, get_cloud("ubuntu"), LOG, [])
contents = util.load_file(self._seed_file)
self.assertEqual("big-toe", contents)
def test_append_random_base64(self):
- data = util.b64e('bubbles')
+ data = util.b64e("bubbles")
cfg = {
- 'random_seed': {
- 'file': self._seed_file,
- 'data': data,
- 'encoding': 'base64',
+ "random_seed": {
+ "file": self._seed_file,
+ "data": data,
+ "encoding": "base64",
}
}
- cc_seed_random.handle('test', cfg, get_cloud('ubuntu'), LOG, [])
+ cc_seed_random.handle("test", cfg, get_cloud("ubuntu"), LOG, [])
contents = util.load_file(self._seed_file)
self.assertEqual("bubbles", contents)
def test_append_random_b64(self):
- data = util.b64e('kit-kat')
+ data = util.b64e("kit-kat")
cfg = {
- 'random_seed': {
- 'file': self._seed_file,
- 'data': data,
- 'encoding': 'b64',
+ "random_seed": {
+ "file": self._seed_file,
+ "data": data,
+ "encoding": "b64",
}
}
- cc_seed_random.handle('test', cfg, get_cloud('ubuntu'), LOG, [])
+ cc_seed_random.handle("test", cfg, get_cloud("ubuntu"), LOG, [])
contents = util.load_file(self._seed_file)
self.assertEqual("kit-kat", contents)
def test_append_random_metadata(self):
cfg = {
- 'random_seed': {
- 'file': self._seed_file,
- 'data': 'tiny-tim-was-here',
+ "random_seed": {
+ "file": self._seed_file,
+ "data": "tiny-tim-was-here",
}
}
- c = get_cloud('ubuntu', metadata={'random_seed': '-so-was-josh'})
- cc_seed_random.handle('test', cfg, c, LOG, [])
+ c = get_cloud("ubuntu", metadata={"random_seed": "-so-was-josh"})
+ cc_seed_random.handle("test", cfg, c, LOG, [])
contents = util.load_file(self._seed_file)
- self.assertEqual('tiny-tim-was-here-so-was-josh', contents)
+ self.assertEqual("tiny-tim-was-here-so-was-josh", contents)
def test_seed_command_provided_and_available(self):
- c = get_cloud('ubuntu')
- self.whichdata = {'pollinate': '/usr/bin/pollinate'}
- cfg = {'random_seed': {'command': ['pollinate', '-q']}}
- cc_seed_random.handle('test', cfg, c, LOG, [])
+ c = get_cloud("ubuntu")
+ self.whichdata = {"pollinate": "/usr/bin/pollinate"}
+ cfg = {"random_seed": {"command": ["pollinate", "-q"]}}
+ cc_seed_random.handle("test", cfg, c, LOG, [])
- subp_args = [f['args'] for f in self.subp_called]
- self.assertIn(['pollinate', '-q'], subp_args)
+ subp_args = [f["args"] for f in self.subp_called]
+ self.assertIn(["pollinate", "-q"], subp_args)
def test_seed_command_not_provided(self):
- c = get_cloud('ubuntu')
+ c = get_cloud("ubuntu")
self.whichdata = {}
- cc_seed_random.handle('test', {}, c, LOG, [])
+ cc_seed_random.handle("test", {}, c, LOG, [])
# subp should not have been called as which would say not available
self.assertFalse(self.subp_called)
def test_unavailable_seed_command_and_required_raises_error(self):
- c = get_cloud('ubuntu')
+ c = get_cloud("ubuntu")
self.whichdata = {}
- cfg = {'random_seed': {'command': ['THIS_NO_COMMAND'],
- 'command_required': True}}
- self.assertRaises(ValueError, cc_seed_random.handle,
- 'test', cfg, c, LOG, [])
+ cfg = {
+ "random_seed": {
+ "command": ["THIS_NO_COMMAND"],
+ "command_required": True,
+ }
+ }
+ self.assertRaises(
+ ValueError, cc_seed_random.handle, "test", cfg, c, LOG, []
+ )
def test_seed_command_and_required(self):
- c = get_cloud('ubuntu')
- self.whichdata = {'foo': 'foo'}
- cfg = {'random_seed': {'command_required': True, 'command': ['foo']}}
- cc_seed_random.handle('test', cfg, c, LOG, [])
+ c = get_cloud("ubuntu")
+ self.whichdata = {"foo": "foo"}
+ cfg = {"random_seed": {"command_required": True, "command": ["foo"]}}
+ cc_seed_random.handle("test", cfg, c, LOG, [])
- self.assertIn(['foo'], [f['args'] for f in self.subp_called])
+ self.assertIn(["foo"], [f["args"] for f in self.subp_called])
def test_file_in_environment_for_command(self):
- c = get_cloud('ubuntu')
- self.whichdata = {'foo': 'foo'}
- cfg = {'random_seed': {'command_required': True, 'command': ['foo'],
- 'file': self._seed_file}}
- cc_seed_random.handle('test', cfg, c, LOG, [])
+ c = get_cloud("ubuntu")
+ self.whichdata = {"foo": "foo"}
+ cfg = {
+ "random_seed": {
+ "command_required": True,
+ "command": ["foo"],
+ "file": self._seed_file,
+ }
+ }
+ cc_seed_random.handle("test", cfg, c, LOG, [])
# this just instists that the first time subp was called,
# RANDOM_SEED_FILE was in the environment set up correctly
- subp_env = [f['env'] for f in self.subp_called]
- self.assertEqual(subp_env[0].get('RANDOM_SEED_FILE'), self._seed_file)
+ subp_env = [f["env"] for f in self.subp_called]
+ self.assertEqual(subp_env[0].get("RANDOM_SEED_FILE"), self._seed_file)
def apply_patches(patches):
@@ -202,4 +217,5 @@ def apply_patches(patches):
ret.append((ref, name, orig))
return ret
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_set_hostname.py b/tests/unittests/config/test_cc_set_hostname.py
index b9a783a7..fd994c4e 100644
--- a/tests/unittests/config/test_cc_set_hostname.py
+++ b/tests/unittests/config/test_cc_set_hostname.py
@@ -1,15 +1,5 @@
# This file is part of cloud-init. See LICENSE file for license information.
-from cloudinit.config import cc_set_hostname
-
-from cloudinit import cloud
-from cloudinit import distros
-from cloudinit import helpers
-from cloudinit import util
-
-from tests.unittests import helpers as t_help
-
-from configobj import ConfigObj
import logging
import os
import shutil
@@ -17,6 +7,12 @@ import tempfile
from io import BytesIO
from unittest import mock
+from configobj import ConfigObj
+
+from cloudinit import cloud, distros, helpers, util
+from cloudinit.config import cc_set_hostname
+from tests.unittests import helpers as t_help
+
LOG = logging.getLogger(__name__)
@@ -27,181 +23,186 @@ class TestHostname(t_help.FilesystemMockingTestCase):
def setUp(self):
super(TestHostname, self).setUp()
self.tmp = tempfile.mkdtemp()
- util.ensure_dir(os.path.join(self.tmp, 'data'))
+ util.ensure_dir(os.path.join(self.tmp, "data"))
self.addCleanup(shutil.rmtree, self.tmp)
def _fetch_distro(self, kind, conf=None):
cls = distros.fetch(kind)
- paths = helpers.Paths({'cloud_dir': self.tmp})
+ paths = helpers.Paths({"cloud_dir": self.tmp})
conf = {} if conf is None else conf
return cls(kind, conf, paths)
def test_debian_write_hostname_prefer_fqdn(self):
cfg = {
- 'hostname': 'blah',
- 'prefer_fqdn_over_hostname': True,
- 'fqdn': 'blah.yahoo.com',
+ "hostname": "blah",
+ "prefer_fqdn_over_hostname": True,
+ "fqdn": "blah.yahoo.com",
}
- distro = self._fetch_distro('debian', cfg)
- paths = helpers.Paths({'cloud_dir': self.tmp})
+ distro = self._fetch_distro("debian", cfg)
+ paths = helpers.Paths({"cloud_dir": self.tmp})
ds = None
cc = cloud.Cloud(ds, paths, {}, distro, None)
self.patchUtils(self.tmp)
- cc_set_hostname.handle('cc_set_hostname',
- cfg, cc, LOG, [])
+ cc_set_hostname.handle("cc_set_hostname", cfg, cc, LOG, [])
contents = util.load_file("/etc/hostname")
- self.assertEqual('blah.yahoo.com', contents.strip())
+ self.assertEqual("blah.yahoo.com", contents.strip())
- @mock.patch('cloudinit.distros.Distro.uses_systemd', return_value=False)
+ @mock.patch("cloudinit.distros.Distro.uses_systemd", return_value=False)
def test_rhel_write_hostname_prefer_hostname(self, m_uses_systemd):
cfg = {
- 'hostname': 'blah',
- 'prefer_fqdn_over_hostname': False,
- 'fqdn': 'blah.yahoo.com',
+ "hostname": "blah",
+ "prefer_fqdn_over_hostname": False,
+ "fqdn": "blah.yahoo.com",
}
- distro = self._fetch_distro('rhel', cfg)
- paths = helpers.Paths({'cloud_dir': self.tmp})
+ distro = self._fetch_distro("rhel", cfg)
+ paths = helpers.Paths({"cloud_dir": self.tmp})
ds = None
cc = cloud.Cloud(ds, paths, {}, distro, None)
self.patchUtils(self.tmp)
- cc_set_hostname.handle('cc_set_hostname',
- cfg, cc, LOG, [])
+ cc_set_hostname.handle("cc_set_hostname", cfg, cc, LOG, [])
contents = util.load_file("/etc/sysconfig/network", decode=False)
n_cfg = ConfigObj(BytesIO(contents))
- self.assertEqual(
- {'HOSTNAME': 'blah'},
- dict(n_cfg))
+ self.assertEqual({"HOSTNAME": "blah"}, dict(n_cfg))
- @mock.patch('cloudinit.distros.Distro.uses_systemd', return_value=False)
+ @mock.patch("cloudinit.distros.Distro.uses_systemd", return_value=False)
def test_write_hostname_rhel(self, m_uses_systemd):
- cfg = {
- 'hostname': 'blah',
- 'fqdn': 'blah.blah.blah.yahoo.com'
- }
- distro = self._fetch_distro('rhel')
- paths = helpers.Paths({'cloud_dir': self.tmp})
+ cfg = {"hostname": "blah", "fqdn": "blah.blah.blah.yahoo.com"}
+ distro = self._fetch_distro("rhel")
+ paths = helpers.Paths({"cloud_dir": self.tmp})
ds = None
cc = cloud.Cloud(ds, paths, {}, distro, None)
self.patchUtils(self.tmp)
- cc_set_hostname.handle('cc_set_hostname',
- cfg, cc, LOG, [])
+ cc_set_hostname.handle("cc_set_hostname", cfg, cc, LOG, [])
contents = util.load_file("/etc/sysconfig/network", decode=False)
n_cfg = ConfigObj(BytesIO(contents))
- self.assertEqual(
- {'HOSTNAME': 'blah.blah.blah.yahoo.com'},
- dict(n_cfg))
+ self.assertEqual({"HOSTNAME": "blah.blah.blah.yahoo.com"}, dict(n_cfg))
def test_write_hostname_debian(self):
cfg = {
- 'hostname': 'blah',
- 'fqdn': 'blah.blah.blah.yahoo.com',
+ "hostname": "blah",
+ "fqdn": "blah.blah.blah.yahoo.com",
}
- distro = self._fetch_distro('debian')
- paths = helpers.Paths({'cloud_dir': self.tmp})
+ distro = self._fetch_distro("debian")
+ paths = helpers.Paths({"cloud_dir": self.tmp})
ds = None
cc = cloud.Cloud(ds, paths, {}, distro, None)
self.patchUtils(self.tmp)
- cc_set_hostname.handle('cc_set_hostname',
- cfg, cc, LOG, [])
+ cc_set_hostname.handle("cc_set_hostname", cfg, cc, LOG, [])
contents = util.load_file("/etc/hostname")
- self.assertEqual('blah', contents.strip())
+ self.assertEqual("blah", contents.strip())
- @mock.patch('cloudinit.distros.Distro.uses_systemd', return_value=False)
+ @mock.patch("cloudinit.distros.Distro.uses_systemd", return_value=False)
def test_write_hostname_sles(self, m_uses_systemd):
cfg = {
- 'hostname': 'blah.blah.blah.suse.com',
+ "hostname": "blah.blah.blah.suse.com",
}
- distro = self._fetch_distro('sles')
- paths = helpers.Paths({'cloud_dir': self.tmp})
+ distro = self._fetch_distro("sles")
+ paths = helpers.Paths({"cloud_dir": self.tmp})
ds = None
cc = cloud.Cloud(ds, paths, {}, distro, None)
self.patchUtils(self.tmp)
- cc_set_hostname.handle('cc_set_hostname', cfg, cc, LOG, [])
+ cc_set_hostname.handle("cc_set_hostname", cfg, cc, LOG, [])
contents = util.load_file(distro.hostname_conf_fn)
- self.assertEqual('blah', contents.strip())
+ self.assertEqual("blah", contents.strip())
- @mock.patch('cloudinit.distros.photon.subp.subp')
+ @mock.patch("cloudinit.distros.photon.subp.subp")
def test_photon_hostname(self, m_subp):
cfg1 = {
- 'hostname': 'photon',
- 'prefer_fqdn_over_hostname': True,
- 'fqdn': 'test1.vmware.com',
+ "hostname": "photon",
+ "prefer_fqdn_over_hostname": True,
+ "fqdn": "test1.vmware.com",
}
cfg2 = {
- 'hostname': 'photon',
- 'prefer_fqdn_over_hostname': False,
- 'fqdn': 'test2.vmware.com',
+ "hostname": "photon",
+ "prefer_fqdn_over_hostname": False,
+ "fqdn": "test2.vmware.com",
}
ds = None
m_subp.return_value = (None, None)
- distro = self._fetch_distro('photon', cfg1)
- paths = helpers.Paths({'cloud_dir': self.tmp})
+ distro = self._fetch_distro("photon", cfg1)
+ paths = helpers.Paths({"cloud_dir": self.tmp})
cc = cloud.Cloud(ds, paths, {}, distro, None)
for c in [cfg1, cfg2]:
- cc_set_hostname.handle('cc_set_hostname', c, cc, LOG, [])
+ cc_set_hostname.handle("cc_set_hostname", c, cc, LOG, [])
print("\n", m_subp.call_args_list)
- if c['prefer_fqdn_over_hostname']:
+ if c["prefer_fqdn_over_hostname"]:
assert [
- mock.call(['hostnamectl', 'set-hostname', c['fqdn']],
- capture=True)
+ mock.call(
+ ["hostnamectl", "set-hostname", c["fqdn"]],
+ capture=True,
+ )
] in m_subp.call_args_list
assert [
- mock.call(['hostnamectl', 'set-hostname', c['hostname']],
- capture=True)
+ mock.call(
+ ["hostnamectl", "set-hostname", c["hostname"]],
+ capture=True,
+ )
] not in m_subp.call_args_list
else:
assert [
- mock.call(['hostnamectl', 'set-hostname', c['hostname']],
- capture=True)
+ mock.call(
+ ["hostnamectl", "set-hostname", c["hostname"]],
+ capture=True,
+ )
] in m_subp.call_args_list
assert [
- mock.call(['hostnamectl', 'set-hostname', c['fqdn']],
- capture=True)
+ mock.call(
+ ["hostnamectl", "set-hostname", c["fqdn"]],
+ capture=True,
+ )
] not in m_subp.call_args_list
def test_multiple_calls_skips_unchanged_hostname(self):
"""Only new hostname or fqdn values will generate a hostname call."""
- distro = self._fetch_distro('debian')
- paths = helpers.Paths({'cloud_dir': self.tmp})
+ distro = self._fetch_distro("debian")
+ paths = helpers.Paths({"cloud_dir": self.tmp})
ds = None
cc = cloud.Cloud(ds, paths, {}, distro, None)
self.patchUtils(self.tmp)
cc_set_hostname.handle(
- 'cc_set_hostname', {'hostname': 'hostname1.me.com'}, cc, LOG, [])
+ "cc_set_hostname", {"hostname": "hostname1.me.com"}, cc, LOG, []
+ )
contents = util.load_file("/etc/hostname")
- self.assertEqual('hostname1', contents.strip())
+ self.assertEqual("hostname1", contents.strip())
cc_set_hostname.handle(
- 'cc_set_hostname', {'hostname': 'hostname1.me.com'}, cc, LOG, [])
+ "cc_set_hostname", {"hostname": "hostname1.me.com"}, cc, LOG, []
+ )
self.assertIn(
- 'DEBUG: No hostname changes. Skipping set-hostname\n',
- self.logs.getvalue())
+ "DEBUG: No hostname changes. Skipping set-hostname\n",
+ self.logs.getvalue(),
+ )
cc_set_hostname.handle(
- 'cc_set_hostname', {'hostname': 'hostname2.me.com'}, cc, LOG, [])
+ "cc_set_hostname", {"hostname": "hostname2.me.com"}, cc, LOG, []
+ )
contents = util.load_file("/etc/hostname")
- self.assertEqual('hostname2', contents.strip())
+ self.assertEqual("hostname2", contents.strip())
self.assertIn(
- 'Non-persistently setting the system hostname to hostname2',
- self.logs.getvalue())
+ "Non-persistently setting the system hostname to hostname2",
+ self.logs.getvalue(),
+ )
def test_error_on_distro_set_hostname_errors(self):
"""Raise SetHostnameError on exceptions from distro.set_hostname."""
- distro = self._fetch_distro('debian')
+ distro = self._fetch_distro("debian")
def set_hostname_error(hostname, fqdn):
raise Exception("OOPS on: %s" % fqdn)
distro.set_hostname = set_hostname_error
- paths = helpers.Paths({'cloud_dir': self.tmp})
+ paths = helpers.Paths({"cloud_dir": self.tmp})
ds = None
cc = cloud.Cloud(ds, paths, {}, distro, None)
self.patchUtils(self.tmp)
with self.assertRaises(cc_set_hostname.SetHostnameError) as ctx_mgr:
cc_set_hostname.handle(
- 'somename', {'hostname': 'hostname1.me.com'}, cc, LOG, [])
+ "somename", {"hostname": "hostname1.me.com"}, cc, LOG, []
+ )
self.assertEqual(
- 'Failed to set the hostname to hostname1.me.com (hostname1):'
- ' OOPS on: hostname1.me.com',
- str(ctx_mgr.exception))
+ "Failed to set the hostname to hostname1.me.com (hostname1):"
+ " OOPS on: hostname1.me.com",
+ str(ctx_mgr.exception),
+ )
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_set_passwords.py b/tests/unittests/config/test_cc_set_passwords.py
index 9bcd0439..bc81214b 100644
--- a/tests/unittests/config/test_cc_set_passwords.py
+++ b/tests/unittests/config/test_cc_set_passwords.py
@@ -2,9 +2,9 @@
from unittest import mock
+from cloudinit import util
from cloudinit.config import cc_set_passwords as setpass
from tests.unittests.helpers import CiTestCase
-from cloudinit import util
MODPATH = "cloudinit.config.cc_set_passwords."
@@ -16,27 +16,29 @@ class TestHandleSshPwauth(CiTestCase):
@mock.patch("cloudinit.distros.subp.subp")
def test_unknown_value_logs_warning(self, m_subp):
- cloud = self.tmp_cloud(distro='ubuntu')
+ cloud = self.tmp_cloud(distro="ubuntu")
setpass.handle_ssh_pwauth("floo", cloud.distro)
- self.assertIn("Unrecognized value: ssh_pwauth=floo",
- self.logs.getvalue())
+ self.assertIn(
+ "Unrecognized value: ssh_pwauth=floo", self.logs.getvalue()
+ )
m_subp.assert_not_called()
@mock.patch(MODPATH + "update_ssh_config", return_value=True)
@mock.patch("cloudinit.distros.subp.subp")
def test_systemctl_as_service_cmd(self, m_subp, m_update_ssh_config):
"""If systemctl in service cmd: systemctl restart name."""
- cloud = self.tmp_cloud(distro='ubuntu')
- cloud.distro.init_cmd = ['systemctl']
+ cloud = self.tmp_cloud(distro="ubuntu")
+ cloud.distro.init_cmd = ["systemctl"]
setpass.handle_ssh_pwauth(True, cloud.distro)
m_subp.assert_called_with(
- ["systemctl", "restart", "ssh"], capture=True)
+ ["systemctl", "restart", "ssh"], capture=True
+ )
@mock.patch(MODPATH + "update_ssh_config", return_value=False)
@mock.patch("cloudinit.distros.subp.subp")
def test_not_restarted_if_not_updated(self, m_subp, m_update_ssh_config):
"""If config is not updated, then no system restart should be done."""
- cloud = self.tmp_cloud(distro='ubuntu')
+ cloud = self.tmp_cloud(distro="ubuntu")
setpass.handle_ssh_pwauth(True, cloud.distro)
m_subp.assert_not_called()
self.assertIn("No need to restart SSH", self.logs.getvalue())
@@ -45,7 +47,7 @@ class TestHandleSshPwauth(CiTestCase):
@mock.patch("cloudinit.distros.subp.subp")
def test_unchanged_does_nothing(self, m_subp, m_update_ssh_config):
"""If 'unchanged', then no updates to config and no restart."""
- cloud = self.tmp_cloud(distro='ubuntu')
+ cloud = self.tmp_cloud(distro="ubuntu")
setpass.handle_ssh_pwauth("unchanged", cloud.distro)
m_update_ssh_config.assert_not_called()
m_subp.assert_not_called()
@@ -53,7 +55,7 @@ class TestHandleSshPwauth(CiTestCase):
@mock.patch("cloudinit.distros.subp.subp")
def test_valid_change_values(self, m_subp):
"""If value is a valid changen value, then update should be called."""
- cloud = self.tmp_cloud(distro='ubuntu')
+ cloud = self.tmp_cloud(distro="ubuntu")
upname = MODPATH + "update_ssh_config"
optname = "PasswordAuthentication"
for value in util.FALSE_STRINGS + util.TRUE_STRINGS:
@@ -71,52 +73,65 @@ class TestSetPasswordsHandle(CiTestCase):
def test_handle_on_empty_config(self, *args):
"""handle logs that no password has changed when config is empty."""
- cloud = self.tmp_cloud(distro='ubuntu')
+ cloud = self.tmp_cloud(distro="ubuntu")
setpass.handle(
- 'IGNORED', cfg={}, cloud=cloud, log=self.logger, args=[])
+ "IGNORED", cfg={}, cloud=cloud, log=self.logger, args=[]
+ )
self.assertEqual(
"DEBUG: Leaving SSH config 'PasswordAuthentication' unchanged. "
- 'ssh_pwauth=None\n',
- self.logs.getvalue())
+ "ssh_pwauth=None\n",
+ self.logs.getvalue(),
+ )
def test_handle_on_chpasswd_list_parses_common_hashes(self):
"""handle parses command password hashes."""
- cloud = self.tmp_cloud(distro='ubuntu')
+ cloud = self.tmp_cloud(distro="ubuntu")
valid_hashed_pwds = [
- 'root:$2y$10$8BQjxjVByHA/Ee.O1bCXtO8S7Y5WojbXWqnqYpUW.BrPx/'
- 'Dlew1Va',
- 'ubuntu:$6$5hOurLPO$naywm3Ce0UlmZg9gG2Fl9acWCVEoakMMC7dR52q'
- 'SDexZbrN9z8yHxhUM2b.sxpguSwOlbOQSW/HpXazGGx3oo1']
- cfg = {'chpasswd': {'list': valid_hashed_pwds}}
- with mock.patch.object(setpass, 'chpasswd') as chpasswd:
+ "root:$2y$10$8BQjxjVByHA/Ee.O1bCXtO8S7Y5WojbXWqnqYpUW.BrPx/"
+ "Dlew1Va",
+ "ubuntu:$6$5hOurLPO$naywm3Ce0UlmZg9gG2Fl9acWCVEoakMMC7dR52q"
+ "SDexZbrN9z8yHxhUM2b.sxpguSwOlbOQSW/HpXazGGx3oo1",
+ ]
+ cfg = {"chpasswd": {"list": valid_hashed_pwds}}
+ with mock.patch.object(setpass, "chpasswd") as chpasswd:
setpass.handle(
- 'IGNORED', cfg=cfg, cloud=cloud, log=self.logger, args=[])
+ "IGNORED", cfg=cfg, cloud=cloud, log=self.logger, args=[]
+ )
self.assertIn(
- 'DEBUG: Handling input for chpasswd as list.',
- self.logs.getvalue())
+ "DEBUG: Handling input for chpasswd as list.", self.logs.getvalue()
+ )
self.assertIn(
"DEBUG: Setting hashed password for ['root', 'ubuntu']",
- self.logs.getvalue())
- valid = '\n'.join(valid_hashed_pwds) + '\n'
+ self.logs.getvalue(),
+ )
+ valid = "\n".join(valid_hashed_pwds) + "\n"
called = chpasswd.call_args[0][1]
self.assertEqual(valid, called)
@mock.patch(MODPATH + "util.is_BSD")
@mock.patch(MODPATH + "subp.subp")
def test_bsd_calls_custom_pw_cmds_to_set_and_expire_passwords(
- self, m_subp, m_is_bsd):
+ self, m_subp, m_is_bsd
+ ):
"""BSD don't use chpasswd"""
m_is_bsd.return_value = True
- cloud = self.tmp_cloud(distro='freebsd')
- valid_pwds = ['ubuntu:passw0rd']
- cfg = {'chpasswd': {'list': valid_pwds}}
+ cloud = self.tmp_cloud(distro="freebsd")
+ valid_pwds = ["ubuntu:passw0rd"]
+ cfg = {"chpasswd": {"list": valid_pwds}}
setpass.handle(
- 'IGNORED', cfg=cfg, cloud=cloud, log=self.logger, args=[])
- self.assertEqual([
- mock.call(['pw', 'usermod', 'ubuntu', '-h', '0'], data='passw0rd',
- logstring="chpasswd for ubuntu"),
- mock.call(['pw', 'usermod', 'ubuntu', '-p', '01-Jan-1970'])],
- m_subp.call_args_list)
+ "IGNORED", cfg=cfg, cloud=cloud, log=self.logger, args=[]
+ )
+ self.assertEqual(
+ [
+ mock.call(
+ ["pw", "usermod", "ubuntu", "-h", "0"],
+ data="passw0rd",
+ logstring="chpasswd for ubuntu",
+ ),
+ mock.call(["pw", "usermod", "ubuntu", "-p", "01-Jan-1970"]),
+ ],
+ m_subp.call_args_list,
+ )
@mock.patch(MODPATH + "util.multi_log")
@mock.patch(MODPATH + "subp.subp")
@@ -124,29 +139,29 @@ class TestSetPasswordsHandle(CiTestCase):
self, m_subp, m_multi_log
):
"""handle parses command set random passwords."""
- cloud = self.tmp_cloud(distro='ubuntu')
- valid_random_pwds = [
- 'root:R',
- 'ubuntu:RANDOM']
- cfg = {'chpasswd': {'expire': 'false', 'list': valid_random_pwds}}
- with mock.patch.object(setpass, 'chpasswd') as chpasswd:
+ cloud = self.tmp_cloud(distro="ubuntu")
+ valid_random_pwds = ["root:R", "ubuntu:RANDOM"]
+ cfg = {"chpasswd": {"expire": "false", "list": valid_random_pwds}}
+ with mock.patch.object(setpass, "chpasswd") as chpasswd:
setpass.handle(
- 'IGNORED', cfg=cfg, cloud=cloud, log=self.logger, args=[])
+ "IGNORED", cfg=cfg, cloud=cloud, log=self.logger, args=[]
+ )
self.assertIn(
- 'DEBUG: Handling input for chpasswd as list.',
- self.logs.getvalue())
+ "DEBUG: Handling input for chpasswd as list.", self.logs.getvalue()
+ )
self.assertEqual(1, chpasswd.call_count)
passwords, _ = chpasswd.call_args
user_pass = {
user: password
- for user, password
- in (line.split(":") for line in passwords[1].splitlines())
+ for user, password in (
+ line.split(":") for line in passwords[1].splitlines()
+ )
}
self.assertEqual(1, m_multi_log.call_count)
self.assertEqual(
mock.call(mock.ANY, stderr=False, fallback_to_stdout=False),
- m_multi_log.call_args
+ m_multi_log.call_args,
)
self.assertEqual(set(["root", "ubuntu"]), set(user_pass.keys()))
diff --git a/tests/unittests/config/test_cc_snap.py b/tests/unittests/config/test_cc_snap.py
index e8113eca..f7e66ad2 100644
--- a/tests/unittests/config/test_cc_snap.py
+++ b/tests/unittests/config/test_cc_snap.py
@@ -3,14 +3,23 @@
import re
from io import StringIO
+from cloudinit import util
from cloudinit.config.cc_snap import (
- ASSERTIONS_FILE, add_assertions, handle, maybe_install_squashfuse,
- run_commands, schema)
+ ASSERTIONS_FILE,
+ add_assertions,
+ handle,
+ maybe_install_squashfuse,
+ run_commands,
+ schema,
+)
from cloudinit.config.schema import validate_cloudconfig_schema
-from cloudinit import util
from tests.unittests.helpers import (
- CiTestCase, SchemaTestCaseMixin, mock, wrap_and_call, skipUnlessJsonSchema)
-
+ CiTestCase,
+ SchemaTestCaseMixin,
+ mock,
+ skipUnlessJsonSchema,
+ wrap_and_call,
+)
SYSTEM_USER_ASSERTION = """\
type: system-user
@@ -92,11 +101,11 @@ class TestAddAssertions(CiTestCase):
super(TestAddAssertions, self).setUp()
self.tmp = self.tmp_dir()
- @mock.patch('cloudinit.config.cc_snap.subp.subp')
+ @mock.patch("cloudinit.config.cc_snap.subp.subp")
def test_add_assertions_on_empty_list(self, m_subp):
"""When provided with an empty list, add_assertions does nothing."""
add_assertions([])
- self.assertEqual('', self.logs.getvalue())
+ self.assertEqual("", self.logs.getvalue())
m_subp.assert_not_called()
def test_add_assertions_on_non_list_or_dict(self):
@@ -105,58 +114,72 @@ class TestAddAssertions(CiTestCase):
add_assertions(assertions="I'm Not Valid")
self.assertEqual(
"assertion parameter was not a list or dict: I'm Not Valid",
- str(context_manager.exception))
+ str(context_manager.exception),
+ )
- @mock.patch('cloudinit.config.cc_snap.subp.subp')
+ @mock.patch("cloudinit.config.cc_snap.subp.subp")
def test_add_assertions_adds_assertions_as_list(self, m_subp):
"""When provided with a list, add_assertions adds all assertions."""
self.assertEqual(
- ASSERTIONS_FILE, '/var/lib/cloud/instance/snapd.assertions')
- assert_file = self.tmp_path('snapd.assertions', dir=self.tmp)
+ ASSERTIONS_FILE, "/var/lib/cloud/instance/snapd.assertions"
+ )
+ assert_file = self.tmp_path("snapd.assertions", dir=self.tmp)
assertions = [SYSTEM_USER_ASSERTION, ACCOUNT_ASSERTION]
wrap_and_call(
- 'cloudinit.config.cc_snap',
- {'ASSERTIONS_FILE': {'new': assert_file}},
- add_assertions, assertions)
+ "cloudinit.config.cc_snap",
+ {"ASSERTIONS_FILE": {"new": assert_file}},
+ add_assertions,
+ assertions,
+ )
self.assertIn(
- 'Importing user-provided snap assertions', self.logs.getvalue())
- self.assertIn(
- 'sertions', self.logs.getvalue())
+ "Importing user-provided snap assertions", self.logs.getvalue()
+ )
+ self.assertIn("sertions", self.logs.getvalue())
self.assertEqual(
- [mock.call(['snap', 'ack', assert_file], capture=True)],
- m_subp.call_args_list)
- compare_file = self.tmp_path('comparison', dir=self.tmp)
- util.write_file(compare_file, '\n'.join(assertions).encode('utf-8'))
+ [mock.call(["snap", "ack", assert_file], capture=True)],
+ m_subp.call_args_list,
+ )
+ compare_file = self.tmp_path("comparison", dir=self.tmp)
+ util.write_file(compare_file, "\n".join(assertions).encode("utf-8"))
self.assertEqual(
- util.load_file(compare_file), util.load_file(assert_file))
+ util.load_file(compare_file), util.load_file(assert_file)
+ )
- @mock.patch('cloudinit.config.cc_snap.subp.subp')
+ @mock.patch("cloudinit.config.cc_snap.subp.subp")
def test_add_assertions_adds_assertions_as_dict(self, m_subp):
"""When provided with a dict, add_assertions adds all assertions."""
self.assertEqual(
- ASSERTIONS_FILE, '/var/lib/cloud/instance/snapd.assertions')
- assert_file = self.tmp_path('snapd.assertions', dir=self.tmp)
- assertions = {'00': SYSTEM_USER_ASSERTION, '01': ACCOUNT_ASSERTION}
+ ASSERTIONS_FILE, "/var/lib/cloud/instance/snapd.assertions"
+ )
+ assert_file = self.tmp_path("snapd.assertions", dir=self.tmp)
+ assertions = {"00": SYSTEM_USER_ASSERTION, "01": ACCOUNT_ASSERTION}
wrap_and_call(
- 'cloudinit.config.cc_snap',
- {'ASSERTIONS_FILE': {'new': assert_file}},
- add_assertions, assertions)
+ "cloudinit.config.cc_snap",
+ {"ASSERTIONS_FILE": {"new": assert_file}},
+ add_assertions,
+ assertions,
+ )
self.assertIn(
- 'Importing user-provided snap assertions', self.logs.getvalue())
+ "Importing user-provided snap assertions", self.logs.getvalue()
+ )
self.assertIn(
"DEBUG: Snap acking: ['type: system-user', 'authority-id: Lqv",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
self.assertIn(
"DEBUG: Snap acking: ['type: account-key', 'authority-id: canonic",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
self.assertEqual(
- [mock.call(['snap', 'ack', assert_file], capture=True)],
- m_subp.call_args_list)
- compare_file = self.tmp_path('comparison', dir=self.tmp)
- combined = '\n'.join(assertions.values())
- util.write_file(compare_file, combined.encode('utf-8'))
+ [mock.call(["snap", "ack", assert_file], capture=True)],
+ m_subp.call_args_list,
+ )
+ compare_file = self.tmp_path("comparison", dir=self.tmp)
+ combined = "\n".join(assertions.values())
+ util.write_file(compare_file, combined.encode("utf-8"))
self.assertEqual(
- util.load_file(compare_file), util.load_file(assert_file))
+ util.load_file(compare_file), util.load_file(assert_file)
+ )
class TestRunCommands(CiTestCase):
@@ -168,11 +191,11 @@ class TestRunCommands(CiTestCase):
super(TestRunCommands, self).setUp()
self.tmp = self.tmp_dir()
- @mock.patch('cloudinit.config.cc_snap.subp.subp')
+ @mock.patch("cloudinit.config.cc_snap.subp.subp")
def test_run_commands_on_empty_list(self, m_subp):
"""When provided with an empty list, run_commands does nothing."""
run_commands([])
- self.assertEqual('', self.logs.getvalue())
+ self.assertEqual("", self.logs.getvalue())
m_subp.assert_not_called()
def test_run_commands_on_non_list_or_dict(self):
@@ -181,68 +204,74 @@ class TestRunCommands(CiTestCase):
run_commands(commands="I'm Not Valid")
self.assertEqual(
"commands parameter was not a list or dict: I'm Not Valid",
- str(context_manager.exception))
+ str(context_manager.exception),
+ )
def test_run_command_logs_commands_and_exit_codes_to_stderr(self):
"""All exit codes are logged to stderr."""
- outfile = self.tmp_path('output.log', dir=self.tmp)
+ outfile = self.tmp_path("output.log", dir=self.tmp)
cmd1 = 'echo "HI" >> %s' % outfile
- cmd2 = 'bogus command'
+ cmd2 = "bogus command"
cmd3 = 'echo "MOM" >> %s' % outfile
commands = [cmd1, cmd2, cmd3]
- mock_path = 'cloudinit.config.cc_snap.sys.stderr'
+ mock_path = "cloudinit.config.cc_snap.sys.stderr"
with mock.patch(mock_path, new_callable=StringIO) as m_stderr:
with self.assertRaises(RuntimeError) as context_manager:
run_commands(commands=commands)
self.assertIsNotNone(
- re.search(r'bogus: (command )?not found',
- str(context_manager.exception)),
- msg='Expected bogus command not found')
- expected_stderr_log = '\n'.join([
- 'Begin run command: {cmd}'.format(cmd=cmd1),
- 'End run command: exit(0)',
- 'Begin run command: {cmd}'.format(cmd=cmd2),
- 'ERROR: End run command: exit(127)',
- 'Begin run command: {cmd}'.format(cmd=cmd3),
- 'End run command: exit(0)\n'])
+ re.search(
+ r"bogus: (command )?not found", str(context_manager.exception)
+ ),
+ msg="Expected bogus command not found",
+ )
+ expected_stderr_log = "\n".join(
+ [
+ "Begin run command: {cmd}".format(cmd=cmd1),
+ "End run command: exit(0)",
+ "Begin run command: {cmd}".format(cmd=cmd2),
+ "ERROR: End run command: exit(127)",
+ "Begin run command: {cmd}".format(cmd=cmd3),
+ "End run command: exit(0)\n",
+ ]
+ )
self.assertEqual(expected_stderr_log, m_stderr.getvalue())
def test_run_command_as_lists(self):
"""When commands are specified as a list, run them in order."""
- outfile = self.tmp_path('output.log', dir=self.tmp)
+ outfile = self.tmp_path("output.log", dir=self.tmp)
cmd1 = 'echo "HI" >> %s' % outfile
cmd2 = 'echo "MOM" >> %s' % outfile
commands = [cmd1, cmd2]
- mock_path = 'cloudinit.config.cc_snap.sys.stderr'
+ mock_path = "cloudinit.config.cc_snap.sys.stderr"
with mock.patch(mock_path, new_callable=StringIO):
run_commands(commands=commands)
self.assertIn(
- 'DEBUG: Running user-provided snap commands',
- self.logs.getvalue())
- self.assertEqual('HI\nMOM\n', util.load_file(outfile))
+ "DEBUG: Running user-provided snap commands", self.logs.getvalue()
+ )
+ self.assertEqual("HI\nMOM\n", util.load_file(outfile))
self.assertIn(
- 'WARNING: Non-snap commands in snap config:', self.logs.getvalue())
+ "WARNING: Non-snap commands in snap config:", self.logs.getvalue()
+ )
def test_run_command_dict_sorted_as_command_script(self):
"""When commands are a dict, sort them and run."""
- outfile = self.tmp_path('output.log', dir=self.tmp)
+ outfile = self.tmp_path("output.log", dir=self.tmp)
cmd1 = 'echo "HI" >> %s' % outfile
cmd2 = 'echo "MOM" >> %s' % outfile
- commands = {'02': cmd1, '01': cmd2}
- mock_path = 'cloudinit.config.cc_snap.sys.stderr'
+ commands = {"02": cmd1, "01": cmd2}
+ mock_path = "cloudinit.config.cc_snap.sys.stderr"
with mock.patch(mock_path, new_callable=StringIO):
run_commands(commands=commands)
- expected_messages = [
- 'DEBUG: Running user-provided snap commands']
+ expected_messages = ["DEBUG: Running user-provided snap commands"]
for message in expected_messages:
self.assertIn(message, self.logs.getvalue())
- self.assertEqual('MOM\nHI\n', util.load_file(outfile))
+ self.assertEqual("MOM\nHI\n", util.load_file(outfile))
@skipUnlessJsonSchema()
@@ -253,70 +282,72 @@ class TestSchema(CiTestCase, SchemaTestCaseMixin):
def test_schema_warns_on_snap_not_as_dict(self):
"""If the snap configuration is not a dict, emit a warning."""
- validate_cloudconfig_schema({'snap': 'wrong type'}, schema)
+ validate_cloudconfig_schema({"snap": "wrong type"}, schema)
self.assertEqual(
"WARNING: Invalid config:\nsnap: 'wrong type' is not of type"
" 'object'\n",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
- @mock.patch('cloudinit.config.cc_snap.run_commands')
+ @mock.patch("cloudinit.config.cc_snap.run_commands")
def test_schema_disallows_unknown_keys(self, _):
"""Unknown keys in the snap configuration emit warnings."""
validate_cloudconfig_schema(
- {'snap': {'commands': ['ls'], 'invalid-key': ''}}, schema)
+ {"snap": {"commands": ["ls"], "invalid-key": ""}}, schema
+ )
self.assertIn(
- 'WARNING: Invalid config:\nsnap: Additional properties are not'
+ "WARNING: Invalid config:\nsnap: Additional properties are not"
" allowed ('invalid-key' was unexpected)",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
def test_warn_schema_requires_either_commands_or_assertions(self):
"""Warn when snap configuration lacks both commands and assertions."""
- validate_cloudconfig_schema(
- {'snap': {}}, schema)
+ validate_cloudconfig_schema({"snap": {}}, schema)
self.assertIn(
- 'WARNING: Invalid config:\nsnap: {} does not have enough'
- ' properties',
- self.logs.getvalue())
+ "WARNING: Invalid config:\nsnap: {} does not have enough"
+ " properties",
+ self.logs.getvalue(),
+ )
- @mock.patch('cloudinit.config.cc_snap.run_commands')
+ @mock.patch("cloudinit.config.cc_snap.run_commands")
def test_warn_schema_commands_is_not_list_or_dict(self, _):
"""Warn when snap:commands config is not a list or dict."""
- validate_cloudconfig_schema(
- {'snap': {'commands': 'broken'}}, schema)
+ validate_cloudconfig_schema({"snap": {"commands": "broken"}}, schema)
self.assertEqual(
"WARNING: Invalid config:\nsnap.commands: 'broken' is not of type"
" 'object', 'array'\n",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
- @mock.patch('cloudinit.config.cc_snap.run_commands')
+ @mock.patch("cloudinit.config.cc_snap.run_commands")
def test_warn_schema_when_commands_is_empty(self, _):
"""Emit warnings when snap:commands is an empty list or dict."""
- validate_cloudconfig_schema(
- {'snap': {'commands': []}}, schema)
- validate_cloudconfig_schema(
- {'snap': {'commands': {}}}, schema)
+ validate_cloudconfig_schema({"snap": {"commands": []}}, schema)
+ validate_cloudconfig_schema({"snap": {"commands": {}}}, schema)
self.assertEqual(
"WARNING: Invalid config:\nsnap.commands: [] is too short\n"
"WARNING: Invalid config:\nsnap.commands: {} does not have enough"
" properties\n",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
- @mock.patch('cloudinit.config.cc_snap.run_commands')
+ @mock.patch("cloudinit.config.cc_snap.run_commands")
def test_schema_when_commands_are_list_or_dict(self, _):
"""No warnings when snap:commands are either a list or dict."""
+ validate_cloudconfig_schema({"snap": {"commands": ["valid"]}}, schema)
validate_cloudconfig_schema(
- {'snap': {'commands': ['valid']}}, schema)
- validate_cloudconfig_schema(
- {'snap': {'commands': {'01': 'also valid'}}}, schema)
- self.assertEqual('', self.logs.getvalue())
+ {"snap": {"commands": {"01": "also valid"}}}, schema
+ )
+ self.assertEqual("", self.logs.getvalue())
- @mock.patch('cloudinit.config.cc_snap.run_commands')
+ @mock.patch("cloudinit.config.cc_snap.run_commands")
def test_schema_when_commands_values_are_invalid_type(self, _):
"""Warnings when snap:commands values are invalid type (e.g. int)"""
+ validate_cloudconfig_schema({"snap": {"commands": [123]}}, schema)
validate_cloudconfig_schema(
- {'snap': {'commands': [123]}}, schema)
- validate_cloudconfig_schema(
- {'snap': {'commands': {'01': 123}}}, schema)
+ {"snap": {"commands": {"01": 123}}}, schema
+ )
self.assertEqual(
"WARNING: Invalid config:\n"
"snap.commands.0: 123 is not valid under any of the given"
@@ -324,15 +355,18 @@ class TestSchema(CiTestCase, SchemaTestCaseMixin):
"WARNING: Invalid config:\n"
"snap.commands.01: 123 is not valid under any of the given"
" schemas\n",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
- @mock.patch('cloudinit.config.cc_snap.run_commands')
+ @mock.patch("cloudinit.config.cc_snap.run_commands")
def test_schema_when_commands_list_values_are_invalid_type(self, _):
"""Warnings when snap:commands list values are wrong type (e.g. int)"""
validate_cloudconfig_schema(
- {'snap': {'commands': [["snap", "install", 123]]}}, schema)
+ {"snap": {"commands": [["snap", "install", 123]]}}, schema
+ )
validate_cloudconfig_schema(
- {'snap': {'commands': {'01': ["snap", "install", 123]}}}, schema)
+ {"snap": {"commands": {"01": ["snap", "install", 123]}}}, schema
+ )
self.assertEqual(
"WARNING: Invalid config:\n"
"snap.commands.0: ['snap', 'install', 123] is not valid under any"
@@ -340,77 +374,84 @@ class TestSchema(CiTestCase, SchemaTestCaseMixin):
"WARNING: Invalid config:\n"
"snap.commands.0: ['snap', 'install', 123] is not valid under any"
" of the given schemas\n",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
- @mock.patch('cloudinit.config.cc_snap.run_commands')
+ @mock.patch("cloudinit.config.cc_snap.run_commands")
def test_schema_when_assertions_values_are_invalid_type(self, _):
"""Warnings when snap:assertions values are invalid type (e.g. int)"""
+ validate_cloudconfig_schema({"snap": {"assertions": [123]}}, schema)
validate_cloudconfig_schema(
- {'snap': {'assertions': [123]}}, schema)
- validate_cloudconfig_schema(
- {'snap': {'assertions': {'01': 123}}}, schema)
+ {"snap": {"assertions": {"01": 123}}}, schema
+ )
self.assertEqual(
"WARNING: Invalid config:\n"
"snap.assertions.0: 123 is not of type 'string'\n"
"WARNING: Invalid config:\n"
"snap.assertions.01: 123 is not of type 'string'\n",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
- @mock.patch('cloudinit.config.cc_snap.add_assertions')
+ @mock.patch("cloudinit.config.cc_snap.add_assertions")
def test_warn_schema_assertions_is_not_list_or_dict(self, _):
"""Warn when snap:assertions config is not a list or dict."""
- validate_cloudconfig_schema(
- {'snap': {'assertions': 'broken'}}, schema)
+ validate_cloudconfig_schema({"snap": {"assertions": "broken"}}, schema)
self.assertEqual(
"WARNING: Invalid config:\nsnap.assertions: 'broken' is not of"
" type 'object', 'array'\n",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
- @mock.patch('cloudinit.config.cc_snap.add_assertions')
+ @mock.patch("cloudinit.config.cc_snap.add_assertions")
def test_warn_schema_when_assertions_is_empty(self, _):
"""Emit warnings when snap:assertions is an empty list or dict."""
- validate_cloudconfig_schema(
- {'snap': {'assertions': []}}, schema)
- validate_cloudconfig_schema(
- {'snap': {'assertions': {}}}, schema)
+ validate_cloudconfig_schema({"snap": {"assertions": []}}, schema)
+ validate_cloudconfig_schema({"snap": {"assertions": {}}}, schema)
self.assertEqual(
"WARNING: Invalid config:\nsnap.assertions: [] is too short\n"
"WARNING: Invalid config:\nsnap.assertions: {} does not have"
" enough properties\n",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
- @mock.patch('cloudinit.config.cc_snap.add_assertions')
+ @mock.patch("cloudinit.config.cc_snap.add_assertions")
def test_schema_when_assertions_are_list_or_dict(self, _):
"""No warnings when snap:assertions are a list or dict."""
validate_cloudconfig_schema(
- {'snap': {'assertions': ['valid']}}, schema)
+ {"snap": {"assertions": ["valid"]}}, schema
+ )
validate_cloudconfig_schema(
- {'snap': {'assertions': {'01': 'also valid'}}}, schema)
- self.assertEqual('', self.logs.getvalue())
+ {"snap": {"assertions": {"01": "also valid"}}}, schema
+ )
+ self.assertEqual("", self.logs.getvalue())
def test_duplicates_are_fine_array_array(self):
"""Duplicated commands array/array entries are allowed."""
self.assertSchemaValid(
- {'commands': [["echo", "bye"], ["echo", "bye"]]},
- "command entries can be duplicate.")
+ {"commands": [["echo", "bye"], ["echo", "bye"]]},
+ "command entries can be duplicate.",
+ )
def test_duplicates_are_fine_array_string(self):
"""Duplicated commands array/string entries are allowed."""
self.assertSchemaValid(
- {'commands': ["echo bye", "echo bye"]},
- "command entries can be duplicate.")
+ {"commands": ["echo bye", "echo bye"]},
+ "command entries can be duplicate.",
+ )
def test_duplicates_are_fine_dict_array(self):
"""Duplicated commands dict/array entries are allowed."""
self.assertSchemaValid(
- {'commands': {'00': ["echo", "bye"], '01': ["echo", "bye"]}},
- "command entries can be duplicate.")
+ {"commands": {"00": ["echo", "bye"], "01": ["echo", "bye"]}},
+ "command entries can be duplicate.",
+ )
def test_duplicates_are_fine_dict_string(self):
"""Duplicated commands dict/string entries are allowed."""
self.assertSchemaValid(
- {'commands': {'00': "echo bye", '01': "echo bye"}},
- "command entries can be duplicate.")
+ {"commands": {"00": "echo bye", "01": "echo bye"}},
+ "command entries can be duplicate.",
+ )
class TestHandle(CiTestCase):
@@ -421,92 +462,122 @@ class TestHandle(CiTestCase):
super(TestHandle, self).setUp()
self.tmp = self.tmp_dir()
- @mock.patch('cloudinit.config.cc_snap.run_commands')
- @mock.patch('cloudinit.config.cc_snap.add_assertions')
- @mock.patch('cloudinit.config.cc_snap.validate_cloudconfig_schema')
+ @mock.patch("cloudinit.config.cc_snap.run_commands")
+ @mock.patch("cloudinit.config.cc_snap.add_assertions")
+ @mock.patch("cloudinit.config.cc_snap.validate_cloudconfig_schema")
def test_handle_no_config(self, m_schema, m_add, m_run):
"""When no snap-related configuration is provided, nothing happens."""
cfg = {}
- handle('snap', cfg=cfg, cloud=None, log=self.logger, args=None)
+ handle("snap", cfg=cfg, cloud=None, log=self.logger, args=None)
self.assertIn(
"DEBUG: Skipping module named snap, no 'snap' key in config",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
m_schema.assert_not_called()
m_add.assert_not_called()
m_run.assert_not_called()
- @mock.patch('cloudinit.config.cc_snap.run_commands')
- @mock.patch('cloudinit.config.cc_snap.add_assertions')
- @mock.patch('cloudinit.config.cc_snap.maybe_install_squashfuse')
- def test_handle_skips_squashfuse_when_unconfigured(self, m_squash, m_add,
- m_run):
+ @mock.patch("cloudinit.config.cc_snap.run_commands")
+ @mock.patch("cloudinit.config.cc_snap.add_assertions")
+ @mock.patch("cloudinit.config.cc_snap.maybe_install_squashfuse")
+ def test_handle_skips_squashfuse_when_unconfigured(
+ self, m_squash, m_add, m_run
+ ):
"""When squashfuse_in_container is unset, don't attempt to install."""
handle(
- 'snap', cfg={'snap': {}}, cloud=None, log=self.logger, args=None)
+ "snap", cfg={"snap": {}}, cloud=None, log=self.logger, args=None
+ )
handle(
- 'snap', cfg={'snap': {'squashfuse_in_container': None}},
- cloud=None, log=self.logger, args=None)
+ "snap",
+ cfg={"snap": {"squashfuse_in_container": None}},
+ cloud=None,
+ log=self.logger,
+ args=None,
+ )
handle(
- 'snap', cfg={'snap': {'squashfuse_in_container': False}},
- cloud=None, log=self.logger, args=None)
+ "snap",
+ cfg={"snap": {"squashfuse_in_container": False}},
+ cloud=None,
+ log=self.logger,
+ args=None,
+ )
self.assertEqual([], m_squash.call_args_list) # No calls
# snap configuration missing assertions and commands will default to []
self.assertIn(mock.call([]), m_add.call_args_list)
self.assertIn(mock.call([]), m_run.call_args_list)
- @mock.patch('cloudinit.config.cc_snap.maybe_install_squashfuse')
+ @mock.patch("cloudinit.config.cc_snap.maybe_install_squashfuse")
def test_handle_tries_to_install_squashfuse(self, m_squash):
"""If squashfuse_in_container is True, try installing squashfuse."""
- cfg = {'snap': {'squashfuse_in_container': True}}
+ cfg = {"snap": {"squashfuse_in_container": True}}
mycloud = FakeCloud(None)
- handle('snap', cfg=cfg, cloud=mycloud, log=self.logger, args=None)
- self.assertEqual(
- [mock.call(mycloud)], m_squash.call_args_list)
+ handle("snap", cfg=cfg, cloud=mycloud, log=self.logger, args=None)
+ self.assertEqual([mock.call(mycloud)], m_squash.call_args_list)
def test_handle_runs_commands_provided(self):
"""If commands are specified as a list, run them."""
- outfile = self.tmp_path('output.log', dir=self.tmp)
+ outfile = self.tmp_path("output.log", dir=self.tmp)
cfg = {
- 'snap': {'commands': ['echo "HI" >> %s' % outfile,
- 'echo "MOM" >> %s' % outfile]}}
- mock_path = 'cloudinit.config.cc_snap.sys.stderr'
+ "snap": {
+ "commands": [
+ 'echo "HI" >> %s' % outfile,
+ 'echo "MOM" >> %s' % outfile,
+ ]
+ }
+ }
+ mock_path = "cloudinit.config.cc_snap.sys.stderr"
with self.allow_subp([CiTestCase.SUBP_SHELL_TRUE]):
with mock.patch(mock_path, new_callable=StringIO):
- handle('snap', cfg=cfg, cloud=None, log=self.logger, args=None)
+ handle("snap", cfg=cfg, cloud=None, log=self.logger, args=None)
- self.assertEqual('HI\nMOM\n', util.load_file(outfile))
+ self.assertEqual("HI\nMOM\n", util.load_file(outfile))
- @mock.patch('cloudinit.config.cc_snap.subp.subp')
+ @mock.patch("cloudinit.config.cc_snap.subp.subp")
def test_handle_adds_assertions(self, m_subp):
"""Any configured snap assertions are provided to add_assertions."""
- assert_file = self.tmp_path('snapd.assertions', dir=self.tmp)
- compare_file = self.tmp_path('comparison', dir=self.tmp)
+ assert_file = self.tmp_path("snapd.assertions", dir=self.tmp)
+ compare_file = self.tmp_path("comparison", dir=self.tmp)
cfg = {
- 'snap': {'assertions': [SYSTEM_USER_ASSERTION, ACCOUNT_ASSERTION]}}
+ "snap": {"assertions": [SYSTEM_USER_ASSERTION, ACCOUNT_ASSERTION]}
+ }
wrap_and_call(
- 'cloudinit.config.cc_snap',
- {'ASSERTIONS_FILE': {'new': assert_file}},
- handle, 'snap', cfg=cfg, cloud=None, log=self.logger, args=None)
- content = '\n'.join(cfg['snap']['assertions'])
- util.write_file(compare_file, content.encode('utf-8'))
+ "cloudinit.config.cc_snap",
+ {"ASSERTIONS_FILE": {"new": assert_file}},
+ handle,
+ "snap",
+ cfg=cfg,
+ cloud=None,
+ log=self.logger,
+ args=None,
+ )
+ content = "\n".join(cfg["snap"]["assertions"])
+ util.write_file(compare_file, content.encode("utf-8"))
self.assertEqual(
- util.load_file(compare_file), util.load_file(assert_file))
+ util.load_file(compare_file), util.load_file(assert_file)
+ )
- @mock.patch('cloudinit.config.cc_snap.subp.subp')
+ @mock.patch("cloudinit.config.cc_snap.subp.subp")
@skipUnlessJsonSchema()
def test_handle_validates_schema(self, m_subp):
"""Any provided configuration is runs validate_cloudconfig_schema."""
- assert_file = self.tmp_path('snapd.assertions', dir=self.tmp)
- cfg = {'snap': {'invalid': ''}} # Generates schema warning
+ assert_file = self.tmp_path("snapd.assertions", dir=self.tmp)
+ cfg = {"snap": {"invalid": ""}} # Generates schema warning
wrap_and_call(
- 'cloudinit.config.cc_snap',
- {'ASSERTIONS_FILE': {'new': assert_file}},
- handle, 'snap', cfg=cfg, cloud=None, log=self.logger, args=None)
+ "cloudinit.config.cc_snap",
+ {"ASSERTIONS_FILE": {"new": assert_file}},
+ handle,
+ "snap",
+ cfg=cfg,
+ cloud=None,
+ log=self.logger,
+ args=None,
+ )
self.assertEqual(
"WARNING: Invalid config:\nsnap: Additional properties are not"
" allowed ('invalid' was unexpected)\n",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
class TestMaybeInstallSquashFuse(CiTestCase):
@@ -517,48 +588,52 @@ class TestMaybeInstallSquashFuse(CiTestCase):
super(TestMaybeInstallSquashFuse, self).setUp()
self.tmp = self.tmp_dir()
- @mock.patch('cloudinit.config.cc_snap.util.is_container')
+ @mock.patch("cloudinit.config.cc_snap.util.is_container")
def test_maybe_install_squashfuse_skips_non_containers(self, m_container):
"""maybe_install_squashfuse does nothing when not on a container."""
m_container.return_value = False
maybe_install_squashfuse(cloud=FakeCloud(None))
self.assertEqual([mock.call()], m_container.call_args_list)
- self.assertEqual('', self.logs.getvalue())
+ self.assertEqual("", self.logs.getvalue())
- @mock.patch('cloudinit.config.cc_snap.util.is_container')
+ @mock.patch("cloudinit.config.cc_snap.util.is_container")
def test_maybe_install_squashfuse_raises_install_errors(self, m_container):
"""maybe_install_squashfuse logs and raises package install errors."""
m_container.return_value = True
distro = mock.MagicMock()
distro.update_package_sources.side_effect = RuntimeError(
- 'Some apt error')
+ "Some apt error"
+ )
with self.assertRaises(RuntimeError) as context_manager:
maybe_install_squashfuse(cloud=FakeCloud(distro))
- self.assertEqual('Some apt error', str(context_manager.exception))
- self.assertIn('Package update failed\nTraceback', self.logs.getvalue())
+ self.assertEqual("Some apt error", str(context_manager.exception))
+ self.assertIn("Package update failed\nTraceback", self.logs.getvalue())
- @mock.patch('cloudinit.config.cc_snap.util.is_container')
+ @mock.patch("cloudinit.config.cc_snap.util.is_container")
def test_maybe_install_squashfuse_raises_update_errors(self, m_container):
"""maybe_install_squashfuse logs and raises package update errors."""
m_container.return_value = True
distro = mock.MagicMock()
distro.update_package_sources.side_effect = RuntimeError(
- 'Some apt error')
+ "Some apt error"
+ )
with self.assertRaises(RuntimeError) as context_manager:
maybe_install_squashfuse(cloud=FakeCloud(distro))
- self.assertEqual('Some apt error', str(context_manager.exception))
- self.assertIn('Package update failed\nTraceback', self.logs.getvalue())
+ self.assertEqual("Some apt error", str(context_manager.exception))
+ self.assertIn("Package update failed\nTraceback", self.logs.getvalue())
- @mock.patch('cloudinit.config.cc_snap.util.is_container')
+ @mock.patch("cloudinit.config.cc_snap.util.is_container")
def test_maybe_install_squashfuse_happy_path(self, m_container):
"""maybe_install_squashfuse logs and raises package install errors."""
m_container.return_value = True
distro = mock.MagicMock() # No errors raised
maybe_install_squashfuse(cloud=FakeCloud(distro))
self.assertEqual(
- [mock.call()], distro.update_package_sources.call_args_list)
+ [mock.call()], distro.update_package_sources.call_args_list
+ )
self.assertEqual(
- [mock.call(['squashfuse'])],
- distro.install_packages.call_args_list)
+ [mock.call(["squashfuse"])], distro.install_packages.call_args_list
+ )
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_spacewalk.py b/tests/unittests/config/test_cc_spacewalk.py
index 96efccf0..e1f42968 100644
--- a/tests/unittests/config/test_cc_spacewalk.py
+++ b/tests/unittests/config/test_cc_spacewalk.py
@@ -1,21 +1,20 @@
# This file is part of cloud-init. See LICENSE file for license information.
-from cloudinit.config import cc_spacewalk
-from cloudinit import subp
-
-from tests.unittests import helpers
-
import logging
from unittest import mock
+from cloudinit import subp
+from cloudinit.config import cc_spacewalk
+from tests.unittests import helpers
+
LOG = logging.getLogger(__name__)
class TestSpacewalk(helpers.TestCase):
space_cfg = {
- 'spacewalk': {
- 'server': 'localhost',
- 'profile_name': 'test',
+ "spacewalk": {
+ "server": "localhost",
+ "profile_name": "test",
}
}
@@ -31,12 +30,19 @@ class TestSpacewalk(helpers.TestCase):
@mock.patch("cloudinit.config.cc_spacewalk.subp.subp")
def test_do_register(self, mock_subp):
- cc_spacewalk.do_register(**self.space_cfg['spacewalk'])
- mock_subp.assert_called_with([
- 'rhnreg_ks',
- '--serverUrl', 'https://localhost/XMLRPC',
- '--profilename', 'test',
- '--sslCACert', cc_spacewalk.def_ca_cert_path,
- ], capture=False)
+ cc_spacewalk.do_register(**self.space_cfg["spacewalk"])
+ mock_subp.assert_called_with(
+ [
+ "rhnreg_ks",
+ "--serverUrl",
+ "https://localhost/XMLRPC",
+ "--profilename",
+ "test",
+ "--sslCACert",
+ cc_spacewalk.def_ca_cert_path,
+ ],
+ capture=False,
+ )
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_ssh.py b/tests/unittests/config/test_cc_ssh.py
index ba179bbf..d66cc4cb 100644
--- a/tests/unittests/config/test_cc_ssh.py
+++ b/tests/unittests/config/test_cc_ssh.py
@@ -1,17 +1,18 @@
# This file is part of cloud-init. See LICENSE file for license information.
+import logging
import os.path
-from cloudinit.config import cc_ssh
from cloudinit import ssh_util
+from cloudinit.config import cc_ssh
from tests.unittests.helpers import CiTestCase, mock
-import logging
LOG = logging.getLogger(__name__)
MODPATH = "cloudinit.config.cc_ssh."
-KEY_NAMES_NO_DSA = [name for name in cc_ssh.GENERATE_KEY_NAMES
- if name not in 'dsa']
+KEY_NAMES_NO_DSA = [
+ name for name in cc_ssh.GENERATE_KEY_NAMES if name not in "dsa"
+]
@mock.patch(MODPATH + "ssh_util.setup_user_keys")
@@ -20,39 +21,45 @@ class TestHandleSsh(CiTestCase):
def _publish_hostkey_test_setup(self):
self.test_hostkeys = {
- 'dsa': ('ssh-dss', 'AAAAB3NzaC1kc3MAAACB'),
- 'ecdsa': ('ecdsa-sha2-nistp256', 'AAAAE2VjZ'),
- 'ed25519': ('ssh-ed25519', 'AAAAC3NzaC1lZDI'),
- 'rsa': ('ssh-rsa', 'AAAAB3NzaC1yc2EAAA'),
+ "dsa": ("ssh-dss", "AAAAB3NzaC1kc3MAAACB"),
+ "ecdsa": ("ecdsa-sha2-nistp256", "AAAAE2VjZ"),
+ "ed25519": ("ssh-ed25519", "AAAAC3NzaC1lZDI"),
+ "rsa": ("ssh-rsa", "AAAAB3NzaC1yc2EAAA"),
}
self.test_hostkey_files = []
hostkey_tmpdir = self.tmp_dir()
for key_type in cc_ssh.GENERATE_KEY_NAMES:
key_data = self.test_hostkeys[key_type]
- filename = 'ssh_host_%s_key.pub' % key_type
+ filename = "ssh_host_%s_key.pub" % key_type
filepath = os.path.join(hostkey_tmpdir, filename)
self.test_hostkey_files.append(filepath)
- with open(filepath, 'w') as f:
- f.write(' '.join(key_data))
+ with open(filepath, "w") as f:
+ f.write(" ".join(key_data))
- cc_ssh.KEY_FILE_TPL = os.path.join(hostkey_tmpdir, 'ssh_host_%s_key')
+ cc_ssh.KEY_FILE_TPL = os.path.join(hostkey_tmpdir, "ssh_host_%s_key")
def test_apply_credentials_with_user(self, m_setup_keys):
"""Apply keys for the given user and root."""
keys = ["key1"]
user = "clouduser"
cc_ssh.apply_credentials(keys, user, False, ssh_util.DISABLE_USER_OPTS)
- self.assertEqual([mock.call(set(keys), user),
- mock.call(set(keys), "root", options="")],
- m_setup_keys.call_args_list)
+ self.assertEqual(
+ [
+ mock.call(set(keys), user),
+ mock.call(set(keys), "root", options=""),
+ ],
+ m_setup_keys.call_args_list,
+ )
def test_apply_credentials_with_no_user(self, m_setup_keys):
"""Apply keys for root only."""
keys = ["key1"]
user = None
cc_ssh.apply_credentials(keys, user, False, ssh_util.DISABLE_USER_OPTS)
- self.assertEqual([mock.call(set(keys), "root", options="")],
- m_setup_keys.call_args_list)
+ self.assertEqual(
+ [mock.call(set(keys), "root", options="")],
+ m_setup_keys.call_args_list,
+ )
def test_apply_credentials_with_user_disable_root(self, m_setup_keys):
"""Apply keys for the given user and disable root ssh."""
@@ -62,9 +69,13 @@ class TestHandleSsh(CiTestCase):
cc_ssh.apply_credentials(keys, user, True, options)
options = options.replace("$USER", user)
options = options.replace("$DISABLE_USER", "root")
- self.assertEqual([mock.call(set(keys), user),
- mock.call(set(keys), "root", options=options)],
- m_setup_keys.call_args_list)
+ self.assertEqual(
+ [
+ mock.call(set(keys), user),
+ mock.call(set(keys), "root", options=options),
+ ],
+ m_setup_keys.call_args_list,
+ )
def test_apply_credentials_with_no_user_disable_root(self, m_setup_keys):
"""Apply keys no user and disable root ssh."""
@@ -74,14 +85,15 @@ class TestHandleSsh(CiTestCase):
cc_ssh.apply_credentials(keys, user, True, options)
options = options.replace("$USER", "NONE")
options = options.replace("$DISABLE_USER", "root")
- self.assertEqual([mock.call(set(keys), "root", options=options)],
- m_setup_keys.call_args_list)
+ self.assertEqual(
+ [mock.call(set(keys), "root", options=options)],
+ m_setup_keys.call_args_list,
+ )
@mock.patch(MODPATH + "glob.glob")
@mock.patch(MODPATH + "ug_util.normalize_users_groups")
@mock.patch(MODPATH + "os.path.exists")
- def test_handle_no_cfg(self, m_path_exists, m_nug,
- m_glob, m_setup_keys):
+ def test_handle_no_cfg(self, m_path_exists, m_nug, m_glob, m_setup_keys):
"""Test handle with no config ignores generating existing keyfiles."""
cfg = {}
keys = ["key1"]
@@ -90,28 +102,33 @@ class TestHandleSsh(CiTestCase):
m_path_exists.return_value = True
m_nug.return_value = ([], {})
cc_ssh.PUBLISH_HOST_KEYS = False
- cloud = self.tmp_cloud(
- distro='ubuntu', metadata={'public-keys': keys})
+ cloud = self.tmp_cloud(distro="ubuntu", metadata={"public-keys": keys})
cc_ssh.handle("name", cfg, cloud, LOG, None)
options = ssh_util.DISABLE_USER_OPTS.replace("$USER", "NONE")
options = options.replace("$DISABLE_USER", "root")
- m_glob.assert_called_once_with('/etc/ssh/ssh_host_*key*')
+ m_glob.assert_called_once_with("/etc/ssh/ssh_host_*key*")
self.assertIn(
- [mock.call('/etc/ssh/ssh_host_rsa_key'),
- mock.call('/etc/ssh/ssh_host_dsa_key'),
- mock.call('/etc/ssh/ssh_host_ecdsa_key'),
- mock.call('/etc/ssh/ssh_host_ed25519_key')],
- m_path_exists.call_args_list)
- self.assertEqual([mock.call(set(keys), "root", options=options)],
- m_setup_keys.call_args_list)
+ [
+ mock.call("/etc/ssh/ssh_host_rsa_key"),
+ mock.call("/etc/ssh/ssh_host_dsa_key"),
+ mock.call("/etc/ssh/ssh_host_ecdsa_key"),
+ mock.call("/etc/ssh/ssh_host_ed25519_key"),
+ ],
+ m_path_exists.call_args_list,
+ )
+ self.assertEqual(
+ [mock.call(set(keys), "root", options=options)],
+ m_setup_keys.call_args_list,
+ )
@mock.patch(MODPATH + "glob.glob")
@mock.patch(MODPATH + "ug_util.normalize_users_groups")
@mock.patch(MODPATH + "os.path.exists")
- def test_dont_allow_public_ssh_keys(self, m_path_exists, m_nug,
- m_glob, m_setup_keys):
+ def test_dont_allow_public_ssh_keys(
+ self, m_path_exists, m_nug, m_glob, m_setup_keys
+ ):
"""Test allow_public_ssh_keys=False ignores ssh public keys from
- platform.
+ platform.
"""
cfg = {"allow_public_ssh_keys": False}
keys = ["key1"]
@@ -120,21 +137,25 @@ class TestHandleSsh(CiTestCase):
# Mock os.path.exits to True to short-circuit the key writing logic
m_path_exists.return_value = True
m_nug.return_value = ({user: {"default": user}}, {})
- cloud = self.tmp_cloud(
- distro='ubuntu', metadata={'public-keys': keys})
+ cloud = self.tmp_cloud(distro="ubuntu", metadata={"public-keys": keys})
cc_ssh.handle("name", cfg, cloud, LOG, None)
options = ssh_util.DISABLE_USER_OPTS.replace("$USER", user)
options = options.replace("$DISABLE_USER", "root")
- self.assertEqual([mock.call(set(), user),
- mock.call(set(), "root", options=options)],
- m_setup_keys.call_args_list)
+ self.assertEqual(
+ [
+ mock.call(set(), user),
+ mock.call(set(), "root", options=options),
+ ],
+ m_setup_keys.call_args_list,
+ )
@mock.patch(MODPATH + "glob.glob")
@mock.patch(MODPATH + "ug_util.normalize_users_groups")
@mock.patch(MODPATH + "os.path.exists")
- def test_handle_no_cfg_and_default_root(self, m_path_exists, m_nug,
- m_glob, m_setup_keys):
+ def test_handle_no_cfg_and_default_root(
+ self, m_path_exists, m_nug, m_glob, m_setup_keys
+ ):
"""Test handle with no config and a default distro user."""
cfg = {}
keys = ["key1"]
@@ -143,21 +164,25 @@ class TestHandleSsh(CiTestCase):
# Mock os.path.exits to True to short-circuit the key writing logic
m_path_exists.return_value = True
m_nug.return_value = ({user: {"default": user}}, {})
- cloud = self.tmp_cloud(
- distro='ubuntu', metadata={'public-keys': keys})
+ cloud = self.tmp_cloud(distro="ubuntu", metadata={"public-keys": keys})
cc_ssh.handle("name", cfg, cloud, LOG, None)
options = ssh_util.DISABLE_USER_OPTS.replace("$USER", user)
options = options.replace("$DISABLE_USER", "root")
- self.assertEqual([mock.call(set(keys), user),
- mock.call(set(keys), "root", options=options)],
- m_setup_keys.call_args_list)
+ self.assertEqual(
+ [
+ mock.call(set(keys), user),
+ mock.call(set(keys), "root", options=options),
+ ],
+ m_setup_keys.call_args_list,
+ )
@mock.patch(MODPATH + "glob.glob")
@mock.patch(MODPATH + "ug_util.normalize_users_groups")
@mock.patch(MODPATH + "os.path.exists")
- def test_handle_cfg_with_explicit_disable_root(self, m_path_exists, m_nug,
- m_glob, m_setup_keys):
+ def test_handle_cfg_with_explicit_disable_root(
+ self, m_path_exists, m_nug, m_glob, m_setup_keys
+ ):
"""Test handle with explicit disable_root and a default distro user."""
# This test is identical to test_handle_no_cfg_and_default_root,
# except this uses an explicit cfg value
@@ -168,21 +193,25 @@ class TestHandleSsh(CiTestCase):
# Mock os.path.exits to True to short-circuit the key writing logic
m_path_exists.return_value = True
m_nug.return_value = ({user: {"default": user}}, {})
- cloud = self.tmp_cloud(
- distro='ubuntu', metadata={'public-keys': keys})
+ cloud = self.tmp_cloud(distro="ubuntu", metadata={"public-keys": keys})
cc_ssh.handle("name", cfg, cloud, LOG, None)
options = ssh_util.DISABLE_USER_OPTS.replace("$USER", user)
options = options.replace("$DISABLE_USER", "root")
- self.assertEqual([mock.call(set(keys), user),
- mock.call(set(keys), "root", options=options)],
- m_setup_keys.call_args_list)
+ self.assertEqual(
+ [
+ mock.call(set(keys), user),
+ mock.call(set(keys), "root", options=options),
+ ],
+ m_setup_keys.call_args_list,
+ )
@mock.patch(MODPATH + "glob.glob")
@mock.patch(MODPATH + "ug_util.normalize_users_groups")
@mock.patch(MODPATH + "os.path.exists")
- def test_handle_cfg_without_disable_root(self, m_path_exists, m_nug,
- m_glob, m_setup_keys):
+ def test_handle_cfg_without_disable_root(
+ self, m_path_exists, m_nug, m_glob, m_setup_keys
+ ):
"""Test handle with disable_root == False."""
# When disable_root == False, the ssh redirect for root is skipped
cfg = {"disable_root": False}
@@ -192,96 +221,111 @@ class TestHandleSsh(CiTestCase):
# Mock os.path.exits to True to short-circuit the key writing logic
m_path_exists.return_value = True
m_nug.return_value = ({user: {"default": user}}, {})
- cloud = self.tmp_cloud(
- distro='ubuntu', metadata={'public-keys': keys})
+ cloud = self.tmp_cloud(distro="ubuntu", metadata={"public-keys": keys})
cloud.get_public_ssh_keys = mock.Mock(return_value=keys)
cc_ssh.handle("name", cfg, cloud, LOG, None)
- self.assertEqual([mock.call(set(keys), user),
- mock.call(set(keys), "root", options="")],
- m_setup_keys.call_args_list)
+ self.assertEqual(
+ [
+ mock.call(set(keys), user),
+ mock.call(set(keys), "root", options=""),
+ ],
+ m_setup_keys.call_args_list,
+ )
@mock.patch(MODPATH + "glob.glob")
@mock.patch(MODPATH + "ug_util.normalize_users_groups")
@mock.patch(MODPATH + "os.path.exists")
def test_handle_publish_hostkeys_default(
- self, m_path_exists, m_nug, m_glob, m_setup_keys):
+ self, m_path_exists, m_nug, m_glob, m_setup_keys
+ ):
"""Test handle with various configs for ssh_publish_hostkeys."""
self._publish_hostkey_test_setup()
cc_ssh.PUBLISH_HOST_KEYS = True
keys = ["key1"]
user = "clouduser"
# Return no matching keys for first glob, test keys for second.
- m_glob.side_effect = iter([
- [],
- self.test_hostkey_files,
- ])
+ m_glob.side_effect = iter(
+ [
+ [],
+ self.test_hostkey_files,
+ ]
+ )
# Mock os.path.exits to True to short-circuit the key writing logic
m_path_exists.return_value = True
m_nug.return_value = ({user: {"default": user}}, {})
- cloud = self.tmp_cloud(
- distro='ubuntu', metadata={'public-keys': keys})
+ cloud = self.tmp_cloud(distro="ubuntu", metadata={"public-keys": keys})
cloud.datasource.publish_host_keys = mock.Mock()
cfg = {}
- expected_call = [self.test_hostkeys[key_type] for key_type
- in KEY_NAMES_NO_DSA]
+ expected_call = [
+ self.test_hostkeys[key_type] for key_type in KEY_NAMES_NO_DSA
+ ]
cc_ssh.handle("name", cfg, cloud, LOG, None)
- self.assertEqual([mock.call(expected_call)],
- cloud.datasource.publish_host_keys.call_args_list)
+ self.assertEqual(
+ [mock.call(expected_call)],
+ cloud.datasource.publish_host_keys.call_args_list,
+ )
@mock.patch(MODPATH + "glob.glob")
@mock.patch(MODPATH + "ug_util.normalize_users_groups")
@mock.patch(MODPATH + "os.path.exists")
def test_handle_publish_hostkeys_config_enable(
- self, m_path_exists, m_nug, m_glob, m_setup_keys):
+ self, m_path_exists, m_nug, m_glob, m_setup_keys
+ ):
"""Test handle with various configs for ssh_publish_hostkeys."""
self._publish_hostkey_test_setup()
cc_ssh.PUBLISH_HOST_KEYS = False
keys = ["key1"]
user = "clouduser"
# Return no matching keys for first glob, test keys for second.
- m_glob.side_effect = iter([
- [],
- self.test_hostkey_files,
- ])
+ m_glob.side_effect = iter(
+ [
+ [],
+ self.test_hostkey_files,
+ ]
+ )
# Mock os.path.exits to True to short-circuit the key writing logic
m_path_exists.return_value = True
m_nug.return_value = ({user: {"default": user}}, {})
- cloud = self.tmp_cloud(
- distro='ubuntu', metadata={'public-keys': keys})
+ cloud = self.tmp_cloud(distro="ubuntu", metadata={"public-keys": keys})
cloud.datasource.publish_host_keys = mock.Mock()
- cfg = {'ssh_publish_hostkeys': {'enabled': True}}
- expected_call = [self.test_hostkeys[key_type] for key_type
- in KEY_NAMES_NO_DSA]
+ cfg = {"ssh_publish_hostkeys": {"enabled": True}}
+ expected_call = [
+ self.test_hostkeys[key_type] for key_type in KEY_NAMES_NO_DSA
+ ]
cc_ssh.handle("name", cfg, cloud, LOG, None)
- self.assertEqual([mock.call(expected_call)],
- cloud.datasource.publish_host_keys.call_args_list)
+ self.assertEqual(
+ [mock.call(expected_call)],
+ cloud.datasource.publish_host_keys.call_args_list,
+ )
@mock.patch(MODPATH + "glob.glob")
@mock.patch(MODPATH + "ug_util.normalize_users_groups")
@mock.patch(MODPATH + "os.path.exists")
def test_handle_publish_hostkeys_config_disable(
- self, m_path_exists, m_nug, m_glob, m_setup_keys):
+ self, m_path_exists, m_nug, m_glob, m_setup_keys
+ ):
"""Test handle with various configs for ssh_publish_hostkeys."""
self._publish_hostkey_test_setup()
cc_ssh.PUBLISH_HOST_KEYS = True
keys = ["key1"]
user = "clouduser"
# Return no matching keys for first glob, test keys for second.
- m_glob.side_effect = iter([
- [],
- self.test_hostkey_files,
- ])
+ m_glob.side_effect = iter(
+ [
+ [],
+ self.test_hostkey_files,
+ ]
+ )
# Mock os.path.exits to True to short-circuit the key writing logic
m_path_exists.return_value = True
m_nug.return_value = ({user: {"default": user}}, {})
- cloud = self.tmp_cloud(
- distro='ubuntu', metadata={'public-keys': keys})
+ cloud = self.tmp_cloud(distro="ubuntu", metadata={"public-keys": keys})
cloud.datasource.publish_host_keys = mock.Mock()
- cfg = {'ssh_publish_hostkeys': {'enabled': False}}
+ cfg = {"ssh_publish_hostkeys": {"enabled": False}}
cc_ssh.handle("name", cfg, cloud, LOG, None)
self.assertFalse(cloud.datasource.publish_host_keys.call_args_list)
cloud.datasource.publish_host_keys.assert_not_called()
@@ -290,61 +334,75 @@ class TestHandleSsh(CiTestCase):
@mock.patch(MODPATH + "ug_util.normalize_users_groups")
@mock.patch(MODPATH + "os.path.exists")
def test_handle_publish_hostkeys_config_blacklist(
- self, m_path_exists, m_nug, m_glob, m_setup_keys):
+ self, m_path_exists, m_nug, m_glob, m_setup_keys
+ ):
"""Test handle with various configs for ssh_publish_hostkeys."""
self._publish_hostkey_test_setup()
cc_ssh.PUBLISH_HOST_KEYS = True
keys = ["key1"]
user = "clouduser"
# Return no matching keys for first glob, test keys for second.
- m_glob.side_effect = iter([
- [],
- self.test_hostkey_files,
- ])
+ m_glob.side_effect = iter(
+ [
+ [],
+ self.test_hostkey_files,
+ ]
+ )
# Mock os.path.exits to True to short-circuit the key writing logic
m_path_exists.return_value = True
m_nug.return_value = ({user: {"default": user}}, {})
- cloud = self.tmp_cloud(
- distro='ubuntu', metadata={'public-keys': keys})
+ cloud = self.tmp_cloud(distro="ubuntu", metadata={"public-keys": keys})
cloud.datasource.publish_host_keys = mock.Mock()
- cfg = {'ssh_publish_hostkeys': {'enabled': True,
- 'blacklist': ['dsa', 'rsa']}}
- expected_call = [self.test_hostkeys[key_type] for key_type
- in ['ecdsa', 'ed25519']]
+ cfg = {
+ "ssh_publish_hostkeys": {
+ "enabled": True,
+ "blacklist": ["dsa", "rsa"],
+ }
+ }
+ expected_call = [
+ self.test_hostkeys[key_type] for key_type in ["ecdsa", "ed25519"]
+ ]
cc_ssh.handle("name", cfg, cloud, LOG, None)
- self.assertEqual([mock.call(expected_call)],
- cloud.datasource.publish_host_keys.call_args_list)
+ self.assertEqual(
+ [mock.call(expected_call)],
+ cloud.datasource.publish_host_keys.call_args_list,
+ )
@mock.patch(MODPATH + "glob.glob")
@mock.patch(MODPATH + "ug_util.normalize_users_groups")
@mock.patch(MODPATH + "os.path.exists")
def test_handle_publish_hostkeys_empty_blacklist(
- self, m_path_exists, m_nug, m_glob, m_setup_keys):
+ self, m_path_exists, m_nug, m_glob, m_setup_keys
+ ):
"""Test handle with various configs for ssh_publish_hostkeys."""
self._publish_hostkey_test_setup()
cc_ssh.PUBLISH_HOST_KEYS = True
keys = ["key1"]
user = "clouduser"
# Return no matching keys for first glob, test keys for second.
- m_glob.side_effect = iter([
- [],
- self.test_hostkey_files,
- ])
+ m_glob.side_effect = iter(
+ [
+ [],
+ self.test_hostkey_files,
+ ]
+ )
# Mock os.path.exits to True to short-circuit the key writing logic
m_path_exists.return_value = True
m_nug.return_value = ({user: {"default": user}}, {})
- cloud = self.tmp_cloud(
- distro='ubuntu', metadata={'public-keys': keys})
+ cloud = self.tmp_cloud(distro="ubuntu", metadata={"public-keys": keys})
cloud.datasource.publish_host_keys = mock.Mock()
- cfg = {'ssh_publish_hostkeys': {'enabled': True,
- 'blacklist': []}}
- expected_call = [self.test_hostkeys[key_type] for key_type
- in cc_ssh.GENERATE_KEY_NAMES]
+ cfg = {"ssh_publish_hostkeys": {"enabled": True, "blacklist": []}}
+ expected_call = [
+ self.test_hostkeys[key_type]
+ for key_type in cc_ssh.GENERATE_KEY_NAMES
+ ]
cc_ssh.handle("name", cfg, cloud, LOG, None)
- self.assertEqual([mock.call(expected_call)],
- cloud.datasource.publish_host_keys.call_args_list)
+ self.assertEqual(
+ [mock.call(expected_call)],
+ cloud.datasource.publish_host_keys.call_args_list,
+ )
@mock.patch(MODPATH + "ug_util.normalize_users_groups")
@mock.patch(MODPATH + "util.write_file")
@@ -369,36 +427,40 @@ class TestHandleSsh(CiTestCase):
cfg["ssh_keys"][public_name] = public_value
cfg["ssh_keys"][cert_name] = cert_value
- expected_calls.extend([
- mock.call(
- '/etc/ssh/ssh_host_{}_key'.format(key_type),
- private_value,
- 384
- ),
- mock.call(
- '/etc/ssh/ssh_host_{}_key.pub'.format(key_type),
- public_value,
- 384
- ),
- mock.call(
- '/etc/ssh/ssh_host_{}_key-cert.pub'.format(key_type),
- cert_value,
- 384
- ),
- mock.call(
- '/etc/ssh/sshd_config',
- ('HostCertificate /etc/ssh/ssh_host_{}_key-cert.pub'
- '\n'.format(key_type)),
- preserve_mode=True
- )
- ])
+ expected_calls.extend(
+ [
+ mock.call(
+ "/etc/ssh/ssh_host_{}_key".format(key_type),
+ private_value,
+ 384,
+ ),
+ mock.call(
+ "/etc/ssh/ssh_host_{}_key.pub".format(key_type),
+ public_value,
+ 384,
+ ),
+ mock.call(
+ "/etc/ssh/ssh_host_{}_key-cert.pub".format(key_type),
+ cert_value,
+ 384,
+ ),
+ mock.call(
+ "/etc/ssh/sshd_config",
+ "HostCertificate /etc/ssh/ssh_host_{}_key-cert.pub"
+ "\n".format(key_type),
+ preserve_mode=True,
+ ),
+ ]
+ )
# Run the handler.
m_nug.return_value = ([], {})
- with mock.patch(MODPATH + 'ssh_util.parse_ssh_config',
- return_value=[]):
- cc_ssh.handle("name", cfg, self.tmp_cloud(distro='ubuntu'),
- LOG, None)
+ with mock.patch(
+ MODPATH + "ssh_util.parse_ssh_config", return_value=[]
+ ):
+ cc_ssh.handle(
+ "name", cfg, self.tmp_cloud(distro="ubuntu"), LOG, None
+ )
# Check that all expected output has been done.
for call_ in expected_calls:
diff --git a/tests/unittests/config/test_cc_timezone.py b/tests/unittests/config/test_cc_timezone.py
index fb6aab5f..f76397b7 100644
--- a/tests/unittests/config/test_cc_timezone.py
+++ b/tests/unittests/config/test_cc_timezone.py
@@ -4,19 +4,16 @@
#
# This file is part of cloud-init. See LICENSE file for license information.
-from cloudinit.config import cc_timezone
-
-from cloudinit import util
-
-
import logging
import shutil
import tempfile
-from configobj import ConfigObj
from io import BytesIO
-from tests.unittests import helpers as t_help
+from configobj import ConfigObj
+from cloudinit import util
+from cloudinit.config import cc_timezone
+from tests.unittests import helpers as t_help
from tests.unittests.util import get_cloud
LOG = logging.getLogger(__name__)
@@ -33,22 +30,24 @@ class TestTimezone(t_help.FilesystemMockingTestCase):
def test_set_timezone_sles(self):
cfg = {
- 'timezone': 'Tatooine/Bestine',
+ "timezone": "Tatooine/Bestine",
}
- cc = get_cloud('sles')
+ cc = get_cloud("sles")
# Create a dummy timezone file
- dummy_contents = '0123456789abcdefgh'
- util.write_file('/usr/share/zoneinfo/%s' % cfg['timezone'],
- dummy_contents)
+ dummy_contents = "0123456789abcdefgh"
+ util.write_file(
+ "/usr/share/zoneinfo/%s" % cfg["timezone"], dummy_contents
+ )
- cc_timezone.handle('cc_timezone', cfg, cc, LOG, [])
+ cc_timezone.handle("cc_timezone", cfg, cc, LOG, [])
- contents = util.load_file('/etc/sysconfig/clock', decode=False)
+ contents = util.load_file("/etc/sysconfig/clock", decode=False)
n_cfg = ConfigObj(BytesIO(contents))
- self.assertEqual({'TIMEZONE': cfg['timezone']}, dict(n_cfg))
+ self.assertEqual({"TIMEZONE": cfg["timezone"]}, dict(n_cfg))
- contents = util.load_file('/etc/localtime')
+ contents = util.load_file("/etc/localtime")
self.assertEqual(dummy_contents, contents.strip())
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_ubuntu_advantage.py b/tests/unittests/config/test_cc_ubuntu_advantage.py
index 8d0c9665..d7519a1b 100644
--- a/tests/unittests/config/test_cc_ubuntu_advantage.py
+++ b/tests/unittests/config/test_cc_ubuntu_advantage.py
@@ -1,15 +1,22 @@
# This file is part of cloud-init. See LICENSE file for license information.
+from cloudinit import subp
from cloudinit.config.cc_ubuntu_advantage import (
- configure_ua, handle, maybe_install_ua_tools, schema)
+ configure_ua,
+ handle,
+ maybe_install_ua_tools,
+ schema,
+)
from cloudinit.config.schema import validate_cloudconfig_schema
-from cloudinit import subp
from tests.unittests.helpers import (
- CiTestCase, mock, SchemaTestCaseMixin, skipUnlessJsonSchema)
-
+ CiTestCase,
+ SchemaTestCaseMixin,
+ mock,
+ skipUnlessJsonSchema,
+)
# Module path used in mocks
-MPATH = 'cloudinit.config.cc_ubuntu_advantage'
+MPATH = "cloudinit.config.cc_ubuntu_advantage"
class FakeCloud(object):
@@ -26,111 +33,131 @@ class TestConfigureUA(CiTestCase):
super(TestConfigureUA, self).setUp()
self.tmp = self.tmp_dir()
- @mock.patch('%s.subp.subp' % MPATH)
+ @mock.patch("%s.subp.subp" % MPATH)
def test_configure_ua_attach_error(self, m_subp):
"""Errors from ua attach command are raised."""
m_subp.side_effect = subp.ProcessExecutionError(
- 'Invalid token SomeToken')
+ "Invalid token SomeToken"
+ )
with self.assertRaises(RuntimeError) as context_manager:
- configure_ua(token='SomeToken')
+ configure_ua(token="SomeToken")
self.assertEqual(
- 'Failure attaching Ubuntu Advantage:\nUnexpected error while'
- ' running command.\nCommand: -\nExit code: -\nReason: -\n'
- 'Stdout: Invalid token SomeToken\nStderr: -',
- str(context_manager.exception))
+ "Failure attaching Ubuntu Advantage:\nUnexpected error while"
+ " running command.\nCommand: -\nExit code: -\nReason: -\n"
+ "Stdout: Invalid token SomeToken\nStderr: -",
+ str(context_manager.exception),
+ )
- @mock.patch('%s.subp.subp' % MPATH)
+ @mock.patch("%s.subp.subp" % MPATH)
def test_configure_ua_attach_with_token(self, m_subp):
"""When token is provided, attach the machine to ua using the token."""
- configure_ua(token='SomeToken')
- m_subp.assert_called_once_with(['ua', 'attach', 'SomeToken'])
+ configure_ua(token="SomeToken")
+ m_subp.assert_called_once_with(["ua", "attach", "SomeToken"])
self.assertEqual(
- 'DEBUG: Attaching to Ubuntu Advantage. ua attach SomeToken\n',
- self.logs.getvalue())
+ "DEBUG: Attaching to Ubuntu Advantage. ua attach SomeToken\n",
+ self.logs.getvalue(),
+ )
- @mock.patch('%s.subp.subp' % MPATH)
+ @mock.patch("%s.subp.subp" % MPATH)
def test_configure_ua_attach_on_service_error(self, m_subp):
"""all services should be enabled and then any failures raised"""
def fake_subp(cmd, capture=None):
- fail_cmds = [['ua', 'enable', svc] for svc in ['esm', 'cc']]
+ fail_cmds = [["ua", "enable", svc] for svc in ["esm", "cc"]]
if cmd in fail_cmds and capture:
svc = cmd[-1]
raise subp.ProcessExecutionError(
- 'Invalid {} credentials'.format(svc.upper()))
+ "Invalid {} credentials".format(svc.upper())
+ )
m_subp.side_effect = fake_subp
with self.assertRaises(RuntimeError) as context_manager:
- configure_ua(token='SomeToken', enable=['esm', 'cc', 'fips'])
+ configure_ua(token="SomeToken", enable=["esm", "cc", "fips"])
self.assertEqual(
m_subp.call_args_list,
- [mock.call(['ua', 'attach', 'SomeToken']),
- mock.call(['ua', 'enable', 'esm'], capture=True),
- mock.call(['ua', 'enable', 'cc'], capture=True),
- mock.call(['ua', 'enable', 'fips'], capture=True)])
+ [
+ mock.call(["ua", "attach", "SomeToken"]),
+ mock.call(["ua", "enable", "esm"], capture=True),
+ mock.call(["ua", "enable", "cc"], capture=True),
+ mock.call(["ua", "enable", "fips"], capture=True),
+ ],
+ )
self.assertIn(
'WARNING: Failure enabling "esm":\nUnexpected error'
- ' while running command.\nCommand: -\nExit code: -\nReason: -\n'
- 'Stdout: Invalid ESM credentials\nStderr: -\n',
- self.logs.getvalue())
+ " while running command.\nCommand: -\nExit code: -\nReason: -\n"
+ "Stdout: Invalid ESM credentials\nStderr: -\n",
+ self.logs.getvalue(),
+ )
self.assertIn(
'WARNING: Failure enabling "cc":\nUnexpected error'
- ' while running command.\nCommand: -\nExit code: -\nReason: -\n'
- 'Stdout: Invalid CC credentials\nStderr: -\n',
- self.logs.getvalue())
+ " while running command.\nCommand: -\nExit code: -\nReason: -\n"
+ "Stdout: Invalid CC credentials\nStderr: -\n",
+ self.logs.getvalue(),
+ )
self.assertEqual(
'Failure enabling Ubuntu Advantage service(s): "esm", "cc"',
- str(context_manager.exception))
+ str(context_manager.exception),
+ )
- @mock.patch('%s.subp.subp' % MPATH)
+ @mock.patch("%s.subp.subp" % MPATH)
def test_configure_ua_attach_with_empty_services(self, m_subp):
"""When services is an empty list, do not auto-enable attach."""
- configure_ua(token='SomeToken', enable=[])
- m_subp.assert_called_once_with(['ua', 'attach', 'SomeToken'])
+ configure_ua(token="SomeToken", enable=[])
+ m_subp.assert_called_once_with(["ua", "attach", "SomeToken"])
self.assertEqual(
- 'DEBUG: Attaching to Ubuntu Advantage. ua attach SomeToken\n',
- self.logs.getvalue())
+ "DEBUG: Attaching to Ubuntu Advantage. ua attach SomeToken\n",
+ self.logs.getvalue(),
+ )
- @mock.patch('%s.subp.subp' % MPATH)
+ @mock.patch("%s.subp.subp" % MPATH)
def test_configure_ua_attach_with_specific_services(self, m_subp):
"""When services a list, only enable specific services."""
- configure_ua(token='SomeToken', enable=['fips'])
+ configure_ua(token="SomeToken", enable=["fips"])
self.assertEqual(
m_subp.call_args_list,
- [mock.call(['ua', 'attach', 'SomeToken']),
- mock.call(['ua', 'enable', 'fips'], capture=True)])
+ [
+ mock.call(["ua", "attach", "SomeToken"]),
+ mock.call(["ua", "enable", "fips"], capture=True),
+ ],
+ )
self.assertEqual(
- 'DEBUG: Attaching to Ubuntu Advantage. ua attach SomeToken\n',
- self.logs.getvalue())
+ "DEBUG: Attaching to Ubuntu Advantage. ua attach SomeToken\n",
+ self.logs.getvalue(),
+ )
- @mock.patch('%s.maybe_install_ua_tools' % MPATH, mock.MagicMock())
- @mock.patch('%s.subp.subp' % MPATH)
+ @mock.patch("%s.maybe_install_ua_tools" % MPATH, mock.MagicMock())
+ @mock.patch("%s.subp.subp" % MPATH)
def test_configure_ua_attach_with_string_services(self, m_subp):
"""When services a string, treat as singleton list and warn"""
- configure_ua(token='SomeToken', enable='fips')
+ configure_ua(token="SomeToken", enable="fips")
self.assertEqual(
m_subp.call_args_list,
- [mock.call(['ua', 'attach', 'SomeToken']),
- mock.call(['ua', 'enable', 'fips'], capture=True)])
+ [
+ mock.call(["ua", "attach", "SomeToken"]),
+ mock.call(["ua", "enable", "fips"], capture=True),
+ ],
+ )
self.assertEqual(
- 'WARNING: ubuntu_advantage: enable should be a list, not a'
- ' string; treating as a single enable\n'
- 'DEBUG: Attaching to Ubuntu Advantage. ua attach SomeToken\n',
- self.logs.getvalue())
+ "WARNING: ubuntu_advantage: enable should be a list, not a"
+ " string; treating as a single enable\n"
+ "DEBUG: Attaching to Ubuntu Advantage. ua attach SomeToken\n",
+ self.logs.getvalue(),
+ )
- @mock.patch('%s.subp.subp' % MPATH)
+ @mock.patch("%s.subp.subp" % MPATH)
def test_configure_ua_attach_with_weird_services(self, m_subp):
"""When services not string or list, warn but still attach"""
- configure_ua(token='SomeToken', enable={'deffo': 'wont work'})
+ configure_ua(token="SomeToken", enable={"deffo": "wont work"})
self.assertEqual(
- m_subp.call_args_list,
- [mock.call(['ua', 'attach', 'SomeToken'])])
+ m_subp.call_args_list, [mock.call(["ua", "attach", "SomeToken"])]
+ )
self.assertEqual(
- 'WARNING: ubuntu_advantage: enable should be a list, not a'
- ' dict; skipping enabling services\n'
- 'DEBUG: Attaching to Ubuntu Advantage. ua attach SomeToken\n',
- self.logs.getvalue())
+ "WARNING: ubuntu_advantage: enable should be a list, not a"
+ " dict; skipping enabling services\n"
+ "DEBUG: Attaching to Ubuntu Advantage. ua attach SomeToken\n",
+ self.logs.getvalue(),
+ )
@skipUnlessJsonSchema()
@@ -139,49 +166,57 @@ class TestSchema(CiTestCase, SchemaTestCaseMixin):
with_logs = True
schema = schema
- @mock.patch('%s.maybe_install_ua_tools' % MPATH)
- @mock.patch('%s.configure_ua' % MPATH)
+ @mock.patch("%s.maybe_install_ua_tools" % MPATH)
+ @mock.patch("%s.configure_ua" % MPATH)
def test_schema_warns_on_ubuntu_advantage_not_dict(self, _cfg, _):
"""If ubuntu_advantage configuration is not a dict, emit a warning."""
- validate_cloudconfig_schema({'ubuntu_advantage': 'wrong type'}, schema)
+ validate_cloudconfig_schema({"ubuntu_advantage": "wrong type"}, schema)
self.assertEqual(
"WARNING: Invalid config:\nubuntu_advantage: 'wrong type' is not"
" of type 'object'\n",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
- @mock.patch('%s.maybe_install_ua_tools' % MPATH)
- @mock.patch('%s.configure_ua' % MPATH)
+ @mock.patch("%s.maybe_install_ua_tools" % MPATH)
+ @mock.patch("%s.configure_ua" % MPATH)
def test_schema_disallows_unknown_keys(self, _cfg, _):
"""Unknown keys in ubuntu_advantage configuration emit warnings."""
validate_cloudconfig_schema(
- {'ubuntu_advantage': {'token': 'winner', 'invalid-key': ''}},
- schema)
+ {"ubuntu_advantage": {"token": "winner", "invalid-key": ""}},
+ schema,
+ )
self.assertIn(
- 'WARNING: Invalid config:\nubuntu_advantage: Additional properties'
+ "WARNING: Invalid config:\nubuntu_advantage: Additional properties"
" are not allowed ('invalid-key' was unexpected)",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
- @mock.patch('%s.maybe_install_ua_tools' % MPATH)
- @mock.patch('%s.configure_ua' % MPATH)
+ @mock.patch("%s.maybe_install_ua_tools" % MPATH)
+ @mock.patch("%s.configure_ua" % MPATH)
def test_warn_schema_requires_token(self, _cfg, _):
"""Warn if ubuntu_advantage configuration lacks token."""
validate_cloudconfig_schema(
- {'ubuntu_advantage': {'enable': ['esm']}}, schema)
+ {"ubuntu_advantage": {"enable": ["esm"]}}, schema
+ )
self.assertEqual(
"WARNING: Invalid config:\nubuntu_advantage:"
- " 'token' is a required property\n", self.logs.getvalue())
+ " 'token' is a required property\n",
+ self.logs.getvalue(),
+ )
- @mock.patch('%s.maybe_install_ua_tools' % MPATH)
- @mock.patch('%s.configure_ua' % MPATH)
+ @mock.patch("%s.maybe_install_ua_tools" % MPATH)
+ @mock.patch("%s.configure_ua" % MPATH)
def test_warn_schema_services_is_not_list_or_dict(self, _cfg, _):
"""Warn when ubuntu_advantage:enable config is not a list."""
validate_cloudconfig_schema(
- {'ubuntu_advantage': {'enable': 'needslist'}}, schema)
+ {"ubuntu_advantage": {"enable": "needslist"}}, schema
+ )
self.assertEqual(
"WARNING: Invalid config:\nubuntu_advantage: 'token' is a"
" required property\nubuntu_advantage.enable: 'needslist'"
" is not of type 'array'\n",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
class TestHandle(CiTestCase):
@@ -192,89 +227,93 @@ class TestHandle(CiTestCase):
super(TestHandle, self).setUp()
self.tmp = self.tmp_dir()
- @mock.patch('%s.validate_cloudconfig_schema' % MPATH)
+ @mock.patch("%s.validate_cloudconfig_schema" % MPATH)
def test_handle_no_config(self, m_schema):
"""When no ua-related configuration is provided, nothing happens."""
cfg = {}
- handle('ua-test', cfg=cfg, cloud=None, log=self.logger, args=None)
+ handle("ua-test", cfg=cfg, cloud=None, log=self.logger, args=None)
self.assertIn(
"DEBUG: Skipping module named ua-test, no 'ubuntu_advantage'"
- ' configuration found',
- self.logs.getvalue())
+ " configuration found",
+ self.logs.getvalue(),
+ )
m_schema.assert_not_called()
- @mock.patch('%s.configure_ua' % MPATH)
- @mock.patch('%s.maybe_install_ua_tools' % MPATH)
+ @mock.patch("%s.configure_ua" % MPATH)
+ @mock.patch("%s.maybe_install_ua_tools" % MPATH)
def test_handle_tries_to_install_ubuntu_advantage_tools(
- self, m_install, m_cfg):
+ self, m_install, m_cfg
+ ):
"""If ubuntu_advantage is provided, try installing ua-tools package."""
- cfg = {'ubuntu_advantage': {'token': 'valid'}}
+ cfg = {"ubuntu_advantage": {"token": "valid"}}
mycloud = FakeCloud(None)
- handle('nomatter', cfg=cfg, cloud=mycloud, log=self.logger, args=None)
+ handle("nomatter", cfg=cfg, cloud=mycloud, log=self.logger, args=None)
m_install.assert_called_once_with(mycloud)
- @mock.patch('%s.configure_ua' % MPATH)
- @mock.patch('%s.maybe_install_ua_tools' % MPATH)
+ @mock.patch("%s.configure_ua" % MPATH)
+ @mock.patch("%s.maybe_install_ua_tools" % MPATH)
def test_handle_passes_credentials_and_services_to_configure_ua(
- self, m_install, m_configure_ua):
+ self, m_install, m_configure_ua
+ ):
"""All ubuntu_advantage config keys are passed to configure_ua."""
- cfg = {'ubuntu_advantage': {'token': 'token', 'enable': ['esm']}}
- handle('nomatter', cfg=cfg, cloud=None, log=self.logger, args=None)
- m_configure_ua.assert_called_once_with(
- token='token', enable=['esm'])
+ cfg = {"ubuntu_advantage": {"token": "token", "enable": ["esm"]}}
+ handle("nomatter", cfg=cfg, cloud=None, log=self.logger, args=None)
+ m_configure_ua.assert_called_once_with(token="token", enable=["esm"])
- @mock.patch('%s.maybe_install_ua_tools' % MPATH, mock.MagicMock())
- @mock.patch('%s.configure_ua' % MPATH)
+ @mock.patch("%s.maybe_install_ua_tools" % MPATH, mock.MagicMock())
+ @mock.patch("%s.configure_ua" % MPATH)
def test_handle_warns_on_deprecated_ubuntu_advantage_key_w_config(
- self, m_configure_ua):
+ self, m_configure_ua
+ ):
"""Warning when ubuntu-advantage key is present with new config"""
- cfg = {'ubuntu-advantage': {'token': 'token', 'enable': ['esm']}}
- handle('nomatter', cfg=cfg, cloud=None, log=self.logger, args=None)
+ cfg = {"ubuntu-advantage": {"token": "token", "enable": ["esm"]}}
+ handle("nomatter", cfg=cfg, cloud=None, log=self.logger, args=None)
self.assertEqual(
'WARNING: Deprecated configuration key "ubuntu-advantage"'
' provided. Expected underscore delimited "ubuntu_advantage";'
- ' will attempt to continue.',
- self.logs.getvalue().splitlines()[0])
- m_configure_ua.assert_called_once_with(
- token='token', enable=['esm'])
+ " will attempt to continue.",
+ self.logs.getvalue().splitlines()[0],
+ )
+ m_configure_ua.assert_called_once_with(token="token", enable=["esm"])
def test_handle_error_on_deprecated_commands_key_dashed(self):
"""Error when commands is present in ubuntu-advantage key."""
- cfg = {'ubuntu-advantage': {'commands': 'nogo'}}
+ cfg = {"ubuntu-advantage": {"commands": "nogo"}}
with self.assertRaises(RuntimeError) as context_manager:
- handle('nomatter', cfg=cfg, cloud=None, log=self.logger, args=None)
+ handle("nomatter", cfg=cfg, cloud=None, log=self.logger, args=None)
self.assertEqual(
'Deprecated configuration "ubuntu-advantage: commands" provided.'
' Expected "token"',
- str(context_manager.exception))
+ str(context_manager.exception),
+ )
def test_handle_error_on_deprecated_commands_key_underscored(self):
"""Error when commands is present in ubuntu_advantage key."""
- cfg = {'ubuntu_advantage': {'commands': 'nogo'}}
+ cfg = {"ubuntu_advantage": {"commands": "nogo"}}
with self.assertRaises(RuntimeError) as context_manager:
- handle('nomatter', cfg=cfg, cloud=None, log=self.logger, args=None)
+ handle("nomatter", cfg=cfg, cloud=None, log=self.logger, args=None)
self.assertEqual(
'Deprecated configuration "ubuntu-advantage: commands" provided.'
' Expected "token"',
- str(context_manager.exception))
+ str(context_manager.exception),
+ )
- @mock.patch('%s.maybe_install_ua_tools' % MPATH, mock.MagicMock())
- @mock.patch('%s.configure_ua' % MPATH)
- def test_handle_prefers_new_style_config(
- self, m_configure_ua):
+ @mock.patch("%s.maybe_install_ua_tools" % MPATH, mock.MagicMock())
+ @mock.patch("%s.configure_ua" % MPATH)
+ def test_handle_prefers_new_style_config(self, m_configure_ua):
"""ubuntu_advantage should be preferred over ubuntu-advantage"""
cfg = {
- 'ubuntu-advantage': {'token': 'nope', 'enable': ['wrong']},
- 'ubuntu_advantage': {'token': 'token', 'enable': ['esm']},
+ "ubuntu-advantage": {"token": "nope", "enable": ["wrong"]},
+ "ubuntu_advantage": {"token": "token", "enable": ["esm"]},
}
- handle('nomatter', cfg=cfg, cloud=None, log=self.logger, args=None)
+ handle("nomatter", cfg=cfg, cloud=None, log=self.logger, args=None)
self.assertEqual(
'WARNING: Deprecated configuration key "ubuntu-advantage"'
' provided. Expected underscore delimited "ubuntu_advantage";'
- ' will attempt to continue.',
- self.logs.getvalue().splitlines()[0])
- m_configure_ua.assert_called_once_with(
- token='token', enable=['esm'])
+ " will attempt to continue.",
+ self.logs.getvalue().splitlines()[0],
+ )
+ m_configure_ua.assert_called_once_with(token="token", enable=["esm"])
class TestMaybeInstallUATools(CiTestCase):
@@ -285,42 +324,46 @@ class TestMaybeInstallUATools(CiTestCase):
super(TestMaybeInstallUATools, self).setUp()
self.tmp = self.tmp_dir()
- @mock.patch('%s.subp.which' % MPATH)
+ @mock.patch("%s.subp.which" % MPATH)
def test_maybe_install_ua_tools_noop_when_ua_tools_present(self, m_which):
"""Do nothing if ubuntu-advantage-tools already exists."""
- m_which.return_value = '/usr/bin/ua' # already installed
+ m_which.return_value = "/usr/bin/ua" # already installed
distro = mock.MagicMock()
distro.update_package_sources.side_effect = RuntimeError(
- 'Some apt error')
+ "Some apt error"
+ )
maybe_install_ua_tools(cloud=FakeCloud(distro)) # No RuntimeError
- @mock.patch('%s.subp.which' % MPATH)
+ @mock.patch("%s.subp.which" % MPATH)
def test_maybe_install_ua_tools_raises_update_errors(self, m_which):
"""maybe_install_ua_tools logs and raises apt update errors."""
m_which.return_value = None
distro = mock.MagicMock()
distro.update_package_sources.side_effect = RuntimeError(
- 'Some apt error')
+ "Some apt error"
+ )
with self.assertRaises(RuntimeError) as context_manager:
maybe_install_ua_tools(cloud=FakeCloud(distro))
- self.assertEqual('Some apt error', str(context_manager.exception))
- self.assertIn('Package update failed\nTraceback', self.logs.getvalue())
+ self.assertEqual("Some apt error", str(context_manager.exception))
+ self.assertIn("Package update failed\nTraceback", self.logs.getvalue())
- @mock.patch('%s.subp.which' % MPATH)
+ @mock.patch("%s.subp.which" % MPATH)
def test_maybe_install_ua_raises_install_errors(self, m_which):
"""maybe_install_ua_tools logs and raises package install errors."""
m_which.return_value = None
distro = mock.MagicMock()
distro.update_package_sources.return_value = None
distro.install_packages.side_effect = RuntimeError(
- 'Some install error')
+ "Some install error"
+ )
with self.assertRaises(RuntimeError) as context_manager:
maybe_install_ua_tools(cloud=FakeCloud(distro))
- self.assertEqual('Some install error', str(context_manager.exception))
+ self.assertEqual("Some install error", str(context_manager.exception))
self.assertIn(
- 'Failed to install ubuntu-advantage-tools\n', self.logs.getvalue())
+ "Failed to install ubuntu-advantage-tools\n", self.logs.getvalue()
+ )
- @mock.patch('%s.subp.which' % MPATH)
+ @mock.patch("%s.subp.which" % MPATH)
def test_maybe_install_ua_tools_happy_path(self, m_which):
"""maybe_install_ua_tools installs ubuntu-advantage-tools."""
m_which.return_value = None
@@ -328,6 +371,8 @@ class TestMaybeInstallUATools(CiTestCase):
maybe_install_ua_tools(cloud=FakeCloud(distro))
distro.update_package_sources.assert_called_once_with()
distro.install_packages.assert_called_once_with(
- ['ubuntu-advantage-tools'])
+ ["ubuntu-advantage-tools"]
+ )
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_ubuntu_drivers.py b/tests/unittests/config/test_cc_ubuntu_drivers.py
index d341fbfd..4987492d 100644
--- a/tests/unittests/config/test_cc_ubuntu_drivers.py
+++ b/tests/unittests/config/test_cc_ubuntu_drivers.py
@@ -3,17 +3,20 @@
import copy
import os
-from tests.unittests.helpers import CiTestCase, skipUnlessJsonSchema, mock
-from cloudinit.config.schema import (
- SchemaValidationError, validate_cloudconfig_schema)
from cloudinit.config import cc_ubuntu_drivers as drivers
+from cloudinit.config.schema import (
+ SchemaValidationError,
+ validate_cloudconfig_schema,
+)
from cloudinit.subp import ProcessExecutionError
+from tests.unittests.helpers import CiTestCase, mock, skipUnlessJsonSchema
MPATH = "cloudinit.config.cc_ubuntu_drivers."
M_TMP_PATH = MPATH + "temp_utils.mkdtemp"
OLD_UBUNTU_DRIVERS_ERROR_STDERR = (
"ubuntu-drivers: error: argument <command>: invalid choice: 'install' "
- "(choose from 'list', 'autoinstall', 'devices', 'debug')\n")
+ "(choose from 'list', 'autoinstall', 'devices', 'debug')\n"
+)
# The tests in this module call helper methods which are decorated with
@@ -23,8 +26,8 @@ OLD_UBUNTU_DRIVERS_ERROR_STDERR = (
# disable it for the entire module:
# pylint: disable=no-value-for-parameter
-class AnyTempScriptAndDebconfFile(object):
+class AnyTempScriptAndDebconfFile(object):
def __init__(self, tmp_dir, debconf_file):
self.tmp_dir = tmp_dir
self.debconf_file = debconf_file
@@ -33,60 +36,68 @@ class AnyTempScriptAndDebconfFile(object):
if not len(cmd) == 2:
return False
script, debconf_file = cmd
- if bool(script.startswith(self.tmp_dir) and script.endswith('.sh')):
+ if bool(script.startswith(self.tmp_dir) and script.endswith(".sh")):
return debconf_file == self.debconf_file
return False
class TestUbuntuDrivers(CiTestCase):
- cfg_accepted = {'drivers': {'nvidia': {'license-accepted': True}}}
- install_gpgpu = ['ubuntu-drivers', 'install', '--gpgpu', 'nvidia']
+ cfg_accepted = {"drivers": {"nvidia": {"license-accepted": True}}}
+ install_gpgpu = ["ubuntu-drivers", "install", "--gpgpu", "nvidia"]
with_logs = True
@skipUnlessJsonSchema()
def test_schema_requires_boolean_for_license_accepted(self):
with self.assertRaisesRegex(
- SchemaValidationError, ".*license-accepted.*TRUE.*boolean"):
+ SchemaValidationError, ".*license-accepted.*TRUE.*boolean"
+ ):
validate_cloudconfig_schema(
- {'drivers': {'nvidia': {'license-accepted': "TRUE"}}},
- schema=drivers.schema, strict=True)
+ {"drivers": {"nvidia": {"license-accepted": "TRUE"}}},
+ schema=drivers.schema,
+ strict=True,
+ )
@mock.patch(M_TMP_PATH)
- @mock.patch(MPATH + "subp.subp", return_value=('', ''))
+ @mock.patch(MPATH + "subp.subp", return_value=("", ""))
@mock.patch(MPATH + "subp.which", return_value=False)
- def _assert_happy_path_taken(
- self, config, m_which, m_subp, m_tmp):
+ def _assert_happy_path_taken(self, config, m_which, m_subp, m_tmp):
"""Positive path test through handle. Package should be installed."""
tdir = self.tmp_dir()
- debconf_file = os.path.join(tdir, 'nvidia.template')
+ debconf_file = os.path.join(tdir, "nvidia.template")
m_tmp.return_value = tdir
myCloud = mock.MagicMock()
- drivers.handle('ubuntu_drivers', config, myCloud, None, None)
- self.assertEqual([mock.call(['ubuntu-drivers-common'])],
- myCloud.distro.install_packages.call_args_list)
+ drivers.handle("ubuntu_drivers", config, myCloud, None, None)
+ self.assertEqual(
+ [mock.call(["ubuntu-drivers-common"])],
+ myCloud.distro.install_packages.call_args_list,
+ )
self.assertEqual(
- [mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)),
- mock.call(self.install_gpgpu)],
- m_subp.call_args_list)
+ [
+ mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)),
+ mock.call(self.install_gpgpu),
+ ],
+ m_subp.call_args_list,
+ )
def test_handle_does_package_install(self):
self._assert_happy_path_taken(self.cfg_accepted)
def test_trueish_strings_are_considered_approval(self):
- for true_value in ['yes', 'true', 'on', '1']:
+ for true_value in ["yes", "true", "on", "1"]:
new_config = copy.deepcopy(self.cfg_accepted)
- new_config['drivers']['nvidia']['license-accepted'] = true_value
+ new_config["drivers"]["nvidia"]["license-accepted"] = true_value
self._assert_happy_path_taken(new_config)
@mock.patch(M_TMP_PATH)
@mock.patch(MPATH + "subp.subp")
@mock.patch(MPATH + "subp.which", return_value=False)
def test_handle_raises_error_if_no_drivers_found(
- self, m_which, m_subp, m_tmp):
+ self, m_which, m_subp, m_tmp
+ ):
"""If ubuntu-drivers doesn't install any drivers, raise an error."""
tdir = self.tmp_dir()
- debconf_file = os.path.join(tdir, 'nvidia.template')
+ debconf_file = os.path.join(tdir, "nvidia.template")
m_tmp.return_value = tdir
myCloud = mock.MagicMock()
@@ -94,84 +105,103 @@ class TestUbuntuDrivers(CiTestCase):
if cmd[0].startswith(tdir):
return
raise ProcessExecutionError(
- stdout='No drivers found for installation.\n', exit_code=1)
+ stdout="No drivers found for installation.\n", exit_code=1
+ )
+
m_subp.side_effect = fake_subp
with self.assertRaises(Exception):
drivers.handle(
- 'ubuntu_drivers', self.cfg_accepted, myCloud, None, None)
- self.assertEqual([mock.call(['ubuntu-drivers-common'])],
- myCloud.distro.install_packages.call_args_list)
+ "ubuntu_drivers", self.cfg_accepted, myCloud, None, None
+ )
self.assertEqual(
- [mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)),
- mock.call(self.install_gpgpu)],
- m_subp.call_args_list)
- self.assertIn('ubuntu-drivers found no drivers for installation',
- self.logs.getvalue())
-
- @mock.patch(MPATH + "subp.subp", return_value=('', ''))
+ [mock.call(["ubuntu-drivers-common"])],
+ myCloud.distro.install_packages.call_args_list,
+ )
+ self.assertEqual(
+ [
+ mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)),
+ mock.call(self.install_gpgpu),
+ ],
+ m_subp.call_args_list,
+ )
+ self.assertIn(
+ "ubuntu-drivers found no drivers for installation",
+ self.logs.getvalue(),
+ )
+
+ @mock.patch(MPATH + "subp.subp", return_value=("", ""))
@mock.patch(MPATH + "subp.which", return_value=False)
def _assert_inert_with_config(self, config, m_which, m_subp):
"""Helper to reduce repetition when testing negative cases"""
myCloud = mock.MagicMock()
- drivers.handle('ubuntu_drivers', config, myCloud, None, None)
+ drivers.handle("ubuntu_drivers", config, myCloud, None, None)
self.assertEqual(0, myCloud.distro.install_packages.call_count)
self.assertEqual(0, m_subp.call_count)
def test_handle_inert_if_license_not_accepted(self):
"""Ensure we don't do anything if the license is rejected."""
self._assert_inert_with_config(
- {'drivers': {'nvidia': {'license-accepted': False}}})
+ {"drivers": {"nvidia": {"license-accepted": False}}}
+ )
def test_handle_inert_if_garbage_in_license_field(self):
"""Ensure we don't do anything if unknown text is in license field."""
self._assert_inert_with_config(
- {'drivers': {'nvidia': {'license-accepted': 'garbage'}}})
+ {"drivers": {"nvidia": {"license-accepted": "garbage"}}}
+ )
def test_handle_inert_if_no_license_key(self):
"""Ensure we don't do anything if no license key."""
- self._assert_inert_with_config({'drivers': {'nvidia': {}}})
+ self._assert_inert_with_config({"drivers": {"nvidia": {}}})
def test_handle_inert_if_no_nvidia_key(self):
"""Ensure we don't do anything if other license accepted."""
self._assert_inert_with_config(
- {'drivers': {'acme': {'license-accepted': True}}})
+ {"drivers": {"acme": {"license-accepted": True}}}
+ )
def test_handle_inert_if_string_given(self):
"""Ensure we don't do anything if string refusal given."""
- for false_value in ['no', 'false', 'off', '0']:
+ for false_value in ["no", "false", "off", "0"]:
self._assert_inert_with_config(
- {'drivers': {'nvidia': {'license-accepted': false_value}}})
+ {"drivers": {"nvidia": {"license-accepted": false_value}}}
+ )
@mock.patch(MPATH + "install_drivers")
def test_handle_no_drivers_does_nothing(self, m_install_drivers):
"""If no 'drivers' key in the config, nothing should be done."""
myCloud = mock.MagicMock()
myLog = mock.MagicMock()
- drivers.handle('ubuntu_drivers', {'foo': 'bzr'}, myCloud, myLog, None)
- self.assertIn('Skipping module named',
- myLog.debug.call_args_list[0][0][0])
+ drivers.handle("ubuntu_drivers", {"foo": "bzr"}, myCloud, myLog, None)
+ self.assertIn(
+ "Skipping module named", myLog.debug.call_args_list[0][0][0]
+ )
self.assertEqual(0, m_install_drivers.call_count)
@mock.patch(M_TMP_PATH)
- @mock.patch(MPATH + "subp.subp", return_value=('', ''))
+ @mock.patch(MPATH + "subp.subp", return_value=("", ""))
@mock.patch(MPATH + "subp.which", return_value=True)
def test_install_drivers_no_install_if_present(
- self, m_which, m_subp, m_tmp):
+ self, m_which, m_subp, m_tmp
+ ):
"""If 'ubuntu-drivers' is present, no package install should occur."""
tdir = self.tmp_dir()
- debconf_file = os.path.join(tdir, 'nvidia.template')
+ debconf_file = os.path.join(tdir, "nvidia.template")
m_tmp.return_value = tdir
pkg_install = mock.MagicMock()
- drivers.install_drivers(self.cfg_accepted['drivers'],
- pkg_install_func=pkg_install)
+ drivers.install_drivers(
+ self.cfg_accepted["drivers"], pkg_install_func=pkg_install
+ )
self.assertEqual(0, pkg_install.call_count)
- self.assertEqual([mock.call('ubuntu-drivers')],
- m_which.call_args_list)
+ self.assertEqual([mock.call("ubuntu-drivers")], m_which.call_args_list)
self.assertEqual(
- [mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)),
- mock.call(self.install_gpgpu)],
- m_subp.call_args_list)
+ [
+ mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)),
+ mock.call(self.install_gpgpu),
+ ],
+ m_subp.call_args_list,
+ )
def test_install_drivers_rejects_invalid_config(self):
"""install_drivers should raise TypeError if not given a config dict"""
@@ -184,10 +214,11 @@ class TestUbuntuDrivers(CiTestCase):
@mock.patch(MPATH + "subp.subp")
@mock.patch(MPATH + "subp.which", return_value=False)
def test_install_drivers_handles_old_ubuntu_drivers_gracefully(
- self, m_which, m_subp, m_tmp):
+ self, m_which, m_subp, m_tmp
+ ):
"""Older ubuntu-drivers versions should emit message and raise error"""
tdir = self.tmp_dir()
- debconf_file = os.path.join(tdir, 'nvidia.template')
+ debconf_file = os.path.join(tdir, "nvidia.template")
m_tmp.return_value = tdir
myCloud = mock.MagicMock()
@@ -195,50 +226,68 @@ class TestUbuntuDrivers(CiTestCase):
if cmd[0].startswith(tdir):
return
raise ProcessExecutionError(
- stderr=OLD_UBUNTU_DRIVERS_ERROR_STDERR, exit_code=2)
+ stderr=OLD_UBUNTU_DRIVERS_ERROR_STDERR, exit_code=2
+ )
+
m_subp.side_effect = fake_subp
with self.assertRaises(Exception):
drivers.handle(
- 'ubuntu_drivers', self.cfg_accepted, myCloud, None, None)
- self.assertEqual([mock.call(['ubuntu-drivers-common'])],
- myCloud.distro.install_packages.call_args_list)
+ "ubuntu_drivers", self.cfg_accepted, myCloud, None, None
+ )
self.assertEqual(
- [mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)),
- mock.call(self.install_gpgpu)],
- m_subp.call_args_list)
- self.assertIn('WARNING: the available version of ubuntu-drivers is'
- ' too old to perform requested driver installation',
- self.logs.getvalue())
+ [mock.call(["ubuntu-drivers-common"])],
+ myCloud.distro.install_packages.call_args_list,
+ )
+ self.assertEqual(
+ [
+ mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)),
+ mock.call(self.install_gpgpu),
+ ],
+ m_subp.call_args_list,
+ )
+ self.assertIn(
+ "WARNING: the available version of ubuntu-drivers is"
+ " too old to perform requested driver installation",
+ self.logs.getvalue(),
+ )
# Sub-class TestUbuntuDrivers to run the same test cases, but with a version
class TestUbuntuDriversWithVersion(TestUbuntuDrivers):
cfg_accepted = {
- 'drivers': {'nvidia': {'license-accepted': True, 'version': '123'}}}
- install_gpgpu = ['ubuntu-drivers', 'install', '--gpgpu', 'nvidia:123']
+ "drivers": {"nvidia": {"license-accepted": True, "version": "123"}}
+ }
+ install_gpgpu = ["ubuntu-drivers", "install", "--gpgpu", "nvidia:123"]
@mock.patch(M_TMP_PATH)
- @mock.patch(MPATH + "subp.subp", return_value=('', ''))
+ @mock.patch(MPATH + "subp.subp", return_value=("", ""))
@mock.patch(MPATH + "subp.which", return_value=False)
def test_version_none_uses_latest(self, m_which, m_subp, m_tmp):
tdir = self.tmp_dir()
- debconf_file = os.path.join(tdir, 'nvidia.template')
+ debconf_file = os.path.join(tdir, "nvidia.template")
m_tmp.return_value = tdir
myCloud = mock.MagicMock()
version_none_cfg = {
- 'drivers': {'nvidia': {'license-accepted': True, 'version': None}}}
- drivers.handle(
- 'ubuntu_drivers', version_none_cfg, myCloud, None, None)
+ "drivers": {"nvidia": {"license-accepted": True, "version": None}}
+ }
+ drivers.handle("ubuntu_drivers", version_none_cfg, myCloud, None, None)
self.assertEqual(
- [mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)),
- mock.call(['ubuntu-drivers', 'install', '--gpgpu', 'nvidia'])],
- m_subp.call_args_list)
+ [
+ mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)),
+ mock.call(["ubuntu-drivers", "install", "--gpgpu", "nvidia"]),
+ ],
+ m_subp.call_args_list,
+ )
def test_specifying_a_version_doesnt_override_license_acceptance(self):
- self._assert_inert_with_config({
- 'drivers': {'nvidia': {'license-accepted': False,
- 'version': '123'}}
- })
+ self._assert_inert_with_config(
+ {
+ "drivers": {
+ "nvidia": {"license-accepted": False, "version": "123"}
+ }
+ }
+ )
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_update_etc_hosts.py b/tests/unittests/config/test_cc_update_etc_hosts.py
index 35ad6413..2bbc16f4 100644
--- a/tests/unittests/config/test_cc_update_etc_hosts.py
+++ b/tests/unittests/config/test_cc_update_etc_hosts.py
@@ -1,18 +1,13 @@
# This file is part of cloud-init. See LICENSE file for license information.
-from cloudinit.config import cc_update_etc_hosts
-
-from cloudinit import cloud
-from cloudinit import distros
-from cloudinit import helpers
-from cloudinit import util
-
-from tests.unittests import helpers as t_help
-
import logging
import os
import shutil
+from cloudinit import cloud, distros, helpers, util
+from cloudinit.config import cc_update_etc_hosts
+from tests.unittests import helpers as t_help
+
LOG = logging.getLogger(__name__)
@@ -28,46 +23,46 @@ class TestHostsFile(t_help.FilesystemMockingTestCase):
def test_write_etc_hosts_suse_localhost(self):
cfg = {
- 'manage_etc_hosts': 'localhost',
- 'hostname': 'cloud-init.test.us'
+ "manage_etc_hosts": "localhost",
+ "hostname": "cloud-init.test.us",
}
- os.makedirs('%s/etc/' % self.tmp)
- hosts_content = '192.168.1.1 blah.blah.us blah\n'
- fout = open('%s/etc/hosts' % self.tmp, 'w')
+ os.makedirs("%s/etc/" % self.tmp)
+ hosts_content = "192.168.1.1 blah.blah.us blah\n"
+ fout = open("%s/etc/hosts" % self.tmp, "w")
fout.write(hosts_content)
fout.close()
- distro = self._fetch_distro('sles')
- distro.hosts_fn = '%s/etc/hosts' % self.tmp
+ distro = self._fetch_distro("sles")
+ distro.hosts_fn = "%s/etc/hosts" % self.tmp
paths = helpers.Paths({})
ds = None
cc = cloud.Cloud(ds, paths, {}, distro, None)
self.patchUtils(self.tmp)
- cc_update_etc_hosts.handle('test', cfg, cc, LOG, [])
- contents = util.load_file('%s/etc/hosts' % self.tmp)
- if '127.0.1.1\tcloud-init.test.us\tcloud-init' not in contents:
- self.assertIsNone('No entry for 127.0.1.1 in etc/hosts')
- if '192.168.1.1\tblah.blah.us\tblah' not in contents:
- self.assertIsNone('Default etc/hosts content modified')
+ cc_update_etc_hosts.handle("test", cfg, cc, LOG, [])
+ contents = util.load_file("%s/etc/hosts" % self.tmp)
+ if "127.0.1.1\tcloud-init.test.us\tcloud-init" not in contents:
+ self.assertIsNone("No entry for 127.0.1.1 in etc/hosts")
+ if "192.168.1.1\tblah.blah.us\tblah" not in contents:
+ self.assertIsNone("Default etc/hosts content modified")
@t_help.skipUnlessJinja()
def test_write_etc_hosts_suse_template(self):
cfg = {
- 'manage_etc_hosts': 'template',
- 'hostname': 'cloud-init.test.us'
+ "manage_etc_hosts": "template",
+ "hostname": "cloud-init.test.us",
}
shutil.copytree(
- t_help.cloud_init_project_dir('templates'),
- '%s/etc/cloud/templates' % self.tmp,
+ t_help.cloud_init_project_dir("templates"),
+ "%s/etc/cloud/templates" % self.tmp,
)
- distro = self._fetch_distro('sles')
+ distro = self._fetch_distro("sles")
paths = helpers.Paths({})
- paths.template_tpl = '%s' % self.tmp + '/etc/cloud/templates/%s.tmpl'
+ paths.template_tpl = "%s" % self.tmp + "/etc/cloud/templates/%s.tmpl"
ds = None
cc = cloud.Cloud(ds, paths, {}, distro, None)
self.patchUtils(self.tmp)
- cc_update_etc_hosts.handle('test', cfg, cc, LOG, [])
- contents = util.load_file('%s/etc/hosts' % self.tmp)
- if '127.0.1.1 cloud-init.test.us cloud-init' not in contents:
- self.assertIsNone('No entry for 127.0.1.1 in etc/hosts')
- if '::1 cloud-init.test.us cloud-init' not in contents:
- self.assertIsNone('No entry for 127.0.0.1 in etc/hosts')
+ cc_update_etc_hosts.handle("test", cfg, cc, LOG, [])
+ contents = util.load_file("%s/etc/hosts" % self.tmp)
+ if "127.0.1.1 cloud-init.test.us cloud-init" not in contents:
+ self.assertIsNone("No entry for 127.0.1.1 in etc/hosts")
+ if "::1 cloud-init.test.us cloud-init" not in contents:
+ self.assertIsNone("No entry for 127.0.0.1 in etc/hosts")
diff --git a/tests/unittests/config/test_cc_users_groups.py b/tests/unittests/config/test_cc_users_groups.py
index 4ef844cb..0bd3c980 100644
--- a/tests/unittests/config/test_cc_users_groups.py
+++ b/tests/unittests/config/test_cc_users_groups.py
@@ -7,8 +7,8 @@ from tests.unittests.helpers import CiTestCase, mock
MODPATH = "cloudinit.config.cc_users_groups"
-@mock.patch('cloudinit.distros.ubuntu.Distro.create_group')
-@mock.patch('cloudinit.distros.ubuntu.Distro.create_user')
+@mock.patch("cloudinit.distros.ubuntu.Distro.create_group")
+@mock.patch("cloudinit.distros.ubuntu.Distro.create_user")
class TestHandleUsersGroups(CiTestCase):
"""Test cc_users_groups handling of config."""
@@ -18,58 +18,90 @@ class TestHandleUsersGroups(CiTestCase):
"""Test handle with no config will not create users or groups."""
cfg = {} # merged cloud-config
# System config defines a default user for the distro.
- sys_cfg = {'default_user': {'name': 'ubuntu', 'lock_passwd': True,
- 'groups': ['lxd', 'sudo'],
- 'shell': '/bin/bash'}}
+ sys_cfg = {
+ "default_user": {
+ "name": "ubuntu",
+ "lock_passwd": True,
+ "groups": ["lxd", "sudo"],
+ "shell": "/bin/bash",
+ }
+ }
metadata = {}
cloud = self.tmp_cloud(
- distro='ubuntu', sys_cfg=sys_cfg, metadata=metadata)
- cc_users_groups.handle('modulename', cfg, cloud, None, None)
+ distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata
+ )
+ cc_users_groups.handle("modulename", cfg, cloud, None, None)
m_user.assert_not_called()
m_group.assert_not_called()
def test_handle_users_in_cfg_calls_create_users(self, m_user, m_group):
"""When users in config, create users with distro.create_user."""
- cfg = {'users': ['default', {'name': 'me2'}]} # merged cloud-config
+ cfg = {"users": ["default", {"name": "me2"}]} # merged cloud-config
# System config defines a default user for the distro.
- sys_cfg = {'default_user': {'name': 'ubuntu', 'lock_passwd': True,
- 'groups': ['lxd', 'sudo'],
- 'shell': '/bin/bash'}}
+ sys_cfg = {
+ "default_user": {
+ "name": "ubuntu",
+ "lock_passwd": True,
+ "groups": ["lxd", "sudo"],
+ "shell": "/bin/bash",
+ }
+ }
metadata = {}
cloud = self.tmp_cloud(
- distro='ubuntu', sys_cfg=sys_cfg, metadata=metadata)
- cc_users_groups.handle('modulename', cfg, cloud, None, None)
+ distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata
+ )
+ cc_users_groups.handle("modulename", cfg, cloud, None, None)
self.assertCountEqual(
m_user.call_args_list,
- [mock.call('ubuntu', groups='lxd,sudo', lock_passwd=True,
- shell='/bin/bash'),
- mock.call('me2', default=False)])
+ [
+ mock.call(
+ "ubuntu",
+ groups="lxd,sudo",
+ lock_passwd=True,
+ shell="/bin/bash",
+ ),
+ mock.call("me2", default=False),
+ ],
+ )
m_group.assert_not_called()
- @mock.patch('cloudinit.distros.freebsd.Distro.create_group')
- @mock.patch('cloudinit.distros.freebsd.Distro.create_user')
+ @mock.patch("cloudinit.distros.freebsd.Distro.create_group")
+ @mock.patch("cloudinit.distros.freebsd.Distro.create_user")
def test_handle_users_in_cfg_calls_create_users_on_bsd(
- self,
- m_fbsd_user,
- m_fbsd_group,
- m_linux_user,
- m_linux_group,
+ self,
+ m_fbsd_user,
+ m_fbsd_group,
+ m_linux_user,
+ m_linux_group,
):
"""When users in config, create users with freebsd.create_user."""
- cfg = {'users': ['default', {'name': 'me2'}]} # merged cloud-config
+ cfg = {"users": ["default", {"name": "me2"}]} # merged cloud-config
# System config defines a default user for the distro.
- sys_cfg = {'default_user': {'name': 'freebsd', 'lock_passwd': True,
- 'groups': ['wheel'],
- 'shell': '/bin/tcsh'}}
+ sys_cfg = {
+ "default_user": {
+ "name": "freebsd",
+ "lock_passwd": True,
+ "groups": ["wheel"],
+ "shell": "/bin/tcsh",
+ }
+ }
metadata = {}
cloud = self.tmp_cloud(
- distro='freebsd', sys_cfg=sys_cfg, metadata=metadata)
- cc_users_groups.handle('modulename', cfg, cloud, None, None)
+ distro="freebsd", sys_cfg=sys_cfg, metadata=metadata
+ )
+ cc_users_groups.handle("modulename", cfg, cloud, None, None)
self.assertCountEqual(
m_fbsd_user.call_args_list,
- [mock.call('freebsd', groups='wheel', lock_passwd=True,
- shell='/bin/tcsh'),
- mock.call('me2', default=False)])
+ [
+ mock.call(
+ "freebsd",
+ groups="wheel",
+ lock_passwd=True,
+ shell="/bin/tcsh",
+ ),
+ mock.call("me2", default=False),
+ ],
+ )
m_fbsd_group.assert_not_called()
m_linux_group.assert_not_called()
m_linux_user.assert_not_called()
@@ -77,96 +109,160 @@ class TestHandleUsersGroups(CiTestCase):
def test_users_with_ssh_redirect_user_passes_keys(self, m_user, m_group):
"""When ssh_redirect_user is True pass default user and cloud keys."""
cfg = {
- 'users': ['default', {'name': 'me2', 'ssh_redirect_user': True}]}
+ "users": ["default", {"name": "me2", "ssh_redirect_user": True}]
+ }
# System config defines a default user for the distro.
- sys_cfg = {'default_user': {'name': 'ubuntu', 'lock_passwd': True,
- 'groups': ['lxd', 'sudo'],
- 'shell': '/bin/bash'}}
- metadata = {'public-keys': ['key1']}
+ sys_cfg = {
+ "default_user": {
+ "name": "ubuntu",
+ "lock_passwd": True,
+ "groups": ["lxd", "sudo"],
+ "shell": "/bin/bash",
+ }
+ }
+ metadata = {"public-keys": ["key1"]}
cloud = self.tmp_cloud(
- distro='ubuntu', sys_cfg=sys_cfg, metadata=metadata)
- cc_users_groups.handle('modulename', cfg, cloud, None, None)
+ distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata
+ )
+ cc_users_groups.handle("modulename", cfg, cloud, None, None)
self.assertCountEqual(
m_user.call_args_list,
- [mock.call('ubuntu', groups='lxd,sudo', lock_passwd=True,
- shell='/bin/bash'),
- mock.call('me2', cloud_public_ssh_keys=['key1'], default=False,
- ssh_redirect_user='ubuntu')])
+ [
+ mock.call(
+ "ubuntu",
+ groups="lxd,sudo",
+ lock_passwd=True,
+ shell="/bin/bash",
+ ),
+ mock.call(
+ "me2",
+ cloud_public_ssh_keys=["key1"],
+ default=False,
+ ssh_redirect_user="ubuntu",
+ ),
+ ],
+ )
m_group.assert_not_called()
def test_users_with_ssh_redirect_user_default_str(self, m_user, m_group):
"""When ssh_redirect_user is 'default' pass default username."""
cfg = {
- 'users': ['default', {'name': 'me2',
- 'ssh_redirect_user': 'default'}]}
+ "users": [
+ "default",
+ {"name": "me2", "ssh_redirect_user": "default"},
+ ]
+ }
# System config defines a default user for the distro.
- sys_cfg = {'default_user': {'name': 'ubuntu', 'lock_passwd': True,
- 'groups': ['lxd', 'sudo'],
- 'shell': '/bin/bash'}}
- metadata = {'public-keys': ['key1']}
+ sys_cfg = {
+ "default_user": {
+ "name": "ubuntu",
+ "lock_passwd": True,
+ "groups": ["lxd", "sudo"],
+ "shell": "/bin/bash",
+ }
+ }
+ metadata = {"public-keys": ["key1"]}
cloud = self.tmp_cloud(
- distro='ubuntu', sys_cfg=sys_cfg, metadata=metadata)
- cc_users_groups.handle('modulename', cfg, cloud, None, None)
+ distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata
+ )
+ cc_users_groups.handle("modulename", cfg, cloud, None, None)
self.assertCountEqual(
m_user.call_args_list,
- [mock.call('ubuntu', groups='lxd,sudo', lock_passwd=True,
- shell='/bin/bash'),
- mock.call('me2', cloud_public_ssh_keys=['key1'], default=False,
- ssh_redirect_user='ubuntu')])
+ [
+ mock.call(
+ "ubuntu",
+ groups="lxd,sudo",
+ lock_passwd=True,
+ shell="/bin/bash",
+ ),
+ mock.call(
+ "me2",
+ cloud_public_ssh_keys=["key1"],
+ default=False,
+ ssh_redirect_user="ubuntu",
+ ),
+ ],
+ )
m_group.assert_not_called()
def test_users_with_ssh_redirect_user_non_default(self, m_user, m_group):
"""Warn when ssh_redirect_user is not 'default'."""
cfg = {
- 'users': ['default', {'name': 'me2',
- 'ssh_redirect_user': 'snowflake'}]}
+ "users": [
+ "default",
+ {"name": "me2", "ssh_redirect_user": "snowflake"},
+ ]
+ }
# System config defines a default user for the distro.
- sys_cfg = {'default_user': {'name': 'ubuntu', 'lock_passwd': True,
- 'groups': ['lxd', 'sudo'],
- 'shell': '/bin/bash'}}
- metadata = {'public-keys': ['key1']}
+ sys_cfg = {
+ "default_user": {
+ "name": "ubuntu",
+ "lock_passwd": True,
+ "groups": ["lxd", "sudo"],
+ "shell": "/bin/bash",
+ }
+ }
+ metadata = {"public-keys": ["key1"]}
cloud = self.tmp_cloud(
- distro='ubuntu', sys_cfg=sys_cfg, metadata=metadata)
+ distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata
+ )
with self.assertRaises(ValueError) as context_manager:
- cc_users_groups.handle('modulename', cfg, cloud, None, None)
+ cc_users_groups.handle("modulename", cfg, cloud, None, None)
m_group.assert_not_called()
self.assertEqual(
- 'Not creating user me2. Invalid value of ssh_redirect_user:'
- ' snowflake. Expected values: true, default or false.',
- str(context_manager.exception))
+ "Not creating user me2. Invalid value of ssh_redirect_user:"
+ " snowflake. Expected values: true, default or false.",
+ str(context_manager.exception),
+ )
def test_users_with_ssh_redirect_user_default_false(self, m_user, m_group):
"""When unspecified ssh_redirect_user is false and not set up."""
- cfg = {'users': ['default', {'name': 'me2'}]}
+ cfg = {"users": ["default", {"name": "me2"}]}
# System config defines a default user for the distro.
- sys_cfg = {'default_user': {'name': 'ubuntu', 'lock_passwd': True,
- 'groups': ['lxd', 'sudo'],
- 'shell': '/bin/bash'}}
- metadata = {'public-keys': ['key1']}
+ sys_cfg = {
+ "default_user": {
+ "name": "ubuntu",
+ "lock_passwd": True,
+ "groups": ["lxd", "sudo"],
+ "shell": "/bin/bash",
+ }
+ }
+ metadata = {"public-keys": ["key1"]}
cloud = self.tmp_cloud(
- distro='ubuntu', sys_cfg=sys_cfg, metadata=metadata)
- cc_users_groups.handle('modulename', cfg, cloud, None, None)
+ distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata
+ )
+ cc_users_groups.handle("modulename", cfg, cloud, None, None)
self.assertCountEqual(
m_user.call_args_list,
- [mock.call('ubuntu', groups='lxd,sudo', lock_passwd=True,
- shell='/bin/bash'),
- mock.call('me2', default=False)])
+ [
+ mock.call(
+ "ubuntu",
+ groups="lxd,sudo",
+ lock_passwd=True,
+ shell="/bin/bash",
+ ),
+ mock.call("me2", default=False),
+ ],
+ )
m_group.assert_not_called()
def test_users_ssh_redirect_user_and_no_default(self, m_user, m_group):
"""Warn when ssh_redirect_user is True and no default user present."""
cfg = {
- 'users': ['default', {'name': 'me2', 'ssh_redirect_user': True}]}
+ "users": ["default", {"name": "me2", "ssh_redirect_user": True}]
+ }
# System config defines *no* default user for the distro.
sys_cfg = {}
metadata = {} # no public-keys defined
cloud = self.tmp_cloud(
- distro='ubuntu', sys_cfg=sys_cfg, metadata=metadata)
- cc_users_groups.handle('modulename', cfg, cloud, None, None)
- m_user.assert_called_once_with('me2', default=False)
+ distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata
+ )
+ cc_users_groups.handle("modulename", cfg, cloud, None, None)
+ m_user.assert_called_once_with("me2", default=False)
m_group.assert_not_called()
self.assertEqual(
- 'WARNING: Ignoring ssh_redirect_user: True for me2. No'
- ' default_user defined. Perhaps missing'
- ' cloud configuration users: [default, ..].\n',
- self.logs.getvalue())
+ "WARNING: Ignoring ssh_redirect_user: True for me2. No"
+ " default_user defined. Perhaps missing"
+ " cloud configuration users: [default, ..].\n",
+ self.logs.getvalue(),
+ )
diff --git a/tests/unittests/config/test_cc_write_files.py b/tests/unittests/config/test_cc_write_files.py
index 99248f74..7eea99d3 100644
--- a/tests/unittests/config/test_cc_write_files.py
+++ b/tests/unittests/config/test_cc_write_files.py
@@ -7,13 +7,15 @@ import io
import shutil
import tempfile
-from cloudinit.config.cc_write_files import (
- handle, decode_perms, write_files)
from cloudinit import log as logging
from cloudinit import util
-
+from cloudinit.config.cc_write_files import decode_perms, handle, write_files
from tests.unittests.helpers import (
- CiTestCase, FilesystemMockingTestCase, mock, skipUnlessJsonSchema)
+ CiTestCase,
+ FilesystemMockingTestCase,
+ mock,
+ skipUnlessJsonSchema,
+)
LOG = logging.getLogger(__name__)
@@ -35,73 +37,89 @@ write_files:
"""
YAML_CONTENT_EXPECTED = {
- '/usr/bin/hello': "#!/bin/sh\necho hello world\n",
- '/wark': "foobar\n",
- '/tmp/message': "hi mom line 1\nhi mom line 2\n",
+ "/usr/bin/hello": "#!/bin/sh\necho hello world\n",
+ "/wark": "foobar\n",
+ "/tmp/message": "hi mom line 1\nhi mom line 2\n",
}
VALID_SCHEMA = {
- 'write_files': [
- {'append': False, 'content': 'a', 'encoding': 'gzip', 'owner': 'jeff',
- 'path': '/some', 'permissions': '0777'}
+ "write_files": [
+ {
+ "append": False,
+ "content": "a",
+ "encoding": "gzip",
+ "owner": "jeff",
+ "path": "/some",
+ "permissions": "0777",
+ }
]
}
INVALID_SCHEMA = { # Dropped required path key
- 'write_files': [
- {'append': False, 'content': 'a', 'encoding': 'gzip', 'owner': 'jeff',
- 'permissions': '0777'}
+ "write_files": [
+ {
+ "append": False,
+ "content": "a",
+ "encoding": "gzip",
+ "owner": "jeff",
+ "permissions": "0777",
+ }
]
}
@skipUnlessJsonSchema()
-@mock.patch('cloudinit.config.cc_write_files.write_files')
+@mock.patch("cloudinit.config.cc_write_files.write_files")
class TestWriteFilesSchema(CiTestCase):
with_logs = True
def test_schema_validation_warns_missing_path(self, m_write_files):
"""The only required file item property is 'path'."""
- cc = self.tmp_cloud('ubuntu')
- valid_config = {'write_files': [{'path': '/some/path'}]}
- handle('cc_write_file', valid_config, cc, LOG, [])
- self.assertNotIn('Invalid config:', self.logs.getvalue())
- handle('cc_write_file', INVALID_SCHEMA, cc, LOG, [])
- self.assertIn('Invalid config:', self.logs.getvalue())
+ cc = self.tmp_cloud("ubuntu")
+ valid_config = {"write_files": [{"path": "/some/path"}]}
+ handle("cc_write_file", valid_config, cc, LOG, [])
+ self.assertNotIn("Invalid config:", self.logs.getvalue())
+ handle("cc_write_file", INVALID_SCHEMA, cc, LOG, [])
+ self.assertIn("Invalid config:", self.logs.getvalue())
self.assertIn("'path' is a required property", self.logs.getvalue())
def test_schema_validation_warns_non_string_type_for_files(
- self, m_write_files):
+ self, m_write_files
+ ):
"""Schema validation warns of non-string values for each file item."""
- cc = self.tmp_cloud('ubuntu')
- for key in VALID_SCHEMA['write_files'][0].keys():
- if key == 'append':
- key_type = 'boolean'
+ cc = self.tmp_cloud("ubuntu")
+ for key in VALID_SCHEMA["write_files"][0].keys():
+ if key == "append":
+ key_type = "boolean"
else:
- key_type = 'string'
+ key_type = "string"
invalid_config = copy.deepcopy(VALID_SCHEMA)
- invalid_config['write_files'][0][key] = 1
- handle('cc_write_file', invalid_config, cc, LOG, [])
+ invalid_config["write_files"][0][key] = 1
+ handle("cc_write_file", invalid_config, cc, LOG, [])
self.assertIn(
- mock.call('cc_write_file', invalid_config['write_files']),
- m_write_files.call_args_list)
+ mock.call("cc_write_file", invalid_config["write_files"]),
+ m_write_files.call_args_list,
+ )
self.assertIn(
- 'write_files.0.%s: 1 is not of type \'%s\'' % (key, key_type),
- self.logs.getvalue())
- self.assertIn('Invalid config:', self.logs.getvalue())
+ "write_files.0.%s: 1 is not of type '%s'" % (key, key_type),
+ self.logs.getvalue(),
+ )
+ self.assertIn("Invalid config:", self.logs.getvalue())
def test_schema_validation_warns_on_additional_undefined_propertes(
- self, m_write_files):
+ self, m_write_files
+ ):
"""Schema validation warns on additional undefined file properties."""
- cc = self.tmp_cloud('ubuntu')
+ cc = self.tmp_cloud("ubuntu")
invalid_config = copy.deepcopy(VALID_SCHEMA)
- invalid_config['write_files'][0]['bogus'] = 'value'
- handle('cc_write_file', invalid_config, cc, LOG, [])
+ invalid_config["write_files"][0]["bogus"] = "value"
+ handle("cc_write_file", invalid_config, cc, LOG, [])
self.assertIn(
"Invalid config:\nwrite_files.0: Additional properties"
" are not allowed ('bogus' was unexpected)",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
class TestWriteFiles(FilesystemMockingTestCase):
@@ -116,20 +134,20 @@ class TestWriteFiles(FilesystemMockingTestCase):
@skipUnlessJsonSchema()
def test_handler_schema_validation_warns_non_array_type(self):
"""Schema validation warns of non-array value."""
- invalid_config = {'write_files': 1}
- cc = self.tmp_cloud('ubuntu')
+ invalid_config = {"write_files": 1}
+ cc = self.tmp_cloud("ubuntu")
with self.assertRaises(TypeError):
- handle('cc_write_file', invalid_config, cc, LOG, [])
+ handle("cc_write_file", invalid_config, cc, LOG, [])
self.assertIn(
- 'Invalid config:\nwrite_files: 1 is not of type \'array\'',
- self.logs.getvalue())
+ "Invalid config:\nwrite_files: 1 is not of type 'array'",
+ self.logs.getvalue(),
+ )
def test_simple(self):
self.patchUtils(self.tmp)
expected = "hello world\n"
filename = "/tmp/my.file"
- write_files(
- "test_simple", [{"content": expected, "path": filename}])
+ write_files("test_simple", [{"content": expected, "path": filename}])
self.assertEqual(util.load_file(filename), expected)
def test_append(self):
@@ -141,13 +159,14 @@ class TestWriteFiles(FilesystemMockingTestCase):
util.write_file(filename, existing)
write_files(
"test_append",
- [{"content": added, "path": filename, "append": "true"}])
+ [{"content": added, "path": filename, "append": "true"}],
+ )
self.assertEqual(util.load_file(filename), expected)
def test_yaml_binary(self):
self.patchUtils(self.tmp)
data = util.load_yaml(YAML_TEXT)
- write_files("testname", data['write_files'])
+ write_files("testname", data["write_files"])
for path, content in YAML_CONTENT_EXPECTED.items():
self.assertEqual(util.load_file(path), content)
@@ -158,13 +177,13 @@ class TestWriteFiles(FilesystemMockingTestCase):
# for 'gz', 'gzip', 'gz+base64' ...
data = b"foobzr"
utf8_valid = b"foobzr"
- utf8_invalid = b'ab\xaadef'
+ utf8_invalid = b"ab\xaadef"
files = []
expected = []
- gz_aliases = ('gz', 'gzip')
- gz_b64_aliases = ('gz+base64', 'gzip+base64', 'gz+b64', 'gzip+b64')
- b64_aliases = ('base64', 'b64')
+ gz_aliases = ("gz", "gzip")
+ gz_b64_aliases = ("gz+base64", "gzip+base64", "gz+b64", "gzip+b64")
+ b64_aliases = ("base64", "b64")
datum = (("utf8", utf8_valid), ("no-utf8", utf8_invalid))
for name, data in datum:
@@ -173,11 +192,13 @@ class TestWriteFiles(FilesystemMockingTestCase):
b64 = (base64.b64encode(data), b64_aliases)
for content, aliases in (gz, gz_b64, b64):
for enc in aliases:
- cur = {'content': content,
- 'path': '/tmp/file-%s-%s' % (name, enc),
- 'encoding': enc}
+ cur = {
+ "content": content,
+ "path": "/tmp/file-%s-%s" % (name, enc),
+ "encoding": enc,
+ }
files.append(cur)
- expected.append((cur['path'], data))
+ expected.append((cur["path"], data))
write_files("test_decoding", files)
@@ -185,20 +206,17 @@ class TestWriteFiles(FilesystemMockingTestCase):
self.assertEqual(util.load_file(path, decode=False), content)
# make sure we actually wrote *some* files.
- flen_expected = (
- len(gz_aliases + gz_b64_aliases + b64_aliases) * len(datum))
+ flen_expected = len(gz_aliases + gz_b64_aliases + b64_aliases) * len(
+ datum
+ )
self.assertEqual(len(expected), flen_expected)
def test_deferred(self):
self.patchUtils(self.tmp)
- file_path = '/tmp/deferred.file'
- config = {
- 'write_files': [
- {'path': file_path, 'defer': True}
- ]
- }
- cc = self.tmp_cloud('ubuntu')
- handle('cc_write_file', config, cc, LOG, [])
+ file_path = "/tmp/deferred.file"
+ config = {"write_files": [{"path": file_path, "defer": True}]}
+ cc = self.tmp_cloud("ubuntu")
+ handle("cc_write_file", config, cc, LOG, [])
with self.assertRaises(FileNotFoundError):
util.load_file(file_path)
diff --git a/tests/unittests/config/test_cc_write_files_deferred.py b/tests/unittests/config/test_cc_write_files_deferred.py
index d33d250a..3faac1bf 100644
--- a/tests/unittests/config/test_cc_write_files_deferred.py
+++ b/tests/unittests/config/test_cc_write_files_deferred.py
@@ -1,48 +1,54 @@
# This file is part of cloud-init. See LICENSE file for license information.
-import tempfile
import shutil
+import tempfile
-from cloudinit.config.cc_write_files_deferred import (handle)
-from .test_cc_write_files import (VALID_SCHEMA)
from cloudinit import log as logging
from cloudinit import util
-
+from cloudinit.config.cc_write_files_deferred import handle
from tests.unittests.helpers import (
- CiTestCase, FilesystemMockingTestCase, mock, skipUnlessJsonSchema)
+ CiTestCase,
+ FilesystemMockingTestCase,
+ mock,
+ skipUnlessJsonSchema,
+)
+
+from .test_cc_write_files import VALID_SCHEMA
LOG = logging.getLogger(__name__)
@skipUnlessJsonSchema()
-@mock.patch('cloudinit.config.cc_write_files_deferred.write_files')
+@mock.patch("cloudinit.config.cc_write_files_deferred.write_files")
class TestWriteFilesDeferredSchema(CiTestCase):
with_logs = True
- def test_schema_validation_warns_invalid_value(self,
- m_write_files_deferred):
+ def test_schema_validation_warns_invalid_value(
+ self, m_write_files_deferred
+ ):
"""If 'defer' is defined, it must be of type 'bool'."""
valid_config = {
- 'write_files': [
- {**VALID_SCHEMA.get('write_files')[0], 'defer': True}
+ "write_files": [
+ {**VALID_SCHEMA.get("write_files")[0], "defer": True}
]
}
invalid_config = {
- 'write_files': [
- {**VALID_SCHEMA.get('write_files')[0], 'defer': str('no')}
+ "write_files": [
+ {**VALID_SCHEMA.get("write_files")[0], "defer": str("no")}
]
}
- cc = self.tmp_cloud('ubuntu')
- handle('cc_write_files_deferred', valid_config, cc, LOG, [])
- self.assertNotIn('Invalid config:', self.logs.getvalue())
- handle('cc_write_files_deferred', invalid_config, cc, LOG, [])
- self.assertIn('Invalid config:', self.logs.getvalue())
- self.assertIn("defer: 'no' is not of type 'boolean'",
- self.logs.getvalue())
+ cc = self.tmp_cloud("ubuntu")
+ handle("cc_write_files_deferred", valid_config, cc, LOG, [])
+ self.assertNotIn("Invalid config:", self.logs.getvalue())
+ handle("cc_write_files_deferred", invalid_config, cc, LOG, [])
+ self.assertIn("Invalid config:", self.logs.getvalue())
+ self.assertIn(
+ "defer: 'no' is not of type 'boolean'", self.logs.getvalue()
+ )
class TestWriteFilesDeferred(FilesystemMockingTestCase):
@@ -58,20 +64,20 @@ class TestWriteFilesDeferred(FilesystemMockingTestCase):
self.patchUtils(self.tmp)
expected = "hello world\n"
config = {
- 'write_files': [
+ "write_files": [
{
- 'path': '/tmp/deferred.file',
- 'defer': True,
- 'content': expected
+ "path": "/tmp/deferred.file",
+ "defer": True,
+ "content": expected,
},
- {'path': '/tmp/not_deferred.file'}
+ {"path": "/tmp/not_deferred.file"},
]
}
- cc = self.tmp_cloud('ubuntu')
- handle('cc_write_files_deferred', config, cc, LOG, [])
- self.assertEqual(util.load_file('/tmp/deferred.file'), expected)
+ cc = self.tmp_cloud("ubuntu")
+ handle("cc_write_files_deferred", config, cc, LOG, [])
+ self.assertEqual(util.load_file("/tmp/deferred.file"), expected)
with self.assertRaises(FileNotFoundError):
- util.load_file('/tmp/not_deferred.file')
+ util.load_file("/tmp/not_deferred.file")
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_yum_add_repo.py b/tests/unittests/config/test_cc_yum_add_repo.py
index 2f11b96a..550b0af2 100644
--- a/tests/unittests/config/test_cc_yum_add_repo.py
+++ b/tests/unittests/config/test_cc_yum_add_repo.py
@@ -20,92 +20,101 @@ class TestConfig(helpers.FilesystemMockingTestCase):
def test_bad_config(self):
cfg = {
- 'yum_repos': {
- 'epel-testing': {
- 'name': 'Extra Packages for Enterprise Linux 5 - Testing',
+ "yum_repos": {
+ "epel-testing": {
+ "name": "Extra Packages for Enterprise Linux 5 - Testing",
# Missing this should cause the repo not to be written
# 'baseurl': 'http://blah.org/pub/epel/testing/5/$barch',
- 'enabled': False,
- 'gpgcheck': True,
- 'gpgkey': 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL',
- 'failovermethod': 'priority',
+ "enabled": False,
+ "gpgcheck": True,
+ "gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL",
+ "failovermethod": "priority",
},
},
}
self.patchUtils(self.tmp)
- cc_yum_add_repo.handle('yum_add_repo', cfg, None, LOG, [])
- self.assertRaises(IOError, util.load_file,
- "/etc/yum.repos.d/epel_testing.repo")
+ cc_yum_add_repo.handle("yum_add_repo", cfg, None, LOG, [])
+ self.assertRaises(
+ IOError, util.load_file, "/etc/yum.repos.d/epel_testing.repo"
+ )
def test_write_config(self):
cfg = {
- 'yum_repos': {
- 'epel-testing': {
- 'name': 'Extra Packages for Enterprise Linux 5 - Testing',
- 'baseurl': 'http://blah.org/pub/epel/testing/5/$basearch',
- 'enabled': False,
- 'gpgcheck': True,
- 'gpgkey': 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL',
- 'failovermethod': 'priority',
+ "yum_repos": {
+ "epel-testing": {
+ "name": "Extra Packages for Enterprise Linux 5 - Testing",
+ "baseurl": "http://blah.org/pub/epel/testing/5/$basearch",
+ "enabled": False,
+ "gpgcheck": True,
+ "gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL",
+ "failovermethod": "priority",
},
},
}
self.patchUtils(self.tmp)
- cc_yum_add_repo.handle('yum_add_repo', cfg, None, LOG, [])
+ cc_yum_add_repo.handle("yum_add_repo", cfg, None, LOG, [])
contents = util.load_file("/etc/yum.repos.d/epel_testing.repo")
parser = configparser.ConfigParser()
parser.read_string(contents)
expected = {
- 'epel_testing': {
- 'name': 'Extra Packages for Enterprise Linux 5 - Testing',
- 'failovermethod': 'priority',
- 'gpgkey': 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL',
- 'enabled': '0',
- 'baseurl': 'http://blah.org/pub/epel/testing/5/$basearch',
- 'gpgcheck': '1',
+ "epel_testing": {
+ "name": "Extra Packages for Enterprise Linux 5 - Testing",
+ "failovermethod": "priority",
+ "gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL",
+ "enabled": "0",
+ "baseurl": "http://blah.org/pub/epel/testing/5/$basearch",
+ "gpgcheck": "1",
}
}
for section in expected:
- self.assertTrue(parser.has_section(section),
- "Contains section {0}".format(section))
+ self.assertTrue(
+ parser.has_section(section),
+ "Contains section {0}".format(section),
+ )
for k, v in expected[section].items():
self.assertEqual(parser.get(section, k), v)
def test_write_config_array(self):
cfg = {
- 'yum_repos': {
- 'puppetlabs-products': {
- 'name': 'Puppet Labs Products El 6 - $basearch',
- 'baseurl':
- 'http://yum.puppetlabs.com/el/6/products/$basearch',
- 'gpgkey': [
- 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs',
- 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppet',
+ "yum_repos": {
+ "puppetlabs-products": {
+ "name": "Puppet Labs Products El 6 - $basearch",
+ "baseurl": (
+ "http://yum.puppetlabs.com/el/6/products/$basearch"
+ ),
+ "gpgkey": [
+ "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs",
+ "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppet",
],
- 'enabled': True,
- 'gpgcheck': True,
+ "enabled": True,
+ "gpgcheck": True,
}
}
}
self.patchUtils(self.tmp)
- cc_yum_add_repo.handle('yum_add_repo', cfg, None, LOG, [])
+ cc_yum_add_repo.handle("yum_add_repo", cfg, None, LOG, [])
contents = util.load_file("/etc/yum.repos.d/puppetlabs_products.repo")
parser = configparser.ConfigParser()
parser.read_string(contents)
expected = {
- 'puppetlabs_products': {
- 'name': 'Puppet Labs Products El 6 - $basearch',
- 'baseurl': 'http://yum.puppetlabs.com/el/6/products/$basearch',
- 'gpgkey': 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs\n'
- 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppet',
- 'enabled': '1',
- 'gpgcheck': '1',
+ "puppetlabs_products": {
+ "name": "Puppet Labs Products El 6 - $basearch",
+ "baseurl": "http://yum.puppetlabs.com/el/6/products/$basearch",
+ "gpgkey": (
+ "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs\n"
+ "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppet"
+ ),
+ "enabled": "1",
+ "gpgcheck": "1",
}
}
for section in expected:
- self.assertTrue(parser.has_section(section),
- "Contains section {0}".format(section))
+ self.assertTrue(
+ parser.has_section(section),
+ "Contains section {0}".format(section),
+ )
for k, v in expected[section].items():
self.assertEqual(parser.get(section, k), v)
+
# vi: ts=4 expandtab
diff --git a/tests/unittests/config/test_cc_zypper_add_repo.py b/tests/unittests/config/test_cc_zypper_add_repo.py
index 4af04bee..4304fee1 100644
--- a/tests/unittests/config/test_cc_zypper_add_repo.py
+++ b/tests/unittests/config/test_cc_zypper_add_repo.py
@@ -17,31 +17,28 @@ class TestConfig(helpers.FilesystemMockingTestCase):
def setUp(self):
super(TestConfig, self).setUp()
self.tmp = self.tmp_dir()
- self.zypp_conf = 'etc/zypp/zypp.conf'
+ self.zypp_conf = "etc/zypp/zypp.conf"
def test_bad_repo_config(self):
"""Config has no baseurl, no file should be written"""
cfg = {
- 'repos': [
- {
- 'id': 'foo',
- 'name': 'suse-test',
- 'enabled': '1'
- },
+ "repos": [
+ {"id": "foo", "name": "suse-test", "enabled": "1"},
]
}
self.patchUtils(self.tmp)
- cc_zypper_add_repo._write_repos(cfg['repos'], '/etc/zypp/repos.d')
- self.assertRaises(IOError, util.load_file,
- "/etc/zypp/repos.d/foo.repo")
+ cc_zypper_add_repo._write_repos(cfg["repos"], "/etc/zypp/repos.d")
+ self.assertRaises(
+ IOError, util.load_file, "/etc/zypp/repos.d/foo.repo"
+ )
def test_write_repos(self):
"""Verify valid repos get written"""
cfg = self._get_base_config_repos()
root_d = self.tmp_dir()
- cc_zypper_add_repo._write_repos(cfg['zypper']['repos'], root_d)
- repos = glob.glob('%s/*.repo' % root_d)
- expected_repos = ['testing-foo.repo', 'testing-bar.repo']
+ cc_zypper_add_repo._write_repos(cfg["zypper"]["repos"], root_d)
+ repos = glob.glob("%s/*.repo" % root_d)
+ expected_repos = ["testing-foo.repo", "testing-bar.repo"]
if len(repos) != 2:
assert 'Number of repos written is "%d" expected 2' % len(repos)
for repo in repos:
@@ -53,80 +50,77 @@ class TestConfig(helpers.FilesystemMockingTestCase):
def test_write_repo(self):
"""Verify the content of a repo file"""
cfg = {
- 'repos': [
+ "repos": [
{
- 'baseurl': 'http://foo',
- 'name': 'test-foo',
- 'id': 'testing-foo'
+ "baseurl": "http://foo",
+ "name": "test-foo",
+ "id": "testing-foo",
},
]
}
root_d = self.tmp_dir()
- cc_zypper_add_repo._write_repos(cfg['repos'], root_d)
+ cc_zypper_add_repo._write_repos(cfg["repos"], root_d)
contents = util.load_file("%s/testing-foo.repo" % root_d)
parser = configparser.ConfigParser()
parser.read_string(contents)
expected = {
- 'testing-foo': {
- 'name': 'test-foo',
- 'baseurl': 'http://foo',
- 'enabled': '1',
- 'autorefresh': '1'
+ "testing-foo": {
+ "name": "test-foo",
+ "baseurl": "http://foo",
+ "enabled": "1",
+ "autorefresh": "1",
}
}
for section in expected:
- self.assertTrue(parser.has_section(section),
- "Contains section {0}".format(section))
+ self.assertTrue(
+ parser.has_section(section),
+ "Contains section {0}".format(section),
+ )
for k, v in expected[section].items():
self.assertEqual(parser.get(section, k), v)
def test_config_write(self):
"""Write valid configuration data"""
- cfg = {
- 'config': {
- 'download.deltarpm': 'False',
- 'reposdir': 'foo'
- }
- }
+ cfg = {"config": {"download.deltarpm": "False", "reposdir": "foo"}}
root_d = self.tmp_dir()
- helpers.populate_dir(root_d, {self.zypp_conf: '# Zypp config\n'})
+ helpers.populate_dir(root_d, {self.zypp_conf: "# Zypp config\n"})
self.reRoot(root_d)
- cc_zypper_add_repo._write_zypp_config(cfg['config'])
+ cc_zypper_add_repo._write_zypp_config(cfg["config"])
cfg_out = os.path.join(root_d, self.zypp_conf)
contents = util.load_file(cfg_out)
expected = [
- '# Zypp config',
- '# Added via cloud.cfg',
- 'download.deltarpm=False',
- 'reposdir=foo'
+ "# Zypp config",
+ "# Added via cloud.cfg",
+ "download.deltarpm=False",
+ "reposdir=foo",
]
- for item in contents.split('\n'):
+ for item in contents.split("\n"):
if item not in expected:
self.assertIsNone(item)
- @mock.patch('cloudinit.log.logging')
+ @mock.patch("cloudinit.log.logging")
def test_config_write_skip_configdir(self, mock_logging):
"""Write configuration but skip writing 'configdir' setting"""
cfg = {
- 'config': {
- 'download.deltarpm': 'False',
- 'reposdir': 'foo',
- 'configdir': 'bar'
+ "config": {
+ "download.deltarpm": "False",
+ "reposdir": "foo",
+ "configdir": "bar",
}
}
root_d = self.tmp_dir()
- helpers.populate_dir(root_d, {self.zypp_conf: '# Zypp config\n'})
+ helpers.populate_dir(root_d, {self.zypp_conf: "# Zypp config\n"})
self.reRoot(root_d)
- cc_zypper_add_repo._write_zypp_config(cfg['config'])
+ cc_zypper_add_repo._write_zypp_config(cfg["config"])
cfg_out = os.path.join(root_d, self.zypp_conf)
contents = util.load_file(cfg_out)
expected = [
- '# Zypp config',
- '# Added via cloud.cfg',
- 'download.deltarpm=False',
- 'reposdir=foo'
+ "# Zypp config",
+ "# Added via cloud.cfg",
+ "download.deltarpm=False",
+ "reposdir=foo",
]
- for item in contents.split('\n'):
+ for item in contents.split("\n"):
if item not in expected:
self.assertIsNone(item)
# Not finding teh right path for mocking :(
@@ -134,55 +128,53 @@ class TestConfig(helpers.FilesystemMockingTestCase):
def test_empty_config_section_no_new_data(self):
"""When the config section is empty no new data should be written to
- zypp.conf"""
+ zypp.conf"""
cfg = self._get_base_config_repos()
- cfg['zypper']['config'] = None
+ cfg["zypper"]["config"] = None
root_d = self.tmp_dir()
- helpers.populate_dir(root_d, {self.zypp_conf: '# No data'})
+ helpers.populate_dir(root_d, {self.zypp_conf: "# No data"})
self.reRoot(root_d)
- cc_zypper_add_repo._write_zypp_config(cfg.get('config', {}))
+ cc_zypper_add_repo._write_zypp_config(cfg.get("config", {}))
cfg_out = os.path.join(root_d, self.zypp_conf)
contents = util.load_file(cfg_out)
- self.assertEqual(contents, '# No data')
+ self.assertEqual(contents, "# No data")
def test_empty_config_value_no_new_data(self):
"""When the config section is not empty but there are no values
- no new data should be written to zypp.conf"""
+ no new data should be written to zypp.conf"""
cfg = self._get_base_config_repos()
- cfg['zypper']['config'] = {
- 'download.deltarpm': None
- }
+ cfg["zypper"]["config"] = {"download.deltarpm": None}
root_d = self.tmp_dir()
- helpers.populate_dir(root_d, {self.zypp_conf: '# No data'})
+ helpers.populate_dir(root_d, {self.zypp_conf: "# No data"})
self.reRoot(root_d)
- cc_zypper_add_repo._write_zypp_config(cfg.get('config', {}))
+ cc_zypper_add_repo._write_zypp_config(cfg.get("config", {}))
cfg_out = os.path.join(root_d, self.zypp_conf)
contents = util.load_file(cfg_out)
- self.assertEqual(contents, '# No data')
+ self.assertEqual(contents, "# No data")
def test_handler_full_setup(self):
"""Test that the handler ends up calling the renderers"""
cfg = self._get_base_config_repos()
- cfg['zypper']['config'] = {
- 'download.deltarpm': 'False',
+ cfg["zypper"]["config"] = {
+ "download.deltarpm": "False",
}
root_d = self.tmp_dir()
- os.makedirs('%s/etc/zypp/repos.d' % root_d)
- helpers.populate_dir(root_d, {self.zypp_conf: '# Zypp config\n'})
+ os.makedirs("%s/etc/zypp/repos.d" % root_d)
+ helpers.populate_dir(root_d, {self.zypp_conf: "# Zypp config\n"})
self.reRoot(root_d)
- cc_zypper_add_repo.handle('zypper_add_repo', cfg, None, LOG, [])
+ cc_zypper_add_repo.handle("zypper_add_repo", cfg, None, LOG, [])
cfg_out = os.path.join(root_d, self.zypp_conf)
contents = util.load_file(cfg_out)
expected = [
- '# Zypp config',
- '# Added via cloud.cfg',
- 'download.deltarpm=False',
+ "# Zypp config",
+ "# Added via cloud.cfg",
+ "download.deltarpm=False",
]
- for item in contents.split('\n'):
+ for item in contents.split("\n"):
if item not in expected:
self.assertIsNone(item)
- repos = glob.glob('%s/etc/zypp/repos.d/*.repo' % root_d)
- expected_repos = ['testing-foo.repo', 'testing-bar.repo']
+ repos = glob.glob("%s/etc/zypp/repos.d/*.repo" % root_d)
+ expected_repos = ["testing-foo.repo", "testing-bar.repo"]
if len(repos) != 2:
assert 'Number of repos written is "%d" expected 2' % len(repos)
for repo in repos:
@@ -192,39 +184,39 @@ class TestConfig(helpers.FilesystemMockingTestCase):
def test_no_config_section_no_new_data(self):
"""When there is no config section no new data should be written to
- zypp.conf"""
+ zypp.conf"""
cfg = self._get_base_config_repos()
root_d = self.tmp_dir()
- helpers.populate_dir(root_d, {self.zypp_conf: '# No data'})
+ helpers.populate_dir(root_d, {self.zypp_conf: "# No data"})
self.reRoot(root_d)
- cc_zypper_add_repo._write_zypp_config(cfg.get('config', {}))
+ cc_zypper_add_repo._write_zypp_config(cfg.get("config", {}))
cfg_out = os.path.join(root_d, self.zypp_conf)
contents = util.load_file(cfg_out)
- self.assertEqual(contents, '# No data')
+ self.assertEqual(contents, "# No data")
def test_no_repo_data(self):
"""When there is no repo data nothing should happen"""
root_d = self.tmp_dir()
self.reRoot(root_d)
cc_zypper_add_repo._write_repos(None, root_d)
- content = glob.glob('%s/*' % root_d)
+ content = glob.glob("%s/*" % root_d)
self.assertEqual(len(content), 0)
def _get_base_config_repos(self):
"""Basic valid repo configuration"""
cfg = {
- 'zypper': {
- 'repos': [
+ "zypper": {
+ "repos": [
{
- 'baseurl': 'http://foo',
- 'name': 'test-foo',
- 'id': 'testing-foo'
+ "baseurl": "http://foo",
+ "name": "test-foo",
+ "id": "testing-foo",
},
{
- 'baseurl': 'http://bar',
- 'name': 'test-bar',
- 'id': 'testing-bar'
- }
+ "baseurl": "http://bar",
+ "name": "test-bar",
+ "id": "testing-bar",
+ },
]
}
}
diff --git a/tests/unittests/config/test_schema.py b/tests/unittests/config/test_schema.py
index 40803cae..fb5b891d 100644
--- a/tests/unittests/config/test_schema.py
+++ b/tests/unittests/config/test_schema.py
@@ -2,35 +2,36 @@
import importlib
-import sys
import inspect
+import itertools
import logging
+import sys
from copy import copy
-import itertools
-import pytest
from pathlib import Path
from textwrap import dedent
+
+import pytest
from yaml import safe_load
from cloudinit.config.schema import (
CLOUD_CONFIG_HEADER,
+ MetaSchema,
SchemaValidationError,
annotated_cloudconfig_file,
+ get_jsonschema_validator,
get_meta_doc,
get_schema,
- get_jsonschema_validator,
+ main,
validate_cloudconfig_file,
validate_cloudconfig_metaschema,
validate_cloudconfig_schema,
- main,
- MetaSchema,
)
from cloudinit.util import write_file
from tests.unittests.helpers import (
CiTestCase,
+ cloud_init_project_dir,
mock,
skipUnlessJsonSchema,
- cloud_init_project_dir,
)
@@ -78,26 +79,25 @@ def get_module_variable(var_name) -> dict:
class GetSchemaTest(CiTestCase):
-
def test_get_schema_coalesces_known_schema(self):
"""Every cloudconfig module with schema is listed in allOf keyword."""
schema = get_schema()
self.assertCountEqual(
[
- 'cc_apk_configure',
- 'cc_apt_configure',
- 'cc_bootcmd',
- 'cc_locale',
- 'cc_ntp',
- 'cc_resizefs',
- 'cc_runcmd',
- 'cc_snap',
- 'cc_ubuntu_advantage',
- 'cc_ubuntu_drivers',
- 'cc_write_files',
- 'cc_zypper_add_repo',
- 'cc_chef',
- 'cc_install_hotplug',
+ "cc_apk_configure",
+ "cc_apt_configure",
+ "cc_bootcmd",
+ "cc_locale",
+ "cc_ntp",
+ "cc_resizefs",
+ "cc_runcmd",
+ "cc_snap",
+ "cc_ubuntu_advantage",
+ "cc_ubuntu_drivers",
+ "cc_write_files",
+ "cc_zypper_add_repo",
+ "cc_chef",
+ "cc_install_hotplug",
],
[meta["id"] for meta in get_metas().values() if meta is not None],
)
@@ -113,15 +113,18 @@ class SchemaValidationErrorTest(CiTestCase):
def test_schema_validation_error_expects_schema_errors(self):
"""SchemaValidationError is initialized from schema_errors."""
- errors = (('key.path', 'unexpected key "junk"'),
- ('key2.path', '"-123" is not a valid "hostname" format'))
+ errors = (
+ ("key.path", 'unexpected key "junk"'),
+ ("key2.path", '"-123" is not a valid "hostname" format'),
+ )
exception = SchemaValidationError(schema_errors=errors)
self.assertIsInstance(exception, Exception)
self.assertEqual(exception.schema_errors, errors)
self.assertEqual(
'Cloud config schema errors: key.path: unexpected key "junk", '
'key2.path: "-123" is not a valid "hostname" format',
- str(exception))
+ str(exception),
+ )
self.assertTrue(isinstance(exception, ValueError))
@@ -133,18 +136,19 @@ class ValidateCloudConfigSchemaTest(CiTestCase):
@skipUnlessJsonSchema()
def test_validateconfig_schema_non_strict_emits_warnings(self):
"""When strict is False validate_cloudconfig_schema emits warnings."""
- schema = {'properties': {'p1': {'type': 'string'}}}
- validate_cloudconfig_schema({'p1': -1}, schema, strict=False)
+ schema = {"properties": {"p1": {"type": "string"}}}
+ validate_cloudconfig_schema({"p1": -1}, schema, strict=False)
self.assertIn(
"Invalid config:\np1: -1 is not of type 'string'\n",
- self.logs.getvalue())
+ self.logs.getvalue(),
+ )
@skipUnlessJsonSchema()
def test_validateconfig_schema_emits_warning_on_missing_jsonschema(self):
"""Warning from validate_cloudconfig_schema when missing jsonschema."""
- schema = {'properties': {'p1': {'type': 'string'}}}
- with mock.patch.dict('sys.modules', **{'jsonschema': ImportError()}):
- validate_cloudconfig_schema({'p1': -1}, schema, strict=True)
+ schema = {"properties": {"p1": {"type": "string"}}}
+ with mock.patch.dict("sys.modules", **{"jsonschema": ImportError()}):
+ validate_cloudconfig_schema({"p1": -1}, schema, strict=True)
self.assertIn(
"Ignoring schema validation. jsonschema is not present",
self.logs.getvalue(),
@@ -153,28 +157,28 @@ class ValidateCloudConfigSchemaTest(CiTestCase):
@skipUnlessJsonSchema()
def test_validateconfig_schema_strict_raises_errors(self):
"""When strict is True validate_cloudconfig_schema raises errors."""
- schema = {'properties': {'p1': {'type': 'string'}}}
+ schema = {"properties": {"p1": {"type": "string"}}}
with self.assertRaises(SchemaValidationError) as context_mgr:
- validate_cloudconfig_schema({'p1': -1}, schema, strict=True)
+ validate_cloudconfig_schema({"p1": -1}, schema, strict=True)
self.assertEqual(
"Cloud config schema errors: p1: -1 is not of type 'string'",
- str(context_mgr.exception))
+ str(context_mgr.exception),
+ )
@skipUnlessJsonSchema()
def test_validateconfig_schema_honors_formats(self):
"""With strict True, validate_cloudconfig_schema errors on format."""
- schema = {
- 'properties': {'p1': {'type': 'string', 'format': 'email'}}}
+ schema = {"properties": {"p1": {"type": "string", "format": "email"}}}
with self.assertRaises(SchemaValidationError) as context_mgr:
- validate_cloudconfig_schema({'p1': '-1'}, schema, strict=True)
+ validate_cloudconfig_schema({"p1": "-1"}, schema, strict=True)
self.assertEqual(
"Cloud config schema errors: p1: '-1' is not a 'email'",
- str(context_mgr.exception))
+ str(context_mgr.exception),
+ )
@skipUnlessJsonSchema()
def test_validateconfig_schema_honors_formats_strict_metaschema(self):
- """With strict True and strict_metascheam True, ensure errors on format
- """
+ """With strict and strict_metaschema True, ensure errors on format"""
schema = {"properties": {"p1": {"type": "string", "format": "email"}}}
with self.assertRaises(SchemaValidationError) as context_mgr:
validate_cloudconfig_schema(
@@ -229,15 +233,15 @@ class ValidateCloudConfigFileTest(CiTestCase):
def setUp(self):
super(ValidateCloudConfigFileTest, self).setUp()
- self.config_file = self.tmp_path('cloudcfg.yaml')
+ self.config_file = self.tmp_path("cloudcfg.yaml")
def test_validateconfig_file_error_on_absent_file(self):
"""On absent config_path, validate_cloudconfig_file errors."""
with self.assertRaises(RuntimeError) as context_mgr:
- validate_cloudconfig_file('/not/here', {})
+ validate_cloudconfig_file("/not/here", {})
self.assertEqual(
- 'Configfile /not/here does not exist',
- str(context_mgr.exception))
+ "Configfile /not/here does not exist", str(context_mgr.exception)
+ )
def test_validateconfig_file_error_on_invalid_header(self):
"""On invalid header, validate_cloudconfig_file errors.
@@ -245,48 +249,54 @@ class ValidateCloudConfigFileTest(CiTestCase):
A SchemaValidationError is raised when the file doesn't begin with
CLOUD_CONFIG_HEADER.
"""
- write_file(self.config_file, '#junk')
+ write_file(self.config_file, "#junk")
with self.assertRaises(SchemaValidationError) as context_mgr:
validate_cloudconfig_file(self.config_file, {})
self.assertEqual(
- 'Cloud config schema errors: format-l1.c1: File {0} needs to begin'
+ "Cloud config schema errors: format-l1.c1: File {0} needs to begin"
' with "{1}"'.format(
- self.config_file, CLOUD_CONFIG_HEADER.decode()),
- str(context_mgr.exception))
+ self.config_file, CLOUD_CONFIG_HEADER.decode()
+ ),
+ str(context_mgr.exception),
+ )
def test_validateconfig_file_error_on_non_yaml_scanner_error(self):
"""On non-yaml scan issues, validate_cloudconfig_file errors."""
# Generate a scanner error by providing text on a single line with
# improper indent.
- write_file(self.config_file, '#cloud-config\nasdf:\nasdf')
+ write_file(self.config_file, "#cloud-config\nasdf:\nasdf")
with self.assertRaises(SchemaValidationError) as context_mgr:
validate_cloudconfig_file(self.config_file, {})
self.assertIn(
- 'schema errors: format-l3.c1: File {0} is not valid yaml.'.format(
- self.config_file),
- str(context_mgr.exception))
+ "schema errors: format-l3.c1: File {0} is not valid yaml.".format(
+ self.config_file
+ ),
+ str(context_mgr.exception),
+ )
def test_validateconfig_file_error_on_non_yaml_parser_error(self):
"""On non-yaml parser issues, validate_cloudconfig_file errors."""
- write_file(self.config_file, '#cloud-config\n{}}')
+ write_file(self.config_file, "#cloud-config\n{}}")
with self.assertRaises(SchemaValidationError) as context_mgr:
validate_cloudconfig_file(self.config_file, {})
self.assertIn(
- 'schema errors: format-l2.c3: File {0} is not valid yaml.'.format(
- self.config_file),
- str(context_mgr.exception))
+ "schema errors: format-l2.c3: File {0} is not valid yaml.".format(
+ self.config_file
+ ),
+ str(context_mgr.exception),
+ )
@skipUnlessJsonSchema()
def test_validateconfig_file_sctrictly_validates_schema(self):
"""validate_cloudconfig_file raises errors on invalid schema."""
- schema = {
- 'properties': {'p1': {'type': 'string', 'format': 'string'}}}
- write_file(self.config_file, '#cloud-config\np1: -1')
+ schema = {"properties": {"p1": {"type": "string", "format": "string"}}}
+ write_file(self.config_file, "#cloud-config\np1: -1")
with self.assertRaises(SchemaValidationError) as context_mgr:
validate_cloudconfig_file(self.config_file, schema)
self.assertEqual(
"Cloud config schema errors: p1: -1 is not of type 'string'",
- str(context_mgr.exception))
+ str(context_mgr.exception),
+ )
class GetSchemaDocTest(CiTestCase):
@@ -321,13 +331,21 @@ class GetSchemaDocTest(CiTestCase):
"""get_meta_doc returns restructured text for a cloudinit schema."""
full_schema = copy(self.required_schema)
full_schema.update(
- {'properties': {
- 'prop1': {'type': 'array', 'description': 'prop-description',
- 'items': {'type': 'integer'}}}})
+ {
+ "properties": {
+ "prop1": {
+ "type": "array",
+ "description": "prop-description",
+ "items": {"type": "integer"},
+ }
+ }
+ }
+ )
doc = get_meta_doc(self.meta, full_schema)
self.assertEqual(
- dedent("""
+ dedent(
+ """
name
----
**Summary:** title
@@ -349,7 +367,8 @@ class GetSchemaDocTest(CiTestCase):
[don't, expand, "this"]
# --- Example2 ---
ex2: true
- """),
+ """
+ ),
doc,
)
@@ -388,12 +407,23 @@ class GetSchemaDocTest(CiTestCase):
"""get_meta_doc properly indented examples as a list of strings."""
full_schema = copy(self.required_schema)
full_schema.update(
- {'examples': ['ex1:\n [don\'t, expand, "this"]', 'ex2: true'],
- 'properties': {
- 'prop1': {'type': 'array', 'description': 'prop-description',
- 'items': {'type': 'integer'}}}})
+ {
+ "examples": [
+ 'ex1:\n [don\'t, expand, "this"]',
+ "ex2: true",
+ ],
+ "properties": {
+ "prop1": {
+ "type": "array",
+ "description": "prop-description",
+ "items": {"type": "integer"},
+ }
+ },
+ }
+ )
self.assertIn(
- dedent("""
+ dedent(
+ """
**Config schema**:
**prop1:** (array of integer) prop-description
@@ -403,7 +433,8 @@ class GetSchemaDocTest(CiTestCase):
[don't, expand, "this"]
# --- Example2 ---
ex2: true
- """),
+ """
+ ),
get_meta_doc(self.meta, full_schema),
)
@@ -424,13 +455,15 @@ class GetSchemaDocTest(CiTestCase):
- option3
The default value is
- option1""")
+ option1"""
+ ),
}
}
}
self.assertIn(
- dedent("""
+ dedent(
+ """
**Config schema**:
**p1:** (string) This item has the following options:
@@ -440,7 +473,8 @@ class GetSchemaDocTest(CiTestCase):
The default value is option1
- """),
+ """
+ ),
get_meta_doc(self.meta, schema),
)
@@ -475,7 +509,7 @@ class GetSchemaDocTest(CiTestCase):
"type": "string",
},
"prop_array": {
- "label": 'array_label',
+ "label": "array_label",
"type": "array",
"items": {
"type": "object",
@@ -490,7 +524,7 @@ class GetSchemaDocTest(CiTestCase):
"type": "string",
"label": "label2",
}
- }
+ },
}
meta_doc = get_meta_doc(self.meta, schema)
assert "**label1:** (string)" in meta_doc
@@ -507,20 +541,23 @@ class AnnotatedCloudconfigFileTest(CiTestCase):
def test_annotated_cloudconfig_file_no_schema_errors(self):
"""With no schema_errors, print the original content."""
- content = b'ntp:\n pools: [ntp1.pools.com]\n'
+ content = b"ntp:\n pools: [ntp1.pools.com]\n"
self.assertEqual(
- content,
- annotated_cloudconfig_file({}, content, schema_errors=[]))
+ content, annotated_cloudconfig_file({}, content, schema_errors=[])
+ )
def test_annotated_cloudconfig_file_schema_annotates_and_adds_footer(self):
"""With schema_errors, error lines are annotated and a footer added."""
- content = dedent("""\
+ content = dedent(
+ """\
#cloud-config
# comment
ntp:
pools: [-99, 75]
- """).encode()
- expected = dedent("""\
+ """
+ ).encode()
+ expected = dedent(
+ """\
#cloud-config
# comment
ntp: # E1
@@ -531,38 +568,48 @@ class AnnotatedCloudconfigFileTest(CiTestCase):
# E2: -99 is not a string
# E3: 75 is not a string
- """)
+ """
+ )
parsed_config = safe_load(content[13:])
schema_errors = [
- ('ntp', 'Some type error'), ('ntp.pools.0', '-99 is not a string'),
- ('ntp.pools.1', '75 is not a string')]
+ ("ntp", "Some type error"),
+ ("ntp.pools.0", "-99 is not a string"),
+ ("ntp.pools.1", "75 is not a string"),
+ ]
self.assertEqual(
expected,
- annotated_cloudconfig_file(parsed_config, content, schema_errors))
+ annotated_cloudconfig_file(parsed_config, content, schema_errors),
+ )
def test_annotated_cloudconfig_file_annotates_separate_line_items(self):
"""Errors are annotated for lists with items on separate lines."""
- content = dedent("""\
+ content = dedent(
+ """\
#cloud-config
# comment
ntp:
pools:
- -99
- 75
- """).encode()
- expected = dedent("""\
+ """
+ ).encode()
+ expected = dedent(
+ """\
ntp:
pools:
- -99 # E1
- 75 # E2
- """)
+ """
+ )
parsed_config = safe_load(content[13:])
schema_errors = [
- ('ntp.pools.0', '-99 is not a string'),
- ('ntp.pools.1', '75 is not a string')]
+ ("ntp.pools.0", "-99 is not a string"),
+ ("ntp.pools.1", "75 is not a string"),
+ ]
self.assertIn(
expected,
- annotated_cloudconfig_file(parsed_config, content, schema_errors))
+ annotated_cloudconfig_file(parsed_config, content, schema_errors),
+ )
class TestMain:
@@ -575,94 +622,94 @@ class TestMain:
def test_main_exclusive_args(self, params, capsys):
"""Main exits non-zero and error on required exclusive args."""
params = list(itertools.chain(*[a.split() for a in params]))
- with mock.patch('sys.argv', ['mycmd'] + params):
+ with mock.patch("sys.argv", ["mycmd"] + params):
with pytest.raises(SystemExit) as context_manager:
main()
assert 1 == context_manager.value.code
_out, err = capsys.readouterr()
expected = (
- 'Error:\n'
- 'Expected one of --config-file, --system or --docs arguments\n'
+ "Error:\n"
+ "Expected one of --config-file, --system or --docs arguments\n"
)
assert expected == err
def test_main_missing_args(self, capsys):
"""Main exits non-zero and reports an error on missing parameters."""
- with mock.patch('sys.argv', ['mycmd']):
+ with mock.patch("sys.argv", ["mycmd"]):
with pytest.raises(SystemExit) as context_manager:
main()
assert 1 == context_manager.value.code
_out, err = capsys.readouterr()
expected = (
- 'Error:\n'
- 'Expected one of --config-file, --system or --docs arguments\n'
+ "Error:\n"
+ "Expected one of --config-file, --system or --docs arguments\n"
)
assert expected == err
def test_main_absent_config_file(self, capsys):
"""Main exits non-zero when config file is absent."""
- myargs = ['mycmd', '--annotate', '--config-file', 'NOT_A_FILE']
- with mock.patch('sys.argv', myargs):
+ myargs = ["mycmd", "--annotate", "--config-file", "NOT_A_FILE"]
+ with mock.patch("sys.argv", myargs):
with pytest.raises(SystemExit) as context_manager:
main()
assert 1 == context_manager.value.code
_out, err = capsys.readouterr()
- assert 'Error:\nConfigfile NOT_A_FILE does not exist\n' == err
+ assert "Error:\nConfigfile NOT_A_FILE does not exist\n" == err
def test_main_prints_docs(self, capsys):
"""When --docs parameter is provided, main generates documentation."""
- myargs = ['mycmd', '--docs', 'all']
- with mock.patch('sys.argv', myargs):
- assert 0 == main(), 'Expected 0 exit code'
+ myargs = ["mycmd", "--docs", "all"]
+ with mock.patch("sys.argv", myargs):
+ assert 0 == main(), "Expected 0 exit code"
out, _err = capsys.readouterr()
- assert '\nNTP\n---\n' in out
- assert '\nRuncmd\n------\n' in out
+ assert "\nNTP\n---\n" in out
+ assert "\nRuncmd\n------\n" in out
def test_main_validates_config_file(self, tmpdir, capsys):
"""When --config-file parameter is provided, main validates schema."""
- myyaml = tmpdir.join('my.yaml')
- myargs = ['mycmd', '--config-file', myyaml.strpath]
- myyaml.write(b'#cloud-config\nntp:') # shortest ntp schema
- with mock.patch('sys.argv', myargs):
- assert 0 == main(), 'Expected 0 exit code'
+ myyaml = tmpdir.join("my.yaml")
+ myargs = ["mycmd", "--config-file", myyaml.strpath]
+ myyaml.write(b"#cloud-config\nntp:") # shortest ntp schema
+ with mock.patch("sys.argv", myargs):
+ assert 0 == main(), "Expected 0 exit code"
out, _err = capsys.readouterr()
- assert 'Valid cloud-config: {0}\n'.format(myyaml) == out
+ assert "Valid cloud-config: {0}\n".format(myyaml) == out
- @mock.patch('cloudinit.config.schema.read_cfg_paths')
- @mock.patch('cloudinit.config.schema.os.getuid', return_value=0)
+ @mock.patch("cloudinit.config.schema.read_cfg_paths")
+ @mock.patch("cloudinit.config.schema.os.getuid", return_value=0)
def test_main_validates_system_userdata(
self, m_getuid, m_read_cfg_paths, capsys, paths
):
"""When --system is provided, main validates system userdata."""
m_read_cfg_paths.return_value = paths
ud_file = paths.get_ipath_cur("userdata_raw")
- write_file(ud_file, b'#cloud-config\nntp:')
- myargs = ['mycmd', '--system']
- with mock.patch('sys.argv', myargs):
- assert 0 == main(), 'Expected 0 exit code'
+ write_file(ud_file, b"#cloud-config\nntp:")
+ myargs = ["mycmd", "--system"]
+ with mock.patch("sys.argv", myargs):
+ assert 0 == main(), "Expected 0 exit code"
out, _err = capsys.readouterr()
- assert 'Valid cloud-config: system userdata\n' == out
+ assert "Valid cloud-config: system userdata\n" == out
- @mock.patch('cloudinit.config.schema.os.getuid', return_value=1000)
+ @mock.patch("cloudinit.config.schema.os.getuid", return_value=1000)
def test_main_system_userdata_requires_root(self, m_getuid, capsys, paths):
"""Non-root user can't use --system param"""
- myargs = ['mycmd', '--system']
- with mock.patch('sys.argv', myargs):
+ myargs = ["mycmd", "--system"]
+ with mock.patch("sys.argv", myargs):
with pytest.raises(SystemExit) as context_manager:
main()
assert 1 == context_manager.value.code
_out, err = capsys.readouterr()
expected = (
- 'Error:\nUnable to read system userdata as non-root user. '
- 'Try using sudo\n'
+ "Error:\nUnable to read system userdata as non-root user. "
+ "Try using sudo\n"
)
assert expected == err
def _get_meta_doc_examples():
- examples_dir = Path(cloud_init_project_dir('doc/examples'))
+ examples_dir = Path(cloud_init_project_dir("doc/examples"))
assert examples_dir.is_dir()
return (
@@ -712,7 +759,7 @@ class TestStrictMetaschema:
}
with pytest.raises(
SchemaValidationError,
- match=(r"Additional properties are not allowed.*")
+ match=r"Additional properties are not allowed.*",
):
validate_cloudconfig_metaschema(validator, schema)