~mpontillo/maas/dns-template-changes-1.7

« back to all changes in this revision

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

  • Committer: Tarmac
  • Author(s): Gavin Panella
  • Date: 2012-02-16 10:10:36 UTC
  • mfrom: (130.2.7 pserv-config-file)
  • Revision ID: ed@carob-20120216101036-y652y5t4vdkmzhg9
[r=jtv][bug=][author=allenap] Use a config file for pserv instead of command-line options.

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
 
14
14
from functools import partial
15
15
import os
16
 
from unittest import skip
17
16
 
18
17
from fixtures import TempDir
 
18
import formencode
19
19
from provisioningserver.plugin import (
 
20
    Config,
20
21
    Options,
21
22
    ProvisioningServiceMaker,
22
23
    )
27
28
    )
28
29
from twisted.application.service import MultiService
29
30
from twisted.python.usage import UsageError
 
31
import yaml
 
32
 
 
33
 
 
34
class TestConfig(TestCase):
 
35
    """Tests for `provisioningserver.plugin.Config`."""
 
36
 
 
37
    def test_defaults(self):
 
38
        expected = {
 
39
            'broker': {
 
40
                'host': 'localhost',
 
41
                'password': None,
 
42
                'port': 5673,
 
43
                'username': None,
 
44
                'vhost': u'/',
 
45
                },
 
46
            'logfile': '/some/where.log',
 
47
            'oops': {
 
48
                'directory': '',
 
49
                'reporter': '',
 
50
                },
 
51
            'port': 8001,
 
52
            }
 
53
        mandatory_arguments = {
 
54
            "logfile": "/some/where.log",
 
55
            }
 
56
        observed = Config.to_python(mandatory_arguments)
 
57
        self.assertEqual(expected, observed)
 
58
 
 
59
    def test_parse(self):
 
60
        # Configuration can be parsed from a snippet of YAML.
 
61
        observed = Config.parse(
 
62
            b'logfile: "/some/where.log"')
 
63
        self.assertEqual("/some/where.log", observed["logfile"])
 
64
 
 
65
    def test_load(self):
 
66
        # Configuration can be loaded and parsed from a file.
 
67
        filename = os.path.join(
 
68
            self.useFixture(TempDir()).path, "config.yaml")
 
69
        with open(filename, "wb") as stream:
 
70
            stream.write(b'logfile: "/some/where.log"')
 
71
        observed = Config.load(filename)
 
72
        self.assertEqual("/some/where.log", observed["logfile"])
 
73
 
 
74
    def test_load_example(self):
 
75
        # The example configuration can be loaded and validated.
 
76
        filename = os.path.join(
 
77
            os.path.dirname(__file__), os.pardir,
 
78
            os.pardir, os.pardir, "etc", "pserv.yaml")
 
79
        Config.load(filename)
 
80
 
 
81
    def test_oops_directory_without_reporter(self):
 
82
        # It is an error to omit the OOPS reporter if directory is specified.
 
83
        config = (
 
84
            'logfile: "/some/where.log"\n'
 
85
            'oops:\n'
 
86
            '  directory: /tmp/oops\n'
 
87
            )
 
88
        expected = MatchesException(
 
89
            formencode.Invalid, "oops: You must give a value for reporter")
 
90
        self.assertThat(
 
91
            partial(Config.parse, config),
 
92
            Raises(expected))
30
93
 
31
94
 
32
95
class TestOptions(TestCase):
33
96
    """Tests for `provisioningserver.plugin.Options`."""
34
97
 
35
 
    @skip(
36
 
        "RabbitMQ is not yet a required component "
37
 
        "of a running MaaS installation. Re-enable "
38
 
        "when RabbitMQ is once again needed; remove "
39
 
        "the other similarly named test.")
40
 
    def test_defaults_SKIPPED(self):
41
 
        options = Options()
42
 
        expected = {
43
 
            "brokerhost": "127.0.0.1",
44
 
            "brokerpassword": None,
45
 
            "brokerport": 5672,
46
 
            "brokeruser": None,
47
 
            "brokervhost": "/",
48
 
            "logfile": "pserv.log",
49
 
            "oops-dir": None,
50
 
            "oops-reporter": "MAAS-PS",
51
 
            "port": 8001,
52
 
            }
