~lutostag/ubuntu/trusty/maas/1.5.2+packagefix

« back to all changes in this revision

Viewing changes to src/provisioningserver/tests/test_config.py

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez
  • Date: 2014-03-28 10:43:53 UTC
  • mto: This revision was merged to the branch mainline in revision 57.
  • Revision ID: package-import@ubuntu.com-20140328104353-ekpolg0pm5xnvq2s
Tags: upstream-1.5+bzr2204
ImportĀ upstreamĀ versionĀ 1.5+bzr2204

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2005-2013 Canonical Ltd.  This software is licensed under the
 
1
# Copyright 2005-2014 Canonical Ltd.  This software is licensed under the
2
2
# GNU Affero General Public License version 3 (see the file LICENSE).
3
3
 
4
4
"""Tests for provisioning configuration."""
15
15
__all__ = []
16
16
 
17
17
from copy import deepcopy
 
18
import errno
18
19
from functools import partial
19
20
from getpass import getuser
20
21
import os
22
23
 
23
24
from fixtures import EnvironmentVariableFixture
24
25
import formencode
 
26
import formencode.validators
25
27
from maastesting import root
26
28
from maastesting.factory import factory
27
29
from maastesting.testcase import MAASTestCase
28
 
from provisioningserver.config import Config
29
 
from provisioningserver.testing.config import ConfigFixture
 
30
from provisioningserver.config import (
 
31
    BootConfig,
 
32
    Config,
 
33
    ConfigBase,
 
34
    ConfigMeta,
 
35
    )
 
36
from provisioningserver.testing.config import ConfigFixtureBase
30
37
from testtools.matchers import (
31
38
    DirExists,
32
39
    FileContains,
37
44
import yaml
38
45
 
39
46
 
40
 
class TestConfigFixture(MAASTestCase):
41
 
    """Tests for `provisioningserver.testing.config.ConfigFixture`."""
 
47
class ExampleConfig(ConfigBase):
 
48
    """An example configuration schema.
 
49
 
 
50
    It derives from :class:`ConfigBase` and has a metaclass derived from
 
51
    :class:`ConfigMeta`, just as a "real" schema must.
 
52
    """
 
53
 
 
54
    class __metaclass__(ConfigMeta):
 
55
        envvar = "MAAS_TESTING_SETTINGS"
 
56
        default = "example.yaml"
 
57
 
 
58
    something = formencode.validators.String(if_missing="*missing*")
 
59
 
 
60
 
 
61
class ExampleConfigFixture(ConfigFixtureBase):
 
62
    """A fixture to help with testing :class:`ExampleConfig`."""
 
63
 
 
64
    schema = ExampleConfig
 
65
 
 
66
 
 
67
class TestConfigFixtureBase(MAASTestCase):
 
68
    """Tests for `ConfigFixtureBase`."""
42
69
 
43
70
    def exercise_fixture(self, fixture):
44
 
        # ConfigFixture arranges a minimal configuration on disk, and exports
45
 
        # the configuration filename to the environment so that subprocesses
46
 
        # can find it.
 
71
        # ConfigFixtureBase arranges a minimal configuration on disk,
 
72
        # and exports the configuration filename to the environment so
 
73
        # that subprocesses can find it.
47
74
        with fixture:
48
75
            self.assertThat(fixture.dir, DirExists())
49
76
            self.assertThat(fixture.filename, FileExists())
50
77
            self.assertEqual(
51
 
                {"MAAS_PROVISIONING_SETTINGS": fixture.filename},
 
78
                {fixture.schema.envvar: fixture.filename},
52
79
                fixture.environ)
53
80
            self.assertEqual(
54
 
                fixture.filename, os.environ["MAAS_PROVISIONING_SETTINGS"])
 
81
                fixture.filename, os.environ[fixture.schema.envvar])
55
82
            with open(fixture.filename, "rb") as stream:
56
83
                self.assertEqual(fixture.config, yaml.safe_load(stream))
57
84
 
58
85
    def test_use_minimal(self):
59
 
        # With no arguments, ConfigFixture arranges a minimal configuration.
60
 
        fixture = ConfigFixture()
 
86
        # With no arguments, ConfigFixtureBase arranges a minimal
 
