Delete hosts synchronously when using SQL (#1141)

Also put some common logic in helper funcions in ContactDeleteFlowTest
to reduce clutter.
This commit is contained in:
Lai Jiang 2021-05-10 10:22:01 -04:00 committed by GitHub
parent afbb36f68c
commit 6115c7eb21
10 changed files with 268 additions and 218 deletions

View file

@ -32,6 +32,7 @@ import google.registry.model.eppinput.ResourceCommand;
import google.registry.model.eppinput.ResourceCommand.SingleResourceCommand;
import google.registry.model.eppoutput.EppResponse;
import google.registry.model.eppoutput.Result;
import google.registry.model.host.HostHistory;
import google.registry.model.reporting.HistoryEntry;
import java.lang.annotation.Documented;
import java.util.Optional;
@ -233,11 +234,11 @@ public class FlowModule {
.setClientId(clientId);
Optional<MetadataExtension> metadataExtension =
eppInput.getSingleExtension(MetadataExtension.class);
if (metadataExtension.isPresent()) {
historyBuilder
.setReason(metadataExtension.get().getReason())
.setRequestedByRegistrar(metadataExtension.get().getRequestedByRegistrar());
}
metadataExtension.ifPresent(
extension ->
historyBuilder
.setReason(extension.getReason())
.setRequestedByRegistrar(extension.getRequestedByRegistrar()));
return historyBuilder;
}
@ -253,6 +254,11 @@ public class FlowModule {
return new DomainHistory.Builder().copyFrom(historyEntryBuilder);
}
@Provides
static HostHistory.Builder provideHostHistoryBuilder(HistoryEntry.Builder historyEntryBuilder) {
return new HostHistory.Builder().copyFrom(historyEntryBuilder);
}
/**
* Provides a partially filled in {@link EppResponse} builder.
*
@ -263,7 +269,7 @@ public class FlowModule {
static EppResponse.Builder provideEppResponseBuilder(Trid trid) {
return new EppResponse.Builder()
.setTrid(trid)
.setResultFromCode(Result.Code.SUCCESS); // Default to success.
.setResultFromCode(Result.Code.SUCCESS); // Default to success.
}
@Provides

View file

@ -20,12 +20,13 @@ import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
import static google.registry.flows.host.HostFlowUtils.validateHostName;
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.batch.AsyncTaskEnqueuer;
import google.registry.dns.DnsQueue;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.FlowModule.ClientId;
@ -39,8 +40,11 @@ import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppcommon.Trid;
import google.registry.model.eppoutput.EppResponse;
import google.registry.model.eppoutput.Result;
import google.registry.model.host.HostHistory;
import google.registry.model.host.HostResource;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.HistoryEntry.Type;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import javax.inject.Inject;
import org.joda.time.DateTime;
@ -71,12 +75,14 @@ public final class HostDeleteFlow implements TransactionalFlow {
StatusValue.PENDING_DELETE,
StatusValue.SERVER_DELETE_PROHIBITED);
private static final DnsQueue dnsQueue = DnsQueue.create();
@Inject ExtensionManager extensionManager;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject Trid trid;
@Inject @Superuser boolean isSuperuser;
@Inject HistoryEntry.Builder historyBuilder;
@Inject HostHistory.Builder historyBuilder;
@Inject AsyncTaskEnqueuer asyncTaskEnqueuer;
@Inject EppResponse.Builder responseBuilder;
@ -102,16 +108,31 @@ public final class HostDeleteFlow implements TransactionalFlow {
: existingHost;
verifyResourceOwnership(clientId, owningResource);
}
asyncTaskEnqueuer.enqueueAsyncDelete(
existingHost, tm().getTransactionTime(), clientId, trid, isSuperuser);
HostResource newHost =
existingHost.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build();
historyBuilder
.setType(HistoryEntry.Type.HOST_PENDING_DELETE)
.setModificationTime(now)
.setParent(Key.create(existingHost));
tm().insert(historyBuilder.build().toChildHistoryEntity());
HistoryEntry.Type historyEntryType;
Result.Code resultCode;
HostResource newHost;
if (tm().isOfy()) {
asyncTaskEnqueuer.enqueueAsyncDelete(
existingHost, tm().getTransactionTime(), clientId, trid, isSuperuser);
newHost = existingHost.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build();
historyEntryType = Type.HOST_PENDING_DELETE;
resultCode = SUCCESS_WITH_ACTION_PENDING;
} else {
newHost = existingHost.asBuilder().setStatusValues(null).setDeletionTime(now).build();
if (existingHost.isSubordinate()) {
dnsQueue.addHostRefreshTask(existingHost.getHostName());
tm().update(
tm().loadByKey(existingHost.getSuperordinateDomain())
.asBuilder()
.removeSubordinateHost(existingHost.getHostName())
.build());
}
historyEntryType = Type.HOST_DELETE;
resultCode = SUCCESS;
}
historyBuilder.setType(historyEntryType).setModificationTime(now).setHostBase(newHost);
tm().insert(historyBuilder.build());
tm().update(newHost);
return responseBuilder.setResultFromCode(SUCCESS_WITH_ACTION_PENDING).build();
return responseBuilder.setResultFromCode(resultCode).build();
}
}

View file

@ -65,22 +65,22 @@ class EppLifecycleContactTest extends EppTestCase {
.hasCommandName("ContactInfo")
.and()
.hasStatus(SUCCESS);
Result.Code resultCode;
Result.Code deleteResultCode;
if (tm().isOfy()) {
assertThatCommand("contact_delete_sh8013.xml")
.hasResponse("contact_delete_response_sh8013_pending.xml");
resultCode = SUCCESS_WITH_ACTION_PENDING;
deleteResultCode = SUCCESS_WITH_ACTION_PENDING;
} else {
assertThatCommand("contact_delete_sh8013.xml")
.hasResponse("contact_delete_response_sh8013.xml");
resultCode = SUCCESS;
deleteResultCode = SUCCESS;
}
assertThat(getRecordedEppMetric())
.hasClientId("NewRegistrar")
.and()
.hasCommandName("ContactDelete")
.and()
.hasStatus(resultCode);
.hasStatus(deleteResultCode);
assertThatLogoutSucceeds();
}

View file

@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.createTlds;
import static google.registry.testing.EppMetricSubject.assertThat;
@ -25,6 +26,7 @@ import static google.registry.testing.HostResourceSubject.assertAboutHosts;
import com.google.common.collect.ImmutableMap;
import google.registry.model.domain.DomainBase;
import google.registry.model.eppoutput.Result;
import google.registry.model.host.HostResource;
import google.registry.testing.AppEngineExtension;
import google.registry.testing.DualDatabaseTest;
@ -80,15 +82,24 @@ class EppLifecycleHostTest extends EppTestCase {
.hasCommandName("HostInfo")
.and()
.hasStatus(SUCCESS);
assertThatCommand("host_delete.xml", ImmutableMap.of("HOSTNAME", "ns1.example.tld"))
.atTime("2000-06-02T00:03:00Z")
.hasResponse("generic_success_action_pending_response.xml");
Result.Code deleteResultCode;
if (tm().isOfy()) {
assertThatCommand("host_delete.xml", ImmutableMap.of("HOSTNAME", "ns1.example.tld"))
.atTime("2000-06-02T00:03:00Z")
.hasResponse("generic_success_action_pending_response.xml");
deleteResultCode = SUCCESS_WITH_ACTION_PENDING;
} else {
assertThatCommand("host_delete.xml", ImmutableMap.of("HOSTNAME", "ns1.example.tld"))
.atTime("2000-06-02T00:03:00Z")
.hasResponse("generic_success_response.xml");
deleteResultCode = SUCCESS;
}
assertThat(getRecordedEppMetric())
.hasClientId("NewRegistrar")
.and()
.hasCommandName("HostDelete")
.and()
.hasStatus(SUCCESS_WITH_ACTION_PENDING);
.hasStatus(deleteResultCode);
assertThatLogoutSucceeds();
}

View file

@ -17,7 +17,7 @@ package google.registry.flows.contact;
import static com.google.common.collect.MoreCollectors.onlyElement;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_DELETE;
import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_PENDING_DELETE;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.ContactResourceSubject.assertAboutContacts;
import static google.registry.testing.DatabaseHelper.assertNoBillingEvents;
import static google.registry.testing.DatabaseHelper.createTld;
@ -46,6 +46,7 @@ import google.registry.model.eppcommon.Trid;
import google.registry.model.poll.PendingActionNotificationResponse;
import google.registry.model.poll.PollMessage;
import google.registry.model.registry.Registry;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.HistoryEntry.Type;
import google.registry.model.transfer.TransferData;
import google.registry.model.transfer.TransferResponse;
@ -53,7 +54,6 @@ import google.registry.model.transfer.TransferStatus;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.ReplayExtension;
import google.registry.testing.TestOfyAndSql;
import google.registry.testing.TestOfyOnly;
import google.registry.testing.TestSqlOnly;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
@ -73,61 +73,28 @@ class ContactDeleteFlowTest extends ResourceFlowTestCase<ContactDeleteFlow, Cont
setEppInput("contact_delete.xml");
}
@TestOfyOnly
void testDryRun_ofy() throws Exception {
@TestOfyAndSql
void testDryRun() throws Exception {
persistActiveContact(getUniqueIdFromCommand());
dryRunFlowAssertResponse(loadFile("contact_delete_response_pending.xml"));
if (tm().isOfy()) {
dryRunFlowAssertResponse(loadFile("contact_delete_response_pending.xml"));
} else {
dryRunFlowAssertResponse(loadFile("contact_delete_response.xml"));
}
}
@TestSqlOnly
void testDryRun_sql() throws Exception {
persistActiveContact(getUniqueIdFromCommand());
dryRunFlowAssertResponse(loadFile("contact_delete_response.xml"));
}
@TestOfyOnly
void testSuccess_ofy() throws Exception {
@TestOfyAndSql
void testSuccess() throws Exception {
persistActiveContact(getUniqueIdFromCommand());
clock.advanceOneMilli();
assertTransactionalFlow(true);
runFlowAssertResponse(loadFile("contact_delete_response_pending.xml"));
ContactResource deletedContact = reloadResourceByForeignKey();
assertAboutContacts().that(deletedContact).hasStatusValue(StatusValue.PENDING_DELETE);
assertAsyncDeletionTaskEnqueued(
deletedContact, "TheRegistrar", Trid.create("ABC-12345", "server-trid"), false);
assertAboutContacts()
.that(deletedContact)
.hasOnlyOneHistoryEntryWhich()
.hasType(Type.CONTACT_PENDING_DELETE);
assertNoBillingEvents();
assertLastHistoryContainsResource(deletedContact);
}
@TestSqlOnly
void testSuccess_sql() throws Exception {
persistActiveContact(getUniqueIdFromCommand());
clock.advanceOneMilli();
assertTransactionalFlow(true);
runFlowAssertResponse(loadFile("contact_delete_response.xml"));
assertThat(reloadResourceByForeignKey()).isNull();
assertAboutContacts()
.that(reloadResourceByForeignKey(clock.nowUtc().minusMillis(1)))
.isNotActiveAt(clock.nowUtc())
.and()
.hasNullLocalizedPostalInfo()
.and()
.hasNullInternationalizedPostalInfo()
.and()
.hasNullEmailAddress()
.and()
.hasNullVoiceNumber()
.and()
.hasNullFaxNumber()
.and()
.hasOnlyOneHistoryEntryWhich()
.hasType(Type.CONTACT_DELETE);
assertNoTasksEnqueued(QUEUE_ASYNC_DELETE);
assertNoBillingEvents();
if (tm().isOfy()) {
runFlowAssertResponse(loadFile("contact_delete_response_pending.xml"));
assertOfyDeleteSuccess();
} else {
runFlowAssertResponse(loadFile("contact_delete_response.xml"));
assertSqlDeleteSuccess();
}
}
@TestSqlOnly
@ -143,23 +110,8 @@ class ContactDeleteFlowTest extends ResourceFlowTestCase<ContactDeleteFlow, Cont
clock.advanceOneMilli();
assertTransactionalFlow(true);
runFlowAssertResponse(loadFile("contact_delete_response.xml"));
assertThat(reloadResourceByForeignKey()).isNull();
assertSqlDeleteSuccess(Type.CONTACT_DELETE, Type.CONTACT_TRANSFER_REQUEST);
ContactResource softDeletedContact = reloadResourceByForeignKey(clock.nowUtc().minusMillis(1));
assertAboutContacts()
.that(softDeletedContact)
.isNotActiveAt(clock.nowUtc())
.and()
.hasNullLocalizedPostalInfo()
.and()
.hasNullInternationalizedPostalInfo()
.and()
.hasNullEmailAddress()
.and()
.hasNullVoiceNumber()
.and()
.hasNullFaxNumber()
.and()
.hasOneHistoryEntryEachOfTypes(Type.CONTACT_DELETE, Type.CONTACT_TRANSFER_REQUEST);
assertThat(softDeletedContact.getTransferData())
.isEqualTo(
oldTransferData
@ -185,54 +137,21 @@ class ContactDeleteFlowTest extends ResourceFlowTestCase<ContactDeleteFlow, Cont
assertThat(panData.getTrid())
.isEqualTo(Trid.create("transferClient-trid", "transferServer-trid"));
assertThat(panData.getActionResult()).isFalse();
assertNoTasksEnqueued(QUEUE_ASYNC_DELETE);
assertNoBillingEvents();
}
@TestOfyOnly
void testSuccess_clTridNotSpecified_ofy() throws Exception {
@TestOfyAndSql
void testSuccess_clTridNotSpecified() throws Exception {
setEppInput("contact_delete_no_cltrid.xml");
persistActiveContact(getUniqueIdFromCommand());
clock.advanceOneMilli();
assertTransactionalFlow(true);
runFlowAssertResponse(loadFile("contact_delete_response_no_cltrid_pending.xml"));
ContactResource deletedContact = reloadResourceByForeignKey();
assertAboutContacts().that(deletedContact).hasStatusValue(StatusValue.PENDING_DELETE);
assertAsyncDeletionTaskEnqueued(
deletedContact, "TheRegistrar", Trid.create(null, "server-trid"), false);
assertAboutContacts()
.that(deletedContact)
.hasOnlyOneHistoryEntryWhich()
.hasType(CONTACT_PENDING_DELETE);
assertNoBillingEvents();
}
@TestSqlOnly
void testSuccess_clTridNotSpecified_sql() throws Exception {
setEppInput("contact_delete_no_cltrid.xml");
persistActiveContact(getUniqueIdFromCommand());
clock.advanceOneMilli();
assertTransactionalFlow(true);
runFlowAssertResponse(loadFile("contact_delete_response_no_cltrid.xml"));
assertThat(reloadResourceByForeignKey()).isNull();
assertAboutContacts()
.that(reloadResourceByForeignKey(clock.nowUtc().minusMillis(1)))
.isNotActiveAt(clock.nowUtc())
.and()
.hasNullLocalizedPostalInfo()
.and()
.hasNullInternationalizedPostalInfo()
.and()
.hasNullEmailAddress()
.and()
.hasNullVoiceNumber()
.and()
.hasNullFaxNumber()
.and()
.hasOnlyOneHistoryEntryWhich()
.hasType(Type.CONTACT_DELETE);
assertNoTasksEnqueued(QUEUE_ASYNC_DELETE);
assertNoBillingEvents();
if (tm().isOfy()) {
runFlowAssertResponse(loadFile("contact_delete_response_no_cltrid_pending.xml"));
assertOfyDeleteSuccess("TheRegistrar", null, false);
} else {
runFlowAssertResponse(loadFile("contact_delete_response_no_cltrid.xml"));
assertSqlDeleteSuccess();
}
}
@TestOfyAndSql
@ -290,50 +209,22 @@ class ContactDeleteFlowTest extends ResourceFlowTestCase<ContactDeleteFlow, Cont
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@TestOfyOnly
void testSuccess_superuserUnauthorizedClient_ofy() throws Exception {
@TestOfyAndSql
void testSuccess_superuserUnauthorizedClient() throws Exception {
sessionMetadata.setClientId("NewRegistrar");
persistActiveContact(getUniqueIdFromCommand());
clock.advanceOneMilli();
runFlowAssertResponse(
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("contact_delete_response_pending.xml"));
ContactResource deletedContact = reloadResourceByForeignKey();
assertAboutContacts().that(deletedContact).hasStatusValue(StatusValue.PENDING_DELETE);
assertAsyncDeletionTaskEnqueued(
deletedContact, "NewRegistrar", Trid.create("ABC-12345", "server-trid"), true);
assertAboutContacts()
.that(deletedContact)
.hasOnlyOneHistoryEntryWhich()
.hasType(CONTACT_PENDING_DELETE);
assertNoBillingEvents();
}
@TestSqlOnly
void testSuccess_superuserUnauthorizedClient_sql() throws Exception {
sessionMetadata.setClientId("NewRegistrar");
persistActiveContact(getUniqueIdFromCommand());
clock.advanceOneMilli();
runFlowAssertResponse(
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("contact_delete_response.xml"));
assertThat(reloadResourceByForeignKey()).isNull();
assertAboutContacts()
.that(reloadResourceByForeignKey(clock.nowUtc().minusMillis(1)))
.isNotActiveAt(clock.nowUtc())
.and()
.hasNullLocalizedPostalInfo()
.and()
.hasNullInternationalizedPostalInfo()
.and()
.hasNullEmailAddress()
.and()
.hasNullVoiceNumber()
.and()
.hasNullFaxNumber()
.and()
.hasOnlyOneHistoryEntryWhich()
.hasType(Type.CONTACT_DELETE);
assertNoTasksEnqueued(QUEUE_ASYNC_DELETE);
assertNoBillingEvents();
if (tm().isOfy()) {
runFlowAssertResponse(
CommitMode.LIVE,
UserPrivileges.SUPERUSER,
loadFile("contact_delete_response_pending.xml"));
assertOfyDeleteSuccess("NewRegistrar", "ABC-12345", true);
} else {
runFlowAssertResponse(
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("contact_delete_response.xml"));
assertSqlDeleteSuccess();
}
}
@TestOfyAndSql
@ -359,4 +250,50 @@ class ContactDeleteFlowTest extends ResourceFlowTestCase<ContactDeleteFlow, Cont
runFlow();
assertIcannReportingActivityFieldLogged("srs-cont-delete");
}
private void assertOfyDeleteSuccess(String clientId, String clientTrid, boolean isSuperuser)
throws Exception {
ContactResource deletedContact = reloadResourceByForeignKey();
assertAsyncDeletionTaskEnqueued(
deletedContact, clientId, Trid.create(clientTrid, "server-trid"), isSuperuser);
assertAboutContacts()
.that(deletedContact)
.hasStatusValue(StatusValue.PENDING_DELETE)
.and()
.hasOnlyOneHistoryEntryWhich()
.hasType(Type.CONTACT_PENDING_DELETE);
assertNoBillingEvents();
assertLastHistoryContainsResource(deletedContact);
}
private void assertOfyDeleteSuccess() throws Exception {
assertOfyDeleteSuccess("TheRegistrar", "ABC-12345", false);
}
private void assertSqlDeleteSuccess(HistoryEntry.Type... historyEntryTypes) throws Exception {
assertThat(reloadResourceByForeignKey()).isNull();
assertAboutContacts()
.that(reloadResourceByForeignKey(clock.nowUtc().minusMillis(1)))
.isNotActiveAt(clock.nowUtc())
.and()
.hasNullLocalizedPostalInfo()
.and()
.hasNullInternationalizedPostalInfo()
.and()
.hasNullEmailAddress()
.and()
.hasNullVoiceNumber()
.and()
.hasNullFaxNumber()
.and()
.hasExactlyStatusValues(StatusValue.OK)
.and()
.hasOneHistoryEntryEachOfTypes(historyEntryTypes);
assertNoTasksEnqueued(QUEUE_ASYNC_DELETE);
assertNoBillingEvents();
}
private void assertSqlDeleteSuccess() throws Exception {
assertSqlDeleteSuccess(Type.CONTACT_DELETE);
}
}

View file

@ -15,8 +15,11 @@
package google.registry.flows.host;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_DELETE;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatabaseHelper.assertNoBillingEvents;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.loadByKey;
import static google.registry.testing.DatabaseHelper.newDomainBase;
import static google.registry.testing.DatabaseHelper.newHostResource;
import static google.registry.testing.DatabaseHelper.persistActiveHost;
@ -24,7 +27,9 @@ import static google.registry.testing.DatabaseHelper.persistDeletedHost;
import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
import static google.registry.testing.HostResourceSubject.assertAboutHosts;
import static google.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
import static google.registry.testing.TaskQueueHelper.assertNoDnsTasksEnqueued;
import static google.registry.testing.TaskQueueHelper.assertNoTasksEnqueued;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.collect.ImmutableMap;
@ -43,7 +48,7 @@ import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppcommon.Trid;
import google.registry.model.host.HostResource;
import google.registry.model.registry.Registry;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.HistoryEntry.Type;
import google.registry.model.transfer.DomainTransferData;
import google.registry.model.transfer.TransferStatus;
import google.registry.testing.DualDatabaseTest;
@ -70,7 +75,11 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResour
@TestOfyAndSql
void testDryRun() throws Exception {
persistActiveHost("ns1.example.tld");
dryRunFlowAssertResponse(loadFile("host_delete_response.xml"));
if (tm().isOfy()) {
dryRunFlowAssertResponse(loadFile("host_delete_response_pending.xml"));
} else {
dryRunFlowAssertResponse(loadFile("host_delete_response.xml"));
}
}
@TestOfyAndSql
@ -78,17 +87,13 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResour
persistActiveHost("ns1.example.tld");
clock.advanceOneMilli();
assertTransactionalFlow(true);
runFlowAssertResponse(loadFile("host_delete_response.xml"));
HostResource deletedHost = reloadResourceByForeignKey();
assertAboutHosts().that(deletedHost).hasStatusValue(StatusValue.PENDING_DELETE);
assertAsyncDeletionTaskEnqueued(
deletedHost, "TheRegistrar", Trid.create("ABC-12345", "server-trid"), false);
assertAboutHosts()
.that(deletedHost)
.hasOnlyOneHistoryEntryWhich()
.hasType(HistoryEntry.Type.HOST_PENDING_DELETE);
assertNoBillingEvents();
assertNoDnsTasksEnqueued();
if (tm().isOfy()) {
runFlowAssertResponse(loadFile("host_delete_response_pending.xml"));
assertOfyDeleteSuccess();
} else {
runFlowAssertResponse(loadFile("host_delete_response.xml"));
assertSqlDeleteSuccess();
}
}
@TestOfyAndSql
@ -97,17 +102,13 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResour
persistActiveHost("ns1.example.tld");
clock.advanceOneMilli();
assertTransactionalFlow(true);
runFlowAssertResponse(loadFile("host_delete_response_no_cltrid.xml"));
HostResource deletedHost = reloadResourceByForeignKey();
assertAboutHosts().that(deletedHost).hasStatusValue(StatusValue.PENDING_DELETE);
assertAsyncDeletionTaskEnqueued(
deletedHost, "TheRegistrar", Trid.create(null, "server-trid"), false);
assertAboutHosts()
.that(deletedHost)
.hasOnlyOneHistoryEntryWhich()
.hasType(HistoryEntry.Type.HOST_PENDING_DELETE);
assertNoBillingEvents();
assertNoDnsTasksEnqueued();
if (tm().isOfy()) {
runFlowAssertResponse(loadFile("host_delete_response_no_cltrid_pending.xml"));
assertOfyDeleteSuccess("TheRegistrar", null, false);
} else {
runFlowAssertResponse(loadFile("host_delete_response_no_cltrid.xml"));
assertSqlDeleteSuccess();
}
}
@TestOfyAndSql
@ -166,18 +167,15 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResour
sessionMetadata.setClientId("NewRegistrar");
persistActiveHost("ns1.example.tld");
clock.advanceOneMilli();
runFlowAssertResponse(
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("host_delete_response.xml"));
HostResource deletedHost = reloadResourceByForeignKey();
assertAboutHosts().that(deletedHost).hasStatusValue(StatusValue.PENDING_DELETE);
assertAsyncDeletionTaskEnqueued(
deletedHost, "NewRegistrar", Trid.create("ABC-12345", "server-trid"), true);
assertAboutHosts()
.that(deletedHost)
.hasOnlyOneHistoryEntryWhich()
.hasType(HistoryEntry.Type.HOST_PENDING_DELETE);
assertNoBillingEvents();
assertNoDnsTasksEnqueued();
if (tm().isOfy()) {
runFlowAssertResponse(
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("host_delete_response_pending.xml"));
assertOfyDeleteSuccess("NewRegistrar", "ABC-12345", true);
} else {
runFlowAssertResponse(
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("host_delete_response.xml"));
assertSqlDeleteSuccess();
}
}
@TestOfyAndSql
@ -197,7 +195,13 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResour
.setSuperordinateDomain(domain.createVKey())
.build());
clock.advanceOneMilli();
runFlowAssertResponse(loadFile("host_delete_response.xml"));
if (tm().isOfy()) {
runFlowAssertResponse(loadFile("host_delete_response_pending.xml"));
assertOfyDeleteSuccess();
} else {
runFlowAssertResponse(loadFile("host_delete_response.xml"));
assertSqlDeleteSuccess(true);
}
}
@TestOfyAndSql
@ -250,7 +254,13 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResour
.setSuperordinateDomain(domain.createVKey())
.build());
clock.advanceOneMilli();
runFlowAssertResponse(loadFile("host_delete_response.xml"));
if (tm().isOfy()) {
runFlowAssertResponse(loadFile("host_delete_response_pending.xml"));
assertOfyDeleteSuccess("NewRegistrar", "ABC-12345", false);
} else {
runFlowAssertResponse(loadFile("host_delete_response.xml"));
assertSqlDeleteSuccess(true);
}
}
@TestOfyAndSql
@ -327,4 +337,48 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResour
runFlow();
assertIcannReportingActivityFieldLogged("srs-host-delete");
}
private void assertOfyDeleteSuccess(String clientId, String clientTrid, boolean isSuperuser)
throws Exception {
HostResource deletedHost = reloadResourceByForeignKey();
assertAsyncDeletionTaskEnqueued(
deletedHost, clientId, Trid.create(clientTrid, "server-trid"), isSuperuser);
assertAboutHosts()
.that(deletedHost)
.hasStatusValue(StatusValue.PENDING_DELETE)
.and()
.hasOnlyOneHistoryEntryWhich()
.hasType(Type.HOST_PENDING_DELETE);
assertNoBillingEvents();
assertNoDnsTasksEnqueued();
}
private void assertOfyDeleteSuccess() throws Exception {
assertOfyDeleteSuccess("TheRegistrar", "ABC-12345", false);
}
private void assertSqlDeleteSuccess(boolean isSubordinate) throws Exception {
assertThat(reloadResourceByForeignKey()).isNull();
HostResource deletedHost = reloadResourceByForeignKey(clock.nowUtc().minusMillis(1));
assertAboutHosts()
.that(deletedHost)
.isNotActiveAt(clock.nowUtc())
.and()
.hasExactlyStatusValues(StatusValue.OK)
.and()
.hasOnlyOneHistoryEntryWhich()
.hasType(Type.HOST_DELETE);
assertNoBillingEvents();
if (isSubordinate) {
assertDnsTasksEnqueued(deletedHost.getHostName());
assertThat(loadByKey(deletedHost.getSuperordinateDomain()).getSubordinateHosts()).isEmpty();
} else {
assertNoDnsTasksEnqueued();
}
assertNoTasksEnqueued(QUEUE_ASYNC_DELETE);
}
private void assertSqlDeleteSuccess() throws Exception {
assertSqlDeleteSuccess(false);
}
}

View file

@ -1,7 +1,7 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1001">
<msg>Command completed successfully; action pending</msg>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<trID>
<clTRID>ABC-12345</clTRID>

View file

@ -1,7 +1,7 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1001">
<msg>Command completed successfully; action pending</msg>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<trID>
<svTRID>server-trid</svTRID>

View file

@ -0,0 +1,10 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1001">
<msg>Command completed successfully; action pending</msg>
</result>
<trID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>

View file

@ -0,0 +1,11 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1001">
<msg>Command completed successfully; action pending</msg>
</result>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>