~mpontillo/maas/migrate-dns-settings-trunk

« back to all changes in this revision

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

  • Committer: Mike Pontillo
  • Date: 2015-07-07 16:24:44 UTC
  • mfrom: (4058.2.13 maas)
  • Revision ID: mike.pontillo@canonical.com-20150707162444-ush8b4k1lezlepbs
Merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2014-2015 Canonical Ltd.  This software is licensed under the
2
 
# GNU Affero General Public License version 3 (see the file LICENSE).
3
 
 
4
 
"""Tests for `MAAS_URL` configuration update code."""
5
 
 
6
 
from __future__ import (
7
 
    absolute_import,
8
 
    print_function,
9
 
    unicode_literals,
10
 
    )
11
 
 
12
 
str = None
13
 
 
14
 
__metaclass__ = type
15
 
__all__ = []
16
 
 
17
 
from argparse import ArgumentParser
18
 
from random import randint
19
 
from textwrap import dedent
20
 
 
21
 
from maastesting.factory import factory
22
 
from maastesting.matchers import (
23
 
    MockAnyCall,
24
 
    MockCalledOnceWith,
25
 
)
26
 
from maastesting.testcase import MAASTestCase
27
 
from mock import (
28
 
    ANY,
29
 
    Mock,
30
 
)
31
 
from provisioningserver import configure_maas_url
32
 
from provisioningserver.configure_maas_url import substitute_pserv_yaml_line
33
 
from testtools.matchers import (
34
 
    FileContains,
35
 
    StartsWith,
36
 
)
37
 
 
38
 
 
39
 
class TestRewriteConfigFile(MAASTestCase):
40
 
 
41
 
    def test__rewrites_file(self):
42
 
        path = self.make_file(contents='foo\n')
43
 
        configure_maas_url.rewrite_config_file(path, lambda line: 'bar')
44
 
        self.assertThat(path, FileContains('bar\n'))
45
 
 
46
 
    def test__sets_access_permissions(self):
47
 
        writer = self.patch(configure_maas_url, 'atomic_write')
48
 
        mode = 0215
49
 
        path = self.make_file()
50
 
        configure_maas_url.rewrite_config_file(
51
 
            path, lambda line: line, mode=mode)
52
 
        self.assertThat(writer, MockCalledOnceWith(ANY, path, mode=mode))
53
 
 
54
 
    def test__preserves_trailing_newline(self):
55
 
        path = self.make_file(contents='x\n')
56
 
        configure_maas_url.rewrite_config_file(path, lambda line: line)
57
 
        self.assertThat(path, FileContains('x\n'))
58
 
 
59
 
    def test__ensures_trailing_newline(self):
60
 
        path = self.make_file(contents='x')
61
 
        configure_maas_url.rewrite_config_file(path, lambda line: line)
62
 
        self.assertThat(path, FileContains('x\n'))
63
 
 
64
 
 
65
 
class TestUpdateMAASClusterConf(MAASTestCase):
66
 
 
67
 
    def patch_file(self, content):
68
 
        """Inject a fake `/etc/maas/maas_cluster.conf`."""
69
 
        path = self.make_file(name='maas_cluster.conf', contents=content)
70
 
        self.patch(configure_maas_url, 'MAAS_CLUSTER_CONF', path)
71
 
        return path
72
 
 
73
 
    def test__updates_realistic_file(self):
74
 
        config_file = self.patch_file(dedent("""\
75
 
            # Leading comments.
76
 
            MAAS_URL="http://10.9.8.7/MAAS"
77
 
            CLUSTER_UUID="5d02950e-6318-8195-ac3e-e6ccb12673c5"
78
 
            """))
79
 
        configure_maas_url.update_maas_cluster_conf('http://1.2.3.4/MAAS')
80
 
        self.assertThat(
81
 
            config_file,
82
 
            FileContains(dedent("""\
83
 
                # Leading comments.
84
 
                MAAS_URL="http://1.2.3.4/MAAS"
85
 
                CLUSTER_UUID="5d02950e-6318-8195-ac3e-e6ccb12673c5"
86
 
                """)))
87
 
 
88
 
    def test__updates_quoted_value(self):
89
 
        old_url = factory.make_url()