87
        # configuration.
 
88
        fixture = ExampleConfigFixture()
61
89
        self.exercise_fixture(fixture)
62
90
 
63
91
    def test_use_with_config(self):
64
 
        # Given a configuration, ConfigFixture can arrange a minimal global
65
 
        # configuration with the additional options merged in.
66
 
        dummy_logfile = factory.make_name("logfile")
67
 
        fixture = ConfigFixture({"logfile": dummy_logfile})
68
 
        self.assertEqual(dummy_logfile, fixture.config["logfile"])
 
92
        # Given a configuration, ConfigFixtureBase can arrange a minimal
 
93
        # global configuration with the additional options merged in.
 
94
        something = self.getUniqueString("something")
 
95
        fixture = ExampleConfigFixture({"something": something})
 
96
        self.assertEqual(something, fixture.config["something"])
69
97
        self.exercise_fixture(fixture)
70
98
 
71
99
 
72
 
class TestConfig_DEFAULT_FILENAME(MAASTestCase):
73
 
    """Tests for `provisioningserver.config.Config.DEFAULT_FILENAME`."""
 
100
class TestConfigMeta_DEFAULT_FILENAME(MAASTestCase):
 
101
    """Tests for `provisioningserver.config.ConfigBase.DEFAULT_FILENAME`."""
74
102
 
75
 
    def set_MAAS_PROVISIONING_SETTINGS(self, filepath=None):
76
 
        """Continue this test with a given `MAAS_PROVISIONING_SETTINGS`."""
 
103
    def set_envvar(self, filepath=None):
 
104
        """Continue this test with a given environment variable."""
77
105
        self.useFixture(EnvironmentVariableFixture(
78
 
            "MAAS_PROVISIONING_SETTINGS", filepath))
 
106
            ExampleConfig.envvar, filepath))
79
107
 
80
108
    def set_MAAS_CONFIG_DIR(self, dirpath=None):
81
109
        """Continue this test with a given `MAAS_CONFIG_DIR`."""
82
110
        self.useFixture(EnvironmentVariableFixture("MAAS_CONFIG_DIR", dirpath))
83
111
 
84
 
    def make_config(self, name='pserv.yaml'):
85
 
        """Create a `pserv.yaml` in a directory of its own."""
86
 
        return self.make_file(name=name)
 
112
    def make_config(self):
 
113
        """Create a config file in a directory of its own."""
 
114
        return self.make_file(name=ExampleConfig.default)
87
115
 
88
116
    def test_gets_filename_from_MAAS_PROVISIONING_SETTNGS(self):
89
117
        dummy_filename = factory.make_name("config")
90
118
        self.set_MAAS_CONFIG_DIR(None)
91
 
        self.set_MAAS_PROVISIONING_SETTINGS(dummy_filename)
92
 
        self.assertEqual(dummy_filename, Config.DEFAULT_FILENAME)
 
119
        self.set_envvar(dummy_filename)
 
120
        self.assertEqual(dummy_filename, ExampleConfig.DEFAULT_FILENAME)
93
121
 
94
122
    def test_falls_back_to_MAAS_CONFIG_DIR(self):
95
123
        config_file = self.make_config()
96
124
        self.set_MAAS_CONFIG_DIR(os.path.dirname(config_file))
97
 
        self.set_MAAS_PROVISIONING_SETTINGS(None)
98
 
        self.assertEqual(config_file, Config.DEFAULT_FILENAME)
 
125
        self.set_envvar(None)
 
126
        self.assertEqual(config_file, ExampleConfig.DEFAULT_FILENAME)
99
127
 
100
128
    def test_MAAS_PROVISIONING_SETTINGS_trumps_MAAS_CONFIG_DIR(self):
101
129
        provisioning_settings = factory.make_name("config")
102
130
        self.set_MAAS_CONFIG_DIR(os.path.dirname(self.make_config()))
103
 
        self.set_MAAS_PROVISIONING_SETTINGS(provisioning_settings)
104
 
        self.assertEqual(provisioning_settings, Config.DEFAULT_FILENAME)
 
131
        self.set_envvar(provisioning_settings)
 
132
        self.assertEqual(
 
133
            provisioning_settings,
 
134
            ExampleConfig.DEFAULT_FILENAME)
