~marcoceppi/charms/precise/haproxy/cfg-changed-fix

« back to all changes in this revision

Viewing changes to hooks/tests/test_reverseproxy_hooks.py

  • Committer: Marco Ceppi
  • Date: 2013-10-17 03:33:47 UTC
  • mfrom: (60.1.27 haproxy)
  • Revision ID: marco@ceppi.net-20131017033347-7ha6tdiivmpardtx
[sidnei] The 'all_services' config now supports a static list of servers to be used *in addition* to the ones provided via relation.
[sidnei] When more than one haproxy units exist, the configured service is upgraded in-place to a mode where traffic is routed to a single haproxy unit (the first one in unit-name order) and the remaining ones are configured as 'backup'. This is done to allow the enforcement of a 'maxconn' session in the configured services, which would not be possible to enforce otherwise.
[sidnei] Changes to the configured services are properly propagated to the upstream relation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from testtools import TestCase
 
2
from mock import patch, call
 
3
 
 
4
import hooks
 
5
 
 
6
 
 
7
class ReverseProxyRelationTest(TestCase):
 
8
 
 
9
    def setUp(self):
 
10
        super(ReverseProxyRelationTest, self).setUp()
 
11
 
 
12
        self.relations_of_type = self.patch_hook("relations_of_type")
 
13
        self.get_config_services = self.patch_hook("get_config_services")
 
14
        self.log = self.patch_hook("log")
 
15
        self.write_service_config = self.patch_hook("write_service_config")
 
16
        self.apply_peer_config = self.patch_hook("apply_peer_config")
 
17
        self.apply_peer_config.side_effect = lambda value: value
 
18
 
 
19
    def patch_hook(self, hook_name):
 
20
        mock_controller = patch.object(hooks, hook_name)
 
21
        mock = mock_controller.start()
 
22
        self.addCleanup(mock_controller.stop)
 
23
        return mock
 
24
 
 
25
    def test_relation_data_returns_none(self):
 
26
        self.get_config_services.return_value = {
 
27
            "service": {
 
28
                "service_name": "service",
 
29
                },
 
30
            }
 
31
        self.relations_of_type.return_value = []
 
32
        self.assertIs(None, hooks.create_services())
 
33
        self.log.assert_called_once_with("No backend servers, exiting.")
 
34
        self.write_service_config.assert_not_called()
 
35
 
 
36
    def test_relation_data_returns_no_relations(self):
 
37
        self.get_config_services.return_value = {
 
38
            "service": {
 
39
                "service_name": "service",
 
40
                },
 
41
            }
 
42
        self.relations_of_type.return_value = []
 
43
        self.assertIs(None, hooks.create_services())
 
44
        self.log.assert_called_once_with("No backend servers, exiting.")
 
45
        self.write_service_config.assert_not_called()
 
46
 
 
47
    def test_relation_no_services(self):
 
48
        self.get_config_services.return_value = {}
 
49
        self.relations_of_type.return_value = [
 
50
            {"port": 4242,
 
51
             "__unit__": "foo/0",
 
52
             "hostname": "backend.1",
 
53
             "private-address": "1.2.3.4"},
 
54
        ]
 
55
        self.assertIs(None, hooks.create_services())
 
56
        self.log.assert_called_once_with("No services configured, exiting.")
 
57
        self.write_service_config.assert_not_called()
 
58
 
 
59
    def test_no_port_in_relation_data(self):
 
60
        self.get_config_services.return_value = {
 
61
            "service": {
 
62
                "service_name": "service",
 
63
                },
 
64
            }
 
65
        self.relations_of_type.return_value = [
 
66
            {"private-address": "1.2.3.4",
 
67
             "__unit__": "foo/0"},
 
68
        ]
 
69
        self.assertIs(None, hooks.create_services())
 
70
        self.log.assert_has_calls([call.log(
 
71
            "No port in relation data for 'foo/0', skipping.")])
 
72
        self.write_service_config.assert_not_called()
 
73
 
 
74
    def test_no_private_address_in_relation_data(self):
 
75
        self.get_config_services.return_value = {
 
76
            "service": {
 
77
                "service_name": "service",
 
78
                },
 
79
            }
 
80
        self.relations_of_type.return_value = [
 
81
            {"port": 4242,
 
82
             "__unit__": "foo/0"},
 
83
        ]
 
84
        self.assertIs(None, hooks.create_services())
 
85
        self.log.assert_has_calls([call.log(
 
86
            "No private-address in relation data for 'foo/0', skipping.")])
 
87
        self.write_service_config.assert_not_called()
 
88
 
 
89
    def test_no_hostname_in_relation_data(self):
 
90
        self.get_config_services.return_value = {
 
91
            "service": {
 
92
                "service_name": "service",
 
93
                },
 
94
            }
 
95
        self.relations_of_type.return_value = [
 
96
            {"port": 4242,
 
97
             "private-address": "1.2.3.4",
 
98
             "__unit__": "foo/0"},
 
99
        ]
 
100
        self.assertIs(None, hooks.create_services())
 
101
        self.log.assert_has_calls([call.log(
 
102
            "No hostname in relation data for 'foo/0', skipping.")])
 
103
        self.write_service_config.assert_not_called()
 
104
 
 
105
    def test_relation_unknown_service(self):
 
106
        self.get_config_services.return_value = {
 
107
            "service": {
 
108
                "service_name": "service",
 
109
                },
 
110
            }
 
111
        self.relations_of_type.return_value = [
 
112
            {"port": 4242,
 
113
             "hostname": "backend.1",
 
114
             "service_name": "invalid",
 
115
             "private-address": "1.2.3.4",
 
116
             "__unit__": "foo/0"},
 
117
        ]
 
118
        self.assertIs(None, hooks.create_services())
 
119
        self.log.assert_has_calls([call.log(
 
120
            "Service 'invalid' does not exist.")])
 
121
        self.write_service_config.assert_not_called()
 
122
 
 
123
    def test_no_relation_but_has_servers_from_config(self):
 
124
        self.get_config_services.return_value = {
 
125
            None: {
 
126
                "service_name": "service",
 
127
                },
 
128
            "service": {
 
129
                "service_name": "service",
 
130
                "servers": [
 
131
                    ("legacy-backend", "1.2.3.1", 4242, ["maxconn 42"]),
 
132
                    ]
 
133
                },
 
134
            }
 
135
        self.relations_of_type.return_value = []
 
136
 
 
137
        expected = {
 
138
            'service': {
 
139
                'service_name': 'service',
 
140
                'servers': [
 
141
                    ("legacy-backend", "1.2.3.1", 4242, ["maxconn 42"]),
 
142
                    ],
 
143
                },
 
144
            }
 
145
        self.assertEqual(expected, hooks.create_services())
 
146
        self.write_service_config.assert_called_with(expected)
 
147
 
 
148
    def test_relation_default_service(self):
 
149
        self.get_config_services.return_value = {
 
150
            None: {
 
151
                "service_name": "service",
 
152
                },
 
153
            "service": {
 
154
                "service_name": "service",
 
155
                },
 
156
            }
 
157
        self.relations_of_type.return_value = [
 
158
            {"port": 4242,
 
159
             "hostname": "backend.1",
 
160
             "private-address": "1.2.3.4",
 
161
             "__unit__": "foo/0"},
 
162
        ]
 
163
 
 
164
        expected = {
 
165
            'service': {
 
166
                'service_name': 'service',
 
167
                'servers': [('foo-0-4242', '1.2.3.4', 4242, [])],
 
168
                },
 
169
            }
 
170
        self.assertEqual(expected, hooks.create_services())
 
171
        self.write_service_config.assert_called_with(expected)
 
172
 
 
173
    def test_with_service_options(self):
 
174
        self.get_config_services.return_value = {
 
175
            None: {
 
176
                "service_name": "service",
 
177
                },
 
178
            "service": {
 
179
                "service_name": "service",
 
180
                "server_options": ["maxconn 4"],
 
181
                },
 
182
            }
 
183
        self.relations_of_type.return_value = [
 
184
            {"port": 4242,
 
185
             "hostname": "backend.1",
 
186
             "private-address": "1.2.3.4",
 
187
             "__unit__": "foo/0"},
 
188
        ]
 
189
 
 
190
        expected = {
 
191
            'service': {
 
192
                'service_name': 'service',
 
193
                'server_options': ["maxconn 4"],
 
194
                'servers': [('foo-0-4242', '1.2.3.4',
 
195
                             4242, ["maxconn 4"])],
 
196
                },
 
197
            }
 
198
        self.assertEqual(expected, hooks.create_services())
 
199
        self.write_service_config.assert_called_with(expected)
 
200
 
 
201
    def test_with_service_name(self):
 
202
        self.get_config_services.return_value = {
 
203
            None: {
 
204
                "service_name": "service",
 
205
                },
 
206
            "foo_service": {
 
207
                "service_name": "foo_service",
 
208
                "server_options": ["maxconn 4"],
 
209
                },
 
210
            }
 
211
        self.relations_of_type.return_value = [
 
212
            {"port": 4242,
 
213
             "hostname": "backend.1",
 
214
             "service_name": "foo_service",
 
215
             "private-address": "1.2.3.4",
 
216
             "__unit__": "foo/0"},
 
217
        ]
 