90
 
        new_url = factory.make_url()
91
 
        config_file = self.patch_file('MAAS_URL="%s"\n' % old_url)
92
 
        configure_maas_url.update_maas_cluster_conf(new_url)
93
 
        self.assertThat(
94
 
            config_file,
95
 
            FileContains('MAAS_URL="%s"\n' % new_url))
96
 
 
97
 
    def test__updates_unquoted_value(self):
98
 
        old_url = factory.make_url()
99
 
        new_url = factory.make_url()
100
 
        config_file = self.patch_file('MAAS_URL=%s\n' % old_url)
101
 
        configure_maas_url.update_maas_cluster_conf(new_url)
102
 
        self.assertThat(
103
 
            config_file,
104
 
            FileContains('MAAS_URL="%s"\n' % new_url))
105
 
 
106
 
    def test__leaves_other_lines_unchanged(self):
107
 
        old_content = '#MAAS_URL="%s"\n' % factory.make_url()
108
 
        config_file = self.patch_file(old_content)
109
 
        configure_maas_url.update_maas_cluster_conf(factory.make_url())
110
 
        self.assertThat(config_file, FileContains(old_content))
111
 
 
112
 
 
113
 
class TestExtractHost(MAASTestCase):
114
 
 
115
 
    def test__extracts_hostname(self):
116
 
        host = factory.make_name('host').lower()
117
 
        port = factory.pick_port()
118
 
        self.assertEqual(
119
 
            host,
120
 
            configure_maas_url.extract_host('http://%s/path' % host))
121
 
        self.assertEqual(
122
 
            host,
123
 
            configure_maas_url.extract_host('http://%s:%d' % (host, port)))
124
 
 
125
 
    def test__extracts_IPv4_address(self):
126
 
        host = factory.make_ipv4_address()
127
 
        port = factory.pick_port()
128
 
        self.assertEqual(
129
 
            host,
130
 
            configure_maas_url.extract_host('http://%s' % host))
131
 
        self.assertEqual(
132
 
            host,
133
 
            configure_maas_url.extract_host('http://%s:%d' % (host, port)))
134
 
 
135
 
    def test__extracts_IPv6_address(self):
136
 
        host = factory.make_ipv6_address()
137
 
        port = factory.pick_port()
138
 
        self.assertEqual(
139
 
            host,
140
 
            configure_maas_url.extract_host('http://[%s]' % host))
141
 
        self.assertEqual(
142
 
            host,
143
 
            configure_maas_url.extract_host('http://[%s]:%d' % (host, port)))
144
 
 
145
 
    def test__extracts_IPv6_address_with_zone_index(self):
146
 
        host = (
147
 
            factory.make_ipv6_address() +
148
 
            '%25' +
149
 
            factory.make_name('zone').lower())
150
 
        port = factory.pick_port()
151
 
        self.assertEqual(
152
 
            host,
153
 
            configure_maas_url.extract_host('http://[%s]' % host))
154
 
        self.assertEqual(
155
 
            host,
156
 
            configure_maas_url.extract_host('http://[%s]:%d' % (host, port)))
157
 
 
158
 
 
159
 
class TestSubstitutePservYamlLine(MAASTestCase):
160
 
 
161
 
    def make_generator_line(self, url):
162
 
        return "  generator: %s" % url
163
 
 
164
 
    def test__replaces_hostname_generator_URL(self):
165
 
        old_host = factory.make_name('old-host')
166
 
        new_host = factory.make_name('new-host')
167
 
        input_line = self.make_generator_line('http://%s' % old_host)
168
 
        self.assertEqual(
169
 
            self.make_generator_line('http://%s' % new_host),
170
 
            substitute_pserv_yaml_line(new_host, input_line))
171
 
 
172
 
    def test__replaces_IPv4_generator_URL(self):
173
 
        old_host = factory.make_ipv4_address()
174
 
        new_host = factory.make_name('new-host')
175
 
        input_line = self.make_generator_line('http://%s' % old_host)
176
 
        self.assertEqual(
177
 
            self.make_generator_line('http://%s' % new_host),
178
 
            substitute_pserv_yaml_line(new_host, input_line))
179
 
 
180
 
    def test__replaces_IPv6_generator_URL(self):