105
135
 
106
136
    def test_defaults_to_global_config(self):
107
137
        self.set_MAAS_CONFIG_DIR(None)
108
 
        self.set_MAAS_PROVISIONING_SETTINGS(None)
109
 
        self.assertEqual('/etc/maas/pserv.yaml', Config.DEFAULT_FILENAME)
 
138
        self.set_envvar(None)
 
139
        self.assertEqual(
 
140
            '/etc/maas/%s' % ExampleConfig.default,
 
141
            ExampleConfig.DEFAULT_FILENAME)
110
142
 
111
143
    def test_set(self):
112
144
        dummy_filename = factory.make_name("config")
113
 
        Config.DEFAULT_FILENAME = dummy_filename
114
 
        self.assertEqual(dummy_filename, Config.DEFAULT_FILENAME)
 
145
        ExampleConfig.DEFAULT_FILENAME = dummy_filename
 
146
        self.assertEqual(dummy_filename, ExampleConfig.DEFAULT_FILENAME)
115
147
 
116
148
    def test_delete(self):
117
149
        self.set_MAAS_CONFIG_DIR(None)
118
 
        self.set_MAAS_PROVISIONING_SETTINGS(None)
119
 
        Config.DEFAULT_FILENAME = factory.make_name("config")
120
 
        del Config.DEFAULT_FILENAME
 
150
        self.set_envvar(None)
 
151
        ExampleConfig.DEFAULT_FILENAME = factory.make_name("config")
 
152
        del ExampleConfig.DEFAULT_FILENAME
121
153
        # The filename reverts; see test_get_with_environment_empty.
122
 
        self.assertEqual("/etc/maas/pserv.yaml", Config.DEFAULT_FILENAME)
 
154
        self.assertEqual(
 
155
            "/etc/maas/%s" % ExampleConfig.default,
 
156
            ExampleConfig.DEFAULT_FILENAME)
123
157
        # The delete does not fail when called multiple times.
124
 
        del Config.DEFAULT_FILENAME
 
158
        del ExampleConfig.DEFAULT_FILENAME
 
159
 
 
160
 
 
161
class TestConfigBase(MAASTestCase):
 
162
    """Tests for `provisioningserver.config.ConfigBase`."""
 
163
 
 
164
    def make_config_data(self):
 
165
        """Return random config data for `ExampleConfig`."""
 
166
        return {'something': factory.make_name('value')}
 
167
 
 
168
    def make_config_file(self, name=None, data=None):
 
169
        """Write a YAML config file, and return its path."""
 
170
        if name is None:
 
171
            name = factory.make_name('config') + '.yaml'
 
172
        if data is None:
 
173
            data = self.make_config_data()
 
174
        return self.make_file(name=name, contents=yaml.safe_dump(data))
 
175
 
 
176
    def test_get_defaults_returns_default_config(self):
 
177
        # The default configuration is production-ready.
 
178
        observed = ExampleConfig.get_defaults()
 
179
        self.assertEqual({"something": "*missing*"}, observed)
 
180
 
 
181
    def test_get_defaults_ignores_settings(self):
 
182
        self.useFixture(ExampleConfigFixture(self.make_config_data()))
 
183
        observed = ExampleConfig.get_defaults()
 
184
        self.assertEqual({"something": "*missing*"}, observed)
 
185
 
 
186
    def test_parse(self):
 
187
        # Configuration can be parsed from a snippet of YAML.
 
188
        observed = ExampleConfig.parse(b'something: "important"\n')
 
189
        self.assertEqual("important", observed["something"])
 
190
 
 
191
    def test_load(self):
 
192
        # Configuration can be loaded and parsed from a file.
 
193
        config = dedent("""
 
194
            something: "important"
 
195
            """)
 
196
        filename = self.make_file(contents=config)
 
197
        observed = ExampleConfig.load(filename)
 
198
        self.assertEqual({"something": "important"}, observed)
 
199
 
 
200
    def test_load_defaults_to_default_filename(self):
 
201
        data = self.make_config_data()
 
202
        filename = self.make_config_file(name='config.yaml', data=data)
 
203
        self.patch(ExampleConfig, 'DEFAULT_FILENAME', filename)
 
204
        self.assertEqual(data, ExampleConfig.load())
 
205
 
 
206
    def test_load_from_cache_loads_config(self):
 
207
        data = self.make_config_data()
 
208
        filename = self.make_config_file(data=data)
 
209
        self.assertEqual(data, ExampleConfig.load_from_cache(filename))
 
210
 
 
211
    def test_load_from_cache_uses_defaults(self):
 
212
        filename = self.make_file(contents='')
 
213
        self.assertEqual(
 
214
            ExampleConfig.get_defaults(),
 
215
            ExampleConfig.load_from_cache(filename))
 
216
 
 
217
    def test_load_from_cache_caches_each_file_separately(self):
 
218
        config1 = self.make_file(contents=yaml.safe_dump({'something': "1"}))
 
219
        config2 = self.make_file(contents=yaml.safe_dump({'something': "2"}))
 
220
 
 
221
        self.assertEqual(
 
222
            {"something": "1"},
 
223
            ExampleConfig.load_from_cache(config1))
 
224
        self.assertEqual(
 
225
            {"something": "2"},
 
226
            ExampleConfig.load_from_cache(config2))
 
227
 
 
228
    def test_load_from_cache_reloads_from_cache_not_from_file(self):
 
229
        # A config loaded by Config.load_from_cache() is never reloaded.
 
230
        filename = self.make_config_file()
 
231
        config_before = ExampleConfig.load_from_cache(filename)
 
232
        os.unlink(filename)
 
233
        config_after = ExampleConfig.load_from_cache(filename)
 
234
        self.assertEqual(config_before, config_after)
 
235
 
 
236
    def test_load_from_cache_caches_immutable_copy(self):
 
237
        filename = self.make_config_file()
 
238
 
 
239
        first_load = ExampleConfig.load_from_cache(filename)
 
240
        second_load = ExampleConfig.load_from_cache(filename)
 
241
 
 
242
        self.assertEqual(first_load, second_load)
 
243
        self.assertIsNot(first_load, second_load)
 
244
        first_load['something'] = factory.make_name('newthing')
 
245
        self.assertNotEqual(first_load['something'], second_load['something'])
 
246
 
 
247
    def test_flush_cache_without_filename_empties_cache(self):
 
248
        filename = self.make_config_file()
 
249
        ExampleConfig.load_from_cache(filename)
 
250
        os.unlink(filename)
 
251
        ExampleConfig.flush_cache()
 
252
        error = self.assertRaises(
 
253
            IOError,
 
254
            ExampleConfig.load_from_cache, filename)
 
255
        self.assertEqual(errno.ENOENT, error.errno)
 
256
 
 
257
    def test_flush_cache_flushes_specific_file(self):
 
258
        filename = self.make_config_file()
 
259
        ExampleConfig.load_from_cache(filename)
 
260
        os.unlink(filename)
 
261
        ExampleConfig.flush_cache(filename)
 
262
        error = self.assertRaises(
 
263
            IOError,
 
264
            ExampleConfig.load_from_cache, filename)
 
265
        self.assertEqual(errno.ENOENT, error.errno)
 
266
 
 
267
    def test_flush_cache_retains_other_files(self):
 
268
        flushed_file = self.make_config_file()
 
269
        cached_file = self.make_config_file()
 
270
        ExampleConfig.load_from_cache(flushed_file)
 
271
        cached_config = ExampleConfig.load_from_cache(cached_file)
 
272
        os.unlink(cached_file)
 
273
        ExampleConfig.flush_cache(flushed_file)
 
274
        self.assertEqual(
 
275
            cached_config,
 
276
            ExampleConfig.load_from_cache(cached_file))
 
277
 
 
278
    def test_flush_cache_ignores_uncached_files(self):
 
279
        data = self.make_config_data()
 
280
        filename = self.make_config_file(data=data)
 
281
        ExampleConfig.flush_cache(filename)
 
282
        self.assertEqual(data, ExampleConfig.load_from_cache(filename))
 
283
 
 
284
    def test_field(self):
 
285
        self.assertIs(ExampleConfig, ExampleConfig.field())
 
286
        self.assertIs(
 
287
            ExampleConfig.fields["something"],
 
288
            ExampleConfig.field("something"))
 
