Add a configureTld command that uses YAML files for configuration (#2117)

* Add a configureTld command that uses YAML

* Add more tests and edge case handling

* Add out of order test and fix wrong inject

* small changes

* Add check for ascii

* Add check for ROID suffix
This commit is contained in:
sarahcaseybot
2023-09-06 16:17:22 -04:00
committed by GitHub
parent 001e9363a1
commit 1248c25041
18 changed files with 1144 additions and 15 deletions
@@ -0,0 +1,448 @@
// Copyright 2023 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.domain.token.AllocationToken.TokenType.DEFAULT_PROMO;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.persistPremiumList;
import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.TestDataHelper.loadFile;
import static google.registry.tldconfig.idn.IdnTableEnum.EXTENDED_LATIN;
import static google.registry.tldconfig.idn.IdnTableEnum.JA;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.joda.money.CurrencyUnit.JPY;
import static org.joda.money.CurrencyUnit.USD;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
import com.google.common.base.Ascii;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.Files;
import google.registry.model.EntityYamlUtils;
import google.registry.model.domain.token.AllocationToken;
import google.registry.model.tld.Tld;
import google.registry.model.tld.label.PremiumList;
import google.registry.model.tld.label.PremiumListDao;
import java.io.File;
import org.joda.money.Money;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.testcontainers.shaded.com.google.common.collect.ImmutableMap;
/** Unit tests for {@link ConfigureTldCommand} */
public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand> {
PremiumList premiumList;
ObjectMapper objectMapper = EntityYamlUtils.createObjectMapper();
@BeforeEach
void beforeEach() {
command.mapper = objectMapper;
premiumList = persistPremiumList("test", USD, "silver,USD 50", "gold,USD 80");
command.validDnsWriterNames = ImmutableSet.of("VoidDnsWriter", "FooDnsWriter");
}
private void testTldConfiguredSuccessfully(Tld tld, String filename)
throws JsonProcessingException {
String yaml = objectMapper.writeValueAsString(tld);
assertThat(yaml).isEqualTo(loadFile(getClass(), filename));
}
@Test
void testSuccess_createNewTld() throws Exception {
File tldFile = tmpDir.resolve("tld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
runCommandForced("--input=" + tldFile);
Tld tld = Tld.get("tld");
assertThat(tld).isNotNull();
assertThat(tld.getDriveFolderId()).isEqualTo("driveFolder");
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
testTldConfiguredSuccessfully(tld, "tld.yaml");
}
@Test
void testSuccess_updateTld() throws Exception {
Tld tld = createTld("tld");
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 13));
File tldFile = tmpDir.resolve("tld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
runCommandForced("--input=" + tldFile);
Tld updatedTld = Tld.get("tld");
assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
testTldConfiguredSuccessfully(updatedTld, "tld.yaml");
}
@Test
void testSuccess_outOfOrderFieldsOnCreate() throws Exception {
File tldFile = tmpDir.resolve("outoforderfields.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "outoforderfields.yaml"));
runCommandForced("--input=" + tldFile);
Tld tld = Tld.get("outoforderfields");
// Cannot test that created TLD converted to YAML is equal to original YAML since the created
// TLD's YAML will contain the fields in the correct order
assertThat(tld).isNotNull();
assertThat(tld.getDriveFolderId()).isEqualTo("driveFolder");
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
assertThat(tld.getPremiumListName().get()).isEqualTo("test");
}
@Test
void testSuccess_outOfOrderFieldsOnUpdate() throws Exception {
Tld tld = createTld("outoforderfields");
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 13));
File tldFile = tmpDir.resolve("outoforderfields.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "outoforderfields.yaml"));
runCommandForced("--input=" + tldFile);
Tld updatedTld = Tld.get("outoforderfields");
// Cannot test that created TLD converted to YAML is equal to original YAML since the created
// TLD's YAML will contain the fields in the correct order
assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
}
@Test
void testFailure_fileMissingNullableFieldsOnCreate() throws Exception {
File tldFile = tmpDir.resolve("missingnullablefields.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "missingnullablefields.yaml"));
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage())
.isEqualTo(
"The input file is missing data for the following fields: [tldStateTransitions,"
+ " premiumListName, currency, numDnsPublishLocks]");
}
@Test
void testFailure_fileMissingNullableFieldOnUpdate() throws Exception {
Tld tld = createTld("missingnullablefields");
persistResource(
tld.asBuilder().setNumDnsPublishLocks(5).build()); // numDnsPublishLocks is nullable
File tldFile = tmpDir.resolve("missingnullablefields.yaml").toFile();
Files.asCharSink(tldFile, UTF_8)
.write(
loadFile(
getClass(), "missingnullablefields.yaml")); // file is missing numDnsPublishLocks
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage())
.isEqualTo(
"The input file is missing data for the following fields: [tldStateTransitions,"
+ " premiumListName, currency, numDnsPublishLocks]");
}
@Test
void testSuccess_nullableFieldsAllNullOnCreate() throws Exception {
File tldFile = tmpDir.resolve("nullablefieldsallnull.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "nullablefieldsallnull.yaml"));
runCommandForced("--input=" + tldFile);
Tld tld = Tld.get("nullablefieldsallnull");
assertThat(tld).isNotNull();
assertThat(tld.getDriveFolderId()).isEqualTo(null);
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
// cannot test that created TLD converted to YAML is equal to original YAML since the created
// TLD's YAML will contain empty sets for some of the null fields
assertThat(tld.getIdnTables()).isEmpty();
assertThat(tld.getDefaultPromoTokens()).isEmpty();
}
@Test
void testSuccess_nullableFieldsAllNullOnUpdate() throws Exception {
Tld tld = createTld("nullablefieldsallnull");
persistResource(
tld.asBuilder().setIdnTables(ImmutableSet.of(JA)).setDriveFolderId("drive").build());
File tldFile = tmpDir.resolve("nullablefieldsallnull.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "nullablefieldsallnull.yaml"));
runCommandForced("--input=" + tldFile);
Tld updatedTld = Tld.get("nullablefieldsallnull");
assertThat(updatedTld).isNotNull();
assertThat(updatedTld.getDriveFolderId()).isEqualTo(null);
assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
// cannot test that created TLD converted to YAML is equal to original YAML since the created
// TLD's YAML will contain empty sets for some of the null fields
assertThat(updatedTld.getIdnTables()).isEmpty();
assertThat(updatedTld.getDefaultPromoTokens()).isEmpty();
}
@Test
void testFailure_fileContainsExtraFields() throws Exception {
File tldFile = tmpDir.resolve("extrafield.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "extrafield.yaml"));
assertThrows(UnrecognizedPropertyException.class, () -> runCommandForced("--input=" + tldFile));
}
@Test
void testFailure_fileNameDoesNotMatchTldName() throws Exception {
File tldFile = tmpDir.resolve("othertld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage())
.isEqualTo("The input file name must match the name of the TLD it represents");
}
@Test
void testFailure_tldUnicodeDoesNotMatch() throws Exception {
File tldFile = tmpDir.resolve("badunicode.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "badunicode.yaml"));
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage())
.isEqualTo(
"The value for tldUnicode must equal the unicode representation of the TLD name");
}
@Test
void testFailure_tldUpperCase() throws Exception {
String name = "TLD";
File tldFile = tmpDir.resolve("TLD.yaml").toFile();
Files.asCharSink(tldFile, UTF_8)
.write(
loadFile(
getClass(),
"wildcard.yaml",
ImmutableMap.of(
"TLDSTR", name, "TLDUNICODE", name, "ROIDSUFFIX", Ascii.toUpperCase(name))));
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage())
.isEqualTo(
"The value for tldUnicode must equal the unicode representation of the TLD name");
}
@Test
void testSuccess_asciiNameWithOptionalPunycode() throws Exception {
String name = "xn--q9jyb4c";
File tldFile = tmpDir.resolve(name + ".yaml").toFile();
String fileContents =
loadFile(
getClass(),
"wildcard.yaml",
ImmutableMap.of(
"TLDSTR",
"\"" + name + "\"",
"TLDUNICODE",
"\"みんな\"",
"ROIDSUFFIX",
"\"Q9JYB4C\""));
Files.asCharSink(tldFile, UTF_8).write(fileContents);
runCommandForced("--input=" + tldFile);
Tld tld = Tld.get(name);
assertThat(tld).isNotNull();
assertThat(tld.getDriveFolderId()).isEqualTo("driveFolder");
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
String yaml = objectMapper.writeValueAsString(tld);
assertThat(yaml).isEqualTo(fileContents);
}
@Test
void testFailure_punycodeDoesNotMatch() throws Exception {
String name = "xn--q9jyb4c";
File tldFile = tmpDir.resolve(name + ".yaml").toFile();
String fileContents =
loadFile(
getClass(),
"wildcard.yaml",
ImmutableMap.of(
"TLDSTR",
"\"" + name + "\"",
"TLDUNICODE",
"\"yoyo\"",
"ROIDSUFFIX",
"\"Q9JYB4C\""));
Files.asCharSink(tldFile, UTF_8).write(fileContents);
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage())
.isEqualTo(
"The value for tldUnicode must equal the unicode representation of the TLD name");
}
@Test
void testFailure_punycodeName() throws Exception {
String name = "みんな";
File tldFile = tmpDir.resolve(name + ".yaml").toFile();
String fileContents =
loadFile(
getClass(),
"wildcard.yaml",
ImmutableMap.of(
"TLDSTR",
"\"" + name + "\"",
"TLDUNICODE",
"\"みんな\"",
"ROIDSUFFIX",
"\"Q9JYB4C\""));
Files.asCharSink(tldFile, UTF_8).write(fileContents);
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage()).isEqualTo("A TLD name must be in plain ASCII");
}
@Test
void testFailure_invalidRoidSuffix() throws Exception {
String name = "tld";
File tldFile = tmpDir.resolve("tld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8)
.write(
loadFile(
getClass(),
"wildcard.yaml",
ImmutableMap.of(
"TLDSTR", name, "TLDUNICODE", name, "ROIDSUFFIX", "TLLLLLLLLLLLLLLLLLLLLLLD")));
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage()).isEqualTo("ROID suffix must be in format ^[A-Z\\d_]{1,8}$");
}
@Test
void testFailure_invalidIdnTable() throws Exception {
File tldFile = tmpDir.resolve("badidn.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "badidn.yaml"));
assertThrows(InvalidFormatException.class, () -> runCommandForced("--input=" + tldFile));
}
@Test
void testFailure_tldNameStartsWithNumber() throws Exception {
File tldFile = tmpDir.resolve("1tld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "1tld.yaml"));
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage()).isEqualTo("TLDs cannot begin with a number");
}
@Test
void testFailure_invalidDnsWriter() throws Exception {
command.validDnsWriterNames = ImmutableSet.of("foo");
File tldFile = tmpDir.resolve("tld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage())
.isEqualTo("Invalid DNS writer name(s) specified: [VoidDnsWriter]");
}
@Test
void testFailure_mismatchedCurrencyUnitsOnCreate() throws Exception {
File tldFile = tmpDir.resolve("wrongcurrency.yaml").toFile();
Files.asCharSink(tldFile, UTF_8)
.write(
loadFile(
getClass(),
"wrongcurrency.yaml",
ImmutableMap.of("RESTORECURRENCY", "EUR", "RENEWCURRENCY", "USD")));
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage())
.isEqualTo("restoreBillingCost must use the same currency as the TLD");
File tldFile2 = tmpDir.resolve("wrongcurrency.yaml").toFile();
Files.asCharSink(tldFile2, UTF_8)
.write(
loadFile(
getClass(),
"wrongcurrency.yaml",
ImmutableMap.of("RESTORECURRENCY", "USD", "RENEWCURRENCY", "EUR")));
thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile2));
assertThat(thrown.getMessage())
.isEqualTo(
"All Money values in the renewBillingCostTransitions map must use the TLD's currency"
+ " unit");
}
@Test
void testFailure_mismatchedCurrencyUnitsOnUpdate() throws Exception {
createTld("wrongcurreency");
File tldFile = tmpDir.resolve("wrongcurrency.yaml").toFile();
Files.asCharSink(tldFile, UTF_8)
.write(
loadFile(
getClass(),
"wrongcurrency.yaml",
ImmutableMap.of("RESTORECURRENCY", "EUR", "RENEWCURRENCY", "USD")));
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage())
.isEqualTo("restoreBillingCost must use the same currency as the TLD");
File tldFile2 = tmpDir.resolve("wrongcurrency.yaml").toFile();
Files.asCharSink(tldFile2, UTF_8)
.write(
loadFile(
getClass(),
"wrongcurrency.yaml",
ImmutableMap.of("RESTORECURRENCY", "USD", "RENEWCURRENCY", "EUR")));
thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile2));
assertThat(thrown.getMessage())
.isEqualTo(
"All Money values in the renewBillingCostTransitions map must use the TLD's currency"
+ " unit");
}
@Test
void testSuccess_emptyStringClearsDefaultPromoTokens() throws Exception {
Tld tld = createTld("tld");
AllocationToken defaultToken =
persistResource(
new AllocationToken.Builder()
.setToken("bbbbb")
.setTokenType(DEFAULT_PROMO)
.setAllowedTlds(ImmutableSet.of("tld"))
.build());
persistResource(
tld.asBuilder().setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey())).build());
File tldFile = tmpDir.resolve("tld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
runCommandForced("--input=" + tldFile);
Tld updatedTld = Tld.get("tld");
assertThat(updatedTld.getDefaultPromoTokens()).isEmpty();
testTldConfiguredSuccessfully(updatedTld, "tld.yaml");
}
@Test
void testSuccess_emptyStringClearsIdnTables() throws Exception {
Tld tld = createTld("tld");
persistResource(tld.asBuilder().setIdnTables(ImmutableSet.of(EXTENDED_LATIN, JA)).build());
File tldFile = tmpDir.resolve("tld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
runCommandForced("--input=" + tldFile);
Tld updatedTld = Tld.get("tld");
assertThat(updatedTld.getIdnTables()).isEmpty();
testTldConfiguredSuccessfully(updatedTld, "tld.yaml");
}
@Test
void testFailure_premiumListDoesNotExist() throws Exception {
PremiumListDao.delete(premiumList);
File tldFile = tmpDir.resolve("tld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage()).isEqualTo("The premium list with the name test does not exist");
}
@Test
void testFailure_premiumListWrongCurrency() throws Exception {
PremiumListDao.delete(premiumList);
persistPremiumList("test", JPY, "bronze,JPY 80");
File tldFile = tmpDir.resolve("tld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage()).isEqualTo("The premium list must use the TLD's currency");
}
}
@@ -632,7 +632,7 @@ class CreateTldCommandTest extends CommandTestCase<CreateTldCommand> {
"xn--q9jyb4c", "--roid_suffix=Q9JYB4C", "--dns_writers=Invalid,Deadbeef"));
assertThat(thrown)
.hasMessageThat()
.contains("Invalid DNS writer name(s) specified: [Deadbeef, Invalid]");
.contains("Invalid DNS writer name(s) specified: [Invalid, Deadbeef]");
}
@Test
@@ -16,11 +16,18 @@ package google.registry.tools;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.createTlds;
import static google.registry.testing.DatabaseHelper.persistPremiumList;
import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.TestDataHelper.loadFile;
import static org.joda.money.CurrencyUnit.USD;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.beust.jcommander.ParameterException;
import google.registry.model.EntityYamlUtils;
import google.registry.model.tld.Tld;
import google.registry.model.tld.label.PremiumList;
import org.joda.money.Money;
import org.joda.time.Duration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -34,8 +41,16 @@ class GetTldCommandTest extends CommandTestCase<GetTldCommand> {
@Test
void testSuccess() throws Exception {
createTld("xn--q9jyb4c");
runCommand("xn--q9jyb4c");
Tld tld = createTld("tld");
PremiumList premiumList = persistPremiumList("test", USD, "silver,USD 50", "gold,USD 80");
persistResource(
tld.asBuilder()
.setDnsAPlusAaaaTtl(Duration.millis(900))
.setDriveFolderId("driveFolder")
.setCreateBillingCost(Money.of(USD, 25))
.setPremiumList(premiumList)
.build());
runCommand("tld");
assertInStdout(loadFile(getClass(), "tld.yaml"));
}
@@ -0,0 +1,55 @@
addGracePeriodLength: 432000000
allowedFullyQualifiedHostNames: []
allowedRegistrantContactIds: []
anchorTenantAddGracePeriodLength: 2592000000
autoRenewGracePeriodLength: 3888000000
automaticTransferLength: 432000000
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
createBillingCost:
currency: "USD"
amount: 25.00
creationTime: "2022-09-01T00:00:00.000Z"
currency: "USD"
defaultPromoTokens: []
dnsAPlusAaaaTtl: 900
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: 432000000
premiumListName: "test"
pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine"
redemptionGracePeriodLength: 2592000000
registryLockOrUnlockBillingCost:
currency: "USD"
amount: 0.00
renewBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 11.00
renewGracePeriodLength: 432000000
reservedListNames: []
restoreBillingCost:
currency: "USD"
amount: 17.00
roidSuffix: "1TLD"
serverStatusChangeBillingCost:
currency: "USD"
amount: 19.00
tldStateTransitions:
"1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY"
tldStr: "1tld"
tldType: "REAL"
tldUnicode: "1tld"
transferGracePeriodLength: 432000000
@@ -0,0 +1,56 @@
addGracePeriodLength: 432000000
allowedFullyQualifiedHostNames: []
allowedRegistrantContactIds: []
anchorTenantAddGracePeriodLength: 2592000000
autoRenewGracePeriodLength: 3888000000
automaticTransferLength: 432000000
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
createBillingCost:
currency: "USD"
amount: 25.00
creationTime: "2022-09-01T00:00:00.000Z"
currency: "USD"
defaultPromoTokens: []
dnsAPlusAaaaTtl: 900
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:
- "foo"
invoicingEnabled: false
lordnUsername: null
numDnsPublishLocks: 1
pendingDeleteLength: 432000000
premiumListName: "test"
pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine"
redemptionGracePeriodLength: 2592000000
registryLockOrUnlockBillingCost:
currency: "USD"
amount: 0.00
renewBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 11.00
renewGracePeriodLength: 432000000
reservedListNames: []
restoreBillingCost:
currency: "USD"
amount: 17.00
roidSuffix: "BADIDN"
serverStatusChangeBillingCost:
currency: "USD"
amount: 19.00
tldStateTransitions:
"1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY"
tldStr: "badidn"
tldType: "REAL"
tldUnicode: "badidn"
transferGracePeriodLength: 432000000
@@ -0,0 +1,55 @@
addGracePeriodLength: 432000000
allowedFullyQualifiedHostNames: []
allowedRegistrantContactIds: []
anchorTenantAddGracePeriodLength: 2592000000
autoRenewGracePeriodLength: 3888000000
automaticTransferLength: 432000000
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
createBillingCost:
currency: "USD"
amount: 25.00
creationTime: "2022-09-01T00:00:00.000Z"
currency: "USD"
defaultPromoTokens: []
dnsAPlusAaaaTtl: 900
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: 432000000
premiumListName: "test"
pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine"
redemptionGracePeriodLength: 2592000000
registryLockOrUnlockBillingCost:
currency: "USD"
amount: 0.00
renewBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 11.00
renewGracePeriodLength: 432000000
reservedListNames: []
restoreBillingCost:
currency: "USD"
amount: 17.00
roidSuffix: "TLD"
serverStatusChangeBillingCost:
currency: "USD"
amount: 19.00
tldStateTransitions:
"1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY"
tldStr: "badunicode"
tldType: "REAL"
tldUnicode: "tld"
transferGracePeriodLength: 432000000
@@ -0,0 +1,56 @@
addGracePeriodLength: 432000000
allowedFullyQualifiedHostNames: []
allowedRegistrantContactIds: []
anchorTenantAddGracePeriodLength: 2592000000
autoRenewGracePeriodLength: 3888000000
automaticTransferLength: 432000000
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
createBillingCost:
currency: "USD"
amount: 25.00
creationTime: "2022-09-01T00:00:00.000Z"
currency: "USD"
defaultPromoTokens: []
dnsAPlusAaaaTtl: 900
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: 432000000
premiumListName: "test"
pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine"
redemptionGracePeriodLength: 2592000000
registryLockOrUnlockBillingCost:
currency: "USD"
amount: 0.00
renewBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 11.00
renewGracePeriodLength: 432000000
reservedListNames: []
restoreBillingCost:
currency: "USD"
amount: 17.00
roidSuffix: "EXTRA"
serverStatusChangeBillingCost:
currency: "USD"
amount: 19.00
tldStateTransitions:
"1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY"
tldStr: "extrafield"
tldType: "REAL"
tldUnicode: "extrafield"
transferGracePeriodLength: 432000000
extraField: "hello"
@@ -0,0 +1,50 @@
addGracePeriodLength: 432000000
allowedFullyQualifiedHostNames: []
allowedRegistrantContactIds: []
anchorTenantAddGracePeriodLength: 2592000000
automaticTransferLength: 432000000
autoRenewGracePeriodLength: 3888000000
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
createBillingCost:
currency: "USD"
amount: 25.00
creationTime: "2022-09-01T00:00:00.000Z"
defaultPromoTokens: []
dnsAPlusAaaaTtl: null
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
pendingDeleteLength: 432000000
pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine"
redemptionGracePeriodLength: 2592000000
registryLockOrUnlockBillingCost:
currency: "USD"
amount: 0.00
renewBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 11.00
renewGracePeriodLength: 432000000
reservedListNames: []
restoreBillingCost:
currency: "USD"
amount: 17.00
roidSuffix: "NONULLS"
serverStatusChangeBillingCost:
currency: "USD"
amount: 19.00
tldStr: "missingnullablefields"
tldType: "REAL"
tldUnicode: "missingnullablefields"
transferGracePeriodLength: 432000000
@@ -0,0 +1,55 @@
tldStr: "nullablefieldsallnull"
roidSuffix: "NULLS"
pricingEngineClassName: null
dnsWriters:
- "VoidDnsWriter"
numDnsPublishLocks: 1
dnsAPlusAaaaTtl: null
dnsNsTtl: null
dnsDsTtl: null
tldUnicode: "nullablefieldsallnull"
driveFolderId: null
tldType: "REAL"
invoicingEnabled: false
tldStateTransitions:
"1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY"
creationTime: "2022-09-01T00:00:00.000Z"
reservedListNames: null
premiumListName: null
escrowEnabled: false
dnsPaused: false
addGracePeriodLength: 432000000
anchorTenantAddGracePeriodLength: 2592000000
autoRenewGracePeriodLength: 3888000000
redemptionGracePeriodLength: 2592000000
renewGracePeriodLength: 432000000
transferGracePeriodLength: 432000000
automaticTransferLength: 432000000
pendingDeleteLength: 432000000
currency: "USD"
createBillingCost:
currency: "USD"
amount: 25.00
restoreBillingCost:
currency: "USD"
amount: 17.00
serverStatusChangeBillingCost:
currency: "USD"
amount: 19.00
registryLockOrUnlockBillingCost:
currency: "USD"
amount: 0.00
renewBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 11.00
lordnUsername: null
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
allowedRegistrantContactIds: null
allowedFullyQualifiedHostNames: null
defaultPromoTokens: null
idnTables: null
eapFeeSchedule:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 0.00
@@ -0,0 +1,55 @@
pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine"
numDnsPublishLocks: 1
creationTime: "2022-09-01T00:00:00.000Z"
reservedListNames: []
dnsPaused: false
tldType: "REAL"
escrowEnabled: false
anchorTenantAddGracePeriodLength: 2592000000
dnsNsTtl: null
tldStr: "outoforderfields"
roidSuffix: "TLD"
dnsWriters:
- "VoidDnsWriter"
dnsAPlusAaaaTtl: 900
dnsDsTtl: null
tldUnicode: "outoforderfields"
driveFolderId: "driveFolder"
invoicingEnabled: false
tldStateTransitions:
"1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY"
premiumListName: "test"
addGracePeriodLength: 432000000
autoRenewGracePeriodLength: 3888000000
redemptionGracePeriodLength: 2592000000
renewGracePeriodLength: 432000000
transferGracePeriodLength: 432000000
automaticTransferLength: 432000000
pendingDeleteLength: 432000000
currency: "USD"
createBillingCost:
currency: "USD"
amount: 25.00
restoreBillingCost:
currency: "USD"
amount: 17.00
serverStatusChangeBillingCost:
currency: "USD"
amount: 19.00
registryLockOrUnlockBillingCost:
currency: "USD"
amount: 0.00
renewBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 11.00
lordnUsername: null
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
allowedRegistrantContactIds: []
allowedFullyQualifiedHostNames: []
defaultPromoTokens: []
idnTables: []
eapFeeSchedule:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 0.00
@@ -7,17 +7,17 @@ automaticTransferLength: 432000000
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
createBillingCost:
currency: "USD"
amount: 13.00
amount: 25.00
creationTime: "2022-09-01T00:00:00.000Z"
currency: "USD"
defaultPromoTokens: []
dnsAPlusAaaaTtl: null
dnsAPlusAaaaTtl: 900
dnsDsTtl: null
dnsNsTtl: null
dnsPaused: false
dnsWriters:
- "VoidDnsWriter"
driveFolderId: null
driveFolderId: "driveFolder"
eapFeeSchedule:
"1970-01-01T00:00:00.000Z":
currency: "USD"
@@ -28,7 +28,7 @@ invoicingEnabled: false
lordnUsername: null
numDnsPublishLocks: 1
pendingDeleteLength: 432000000
premiumListName: "xn--q9jyb4c"
premiumListName: "test"
pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine"
redemptionGracePeriodLength: 2592000000
registryLockOrUnlockBillingCost:
@@ -43,13 +43,13 @@ reservedListNames: []
restoreBillingCost:
currency: "USD"
amount: 17.00
roidSuffix: "Q9JYB4C"
roidSuffix: "TLD"
serverStatusChangeBillingCost:
currency: "USD"
amount: 19.00
tldStateTransitions:
"1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY"
tldStr: "xn--q9jyb4c"
tldStr: "tld"
tldType: "REAL"
tldUnicode: "みんな"
transferGracePeriodLength: 432000000
tldUnicode: "tld"
transferGracePeriodLength: 432000000
@@ -0,0 +1,55 @@
addGracePeriodLength: 432000000
allowedFullyQualifiedHostNames: []
allowedRegistrantContactIds: []
anchorTenantAddGracePeriodLength: 2592000000
autoRenewGracePeriodLength: 3888000000
automaticTransferLength: 432000000
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
createBillingCost:
currency: "USD"
amount: 25.00
creationTime: "2022-09-01T00:00:00.000Z"
currency: "USD"
defaultPromoTokens: []
dnsAPlusAaaaTtl: 900
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: 432000000
premiumListName: "test"
pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine"
redemptionGracePeriodLength: 2592000000
registryLockOrUnlockBillingCost:
currency: "USD"
amount: 0.00
renewBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 11.00
renewGracePeriodLength: 432000000
reservedListNames: []
restoreBillingCost:
currency: "USD"
amount: 17.00
roidSuffix: %ROIDSUFFIX%
serverStatusChangeBillingCost:
currency: "USD"
amount: 19.00
tldStateTransitions:
"1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY"
tldStr: %TLDSTR%
tldType: "REAL"
tldUnicode: %TLDUNICODE%
transferGracePeriodLength: 432000000
@@ -0,0 +1,55 @@
tldStr: "wrongcurrency"
roidSuffix: "WRONGCUR"
pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine"
dnsWriters:
- "VoidDnsWriter"
numDnsPublishLocks: 1
dnsAPlusAaaaTtl: 900
dnsNsTtl: null
dnsDsTtl: null
tldUnicode: "wrongcurrency"
driveFolderId: "driveFolder"
tldType: "REAL"
invoicingEnabled: false
tldStateTransitions:
"1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY"
creationTime: "2022-09-01T00:00:00.000Z"
reservedListNames: []
premiumListName: "test"
escrowEnabled: false
dnsPaused: false
addGracePeriodLength: 432000000
anchorTenantAddGracePeriodLength: 2592000000
autoRenewGracePeriodLength: 3888000000
redemptionGracePeriodLength: 2592000000
renewGracePeriodLength: 432000000
transferGracePeriodLength: 432000000
automaticTransferLength: 432000000
pendingDeleteLength: 432000000
currency: "USD"
createBillingCost:
currency: "USD"
amount: 25.00
restoreBillingCost:
currency: %RESTORECURRENCY%
amount: 70.00
serverStatusChangeBillingCost:
currency: "USD"
amount: 19.00
registryLockOrUnlockBillingCost:
currency: "USD"
amount: 0.00
renewBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: %RENEWCURRENCY%
amount: 11.00
lordnUsername: null
claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
allowedRegistrantContactIds: []
allowedFullyQualifiedHostNames: []
defaultPromoTokens: []
idnTables: []
eapFeeSchedule:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 0.00