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)