53
 
        self.assertEqual(expected, options.defaults)
54
 
 
55
98
    def test_defaults(self):
56
99
        options = Options()
57
 
        expected = {
58
 
            "logfile": "pserv.log",
59
 
            "oops-dir": None,
60
 
            "oops-reporter": "MAAS-PS",
61
 
            "port": 8001,
62
 
            }
 
100
        expected = {"config-file": "pserv.yaml"}
63
101
        self.assertEqual(expected, options.defaults)
64
102
 
65
103
    def check_exception(self, options, message, *arguments):
68
106
            partial(options.parseOptions, arguments),
69
107
            Raises(MatchesException(UsageError, message)))
70
108
 
71
 
    @skip(
72
 
        "RabbitMQ is not yet a required component "
73
 
        "of a running MaaS installation.")
74
 
    def test_option_brokeruser_required(self):
75
 
        options = Options()
76
 
        self.check_exception(
77
 
            options,
78
 
            "--brokeruser must be specified")
79
 
 
80
 
    @skip(
81
 
        "RabbitMQ is not yet a required component "
82
 
        "of a running MaaS installation.")
83
 
    def test_option_brokerpassword_required(self):
84
 
        options = Options()
85
 
        self.check_exception(
86
 
            options,
87
 
            "--brokerpassword must be specified",
88
 
            "--brokeruser", "Bob")
89
 
 
90
109
    def test_parse_minimal_options(self):
91
110
        options = Options()
92
111
        # The minimal set of options that must be provided.
93
112
        arguments = []
94
113
        options.parseOptions(arguments)  # No error.
95
114
 
96
 
    @skip(
97
 
        "RabbitMQ is not yet a required component "
98
 
        "of a running MaaS installation. Re-enable "
99
 
        "when RabbitMQ is once again needed; remove "
100
 
        "the other similarly named test.")
101
 
    def test_parse_int_options_SKIPPED(self):
102
 
        # Some options are converted to ints.
103
 
        options = Options()
104
 
        arguments = [
105
 
            "--brokerpassword", "Hoskins",
106
 
            "--brokerport", "4321",
107
 
            "--brokeruser", "Bob",
108
 
            "--port", "3456",
109
 
            ]
110
 
        options.parseOptions(arguments)
111
 
        self.assertEqual(4321, options["brokerport"])
112
 
        self.assertEqual(3456, options["port"])
113
 
 
114
 
    def test_parse_int_options(self):
115
 
        # Some options are converted to ints.
116
 
        options = Options()
117
 
        arguments = [
118
 
            "--port", "3456",
119
 
            ]
120
 
        options.parseOptions(arguments)
121
 
        self.assertEqual(3456, options["port"])
122
 
 
123
 
    @skip(
124
 
        "RabbitMQ is not yet a required component "
125
 
        "of a running MaaS installation. Re-enable "
126
 
        "when RabbitMQ is once again needed; remove "
127
 
        "the other similarly named test.")
128
 
    def test_parse_broken_int_options_SKIPPED(self):
129
 
        # An error is raised if the integer options do not contain integers.
130
 
        options = Options()
131
 
        arguments = [
132
 
            "--brokerpassword", "Hoskins",
133
 
            "--brokerport", "Jr.",
134
 
            "--brokeruser", "Bob",
135
 
            ]
136
 
        self.assertRaises(
137
 
            UsageError, options.parseOptions, arguments)
138
 
 
139
 
    def test_parse_broken_int_options(self):
140
 
        # An error is raised if the integer options do not contain integers.
141
 
        options = Options()
142
 
        arguments = [
143
 
            "--port", "Metallica",
144
 
            ]
145
 
        self.assertRaises(
146
 
            UsageError, options.parseOptions, arguments)
147
 
 
148
 
    @skip(
149
 
        "RabbitMQ is not yet a required component "
150
 
        "of a running MaaS installation. Re-enable "
151
 
        "when RabbitMQ is once again needed; remove "
152
 
        "the other similarly named test.")
153
 
    def test_oops_dir_without_reporter_SKIPPED(self):
154
 
        # It is an error to omit the OOPS reporter if directory is specified.
155
 
        options = Options()
