1
# Copyright 2005-2012 Canonical Ltd. This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
4
"""Tests for provisioning configuration."""
6
from __future__ import (
15
from functools import partial
16
from getpass import getuser
18
from textwrap import dedent
20
from fixtures import EnvironmentVariableFixture
22
from maastesting.factory import factory
23
from maastesting.testcase import TestCase
24
from provisioningserver.config import Config
25
from provisioningserver.testing.config import ConfigFixture
26
from testtools.matchers import (
35
class TestConfigFixture(TestCase):
36
"""Tests for `provisioningserver.testing.config.ConfigFixture`."""
38
def exercise_fixture(self, fixture):
39
# ConfigFixture arranges a minimal configuration on disk, and exports
40
# the configuration filename to the environment so that subprocesses
43
self.assertThat(fixture.dir, DirExists())
44
self.assertThat(fixture.filename, FileExists())
46
{"MAAS_PROVISIONING_SETTINGS": fixture.filename},
49
fixture.filename, os.environ["MAAS_PROVISIONING_SETTINGS"])
50
with open(fixture.filename, "rb") as stream:
51
self.assertEqual(fixture.config, yaml.safe_load(stream))
53
def test_use_minimal(self):
54
# With no arguments, ConfigFixture arranges a minimal configuration.
55
fixture = ConfigFixture()
56
self.exercise_fixture(fixture)
58
def test_use_with_config(self):
59
# Given a configuration, ConfigFixture can arrange a minimal global
60
# configuration with the additional options merged in.
61
dummy_logfile = factory.make_name("logfile")
62
fixture = ConfigFixture({"logfile": dummy_logfile})
63
self.assertEqual(dummy_logfile, fixture.config["logfile"])
64
self.exercise_fixture(fixture)
67
class TestConfig_DEFAULT_FILENAME(TestCase):
68
"""Tests for `provisioningserver.config.Config.DEFAULT_FILENAME`."""
71
super(TestConfig_DEFAULT_FILENAME, self).setUp()
72
# Start with a clean environment every time.
73
fixture = EnvironmentVariableFixture("MAAS_PROVISIONING_SETTINGS")
74
self.useFixture(fixture)
76
def test_get_with_environment_empty(self):
77
self.assertEqual("/etc/maas/pserv.yaml", Config.DEFAULT_FILENAME)
79
def test_get_with_environment_set(self):
80
dummy_filename = factory.make_name("config")
81
fixture = EnvironmentVariableFixture(
82
"MAAS_PROVISIONING_SETTINGS", dummy_filename)
83
self.useFixture(fixture)
84
self.assertEqual(dummy_filename, Config.DEFAULT_FILENAME)
87
dummy_filename = factory.make_name("config")
88
Config.DEFAULT_FILENAME = dummy_filename
89
self.assertEqual(dummy_filename, Config.DEFAULT_FILENAME)
91
def test_delete(self):
92
Config.DEFAULT_FILENAME = factory.make_name("config")
93
del Config.DEFAULT_FILENAME
94
# The filename reverts; see test_get_with_environment_empty.
95
self.assertEqual("/etc/maas/pserv.yaml", Config.DEFAULT_FILENAME)
96
# The delete does not fail when called multiple times.
97
del Config.DEFAULT_FILENAME
100
class TestConfig(TestCase):
101
"""Tests for `provisioningserver.config.Config`."""
103
def test_defaults(self):
104
dummy_password = factory.make_name("password")
109
'username': getuser(),
114
'url': 'http://localhost/cobbler_api',
115
'username': getuser(),
118
'logfile': 'pserv.log',
124
'generator': 'http://localhost:5243/api/1.0/pxeconfig',
126
'root': "/var/lib/tftpboot",
128
'interface': '127.0.0.1',
130
'username': getuser(),
131
'password': dummy_password,
133
# The password field is set to a random 12-digit string if not
134
# specified. This prevents access, but makes testing easier in other
136
self.patch(Config.field("password"), "if_missing", dummy_password)
137
observed = Config.to_python({})
138
self.assertEqual(expected, observed)
140
def test_parse(self):
141
# Configuration can be parsed from a snippet of YAML.
142
observed = Config.parse(
143
b'logfile: "/some/where.log"\n'
144
b'password: "black_sabbath"\n'
146
self.assertEqual("/some/where.log", observed["logfile"])
149
# Configuration can be loaded and parsed from a file.
151
logfile: "/some/where.log"
153
filename = self.make_file(name="config.yaml", contents=config)
154
observed = Config.load(filename)
155
self.assertEqual("/some/where.log", observed["logfile"])
157
def test_load_example(self):
158
# The example configuration can be loaded and validated.
159
filename = os.path.join(
160
os.path.dirname(__file__), os.pardir,
161
os.pardir, os.pardir, "etc", "pserv.yaml")
162
Config.load(filename)
164
def test_load_from_cache(self):
165
# A config loaded by Config.load_from_cache() is never reloaded.
166
filename = self.make_file(name="config.yaml", contents='')
167
config_before = Config.load_from_cache(filename)
169
config_after = Config.load_from_cache(filename)
170
self.assertIs(config_before, config_after)
172
def test_oops_directory_without_reporter(self):
173
# It is an error to omit the OOPS reporter if directory is specified.
176
' directory: /tmp/oops\n'
178
expected = MatchesException(
179
formencode.Invalid, "oops: You must give a value for reporter")
181
partial(Config.parse, config),
184
def test_field(self):
185
self.assertIs(Config, Config.field())
186
self.assertIs(Config.fields["tftp"], Config.field("tftp"))
188
Config.fields["tftp"].fields["root"],
189
Config.field("tftp", "root"))