This commit is contained in:
zandercymatics 2023-10-18 15:41:38 -06:00
parent c2cc19ee1a
commit 9a12e29c5a
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
6 changed files with 66 additions and 73 deletions

View file

@ -163,16 +163,12 @@ class EPPLibWrapper:
def get_pool(self): def get_pool(self):
"""Get the current pool instance""" """Get the current pool instance"""
return self._pool return self._pool
def _create_pool(self, client, login, options): def _create_pool(self, client, login, options):
"""Creates and returns new pool instance""" """Creates and returns new pool instance"""
return EPPConnectionPool( return EPPConnectionPool(client, login, options)
client, login, options
)
def start_connection_pool( def start_connection_pool(self, restart_pool_if_exists=True):
self, restart_pool_if_exists=True
):
"""Starts a connection pool for the registry. """Starts a connection pool for the registry.
restart_pool_if_exists -> bool: restart_pool_if_exists -> bool:
@ -199,9 +195,7 @@ class EPPLibWrapper:
logger.info("Connection pool restarting...") logger.info("Connection pool restarting...")
self.kill_pool() self.kill_pool()
self._pool = self._create_pool( self._pool = self._create_pool(self._client, self._login, self.pool_options)
self._client, self._login, self.pool_options
)
self.pool_status.pool_running = True self.pool_status.pool_running = True
self.pool_status.pool_hanging = False self.pool_status.pool_hanging = False

View file

@ -59,8 +59,6 @@ class Socket:
counter += 1 counter += 1
sleep((counter * 50) / 1000) # sleep 50 ms to 150 ms sleep((counter * 50) / 1000) # sleep 50 ms to 150 ms
else: # don't try again else: # don't try again
logger.warning("LoginError raised and should not retry or has been retried 3 times already")
logger.warning(f"should retry? {err.should_retry()}")
return False return False
else: else:
self.disconnect() self.disconnect()
@ -69,7 +67,7 @@ class Socket:
if self.is_login_error(response.code): if self.is_login_error(response.code):
logger.warning("was login error") logger.warning("was login error")
return False return False
# otherwise, just return true # otherwise, just return true
return True return True

View file

@ -1,15 +1,11 @@
import datetime import datetime
from pathlib import Path from pathlib import Path
from unittest import skip
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from dateutil.tz import tzlocal from dateutil.tz import tzlocal
from django.conf import settings
from django.test import TestCase from django.test import TestCase
from epplibwrapper.client import EPPLibWrapper from epplibwrapper.client import EPPLibWrapper
from epplibwrapper.socket import Socket from epplibwrapper.socket import Socket
from epplibwrapper.utility.pool import EPPConnectionPool from epplibwrapper.utility.pool import EPPConnectionPool
from registrar.models.domain import Domain
from registrar.models.domain import registry from registrar.models.domain import registry
from contextlib import ExitStack from contextlib import ExitStack
@ -40,7 +36,7 @@ class TestConnectionPool(TestCase):
# Value in seconds => (keepalive / size) # Value in seconds => (keepalive / size)
"keepalive": 60, "keepalive": 60,
} }
def fake_socket(self, login, client): def fake_socket(self, login, client):
# Create a fake client object # Create a fake client object
fake_client = Client( fake_client = Client(
@ -56,55 +52,57 @@ class TestConnectionPool(TestCase):
def patch_success(self): def patch_success(self):
return True return True
def fake_send(self, command, cleaned=None): def fake_send(self, command, cleaned=None):
mock = MagicMock( mock = MagicMock(
code=1000, code=1000,
msg="Command completed successfully", msg="Command completed successfully",
res_data=None, res_data=None,
cl_tr_id="xkw1uo#2023-10-17T15:29:09.559376", cl_tr_id="xkw1uo#2023-10-17T15:29:09.559376",
sv_tr_id="5CcH4gxISuGkq8eqvr1UyQ==-35a", sv_tr_id="5CcH4gxISuGkq8eqvr1UyQ==-35a",
extensions=[], extensions=[],
msg_q=None, msg_q=None,
) )
return mock return mock
@patch.object(EPPLibWrapper, "_test_registry_connection_success", patch_success) @patch.object(EPPLibWrapper, "_test_registry_connection_success", patch_success)
def test_pool_sends_data(self): def test_pool_sends_data(self):
"""A .send is invoked on the pool successfully""" """A .send is invoked on the pool successfully"""
expected_result = { expected_result = {
'cl_tr_id': None, "cl_tr_id": None,
'code': 1000, "code": 1000,
'extensions': [], "extensions": [],
'msg': 'Command completed successfully', "msg": "Command completed successfully",
'msg_q': None, "msg_q": None,
'res_data': [info.InfoDomainResultData( "res_data": [
roid='DF1340360-GOV', info.InfoDomainResultData(
statuses=[ roid="DF1340360-GOV",
common.Status( statuses=[
state='serverTransferProhibited', common.Status(
description=None, state="serverTransferProhibited",
lang='en' description=None,
), lang="en",
common.Status(state='inactive', ),
description=None, common.Status(state="inactive", description=None, lang="en"),
lang='en')], ],
cl_id='gov2023-ote', cl_id="gov2023-ote",
cr_id='gov2023-ote', cr_id="gov2023-ote",
cr_date=datetime.datetime(2023, 8, 15, 23, 56, 36, tzinfo=tzlocal()), cr_date=datetime.datetime(
up_id='gov2023-ote', 2023, 8, 15, 23, 56, 36, tzinfo=tzlocal()
up_date=datetime.datetime(2023, 8, 17, 2, 3, 19, tzinfo=tzlocal()), ),
tr_date=None, up_id="gov2023-ote",
name='test3.gov', up_date=datetime.datetime(2023, 8, 17, 2, 3, 19, tzinfo=tzlocal()),
registrant='TuaWnx9hnm84GCSU', tr_date=None,
admins=[], name="test3.gov",
nsset=None, registrant="TuaWnx9hnm84GCSU",
keyset=None, admins=[],
ex_date=datetime.date(2024, 8, 15), nsset=None,
auth_info=info.DomainAuthInfo(pw='2fooBAR123fooBaz') keyset=None,
) ex_date=datetime.date(2024, 8, 15),
], auth_info=info.DomainAuthInfo(pw="2fooBAR123fooBaz"),
'sv_tr_id': 'wRRNVhKhQW2m6wsUHbo/lA==-29a' )
],
"sv_tr_id": "wRRNVhKhQW2m6wsUHbo/lA==-29a",
} }
def fake_client(mock_client): def fake_client(mock_client):
@ -117,16 +115,18 @@ class TestConnectionPool(TestCase):
) )
) )
return client return client
# Mock a response from EPP # Mock a response from EPP
def fake_receive(command, cleaned=None): def fake_receive(command, cleaned=None):
location= Path(__file__).parent / "utility" / "infoDomain.xml" location = Path(__file__).parent / "utility" / "infoDomain.xml"
xml = (location).read_bytes() xml = (location).read_bytes()
return xml return xml
# Mock what happens inside the "with" # Mock what happens inside the "with"
with ExitStack() as stack: with ExitStack() as stack:
stack.enter_context(patch.object(EPPConnectionPool, "_create_socket", self.fake_socket)) stack.enter_context(
patch.object(EPPConnectionPool, "_create_socket", self.fake_socket)
)
stack.enter_context(patch.object(Socket, "connect", fake_client)) stack.enter_context(patch.object(Socket, "connect", fake_client))
stack.enter_context(patch.object(SocketTransport, "send", self.fake_send)) stack.enter_context(patch.object(SocketTransport, "send", self.fake_send))
stack.enter_context(patch.object(SocketTransport, "receive", fake_receive)) stack.enter_context(patch.object(SocketTransport, "receive", fake_receive))
@ -141,17 +141,18 @@ class TestConnectionPool(TestCase):
# Should this ever fail, it either means that the schema has changed, # Should this ever fail, it either means that the schema has changed,
# or the pool is broken. # or the pool is broken.
# If the schema has changed: Update the associated infoDomain.xml file # If the schema has changed: Update the associated infoDomain.xml file
self.assertEqual(result.__dict__, expected_result) self.assertEqual(result.__dict__, expected_result)
# The number of open pools should match the number of requested ones. # The number of open pools should match the number of requested ones.
# If it is 0, then they failed to open # If it is 0, then they failed to open
self.assertEqual(len(registry._pool.conn), self.pool_options["size"]) self.assertEqual(len(registry._pool.conn), self.pool_options["size"])
@patch.object(EPPLibWrapper, "_test_registry_connection_success", patch_success) @patch.object(EPPLibWrapper, "_test_registry_connection_success", patch_success)
def test_raises_transport_error(self): def test_raises_transport_error(self):
"""A .send is invoked on the pool, but registry connection is lost """A .send is invoked on the pool, but registry connection is lost
right as we send a command.""" right as we send a command."""
# Fake data for the _pool object # Fake data for the _pool object
def fake_client(self): def fake_client(self):
client = Client( client = Client(
@ -165,7 +166,9 @@ class TestConnectionPool(TestCase):
return client return client
with ExitStack() as stack: with ExitStack() as stack:
stack.enter_context(patch.object(EPPConnectionPool, "_create_socket", self.fake_socket)) stack.enter_context(
patch.object(EPPConnectionPool, "_create_socket", self.fake_socket)
)
stack.enter_context(patch.object(Socket, "connect", fake_client)) stack.enter_context(patch.object(Socket, "connect", fake_client))
# Restart the connection pool, since it starts on app startup # Restart the connection pool, since it starts on app startup
registry.start_connection_pool() registry.start_connection_pool()
@ -176,5 +179,3 @@ class TestConnectionPool(TestCase):
# Try to send a command out - should fail # Try to send a command out - should fail
with self.assertRaises(TransportError): with self.assertRaises(TransportError):
registry.send(commands.InfoDomain(name="test.gov"), cleaned=True) registry.send(commands.InfoDomain(name="test.gov"), cleaned=True)

View file

@ -1,9 +1,9 @@
import logging import logging
import greenlet
import gevent import gevent
from geventconnpool import ConnectionPool from geventconnpool import ConnectionPool
from epplibwrapper.socket import Socket from epplibwrapper.socket import Socket
from epplibwrapper.utility.pool_error import PoolError, PoolErrorCodes from epplibwrapper.utility.pool_error import PoolError, PoolErrorCodes
try: try:
from epplib.commands import Hello from epplib.commands import Hello
except ImportError: except ImportError:

View file

@ -546,7 +546,7 @@ EPP_CONNECTION_POOL_SIZE = 1
# Determines the interval in which we ping open connections in seconds # Determines the interval in which we ping open connections in seconds
# Calculated as POOL_KEEP_ALIVE / EPP_CONNECTION_POOL_SIZE # Calculated as POOL_KEEP_ALIVE / EPP_CONNECTION_POOL_SIZE
POOL_KEEP_ALIVE = 60 POOL_KEEP_ALIVE = 60
# Determines how long we try to keep a pool alive for, # Determines how long we try to keep a pool alive for,
# before restarting it. # before restarting it.

View file

@ -16,7 +16,7 @@ from registrar.utility.errors import (
NameserverError, NameserverError,
NameserverErrorCodes as nsErrorCodes, NameserverErrorCodes as nsErrorCodes,
) )
from epplibwrapper import ( from epplibwrapper import (
CLIENT as registry, CLIENT as registry,
commands, commands,