156
 
        arguments = [
157
 
            "--brokerpassword", "Hoskins",
158
 
            "--brokeruser", "Bob",
159
 
            "--oops-dir", "/some/where",
160
 
            "--oops-reporter", "",
161
 
            ]
162
 
        expected = MatchesException(
163
 
            UsageError, "A reporter must be supplied")
164
 
        self.assertThat(
165
 
            partial(options.parseOptions, arguments),
166
 
            Raises(expected))
167
 
 
168
 
    def test_oops_dir_without_reporter(self):
169
 
        # It is an error to omit the OOPS reporter if directory is specified.
170
 
        options = Options()
171
 
        arguments = [
172
 
            "--oops-dir", "/some/where",
173
 
            "--oops-reporter", "",
174
 
            ]
175
 
        expected = MatchesException(
176
 
            UsageError, "A reporter must be supplied")
177
 
        self.assertThat(
178
 
            partial(options.parseOptions, arguments),
179
 
            Raises(expected))
180
 
 
181
115
 
182
116
class TestProvisioningServiceMaker(TestCase):
183
117
    """Tests for `provisioningserver.plugin.ProvisioningServiceMaker`."""
184
118
 
185
 
    def get_log_file(self):
186
 
        return os.path.join(
187
 
            self.useFixture(TempDir()).path, "pserv.log")
 
119
    def setUp(self):
 
120
        super(TestProvisioningServiceMaker, self).setUp()
 
121
        self.tempdir = self.useFixture(TempDir()).path
 
122
 
 
123
    def write_config(self, config):
 
124
        if "logfile" not in config:
 
125
            logfile = os.path.join(self.tempdir, "pserv.log")
 
126
            config = dict(config, logfile=logfile)
 
127
        config_filename = os.path.join(self.tempdir, "config.yaml")
 
128
        with open(config_filename, "wb") as stream:
 
129
            yaml.dump(config, stream)
 
130
        return config_filename
188
131
 
189
132
    def test_init(self):
190
133
        service_maker = ProvisioningServiceMaker("Harry", "Hill")
196
139
        Only the site service is created when no options are given.
197
140
        """
198
141
        options = Options()
199
 
        options["logfile"] = self.get_log_file()
 
142
        options["config-file"] = self.write_config({})
200
143
        service_maker = ProvisioningServiceMaker("Harry", "Hill")
201
 
        service = service_maker.makeService(options, _set_proc_title=False)
 
144
        service = service_maker.makeService(options)
202
145
        self.assertIsInstance(service, MultiService)
203
146
        self.assertSequenceEqual(
204
147
            ["log", "oops", "site"],
206
149
        self.assertEqual(
207
150
            len(service.namedServices), len(service.services),
208
151
            "Not all services are named.")
209
 
        site_service = service.getServiceNamed("site")
210
 
        self.assertEqual(options["port"], site_service.args[0])
211
152
 
212
 
    @skip(
213
 
        "RabbitMQ is not yet a required component "
214
 
        "of a running MaaS installation.")
215
153
    def test_makeService_with_broker(self):
216
154
        """
217
155
        The log, oops, site, and amqp services are created when the broker
218
156
        user and password options are given.
219
157
        """
220
158
        options = Options()
221
 
        options["brokerpassword"] = "Hoskins"
222
 
        options["brokeruser"] = "Bob"
223
 
        options["logfile"] = self.get_log_file()
 
159
        options["config-file"] = self.write_config(
 
160
            {"broker": {"username": "Bob", "password": "Hoskins"}})
224
161
        service_maker = ProvisioningServiceMaker("Harry", "Hill")
225
 
        service = service_maker.makeService(options, _set_proc_title=False)
 
162
        service = service_maker.makeService(options)
226
163
        self.assertIsInstance(service, MultiService)
227
164
        self.assertSequenceEqual(
228
165
            ["amqp", "log", "oops", "site"],
230
167
        self.assertEqual(
231
168
            len(service.namedServices), len(service.services),
232
169
            "Not all services are named.")
233
 
        amqp_client_service = service.getServiceNamed("amqp")
234
 
        self.assertEqual(options["brokerhost"], amqp_client_service.args[0])
235
 
        self.assertEqual(options["brokerport"], amqp_client_service.args[1])
236
 
        site_service = service.getServiceNamed("site")
237
 
        self.assertEqual(options["port"], site_service.args[0])