Add a scrap command to backfill registry locks (#478)

* Add a scrap command to backfill registry locks

* fix tests

* Change comments and messages

* Use URS time (best effort) if one exists

* Don't bother with root cause
This commit is contained in:
gbrodman 2020-02-20 15:07:39 -05:00 committed by GitHub
parent 7bb69e50c5
commit ecf1721755
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 333 additions and 1 deletions

View file

@ -32,6 +32,7 @@ import google.registry.tools.LockDomainCommandTest;
import google.registry.tools.UnlockDomainCommandTest;
import google.registry.tools.UpdateRegistrarCommandTest;
import google.registry.tools.UpdateReservedListCommandTest;
import google.registry.tools.javascrap.BackfillRegistryLocksCommandTest;
import google.registry.tools.server.CreatePremiumListActionTest;
import google.registry.tools.server.UpdatePremiumListActionTest;
import google.registry.ui.server.registrar.RegistryLockGetActionTest;
@ -56,6 +57,7 @@ import org.junit.runners.Suite.SuiteClasses;
*/
@RunWith(Suite.class)
@SuiteClasses({
BackfillRegistryLocksCommandTest.class,
ClaimsListDaoTest.class,
CreatePremiumListActionTest.class,
CreateRegistrarCommandTest.class,

View file

@ -0,0 +1,176 @@
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.tools.javascrap;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.persistActiveDomain;
import static google.registry.testing.DatastoreHelper.persistDeletedDomain;
import static google.registry.testing.DatastoreHelper.persistNewRegistrar;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static org.junit.Assert.assertThrows;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.truth.Truth8;
import google.registry.model.domain.DomainBase;
import google.registry.model.registrar.Registrar;
import google.registry.model.registry.RegistryLockDao;
import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule;
import google.registry.schema.domain.RegistryLock;
import google.registry.testing.DeterministicStringGenerator;
import google.registry.testing.FakeClock;
import google.registry.tools.CommandTestCase;
import google.registry.util.StringGenerator.Alphabets;
import java.util.Optional;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link BackfillRegistryLocksCommand}. */
@RunWith(JUnit4.class)
public class BackfillRegistryLocksCommandTest
extends CommandTestCase<BackfillRegistryLocksCommand> {
private final FakeClock fakeClock = new FakeClock();
@Rule
public final JpaIntegrationWithCoverageRule jpaRule =
new JpaTestRules.Builder().buildIntegrationWithCoverageRule();
@Before
public void before() {
persistNewRegistrar("adminreg", "Admin Registrar", Registrar.Type.REAL, 693L);
createTld("tld");
command.registryAdminClientId = "adminreg";
command.clock = fakeClock;
command.stringGenerator = new DeterministicStringGenerator(Alphabets.BASE_58);
}
@Test
public void testSimpleBackfill() throws Exception {
DomainBase domain = persistLockedDomain("example.tld");
Truth8.assertThat(RegistryLockDao.getMostRecentByRepoId(domain.getRepoId())).isEmpty();
runCommandForced("--domain_roids", domain.getRepoId());
Optional<RegistryLock> lockOptional = RegistryLockDao.getMostRecentByRepoId(domain.getRepoId());
Truth8.assertThat(lockOptional).isPresent();
Truth8.assertThat(lockOptional.get().getLockCompletionTimestamp()).isPresent();
}
@Test
public void testBackfill_onlyLockedDomains() throws Exception {
DomainBase neverLockedDomain = persistActiveDomain("neverlocked.tld");
DomainBase previouslyLockedDomain = persistLockedDomain("unlocked.tld");
persistResource(previouslyLockedDomain.asBuilder().setStatusValues(ImmutableSet.of()).build());
DomainBase lockedDomain = persistLockedDomain("locked.tld");
runCommandForced(
"--domain_roids",
String.format(
"%s,%s,%s",
neverLockedDomain.getRepoId(),
previouslyLockedDomain.getRepoId(),
lockedDomain.getRepoId()));
ImmutableList<RegistryLock> locks = RegistryLockDao.getLockedDomainsByRegistrarId("adminreg");
assertThat(locks).hasSize(1);
assertThat(Iterables.getOnlyElement(locks).getDomainName()).isEqualTo("locked.tld");
}
@Test
public void testBackfill_skipsDeletedDomains() throws Exception {
DomainBase domain = persistDeletedDomain("example.tld", fakeClock.nowUtc());
persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
fakeClock.advanceBy(Duration.standardSeconds(1));
runCommandForced("--domain_roids", domain.getRepoId());
Truth8.assertThat(RegistryLockDao.getMostRecentByRepoId(domain.getRepoId())).isEmpty();
}
@Test
public void testBackfill_skipsDomains_ifLockAlreadyExists() throws Exception {
DomainBase domain = persistLockedDomain("example.tld");
RegistryLock previousLock =
RegistryLockDao.save(
new RegistryLock.Builder()
.isSuperuser(true)
.setRegistrarId("adminreg")
.setRepoId(domain.getRepoId())
.setDomainName(domain.getFullyQualifiedDomainName())
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setVerificationCode(command.stringGenerator.createString(32))
.build());
fakeClock.advanceBy(Duration.standardDays(1));
runCommandForced("--domain_roids", domain.getRepoId());
assertThat(
RegistryLockDao.getMostRecentByRepoId(domain.getRepoId())
.get()
.getLockCompletionTimestamp())
.isEqualTo(previousLock.getLockCompletionTimestamp());
}
@Test
public void testBackfill_usesUrsTime_ifExists() throws Exception {
DateTime ursTime = fakeClock.nowUtc();
DomainBase ursDomain = persistLockedDomain("urs.tld");
HistoryEntry historyEntry =
new HistoryEntry.Builder()
.setBySuperuser(true)
.setClientId("adminreg")
.setModificationTime(ursTime)
.setParent(ursDomain)
.setReason("Uniform Rapid Suspension")
.setType(HistoryEntry.Type.DOMAIN_UPDATE)
.setRequestedByRegistrar(false)
.build();
persistResource(historyEntry);
DomainBase nonUrsDomain = persistLockedDomain("nonurs.tld");
fakeClock.advanceBy(Duration.standardDays(10));
runCommandForced(
"--domain_roids", String.format("%s,%s", ursDomain.getRepoId(), nonUrsDomain.getRepoId()));
RegistryLock ursLock =
RegistryLockDao.getMostRecentVerifiedLockByRepoId(ursDomain.getRepoId()).get();
assertThat(ursLock.getLockCompletionTimestamp().get()).isEqualTo(ursTime);
RegistryLock nonUrsLock =
RegistryLockDao.getMostRecentVerifiedLockByRepoId(nonUrsDomain.getRepoId()).get();
assertThat(nonUrsLock.getLockCompletionTimestamp().get()).isEqualTo(fakeClock.nowUtc());
}
@Test
public void testFailure_mustProvideDomainRoids() {
assertThat(assertThrows(IllegalArgumentException.class, () -> runCommandForced()))
.hasMessageThat()
.isEqualTo("Must provide non-empty domain_roids argument");
}
private static DomainBase persistLockedDomain(String domainName) {
DomainBase domain = persistActiveDomain(domainName);
return persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
}
}