mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-12 12:39:43 +02:00
Rework delete from epp
This commit is contained in:
parent
7cf8b8a82e
commit
6891f5c8df
3 changed files with 70 additions and 40 deletions
|
@ -744,7 +744,12 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
|
|
||||||
successTotalNameservers = len(oldNameservers) - deleteCount + addToDomainCount
|
successTotalNameservers = len(oldNameservers) - deleteCount + addToDomainCount
|
||||||
|
|
||||||
self._delete_hosts_if_not_used(hostsToDelete=deleted_values)
|
try:
|
||||||
|
self._delete_hosts_if_not_used(hostsToDelete=deleted_values)
|
||||||
|
except:
|
||||||
|
# in this case we don't care if there's an error, and it will be logged in the function.
|
||||||
|
pass
|
||||||
|
|
||||||
if successTotalNameservers < 2:
|
if successTotalNameservers < 2:
|
||||||
try:
|
try:
|
||||||
self.dns_needed()
|
self.dns_needed()
|
||||||
|
@ -1032,19 +1037,28 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
RegistryErrors will be logged and raised. Additional
|
RegistryErrors will be logged and raised. Additional
|
||||||
error handling should be provided by the caller.
|
error handling should be provided by the caller.
|
||||||
"""
|
"""
|
||||||
|
logger.info("Deleting contacts for %s", self.name)
|
||||||
contacts = self._cache.get("contacts")
|
contacts = self._cache.get("contacts")
|
||||||
for contact in contacts:
|
logger.debug("Contacts to delete for %s inside _delete_contacts -> %s", self.name, contacts)
|
||||||
self._delete_contact(contact)
|
if contacts:
|
||||||
|
for contact in contacts:
|
||||||
|
self._delete_contact(contact)
|
||||||
|
|
||||||
|
|
||||||
def _delete_subdomains(self):
|
def _delete_subdomains(self):
|
||||||
"""Subdomains of this domain should be deleted from the registry.
|
"""Subdomains of this domain should be deleted from the registry.
|
||||||
Subdomains which are used by other domains (eg as a hostname) will
|
Subdomains which are used by other domains (eg as a hostname) will
|
||||||
not be deleted.
|
not be deleted.
|
||||||
|
|
||||||
Supresses registry error, as registry can disallow delete for various reasons
|
raises:
|
||||||
|
RegistryError: if any subdomain cannot be deleted
|
||||||
"""
|
"""
|
||||||
|
logger.info("Deleting nameservers for %s", self.name)
|
||||||
nameservers = [n[0] for n in self.nameservers]
|
nameservers = [n[0] for n in self.nameservers]
|
||||||
hostsToDelete = self.createDeleteHostList(nameservers)
|
logger.info("Nameservers found: %s", nameservers)
|
||||||
|
hostsToDelete, _ = self.createDeleteHostList(nameservers)
|
||||||
|
logger.debug("HostsToDelete from %s inside _delete_subdomains -> %s", self.name, hostsToDelete)
|
||||||
|
|
||||||
self._delete_hosts_if_not_used(hostsToDelete)
|
self._delete_hosts_if_not_used(hostsToDelete)
|
||||||
|
|
||||||
def _delete_domain(self):
|
def _delete_domain(self):
|
||||||
|
@ -1665,7 +1679,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
def _delete_contact(self, contact: PublicContact):
|
def _delete_contact(self, contact: PublicContact):
|
||||||
"""Try to delete a contact. RegistryErrors will be logged.
|
"""Try to delete a contact from the registry.
|
||||||
|
|
||||||
raises:
|
raises:
|
||||||
RegistryError: if the registry is unable to delete the contact
|
RegistryError: if the registry is unable to delete the contact
|
||||||
|
@ -1790,7 +1804,6 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
"""delete the host object in registry,
|
"""delete the host object in registry,
|
||||||
will only delete the host object, if it's not being used by another domain
|
will only delete the host object, if it's not being used by another domain
|
||||||
Performs just the DeleteHost epp call
|
Performs just the DeleteHost epp call
|
||||||
Supresses regstry error, as registry can disallow delete for various reasons
|
|
||||||
Args:
|
Args:
|
||||||
hostsToDelete (list[str])- list of nameserver/host names to remove
|
hostsToDelete (list[str])- list of nameserver/host names to remove
|
||||||
Returns:
|
Returns:
|
||||||
|
@ -1808,6 +1821,8 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
logger.info("Did not remove host %s because it is in use on another domain." % nameserver)
|
logger.info("Did not remove host %s because it is in use on another domain." % nameserver)
|
||||||
else:
|
else:
|
||||||
logger.error("Error _delete_hosts_if_not_used, code was %s error was %s" % (e.code, e))
|
logger.error("Error _delete_hosts_if_not_used, code was %s error was %s" % (e.code, e))
|
||||||
|
|
||||||
|
raise e
|
||||||
|
|
||||||
def _fix_unknown_state(self, cleaned):
|
def _fix_unknown_state(self, cleaned):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1279,6 +1279,15 @@ class MockEppLib(TestCase):
|
||||||
hosts=["fake.host.com"],
|
hosts=["fake.host.com"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
infoDomainSharedHost = fakedEppObject(
|
||||||
|
"sharedHost.gov",
|
||||||
|
cr_date=make_aware(datetime(2023, 5, 25, 19, 45, 35)),
|
||||||
|
contacts=[],
|
||||||
|
hosts=[
|
||||||
|
"ns1.sharedhost.com",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
infoDomainThreeHosts = fakedEppObject(
|
infoDomainThreeHosts = fakedEppObject(
|
||||||
"my-nameserver.gov",
|
"my-nameserver.gov",
|
||||||
cr_date=make_aware(datetime(2023, 5, 25, 19, 45, 35)),
|
cr_date=make_aware(datetime(2023, 5, 25, 19, 45, 35)),
|
||||||
|
@ -1496,10 +1505,7 @@ class MockEppLib(TestCase):
|
||||||
case commands.UpdateHost:
|
case commands.UpdateHost:
|
||||||
return self.mockUpdateHostCommands(_request, cleaned)
|
return self.mockUpdateHostCommands(_request, cleaned)
|
||||||
case commands.DeleteHost:
|
case commands.DeleteHost:
|
||||||
return MagicMock(
|
return self.mockDeletHostCommands(_request, cleaned)
|
||||||
res_data=[self.mockDataHostChange],
|
|
||||||
code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY,
|
|
||||||
)
|
|
||||||
case commands.CheckDomain:
|
case commands.CheckDomain:
|
||||||
return self.mockCheckDomainCommand(_request, cleaned)
|
return self.mockCheckDomainCommand(_request, cleaned)
|
||||||
case commands.DeleteDomain:
|
case commands.DeleteDomain:
|
||||||
|
@ -1551,6 +1557,16 @@ class MockEppLib(TestCase):
|
||||||
res_data=[self.mockDataHostChange],
|
res_data=[self.mockDataHostChange],
|
||||||
code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY,
|
code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def mockDeletHostCommands(self, _request, cleaned):
|
||||||
|
hosts = getattr(_request, "name", None).hosts
|
||||||
|
for host in hosts:
|
||||||
|
if "sharedhost.com" in host:
|
||||||
|
raise RegistryError(code=ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION)
|
||||||
|
return MagicMock(
|
||||||
|
res_data=[self.mockDataHostChange],
|
||||||
|
code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY,
|
||||||
|
)
|
||||||
|
|
||||||
def mockUpdateDomainCommands(self, _request, cleaned):
|
def mockUpdateDomainCommands(self, _request, cleaned):
|
||||||
if getattr(_request, "name", None) == "dnssec-invalid.gov":
|
if getattr(_request, "name", None) == "dnssec-invalid.gov":
|
||||||
|
@ -1563,10 +1579,7 @@ class MockEppLib(TestCase):
|
||||||
|
|
||||||
def mockDeleteDomainCommands(self, _request, cleaned):
|
def mockDeleteDomainCommands(self, _request, cleaned):
|
||||||
if getattr(_request, "name", None) == "failDelete.gov":
|
if getattr(_request, "name", None) == "failDelete.gov":
|
||||||
name = getattr(_request, "name", None)
|
raise RegistryError(code=ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION)
|
||||||
fake_nameserver = "ns1.failDelete.gov"
|
|
||||||
if name in fake_nameserver:
|
|
||||||
raise RegistryError(code=ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def mockRenewDomainCommand(self, _request, cleaned):
|
def mockRenewDomainCommand(self, _request, cleaned):
|
||||||
|
@ -1636,6 +1649,7 @@ class MockEppLib(TestCase):
|
||||||
"subdomainwoip.gov": (self.mockDataInfoDomainSubdomainNoIP, None),
|
"subdomainwoip.gov": (self.mockDataInfoDomainSubdomainNoIP, None),
|
||||||
"ddomain3.gov": (self.InfoDomainWithContacts, None),
|
"ddomain3.gov": (self.InfoDomainWithContacts, None),
|
||||||
"igorville.gov": (self.InfoDomainWithContacts, None),
|
"igorville.gov": (self.InfoDomainWithContacts, None),
|
||||||
|
"sharingiscaring.gov": (self.infoDomainSharedHost, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Retrieve the corresponding values from the dictionary
|
# Retrieve the corresponding values from the dictionary
|
||||||
|
|
|
@ -2585,6 +2585,7 @@ class TestAnalystDelete(MockEppLib):
|
||||||
self.domain_on_hold, _ = Domain.objects.get_or_create(name="fake-on-hold.gov", state=Domain.State.ON_HOLD)
|
self.domain_on_hold, _ = Domain.objects.get_or_create(name="fake-on-hold.gov", state=Domain.State.ON_HOLD)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
Host.objects.all().delete()
|
||||||
Domain.objects.all().delete()
|
Domain.objects.all().delete()
|
||||||
super().tearDown()
|
super().tearDown()
|
||||||
|
|
||||||
|
@ -2597,39 +2598,39 @@ class TestAnalystDelete(MockEppLib):
|
||||||
|
|
||||||
The deleted date is set.
|
The deleted date is set.
|
||||||
"""
|
"""
|
||||||
with less_console_noise():
|
# with less_console_noise():
|
||||||
# Put the domain in client hold
|
# Put the domain in client hold
|
||||||
self.domain.place_client_hold()
|
self.domain.place_client_hold()
|
||||||
# Delete it...
|
# Delete it...
|
||||||
self.domain.deletedInEpp()
|
self.domain.deletedInEpp()
|
||||||
self.domain.save()
|
self.domain.save()
|
||||||
self.mockedSendFunction.assert_has_calls(
|
self.mockedSendFunction.assert_has_calls(
|
||||||
[
|
[
|
||||||
call(
|
call(
|
||||||
commands.DeleteDomain(name="fake.gov"),
|
commands.DeleteDomain(name="fake.gov"),
|
||||||
cleaned=True,
|
cleaned=True,
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
# Domain itself should not be deleted
|
# Domain itself should not be deleted
|
||||||
self.assertNotEqual(self.domain, None)
|
self.assertNotEqual(self.domain, None)
|
||||||
# Domain should have the right state
|
# Domain should have the right state
|
||||||
self.assertEqual(self.domain.state, Domain.State.DELETED)
|
self.assertEqual(self.domain.state, Domain.State.DELETED)
|
||||||
# Domain should have a deleted
|
# Domain should have a deleted
|
||||||
self.assertNotEqual(self.domain.deleted, None)
|
self.assertNotEqual(self.domain.deleted, None)
|
||||||
# Cache should be invalidated
|
# Cache should be invalidated
|
||||||
self.assertEqual(self.domain._cache, {})
|
self.assertEqual(self.domain._cache, {})
|
||||||
|
|
||||||
def test_deletion_is_unsuccessful(self):
|
def test_deletion_is_unsuccessful(self):
|
||||||
"""
|
"""
|
||||||
Scenario: Domain deletion is unsuccessful
|
Scenario: Domain deletion is unsuccessful
|
||||||
When a subdomain exists
|
When a subdomain exists that is in use by another domain
|
||||||
Then a client error is returned of code 2305
|
Then a client error is returned of code 2305
|
||||||
And `state` is not set to `DELETED`
|
And `state` is not set to `DELETED`
|
||||||
"""
|
"""
|
||||||
with less_console_noise():
|
with less_console_noise():
|
||||||
# Desired domain
|
# Desired domain
|
||||||
domain, _ = Domain.objects.get_or_create(name="failDelete.gov", state=Domain.State.ON_HOLD)
|
domain, _ = Domain.objects.get_or_create(name="sharingiscaring.gov", state=Domain.State.ON_HOLD)
|
||||||
# Put the domain in client hold
|
# Put the domain in client hold
|
||||||
domain.place_client_hold()
|
domain.place_client_hold()
|
||||||
# Delete it
|
# Delete it
|
||||||
|
@ -2640,7 +2641,7 @@ class TestAnalystDelete(MockEppLib):
|
||||||
self.mockedSendFunction.assert_has_calls(
|
self.mockedSendFunction.assert_has_calls(
|
||||||
[
|
[
|
||||||
call(
|
call(
|
||||||
commands.DeleteDomain(name="failDelete.gov"),
|
commands.DeleteHost(name=common.HostObjSet(hosts=['ns1.sharedhost.com'])),
|
||||||
cleaned=True,
|
cleaned=True,
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue