# Path: rpaas/nginx.py
# class Nginx(object):
# 
#     def __init__(self, conf=None):
#         self.nginx_manage_port = config.get_config('NGINX_MANAGE_PORT', '8089', conf)
#         self.nginx_manage_port_tls = config.get_config('NGINX_MANAGE_PORT_TLS', '8090', conf)
#         self.nginx_purge_path = config.get_config('NGINX_PURGE_PATH', '/purge', conf)
#         self.nginx_expected_healthcheck = config.get_config('NGINX_HEALTHECK_EXPECTED',
#                                                             'WORKING', conf)
#         self.nginx_healthcheck_path = config.get_config('NGINX_HEALTHCHECK_PATH',
#                                                         '/healthcheck', conf)
#         self.nginx_healthcheck_app_path = config.get_config('NGINX_HEALTHCHECK_APP_PATH',
#                                                             '/_nginx_healthcheck/', conf)
#         self.nginx_app_port = config.get_config('NGINX_APP_PORT', '8080', conf)
#         self.nginx_app_expected_healthcheck = config.get_config('NGINX_HEALTHECK_APP_EXPECTED',
#                                                                 'WORKING', conf)
#         self.ca_cert = config.get_config('CA_CERT', None, conf)
#         self.ca_path = "/tmp/rpaas_ca.pem"
#         self.config_manager = ConfigManager(conf)
# 
#     def purge_location(self, host, path, preserve_path=False):
#         purge_path = self.nginx_purge_path.lstrip('/')
#         purged = False
#         if preserve_path:
#             for encoding in ['gzip', 'identity']:
#                 try:
#                     self._nginx_request(host, "{}/{}".format(purge_path, path),
#                                         {'Accept-Encoding': encoding})
#                     purged = True
#                 except:
#                     pass
#             return purged
#         for scheme in ['http', 'https']:
#             for encoding in ['gzip', 'identity']:
#                 try:
#                     self._nginx_request(host, "{}/{}{}".format(purge_path, scheme, path),
#                                         {'Accept-Encoding': encoding})
#                     purged = True
#                 except:
#                     pass
#         return purged
# 
#     @retry_request
#     def wait_healthcheck(self, host, timeout=30, manage_healthcheck=True):
#         if manage_healthcheck:
#             healthcheck_path = self.nginx_healthcheck_path.lstrip('/')
#             expected_response = self.nginx_expected_healthcheck
#             port = self.nginx_manage_port
#         else:
#             healthcheck_path = self.nginx_healthcheck_app_path.lstrip('/')
#             expected_response = self.nginx_app_expected_healthcheck
#             port = self.nginx_app_port
#         self._nginx_request(host, healthcheck_path, port=port, expected_response=expected_response)
# 
#     @retry_request
#     def add_session_ticket(self, host, data, timeout=30):
#         self._nginx_request(host, 'session_ticket', data=data, method='POST', secure=True,
#                             expected_response='ticket was succsessfully added')
# 
#     def _nginx_request(self, host, path, headers=None, port=None,
#                        expected_response=None, secure=False, method='GET', data=None):
#         params = {}
#         if secure:
#             if not port:
#                 port = self.nginx_manage_port_tls
#             protocol = 'https'
#             self._ensure_ca_cert_file()
#             params['verify'] = self.ca_path
#         else:
#             if not port:
#                 port = self.nginx_manage_port
#             protocol = 'http'
#         url = "{}://{}:{}/{}".format(protocol, host, port, path)
#         if method not in ['POST', 'PUT', 'GET']:
#             raise NginxError("Unsupported method {}".format(method))
#         if headers:
#             params['headers'] = headers
#         if data:
#             params['data'] = data
#         rsp = requests.request(method.lower(), url, timeout=2, **params)
#         if rsp.status_code != 200 or (expected_response and expected_response not in rsp.text):
#             raise NginxError(
#                 "Error trying to access admin path in nginx: {}: {}".format(url, rsp.text))
# 
#     def _ensure_ca_cert_file(self):
#         if not self.ca_cert:
#             raise NginxError("CA_CERT should be set for nginx https internal requests")
#         if not os.path.exists(self.ca_path):
#             with open(self.ca_path, "w") as ca_file:
#                 ca_file.write(self.ca_cert)
# 
# class NginxError(Exception):
#     pass


import unittest
import mock
from rpaas.nginx import Nginx, NginxError

    @mock.patch('rpaas.nginx.requests')
    def test_wait_healthcheck_timeout(self, requests):
        nginx = Nginx()

        def side_effect(method, url, timeout, **params):
            raise Exception('some error')

        requests.request.side_effect = side_effect
        with self.assertRaises(Exception):
            nginx.wait_healthcheck('myhost.com', timeout=2)
        self.assertGreaterEqual(requests.request.call_count, 2)
        requests.request.assert_called_with('get', 'http://myhost.com:8089/healthcheck', timeout=2)

    @mock.patch('os.path')
    @mock.patch('rpaas.nginx.requests')
    def test_add_session_ticket_success(self, requests, os_path):
        nginx = Nginx({'CA_CERT': 'cert data'})
        os_path.exists.return_value = True
        response = mock.Mock()
        response.status_code = 200
        response.text = '\n\nticket was succsessfully added'
        requests.request.return_value = response
        nginx.add_session_ticket('host-1', 'random data', timeout=2)
        requests.request.assert_called_once_with('post', 'https://host-1:8090/session_ticket', timeout=2,
                                                 data='random data', verify='/tmp/rpaas_ca.pem')

    @mock.patch('rpaas.nginx.requests')
    def test_missing_ca_cert(self, requests):
        nginx = Nginx()

