mirror of
https://github.com/google/nomulus.git
synced 2025-07-22 18:55:58 +02:00
Add java changes for createBillingCostTransitions (#2314)
* Add java changes for createBillingCostTransitions * Add negative cost test * Remove default value * remove unused variable * Add check that create cost and trnasitions map are the same * inject clock, only use key set when checking for missing fields * Add test for removing map
This commit is contained in:
parent
7b47ecb1f1
commit
abc1a0ef3d
14 changed files with 391 additions and 4 deletions
|
@ -74,6 +74,7 @@ import google.registry.tldconfig.idn.IdnTableEnum;
|
||||||
import google.registry.util.Idn;
|
import google.registry.util.Idn;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
@ -458,6 +459,8 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
|
||||||
@JsonDeserialize(using = CurrencyDeserializer.class)
|
@JsonDeserialize(using = CurrencyDeserializer.class)
|
||||||
CurrencyUnit currency = DEFAULT_CURRENCY;
|
CurrencyUnit currency = DEFAULT_CURRENCY;
|
||||||
|
|
||||||
|
// TODO(sarahbot@): Remove this field and make createBillingCostTransitions not-null once all TLDs
|
||||||
|
// are populated with a create cost transition map
|
||||||
/** The per-year billing cost for registering a new domain name. */
|
/** The per-year billing cost for registering a new domain name. */
|
||||||
@Type(type = JodaMoneyType.TYPE_NAME)
|
@Type(type = JodaMoneyType.TYPE_NAME)
|
||||||
@Columns(
|
@Columns(
|
||||||
|
@ -467,6 +470,12 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
|
||||||
})
|
})
|
||||||
Money createBillingCost = DEFAULT_CREATE_BILLING_COST;
|
Money createBillingCost = DEFAULT_CREATE_BILLING_COST;
|
||||||
|
|
||||||
|
// TODO(sarahbot@): Make this field not null and add a default value once field is populated on
|
||||||
|
// all existing TLDs
|
||||||
|
/** A property that transitions to different create billing costs at different times. */
|
||||||
|
@JsonDeserialize(using = TimedTransitionPropertyMoneyDeserializer.class)
|
||||||
|
TimedTransitionProperty<Money> createBillingCostTransitions;
|
||||||
|
|
||||||
/** The one-time billing cost for restoring a domain name from the redemption grace period. */
|
/** The one-time billing cost for restoring a domain name from the redemption grace period. */
|
||||||
@Type(type = JodaMoneyType.TYPE_NAME)
|
@Type(type = JodaMoneyType.TYPE_NAME)
|
||||||
@Columns(
|
@Columns(
|
||||||
|
@ -676,6 +685,13 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
|
||||||
return createBillingCost;
|
return createBillingCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ImmutableSortedMap<DateTime, Money> getCreateBillingCostTransitions() {
|
||||||
|
return Objects.requireNonNullElseGet(
|
||||||
|
createBillingCostTransitions,
|
||||||
|
() -> TimedTransitionProperty.withInitialValue(getCreateBillingCost()))
|
||||||
|
.toValueMap();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the add-on cost of a domain restore (the flat tld-wide fee charged in addition to one
|
* Returns the add-on cost of a domain restore (the flat tld-wide fee charged in addition to one
|
||||||
* year of renewal for that name).
|
* year of renewal for that name).
|
||||||
|
@ -959,6 +975,17 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder setCreateBillingCostTransitions(
|
||||||
|
ImmutableSortedMap<DateTime, Money> createCostsMap) {
|
||||||
|
checkArgumentNotNull(createCostsMap, "Create billing costs map cannot be null");
|
||||||
|
checkArgument(
|
||||||
|
createCostsMap.values().stream().allMatch(Money::isPositiveOrZero),
|
||||||
|
"Create billing cost cannot be negative");
|
||||||
|
getInstance().createBillingCostTransitions =
|
||||||
|
TimedTransitionProperty.fromValueMap(createCostsMap);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Builder setReservedListsByName(Set<String> reservedListNames) {
|
public Builder setReservedListsByName(Set<String> reservedListNames) {
|
||||||
// TODO(b/309175133): forbid if enrolled with BSA
|
// TODO(b/309175133): forbid if enrolled with BSA
|
||||||
checkArgument(reservedListNames != null, "reservedListNames must not be null");
|
checkArgument(reservedListNames != null, "reservedListNames must not be null");
|
||||||
|
@ -1131,6 +1158,10 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
|
||||||
// here to catch cases where we loaded an invalid TimedTransitionProperty from the database
|
// here to catch cases where we loaded an invalid TimedTransitionProperty from the database
|
||||||
// and cloned it into a new builder, to block re-building a Tld in an invalid state.
|
// and cloned it into a new builder, to block re-building a Tld in an invalid state.
|
||||||
instance.tldStateTransitions.checkValidity();
|
instance.tldStateTransitions.checkValidity();
|
||||||
|
// TODO(sarahbot@): Remove null check when createBillingCostTransitions field is made not-null
|
||||||
|
if (instance.createBillingCostTransitions != null) {
|
||||||
|
instance.createBillingCostTransitions.checkValidity();
|
||||||
|
}
|
||||||
instance.renewBillingCostTransitions.checkValidity();
|
instance.renewBillingCostTransitions.checkValidity();
|
||||||
instance.eapFeeSchedule.checkValidity();
|
instance.eapFeeSchedule.checkValidity();
|
||||||
// All costs must be in the expected currency.
|
// All costs must be in the expected currency.
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
package google.registry.tools;
|
package google.registry.tools;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||||
import static google.registry.model.tld.Tld.Builder.ROID_SUFFIX_PATTERN;
|
import static google.registry.model.tld.Tld.Builder.ROID_SUFFIX_PATTERN;
|
||||||
import static google.registry.model.tld.Tlds.getTlds;
|
import static google.registry.model.tld.Tlds.getTlds;
|
||||||
import static google.registry.util.ListNamingUtils.convertFilePathToName;
|
import static google.registry.util.ListNamingUtils.convertFilePathToName;
|
||||||
|
@ -28,10 +29,12 @@ import com.google.common.collect.ImmutableSortedMap;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.collect.Sets.SetView;
|
import com.google.common.collect.Sets.SetView;
|
||||||
import com.google.common.flogger.FluentLogger;
|
import com.google.common.flogger.FluentLogger;
|
||||||
|
import google.registry.model.common.TimedTransitionProperty;
|
||||||
import google.registry.model.tld.Tld;
|
import google.registry.model.tld.Tld;
|
||||||
import google.registry.model.tld.label.PremiumList;
|
import google.registry.model.tld.label.PremiumList;
|
||||||
import google.registry.model.tld.label.PremiumListDao;
|
import google.registry.model.tld.label.PremiumListDao;
|
||||||
import google.registry.tools.params.PathParameter;
|
import google.registry.tools.params.PathParameter;
|
||||||
|
import google.registry.util.Clock;
|
||||||
import google.registry.util.Idn;
|
import google.registry.util.Idn;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
@ -40,9 +43,11 @@ import java.nio.file.Path;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import org.joda.money.CurrencyUnit;
|
import org.joda.money.CurrencyUnit;
|
||||||
|
@ -90,6 +95,8 @@ public class ConfigureTldCommand extends MutatingCommand {
|
||||||
|
|
||||||
@Inject ObjectMapper mapper;
|
@Inject ObjectMapper mapper;
|
||||||
|
|
||||||
|
@Inject Clock clock;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@Named("dnsWriterNames")
|
@Named("dnsWriterNames")
|
||||||
Set<String> validDnsWriterNames;
|
Set<String> validDnsWriterNames;
|
||||||
|
@ -114,8 +121,11 @@ public class ConfigureTldCommand extends MutatingCommand {
|
||||||
String name = convertFilePathToName(inputFile);
|
String name = convertFilePathToName(inputFile);
|
||||||
Map<String, Object> tldData = new Yaml().load(Files.newBufferedReader(inputFile));
|
Map<String, Object> tldData = new Yaml().load(Files.newBufferedReader(inputFile));
|
||||||
checkName(name, tldData);
|
checkName(name, tldData);
|
||||||
checkForMissingFields(tldData);
|
|
||||||
Tld oldTld = getTlds().contains(name) ? Tld.get(name) : null;
|
Tld oldTld = getTlds().contains(name) ? Tld.get(name) : null;
|
||||||
|
|
||||||
|
checkForMissingFields(
|
||||||
|
Stream.concat(tldData.keySet().stream(), Stream.of("createBillingCostTransitions"))
|
||||||
|
.collect(toImmutableSet()));
|
||||||
Tld newTld = mapper.readValue(inputFile.toFile(), Tld.class);
|
Tld newTld = mapper.readValue(inputFile.toFile(), Tld.class);
|
||||||
if (oldTld != null) {
|
if (oldTld != null) {
|
||||||
oldTldInBreakGlass = oldTld.getBreakglassMode();
|
oldTldInBreakGlass = oldTld.getBreakglassMode();
|
||||||
|
@ -146,6 +156,14 @@ public class ConfigureTldCommand extends MutatingCommand {
|
||||||
checkPremiumList(newTld);
|
checkPremiumList(newTld);
|
||||||
checkDnsWriters(newTld);
|
checkDnsWriters(newTld);
|
||||||
checkCurrency(newTld);
|
checkCurrency(newTld);
|
||||||
|
// TODO(sarahbot@): Remove this once the createBillingCost field is removed
|
||||||
|
checkArgument(
|
||||||
|
Objects.equals(
|
||||||
|
TimedTransitionProperty.fromValueMap(newTld.getCreateBillingCostTransitions())
|
||||||
|
.getValueAtTime(clock.nowUtc()),
|
||||||
|
newTld.getCreateBillingCost()),
|
||||||
|
"The createBillingCostTransitions map must have the same current cost as the"
|
||||||
|
+ " createBillingCost field");
|
||||||
// bsaEnrollStartTime only exists in DB. Need to carry it over to the updated copy. See Tld.java
|
// bsaEnrollStartTime only exists in DB. Need to carry it over to the updated copy. See Tld.java
|
||||||
// for more information.
|
// for more information.
|
||||||
Optional<DateTime> bsaEnrollTime =
|
Optional<DateTime> bsaEnrollTime =
|
||||||
|
@ -198,7 +216,7 @@ public class ConfigureTldCommand extends MutatingCommand {
|
||||||
ROID_SUFFIX_PATTERN.pattern());
|
ROID_SUFFIX_PATTERN.pattern());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkForMissingFields(Map<String, Object> tldData) {
|
private void checkForMissingFields(ImmutableSet<String> keySet) {
|
||||||
Set<String> tldFields =
|
Set<String> tldFields =
|
||||||
Arrays.stream(Tld.class.getDeclaredFields())
|
Arrays.stream(Tld.class.getDeclaredFields())
|
||||||
.filter(field -> !Modifier.isStatic(field.getModifiers()))
|
.filter(field -> !Modifier.isStatic(field.getModifiers()))
|
||||||
|
@ -207,7 +225,7 @@ public class ConfigureTldCommand extends MutatingCommand {
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
Set<String> missingFields = new HashSet<>();
|
Set<String> missingFields = new HashSet<>();
|
||||||
for (String field : tldFields) {
|
for (String field : tldFields) {
|
||||||
if (!tldData.containsKey(field)) {
|
if (!keySet.contains(field)) {
|
||||||
missingFields.add(field);
|
missingFields.add(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.ImmutableSortedMap;
|
import com.google.common.collect.ImmutableSortedMap;
|
||||||
import google.registry.dns.writer.VoidDnsWriter;
|
import google.registry.dns.writer.VoidDnsWriter;
|
||||||
import google.registry.model.EntityTestCase;
|
import google.registry.model.EntityTestCase;
|
||||||
|
import google.registry.model.common.TimedTransitionProperty;
|
||||||
import google.registry.model.domain.token.AllocationToken;
|
import google.registry.model.domain.token.AllocationToken;
|
||||||
import google.registry.model.tld.Tld.TldNotFoundException;
|
import google.registry.model.tld.Tld.TldNotFoundException;
|
||||||
import google.registry.model.tld.Tld.TldState;
|
import google.registry.model.tld.Tld.TldState;
|
||||||
|
@ -149,6 +150,8 @@ public final class TldTest extends EntityTestCase {
|
||||||
.asBuilder()
|
.asBuilder()
|
||||||
.setDnsAPlusAaaaTtl(Duration.standardHours(1))
|
.setDnsAPlusAaaaTtl(Duration.standardHours(1))
|
||||||
.setDnsWriters(ImmutableSet.of("baz", "bang"))
|
.setDnsWriters(ImmutableSet.of("baz", "bang"))
|
||||||
|
.setCreateBillingCostTransitions(
|
||||||
|
TimedTransitionProperty.withInitialValue(Money.of(USD, 13)).toValueMap())
|
||||||
.setEapFeeSchedule(
|
.setEapFeeSchedule(
|
||||||
ImmutableSortedMap.of(
|
ImmutableSortedMap.of(
|
||||||
START_OF_TIME,
|
START_OF_TIME,
|
||||||
|
@ -170,7 +173,12 @@ public final class TldTest extends EntityTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSuccess_tldYamlRoundtrip() throws Exception {
|
void testSuccess_tldYamlRoundtrip() throws Exception {
|
||||||
Tld testTld = createTld("test");
|
Tld testTld =
|
||||||
|
createTld("test")
|
||||||
|
.asBuilder()
|
||||||
|
.setCreateBillingCostTransitions(
|
||||||
|
TimedTransitionProperty.withInitialValue(Money.of(USD, 8)).toValueMap())
|
||||||
|
.build();
|
||||||
ObjectMapper mapper = createObjectMapper();
|
ObjectMapper mapper = createObjectMapper();
|
||||||
String yaml = mapper.writeValueAsString(testTld);
|
String yaml = mapper.writeValueAsString(testTld);
|
||||||
Tld constructedTld = mapper.readValue(yaml, Tld.class);
|
Tld constructedTld = mapper.readValue(yaml, Tld.class);
|
||||||
|
@ -224,6 +232,46 @@ public final class TldTest extends EntityTestCase {
|
||||||
assertThat(registry.getRestoreBillingCost()).isEqualTo(Money.of(USD, 17));
|
assertThat(registry.getRestoreBillingCost()).isEqualTo(Money.of(USD, 17));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSetCreateBillingCostTransitions() {
|
||||||
|
ImmutableSortedMap<DateTime, Money> createCostTransitions =
|
||||||
|
ImmutableSortedMap.of(
|
||||||
|
START_OF_TIME,
|
||||||
|
Money.of(USD, 8),
|
||||||
|
fakeClock.nowUtc(),
|
||||||
|
Money.of(USD, 1),
|
||||||
|
fakeClock.nowUtc().plusMonths(1),
|
||||||
|
Money.of(USD, 2),
|
||||||
|
fakeClock.nowUtc().plusMonths(2),
|
||||||
|
Money.of(USD, 3));
|
||||||
|
Tld registry =
|
||||||
|
Tld.get("tld").asBuilder().setCreateBillingCostTransitions(createCostTransitions).build();
|
||||||
|
assertThat(registry.getCreateBillingCostTransitions()).isEqualTo(createCostTransitions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSetCreateBillingCostTransitionsNegativeCost() throws Exception {
|
||||||
|
ImmutableSortedMap<DateTime, Money> createCostTransitions =
|
||||||
|
ImmutableSortedMap.of(
|
||||||
|
START_OF_TIME,
|
||||||
|
Money.of(USD, 8),
|
||||||
|
fakeClock.nowUtc(),
|
||||||
|
Money.of(USD, 1),
|
||||||
|
fakeClock.nowUtc().plusMonths(1),
|
||||||
|
Money.of(USD, -2),
|
||||||
|
fakeClock.nowUtc().plusMonths(2),
|
||||||
|
Money.of(USD, 3));
|
||||||
|
IllegalArgumentException thrown =
|
||||||
|
assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() ->
|
||||||
|
Tld.get("tld")
|
||||||
|
.asBuilder()
|
||||||
|
.setCreateBillingCostTransitions(createCostTransitions)
|
||||||
|
.build());
|
||||||
|
assertThat(thrown.getMessage()).isEqualTo("Create billing cost cannot be negative");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSettingRestoreBillingCost() {
|
void testSettingRestoreBillingCost() {
|
||||||
Tld registry = Tld.get("tld").asBuilder().setRestoreBillingCost(Money.of(USD, 42)).build();
|
Tld registry = Tld.get("tld").asBuilder().setRestoreBillingCost(Money.of(USD, 42)).build();
|
||||||
|
|
|
@ -25,6 +25,7 @@ import static google.registry.testing.TestDataHelper.loadFile;
|
||||||
import static google.registry.tldconfig.idn.IdnTableEnum.EXTENDED_LATIN;
|
import static google.registry.tldconfig.idn.IdnTableEnum.EXTENDED_LATIN;
|
||||||
import static google.registry.tldconfig.idn.IdnTableEnum.JA;
|
import static google.registry.tldconfig.idn.IdnTableEnum.JA;
|
||||||
import static google.registry.tldconfig.idn.IdnTableEnum.UNCONFUSABLE_LATIN;
|
import static google.registry.tldconfig.idn.IdnTableEnum.UNCONFUSABLE_LATIN;
|
||||||
|
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static org.joda.money.CurrencyUnit.JPY;
|
import static org.joda.money.CurrencyUnit.JPY;
|
||||||
|
@ -39,6 +40,7 @@ import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
|
||||||
import com.google.common.base.Ascii;
|
import com.google.common.base.Ascii;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.ImmutableSortedMap;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.common.testing.TestLogHandler;
|
import com.google.common.testing.TestLogHandler;
|
||||||
import google.registry.model.domain.token.AllocationToken;
|
import google.registry.model.domain.token.AllocationToken;
|
||||||
|
@ -70,6 +72,7 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
|
||||||
command.mapper = objectMapper;
|
command.mapper = objectMapper;
|
||||||
premiumList = persistPremiumList("test", USD, "silver,USD 50", "gold,USD 80");
|
premiumList = persistPremiumList("test", USD, "silver,USD 50", "gold,USD 80");
|
||||||
command.validDnsWriterNames = ImmutableSet.of("VoidDnsWriter", "FooDnsWriter");
|
command.validDnsWriterNames = ImmutableSet.of("VoidDnsWriter", "FooDnsWriter");
|
||||||
|
command.clock = fakeClock;
|
||||||
logger.addHandler(logHandler);
|
logger.addHandler(logHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,6 +176,57 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
|
||||||
assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
|
assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSuccess_fileMissingCreateBillingCostTransitions() throws Exception {
|
||||||
|
createTld("nocreatecostmap");
|
||||||
|
File tldFile = tmpDir.resolve("nocreatecostmap.yaml").toFile();
|
||||||
|
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "nocreatecostmap.yaml"));
|
||||||
|
runCommandForced("--input=" + tldFile);
|
||||||
|
Tld updatedTld = Tld.get("nocreatecostmap");
|
||||||
|
assertThat(updatedTld.getCreateBillingCostTransitions())
|
||||||
|
.isEqualTo(ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 25)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSuccess_fileMissingCreateBillingCostTransitionsRevertsToBasicConstructedMap()
|
||||||
|
throws Exception {
|
||||||
|
ImmutableSortedMap<DateTime, Money> createCostTransitions =
|
||||||
|
ImmutableSortedMap.of(
|
||||||
|
START_OF_TIME,
|
||||||
|
Money.of(USD, 8),
|
||||||
|
fakeClock.nowUtc(),
|
||||||
|
Money.of(USD, 1),
|
||||||
|
fakeClock.nowUtc().plusMonths(1),
|
||||||
|
Money.of(USD, 2),
|
||||||
|
fakeClock.nowUtc().plusMonths(2),
|
||||||
|
Money.of(USD, 3));
|
||||||
|
Tld tld =
|
||||||
|
createTld("nocreatecostmap")
|
||||||
|
.asBuilder()
|
||||||
|
.setCreateBillingCostTransitions(createCostTransitions)
|
||||||
|
.build();
|
||||||
|
assertThat(tld.getCreateBillingCostTransitions().size()).isEqualTo(4);
|
||||||
|
File tldFile = tmpDir.resolve("nocreatecostmap.yaml").toFile();
|
||||||
|
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "nocreatecostmap.yaml"));
|
||||||
|
runCommandForced("--input=" + tldFile);
|
||||||
|
Tld updatedTld = Tld.get("nocreatecostmap");
|
||||||
|
assertThat(updatedTld.getCreateBillingCostTransitions())
|
||||||
|
.isEqualTo(ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 25)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFailure_billingCostTransitionsDoesNotMatchCreateCost() throws Exception {
|
||||||
|
createTld("diffcostmap");
|
||||||
|
File tldFile = tmpDir.resolve("diffcostmap.yaml").toFile();
|
||||||
|
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "diffcostmap.yaml"));
|
||||||
|
IllegalArgumentException thrown =
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
|
||||||
|
assertThat(thrown.getMessage())
|
||||||
|
.isEqualTo(
|
||||||
|
"The createBillingCostTransitions map must have the same current cost as the"
|
||||||
|
+ " createBillingCost field");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testFailure_fileMissingNullableFieldsOnCreate() throws Exception {
|
void testFailure_fileMissingNullableFieldsOnCreate() throws Exception {
|
||||||
File tldFile = tmpDir.resolve("missingnullablefields.yaml").toFile();
|
File tldFile = tmpDir.resolve("missingnullablefields.yaml").toFile();
|
||||||
|
@ -185,6 +239,20 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
|
||||||
+ " premiumListName, currency, numDnsPublishLocks]");
|
+ " premiumListName, currency, numDnsPublishLocks]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSuccess_addCreateBillingCostTransitions() throws Exception {
|
||||||
|
createTld("costmap");
|
||||||
|
File tldFile = tmpDir.resolve("costmap.yaml").toFile();
|
||||||
|
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "costmap.yaml"));
|
||||||
|
runCommandForced("--input=" + tldFile);
|
||||||
|
Tld updatedTld = Tld.get("costmap");
|
||||||
|
ImmutableSortedMap<DateTime, Money> costTransitions =
|
||||||
|
updatedTld.getCreateBillingCostTransitions();
|
||||||
|
assertThat(costTransitions.size()).isEqualTo(3);
|
||||||
|
assertThat(costTransitions.get(START_OF_TIME)).isEqualTo(Money.of(USD, 13));
|
||||||
|
assertThat(costTransitions.get(START_OF_TIME.plusYears(26))).isEqualTo(Money.of(USD, 14));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testFailure_fileMissingNullableFieldOnUpdate() throws Exception {
|
void testFailure_fileMissingNullableFieldOnUpdate() throws Exception {
|
||||||
Tld tld = createTld("missingnullablefields");
|
Tld tld = createTld("missingnullablefields");
|
||||||
|
|
|
@ -19,14 +19,17 @@ import static google.registry.testing.DatabaseHelper.createTlds;
|
||||||
import static google.registry.testing.DatabaseHelper.persistPremiumList;
|
import static google.registry.testing.DatabaseHelper.persistPremiumList;
|
||||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||||
import static google.registry.testing.TestDataHelper.loadFile;
|
import static google.registry.testing.TestDataHelper.loadFile;
|
||||||
|
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||||
import static org.joda.money.CurrencyUnit.USD;
|
import static org.joda.money.CurrencyUnit.USD;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
import com.beust.jcommander.ParameterException;
|
import com.beust.jcommander.ParameterException;
|
||||||
|
import com.google.common.collect.ImmutableSortedMap;
|
||||||
import google.registry.model.EntityYamlUtils;
|
import google.registry.model.EntityYamlUtils;
|
||||||
import google.registry.model.tld.Tld;
|
import google.registry.model.tld.Tld;
|
||||||
import google.registry.model.tld.label.PremiumList;
|
import google.registry.model.tld.label.PremiumList;
|
||||||
import org.joda.money.Money;
|
import org.joda.money.Money;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.Duration;
|
import org.joda.time.Duration;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -48,6 +51,12 @@ class GetTldCommandTest extends CommandTestCase<GetTldCommand> {
|
||||||
.setDnsAPlusAaaaTtl(Duration.standardMinutes(15))
|
.setDnsAPlusAaaaTtl(Duration.standardMinutes(15))
|
||||||
.setDriveFolderId("driveFolder")
|
.setDriveFolderId("driveFolder")
|
||||||
.setCreateBillingCost(Money.of(USD, 25))
|
.setCreateBillingCost(Money.of(USD, 25))
|
||||||
|
.setCreateBillingCostTransitions(
|
||||||
|
ImmutableSortedMap.of(
|
||||||
|
START_OF_TIME,
|
||||||
|
Money.of(USD, 8),
|
||||||
|
DateTime.parse("2020-01-01T00:00:00Z"),
|
||||||
|
Money.of(USD, 25)))
|
||||||
.setPremiumList(premiumList)
|
.setPremiumList(premiumList)
|
||||||
.build());
|
.build());
|
||||||
runCommand("tld");
|
runCommand("tld");
|
||||||
|
|
|
@ -9,6 +9,10 @@ claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
|
||||||
createBillingCost:
|
createBillingCost:
|
||||||
currency: "USD"
|
currency: "USD"
|
||||||
amount: 13.00
|
amount: 13.00
|
||||||
|
createBillingCostTransitions:
|
||||||
|
"1970-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 13.00
|
||||||
creationTime: "1970-01-01T00:00:00.000Z"
|
creationTime: "1970-01-01T00:00:00.000Z"
|
||||||
currency: "USD"
|
currency: "USD"
|
||||||
defaultPromoTokens:
|
defaultPromoTokens:
|
||||||
|
|
75
core/src/test/resources/google/registry/tools/costmap.yaml
Normal file
75
core/src/test/resources/google/registry/tools/costmap.yaml
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
addGracePeriodLength: "PT432000S"
|
||||||
|
allowedFullyQualifiedHostNames:
|
||||||
|
- "foo"
|
||||||
|
allowedRegistrantContactIds: []
|
||||||
|
anchorTenantAddGracePeriodLength: "PT2592000S"
|
||||||
|
autoRenewGracePeriodLength: "PT3888000S"
|
||||||
|
automaticTransferLength: "PT432000S"
|
||||||
|
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
|
||||||
|
createBillingCost:
|
||||||
|
currency: "USD"
|
||||||
|
amount: 14.00
|
||||||
|
createBillingCostTransitions:
|
||||||
|
"1970-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 13.00
|
||||||
|
"1996-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 14.00
|
||||||
|
"2050-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 15.00
|
||||||
|
creationTime: "1970-01-01T00:00:00.000Z"
|
||||||
|
currency: "USD"
|
||||||
|
defaultPromoTokens:
|
||||||
|
- "bbbbb"
|
||||||
|
dnsAPlusAaaaTtl: "PT3600S"
|
||||||
|
dnsDsTtl: null
|
||||||
|
dnsNsTtl: null
|
||||||
|
dnsPaused: false
|
||||||
|
dnsWriters:
|
||||||
|
- "VoidDnsWriter"
|
||||||
|
driveFolderId: null
|
||||||
|
eapFeeSchedule:
|
||||||
|
"1970-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 0.00
|
||||||
|
"2000-06-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 100.00
|
||||||
|
"2000-06-02T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 0.00
|
||||||
|
escrowEnabled: false
|
||||||
|
idnTables:
|
||||||
|
- "EXTENDED_LATIN"
|
||||||
|
- "JA"
|
||||||
|
invoicingEnabled: false
|
||||||
|
lordnUsername: null
|
||||||
|
numDnsPublishLocks: 1
|
||||||
|
pendingDeleteLength: "PT432000S"
|
||||||
|
premiumListName: "test"
|
||||||
|
pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine"
|
||||||
|
redemptionGracePeriodLength: "PT2592000S"
|
||||||
|
registryLockOrUnlockBillingCost:
|
||||||
|
currency: "USD"
|
||||||
|
amount: 0.00
|
||||||
|
renewBillingCostTransitions:
|
||||||
|
"1970-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 11.00
|
||||||
|
renewGracePeriodLength: "PT432000S"
|
||||||
|
reservedListNames: []
|
||||||
|
restoreBillingCost:
|
||||||
|
currency: "USD"
|
||||||
|
amount: 17.00
|
||||||
|
roidSuffix: "COSTMAP"
|
||||||
|
serverStatusChangeBillingCost:
|
||||||
|
currency: "USD"
|
||||||
|
amount: 19.00
|
||||||
|
tldStateTransitions:
|
||||||
|
"1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY"
|
||||||
|
tldStr: "costmap"
|
||||||
|
tldType: "REAL"
|
||||||
|
tldUnicode: "costmap"
|
||||||
|
transferGracePeriodLength: "PT432000S"
|
|
@ -0,0 +1,59 @@
|
||||||
|
addGracePeriodLength: "PT432000S"
|
||||||
|
allowedFullyQualifiedHostNames: []
|
||||||
|
allowedRegistrantContactIds: []
|
||||||
|
anchorTenantAddGracePeriodLength: "PT2592000S"
|
||||||
|
autoRenewGracePeriodLength: "PT3888000S"
|
||||||
|
automaticTransferLength: "PT432000S"
|
||||||
|
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
|
||||||
|
createBillingCost:
|
||||||
|
currency: "USD"
|
||||||
|
amount: 25.00
|
||||||
|
createBillingCostTransitions:
|
||||||
|
"1970-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 12.00
|
||||||
|
creationTime: "2022-09-01T00:00:00.000Z"
|
||||||
|
currency: "USD"
|
||||||
|
defaultPromoTokens: []
|
||||||
|
dnsAPlusAaaaTtl: "PT900S"
|
||||||
|
dnsDsTtl: null
|
||||||
|
dnsNsTtl: null
|
||||||
|
dnsPaused: false
|
||||||
|
dnsWriters:
|
||||||
|
- "VoidDnsWriter"
|
||||||
|
driveFolderId: "driveFolder"
|
||||||
|
eapFeeSchedule:
|
||||||
|
"1970-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 0.00
|
||||||
|
escrowEnabled: false
|
||||||
|
idnTables: []
|
||||||
|
invoicingEnabled: false
|
||||||
|
lordnUsername: null
|
||||||
|
numDnsPublishLocks: 1
|
||||||
|
pendingDeleteLength: "PT432000S"
|
||||||
|
premiumListName: "test"
|
||||||
|
pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine"
|
||||||
|
redemptionGracePeriodLength: "PT2592000S"
|
||||||
|
registryLockOrUnlockBillingCost:
|
||||||
|
currency: "USD"
|
||||||
|
amount: 0.00
|
||||||
|
renewBillingCostTransitions:
|
||||||
|
"1970-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 11.00
|
||||||
|
renewGracePeriodLength: "PT432000S"
|
||||||
|
reservedListNames: []
|
||||||
|
restoreBillingCost:
|
||||||
|
currency: "USD"
|
||||||
|
amount: 17.00
|
||||||
|
roidSuffix: "DIFFMAP"
|
||||||
|
serverStatusChangeBillingCost:
|
||||||
|
currency: "USD"
|
||||||
|
amount: 19.00
|
||||||
|
tldStateTransitions:
|
||||||
|
"1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY"
|
||||||
|
tldStr: "diffcostmap"
|
||||||
|
tldType: "REAL"
|
||||||
|
tldUnicode: "diffcostmap"
|
||||||
|
transferGracePeriodLength: "PT432000S"
|
|
@ -12,6 +12,10 @@ claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
|
||||||
createBillingCost:
|
createBillingCost:
|
||||||
currency: "USD"
|
currency: "USD"
|
||||||
amount: 13.00
|
amount: 13.00
|
||||||
|
createBillingCostTransitions:
|
||||||
|
"1970-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 13.00
|
||||||
creationTime: "2022-09-01T00:00:00.000Z"
|
creationTime: "2022-09-01T00:00:00.000Z"
|
||||||
currency: "USD"
|
currency: "USD"
|
||||||
defaultPromoTokens: []
|
defaultPromoTokens: []
|
||||||
|
|
|
@ -8,6 +8,10 @@ claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
|
||||||
createBillingCost:
|
createBillingCost:
|
||||||
currency: "JPY"
|
currency: "JPY"
|
||||||
amount: 250
|
amount: 250
|
||||||
|
createBillingCostTransitions:
|
||||||
|
"1970-01-01T00:00:00.000Z":
|
||||||
|
currency: "JPY"
|
||||||
|
amount: 250
|
||||||
creationTime: "2022-09-01T00:00:00.000Z"
|
creationTime: "2022-09-01T00:00:00.000Z"
|
||||||
currency: "JPY"
|
currency: "JPY"
|
||||||
defaultPromoTokens: []
|
defaultPromoTokens: []
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
addGracePeriodLength: "PT432000S"
|
||||||
|
allowedFullyQualifiedHostNames: []
|
||||||
|
allowedRegistrantContactIds: []
|
||||||
|
anchorTenantAddGracePeriodLength: "PT2592000S"
|
||||||
|
autoRenewGracePeriodLength: "PT3888000S"
|
||||||
|
automaticTransferLength: "PT432000S"
|
||||||
|
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
|
||||||
|
createBillingCost:
|
||||||
|
currency: "USD"
|
||||||
|
amount: 25.00
|
||||||
|
creationTime: "2022-09-01T00:00:00.000Z"
|
||||||
|
currency: "USD"
|
||||||
|
defaultPromoTokens: []
|
||||||
|
dnsAPlusAaaaTtl: "PT900S"
|
||||||
|
dnsDsTtl: null
|
||||||
|
dnsNsTtl: null
|
||||||
|
dnsPaused: false
|
||||||
|
dnsWriters:
|
||||||
|
- "VoidDnsWriter"
|
||||||
|
driveFolderId: "driveFolder"
|
||||||
|
eapFeeSchedule:
|
||||||
|
"1970-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 0.00
|
||||||
|
escrowEnabled: false
|
||||||
|
idnTables: []
|
||||||
|
invoicingEnabled: false
|
||||||
|
lordnUsername: null
|
||||||
|
numDnsPublishLocks: 1
|
||||||
|
pendingDeleteLength: "PT432000S"
|
||||||
|
premiumListName: "test"
|
||||||
|
pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine"
|
||||||
|
redemptionGracePeriodLength: "PT2592000S"
|
||||||
|
registryLockOrUnlockBillingCost:
|
||||||
|
currency: "USD"
|
||||||
|
amount: 0.00
|
||||||
|
renewBillingCostTransitions:
|
||||||
|
"1970-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 11.00
|
||||||
|
renewGracePeriodLength: "PT432000S"
|
||||||
|
reservedListNames: []
|
||||||
|
restoreBillingCost:
|
||||||
|
currency: "USD"
|
||||||
|
amount: 17.00
|
||||||
|
roidSuffix: "NOCREATE"
|
||||||
|
serverStatusChangeBillingCost:
|
||||||
|
currency: "USD"
|
||||||
|
amount: 19.00
|
||||||
|
tldStateTransitions:
|
||||||
|
"1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY"
|
||||||
|
tldStr: "nocreatecostmap"
|
||||||
|
tldType: "REAL"
|
||||||
|
tldUnicode: "nocreatecostmap"
|
||||||
|
transferGracePeriodLength: "PT432000S"
|
|
@ -8,6 +8,13 @@ claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
|
||||||
createBillingCost:
|
createBillingCost:
|
||||||
currency: "USD"
|
currency: "USD"
|
||||||
amount: 25.00
|
amount: 25.00
|
||||||
|
createBillingCostTransitions:
|
||||||
|
"1970-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 8.00
|
||||||
|
"2020-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 25.00
|
||||||
creationTime: "2022-09-01T00:00:00.000Z"
|
creationTime: "2022-09-01T00:00:00.000Z"
|
||||||
currency: "USD"
|
currency: "USD"
|
||||||
defaultPromoTokens: []
|
defaultPromoTokens: []
|
||||||
|
|
|
@ -8,6 +8,10 @@ claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
|
||||||
createBillingCost:
|
createBillingCost:
|
||||||
currency: "USD"
|
currency: "USD"
|
||||||
amount: 25.00
|
amount: 25.00
|
||||||
|
createBillingCostTransitions:
|
||||||
|
"1970-01-01T00:00:00.000Z":
|
||||||
|
currency: "USD"
|
||||||
|
amount: 25.00
|
||||||
creationTime: "2022-09-01T00:00:00.000Z"
|
creationTime: "2022-09-01T00:00:00.000Z"
|
||||||
currency: "USD"
|
currency: "USD"
|
||||||
defaultPromoTokens: []
|
defaultPromoTokens: []
|
||||||
|
|
|
@ -740,6 +740,7 @@
|
||||||
claims_period_end timestamptz not null,
|
claims_period_end timestamptz not null,
|
||||||
create_billing_cost_amount numeric(19, 2),
|
create_billing_cost_amount numeric(19, 2),
|
||||||
create_billing_cost_currency text,
|
create_billing_cost_currency text,
|
||||||
|
create_billing_cost_transitions hstore,
|
||||||
creation_time timestamptz not null,
|
creation_time timestamptz not null,
|
||||||
currency text not null,
|
currency text not null,
|
||||||
default_promo_tokens text[],
|
default_promo_tokens text[],
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue