github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/acceptancetests/repository/trusty/haproxy/hooks/tests/test_peer_hooks.py (about) 1 import base64 2 import os 3 import yaml 4 import pwd 5 6 from testtools import TestCase 7 from mock import patch 8 9 import hooks 10 from utils_for_tests import patch_open 11 12 13 class PeerRelationTest(TestCase): 14 15 def setUp(self): 16 super(PeerRelationTest, self).setUp() 17 18 self.relations_of_type = self.patch_hook("relations_of_type") 19 self.log = self.patch_hook("log") 20 self.unit_get = self.patch_hook("unit_get") 21 22 def patch_hook(self, hook_name): 23 mock_controller = patch.object(hooks, hook_name) 24 mock = mock_controller.start() 25 self.addCleanup(mock_controller.stop) 26 return mock 27 28 @patch.dict(os.environ, {"JUJU_UNIT_NAME": "haproxy/2"}) 29 def test_with_peer_same_services(self): 30 self.unit_get.return_value = "1.2.4.5" 31 self.relations_of_type.return_value = [ 32 {"__unit__": "haproxy/1", 33 "hostname": "haproxy-1", 34 "private-address": "1.2.4.4", 35 "all_services": yaml.dump([ 36 {"service_name": "foo_service", 37 "service_host": "0.0.0.0", 38 "service_options": ["balance leastconn"], 39 "service_port": 4242}, 40 ]) 41 } 42 ] 43 44 services_dict = { 45 "foo_service": { 46 "service_name": "foo_service", 47 "service_host": "0.0.0.0", 48 "service_port": 4242, 49 "service_options": ["balance leastconn"], 50 "server_options": ["maxconn 4"], 51 "servers": [("backend_1__8080", "1.2.3.4", 52 8080, ["maxconn 4"])], 53 }, 54 } 55 56 expected = { 57 "foo_service": { 58 "service_name": "foo_service", 59 "service_host": "0.0.0.0", 60 "service_port": 4242, 61 "service_options": ["balance leastconn", 62 "mode tcp", 63 "option tcplog"], 64 "servers": [ 65 ("haproxy-1", "1.2.4.4", 4243, ["check"]), 66 ("haproxy-2", "1.2.4.5", 4243, ["check", "backup"]) 67 ], 68 }, 69 "foo_service_be": { 70 "service_name": "foo_service_be", 71 "service_host": "0.0.0.0", 72 "service_port": 4243, 73 "service_options": ["balance leastconn"], 74 "server_options": ["maxconn 4"], 75 "servers": [("backend_1__8080", "1.2.3.4", 76 8080, ["maxconn 4"])], 77 }, 78 } 79 self.assertEqual(expected, hooks.apply_peer_config(services_dict)) 80 81 @patch.dict(os.environ, {"JUJU_UNIT_NAME": "haproxy/2"}) 82 def test_inherit_timeout_settings(self): 83 self.unit_get.return_value = "1.2.4.5" 84 self.relations_of_type.return_value = [ 85 {"__unit__": "haproxy/1", 86 "hostname": "haproxy-1", 87 "private-address": "1.2.4.4", 88 "all_services": yaml.dump([ 89 {"service_name": "foo_service", 90 "service_host": "0.0.0.0", 91 "service_options": ["timeout server 5000"], 92 "service_port": 4242}, 93 ]) 94 } 95 ] 96 97 services_dict = { 98 "foo_service": { 99 "service_name": "foo_service", 100 "service_host": "0.0.0.0", 101 "service_port": 4242, 102 "service_options": ["timeout server 5000"], 103 "server_options": ["maxconn 4"], 104 "servers": [("backend_1__8080", "1.2.3.4", 105 8080, ["maxconn 4"])], 106 }, 107 } 108 109 expected = { 110 "foo_service": { 111 "service_name": "foo_service", 112 "service_host": "0.0.0.0", 113 "service_port": 4242, 114 "service_options": ["balance leastconn", 115 "mode tcp", 116 "option tcplog", 117 "timeout server 5000"], 118 "servers": [ 119 ("haproxy-1", "1.2.4.4", 4243, ["check"]), 120 ("haproxy-2", "1.2.4.5", 4243, ["check", "backup"]) 121 ], 122 }, 123 "foo_service_be": { 124 "service_name": "foo_service_be", 125 "service_host": "0.0.0.0", 126 "service_port": 4243, 127 "service_options": ["timeout server 5000"], 128 "server_options": ["maxconn 4"], 129 "servers": [("backend_1__8080", "1.2.3.4", 130 8080, ["maxconn 4"])], 131 }, 132 } 133 self.assertEqual(expected, hooks.apply_peer_config(services_dict)) 134 135 @patch.dict(os.environ, {"JUJU_UNIT_NAME": "haproxy/2"}) 136 def test_with_no_relation_data(self): 137 self.unit_get.return_value = "1.2.4.5" 138 self.relations_of_type.return_value = [] 139 140 services_dict = { 141 "foo_service": { 142 "service_name": "foo_service", 143 "service_host": "0.0.0.0", 144 "service_port": 4242, 145 "service_options": ["balance leastconn"], 146 "server_options": ["maxconn 4"], 147 "servers": [("backend_1__8080", "1.2.3.4", 148 8080, ["maxconn 4"])], 149 }, 150 } 151 152 expected = services_dict 153 self.assertEqual(expected, hooks.apply_peer_config(services_dict)) 154 155 @patch.dict(os.environ, {"JUJU_UNIT_NAME": "haproxy/2"}) 156 def test_with_missing_all_services(self): 157 self.unit_get.return_value = "1.2.4.5" 158 self.relations_of_type.return_value = [ 159 {"__unit__": "haproxy/1", 160 "hostname": "haproxy-1", 161 "private-address": "1.2.4.4", 162 } 163 ] 164 165 services_dict = { 166 "foo_service": { 167 "service_name": "foo_service", 168 "service_host": "0.0.0.0", 169 "service_port": 4242, 170 "service_options": ["balance leastconn"], 171 "server_options": ["maxconn 4"], 172 "servers": [("backend_1__8080", "1.2.3.4", 173 8080, ["maxconn 4"])], 174 }, 175 } 176 177 expected = services_dict 178 self.assertEqual(expected, hooks.apply_peer_config(services_dict)) 179 180 @patch('hooks.create_listen_stanza') 181 def test_writes_service_config(self, create_listen_stanza): 182 create_listen_stanza.return_value = 'some content' 183 services_dict = { 184 'foo': { 185 'service_name': 'bar', 186 'service_host': 'some-host', 187 'service_port': 'some-port', 188 'service_options': 'some-options', 189 'servers': (1, 2), 190 }, 191 } 192 193 with patch.object(os.path, "exists") as exists: 194 exists.return_value = True 195 with patch_open() as (mock_open, mock_file): 196 hooks.write_service_config(services_dict) 197 198 create_listen_stanza.assert_called_with( 199 'bar', 'some-host', 'some-port', 'some-options', 200 (1, 2), [], [], []) 201 mock_open.assert_called_with( 202 '/var/run/haproxy/bar.service', 'w') 203 mock_file.write.assert_called_with('some content') 204 205 @patch('hooks.create_listen_stanza') 206 def test_writes_errorfiles(self, create_listen_stanza): 207 create_listen_stanza.return_value = 'some content' 208 209 content = ("HTTP/1.0 403 Forbidden\r\n" 210 "Content-Type: text/html\r\n" 211 "\r\n" 212 "<html></html>") 213 services_dict = { 214 'foo': { 215 'service_name': 'bar', 216 'service_host': 'some-host', 217 'service_port': 'some-port', 218 'service_options': 'some-options', 219 'servers': (1, 2), 220 'errorfiles': [{ 221 'http_status': 403, 222 'content': base64.b64encode(content) 223 }] 224 }, 225 } 226 227 with patch.object(os.path, "exists") as exists: 228 exists.return_value = True 229 with patch_open() as (mock_open, mock_file): 230 hooks.write_service_config(services_dict) 231 232 mock_open.assert_any_call( 233 '/var/lib/haproxy/service_bar/403.http', 'w') 234 mock_file.write.assert_any_call(content) 235 self.assertTrue(create_listen_stanza.called) 236 237 @patch('hooks.create_listen_stanza') 238 def test_writes_crts(self, create_listen_stanza): 239 create_listen_stanza.return_value = 'some content' 240 241 content = ("-----BEGIN CERTIFICATE-----\n" 242 "<data>\n" 243 "-----END CERTIFICATE-----\n") 244 services_dict = { 245 'foo': { 246 'service_name': 'bar', 247 'service_host': 'some-host', 248 'service_port': 'some-port', 249 'service_options': 'some-options', 250 'servers': (1, 2), 251 'crts': [base64.b64encode(content)] 252 }, 253 } 254 255 with patch.object(os.path, "exists") as exists: 256 exists.return_value = True 257 with patch_open() as (mock_open, mock_file): 258 with patch.object(pwd, "getpwnam") as getpwnam: 259 class DB(object): 260 pw_uid = 9999 261 getpwnam.return_value = DB() 262 with patch.object(os, "chown") as chown: 263 hooks.write_service_config(services_dict) 264 path = '/var/lib/haproxy/service_bar/0.pem' 265 mock_open.assert_any_call(path, 'w') 266 mock_file.write.assert_any_call(content) 267 chown.assert_called_with(path, 9999, - 1) 268 self.assertTrue(create_listen_stanza.called) 269 270 @patch('hooks.create_listen_stanza') 271 def test_skip_crts_default(self, create_listen_stanza): 272 create_listen_stanza.return_value = 'some content' 273 services_dict = { 274 'foo': { 275 'service_name': 'bar', 276 'service_host': 'some-host', 277 'service_port': 'some-port', 278 'service_options': 'some-options', 279 'servers': (1, 2), 280 'crts': ["DEFAULT"] 281 }, 282 } 283 284 with patch.object(os.path, "exists") as exists: 285 exists.return_value = True 286 with patch.object(os, "makedirs"): 287 with patch_open() as (mock_open, mock_file): 288 hooks.write_service_config(services_dict) 289 self.assertNotEqual( 290 mock_open.call_args, 291 ('/var/lib/haproxy/service_bar/0.pem', 'w')) 292 self.assertTrue(create_listen_stanza.called)