181
 
        old_host = factory.make_ipv6_address()
182
 
        new_host = factory.make_name('new-host')
183
 
        input_line = self.make_generator_line('http://[%s]' % old_host)
184
 
        self.assertEqual(
185
 
            self.make_generator_line('http://%s' % new_host),
186
 
            substitute_pserv_yaml_line(new_host, input_line))
187
 
 
188
 
    def test__replaces_IPv6_generator_URL_with_zone_index(self):
189
 
        old_host = (
190
 
            factory.make_ipv6_address() +
191
 
            '%25' +
192
 
            factory.make_name('zone')
193
 
            )
194
 
        new_host = factory.make_name('new-host')
195
 
        input_line = self.make_generator_line('http://[%s]' % old_host)
196
 
        self.assertEqual(
197
 
            self.make_generator_line('http://%s' % new_host),
198
 
            substitute_pserv_yaml_line(new_host, input_line))
199
 
 
200
 
    def test__inserts_IPv6_with_brackets(self):
201
 
        old_host = factory.make_name('old-host')
202
 
        new_host = '[%s]' % factory.make_ipv6_address()
203
 
        input_line = self.make_generator_line('http://%s' % old_host)
204
 
        self.assertEqual(
205
 
            self.make_generator_line('http://%s' % new_host),
206
 
            substitute_pserv_yaml_line(new_host, input_line))
207
 
 
208
 
    def test__inserts_IPv6_without_brackets(self):
209
 
        old_host = factory.make_name('old-host')
210
 
        new_host = factory.make_ipv6_address()
211
 
        input_line = self.make_generator_line('http://%s' % old_host)
212
 
        self.assertEqual(
213
 
            self.make_generator_line('http://[%s]' % new_host),
214
 
            substitute_pserv_yaml_line(new_host, input_line))
215
 
 
216
 
    def test__preserves_port_after_simple_host(self):
217
 
        port = factory.pick_port()
218
 
        old_host = factory.make_name('old-host')
219
 
        new_host = factory.make_name('new-host')
220
 
        input_line = self.make_generator_line(
221
 
            'http://%s:%d' % (old_host, port))
222
 
        self.assertEqual(
223
 
            self.make_generator_line('http://%s:%d' % (new_host, port)),
224
 
            substitute_pserv_yaml_line(new_host, input_line))
225
 
 
226
 
    def test__preserves_port_with_IPv6(self):
227
 
        port = factory.pick_port()
228
 
        old_host = factory.make_ipv6_address()
229
 
        new_host = factory.make_name('new-host')
230
 
        input_line = self.make_generator_line(
231
 
            'http://[%s]:%d' % (old_host, port))
232
 
        self.assertEqual(
233
 
            self.make_generator_line('http://%s:%d' % (new_host, port)),
234
 
            substitute_pserv_yaml_line(new_host, input_line))
235
 
 
236
 
    def test__preserves_port_with_IPv6_and_zone_index(self):
237
 
        port = factory.pick_port()
238
 
        old_host = (
239
 
            factory.make_ipv6_address() +
240
 
            '%25' +
241
 
            factory.make_name('zone')
242
 
            )
243
 
        new_host = factory.make_name('new-host')
244
 
        input_line = self.make_generator_line(
245
 
            'http://[%s]:%d' % (old_host, port))
246
 
        self.assertEqual(
247
 
            self.make_generator_line('http://%s:%d' % (new_host, port)),
248
 
            substitute_pserv_yaml_line(new_host, input_line))
249
 
 
250
 
    def test__preserves_other_line(self):
251
 
        line = '#' + self.make_generator_line(factory.make_url())
252
 
        self.assertEqual(
253
 
            line,
254
 
            substitute_pserv_yaml_line(factory.make_name('host'), line))
255
 
 
256
 
    def test__preserves_indentation(self):
257
 
        spaces = ' ' * randint(0, 10)
258
 
        input_line = spaces + 'generator: %s' % factory.make_url()
259
 
        output_line = substitute_pserv_yaml_line(
260
 
            factory.make_name('host'), input_line)
261
 
        self.assertThat(output_line, StartsWith(spaces + 'generator:'))