# Path: rpaas/nginx.py
# class Nginx(object):
# 
#     def __init__(self, conf=None):
#         self.nginx_manage_port = config.get_config('NGINX_MANAGE_PORT', '8089', conf)
#         self.nginx_manage_port_tls = config.get_config('NGINX_MANAGE_PORT_TLS', '8090', conf)
#         self.nginx_purge_path = config.get_config('NGINX_PURGE_PATH', '/purge', conf)
#         self.nginx_expected_healthcheck = config.get_config('NGINX_HEALTHECK_EXPECTED',
#                                                             'WORKING', conf)
#         self.nginx_healthcheck_path = config.get_config('NGINX_HEALTHCHECK_PATH',
#                                                         '/healthcheck', conf)
#         self.nginx_healthcheck_app_path = config.get_config('NGINX_HEALTHCHECK_APP_PATH',
#                                                             '/_nginx_healthcheck/', conf)
#         self.nginx_app_port = config.get_config('NGINX_APP_PORT', '8080', conf)
#         self.nginx_app_expected_healthcheck = config.get_config('NGINX_HEALTHECK_APP_EXPECTED',
#                                                                 'WORKING', conf)
#         self.ca_cert = config.get_config('CA_CERT', None, conf)
#         self.ca_path = "/tmp/rpaas_ca.pem"
#         self.config_manager = ConfigManager(conf)
# 
#     def purge_location(self, host, path, preserve_path=False):
#         purge_path = self.nginx_purge_path.lstrip('/')
#         purged = False
#         if preserve_path:
#             for encoding in ['gzip', 'identity']:
#                 try:
#                     self._nginx_request(host, "{}/{}".format(purge_path, path),
#                                         {'Accept-Encoding': encoding})
#                     purged = True
#                 except:
#                     pass
#             return purged
#         for scheme in ['http', 'https']:
#             for encoding in ['gzip', 'identity']:
#                 try:
#                     self._nginx_request(host, "{}/{}{}".format(purge_path, scheme, path),
#                                         {'Accept-Encoding': encoding})
#                     purged = True
#                 except:
#                     pass
#         return purged
# 
#     @retry_request
#     def wait_healthcheck(self, host, timeout=30, manage_healthcheck=True):
#         if manage_healthcheck:
#             healthcheck_path = self.nginx_healthcheck_path.lstrip('/')
#             expected_response = self.nginx_expected_healthcheck
#             port = self.nginx_manage_port
#         else:
#             healthcheck_path = self.nginx_healthcheck_app_path.lstrip('/')
#             expected_response = self.nginx_app_expected_healthcheck
#             port = self.nginx_app_port
#         self._nginx_request(host, healthcheck_path, port=port, expected_response=expected_response)
# 
#     @retry_request
#     def add_session_ticket(self, host, data, timeout=30):
#         self._nginx_request(host, 'session_ticket', data=data, method='POST', secure=True,
#                             expected_response='ticket was succsessfully added')
# 
#     def _nginx_request(self, host, path, headers=None, port=None,
#                        expected_response=None, secure=False, method='GET', data=None):
#         params = {}
#         if secure:
#             if not port:
#                 port = self.nginx_manage_port_tls
#             protocol = 'https'
#             self._ensure_ca_cert_file()
#             params['verify'] = self.ca_path
#         else:
#             if not port:
#                 port = self.nginx_manage_port
#             protocol = 'http'
#         url = "{}://{}:{}/{}".format(protocol, host, port, path)
#         if method not in ['POST', 'PUT', 'GET']:
#             raise NginxError("Unsupported method {}".format(method))
#         if headers:
#             params['headers'] = headers
#         if data:
#             params['data'] = data
#         rsp = requests.request(method.lower(), url, timeout=2, **params)
#         if rsp.status_code != 200 or (expected_response and expected_response not in rsp.text):
#             raise NginxError(
#                 "Error trying to access admin path in nginx: {}: {}".format(url, rsp.text))
# 
#     def _ensure_ca_cert_file(self):
#         if not self.ca_cert:
#             raise NginxError("CA_CERT should be set for nginx https internal requests")
#         if not os.path.exists(self.ca_path):
#             with open(self.ca_path, "w") as ca_file:
#                 ca_file.write(self.ca_cert)
# 
# class NginxError(Exception):
#     pass


# Path: tests/test_nginx.py
import unittest
import mock
from rpaas.nginx import Nginx, NginxError


    @mock.patch('rpaas.nginx.requests')
    def test_wait_healthcheck_timeout(self, requests):
        nginx = Nginx()

        def side_effect(method, url, timeout, **params):
            raise Exception('some error')

        requests.request.side_effect = side_effect
        with self.assertRaises(Exception):
            nginx.wait_healthcheck('myhost.com', timeout=2)
        self.assertGreaterEqual(requests.request.call_count, 2)
        requests.request.assert_called_with('get', 'http://myhost.com:8089/healthcheck', timeout=2)

    @mock.patch('os.path')
    @mock.patch('rpaas.nginx.requests')
    def test_add_session_ticket_success(self, requests, os_path):
        nginx = Nginx({'CA_CERT': 'cert data'})
        os_path.exists.return_value = True
        response = mock.Mock()
        response.status_code = 200
        response.text = '\n\nticket was succsessfully added'
        requests.request.return_value = response
        nginx.add_session_ticket('host-1', 'random data', timeout=2)
        requests.request.assert_called_once_with('post', 'https://host-1:8090/session_ticket', timeout=2,
                                                 data='random data', verify='/tmp/rpaas_ca.pem')

    @mock.patch('rpaas.nginx.requests')
    def test_missing_ca_cert(self, requests):
        nginx = Nginx()

        with self.assertRaises(NginxError):