Checking for subdomains, fixing more ip logic stuff and tests

This commit is contained in:
Rebecca Hsieh 2023-09-28 15:55:54 -07:00
parent 026860c88a
commit 1f149700e3
No known key found for this signature in database
GPG key ID: 644527A2F375A379
4 changed files with 401 additions and 196 deletions

View file

@ -21,7 +21,8 @@ class DomainNameserverForm(forms.Form):
"""Form for changing nameservers."""
server = forms.CharField(label="Name server", strip=True)
#when adding IPs to this form ensure they are stripped as well
# when adding IPs to this form ensure they are stripped as well
NameserverFormset = formset_factory(
DomainNameserverForm,

View file

@ -228,8 +228,6 @@ class Domain(TimeStampedModel, DomainHelper):
"""
try:
hosts = self._get_property("hosts")
print("HOST IS ")
print(hosts)
except Exception as err:
# TODO-848: Check/add to error handling ticket if it's not addressed
# (Don't throw error as this is normal for a new domain?)
@ -238,7 +236,7 @@ class Domain(TimeStampedModel, DomainHelper):
hostList = []
for host in hosts:
hostList.append((host["name"],host["addrs"]))
hostList.append((host["name"], host["addrs"]))
return hostList
@ -267,14 +265,11 @@ class Domain(TimeStampedModel, DomainHelper):
returns ErrorCode (int)"""
logger.info("Creating host")
if addrs is not None:
# TODO-848: Make sure to have 1 with ip address + 1 without
addresses = [epp.Ip(addr=addr) for addr in addrs]
request = commands.CreateHost(name=host, addrs=addresses)
else:
# NOTE-848: ip is a specification within the nameserver
request = commands.CreateHost(name=host)
# NOTE-848: if you talk to registry you MUST do try/except
try:
logger.info("_create_host()-> sending req as %s" % request)
response = registry.send(request, cleaned=True)
@ -284,35 +279,41 @@ class Domain(TimeStampedModel, DomainHelper):
return e.code
def _convert_list_to_dict(self, listToConvert: list[tuple[str]]):
newDict={}
newDict = {}
# TODO-848: If duplicated nameserver names, throw error
for tup in listToConvert:
if len(tup) == 1:
newDict[tup[0]] = None
else:
newDict[tup[0]] = tup[1]
return newDict
def isDotGov(self, nameserver):
return nameserver.find(".gov")!=-1
def checkHostIPCombo(self, nameserver:str, ip:list):
if ( self.isDotGov(nameserver) and (ip is None or
ip==[]) ):
raise ValueError("Nameserver %s needs to have an ip address", nameserver)
def isSubdomain(self, nameserver):
return nameserver.find(self.name) != -1
def checkHostIPCombo(self, nameserver: str, ip: list):
if self.isSubdomain(nameserver) and (ip is None or ip == []):
raise ValueError("Nameserver %s needs to have an ip address" % nameserver)
elif not self.isSubdomain(nameserver) and (ip is not None and ip != []):
raise ValueError(
"Nameserver %s cannot be linked "
"because %s is not a subdomain" % (nameserver, ip)
)
return None
def getNameserverChanges(self, hosts:list[tuple[str]]):
"""
def getNameserverChanges(self, hosts: list[tuple[str]]):
"""
calls self.nameserver, it should pull from cache but may result
in an epp call
returns tuple of four values as follows:
returns tuple of four values as follows:
deleted_values:
updated_values:
updated_values:
new_values: dict
oldNameservers:"""
oldNameservers=self.nameservers
oldNameservers = self.nameservers
previousHostDict = self._convert_list_to_dict(oldNameservers)
previousHostDict = self._convert_list_to_dict(oldNameservers)
newHostDict = self._convert_list_to_dict(hosts)
deleted_values = []
@ -320,44 +321,39 @@ class Domain(TimeStampedModel, DomainHelper):
new_values = []
for prevHost in previousHostDict:
addrs=previousHostDict[prevHost]
addrs = previousHostDict[prevHost]
# get deleted values-which are values in previous nameserver list
# but are not in the list of new host values
if prevHost not in newHostDict:
deleted_values.append((prevHost,addrs))
deleted_values.append((prevHost, addrs))
# if the host exists in both, check if the addresses changed
else:
#TODO - host is being updated when previous was None and new is an empty list
# TODO - host is being updated when previous was None and new is an empty list
# add check here
if (newHostDict[prevHost] != addrs
and newHostDict[prevHost] is not None):
# could raise error here if new value is empty and is a dotgov
if newHostDict[prevHost] is not None and set(
newHostDict[prevHost]
) != set(addrs):
self.checkHostIPCombo(nameserver=prevHost, ip=newHostDict[prevHost])
updated_values.append((prevHost,newHostDict[prevHost]))
updated_values.append((prevHost, newHostDict[prevHost]))
new_values=set(newHostDict)-set(previousHostDict) #returns actually a set
new_values = {
key: newHostDict.get(key)
for key in newHostDict
if key not in previousHostDict
}
final_new_values = dict.fromkeys(new_values, None)
# loop in final new values to check for .gov and missing addresses
for nameserver, ip in final_new_values.items():
# check the new values for missing IPs
# raise error if missing
self.checkHostIPCombo(nameserver=nameserver,ip=ip)
return (deleted_values,updated_values,final_new_values, previousHostDict)
for nameserver, ip in new_values.items():
self.checkHostIPCombo(nameserver=nameserver, ip=ip)
return (deleted_values, updated_values, new_values, previousHostDict)
@nameservers.setter # type: ignore
def nameservers(self, hosts: list[tuple[str]]):
"""host should be a tuple of type str, str,... where the elements are
Fully qualified host name, addresses associated with the host
example: [(ns1.okay.gov, 127.0.0.1, others ips)]"""
# TODO-848: ip version checking may need to be added in a different ticket
# We currently don't have IP address functionality
# We can have multiple IP addresses
# If you have a dotgov, then you HAVE to have at least 1 IP address (can have multiple)
# Nameservers already have IP addresses, these IP addresses are additionals
# TODO-848: ip version checking may need to be added in a different ticket
if len(hosts) > 13:
raise ValueError(
@ -366,9 +362,14 @@ class Domain(TimeStampedModel, DomainHelper):
logger.info("Setting nameservers")
logger.info(hosts)
#get the changes made by user and old nameserver values
deleted_values, updated_values, new_values, oldNameservers=self.getNameserverChanges(hosts=hosts)
successDeletedCount = 0
# get the changes made by user and old nameserver values
(
deleted_values,
updated_values,
new_values,
oldNameservers,
) = self.getNameserverChanges(hosts=hosts)
successDeletedCount = 0
successCreatedCount = 0
print("deleted_values")
@ -380,29 +381,31 @@ class Domain(TimeStampedModel, DomainHelper):
print("oldNameservers")
print(oldNameservers)
for hostTuple in deleted_values:
print("hostTuple in deleted_values")
print(hostTuple)
print(deleted_values)
deleted_response_code = self._delete_host(hostTuple[0])
if deleted_response_code == ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY:
successDeletedCount += 1
successDeletedCount += 1
for hostTuple in updated_values:
updated_response_code = self._update_host(hostTuple[0], hostTuple[1], oldNameservers.get(hostTuple[0]))
if updated_response_code not in [ ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY, ErrorCode.OBJECT_EXISTS]:
logger.warning("Could not update host %s. Error code was: %s " % (hostTuple[0], updated_response_code))
updated_response_code = self._update_host(
hostTuple[0], hostTuple[1], oldNameservers.get(hostTuple[0])
)
if updated_response_code not in [
ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY,
ErrorCode.OBJECT_EXISTS,
]:
logger.warning(
"Could not update host %s. Error code was: %s "
% (hostTuple[0], updated_response_code)
)
for key, value in new_values.items():
print("HELLO THERE KEY, VALUE PAIR")
print(key)
print(value)
createdCode = self._create_host(host=key, addrs=value) # creates in registry
# TODO-848: Double check if _create_host should handle duplicates + update domain obj?
# NOTE-848: if createdCode == ErrorCode.OBJECT_EXISTS: --> self.nameservers
# NOTE-848: Host can be used by multiple domains
if createdCode == ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY or createdCode == ErrorCode.OBJECT_EXISTS:
createdCode = self._create_host(
host=key, addrs=value
) # creates in registry
if (
createdCode == ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY
or createdCode == ErrorCode.OBJECT_EXISTS
):
request = commands.UpdateDomain(
name=self.name, add=[epp.HostObjSet([key])]
)
@ -415,9 +418,10 @@ class Domain(TimeStampedModel, DomainHelper):
% (e.code, e)
)
print("")
successTotalNameservers = len(oldNameservers) - successDeletedCount+ successCreatedCount
successTotalNameservers = (
len(oldNameservers) - successDeletedCount + successCreatedCount
)
print("len(oldNameservers) IS ")
print(len(oldNameservers))
print("successDeletedCount IS ")
@ -425,9 +429,6 @@ class Domain(TimeStampedModel, DomainHelper):
print("successCreatedCount IS ")
print(successCreatedCount)
print("SUCCESSTOTALNAMESERVERS IS ")
print(successTotalNameservers)
if successTotalNameservers < 2:
@ -438,17 +439,19 @@ class Domain(TimeStampedModel, DomainHelper):
except Exception as err:
logger.info(
"nameserver setter checked for dns_needed state "
"and it did not succeed. Error: %s" % err
)
"and it did not succeed. Warning: %s" % err
)
elif successTotalNameservers >= 2 and successTotalNameservers <= 13:
try:
print("READY/SAVE: We are in happy path where btwen 2 and 13 inclusive ns")
print(
"READY/SAVE: We are in happy path where btwen 2 and 13 inclusive ns"
)
self.ready()
self.save()
except Exception as err:
logger.info(
"nameserver setter checked for create state "
"and it did not succeed. Error: %s" % err
"and it did not succeed. Warning: %s" % err
)
# TODO-848: Handle removed nameservers here, will need to change the state then go back to DNS_NEEDED
@ -838,7 +841,7 @@ class Domain(TimeStampedModel, DomainHelper):
req = commands.InfoDomain(name=self.name)
domainInfo = registry.send(req, cleaned=True).res_data[0]
exitEarly = True
return domainInfo
return domainInfo
except RegistryError as e:
count += 1
@ -931,17 +934,17 @@ class Domain(TimeStampedModel, DomainHelper):
# when EPP calling is made more efficient
# this should be added back in
# The goal is to double check that
# The goal is to double check that
# the nameservers we set are in fact
# on the registry
# """
# self._invalidate_cache()
# nameserverList = self.nameservers
# return len(nameserverList) < 2
# def dns_not_needed(self):
# return not self.is_dns_needed()
@transition(
field="state",
source=[State.DNS_NEEDED],
@ -964,10 +967,10 @@ class Domain(TimeStampedModel, DomainHelper):
)
def dns_needed(self):
"""Transition to the DNS_NEEDED state
domain should NOT have nameservers but
domain should NOT have nameservers but
SHOULD have all contacts
Going to check nameservers and will
result in an EPP call
Going to check nameservers and will
result in an EPP call
"""
logger.info("Changing to DNS_NEEDED state")
logger.info("able to transition to DNS_NEEDED state")
@ -1087,22 +1090,33 @@ class Domain(TimeStampedModel, DomainHelper):
edited_ip_list = []
if ip_list is None:
return []
for ip_addr in ip_list:
if self.is_ipv6():
if self.is_ipv6(ip_addr):
edited_ip_list.append(epp.Ip(addr=ip_addr, ip="v6"))
else: # default ip addr is v4
else: # default ip addr is v4
edited_ip_list.append(epp.Ip(addr=ip_addr))
return edited_ip_list
def _update_host(self, nameserver: str, ip_list: list[str], old_ip_list: list[str]):
try:
if ip_list is None or len(ip_list) == 0 and isinstance(old_ip_list,list) and len(old_ip_list)!=0 :
if (
ip_list is None
or len(ip_list) == 0
and isinstance(old_ip_list, list)
and len(old_ip_list) != 0
):
return ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY
request = commands.UpdateHost(name=nameserver, add=self._convert_ips(ip_list), rem=self._convert_ips(old_ip_list))
added_ip_list = set(ip_list) - set(old_ip_list)
removed_ip_list = set(old_ip_list) - set(ip_list)
request = commands.UpdateHost(
name=nameserver,
add=self._convert_ips(list(added_ip_list)),
rem=self._convert_ips(list(removed_ip_list)),
)
response = registry.send(request, cleaned=True)
logger.info("_update_host()-> sending req as %s" % request)
return response.code
@ -1113,23 +1127,30 @@ class Domain(TimeStampedModel, DomainHelper):
def _delete_host(self, nameserver: str):
try:
updateReq = commands.UpdateDomain(
name=self.name, rem=[epp.HostObjSet([nameserver])]
)
response=registry.send(updateReq, cleaned=True)
name=self.name, rem=[epp.HostObjSet([nameserver])]
)
response = registry.send(updateReq, cleaned=True)
logger.info("_delete_host()-> sending update domain req as %s" % updateReq)
deleteHostReq = commands.DeleteHost(name=nameserver)
response = registry.send(deleteHostReq, cleaned=True)
logger.info("_delete_host()-> sending delete host req as %s" % deleteHostReq)
logger.info(
"_delete_host()-> sending delete host req as %s" % deleteHostReq
)
return response.code
except RegistryError as e:
if e.code==ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION:
logger.info("Did not remove host %s because it is in use on another domain." % nameserver)
if e.code == ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION:
logger.info(
"Did not remove host %s because it is in use on another domain."
% nameserver
)
else:
logger.error("Error _delete_host, code was %s error was %s" % (e.code, e))
logger.error(
"Error _delete_host, code was %s error was %s" % (e.code, e)
)
return e.code
def _fetch_cache(self, fetch_hosts=False, fetch_contacts=False):
"""Contact registry for info about a domain."""
try:

View file

@ -562,7 +562,7 @@ class MockEppLib(TestCase):
self.contacts = contacts
self.hosts = hosts
self.statuses = statuses
self.avail = avail #use for CheckDomain
self.avail = avail # use for CheckDomain
self.addrs = addrs
mockDataInfoDomain = fakedEppObject(
@ -581,36 +581,52 @@ class MockEppLib(TestCase):
contacts=[],
hosts=["fake.host.com"],
)
infoDomainThreeHosts =fakedEppObject(
infoDomainThreeHosts = fakedEppObject(
"my-nameserver.gov",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35),
contacts=[],
hosts=["ns1.my-nameserver-1.com","ns1.my-nameserver-2.com","ns1.cats-are-superior3.com"],
hosts=[
"ns1.my-nameserver-1.com",
"ns1.my-nameserver-2.com",
"ns1.cats-are-superior3.com",
],
)
infoDomainNoHost =fakedEppObject(
infoDomainNoHost = fakedEppObject(
"my-nameserver.gov",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35),
contacts=[],
hosts=[],
)
infoDomainTwoHosts =fakedEppObject(
infoDomainTwoHosts = fakedEppObject(
"my-nameserver.gov",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35),
contacts=[],
hosts=["ns1.my-nameserver-1.com","ns1.my-nameserver-2.com"],
hosts=["ns1.my-nameserver-1.com", "ns1.my-nameserver-2.com"],
)
mockDataInfoContact = fakedEppObject(
"anotherPw", cr_date=datetime.datetime(2023, 7, 25, 19, 45, 35)
)
mockDataInfoHosts = fakedEppObject(
"lastPw", cr_date=datetime.datetime(2023, 8, 25, 19, 45, 35), addrs=["1.2.3", "2.3.4"]
"lastPw",
cr_date=datetime.datetime(2023, 8, 25, 19, 45, 35),
addrs=["1.2.3", "2.3.4"],
)
mockDataHostChange =fakedEppObject(
mockDataHostChange = fakedEppObject(
"lastPw", cr_date=datetime.datetime(2023, 8, 25, 19, 45, 35)
)
extendedValues=False
infoDomainHasIP = fakedEppObject(
"nameserverwithip.gov",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35),
contacts=[],
hosts=[
"ns1.nameserverwithip.gov",
"ns2.nameserverwithip.gov",
"ns3.nameserverwithip.gov",
],
)
extendedValues = False
def mockSend(self, _request, cleaned):
"""Mocks the registry.send function used inside of domain.py
@ -623,10 +639,14 @@ class MockEppLib(TestCase):
elif getattr(_request, "name", None) == "my-nameserver.gov":
if self.extendedValues:
return MagicMock(res_data=[self.infoDomainThreeHosts])
elif self.mockedSendFunction.call_count==5: ## remove this breaks anything?
elif (
self.mockedSendFunction.call_count == 5
): ## remove this breaks anything?
return MagicMock(res_data=[self.infoDomainTwoHosts])
else:
return MagicMock(res_data=[self.infoDomainNoHost])
elif getattr(_request, "name", None) == "nameserverwithip.gov":
return MagicMock(res_data=[self.infoDomainHasIP])
return MagicMock(res_data=[self.mockDataInfoDomain])
elif isinstance(_request, commands.InfoContact):
return MagicMock(res_data=[self.mockDataInfoContact])
@ -638,12 +658,21 @@ class MockEppLib(TestCase):
# use this for when a contact is being updated
# sets the second send() to fail
raise RegistryError(code=ErrorCode.OBJECT_EXISTS)
elif (isinstance(_request, commands.CreateHost)):
return MagicMock(res_data=[self.mockDataHostChange], code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY)
elif (isinstance(_request, commands.UpdateHost)):
return MagicMock(res_data=[self.mockDataHostChange], code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY)
elif (isinstance(_request, commands.DeleteHost)):
return MagicMock(res_data=[self.mockDataHostChange], code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY)
elif isinstance(_request, commands.CreateHost):
return MagicMock(
res_data=[self.mockDataHostChange],
code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY,
)
elif isinstance(_request, commands.UpdateHost):
return MagicMock(
res_data=[self.mockDataHostChange],
code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY,
)
elif isinstance(_request, commands.DeleteHost):
return MagicMock(
res_data=[self.mockDataHostChange],
code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY,
)
return MagicMock(res_data=[self.mockDataInfoHosts])
def setUp(self):

View file

@ -537,27 +537,39 @@ class TestRegistrantNameservers(MockEppLib):
self.nameserver2 = "ns1.my-nameserver-2.com"
self.nameserver3 = "ns1.cats-are-superior3.com"
self.domain, _ = Domain.objects.get_or_create(name="my-nameserver.gov", state=Domain.State.DNS_NEEDED)
self.domain, _ = Domain.objects.get_or_create(
name="my-nameserver.gov", state=Domain.State.DNS_NEEDED
)
def test_get_nameserver_changes(self):
self.domain._cache["hosts"]=[{
"name": "ns1.example.com",
"addrs": None
},
{"name": "ns2.example.com",
"addrs": ["1.2.3"]
},
{"name": "ns3.example.com",
"addrs": ["1.2.3"]
}
self.domain._cache["hosts"] = [
{"name": "ns1.example.com", "addrs": None},
{"name": "ns2.example.com", "addrs": ["1.2.3"]},
{"name": "ns3.my-nameserver.gov", "addrs": ["1.2.3"]},
]
newChanges=[("ns1.example.com",),("ns3.example.com",["1.2.4"]),("ns4.example.com",)]
deleted_values,updated_values,new_values, oldNameservers=self.domain.getNameserverChanges(newChanges)
newChanges = [
("ns1.example.com",),
("ns3.my-nameserver.gov", ["1.2.4"]),
("ns4.example.com",),
]
(
deleted_values,
updated_values,
new_values,
oldNameservers,
) = self.domain.getNameserverChanges(newChanges)
print(oldNameservers)
self.assertEqual(deleted_values, [('ns2.example.com', ['1.2.3'])])
self.assertEqual(updated_values, [('ns3.example.com', ['1.2.4'])])
self.assertEqual(new_values, {'ns4.example.com':None})
self.assertEqual(oldNameservers, {'ns1.example.com': None, 'ns2.example.com': ['1.2.3'], 'ns3.example.com': ['1.2.3']})
self.assertEqual(deleted_values, [("ns2.example.com", ["1.2.3"])])
self.assertEqual(updated_values, [("ns3.my-nameserver.gov", ["1.2.4"])])
self.assertEqual(new_values, {"ns4.example.com": None})
self.assertEqual(
oldNameservers,
{
"ns1.example.com": None,
"ns2.example.com": ["1.2.3"],
"ns3.my-nameserver.gov": ["1.2.3"],
},
)
def test_user_adds_one_nameserver(self):
"""
@ -571,11 +583,13 @@ class TestRegistrantNameservers(MockEppLib):
# set 1 nameserver
nameserver = "ns1.my-nameserver.com"
self.domain.nameservers = [(nameserver,)]
self.domain.nameservers = [(nameserver,)]
# when you create a host, you also have to update at same time
created_host = commands.CreateHost(nameserver)
update_domain_with_created = commands.UpdateDomain(name=self.domain.name, add=[common.HostObjSet([created_host.name])])
update_domain_with_created = commands.UpdateDomain(
name=self.domain.name, add=[common.HostObjSet([created_host.name])]
)
# checking if commands were sent (commands have to be sent in order)
expectedCalls = [
@ -600,16 +614,20 @@ class TestRegistrantNameservers(MockEppLib):
# set 2 nameservers
print("DOCKER DIDNT SUCK THIS TIME")
self.domain.nameservers = [(self.nameserver1,), (self.nameserver2,)]
self.domain.nameservers = [(self.nameserver1,), (self.nameserver2,)]
# when you create a host, you also have to update at same time
created_host1 = commands.CreateHost(self.nameserver1)
update_domain_with_created1 = commands.UpdateDomain(name=self.domain.name, add=[common.HostObjSet([created_host1.name])])
update_domain_with_created1 = commands.UpdateDomain(
name=self.domain.name, add=[common.HostObjSet([created_host1.name])]
)
created_host2 = commands.CreateHost(self.nameserver2)
update_domain_with_created2 = commands.UpdateDomain(name=self.domain.name, add=[common.HostObjSet([created_host2.name])])
update_domain_with_created2 = commands.UpdateDomain(
name=self.domain.name, add=[common.HostObjSet([created_host2.name])]
)
infoDomain = commands.InfoDomain(name='my-nameserver.gov', auth_info=None)
infoDomain = commands.InfoDomain(name="my-nameserver.gov", auth_info=None)
# checking if commands were sent (commands have to be sent in order)
expectedCalls = [
call(infoDomain, cleaned=True),
@ -619,9 +637,6 @@ class TestRegistrantNameservers(MockEppLib):
call(update_domain_with_created2, cleaned=True),
]
print("self.mockedSendFunction.call_args_list is ")
print(self.mockedSendFunction.call_args_list)
self.mockedSendFunction.assert_has_calls(expectedCalls, any_order=True)
self.assertEqual(5, self.mockedSendFunction.call_count)
# check that status is READY
@ -650,11 +665,24 @@ class TestRegistrantNameservers(MockEppLib):
nameserver12 = "ns1.cats-are-superior12.com"
nameserver13 = "ns1.cats-are-superior13.com"
nameserver14 = "ns1.cats-are-superior14.com"
def _get_14_nameservers():
self.domain.nameservers = [(nameserver1,), (nameserver2,), (nameserver3,), (nameserver4,),
(nameserver5,), (nameserver6,), (nameserver7,), (nameserver8,), (nameserver9), (nameserver10,),
(nameserver11,), (nameserver12,), (nameserver13,), (nameserver14,)]
self.domain.nameservers = [
(nameserver1,),
(nameserver2,),
(nameserver3,),
(nameserver4,),
(nameserver5,),
(nameserver6,),
(nameserver7,),
(nameserver8,),
(nameserver9),
(nameserver10,),
(nameserver11,),
(nameserver12,),
(nameserver13,),
(nameserver14,),
]
self.assertRaises(ValueError, _get_14_nameservers)
self.assertEqual(self.mockedSendFunction.call_count, 0)
@ -670,25 +698,37 @@ class TestRegistrantNameservers(MockEppLib):
"""
# Mock is set to return 3 nameservers on infodomain
self.extendedValues=True
self.extendedValues = True
self.domain.nameservers = [(self.nameserver1,), (self.nameserver2,)]
expectedCalls=[
expectedCalls = [
# calls info domain, and info on all hosts
# to get past values
# then removes the single host and updates domain
call(commands.InfoDomain(name='my-nameserver.gov', auth_info=None), cleaned=True),
call(commands.InfoHost(name='ns1.my-nameserver-1.com'), cleaned=True),
call(commands.InfoHost(name='ns1.my-nameserver-2.com'), cleaned=True),
call(commands.InfoHost(name='ns1.cats-are-superior3.com'), cleaned=True),
call(commands.UpdateDomain(name='my-nameserver.gov', add=[], rem=[common.HostObjSet(hosts=['ns1.cats-are-superior3.com'])], nsset=None, keyset=None, registrant=None, auth_info=None), cleaned=True),
call(commands.DeleteHost(name='ns1.cats-are-superior3.com'), cleaned=True)]
call(
commands.InfoDomain(name="my-nameserver.gov", auth_info=None),
cleaned=True,
),
call(commands.InfoHost(name="ns1.my-nameserver-1.com"), cleaned=True),
call(commands.InfoHost(name="ns1.my-nameserver-2.com"), cleaned=True),
call(commands.InfoHost(name="ns1.cats-are-superior3.com"), cleaned=True),
call(
commands.UpdateDomain(
name="my-nameserver.gov",
add=[],
rem=[common.HostObjSet(hosts=["ns1.cats-are-superior3.com"])],
nsset=None,
keyset=None,
registrant=None,
auth_info=None,
),
cleaned=True,
),
call(commands.DeleteHost(name="ns1.cats-are-superior3.com"), cleaned=True),
]
print("self.mockedSendFunction.call_args_list is ")
print(self.mockedSendFunction.call_args_list)
self.mockedSendFunction.assert_has_calls(expectedCalls, any_order=True)
self.assertTrue(self.domain.is_active())
def test_user_removes_too_many_nameservers(self):
"""
Scenario: Registrant removes some nameservers, bringing the total to less than 2
@ -697,27 +737,51 @@ class TestRegistrantNameservers(MockEppLib):
Then `commands.UpdateDomain` and `commands.DeleteHost` is sent
to the registry
And `domain.is_active` returns False
"""
self.extendedValues=True
self.extendedValues = True
print("domain state")
print(self.domain.state)
self.domain.ready()
print("Domain state is now")
print(self.domain.state)
self.domain.nameservers = [(self.nameserver1,)]
print("self.mockedSendFunction.call_args_list is ")
print(self.mockedSendFunction.call_args_list)
expectedCalls=[call(commands.InfoDomain(name='my-nameserver.gov', auth_info=None), cleaned=True),
call(commands.InfoHost(name='ns1.my-nameserver-1.com'), cleaned=True),
call(commands.InfoHost(name='ns1.my-nameserver-2.com'), cleaned=True),
call(commands.InfoHost(name='ns1.cats-are-superior3.com'), cleaned=True),
call(commands.UpdateDomain(name='my-nameserver.gov', add=[], rem=[common.HostObjSet(hosts=['ns1.my-nameserver-2.com'])], nsset=None, keyset=None, registrant=None, auth_info=None), cleaned=True),
call(commands.DeleteHost(name='ns1.my-nameserver-2.com'), cleaned=True),
call(commands.UpdateDomain(name='my-nameserver.gov', add=[], rem=[common.HostObjSet(hosts=['ns1.cats-are-superior3.com'])], nsset=None, keyset=None, registrant=None, auth_info=None), cleaned=True),
call(commands.DeleteHost(name='ns1.cats-are-superior3.com'), cleaned=True)]
self.domain.nameservers = [(self.nameserver1,)]
expectedCalls = [
call(
commands.InfoDomain(name="my-nameserver.gov", auth_info=None),
cleaned=True,
),
call(commands.InfoHost(name="ns1.my-nameserver-1.com"), cleaned=True),
call(commands.InfoHost(name="ns1.my-nameserver-2.com"), cleaned=True),
call(commands.InfoHost(name="ns1.cats-are-superior3.com"), cleaned=True),
call(
commands.UpdateDomain(
name="my-nameserver.gov",
add=[],
rem=[common.HostObjSet(hosts=["ns1.my-nameserver-2.com"])],
nsset=None,
keyset=None,
registrant=None,
auth_info=None,
),
cleaned=True,
),
call(commands.DeleteHost(name="ns1.my-nameserver-2.com"), cleaned=True),
call(
commands.UpdateDomain(
name="my-nameserver.gov",
add=[],
rem=[common.HostObjSet(hosts=["ns1.cats-are-superior3.com"])],
nsset=None,
keyset=None,
registrant=None,
auth_info=None,
),
cleaned=True,
),
call(commands.DeleteHost(name="ns1.cats-are-superior3.com"), cleaned=True),
]
self.mockedSendFunction.assert_has_calls(expectedCalls, any_order=True)
self.assertFalse(self.domain.is_active())
@ -731,27 +795,72 @@ class TestRegistrantNameservers(MockEppLib):
And `commands.UpdateDomain` is sent to add #4 and #5 plus remove #2 and #3
And `commands.DeleteHost` is sent to delete #2 and #3
"""
self.extendedValues=True
self.extendedValues = True
self.domain.ready()
self.domain.nameservers=[(self.nameserver1,), ("ns1.cats-are-superior1.com",), ("ns1.cats-are-superior2.com",)]
print("self.mockedSendFunction.call_args_list is ")
print(self.mockedSendFunction.call_args_list)
expectedCalls=[call(commands.InfoDomain(name='my-nameserver.gov', auth_info=None), cleaned=True),
call(commands.InfoHost(name='ns1.my-nameserver-1.com'), cleaned=True),
call(commands.InfoHost(name='ns1.my-nameserver-2.com'), cleaned=True),
call(commands.InfoHost(name='ns1.cats-are-superior3.com'), cleaned=True),
call(commands.UpdateDomain(name='my-nameserver.gov', add=[], rem=[common.HostObjSet(hosts=['ns1.my-nameserver-2.com'])], nsset=None, keyset=None, registrant=None, auth_info=None), cleaned=True),
call(commands.DeleteHost(name='ns1.my-nameserver-2.com'), cleaned=True),
call(commands.CreateHost(name='ns1.cats-are-superior1.com', addrs=[]), cleaned=True),
call(commands.UpdateDomain(name='my-nameserver.gov', add=[common.HostObjSet(hosts=['ns1.cats-are-superior1.com'])], rem=[], nsset=None, keyset=None, registrant=None, auth_info=None), cleaned=True),
call(commands.CreateHost(name='ns1.cats-are-superior2.com', addrs=[]), cleaned=True),
call(commands.UpdateDomain(name='my-nameserver.gov', add=[common.HostObjSet(hosts=['ns1.cats-are-superior2.com'])], rem=[], nsset=None, keyset=None, registrant=None, auth_info=None), cleaned=True)
]
self.domain.nameservers = [
(self.nameserver1,),
("ns1.cats-are-superior1.com",),
("ns1.cats-are-superior2.com",),
]
expectedCalls = [
call(
commands.InfoDomain(name="my-nameserver.gov", auth_info=None),
cleaned=True,
),
call(commands.InfoHost(name="ns1.my-nameserver-1.com"), cleaned=True),
call(commands.InfoHost(name="ns1.my-nameserver-2.com"), cleaned=True),
call(commands.InfoHost(name="ns1.cats-are-superior3.com"), cleaned=True),
call(
commands.UpdateDomain(
name="my-nameserver.gov",
add=[],
rem=[common.HostObjSet(hosts=["ns1.my-nameserver-2.com"])],
nsset=None,
keyset=None,
registrant=None,
auth_info=None,
),
cleaned=True,
),
call(commands.DeleteHost(name="ns1.my-nameserver-2.com"), cleaned=True),
call(
commands.CreateHost(name="ns1.cats-are-superior1.com", addrs=[]),
cleaned=True,
),
call(
commands.UpdateDomain(
name="my-nameserver.gov",
add=[common.HostObjSet(hosts=["ns1.cats-are-superior1.com"])],
rem=[],
nsset=None,
keyset=None,
registrant=None,
auth_info=None,
),
cleaned=True,
),
call(
commands.CreateHost(name="ns1.cats-are-superior2.com", addrs=[]),
cleaned=True,
),
call(
commands.UpdateDomain(
name="my-nameserver.gov",
add=[common.HostObjSet(hosts=["ns1.cats-are-superior2.com"])],
rem=[],
nsset=None,
keyset=None,
registrant=None,
auth_info=None,
),
cleaned=True,
),
]
self.mockedSendFunction.assert_has_calls(expectedCalls, any_order=True)
self.assertTrue(self.domain.is_active())
def test_user_cannot_add_subordinate_without_ip(self):
"""
Scenario: Registrant adds a nameserver which is a subdomain of their .gov
@ -760,11 +869,12 @@ class TestRegistrantNameservers(MockEppLib):
with a subdomain of the domain and no IP addresses
Then Domain raises a user-friendly error
"""
#add a nameserver with a .gov and no ip
##assertRaises error
raise
@skip("not implemented yet")
dotgovnameserver = "my-nameserver.gov"
with self.assertRaises(ValueError):
self.domain.nameservers = [(dotgovnameserver,)]
def test_user_updates_ips(self):
"""
Scenario: Registrant changes IP addresses for a nameserver
@ -774,9 +884,49 @@ class TestRegistrantNameservers(MockEppLib):
with a different IP address(es)
Then `commands.UpdateHost` is sent to the registry
"""
raise
domain, _ = Domain.objects.get_or_create(
name="nameserverwithip.gov", state=Domain.State.READY
)
domain.nameservers = [
("ns1.nameserverwithip.gov", ["2.3.4", "1.2.3"]),
("ns2.nameserverwithip.gov", ["1.2.3", "2.3.4", "3.4.5"]),
("ns3.nameserverwithip.gov", ["2.3.4"]),
]
# print("self.mockedSendFunction.call_args_list is ")
# print(self.mockedSendFunction.call_args_list)
expectedCalls = [
call(
commands.InfoDomain(name="nameserverwithip.gov", auth_info=None),
cleaned=True,
),
call(commands.InfoHost(name="ns1.nameserverwithip.gov"), cleaned=True),
call(commands.InfoHost(name="ns2.nameserverwithip.gov"), cleaned=True),
call(commands.InfoHost(name="ns3.nameserverwithip.gov"), cleaned=True),
call(
commands.UpdateHost(
name="ns2.nameserverwithip.gov",
add=[common.Ip(addr="3.4.5", ip="v6")],
rem=[],
chg=None,
),
cleaned=True,
),
call(
commands.UpdateHost(
name="ns3.nameserverwithip.gov",
add=[],
rem=[common.Ip(addr="1.2.3", ip="v6")],
chg=None,
),
cleaned=True,
),
]
self.mockedSendFunction.assert_has_calls(expectedCalls, any_order=True)
self.assertTrue(domain.is_active())
@skip("not implemented yet")
def test_user_cannot_add_non_subordinate_with_ip(self):
"""
Scenario: Registrant adds a nameserver which is NOT a subdomain of their .gov
@ -785,7 +935,10 @@ class TestRegistrantNameservers(MockEppLib):
which is not a subdomain of the domain and has IP addresses
Then Domain raises a user-friendly error
"""
raise
dotgovnameserver = "mynameserverdotgov.gov"
with self.assertRaises(ValueError):
self.domain.nameservers = [(dotgovnameserver, ["1.2.3"])]
@skip("not implemented yet")
def test_nameservers_are_idempotent(self):
@ -810,9 +963,10 @@ class TestRegistrantNameservers(MockEppLib):
raise
def tearDown(self):
self.extendedValues=False
self.extendedValues = False
return super().tearDown()
class TestRegistrantDNSSEC(TestCase):
"""Rule: Registrants may modify their secure DNS data"""