289
 
 
290
    def test_save_and_load_interoperate(self):
 
291
        something = self.getUniqueString()
 
292
        saved_file = self.make_file()
 
293
 
 
294
        ExampleConfig.save({'something': something}, saved_file)
 
295
        loaded_config = ExampleConfig.load(saved_file)
 
296
        self.assertEqual(something, loaded_config['something'])
 
297
 
 
298
    def test_save_saves_yaml_file(self):
 
299
        config = {'something': self.getUniqueString()}
 
300
        saved_file = self.make_file()
 
301
 
 
302
        ExampleConfig.save(config, saved_file)
 
303
 
 
304
        with open(saved_file, 'rb') as written_file:
 
305
            loaded_config = yaml.safe_load(written_file)
 
306
        self.assertEqual(config, loaded_config)
 
307
 
 
308
    def test_save_defaults_to_default_filename(self):
 
309
        something = self.getUniqueString()
 
310
        filename = self.make_file(name="config.yaml")
 
311
        self.patch(ExampleConfig, 'DEFAULT_FILENAME', filename)
 
312
 
 
313
        ExampleConfig.save({'something': something})
 
314
 
 
315
        self.assertEqual(
 
316
            {'something': something},
 
317
            ExampleConfig.load(filename))
 
318
 
 
319
    def test_create_backup_creates_backup(self):
 
320
        something = self.getUniqueString()
 
321
        filename = self.make_file(name="config.yaml")
 
322
        config = {'something': something}
 
323
        yaml_config = yaml.safe_dump(config)
 
324
        self.patch(ExampleConfig, 'DEFAULT_FILENAME', filename)
 
325
        ExampleConfig.save(config)
 
326
 
 
327
        ExampleConfig.create_backup('test')
 
328
 
 
329
        backup_name = "%s.%s.bak" % (filename, 'test')
 
330
        self.assertThat(backup_name, FileContains(yaml_config))
125
331
 
126
332
 
127
333
class TestConfig(MAASTestCase):
128
334
    """Tests for `provisioningserver.config.Config`."""
129
335
 
130
336
    default_production_config = {
131
 
        'boot': {
132
 
            'architectures': None,
133
 
            'ephemeral': {
134
 
                'images_directory': '/var/lib/maas/ephemeral',
135
 
                'releases': None,
136
 
                },
137
 
            },
138
337
        'broker': {
139
338
            'host': 'localhost',
140
339
            'port': 5673,
151
350
        'tftp': {
152
351
            'generator': 'http://localhost/MAAS/api/1.0/pxeconfig/',
153
352
            'port': 69,
 
353
            # The "root" setting is obsolete; resource_root replaces it.
154
354
            'root': "/var/lib/maas/tftp",
 
355
            'resource_root': "/var/lib/maas/boot-resources/current/",
155
356
            },
156
357
        }
157
358
 
167
368
        observed = Config.get_defaults()
168
369
        self.assertEqual(self.default_production_config, observed)
169
370
 
170
 
    def test_get_defaults_ignores_settings(self):
171
 
        self.useFixture(ConfigFixture({'logfile': self.make_file()}))
172
 
 
173
 
        self.assertEqual(
174
 
            self.default_production_config['logfile'],
175
 
            Config.get_defaults()['logfile'])
176
 
 
177
 
    def test_parse(self):
178
 
        # Configuration can be parsed from a snippet of YAML.
179
 
        observed = Config.parse(b'logfile: "/some/where.log"\n')
180
 
        self.assertEqual("/some/where.log", observed["logfile"])
181
 
 
182
 
    def test_load(self):
183
 
        # Configuration can be loaded and parsed from a file.
184
 
        config = dedent("""
185
 
            logfile: "/some/where.log"
186
 
            """)
187
 
        filename = self.make_file(name="config.yaml", contents=config)
188
 
        observed = Config.load(filename)
189
 
        self.assertEqual("/some/where.log", observed["logfile"])
190
 
 
191
 
    def test_load_defaults_to_default_filename(self):
192
 
        logfile = self.make_file(name='test.log')
193
 
        config = yaml.safe_dump({'logfile': logfile})
194
 
        filename = self.make_file(name="config.yaml", contents=config)
195
 
        self.patch(Config, 'DEFAULT_FILENAME', filename)
196
 
 
197
 
        observed = Config.load()
198
 
 
199
 
        self.assertEqual(logfile, observed['logfile'])
200
 
 
201
371
    def test_load_example(self):
202
372
        # The example configuration is designed for development.
203
373
        filename = os.path.join(root, "etc", "maas", "pserv.yaml")
205
375
            self.default_development_config,
206
376
            Config.load(filename))
207
377
 
208
 
    def test_load_from_cache_loads_config(self):
209
 
        logfile = self.make_file()
210
 
        filename = self.make_file(
211
 
            name="config.yaml", contents=yaml.safe_dump({'logfile': logfile}))
212
 
        loaded_config = Config.load_from_cache(filename)
213
 
        self.assertEqual(logfile, loaded_config['logfile'])
214
 
 
215
 
    def test_load_from_cache_uses_defaults(self):
216
 
        filename = self.make_file(name='config.yaml', contents='')
217
 
        self.assertEqual(
218
 
            Config.get_defaults(),
219
 
            Config.load_from_cache(filename))
220
 
 
221
 
    def test_load_from_cache_caches_each_file_separately(self):
222
 
        log1, log2 = self.make_file(), self.make_file()
223
 
        config1 = self.make_file(contents=yaml.safe_dump({'logfile': log1}))
224
 
        config2 = self.make_file(contents=yaml.safe_dump({'logfile': log2}))
225
 
 
226
 
        self.assertEqual(log1, Config.load_from_cache(config1)['logfile'])
227
 
        self.assertEqual(log2, Config.load_from_cache(config2)['logfile'])
228
 
 
229
 
    def test_load_from_cache_reloads_from_cache_not_from_file(self):
230
 
        # A config loaded by Config.load_from_cache() is never reloaded.
231
 
        filename = self.make_file(name="config.yaml", contents='')
232
 
        config_before = Config.load_from_cache(filename)
233
 
        os.unlink(filename)
234
 
        config_after = Config.load_from_cache(filename)
235
 
        self.assertEqual(config_before, config_after)
236
 
 
237
 
    def test_load_from_cache_caches_immutable_copy(self):
238
 
        logfile = self.make_file()
239
 
        filename = self.make_file(
240
 
            name="config.yaml", contents=yaml.safe_dump({'logfile': logfile}))
241
 
 
242
 
        first_load = Config.load_from_cache(filename)
243
 
        second_load = Config.load_from_cache(filename)
244
 
 
245
 
        self.assertEqual(first_load, second_load)
246
 
        self.assertIsNot(first_load, second_load)
247
 
        first_load['logfile'] = factory.make_name('otherlog')
248
 
        self.assertNotEqual(first_load['logfile'], second_load['logfile'])
249
 
        self.assertEqual(logfile, second_load['logfile'])
250
 
        self.assertIsNot(first_load['boot'], second_load['boot'])
251
 
        first_load['boot']['architectures'] = [factory.make_name('otherarch')]
252
 
        self.assertNotEqual(
253
 
            first_load['boot']['architectures'],
254
 
            second_load['boot']['architectures'])
255
 
 
256
378
    def test_oops_directory_without_reporter(self):
257
379
        # It is an error to omit the OOPS reporter if directory is specified.
258
380
        config = (
265
387
            partial(Config.parse, config),
266
388
            Raises(expected))
267
389
 
268
 
    def test_field(self):
269
 
        self.assertIs(Config, Config.field())
270
 
        self.assertIs(Config.fields["tftp"], Config.field("tftp"))
271
 
        self.assertIs(
272
 
            Config.fields["tftp"].fields["root"],
273
 
            Config.field("tftp", "root"))
274
 
 
275
 
    def test_save_and_load_interoperate(self):
276
 
        logfile = self.make_file(name='test.log')
277
 
        saved_file = self.make_file()
278
 
 
279
 
        Config.save({'logfile': logfile}, saved_file)
280
 
        loaded_config = Config.load(saved_file)
281
 
        self.assertEqual(logfile, loaded_config['logfile'])
282
 
 
283
 
    def test_save_saves_yaml_file(self):
284
 
        config = {'logfile': self.make_file()}