262
 
 
263
 
    def test__preserves_trailing_comments(self):
264
 
        comment = " # Trailing comment."
265
 
        old_host = factory.make_name('old-host')
266
 
        new_host = factory.make_name('new-host')
267
 
        input_line = self.make_generator_line('http://%s' % old_host) + comment
268
 
        self.assertEqual(
269
 
            self.make_generator_line('http://%s' % new_host) + comment,
270
 
            substitute_pserv_yaml_line(new_host, input_line))
271
 
 
272
 
 
273
 
class TestUpdatePservYaml(MAASTestCase):
274
 
 
275
 
    def patch_file(self, content):
276
 
        """Inject a fake `/etc/maas/pserv.yaml`."""
277
 
        path = self.make_file(name='pserv.yaml', contents=content)
278
 
        self.patch(configure_maas_url, 'PSERV_YAML', path)
279
 
        return path
280
 
 
281
 
    def test__updates_realistic_file(self):
282
 
        old_host = factory.make_name('old-host')
283
 
        new_host = factory.make_name('new-host')
284
 
        config_file = self.patch_file(dedent("""\
285
 
            ## TFTP configuration.
286
 
            tftp:
287
 
              ## The URL to be contacted to generate PXE configurations.
288
 
              generator: http://%s/MAAS/api/1.0/pxeconfig/
289
 
            """) % old_host)
290
 
        configure_maas_url.update_pserv_yaml(new_host)
291
 
        self.assertThat(
292
 
            config_file,
293
 
            FileContains(dedent("""\
294
 
                ## TFTP configuration.
295
 
                tftp:
296
 
                  ## The URL to be contacted to generate PXE configurations.
297
 
                  generator: http://%s/MAAS/api/1.0/pxeconfig/
298
 
                """) % new_host))
299
 
 
300
 
 
301
 
class TestAddArguments(MAASTestCase):
302
 
 
303
 
    def test__accepts_maas_url(self):
304
 
        url = factory.make_url()
305
 
        parser = ArgumentParser()
306
 
        configure_maas_url.add_arguments(parser)
307
 
        args = parser.parse_args([url])
308
 
        self.assertEqual(url, args.maas_url)
309
 
 
310
 
 
311
 
class TestRun(MAASTestCase):
312
 
 
313
 
    def make_args(self, maas_url):
314
 
        args = Mock()
315
 
        args.maas_url = maas_url
316
 
        return args
317
 
 
318
 
    def patch_read_file(self):
319
 
        return self.patch(configure_maas_url, 'read_text_file')
320
 
 
321
 
    def patch_write_file(self):
322
 
        return self.patch(configure_maas_url, 'atomic_write')
323
 
 
324
 
    def test__updates_maas_cluster_conf(self):
325
 
        reader = self.patch_read_file()
326
 
        writer = self.patch_write_file()
327
 
        url = factory.make_url()
328
 
        configure_maas_url.run(self.make_args(url))
329
 
        self.assertThat(reader, MockAnyCall('/etc/maas/maas_cluster.conf'))
330
 
        self.assertThat(
331
 
            writer,
332
 
            MockAnyCall(ANY, '/etc/maas/maas_cluster.conf', mode=0640))
333
 
 
334
 
    def test__updates_pserv_yaml(self):
335
 
        reader = self.patch_read_file()
336
 
        writer = self.patch_write_file()
337
 
        url = factory.make_url()
338
 
        configure_maas_url.run(self.make_args(url))
339
 
        self.assertThat(reader, MockAnyCall('/etc/maas/pserv.yaml'))
340
 
        self.assertThat(
341
 
            writer,
342
 
            MockAnyCall(ANY, '/etc/maas/pserv.yaml', mode=0644))
343
 
 
344
 
    def test__passes_host_to_update_pserv_yaml(self):
345
 
        self.patch_read_file()
346
 
        self.patch_write_file()
347
 
        update_pserv_yaml = self.patch(configure_maas_url, 'update_pserv_yaml')
348
 
        host = factory.make_name('host').lower()
349
 
        url = factory.make_url(netloc=host)
350
 
        configure_maas_url.run(self.make_args(url))
351
 
        self.assertThat(update_pserv_yaml, MockCalledOnceWith(host))