summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorScott Moser <smoser@brickies.net>2016-10-25 17:06:18 -0400
committerScott Moser <smoser@brickies.net>2016-10-25 17:06:18 -0400
commitf294110e5c8b121f8d8dcb48b0845a419ba13544 (patch)
tree9f5adaa598f5e943310075aa3255169db14fad9f /tests
parent1a2086302c3a62277b272bd004e34eb5d264c2fe (diff)
parent29348af1c889931e8973f8fc8cb090c063316f7a (diff)
downloadvyos-cloud-init-f294110e5c8b121f8d8dcb48b0845a419ba13544.tar.gz
vyos-cloud-init-f294110e5c8b121f8d8dcb48b0845a419ba13544.zip
merge from master at 0.7.8-27-g29348af
Diffstat (limited to 'tests')
-rw-r--r--tests/unittests/__init__.py9
-rw-r--r--tests/unittests/helpers.py8
-rw-r--r--tests/unittests/test_data.py45
-rw-r--r--tests/unittests/test_datasource/test_opennebula.py23
-rwxr-xr-x[-rw-r--r--]tests/unittests/test_distros/test_user_data_normalize.py70
-rw-r--r--tests/unittests/test_handler/test_handler_apt_conf_v1.py2
-rw-r--r--tests/unittests/test_handler/test_handler_snappy.py293
-rw-r--r--tests/unittests/test_util.py2
8 files changed, 404 insertions, 48 deletions
diff --git a/tests/unittests/__init__.py b/tests/unittests/__init__.py
index e69de29b..1b34b5af 100644
--- a/tests/unittests/__init__.py
+++ b/tests/unittests/__init__.py
@@ -0,0 +1,9 @@
+try:
+ # For test cases, avoid the following UserWarning to stderr:
+ # You don't have the C version of NameMapper installed ...
+ from Cheetah import NameMapper as _nm
+ _nm.C_VERSION = True
+except ImportError:
+ pass
+
+# vi: ts=4 expandtab
diff --git a/tests/unittests/helpers.py b/tests/unittests/helpers.py
index 1cdc05a1..a2355a79 100644
--- a/tests/unittests/helpers.py
+++ b/tests/unittests/helpers.py
@@ -205,6 +205,14 @@ class FilesystemMockingTestCase(ResourceUsingTestCase):
self.patched_funcs.enter_context(
mock.patch.object(sys, 'stderr', stderr))
+ def reRoot(self, root=None):
+ if root is None:
+ root = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, root)
+ self.patchUtils(root)
+ self.patchOS(root)
+ return root
+
def import_httpretty():
"""Import HTTPretty and monkey patch Python 3.4 issue.
diff --git a/tests/unittests/test_data.py b/tests/unittests/test_data.py
index 13db8a4c..55d9b93f 100644
--- a/tests/unittests/test_data.py
+++ b/tests/unittests/test_data.py
@@ -3,8 +3,6 @@
import gzip
import logging
import os
-import shutil
-import tempfile
try:
from unittest import mock
@@ -98,10 +96,7 @@ class TestConsumeUserData(helpers.FilesystemMockingTestCase):
ci = stages.Init()
ci.datasource = FakeDataSource(blob)
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self.patchUtils(new_root)
- self.patchOS(new_root)
+ self.reRoot()
ci.fetch()
ci.consume_data()
cc_contents = util.load_file(ci.paths.get_ipath("cloud_config"))
@@ -127,9 +122,7 @@ class TestConsumeUserData(helpers.FilesystemMockingTestCase):
{ "op": "add", "path": "/foo", "value": "quxC" }
]
'''
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self._patchIn(new_root)
+ self.reRoot()
initer = stages.Init()
initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)
initer.read_cfg()
@@ -167,9 +160,7 @@ class TestConsumeUserData(helpers.FilesystemMockingTestCase):
{ "op": "add", "path": "/foo", "value": "quxC" }
]
'''
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self._patchIn(new_root)
+ self.reRoot()
initer = stages.Init()
initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)
initer.read_cfg()
@@ -212,12 +203,9 @@ c: d
message.attach(message_cc)
message.attach(message_jp)
+ self.reRoot()
ci = stages.Init()
ci.datasource = FakeDataSource(str(message))
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self.patchUtils(new_root)
- self.patchOS(new_root)
ci.fetch()
ci.consume_data()
cc_contents = util.load_file(ci.paths.get_ipath("cloud_config"))
@@ -245,9 +233,7 @@ name: user
run:
- z
'''
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self._patchIn(new_root)
+ self.reRoot()
initer = stages.Init()
initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)
initer.read_cfg()
@@ -281,9 +267,7 @@ vendor_data:
enabled: True
prefix: /bin/true
'''
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self._patchIn(new_root)
+ new_root = self.reRoot()
initer = stages.Init()
initer.datasource = FakeDataSource(user_blob, vendordata=vendor_blob)
initer.read_cfg()
@@ -342,10 +326,7 @@ p: 1
paths = c_helpers.Paths({}, ds=FakeDataSource(''))
cloud_cfg = handlers.cloud_config.CloudConfigPartHandler(paths)
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self.patchUtils(new_root)
- self.patchOS(new_root)
+ self.reRoot()
cloud_cfg.handle_part(None, handlers.CONTENT_START, None, None, None,
None)
for i, m in enumerate(messages):
@@ -365,6 +346,7 @@ p: 1
def test_unhandled_type_warning(self):
"""Raw text without magic is ignored but shows warning."""
+ self.reRoot()
ci = stages.Init()
data = "arbitrary text\n"
ci.datasource = FakeDataSource(data)
@@ -402,10 +384,7 @@ c: 4
message.attach(gzip_part(base_content2))
ci = stages.Init()
ci.datasource = FakeDataSource(str(message))
- new_root = tempfile.mkdtemp()
- self.addCleanup(shutil.rmtree, new_root)
- self.patchUtils(new_root)
- self.patchOS(new_root)
+ self.reRoot()
ci.fetch()
ci.consume_data()
contents = util.load_file(ci.paths.get_ipath("cloud_config"))
@@ -418,6 +397,7 @@ c: 4
def test_mime_text_plain(self):
"""Mime message of type text/plain is ignored but shows warning."""
+ self.reRoot()
ci = stages.Init()
message = MIMEBase("text", "plain")
message.set_payload("Just text")
@@ -435,6 +415,7 @@ c: 4
def test_shellscript(self):
"""Raw text starting #!/bin/sh is treated as script."""
+ self.reRoot()
ci = stages.Init()
script = "#!/bin/sh\necho hello\n"
ci.datasource = FakeDataSource(script)
@@ -453,6 +434,7 @@ c: 4
def test_mime_text_x_shellscript(self):
"""Mime message of type text/x-shellscript is treated as script."""
+ self.reRoot()
ci = stages.Init()
script = "#!/bin/sh\necho hello\n"
message = MIMEBase("text", "x-shellscript")
@@ -473,6 +455,7 @@ c: 4
def test_mime_text_plain_shell(self):
"""Mime type text/plain starting #!/bin/sh is treated as script."""
+ self.reRoot()
ci = stages.Init()
script = "#!/bin/sh\necho hello\n"
message = MIMEBase("text", "plain")
@@ -493,6 +476,7 @@ c: 4
def test_mime_application_octet_stream(self):
"""Mime type application/octet-stream is ignored but shows warning."""
+ self.reRoot()
ci = stages.Init()
message = MIMEBase("application", "octet-stream")
message.set_payload(b'\xbf\xe6\xb2\xc3\xd3\xba\x13\xa4\xd8\xa1\xcc')
@@ -516,6 +500,7 @@ c: 4
{'content': non_decodable}]
message = b'#cloud-config-archive\n' + util.yaml_dumps(data).encode()
+ self.reRoot()
ci = stages.Init()
ci.datasource = FakeDataSource(message)
diff --git a/tests/unittests/test_datasource/test_opennebula.py b/tests/unittests/test_datasource/test_opennebula.py
index d796f030..ce5b5550 100644
--- a/tests/unittests/test_datasource/test_opennebula.py
+++ b/tests/unittests/test_datasource/test_opennebula.py
@@ -1,7 +1,7 @@
from cloudinit import helpers
from cloudinit.sources import DataSourceOpenNebula as ds
from cloudinit import util
-from ..helpers import TestCase, populate_dir
+from ..helpers import mock, populate_dir, TestCase
import os
import pwd
@@ -31,12 +31,7 @@ SSH_KEY = 'ssh-rsa AAAAB3NzaC1....sIkJhq8wdX+4I3A4cYbYP ubuntu@server-460-%i'
HOSTNAME = 'foo.example.com'
PUBLIC_IP = '10.0.0.3'
-CMD_IP_OUT = '''\
-1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
- link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
-2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
- link/ether 02:00:0a:12:01:01 brd ff:ff:ff:ff:ff:ff
-'''
+DS_PATH = "cloudinit.sources.DataSourceOpenNebula"
class TestOpenNebulaDataSource(TestCase):
@@ -233,18 +228,19 @@ class TestOpenNebulaDataSource(TestCase):
class TestOpenNebulaNetwork(unittest.TestCase):
- def setUp(self):
- super(TestOpenNebulaNetwork, self).setUp()
+ system_nics = {'02:00:0a:12:01:01': 'eth0'}
def test_lo(self):
- net = ds.OpenNebulaNetwork('', {})
+ net = ds.OpenNebulaNetwork(context={}, system_nics_by_mac={})
self.assertEqual(net.gen_conf(), u'''\
auto lo
iface lo inet loopback
''')
- def test_eth0(self):
- net = ds.OpenNebulaNetwork(CMD_IP_OUT, {})
+ @mock.patch(DS_PATH + ".get_physical_nics_by_mac")
+ def test_eth0(self, m_get_phys_by_mac):
+ m_get_phys_by_mac.return_value = self.system_nics
+ net = ds.OpenNebulaNetwork({})
self.assertEqual(net.gen_conf(), u'''\
auto lo
iface lo inet loopback
@@ -267,7 +263,8 @@ iface eth0 inet static
'ETH0_DNS': '1.2.3.6 1.2.3.7'
}
- net = ds.OpenNebulaNetwork(CMD_IP_OUT, context)
+ net = ds.OpenNebulaNetwork(context,
+ system_nics_by_mac=self.system_nics)
self.assertEqual(net.gen_conf(), u'''\
auto lo
iface lo inet loopback
diff --git a/tests/unittests/test_distros/test_user_data_normalize.py b/tests/unittests/test_distros/test_user_data_normalize.py
index a887a930..33bf922d 100644..100755
--- a/tests/unittests/test_distros/test_user_data_normalize.py
+++ b/tests/unittests/test_distros/test_user_data_normalize.py
@@ -1,8 +1,10 @@
from cloudinit import distros
+from cloudinit.distros import ug_util
from cloudinit import helpers
from cloudinit import settings
from ..helpers import TestCase
+import mock
bcfg = {
@@ -29,7 +31,7 @@ class TestUGNormalize(TestCase):
return distro
def _norm(self, cfg, distro):
- return distros.normalize_users_groups(cfg, distro)
+ return ug_util.normalize_users_groups(cfg, distro)
def test_group_dict(self):
distro = self._make_distro('ubuntu')
@@ -236,7 +238,7 @@ class TestUGNormalize(TestCase):
}
(users, _groups) = self._norm(ug_cfg, distro)
self.assertIn('bob', users)
- (name, config) = distros.extract_default(users)
+ (name, config) = ug_util.extract_default(users)
self.assertEqual(name, 'bob')
expected_config = {}
def_config = None
@@ -295,3 +297,67 @@ class TestUGNormalize(TestCase):
self.assertIn('bob', users)
self.assertEqual({'default': False}, users['joe'])
self.assertEqual({'default': False}, users['bob'])
+
+ @mock.patch('cloudinit.util.subp')
+ def test_create_snap_user(self, mock_subp):
+ mock_subp.side_effect = [('{"username": "joe", "ssh-key-count": 1}\n',
+ '')]
+ distro = self._make_distro('ubuntu')
+ ug_cfg = {
+ 'users': [
+ {'name': 'joe', 'snapuser': 'joe@joe.com'},
+ ],
+ }
+ (users, _groups) = self._norm(ug_cfg, distro)
+ for (user, config) in users.items():
+ print('user=%s config=%s' % (user, config))
+ username = distro.create_user(user, **config)
+
+ snapcmd = ['snap', 'create-user', '--sudoer', '--json', 'joe@joe.com']
+ mock_subp.assert_called_with(snapcmd, capture=True, logstring=snapcmd)
+ self.assertEqual(username, 'joe')
+
+ @mock.patch('cloudinit.util.subp')
+ def test_create_snap_user_known(self, mock_subp):
+ mock_subp.side_effect = [('{"username": "joe", "ssh-key-count": 1}\n',
+ '')]
+ distro = self._make_distro('ubuntu')
+ ug_cfg = {
+ 'users': [
+ {'name': 'joe', 'snapuser': 'joe@joe.com', 'known': True},
+ ],
+ }
+ (users, _groups) = self._norm(ug_cfg, distro)
+ for (user, config) in users.items():
+ print('user=%s config=%s' % (user, config))
+ username = distro.create_user(user, **config)
+
+ snapcmd = ['snap', 'create-user', '--sudoer', '--json', '--known',
+ 'joe@joe.com']
+ mock_subp.assert_called_with(snapcmd, capture=True, logstring=snapcmd)
+ self.assertEqual(username, 'joe')
+
+ @mock.patch('cloudinit.util.system_is_snappy')
+ @mock.patch('cloudinit.util.is_group')
+ @mock.patch('cloudinit.util.subp')
+ def test_add_user_on_snappy_system(self, mock_subp, mock_isgrp,
+ mock_snappy):
+ mock_isgrp.return_value = False
+ mock_subp.return_value = True
+ mock_snappy.return_value = True
+ distro = self._make_distro('ubuntu')
+ ug_cfg = {
+ 'users': [
+ {'name': 'joe', 'groups': 'users', 'create_groups': True},
+ ],
+ }
+ (users, _groups) = self._norm(ug_cfg, distro)
+ for (user, config) in users.items():
+ print('user=%s config=%s' % (user, config))
+ distro.add_user(user, **config)
+
+ groupcmd = ['groupadd', 'users', '--extrausers']
+ addcmd = ['useradd', 'joe', '--extrausers', '--groups', 'users', '-m']
+
+ mock_subp.assert_any_call(groupcmd)
+ mock_subp.assert_any_call(addcmd, logstring=addcmd)
diff --git a/tests/unittests/test_handler/test_handler_apt_conf_v1.py b/tests/unittests/test_handler/test_handler_apt_conf_v1.py
index 45714efd..64acc3e0 100644
--- a/tests/unittests/test_handler/test_handler_apt_conf_v1.py
+++ b/tests/unittests/test_handler/test_handler_apt_conf_v1.py
@@ -118,7 +118,7 @@ class TestConversion(TestCase):
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, {m['uri'] for m in f['apt']['primary']})
+ self.assertIn(mirror, set(m['uri'] for m in f['apt']['primary']))
def test_no_old_content(self):
mirror = 'http://my.mirror/ubuntu'
diff --git a/tests/unittests/test_handler/test_handler_snappy.py b/tests/unittests/test_handler/test_handler_snappy.py
index 57dce1bc..e320dd82 100644
--- a/tests/unittests/test_handler/test_handler_snappy.py
+++ b/tests/unittests/test_handler/test_handler_snappy.py
@@ -1,14 +1,22 @@
from cloudinit.config.cc_snappy import (
makeop, get_package_ops, render_snap_op)
-from cloudinit import util
+from cloudinit.config.cc_snap_config import (
+ add_assertions, add_snap_user, ASSERTIONS_FILE)
+from cloudinit import (distros, helpers, cloud, util)
+from cloudinit.config.cc_snap_config import handle as snap_handle
+from cloudinit.sources import DataSourceNone
+from ..helpers import FilesystemMockingTestCase, mock
from .. import helpers as t_help
+import logging
import os
import shutil
import tempfile
+import textwrap
import yaml
+LOG = logging.getLogger(__name__)
ALLOWED = (dict, list, int, str)
@@ -287,6 +295,289 @@ class TestInstallPackages(t_help.TestCase):
self.assertEqual(yaml.safe_load(mydata), data_found)
+class TestSnapConfig(FilesystemMockingTestCase):
+
+ SYSTEM_USER_ASSERTION = textwrap.dedent("""
+ type: system-user
+ authority-id: LqvZQdfyfGlYvtep4W6Oj6pFXP9t1Ksp
+ brand-id: LqvZQdfyfGlYvtep4W6Oj6pFXP9t1Ksp
+ email: foo@bar.com
+ password: $6$E5YiAuMIPAwX58jG$miomhVNui/vf7f/3ctB/f0RWSKFxG0YXzrJ9rtJ1ikvzt
+ series:
+ - 16
+ since: 2016-09-10T16:34:00+03:00
+ until: 2017-11-10T16:34:00+03:00
+ username: baz
+ sign-key-sha3-384: RuVvnp4n52GilycjfbbTCI3_L8Y6QlIE75wxMc0KzGV3AUQqVd9GuXoj
+
+ AcLBXAQAAQoABgUCV/UU1wAKCRBKnlMoJQLkZVeLD/9/+hIeVywtzsDA3oxl+P+u9D13y9s6svP
+ Jd6Wnf4FTw6sq1GjBE4ZA7lrwSaRCUJ9Vcsvf2q9OGPY7mOb2TBxaDe0PbUMjrSrqllSSQwhpNI
+ zG+NxkkKuxsUmLzFa+k9m6cyojNbw5LFhQZBQCGlr3JYqC0tIREq/UsZxj+90TUC87lDJwkU8GF
+ s4CR+rejZj4itIcDcVxCSnJH6hv6j2JrJskJmvObqTnoOlcab+JXdamXqbldSP3UIhWoyVjqzkj
+ +to7mXgx+cCUA9+ngNCcfUG+1huGGTWXPCYkZ78HvErcRlIdeo4d3xwtz1cl/w3vYnq9og1XwsP
+ Yfetr3boig2qs1Y+j/LpsfYBYncgWjeDfAB9ZZaqQz/oc8n87tIPZDJHrusTlBfop8CqcM4xsKS
+ d+wnEY8e/F24mdSOYmS1vQCIDiRU3MKb6x138Ud6oHXFlRBbBJqMMctPqWDunWzb5QJ7YR0I39q
+ BrnEqv5NE0G7w6HOJ1LSPG5Hae3P4T2ea+ATgkb03RPr3KnXnzXg4TtBbW1nytdlgoNc/BafE1H
+ f3NThcq9gwX4xWZ2PAWnqVPYdDMyCtzW3Ck+o6sIzx+dh4gDLPHIi/6TPe/pUuMop9CBpWwez7V
+ v1z+1+URx6Xlq3Jq18y5pZ6fY3IDJ6km2nQPMzcm4Q==""")
+
+ ACCOUNT_ASSERTION = textwrap.dedent("""
+ type: account-key
+ authority-id: canonical
+ revision: 2
+ public-key-sha3-384: BWDEoaqyr25nF5SNCvEv2v7QnM9QsfCc0PBMYD_i2NGSQ32EF2d4D0
+ account-id: canonical
+ name: store
+ since: 2016-04-01T00:00:00.0Z
+ body-length: 717
+ sign-key-sha3-384: -CvQKAwRQ5h3Ffn10FILJoEZUXOv6km9FwA80-Rcj-f-6jadQ89VRswH
+
+ AcbBTQRWhcGAARAA0KKYYQWuHOrsFVi4p4l7ZzSvX7kLgJFFeFgOkzdWKBTHEnsMKjl5mefFe9j
+ qe8NlmJdfY7BenP7XeBtwKp700H/t9lLrZbpTNAPHXYxEWFJp5bPqIcJYBZ+29oLVLN1Tc5X482
+ vCiDqL8+pPYqBrK2fNlyPlNNSum9wI70rDDL4r6FVvr+osTnGejibdV8JphWX+lrSQDnRSdM8KJ
+ UM43vTgLGTi9W54oRhsA2OFexRfRksTrnqGoonCjqX5wO3OFSaMDzMsO2MJ/hPfLgDqw53qjzuK
+ Iec9OL3k5basvu2cj5u9tKwVFDsCKK2GbKUsWWpx2KTpOifmhmiAbzkTHbH9KaoMS7p0kJwhTQG
+ o9aJ9VMTWHJc/NCBx7eu451u6d46sBPCXS/OMUh2766fQmoRtO1OwCTxsRKG2kkjbMn54UdFULl
+ VfzvyghMNRKIezsEkmM8wueTqGUGZWa6CEZqZKwhe/PROxOPYzqtDH18XZknbU1n5lNb7vNfem9
+ 2ai+3+JyFnW9UhfvpVF7gzAgdyCqNli4C6BIN43uwoS8HkykocZS/+Gv52aUQ/NZ8BKOHLw+7an
+ Q0o8W9ltSLZbEMxFIPSN0stiZlkXAp6DLyvh1Y4wXSynDjUondTpej2fSvSlCz/W5v5V7qA4nIc
+ vUvV7RjVzv17ut0AEQEAAQ==
+
+ AcLDXAQAAQoABgUCV83k9QAKCRDUpVvql9g3IBT8IACKZ7XpiBZ3W4lqbPssY6On81WmxQLtvsM
+ WTp6zZpl/wWOSt2vMNUk9pvcmrNq1jG9CuhDfWFLGXEjcrrmVkN3YuCOajMSPFCGrxsIBLSRt/b
+ nrKykdLAAzMfG8rP1d82bjFFiIieE+urQ0Kcv09Jtdvavq3JT1Tek5mFyyfhHNlQEKOzWqmRWiL
+ 3c3VOZUs1ZD8TSlnuq/x+5T0X0YtOyGjSlVxk7UybbyMNd6MZfNaMpIG4x+mxD3KHFtBAC7O6kL
+ eX3i6j5nCY5UABfA3DZEAkWP4zlmdBEOvZ9t293NaDdOpzsUHRkoi0Zez/9BHQ/kwx/uNc2WqrY
+ inCmu16JGNeXqsyinnLl7Ghn2RwhvDMlLxF6RTx8xdx1yk6p3PBTwhZMUvuZGjUtN/AG8BmVJQ1
+ rsGSRkkSywvnhVJRB2sudnrMBmNS2goJbzSbmJnOlBrd2WsV0T9SgNMWZBiov3LvU4o2SmAb6b+
+ rYwh8H5QHcuuYJuxDjFhPswIp6Wes5T6hUicf3SWtObcDS4HSkVS4ImBjjX9YgCuFy7QdnooOWE
+ aPvkRw3XCVeYq0K6w9GRsk1YFErD4XmXXZjDYY650MX9v42Sz5MmphHV8jdIY5ssbadwFSe2rCQ
+ 6UX08zy7RsIb19hTndE6ncvSNDChUR9eEnCm73eYaWTWTnq1cxdVP/s52r8uss++OYOkPWqh5nO
+ haRn7INjH/yZX4qXjNXlTjo0PnHH0q08vNKDwLhxS+D9du+70FeacXFyLIbcWllSbJ7DmbumGpF
+ yYbtj3FDDPzachFQdIG3lSt+cSUGeyfSs6wVtc3cIPka/2Urx7RprfmoWSI6+a5NcLdj0u2z8O9
+ HxeIgxDpg/3gT8ZIuFKePMcLDM19Fh/p0ysCsX+84B9chNWtsMSmIaE57V+959MVtsLu7SLb9gi
+ skrju0pQCwsu2wHMLTNd1f3PTHmrr49hxetTus07HSQUApMtAGKzQilF5zqFjbyaTd4xgQbd+PK
+ CjFyzQTDOcUhXpuUGt/IzlqiFfsCsmbj2K4KdSNYMlqIgZ3Azu8KvZLIhsyN7v5vNIZSPfEbjde
+ ClU9r0VRiJmtYBUjcSghD9LWn+yRLwOxhfQVjm0cBwIt5R/yPF/qC76yIVuWUtM5Y2/zJR1J8OF
+ qWchvlImHtvDzS9FQeLyzJAOjvZ2CnWp2gILgUz0WQdOk1Dq8ax7KS9BQ42zxw9EZAEPw3PEFqR
+ IQsRTONp+iVS8YxSmoYZjDlCgRMWUmawez/Fv5b9Fb/XkO5Eq4e+KfrpUujXItaipb+tV8h5v3t
+ oG3Ie3WOHrVjCLXIdYslpL1O4nadqR6Xv58pHj6k""")
+
+ test_assertions = [ACCOUNT_ASSERTION, SYSTEM_USER_ASSERTION]
+
+ def setUp(self):
+ super(TestSnapConfig, self).setUp()
+ self.subp = util.subp
+ self.new_root = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, self.new_root)
+
+ def _get_cloud(self, distro, metadata=None):
+ self.patchUtils(self.new_root)
+ paths = helpers.Paths({})
+ cls = distros.fetch(distro)
+ mydist = cls(distro, {}, paths)
+ myds = DataSourceNone.DataSourceNone({}, mydist, paths)
+ if metadata:
+ myds.metadata.update(metadata)
+ return cloud.Cloud(myds, paths, {}, mydist, None)
+
+ @mock.patch('cloudinit.util.write_file')
+ @mock.patch('cloudinit.util.subp')
+ def test_snap_config_add_assertions(self, msubp, mwrite):
+ add_assertions(self.test_assertions)
+
+ combined = "\n".join(self.test_assertions)
+ mwrite.assert_any_call(ASSERTIONS_FILE, combined.encode('utf-8'))
+ msubp.assert_called_with(['snap', 'ack', ASSERTIONS_FILE],
+ capture=True)
+
+ def test_snap_config_add_assertions_empty(self):
+ self.assertRaises(ValueError, add_assertions, [])
+
+ def test_add_assertions_nonlist(self):
+ self.assertRaises(ValueError, add_assertions, {})
+
+ @mock.patch('cloudinit.util.write_file')
+ @mock.patch('cloudinit.util.subp')
+ def test_snap_config_add_assertions_ack_fails(self, msubp, mwrite):
+ msubp.side_effect = [util.ProcessExecutionError("Invalid assertion")]
+ self.assertRaises(util.ProcessExecutionError, add_assertions,
+ self.test_assertions)
+
+ @mock.patch('cloudinit.config.cc_snap_config.add_assertions')
+ @mock.patch('cloudinit.config.cc_snap_config.util')
+ def test_snap_config_handle_no_config(self, mock_util, mock_add):
+ cfg = {}
+ cc = self._get_cloud('ubuntu')
+ cc.distro = mock.MagicMock()
+ cc.distro.name = 'ubuntu'
+ mock_util.which.return_value = None
+ snap_handle('snap_config', cfg, cc, LOG, None)
+ mock_add.assert_not_called()
+
+ def test_snap_config_add_snap_user_no_config(self):
+ usercfg = add_snap_user(cfg=None)
+ self.assertEqual(usercfg, None)
+
+ def test_snap_config_add_snap_user_not_dict(self):
+ cfg = ['foobar']
+ self.assertRaises(ValueError, add_snap_user, cfg)
+
+ def test_snap_config_add_snap_user_no_email(self):
+ cfg = {'assertions': [], 'known': True}
+ usercfg = add_snap_user(cfg=cfg)
+ self.assertEqual(usercfg, None)
+
+ @mock.patch('cloudinit.config.cc_snap_config.util')
+ def test_snap_config_add_snap_user_email_only(self, mock_util):
+ email = 'janet@planetjanet.org'
+ cfg = {'email': email}
+ mock_util.which.return_value = None
+ mock_util.system_is_snappy.return_value = True
+ mock_util.subp.side_effect = [
+ ("false\n", ""), # snap managed
+ ]
+
+ usercfg = add_snap_user(cfg=cfg)
+
+ self.assertEqual(usercfg, {'snapuser': email, 'known': False})
+
+ @mock.patch('cloudinit.config.cc_snap_config.util')
+ def test_snap_config_add_snap_user_email_known(self, mock_util):
+ email = 'janet@planetjanet.org'
+ known = True
+ cfg = {'email': email, 'known': known}
+ mock_util.which.return_value = None
+ mock_util.system_is_snappy.return_value = True
+ mock_util.subp.side_effect = [
+ ("false\n", ""), # snap managed
+ (self.SYSTEM_USER_ASSERTION, ""), # snap known system-user
+ ]
+
+ usercfg = add_snap_user(cfg=cfg)
+
+ self.assertEqual(usercfg, {'snapuser': email, 'known': known})
+
+ @mock.patch('cloudinit.config.cc_snap_config.add_assertions')
+ @mock.patch('cloudinit.config.cc_snap_config.util')
+ def test_snap_config_handle_system_not_snappy(self, mock_util, mock_add):
+ cfg = {'snappy': {'assertions': self.test_assertions}}
+ cc = self._get_cloud('ubuntu')
+ cc.distro = mock.MagicMock()
+ cc.distro.name = 'ubuntu'
+ mock_util.which.return_value = None
+ mock_util.system_is_snappy.return_value = False
+
+ snap_handle('snap_config', cfg, cc, LOG, None)
+
+ mock_add.assert_not_called()
+
+ @mock.patch('cloudinit.config.cc_snap_config.add_assertions')
+ @mock.patch('cloudinit.config.cc_snap_config.util')
+ def test_snap_config_handle_snapuser(self, mock_util, mock_add):
+ email = 'janet@planetjanet.org'
+ cfg = {
+ 'snappy': {
+ 'assertions': self.test_assertions,
+ 'email': email,
+ }
+ }
+ cc = self._get_cloud('ubuntu')
+ cc.distro = mock.MagicMock()
+ cc.distro.name = 'ubuntu'
+ mock_util.which.return_value = None
+ mock_util.system_is_snappy.return_value = True
+ mock_util.subp.side_effect = [
+ ("false\n", ""), # snap managed
+ ]
+
+ snap_handle('snap_config', cfg, cc, LOG, None)
+
+ mock_add.assert_called_with(self.test_assertions)
+ usercfg = {'snapuser': email, 'known': False}
+ cc.distro.create_user.assert_called_with(email, **usercfg)
+
+ @mock.patch('cloudinit.config.cc_snap_config.add_assertions')
+ @mock.patch('cloudinit.config.cc_snap_config.util')
+ def test_snap_config_handle_snapuser_known(self, mock_util, mock_add):
+ email = 'janet@planetjanet.org'
+ cfg = {
+ 'snappy': {
+ 'assertions': self.test_assertions,
+ 'email': email,
+ 'known': True,
+ }
+ }
+ cc = self._get_cloud('ubuntu')
+ cc.distro = mock.MagicMock()
+ cc.distro.name = 'ubuntu'
+ mock_util.which.return_value = None
+ mock_util.system_is_snappy.return_value = True
+ mock_util.subp.side_effect = [
+ ("false\n", ""), # snap managed
+ (self.SYSTEM_USER_ASSERTION, ""), # snap known system-user
+ ]
+
+ snap_handle('snap_config', cfg, cc, LOG, None)
+
+ mock_add.assert_called_with(self.test_assertions)
+ usercfg = {'snapuser': email, 'known': True}
+ cc.distro.create_user.assert_called_with(email, **usercfg)
+
+ @mock.patch('cloudinit.config.cc_snap_config.add_assertions')
+ @mock.patch('cloudinit.config.cc_snap_config.util')
+ def test_snap_config_handle_snapuser_known_managed(self, mock_util,
+ mock_add):
+ email = 'janet@planetjanet.org'
+ cfg = {
+ 'snappy': {
+ 'assertions': self.test_assertions,
+ 'email': email,
+ 'known': True,
+ }
+ }
+ cc = self._get_cloud('ubuntu')
+ cc.distro = mock.MagicMock()
+ cc.distro.name = 'ubuntu'
+ mock_util.which.return_value = None
+ mock_util.system_is_snappy.return_value = True
+ mock_util.subp.side_effect = [
+ ("true\n", ""), # snap managed
+ ]
+
+ snap_handle('snap_config', cfg, cc, LOG, None)
+
+ mock_add.assert_called_with(self.test_assertions)
+ cc.distro.create_user.assert_not_called()
+
+ @mock.patch('cloudinit.config.cc_snap_config.add_assertions')
+ @mock.patch('cloudinit.config.cc_snap_config.util')
+ def test_snap_config_handle_snapuser_known_no_assertion(self, mock_util,
+ mock_add):
+ email = 'janet@planetjanet.org'
+ cfg = {
+ 'snappy': {
+ 'assertions': [self.ACCOUNT_ASSERTION],
+ 'email': email,
+ 'known': True,
+ }
+ }
+ cc = self._get_cloud('ubuntu')
+ cc.distro = mock.MagicMock()
+ cc.distro.name = 'ubuntu'
+ mock_util.which.return_value = None
+ mock_util.system_is_snappy.return_value = True
+ mock_util.subp.side_effect = [
+ ("true\n", ""), # snap managed
+ ("", ""), # snap known system-user
+ ]
+
+ snap_handle('snap_config', cfg, cc, LOG, None)
+
+ mock_add.assert_called_with([self.ACCOUNT_ASSERTION])
+ cc.distro.create_user.assert_not_called()
+
+
def makeop_tmpd(tmpd, op, name, config=None, path=None, cfgfile=None):
if cfgfile:
cfgfile = os.path.sep.join([tmpd, cfgfile])
diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py
index fc6b9d40..881509aa 100644
--- a/tests/unittests/test_util.py
+++ b/tests/unittests/test_util.py
@@ -553,7 +553,7 @@ class TestSubp(helpers.TestCase):
def test_subp_decode_invalid_utf8_replaces(self):
(out, _err) = util.subp(self.stdin2out, capture=True,
data=self.utf8_invalid)
- expected = self.utf8_invalid.decode('utf-8', errors='replace')
+ expected = self.utf8_invalid.decode('utf-8', 'replace')
self.assertEqual(out, expected)
def test_subp_decode_strict_raises(self):