285
 
        saved_file = self.make_file()
286
 
 
287
 
        Config.save(config, saved_file)
288
 
 
289
 
        with open(saved_file, 'rb') as written_file:
290
 
            loaded_config = yaml.load(written_file)
291
 
        self.assertEqual(config, loaded_config)
292
 
 
293
 
    def test_save_defaults_to_default_filename(self):
294
 
        logfile = self.make_file(name='test.log')
295
 
        filename = self.make_file(name="config.yaml")
296
 
        self.patch(Config, 'DEFAULT_FILENAME', filename)
297
 
 
298
 
        Config.save({'logfile': logfile})
299
 
 
300
 
        self.assertEqual(logfile, Config.load(filename)['logfile'])
301
 
 
302
 
    def test_create_backup_creates_backup(self):
303
 
        logfile = self.make_file(name='test.log')
304
 
        filename = self.make_file(name="config.yaml")
305
 
        config = {'logfile': logfile}
306
 
        yaml_config = yaml.safe_dump(config)
307
 
        self.patch(Config, 'DEFAULT_FILENAME', filename)
308
 
        Config.save(config)
309
 
 
310
 
        Config.create_backup('test')
311
 
 
312
 
        backup_name = "%s.%s.bak" % (filename, 'test')
313
 
        self.assertThat(backup_name, FileContains(yaml_config))
 
390
 
 
391
class TestBootConfig(MAASTestCase):
 
392
    """Tests for `provisioningserver.config.BootConfig`."""
 
393
 
 
394
    default_production_config = {
 
395
        'boot': {
 
396
            'sources': [
 
397
                {
 
398
                    'path': (
 
399
                        'http://maas.ubuntu.com/images/ephemeral/releases/'),
 
400
                    'keyring': (
 
401
                        '/usr/share/keyrings/ubuntu-cloudimage-keyring.gpg'),
 
402
                    'selections': [
 
403
                        {
 
404
                            'arches': ['*'],
 
405
                            'release': '*',
 
406
                            'subarches': ['*'],
 
407
                            'labels': ['*'],
 
408
                        },
 
409
                    ],
 
410
                },
 
411
            ],
 
412
            'storage': '/var/lib/maas/boot-resources/',
 
413
            'configure_me': False,
 
414
        },
 
415
    }
 
416
 
 
417
    default_development_config = {
 
418
        'boot': {
 
419
            'sources': [
 
420
                {
 
421
                    'path': (
 
422
                        'http://maas.ubuntu.com/images/ephemeral-v2/daily/'),
 
423
                    'keyring': (
 
424
                        '/usr/share/keyrings/ubuntu-cloudimage-keyring.gpg'),
 
425
                    'selections': [
 
426
                        {
 
427
                            'arches': ['i386', 'amd64'],
 
428
                            'release': 'trusty',
 
429
                            'subarches': ['generic'],
 
430
                            'labels': ['daily'],
 
431
                        },
 
432
                    ],
 
433
                },
 
434
                {
 
435
                    'path': (
 
436
                        'http://maas.ubuntu.com/'
 
437
                        'images/ephemeral-v2/releases/'),
 
438
                    'keyring': (
 
439
                        '/usr/share/keyrings/ubuntu-cloudimage-keyring.gpg'),
 
440
                    'selections': [
 
441
                        {
 
442
                            'arches': ['i386', 'amd64'],
 
443
                            'release': 'precise',
 
444
                            'subarches': ['generic'],
 
445
                            'labels': ['release'],
 
446
                        },
 
447
                    ],
 
448
                },
 
449
            ],
 
450
            'storage': '/var/lib/maas/boot-resources/',
 
451
            'configure_me': True,
 
452
        },
 
453
    }
 
454
 
 
455
    def test_get_defaults_returns_default_config(self):
 
456
        # The default configuration is production-ready.
 
457
        observed = BootConfig.get_defaults()
 
458
        self.assertEqual(self.default_production_config, observed)
 
459
 
 
460
    def test_load_example(self):
 
461
        # The example configuration is designed for development.
 
462
        filename = os.path.join(root, "etc", "maas", "bootresources.yaml")
 
463
        self.assertEqual(
 
464
            self.default_development_config,
 
465
            BootConfig.load(filename))