218
 
 
219
        expected = {
 
220
            'foo_service': {
 
221
                'service_name': 'foo_service',
 
222
                'server_options': ["maxconn 4"],
 
223
                'servers': [('foo-0-4242', '1.2.3.4',
 
224
                             4242, ["maxconn 4"])],
 
225
                },
 
226
            }
 
227
        self.assertEqual(expected, hooks.create_services())
 
228
        self.write_service_config.assert_called_with(expected)
 
229
 
 
230
    def test_no_service_name_unit_name_match_service_name(self):
 
231
        self.get_config_services.return_value = {
 
232
            None: {
 
233
                "service_name": "foo_service",
 
234
                },
 
235
            "foo_service": {
 
236
                "service_name": "foo_service",
 
237
                "server_options": ["maxconn 4"],
 
238
                },
 
239
            }
 
240
        self.relations_of_type.return_value = [
 
241
            {"port": 4242,
 
242
             "hostname": "backend.1",
 
243
             "private-address": "1.2.3.4",
 
244
             "__unit__": "foo/1"},
 
245
        ]
 
246
 
 
247
        expected = {
 
248
            'foo_service': {
 
249
                'service_name': 'foo_service',
 
250
                'server_options': ["maxconn 4"],
 
251
                'servers': [('foo-1-4242', '1.2.3.4',
 
252
                             4242, ["maxconn 4"])],
 
253
                },
 
254
            }
 
255
        self.assertEqual(expected, hooks.create_services())
 
256
        self.write_service_config.assert_called_with(expected)
 
257
 
 
258
    def test_with_sitenames_match_service_name(self):
 
259
        self.get_config_services.return_value = {
 
260
            None: {
 
261
                "service_name": "service",
 
262
                },
 
263
            "foo_srv": {
 
264
                "service_name": "foo_srv",
 
265
                "server_options": ["maxconn 4"],
 
266
                },
 
267
            }
 
268
        self.relations_of_type.return_value = [
 
269
            {"port": 4242,
 
270
             "hostname": "backend.1",
 
271
             "sitenames": "foo_srv bar_srv",
 
272
             "private-address": "1.2.3.4",
 
273
             "__unit__": "foo/0"},
 
274
        ]
 
275
 
 
276
        expected = {
 
277
            'foo_srv': {
 
278
                'service_name': 'foo_srv',
 
279
                'server_options': ["maxconn 4"],
 
280
                'servers': [('foo-0-4242', '1.2.3.4',
 
281
                             4242, ["maxconn 4"])],
 
282
                },
 
283
            }
 
284
        self.assertEqual(expected, hooks.create_services())
 
285
        self.write_service_config.assert_called_with(expected)
 
286
 
 
287
    def test_with_juju_services_match_service_name(self):
 
288
        self.get_config_services.return_value = {
 
289
            None: {
 
290
                "service_name": "service",
 
291
                },
 
292
            "foo_service": {
 
293
                "service_name": "foo_service",
 
294
                "server_options": ["maxconn 4"],
 
295
                },
 
296
            }
 
297
        self.relations_of_type.return_value = [
 
298
            {"port": 4242,
 
299
             "hostname": "backend.1",
 
300
             "private-address": "1.2.3.4",
 
301
             "__unit__": "foo/1"},
 
302
        ]
 
303
 
 
304
        expected = {
 
305
            'foo_service': {
 
306
                'service_name': 'foo_service',
 
307
                'server_options': ["maxconn 4"],
 
308
                'servers': [('foo-1-4242', '1.2.3.4',
 
309
                             4242, ["maxconn 4"])],
 
310
                },
 
311
            }
 
312
 
 
313
        result = hooks.create_services()
 
314
 
 
315
        self.assertEqual(expected, result)
 
316
        self.write_service_config.assert_called_with(expected)
 
317
 
 
318
    def test_with_sitenames_no_match_but_unit_name(self):
 
319
        self.get_config_services.return_value = {
 
320
            None: {
 
321
                "service_name": "service",
 
322
                },
 
323
            "foo": {
 
324
                "service_name": "foo",
 
325
                "server_options": ["maxconn 4"],
 
326
                },
 
327
            }
 
328
        self.relations_of_type.return_value = [
 
329
            {"port": 4242,
 
330
             "hostname": "backend.1",
 
331
             "sitenames": "bar_service baz_service",
 
332
             "private-address": "1.2.3.4",
 
333
             "__unit__": "foo/0"},
 
334
        ]
 
335
 
 
336
        expected = {
 
337
            'foo': {
 
338
                'service_name': 'foo',
 
339
                'server_options': ["maxconn 4"],
 
340
                'servers': [('foo-0-4242', '1.2.3.4',
 
341
                             4242, ["maxconn 4"])],
 
342
                },
 
343
            }
 
344
        self.assertEqual(expected, hooks.create_services())
 
345
        self.write_service_config.assert_called_with(expected)