mirror of
https://github.com/google/nomulus
synced 2026-09-07 00:27:03 +00:00
Add databaseTransitionSchedule entity and tool for updating (#926)
* Add databaseTransitionSchedule entitiy * add UpdateDatabaseTransitionScheduleCommand * small fixes * change entity structure to no longer be singleton * add get command * fix getCache * Change id to TransitionId enum * more fixes * Cleanup tests * Add link to javadoc * Add lastUpdateTime * fix datatype of getCached
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
// Copyright 2021 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.model.common;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.model.EntityTestCase;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.PrimaryDatabase;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.PrimaryDatabaseTransition;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.TransitionId;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link DatabaseTransitionSchedule}. */
|
||||
public class DatabaseTransitionScheduleTest extends EntityTestCase {
|
||||
|
||||
@Test
|
||||
void testSuccess_persistence() {
|
||||
TimedTransitionProperty<PrimaryDatabase, PrimaryDatabaseTransition> databaseTransitions =
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, PrimaryDatabase.DATASTORE),
|
||||
PrimaryDatabaseTransition.class);
|
||||
DatabaseTransitionSchedule schedule =
|
||||
DatabaseTransitionSchedule.create(
|
||||
TransitionId.SIGNED_MARK_REVOCATION_LIST, databaseTransitions);
|
||||
ofyTm().transactNew(() -> ofyTm().put(schedule));
|
||||
|
||||
assertThat(
|
||||
DatabaseTransitionSchedule.get(TransitionId.SIGNED_MARK_REVOCATION_LIST)
|
||||
.get()
|
||||
.databaseTransitions)
|
||||
.isEqualTo(databaseTransitions);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_scheduleWithNoStartOfTime() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
DatabaseTransitionSchedule.create(
|
||||
TransitionId.SIGNED_MARK_REVOCATION_LIST,
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(fakeClock.nowUtc(), PrimaryDatabase.DATASTORE),
|
||||
PrimaryDatabaseTransition.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_getPrimaryDatabase() {
|
||||
DatabaseTransitionSchedule schedule =
|
||||
DatabaseTransitionSchedule.create(
|
||||
TransitionId.SIGNED_MARK_REVOCATION_LIST,
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(
|
||||
START_OF_TIME,
|
||||
PrimaryDatabase.DATASTORE,
|
||||
fakeClock.nowUtc().plusDays(1),
|
||||
PrimaryDatabase.CLOUD_SQL),
|
||||
PrimaryDatabaseTransition.class));
|
||||
assertThat(ofyTm().transact(schedule::getPrimaryDatabase)).isEqualTo(PrimaryDatabase.DATASTORE);
|
||||
fakeClock.advanceBy(Duration.standardDays(5));
|
||||
assertThat(ofyTm().transact(schedule::getPrimaryDatabase)).isEqualTo(PrimaryDatabase.CLOUD_SQL);
|
||||
}
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
// Copyright 2021 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;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.PrimaryDatabase;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.PrimaryDatabaseTransition;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.TransitionId;
|
||||
import google.registry.model.common.TimedTransitionProperty;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link GetDatabaseTransitionScheduleCommand} */
|
||||
public class GetDatabaseTransitionScheduleCommandTest
|
||||
extends CommandTestCase<GetDatabaseTransitionScheduleCommand> {
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
inject.setStaticField(
|
||||
Ofy.class, "clock", new FakeClock(DateTime.parse("1984-12-21T06:07:08.789Z")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess() throws Exception {
|
||||
TimedTransitionProperty<PrimaryDatabase, PrimaryDatabaseTransition> databaseTransitions =
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, PrimaryDatabase.DATASTORE),
|
||||
PrimaryDatabaseTransition.class);
|
||||
DatabaseTransitionSchedule schedule =
|
||||
DatabaseTransitionSchedule.create(
|
||||
TransitionId.SIGNED_MARK_REVOCATION_LIST, databaseTransitions);
|
||||
ofyTm().transactNew(() -> ofyTm().put(schedule));
|
||||
runCommand("SIGNED_MARK_REVOCATION_LIST");
|
||||
assertStdoutIs(
|
||||
"SIGNED_MARK_REVOCATION_LIST(last updated at 1984-12-21T06:07:08.789Z):"
|
||||
+ " {1970-01-01T00:00:00.000Z=DATASTORE}\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_multipleArguments() throws Exception {
|
||||
fakeClock.setTo(DateTime.parse("2020-10-01T00:00:00Z"));
|
||||
TimedTransitionProperty<PrimaryDatabase, PrimaryDatabaseTransition> databaseTransitions =
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, PrimaryDatabase.DATASTORE),
|
||||
PrimaryDatabaseTransition.class);
|
||||
DatabaseTransitionSchedule schedule =
|
||||
DatabaseTransitionSchedule.create(TransitionId.DOMAIN_LABEL_LISTS, databaseTransitions);
|
||||
ofyTm().transactNew(() -> ofyTm().put(schedule));
|
||||
TimedTransitionProperty<PrimaryDatabase, PrimaryDatabaseTransition> databaseTransitions2 =
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(
|
||||
START_OF_TIME,
|
||||
PrimaryDatabase.DATASTORE,
|
||||
fakeClock.nowUtc(),
|
||||
PrimaryDatabase.CLOUD_SQL),
|
||||
PrimaryDatabaseTransition.class);
|
||||
DatabaseTransitionSchedule schedule2 =
|
||||
DatabaseTransitionSchedule.create(
|
||||
TransitionId.SIGNED_MARK_REVOCATION_LIST, databaseTransitions2);
|
||||
ofyTm().transactNew(() -> ofyTm().put(schedule2));
|
||||
runCommand("DOMAIN_LABEL_LISTS", "SIGNED_MARK_REVOCATION_LIST");
|
||||
assertStdoutIs(
|
||||
"DOMAIN_LABEL_LISTS(last updated at 1984-12-21T06:07:08.789Z):"
|
||||
+ " {1970-01-01T00:00:00.000Z=DATASTORE}\n"
|
||||
+ "SIGNED_MARK_REVOCATION_LIST(last updated at 1984-12-21T06:07:08.789Z):"
|
||||
+ " {1970-01-01T00:00:00.000Z=DATASTORE, 2020-10-01T00:00:00.000Z=CLOUD_SQL}\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_scheduleDoesNotExist() {
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class, () -> runCommand("SIGNED_MARK_REVOCATION_LIST"));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains("A database transition schedule for SIGNED_MARK_REVOCATION_LIST does not exist");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_noIdGiven() {
|
||||
assertThrows(ParameterException.class, this::runCommand);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_oneScheduleDoesNotExist() {
|
||||
TimedTransitionProperty<PrimaryDatabase, PrimaryDatabaseTransition> databaseTransitions =
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(START_OF_TIME, PrimaryDatabase.DATASTORE),
|
||||
PrimaryDatabaseTransition.class);
|
||||
DatabaseTransitionSchedule schedule =
|
||||
DatabaseTransitionSchedule.create(TransitionId.DOMAIN_LABEL_LISTS, databaseTransitions);
|
||||
ofyTm().transactNew(() -> ofyTm().put(schedule));
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> runCommand("DOMAIN_LABEL_LISTS", "SIGNED_MARK_REVOCATION_LIST"));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains("A database transition schedule for SIGNED_MARK_REVOCATION_LIST does not exist");
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
// Copyright 2021 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;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.PrimaryDatabase;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.PrimaryDatabaseTransition;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.TransitionId;
|
||||
import google.registry.model.common.TimedTransitionProperty;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link SetDatabaseTransitionScheduleCommand}. */
|
||||
public class SetDatabaseTransitionScheduleCommandTest
|
||||
extends CommandTestCase<SetDatabaseTransitionScheduleCommand> {
|
||||
|
||||
Key<DatabaseTransitionSchedule> key;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
key = Key.create(getCrossTldKey(), DatabaseTransitionSchedule.class, "test");
|
||||
fakeClock.setTo(DateTime.parse("2020-12-01T00:00:00Z"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_currentScheduleIsEmpty() throws Exception {
|
||||
assertThat(ofy().load().key(key).now()).isNull();
|
||||
runCommandForced(
|
||||
"--transition_id=SIGNED_MARK_REVOCATION_LIST",
|
||||
"--transition_schedule=1970-01-01T00:00:00.000Z=DATASTORE");
|
||||
assertThat(
|
||||
ofyTm()
|
||||
.transact(
|
||||
() ->
|
||||
DatabaseTransitionSchedule.get(TransitionId.SIGNED_MARK_REVOCATION_LIST)
|
||||
.get()
|
||||
.getPrimaryDatabase()))
|
||||
.isEqualTo(PrimaryDatabase.DATASTORE);
|
||||
assertThat(command.prompt()).contains("Create DatabaseTransitionSchedule");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess() throws Exception {
|
||||
ImmutableSortedMap<DateTime, PrimaryDatabase> transitionMap =
|
||||
ImmutableSortedMap.of(
|
||||
START_OF_TIME,
|
||||
PrimaryDatabase.DATASTORE,
|
||||
fakeClock.nowUtc().minusDays(1),
|
||||
PrimaryDatabase.CLOUD_SQL);
|
||||
persistResource(
|
||||
DatabaseTransitionSchedule.create(
|
||||
TransitionId.SIGNED_MARK_REVOCATION_LIST,
|
||||
TimedTransitionProperty.fromValueMap(transitionMap, PrimaryDatabaseTransition.class)));
|
||||
assertThat(
|
||||
DatabaseTransitionSchedule.get(TransitionId.SIGNED_MARK_REVOCATION_LIST)
|
||||
.get()
|
||||
.getDatabaseTransitions())
|
||||
.isEqualTo(transitionMap);
|
||||
runCommandForced(
|
||||
"--transition_id=SIGNED_MARK_REVOCATION_LIST",
|
||||
"--transition_schedule=1970-01-01T00:00:00.000Z=DATASTORE,2020-11-30T00:00:00.000Z=CLOUD_SQL,2020-12-06T00:00:00.000Z=DATASTORE");
|
||||
ImmutableSortedMap<DateTime, PrimaryDatabase> retrievedTransitionMap =
|
||||
ofyTm()
|
||||
.transact(
|
||||
() ->
|
||||
DatabaseTransitionSchedule.get(TransitionId.SIGNED_MARK_REVOCATION_LIST)
|
||||
.get()
|
||||
.getDatabaseTransitions());
|
||||
assertThat(retrievedTransitionMap)
|
||||
.containsExactly(
|
||||
START_OF_TIME,
|
||||
PrimaryDatabase.DATASTORE,
|
||||
fakeClock.nowUtc().minusDays(1),
|
||||
PrimaryDatabase.CLOUD_SQL,
|
||||
fakeClock.nowUtc().plusDays(5),
|
||||
PrimaryDatabase.DATASTORE);
|
||||
fakeClock.advanceBy(Duration.standardDays(5));
|
||||
assertThat(
|
||||
ofyTm()
|
||||
.transact(
|
||||
() ->
|
||||
DatabaseTransitionSchedule.get(TransitionId.SIGNED_MARK_REVOCATION_LIST)
|
||||
.get()
|
||||
.getPrimaryDatabase()))
|
||||
.isEqualTo(PrimaryDatabase.DATASTORE);
|
||||
assertThat(command.prompt()).contains("Update DatabaseTransitionSchedule");
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ AllocationToken
|
||||
Cancellation
|
||||
ContactResource
|
||||
Cursor
|
||||
DatabaseTransitionSchedule
|
||||
DomainBase
|
||||
EntityGroupRoot
|
||||
EppResourceIndex
|
||||
|
||||
@@ -78,6 +78,20 @@ class google.registry.model.common.Cursor {
|
||||
google.registry.model.UpdateAutoTimestamp lastUpdateTime;
|
||||
org.joda.time.DateTime cursorTime;
|
||||
}
|
||||
class google.registry.model.common.DatabaseTransitionSchedule {
|
||||
@Id java.lang.String transitionId;
|
||||
@Parent com.googlecode.objectify.Key<google.registry.model.common.EntityGroupRoot> parent;
|
||||
google.registry.model.UpdateAutoTimestamp lastUpdateTime;
|
||||
google.registry.model.common.TimedTransitionProperty<google.registry.model.common.DatabaseTransitionSchedule$PrimaryDatabase, google.registry.model.common.DatabaseTransitionSchedule$PrimaryDatabaseTransition> databaseTransitions;
|
||||
}
|
||||
enum google.registry.model.common.DatabaseTransitionSchedule$PrimaryDatabase {
|
||||
CLOUD_SQL;
|
||||
DATASTORE;
|
||||
}
|
||||
class google.registry.model.common.DatabaseTransitionSchedule$PrimaryDatabaseTransition {
|
||||
google.registry.model.common.DatabaseTransitionSchedule$PrimaryDatabase primaryDatabase;
|
||||
org.joda.time.DateTime transitionTime;
|
||||
}
|
||||
class google.registry.model.common.EntityGroupRoot {
|
||||
@Id java.lang.String id;
|
||||
google.registry.model.UpdateAutoTimestamp updateTimestamp;
|
||||
|
||||
Reference in New Issue
Block a user