|
Server : Apache System : Linux server.mata-lashes.com 3.10.0-1160.90.1.el7.x86_64 #1 SMP Thu May 4 15:21:22 UTC 2023 x86_64 User : matalashes ( 1004) PHP Version : 8.1.29 Disable Function : NONE Directory : /usr/src/cloud-init/tests/unittests/config/ |
Upload File : |
# This file is part of cloud-init. See LICENSE file for license information.
import logging
import pytest
from configobj import ConfigObj
from cloudinit import util
from cloudinit.config import cc_landscape
from cloudinit.config.schema import (
SchemaValidationError,
get_schema,
validate_cloudconfig_schema,
)
from tests.unittests.helpers import (
FilesystemMockingTestCase,
mock,
skipUnlessJsonSchema,
wrap_and_call,
)
from tests.unittests.util import get_cloud
LOG = logging.getLogger(__name__)
class TestLandscape(FilesystemMockingTestCase):
with_logs = True
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.patchUtils(self.new_root)
self.add_patch(
"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.distro = mock.MagicMock()
cfg = {"landscape": {}}
cc_landscape.handle("notimportant", cfg, mycloud, 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"}
with self.assertRaises(RuntimeError) as context_manager:
cc_landscape.handle("notimportant", cfg, mycloud, None)
self.assertIn(
"'landscape' key existed in config, but not a dict",
str(context_manager.exception),
)
@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": {}}}
wrap_and_call(
"cloudinit.config.cc_landscape",
{"LSC_CLIENT_CFG_FILE": {"new": self.conf}},
cc_landscape.handle,
"notimportant",
cfg,
mycloud,
None,
)
self.assertEqual(
[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.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,
None,
)
self.assertEqual(
[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(),
)
default_content = util.load_file(self.default_file)
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",
}
}
wrap_and_call(
"cloudinit.config.cc_landscape",
{"LSC_CLIENT_CFG_FILE": {"new": self.conf}},
cc_landscape.handle,
"notimportant",
cfg,
mycloud,
None,
)
self.assertEqual(expected, dict(ConfigObj(self.conf)))
self.assertIn(
"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",
}
}
wrap_and_call(
"cloudinit.config.cc_landscape",
{"LSC_CLIENT_CFG_FILE": {"new": self.conf}},
cc_landscape.handle,
"notimportant",
cfg,
mycloud,
None,
)
self.assertEqual(expected, dict(ConfigObj(self.conf)))
self.assertIn(
"Wrote landscape config file to {0}".format(self.conf),
self.logs.getvalue(),
)
class TestLandscapeSchema:
@pytest.mark.parametrize(
"config, error_msg",
[
# Allow undocumented keys client keys without error
({"landscape": {"client": {"allow_additional_keys": 1}}}, None),
# tags are comma-delimited
({"landscape": {"client": {"tags": "1,2,3"}}}, None),
({"landscape": {"client": {"tags": "1"}}}, None),
(
{
"landscape": {
"client": {},
"random-config-value": {"tags": "1"},
}
},
"Additional properties are not allowed",
),
# Require client key
({"landscape": {}}, "'client' is a required property"),
# tags are not whitespace-delimited
(
{"landscape": {"client": {"tags": "1, 2,3"}}},
"'1, 2,3' does not match",
),
],
)
@skipUnlessJsonSchema()
def test_schema_validation(self, config, error_msg):
if error_msg is None:
validate_cloudconfig_schema(config, get_schema(), strict=True)
else:
with pytest.raises(SchemaValidationError, match=error_msg):
validate_cloudconfig_schema(config, get_schema(), strict=True)