mirror of
https://github.com/outbackdingo/patroni.git
synced 2026-08-26 15:40:21 +00:00
POST /restart -- will restart postgres You you are restartung leader node, lock would be maintained during restart. POST /reinitialize -- will reinitialize node from the leader. It's not possible to reinitialize current leader. Command will fail when the leader is unknown.
111 lines
3.5 KiB
Python
111 lines
3.5 KiB
Python
import psycopg2
|
|
import unittest
|
|
|
|
from mock import Mock, patch
|
|
from patroni.api import RestApiHandler, RestApiServer
|
|
from six import BytesIO as IO
|
|
from six.moves import BaseHTTPServer
|
|
from test_postgresql import psycopg2_connect, MockCursor
|
|
|
|
|
|
class MockPostgresql(Mock):
|
|
|
|
name = 'test'
|
|
state = 'running'
|
|
role = 'master'
|
|
|
|
def connection(self):
|
|
return psycopg2_connect()
|
|
|
|
def is_running(self):
|
|
return True
|
|
|
|
|
|
class MockHa(Mock):
|
|
|
|
dcs = Mock()
|
|
state_handler = MockPostgresql()
|
|
|
|
def schedule_restart(self):
|
|
return 'restart'
|
|
|
|
def schedule_reinitialize(self):
|
|
return 'reinitialize'
|
|
|
|
def restart(self):
|
|
return True
|
|
|
|
def restart_scheduled(self):
|
|
return False
|
|
|
|
|
|
class MockPatroni:
|
|
|
|
postgresql = MockPostgresql()
|
|
ha = MockHa()
|
|
|
|
|
|
class MockRequest:
|
|
|
|
def __init__(self, path):
|
|
self.path = path
|
|
|
|
def makefile(self, *args, **kwargs):
|
|
return IO(self.path)
|
|
|
|
|
|
class MockRestApiServer(RestApiServer):
|
|
|
|
def __init__(self, Handler, path):
|
|
self.socket = 0
|
|
BaseHTTPServer.HTTPServer.__init__ = Mock()
|
|
MockRestApiServer._BaseServer__is_shut_down = Mock()
|
|
MockRestApiServer._BaseServer__shutdown_request = True
|
|
config = {'listen': '127.0.0.1:8008', 'auth': 'test:test', 'certfile': 'dumb'}
|
|
super(MockRestApiServer, self).__init__(MockPatroni(), config)
|
|
Handler(MockRequest(path), ('0.0.0.0', 8080), self)
|
|
|
|
|
|
@patch('ssl.wrap_socket', Mock(return_value=0))
|
|
class TestRestApiHandler(unittest.TestCase):
|
|
|
|
def test_do_GET(self):
|
|
MockRestApiServer(RestApiHandler, b'GET /master')
|
|
MockRestApiServer(RestApiHandler, b'GET /replica')
|
|
with patch.object(MockHa, 'restart_scheduled', Mock(return_value=True)):
|
|
MockRestApiServer(RestApiHandler, b'GET /master')
|
|
|
|
def test_do_GET_patroni(self):
|
|
MockRestApiServer(RestApiHandler, b'GET /patroni')
|
|
|
|
def test_basicauth(self):
|
|
MockRestApiServer(RestApiHandler, b'POST /restart HTTP/1.0')
|
|
MockRestApiServer(RestApiHandler, b'POST /restart HTTP/1.0\nAuthorization:')
|
|
|
|
def test_do_POST_restart(self):
|
|
request = b'POST /restart HTTP/1.0\nAuthorization: Basic dGVzdDp0ZXN0'
|
|
MockRestApiServer(RestApiHandler, request)
|
|
with patch.object(MockHa, 'schedule_restart', Mock(return_value=None)):
|
|
MockRestApiServer(RestApiHandler, request)
|
|
with patch.object(MockHa, 'restart', Mock(side_effect=Exception)):
|
|
MockRestApiServer(RestApiHandler, request)
|
|
|
|
@patch.object(MockHa, 'dcs')
|
|
def test_do_POST_reinitialize(self, dcs):
|
|
cluster = dcs.get_cluster.return_value
|
|
request = b'POST /reinitialize HTTP/1.0\nAuthorization: Basic dGVzdDp0ZXN0'
|
|
MockRestApiServer(RestApiHandler, request)
|
|
cluster.is_unlocked.return_value = False
|
|
MockRestApiServer(RestApiHandler, request)
|
|
with patch.object(MockHa, 'schedule_reinitialize', Mock(return_value=None)):
|
|
MockRestApiServer(RestApiHandler, request)
|
|
cluster.leader.name = 'test'
|
|
MockRestApiServer(RestApiHandler, request)
|
|
|
|
@patch('time.sleep', Mock())
|
|
def test_RestApiServer_query(self):
|
|
with patch.object(MockCursor, 'execute', Mock(side_effect=psycopg2.OperationalError)):
|
|
MockRestApiServer(RestApiHandler, b'GET /patroni')
|
|
with patch.object(MockPostgresql, 'connection', Mock(side_effect=psycopg2.OperationalError)):
|
|
MockRestApiServer(RestApiHandler, b'GET /patroni')
|