1
0
mirror of https://github.com/google/nomulus synced 2026-06-09 16:33:02 +00:00

Compare commits

...

7 Commits

Author SHA1 Message Date
gbrodman 3b841bbb5b Add domain-specific history fields to DomainHistory objects (#794)
* Add domain-specific history fields to DomainHistory objects

* Add javadoc for Hibernate-only methods

* V52 -> V54

* Use only a single DomainTransactionRecord table

* Add nullables and fix up a comment

* V54 -> V55

* Regenerate db schema

* Regen SQL file
2020-09-18 15:55:17 -04:00
gbrodman 798879d031 Fix semantic merge conflict in Registry (#810)
* Fix semantic merge conflict in Registry
2020-09-18 14:40:11 -04:00
gbrodman 1a63d50b82 Create a separate per-tld registry lock/unlock cost (#800)
* Create a separate per-tld registry lock/unlock cost

Currently we use the standard server status change cost for this, but
this might not be ideal at some point in the future if we wish to allow
manual forced updates outside of the standard registry lock system (we
would charge for these manual forced updates, even if we don't charge
for registry locks).

* Remove period
2020-09-18 13:22:29 -04:00
Lai Jiang 054571a625 Update ICANN activity reporting logging (#808)
1. It appears that when we have a 200 response, the response content is
   garbled, but we don't care since we know the request is successful.
   When we have a 400 response, the response is indeed UTF-8 encoded.
   Print the stack trace of the HTTP exception doesn't help anymore.

2. The result code is a complex type which includes the xml element with
   all its attributes, which don't care. We only want to print the
   value.
2020-09-18 11:37:23 -04:00
sarahcaseybot 7468a9915b Migrate Registry objects to a TLD table in Cloud SQL (#803)
* Add TLD table

* Change reservedLists to array

* Change ReservedLists back to a set

* Rename reservedListKeyConverter to ReservedListKeySetConverter

* Add a postload method
2020-09-17 12:47:50 -04:00
Lai Jiang 157d9f75c1 Use the save API version for the HPA controller and the deployment (#807)
This supposedly can fix our deployment problem. Tested on alpha.

Also updated the deployment script to replace the service object as
well.
2020-09-16 09:15:35 -04:00
Lai Jiang b2e4f07bb9 Update IDN tables (#806)
See b/168508962 for context.

1. Changed the contact to iana-contact@google.com
2. Changed the header from "Script" to "Language" for zh-Hans and
   zh-Hant.
3. Commented out the references in zh-Hans and Zh-Hant
2020-09-16 09:15:27 -04:00
52 changed files with 710 additions and 185 deletions
@@ -2,7 +2,7 @@
# Script: Arab
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -2,7 +2,7 @@
# Script: Armn
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -2,7 +2,7 @@
# Script: Beng
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -1,24 +1,24 @@
# Registry: Charleston Road Registry Inc.
# Script: Chinese
# Language: Chinese
# Version: 1.0
# Effective Date: 04-12-2012
#
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
# Notes: This table describes codepoints allowed for the Chinese script.
Reference 0 Unicode 3.2
Reference 1 A Complete Set of Simplified Chinese Characters
Reference 2 Chinese Variants Collation Table
Reference 3 Chinese Big Dictionary
Reference 4 Chinese Relationship Table for Unihan Project
Reference 5 GB2312
Reference 6 General Table for Modern Chinese
Reference 7 International Chinese Standard Big Dictionary
Reference 8 Unihan Database
Reference 9 BIG5
# Reference 0 Unicode 3.2
# Reference 1 A Complete Set of Simplified Chinese Characters
# Reference 2 Chinese Variants Collation Table
# Reference 3 Chinese Big Dictionary
# Reference 4 Chinese Relationship Table for Unihan Project
# Reference 5 GB2312
# Reference 6 General Table for Modern Chinese
# Reference 7 International Chinese Standard Big Dictionary
# Reference 8 Unihan Database
# Reference 9 BIG5
U+002D(0);U+002D(0);
U+0030(0);U+0030(0);
@@ -2,7 +2,7 @@
# Script: Cyrl
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -2,7 +2,7 @@
# Script: Deva
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -2,7 +2,7 @@
# Script: Ethi
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -3,7 +3,7 @@
#
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -3,7 +3,7 @@
# Script: Grek
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -3,7 +3,7 @@
# Script: Guru
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -2,7 +2,7 @@
# Script: Hebr
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -2,7 +2,7 @@
# Script: Knda
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -2,7 +2,7 @@
# Script: Khmr
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
#
# Telephone: +1 (650) 253-0000
@@ -2,7 +2,7 @@
# Script: Kore
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -2,7 +2,7 @@
# Script: Mlym
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -3,7 +3,7 @@
# Version: 1.0
# Effective Date: 04-12-2012
#
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -2,7 +2,7 @@
# Script: Orya
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -2,7 +2,7 @@
# Script: Sinh
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -2,7 +2,7 @@
# Script: Taml
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -2,7 +2,7 @@
# Script: Telu
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -2,7 +2,7 @@
# Script: Thai
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -2,7 +2,7 @@
# Script: Tibt
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
@@ -1,23 +1,23 @@
# Registry: Charleston Road Registry Inc.
# Script: Traditional Chinese
# Language: Traditional Chinese
# Version: 1.0
# Effective Date: 04-12-2012
# Contact: tas-contact.google.com
# Contact: iana-contact@google.com
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
# Telephone: +1 (650) 253-0000
# Website: www.google.com
# Notes: This table describes codepoints allowed for the Traditional Chinese script.
Reference 0 Unicode 3.2
Reference 1 A Complete Set of Simplified Chinese Characters
Reference 2 Chinese Variants Collation Table
Reference 3 Chinese Big Dictionary
Reference 4 Chinese Relationship Table for Unihan Project
Reference 5 GB2312
Reference 6 General Table for Modern Chinese
Reference 7 International Chinese Standard Big Dictionary
Reference 8 Unihan Database
Reference 9 BIG5
# Reference 0 Unicode 3.2
# Reference 1 A Complete Set of Simplified Chinese Characters
# Reference 2 Chinese Variants Collation Table
# Reference 3 Chinese Big Dictionary
# Reference 4 Chinese Relationship Table for Unihan Project
# Reference 5 GB2312
# Reference 6 General Table for Modern Chinese
# Reference 7 International Chinese Standard Big Dictionary
# Reference 8 Unihan Database
# Reference 9 BIG5
U+002D(0);U+002D(0);
U+0030(0);U+0030(0);
@@ -23,12 +23,17 @@ import google.registry.model.EppResource;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.DomainHistory.DomainHistoryId;
import google.registry.model.host.HostResource;
import google.registry.model.reporting.DomainTransactionRecord;
import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey;
import java.io.Serializable;
import java.util.Set;
import javax.annotation.Nullable;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
@@ -37,7 +42,9 @@ import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.PostLoad;
import javax.persistence.Table;
@@ -75,6 +82,50 @@ public class DomainHistory extends HistoryEntry {
@Column(name = "host_repo_id")
Set<VKey<HostResource>> nsHosts;
@Override
@Nullable
@Access(AccessType.PROPERTY)
@AttributeOverrides({
@AttributeOverride(
name = "unit",
column = @Column(name = "historyPeriodUnit")),
@AttributeOverride(
name = "value",
column = @Column(name = "historyPeriodValue"))
})
public Period getPeriod() {
return super.getPeriod();
}
/**
* For transfers, the id of the other registrar.
*
* <p>For requests and cancels, the other registrar is the losing party (because the registrar
* sending the EPP transfer command is the gaining party). For approves and rejects, the other
* registrar is the gaining party.
*/
@Nullable
@Access(AccessType.PROPERTY)
@Column(name = "historyOtherRegistrarId")
public String getOtherRegistrarId() {
return super.getOtherClientId();
}
/**
* Logging field for transaction reporting.
*
* <p>This will be empty for any DomainHistory/HistoryEntry generated before this field was added,
* mid-2017, as well as any action that does not generate billable events (e.g. updates).
*/
@Access(AccessType.PROPERTY)
@OneToMany(cascade = {CascadeType.ALL})
@JoinColumn(name = "historyRevisionId", referencedColumnName = "historyRevisionId")
@JoinColumn(name = "domainRepoId", referencedColumnName = "domainRepoId")
@Override
public Set<DomainTransactionRecord> getDomainTransactionRecords() {
return super.getDomainTransactionRecords();
}
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TempHistorySequenceGenerator")
@Column(name = "historyRevisionId")
@@ -31,9 +31,9 @@ public class Period extends ImmutableObject {
@XmlAttribute
Unit unit;
@XmlValue
Integer value;
@XmlValue Integer value;
@Enumerated(EnumType.STRING)
public Unit getUnit() {
return unit;
}
@@ -42,6 +42,18 @@ public class Period extends ImmutableObject {
return value;
}
/** This method exists solely to satisfy Hibernate. Use {@link #create(int, Unit)} instead. */
@SuppressWarnings("UnusedMethod")
private void setUnit(Unit unit) {
this.unit = unit;
}
/** This method exists solely to satisfy Hibernate. Use {@link #create(int, Unit)} instead. */
@SuppressWarnings("UnusedMethod")
private void setValue(Integer value) {
this.value = value;
}
/** The unit enum. */
public enum Unit {
@XmlEnumValue("y")
@@ -70,6 +70,13 @@ import java.util.concurrent.ExecutionException;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.PostLoad;
import javax.persistence.Transient;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.joda.time.DateTime;
@@ -78,21 +85,31 @@ import org.joda.time.Duration;
/** Persisted per-TLD configuration data. */
@ReportedOn
@Entity
@javax.persistence.Entity(name = "Tld")
public class Registry extends ImmutableObject implements Buildable {
@Parent Key<EntityGroupRoot> parent = getCrossTldKey();
@Parent @Transient Key<EntityGroupRoot> parent = getCrossTldKey();
/**
* The canonical string representation of the TLD associated with this {@link Registry}, which is
* the standard ASCII for regular TLDs and punycoded ASCII for IDN TLDs.
*/
@Id String tldStrId;
@Id
@javax.persistence.Id
@Column(name = "tld_name", nullable = false)
String tldStrId;
/**
* A duplicate of {@link #tldStrId}, to simplify BigQuery reporting since the id field becomes
* {@code __key__.name} rather than being exported as a named field.
*/
String tldStr;
@Transient String tldStr;
/** Sets the Datastore specific field, tldStr, when the entity is loaded from Cloud SQL */
@PostLoad
void postLoad() {
tldStr = tldStrId;
}
/** The suffix that identifies roids as belonging to this specific tld, e.g. -HOW for .how. */
String roidSuffix;
@@ -116,6 +133,7 @@ public class Registry extends ImmutableObject implements Buildable {
public static final Money DEFAULT_RENEW_BILLING_COST = Money.of(USD, 8);
public static final Money DEFAULT_RESTORE_BILLING_COST = Money.of(USD, 100);
public static final Money DEFAULT_SERVER_STATUS_CHANGE_BILLING_COST = Money.of(USD, 20);
public static final Money DEFAULT_REGISTRY_LOCK_OR_UNLOCK_BILLING_COST = Money.of(USD, 0);
/** The type of TLD, which determines things like backups and escrow policy. */
public enum TldType {
@@ -289,6 +307,7 @@ public class Registry extends ImmutableObject implements Buildable {
* <p>All entries of this list must be valid keys for the map of {@code DnsWriter}s injected by
* <code>@Inject Map<String, DnsWriter></code>
*/
@Column(nullable = false)
Set<String> dnsWriters;
/**
@@ -312,6 +331,7 @@ public class Registry extends ImmutableObject implements Buildable {
* <p>Failure to do so can result in parallel writes to the {@link
* google.registry.dns.writer.DnsWriter}, which may be dangerous depending on your implementation.
*/
@Column(nullable = false)
int numDnsPublishLocks;
/** Updates an unset numDnsPublishLocks (0) to the standard default of 1. */
@@ -327,6 +347,7 @@ public class Registry extends ImmutableObject implements Buildable {
* <p>This will be equal to {@link #tldStr} for ASCII TLDs, but will be non-ASCII for IDN TLDs. We
* store this in a field so that it will be retained upon import into BigQuery.
*/
@Column(nullable = false)
String tldUnicode;
/**
@@ -334,9 +355,11 @@ public class Registry extends ImmutableObject implements Buildable {
*
* <p>This is optional; if not configured, then information won't be exported for this TLD.
*/
String driveFolderId;
@Nullable String driveFolderId;
/** The type of the TLD, whether it's real or for testing. */
@Column(nullable = false)
@Enumerated(EnumType.STRING)
TldType tldType = TldType.REAL;
/**
@@ -345,20 +368,24 @@ public class Registry extends ImmutableObject implements Buildable {
* <p>Note that this boolean is the sole determiner on whether invoices should be generated for a
* TLD. This applies to {@link TldType#TEST} TLDs as well.
*/
@Column(nullable = false)
boolean invoicingEnabled = false;
/**
* A property that transitions to different TldStates at different times. Stored as a list of
* TldStateTransition embedded objects using the @Mapify annotation.
*/
@Column(nullable = false)
@Mapify(TimedTransitionProperty.TimeMapper.class)
TimedTransitionProperty<TldState, TldStateTransition> tldStateTransitions =
TimedTransitionProperty.forMapify(DEFAULT_TLD_STATE, TldStateTransition.class);
/** An automatically managed creation timestamp. */
@Column(nullable = false)
CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
/** The set of reserved lists that are applicable to this registry. */
@Column(name = "reserved_list_names", nullable = false)
Set<Key<ReservedList>> reservedLists;
/** Retrieves an ImmutableSet of all ReservedLists associated with this tld. */
@@ -367,12 +394,15 @@ public class Registry extends ImmutableObject implements Buildable {
}
/** The static {@link PremiumList} for this TLD, if there is one. */
@Column(name = "premium_list_name", nullable = true)
Key<PremiumList> premiumList;
/** Should RDE upload a nightly escrow deposit for this TLD? */
@Column(nullable = false)
boolean escrowEnabled = DEFAULT_ESCROW_ENABLED;
/** Whether the pull queue that writes to authoritative DNS is paused for this TLD. */
@Column(nullable = false)
boolean dnsPaused = DEFAULT_DNS_PAUSED;
/**
@@ -381,41 +411,85 @@ public class Registry extends ImmutableObject implements Buildable {
* <p>Domain deletes are free and effective immediately so long as they take place within this
* amount of time following creation.
*/
@Column(nullable = false)
Duration addGracePeriodLength = DEFAULT_ADD_GRACE_PERIOD;
/** The length of the anchor tenant add grace period for this TLD. */
@Column(nullable = false)
Duration anchorTenantAddGracePeriodLength = DEFAULT_ANCHOR_TENANT_ADD_GRACE_PERIOD;
/** The length of the auto renew grace period for this TLD. */
@Column(nullable = false)
Duration autoRenewGracePeriodLength = DEFAULT_AUTO_RENEW_GRACE_PERIOD;
/** The length of the redemption grace period for this TLD. */
@Column(nullable = false)
Duration redemptionGracePeriodLength = DEFAULT_REDEMPTION_GRACE_PERIOD;
/** The length of the renew grace period for this TLD. */
@Column(nullable = false)
Duration renewGracePeriodLength = DEFAULT_RENEW_GRACE_PERIOD;
/** The length of the transfer grace period for this TLD. */
@Column(nullable = false)
Duration transferGracePeriodLength = DEFAULT_TRANSFER_GRACE_PERIOD;
/** The length of time before a transfer is automatically approved for this TLD. */
@Column(nullable = false)
Duration automaticTransferLength = DEFAULT_AUTOMATIC_TRANSFER_LENGTH;
/** The length of time a domain spends in the non-redeemable pending delete phase for this TLD. */
@Column(nullable = false)
Duration pendingDeleteLength = DEFAULT_PENDING_DELETE_LENGTH;
/** The currency unit for all costs associated with this TLD. */
@Column(nullable = false)
CurrencyUnit currency = DEFAULT_CURRENCY;
/** The per-year billing cost for registering a new domain name. */
@AttributeOverrides({
@AttributeOverride(
name = "money.amount",
column = @Column(name = "create_billing_cost_amount")),
@AttributeOverride(
name = "money.currency",
column = @Column(name = "create_billing_cost_currency"))
})
Money createBillingCost = DEFAULT_CREATE_BILLING_COST;
/** The one-time billing cost for restoring a domain name from the redemption grace period. */
@AttributeOverrides({
@AttributeOverride(
name = "money.amount",
column = @Column(name = "restore_billing_cost_amount")),
@AttributeOverride(
name = "money.currency",
column = @Column(name = "restore_billing_cost_currency"))
})
Money restoreBillingCost = DEFAULT_RESTORE_BILLING_COST;
/** The one-time billing cost for changing the server status (i.e. lock). */
@AttributeOverrides({
@AttributeOverride(
name = "money.amount",
column = @Column(name = "server_status_change_billing_cost_amount")),
@AttributeOverride(
name = "money.currency",
column = @Column(name = "server_status_change_billing_cost_currency"))
})
Money serverStatusChangeBillingCost = DEFAULT_SERVER_STATUS_CHANGE_BILLING_COST;
/** The one-time billing cost for a registry lock/unlock action initiated by a registrar. */
@AttributeOverrides({
@AttributeOverride(
name = "money.amount",
column = @Column(name = "registry_lock_or_unlock_cost_amount")),
@AttributeOverride(
name = "money.currency",
column = @Column(name = "registry_lock_or_unlock_cost_currency"))
})
Money registryLockOrUnlockBillingCost = DEFAULT_REGISTRY_LOCK_OR_UNLOCK_BILLING_COST;
/**
* A property that transitions to different renew billing costs at different times. Stored as a
* list of BillingCostTransition embedded objects using the @Mapify annotation.
@@ -424,11 +498,13 @@ public class Registry extends ImmutableObject implements Buildable {
* name. This cost is also used to compute costs for transfers, since each transfer includes a
* renewal to ensure transfers have a cost.
*/
@Column(nullable = false)
@Mapify(TimedTransitionProperty.TimeMapper.class)
TimedTransitionProperty<Money, BillingCostTransition> renewBillingCostTransitions =
TimedTransitionProperty.forMapify(DEFAULT_RENEW_BILLING_COST, BillingCostTransition.class);
/** A property that tracks the EAP fee schedule (if any) for the TLD. */
@Column(nullable = false)
@Mapify(TimedTransitionProperty.TimeMapper.class)
TimedTransitionProperty<Money, BillingCostTransition> eapFeeSchedule =
TimedTransitionProperty.forMapify(DEFAULT_EAP_BILLING_COST, BillingCostTransition.class);
@@ -437,13 +513,14 @@ public class Registry extends ImmutableObject implements Buildable {
String lordnUsername;
/** The end of the claims period (at or after this time, claims no longer applies). */
@Column(nullable = false)
DateTime claimsPeriodEnd = END_OF_TIME;
/** An allow list of clients allowed to be used on domains on this TLD (ignored if empty). */
Set<String> allowedRegistrantContactIds;
@Nullable Set<String> allowedRegistrantContactIds;
/** An allow list of hosts allowed to be used on domains on this TLD (ignored if empty). */
Set<String> allowedFullyQualifiedHostNames;
@Nullable Set<String> allowedFullyQualifiedHostNames;
public String getTldStr() {
return tldStr;
@@ -566,6 +643,11 @@ public class Registry extends ImmutableObject implements Buildable {
return serverStatusChangeBillingCost;
}
/** Returns the cost of a registry lock/unlock. */
public Money getRegistryLockOrUnlockBillingCost() {
return registryLockOrUnlockBillingCost;
}
public ImmutableSortedMap<DateTime, TldState> getTldStateTransitions() {
return tldStateTransitions.toValueMap();
}
@@ -867,6 +949,12 @@ public class Registry extends ImmutableObject implements Buildable {
return this;
}
public Builder setRegistryLockOrUnlockBillingCost(Money amount) {
checkArgument(amount.isPositiveOrZero(), "Registry lock/unlock cost cannot be negative");
getInstance().registryLockOrUnlockBillingCost = amount;
return this;
}
public Builder setLordnUsername(String username) {
getInstance().lordnUsername = username;
return this;
@@ -918,6 +1006,9 @@ public class Registry extends ImmutableObject implements Buildable {
checkArgument(
instance.getServerStatusChangeCost().getCurrencyUnit().equals(instance.currency),
"Server status change cost must be in the registry's currency");
checkArgument(
instance.getRegistryLockOrUnlockBillingCost().getCurrencyUnit().equals(instance.currency),
"Registry lock/unlock cost must be in the registry's currency");
Predicate<Money> currencyCheck =
(Money money) -> money.getCurrencyUnit().equals(instance.currency);
checkArgument(
@@ -19,8 +19,16 @@ import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.annotation.Embed;
import com.googlecode.objectify.annotation.Ignore;
import google.registry.model.Buildable;
import google.registry.model.ImmutableObject;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.joda.time.DateTime;
/**
@@ -34,9 +42,16 @@ import org.joda.time.DateTime;
* uses HistoryEntry.otherClientId because the losing party in a transfer is always the otherClient.
*/
@Embed
@Entity
public class DomainTransactionRecord extends ImmutableObject implements Buildable {
@Id
@Ignore
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
/** The TLD this record operates on. */
@Column(nullable = false)
String tld;
/**
@@ -50,9 +65,12 @@ public class DomainTransactionRecord extends ImmutableObject implements Buildabl
* href="https://www.icann.org/resources/unthemed-pages/registry-agmt-appc-10-2001-05-11-en">
* Grace period spec</a>
*/
@Column(nullable = false)
DateTime reportingTime;
/** The transaction report field we add reportAmount to for this registrar. */
@Column(nullable = false)
@Enumerated(value = EnumType.STRING)
TransactionReportField reportField;
/**
@@ -67,6 +85,7 @@ public class DomainTransactionRecord extends ImmutableObject implements Buildabl
* original SUCCESSFUL transfer counters. Finally, if we explicitly allow a transfer, the report
* amount is 0, as we've already counted the transfer in the original request.
*/
@Column(nullable = false)
Integer reportAmount;
/**
@@ -202,7 +202,7 @@ public class HistoryEntry extends ImmutableObject implements Buildable, Datastor
return id == null ? 0L : id;
}
// This method is required by Hibernate.
/** This method exists solely to satisfy Hibernate. Use the {@link Builder} instead. */
@SuppressWarnings("UnusedMethod")
private void setId(long id) {
this.id = id;
@@ -254,10 +254,28 @@ public class HistoryEntry extends ImmutableObject implements Buildable, Datastor
return requestedByRegistrar;
}
public ImmutableSet<DomainTransactionRecord> getDomainTransactionRecords() {
public Set<DomainTransactionRecord> getDomainTransactionRecords() {
return nullToEmptyImmutableCopy(domainTransactionRecords);
}
/** This method exists solely to satisfy Hibernate. Use the {@link Builder} instead. */
@SuppressWarnings("UnusedMethod")
private void setPeriod(Period period) {
this.period = period;
}
/** This method exists solely to satisfy Hibernate. Use the {@link Builder} instead. */
@SuppressWarnings("UnusedMethod")
private void setOtherRegistrarId(String otherRegistrarId) {
this.otherClientId = otherRegistrarId;
}
/** This method exists solely to satisfy Hibernate. Use the {@link Builder} instead. */
@SuppressWarnings("UnusedMethod")
private void setDomainTransactionRecords(Set<DomainTransactionRecord> domainTransactionRecords) {
this.domainTransactionRecords = ImmutableSet.copyOf(domainTransactionRecords);
}
public static VKey<HistoryEntry> createVKey(Key<HistoryEntry> key) {
// TODO(b/159207551): This will likely need some revision. As it stands, this method was
// introduced purely to facilitate testing of VKey specialization in VKeyTranslatorFactory.
@@ -18,20 +18,19 @@ import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
import com.googlecode.objectify.Key;
import google.registry.model.registry.label.ReservedList;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
/** JPA converter for a {@link Key} containing a {@link ReservedList} */
/** JPA converter for a set of {@link Key} containing a {@link ReservedList} */
@Converter(autoApply = true)
public class ReservedListKeyConverter implements AttributeConverter<Key<ReservedList>, String> {
public class ReservedListKeySetConverter extends StringSetConverterBase<Key<ReservedList>> {
@Override
public String convertToDatabaseColumn(Key<ReservedList> attribute) {
return (attribute == null) ? null : attribute.getName();
String toString(Key<ReservedList> key) {
return key.getName();
}
@Override
public Key<ReservedList> convertToEntityAttribute(String dbData) {
return (dbData == null) ? null : Key.create(getCrossTldKey(), ReservedList.class, dbData);
Key<ReservedList> fromString(String value) {
return Key.create(getCrossTldKey(), ReservedList.class, value);
}
}
@@ -116,14 +116,10 @@ public class IcannHttpReporter {
// 1000 (i. e. success), there is no need to parse it.
if (response.getStatusCode() == HttpStatusCodes.STATUS_CODE_BAD_REQUEST) {
success = false;
// To debug if there is a problem with our parsing, we wrap the response and print the stack
// trace of it. As far as we can tell, the stack trace for such an exception contains the
// response content that is decoded correctly using the expected charset.
new HttpResponseException(response).printStackTrace();
XjcIirdeaResult result = parseResult(content);
logger.atWarning().log(
"PUT rejected, status code %s:\n%s\n%s",
result.getCode(), result.getMsg(), result.getDescription());
result.getCode().getValue(), result.getMsg(), result.getDescription());
}
} finally {
if (response != null) {
@@ -110,6 +110,12 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
description = "One-time billing cost for a server status change")
private Money serverStatusChangeCost;
@Nullable
@Parameter(
names = "--registry_lock_or_unlock_cost",
description = "One-time billing cost for a registry lock or unlock")
private Money registryLockOrUnlockCost;
@Nullable
@Parameter(
names = "--tld_type",
@@ -326,6 +332,8 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
Optional.ofNullable(roidSuffix).ifPresent(builder::setRoidSuffix);
Optional.ofNullable(serverStatusChangeCost)
.ifPresent(builder::setServerStatusChangeBillingCost);
Optional.ofNullable(registryLockOrUnlockCost)
.ifPresent(builder::setRegistryLockOrUnlockBillingCost);
Optional.ofNullable(tldType).ifPresent(builder::setTldType);
Optional.ofNullable(invoicingEnabled).ifPresent(builder::setInvoicingEnabled);
Optional.ofNullable(lordnUsername).ifPresent(u -> builder.setLordnUsername(u.orElse(null)));
@@ -380,7 +380,7 @@ public final class DomainLockUtils {
.setReason(Reason.SERVER_STATUS)
.setTargetId(domain.getForeignKey())
.setClientId(domain.getCurrentSponsorClientId())
.setCost(Registry.get(domain.getTld()).getServerStatusChangeCost())
.setCost(Registry.get(domain.getTld()).getRegistryLockOrUnlockBillingCost())
.setEventTime(now)
.setBillingTime(now)
.setParent(historyEntry)
@@ -45,25 +45,27 @@
<class>google.registry.model.contact.ContactResource</class>
<class>google.registry.model.domain.DomainBase</class>
<class>google.registry.model.domain.DomainHistory</class>
<class>google.registry.model.domain.GracePeriod</class>
<class>google.registry.model.domain.secdns.DelegationSignerData</class>
<class>google.registry.model.domain.token.AllocationToken</class>
<class>google.registry.model.host.HostHistory</class>
<class>google.registry.model.host.HostResource</class>
<class>google.registry.model.registrar.Registrar</class>
<class>google.registry.model.registrar.RegistrarContact</class>
<class>google.registry.model.registry.label.PremiumList</class>
<class>google.registry.model.reporting.Spec11ThreatMatch</class>
<class>google.registry.persistence.transaction.TransactionEntity</class>
<class>google.registry.model.tmch.ClaimsListShard</class>
<class>google.registry.schema.domain.RegistryLock</class>
<class>google.registry.schema.cursor.Cursor</class>
<class>google.registry.schema.server.Lock</class>
<class>google.registry.schema.tld.PremiumEntry</class>
<class>google.registry.model.domain.secdns.DelegationSignerData</class>
<class>google.registry.model.domain.GracePeriod</class>
<class>google.registry.model.poll.PollMessage</class>
<class>google.registry.model.poll.PollMessage$OneTime</class>
<class>google.registry.model.poll.PollMessage$Autorenew</class>
<class>google.registry.model.registrar.Registrar</class>
<class>google.registry.model.registrar.RegistrarContact</class>
<class>google.registry.model.registry.label.PremiumList</class>
<class>google.registry.model.registry.label.ReservedList</class>
<class>google.registry.model.registry.Registry</class>
<class>google.registry.model.reporting.DomainTransactionRecord</class>
<class>google.registry.model.reporting.Spec11ThreatMatch</class>
<class>google.registry.model.tmch.ClaimsListShard</class>
<class>google.registry.persistence.transaction.TransactionEntity</class>
<class>google.registry.schema.cursor.Cursor</class>
<class>google.registry.schema.domain.RegistryLock</class>
<class>google.registry.schema.server.Lock</class>
<class>google.registry.schema.tld.PremiumEntry</class>
<!-- Customized type converters -->
<class>google.registry.persistence.converter.AllocationTokenStatusTransitionConverter</class>
@@ -81,7 +83,7 @@
<class>google.registry.persistence.converter.PostalInfoChoiceListConverter</class>
<class>google.registry.persistence.converter.PremiumListKeyConverter</class>
<class>google.registry.persistence.converter.RegistrarPocSetConverter</class>
<class>google.registry.persistence.converter.ReservedListKeyConverter</class>
<class>google.registry.persistence.converter.ReservedListKeySetConverter</class>
<class>google.registry.persistence.converter.Spec11ThreatMatchThreatTypeSetConverter</class>
<class>google.registry.persistence.converter.StatusValueSetConverter</class>
<class>google.registry.persistence.converter.StringListConverter</class>
@@ -597,6 +597,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
.setRestoreBillingCost(Money.of(EUR, 11))
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
.setRegistryLockOrUnlockBillingCost(Money.of(EUR, 20))
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
.build());
persistDomain();
@@ -615,6 +616,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
.setRestoreBillingCost(Money.of(EUR, 11))
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
.setRegistryLockOrUnlockBillingCost(Money.of(EUR, 20))
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
.build());
persistDomain();
@@ -633,6 +635,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
.setRestoreBillingCost(Money.of(EUR, 11))
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
.setRegistryLockOrUnlockBillingCost(Money.of(EUR, 20))
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
.build());
persistDomain();
@@ -533,6 +533,7 @@ class DomainRestoreRequestFlowTest
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
.setRegistryLockOrUnlockBillingCost(Money.of(EUR, 0))
.build());
EppException thrown = assertThrows(CurrencyUnitMismatchException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
@@ -17,6 +17,7 @@ package google.registry.model.history;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
import static google.registry.model.ImmutableObjectSubject.immutableObjectCorrespondence;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatastoreHelper.newContactResourceWithRoid;
@@ -25,14 +26,18 @@ import static google.registry.testing.DatastoreHelper.newHostResourceWithRoid;
import static google.registry.testing.SqlHelper.saveRegistrar;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.model.EntityTestCase;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainContent;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.Period;
import google.registry.model.eppcommon.Trid;
import google.registry.model.host.HostResource;
import google.registry.model.reporting.DomainTransactionRecord;
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey;
import org.junit.jupiter.api.Test;
@@ -125,10 +130,24 @@ public class DomainHistoryTest extends EntityTestCase {
static void assertDomainHistoriesEqual(DomainHistory one, DomainHistory two) {
assertAboutImmutableObjects()
.that(one)
.isEqualExceptFields(two, "domainContent", "domainRepoId", "parent", "nsHosts");
.isEqualExceptFields(
two, "domainContent", "domainRepoId", "parent", "nsHosts", "domainTransactionRecords");
// NB: the record's ID gets reset by Hibernate, causing the hash code to differ so we have to
// compare it separately
assertThat(one.getDomainTransactionRecords())
.comparingElementsUsing(immutableObjectCorrespondence())
.containsExactlyElementsIn(two.getDomainTransactionRecords());
}
private DomainHistory createDomainHistory(DomainContent domain) {
DomainTransactionRecord transactionRecord =
new DomainTransactionRecord.Builder()
.setTld("tld")
.setReportingTime(fakeClock.nowUtc())
.setReportField(TransactionReportField.NET_ADDS_1_YR)
.setReportAmount(1)
.build();
return new DomainHistory.Builder()
.setType(HistoryEntry.Type.DOMAIN_CREATE)
.setXmlBytes("<xml></xml>".getBytes(UTF_8))
@@ -140,6 +159,9 @@ public class DomainHistoryTest extends EntityTestCase {
.setRequestedByRegistrar(true)
.setDomainContent(domain)
.setDomainRepoId(domain.getRepoId())
.setDomainTransactionRecords(ImmutableSet.of(transactionRecord))
.setOtherClientId("otherClient")
.setPeriod(Period.create(1, Period.Unit.YEARS))
.build();
}
}
@@ -23,6 +23,7 @@ import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABIL
import static google.registry.model.registry.Registry.TldState.PREDELEGATION;
import static google.registry.model.registry.Registry.TldState.QUIET_PERIOD;
import static google.registry.model.registry.Registry.TldState.START_DATE_SUNRISE;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.newRegistry;
import static google.registry.testing.DatastoreHelper.persistPremiumList;
@@ -43,20 +44,40 @@ import google.registry.model.registry.Registry.RegistryNotFoundException;
import google.registry.model.registry.Registry.TldState;
import google.registry.model.registry.label.PremiumList;
import google.registry.model.registry.label.ReservedList;
import google.registry.persistence.VKey;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageExtension;
import java.math.BigDecimal;
import org.joda.money.Money;
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 Registry}. */
class RegistryTest extends EntityTestCase {
public class RegistryTest extends EntityTestCase {
@BeforeEach
void beforeEach() {
createTld("tld");
}
@RegisterExtension
JpaIntegrationWithCoverageExtension jpa =
new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageExtension();
@Test
public void testCloudSqlPersistence() {
ReservedList rl15 = persistReservedList("tld-reserved15", "potato,FULLY_BLOCKED");
PremiumList pl = persistPremiumList("tld2", "lol,USD 50", "cat,USD 700");
Registry registry =
Registry.get("tld").asBuilder().setReservedLists(rl15).setPremiumList(pl).build();
jpaTm().transact(() -> jpaTm().saveNew(registry));
Registry persisted =
jpaTm().transact(() -> jpaTm().load(VKey.createSql(Registry.class, registry.tldStrId)));
assertThat(persisted).isEqualTo(registry);
}
@Test
void testPersistence() {
assertWithMessage("Registry not found").that(Registry.get("tld")).isNotNull();
@@ -1,90 +0,0 @@
// 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.persistence.converter;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import com.googlecode.objectify.Key;
import google.registry.model.ImmutableObject;
import google.registry.model.registry.label.ReservedList;
import google.registry.testing.AppEngineExtension;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link ReservedListKeyConverter}. */
class ReservedListKeyConverterTest {
@RegisterExtension
final AppEngineExtension appEngine =
AppEngineExtension.builder()
.withDatastoreAndCloudSql()
.withJpaUnitTestEntities(ReservedListEntity.class)
.build();
private final ReservedListKeyConverter converter = new ReservedListKeyConverter();
@Test
void convertToDatabaseColumn_returnsNullIfInputIsNull() {
assertThat(converter.convertToDatabaseColumn(null)).isNull();
}
@Test
void convertToDatabaseColumn_convertsCorrectly() {
assertThat(
converter.convertToDatabaseColumn(
Key.create(getCrossTldKey(), ReservedList.class, "testList")))
.isEqualTo("testList");
}
@Test
void convertToEntityAttribute_returnsNullIfInputIsNull() {
assertThat(converter.convertToEntityAttribute(null)).isNull();
}
@Test
void convertToEntityAttribute_convertsCorrectly() {
assertThat(converter.convertToEntityAttribute("testList"))
.isEqualTo(Key.create(getCrossTldKey(), ReservedList.class, "testList"));
}
@Test
void testRoundTrip() {
Key<ReservedList> key = Key.create(getCrossTldKey(), ReservedList.class, "test");
ReservedListEntity testEntity = new ReservedListEntity(key);
jpaTm().transact(() -> jpaTm().getEntityManager().persist(testEntity));
ReservedListEntity persisted =
jpaTm().transact(() -> jpaTm().getEntityManager().find(ReservedListEntity.class, "test"));
assertThat(persisted.reservedList).isEqualTo(key);
}
@Entity(name = "ReservedListEntity")
private static class ReservedListEntity extends ImmutableObject {
@Id String name;
Key<ReservedList> reservedList;
public ReservedListEntity() {}
ReservedListEntity(Key<ReservedList> reservedList) {
this.name = reservedList.getName();
this.reservedList = reservedList;
}
}
}
@@ -0,0 +1,87 @@
// 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.persistence.converter;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import com.googlecode.objectify.Key;
import google.registry.model.ImmutableObject;
import google.registry.model.registry.label.ReservedList;
import google.registry.testing.AppEngineExtension;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.testcontainers.shaded.com.google.common.collect.ImmutableSet;
/** Unit tests for {@link ReservedListKeySetConverter}. */
class ReservedListKeySetConverterTest {
@RegisterExtension
final AppEngineExtension appEngine =
AppEngineExtension.builder()
.withDatastoreAndCloudSql()
.withJpaUnitTestEntities(ReservedListSetEntity.class)
.build();
@Test
void roundTripConversion_returnsSameSet() {
Key<ReservedList> key1 = Key.create(getCrossTldKey(), ReservedList.class, "test1");
Key<ReservedList> key2 = Key.create(getCrossTldKey(), ReservedList.class, "test2");
Key<ReservedList> key3 = Key.create(getCrossTldKey(), ReservedList.class, "test3");
Set<Key<ReservedList>> reservedLists = ImmutableSet.of(key1, key2, key3);
ReservedListSetEntity testEntity = new ReservedListSetEntity(reservedLists);
jpaTm().transact(() -> jpaTm().getEntityManager().persist(testEntity));
ReservedListSetEntity persisted =
jpaTm().transact(() -> jpaTm().getEntityManager().find(ReservedListSetEntity.class, "id"));
assertThat(persisted.reservedList).containsExactly(key1, key2, key3);
}
@Test
void testNullValue_writesAndReadsNullSuccessfully() {
ReservedListSetEntity testEntity = new ReservedListSetEntity(null);
jpaTm().transact(() -> jpaTm().getEntityManager().persist(testEntity));
ReservedListSetEntity persisted =
jpaTm().transact(() -> jpaTm().getEntityManager().find(ReservedListSetEntity.class, "id"));
assertThat(persisted.reservedList).isNull();
}
@Test
void testEmptyCollection_writesAndReadsEmptyCollectionSuccessfully() {
ReservedListSetEntity testEntity = new ReservedListSetEntity(ImmutableSet.of());
jpaTm().transact(() -> jpaTm().getEntityManager().persist(testEntity));
ReservedListSetEntity persisted =
jpaTm().transact(() -> jpaTm().getEntityManager().find(ReservedListSetEntity.class, "id"));
assertThat(persisted.reservedList).isEmpty();
}
@Entity(name = "ReservedListSetEntity")
private static class ReservedListSetEntity extends ImmutableObject {
@Id String name = "id";
Set<Key<ReservedList>> reservedList;
public ReservedListSetEntity() {}
ReservedListSetEntity(Set<Key<ReservedList>> reservedList) {
this.reservedList = reservedList;
}
}
}
@@ -25,6 +25,7 @@ import google.registry.model.history.DomainHistoryTest;
import google.registry.model.history.HostHistoryTest;
import google.registry.model.poll.PollMessageTest;
import google.registry.model.registry.RegistryLockDaoTest;
import google.registry.model.registry.RegistryTest;
import google.registry.model.registry.label.ReservedListSqlDaoTest;
import google.registry.model.reporting.Spec11ThreatMatchTest;
import google.registry.model.tmch.ClaimsListDaoTest;
@@ -86,6 +87,7 @@ import org.junit.runner.RunWith;
PollMessageTest.class,
PremiumListDaoTest.class,
RegistrarDaoTest.class,
RegistryTest.class,
ReservedListSqlDaoTest.class,
RegistryLockDaoTest.class,
Spec11ThreatMatchTest.class,
@@ -69,6 +69,8 @@ class CreateTldCommandTest extends CommandTestCase<CreateTldCommand> {
assertThat(registry.getRedemptionGracePeriodLength())
.isEqualTo(Registry.DEFAULT_REDEMPTION_GRACE_PERIOD);
assertThat(registry.getPendingDeleteLength()).isEqualTo(Registry.DEFAULT_PENDING_DELETE_LENGTH);
assertThat(registry.getRegistryLockOrUnlockBillingCost())
.isEqualTo(Registry.DEFAULT_REGISTRY_LOCK_OR_UNLOCK_BILLING_COST);
}
@Test
@@ -230,6 +232,17 @@ class CreateTldCommandTest extends CommandTestCase<CreateTldCommand> {
.isEqualTo(Money.of(USD, 42.42));
}
@Test
void testSuccess_registryLockOrUnlockCostFlag() throws Exception {
runCommandForced(
"--registry_lock_or_unlock_cost=\"USD 42.42\"",
"--roid_suffix=Q9JYB4C",
"--dns_writers=VoidDnsWriter",
"xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getRegistryLockOrUnlockBillingCost())
.isEqualTo(Money.of(USD, 42.42));
}
@Test
void testSuccess_nonUsdBillingCostFlag() throws Exception {
runCommandForced(
@@ -237,6 +250,7 @@ class CreateTldCommandTest extends CommandTestCase<CreateTldCommand> {
"--restore_billing_cost=\"JPY 67890\"",
"--initial_renew_billing_cost=\"JPY 101112\"",
"--server_status_change_cost=\"JPY 97865\"",
"--registry_lock_or_unlock_cost=\"JPY 9001\"",
"--roid_suffix=Q9JYB4C",
"--dns_writers=VoidDnsWriter",
"xn--q9jyb4c");
@@ -528,7 +528,7 @@ public final class DomainLockUtilsTest {
.setReason(Reason.SERVER_STATUS)
.setTargetId(domain.getForeignKey())
.setClientId(domain.getCurrentSponsorClientId())
.setCost(Registry.get(domain.getTld()).getServerStatusChangeCost())
.setCost(Registry.get(domain.getTld()).getRegistryLockOrUnlockBillingCost())
.setEventTime(clock.nowUtc())
.setBillingTime(clock.nowUtc())
.setParent(entry)
@@ -212,19 +212,21 @@ class UpdateTldCommandTest extends CommandTestCase<UpdateTldCommand> {
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 1)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(JPY)))
.setServerStatusChangeBillingCost(Money.ofMajor(JPY, 1))
.setRegistryLockOrUnlockBillingCost(Money.ofMajor(JPY, 1))
.build());
runCommandForced(
"--create_billing_cost=\"JPY 12345\"",
"--restore_billing_cost=\"JPY 67890\"",
"--renew_billing_cost_transitions=\"0=JPY 101112\"",
"--server_status_change_cost=\"JPY 97865\"",
"--registry_lock_or_unlock_cost=\"JPY 9001\"",
"xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getStandardCreateCost())
.isEqualTo(Money.ofMajor(JPY, 12345));
assertThat(Registry.get("xn--q9jyb4c").getStandardRestoreCost())
.isEqualTo(Money.ofMajor(JPY, 67890));
assertThat(Registry.get("xn--q9jyb4c").getStandardRenewCost(START_OF_TIME))
.isEqualTo(Money.ofMajor(JPY, 101112));
Registry registry = Registry.get("xn--q9jyb4c");
assertThat(registry.getStandardCreateCost()).isEqualTo(Money.ofMajor(JPY, 12345));
assertThat(registry.getStandardRestoreCost()).isEqualTo(Money.ofMajor(JPY, 67890));
assertThat(registry.getStandardRenewCost(START_OF_TIME)).isEqualTo(Money.ofMajor(JPY, 101112));
assertThat(registry.getServerStatusChangeCost()).isEqualTo(Money.ofMajor(JPY, 97865));
assertThat(registry.getRegistryLockOrUnlockBillingCost()).isEqualTo(Money.ofMajor(JPY, 9001));
}
@Test
@@ -317,7 +317,7 @@ final class RegistryLockVerifyActionTest {
.setReason(Reason.SERVER_STATUS)
.setTargetId(domain.getForeignKey())
.setClientId(domain.getCurrentSponsorClientId())
.setCost(Registry.get(domain.getTld()).getServerStatusChangeCost())
.setCost(Registry.get(domain.getTld()).getRegistryLockOrUnlockBillingCost())
.setEventTime(fakeClock.nowUtc())
.setBillingTime(fakeClock.nowUtc())
.setParent(historyEntry)
@@ -640,6 +640,7 @@ class google.registry.model.registry.Registry {
java.util.Set<java.lang.String> dnsWriters;
org.joda.money.CurrencyUnit currency;
org.joda.money.Money createBillingCost;
org.joda.money.Money registryLockOrUnlockBillingCost;
org.joda.money.Money restoreBillingCost;
org.joda.money.Money serverStatusChangeBillingCost;
org.joda.time.DateTime claimsPeriodEnd;
@@ -0,0 +1,55 @@
-- 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.
create table "Tld" (
tld_name text not null,
add_grace_period_length interval not null,
allowed_fully_qualified_host_names text[],
allowed_registrant_contact_ids text[],
anchor_tenant_add_grace_period_length interval not null,
auto_renew_grace_period_length interval not null,
automatic_transfer_length interval not null,
claims_period_end timestamptz not null,
create_billing_cost_amount numeric(19, 2),
create_billing_cost_currency text,
creation_time timestamptz not null,
currency text not null,
dns_paused boolean not null,
dns_writers text[] not null,
drive_folder_id text,
eap_fee_schedule hstore not null,
escrow_enabled boolean not null,
invoicing_enabled boolean not null,
lordn_username text,
num_dns_publish_locks int4 not null,
pending_delete_length interval not null,
premium_list_name text,
pricing_engine_class_name text,
redemption_grace_period_length interval not null,
registry_lock_or_unlock_cost_amount numeric(19, 2),
registry_lock_or_unlock_cost_currency text,
renew_billing_cost_transitions hstore not null,
renew_grace_period_length interval not null,
reserved_list_names text[] not null,
restore_billing_cost_amount numeric(19, 2),
restore_billing_cost_currency text,
roid_suffix text,
server_status_change_billing_cost_amount numeric(19, 2),
server_status_change_billing_cost_currency text,
tld_state_transitions hstore not null,
tld_type text not null,
tld_unicode text not null,
transfer_grace_period_length interval not null,
primary key (tld_name)
);
@@ -0,0 +1,34 @@
-- 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.
ALTER TABLE "DomainHistory" ADD COLUMN history_other_registrar_id text;
ALTER TABLE "DomainHistory" ADD COLUMN history_period_unit text;
ALTER TABLE "DomainHistory" ADD COLUMN history_period_value int4;
CREATE TABLE "DomainTransactionRecord" (
id bigserial NOT NULL,
report_amount int4 NOT NULL,
report_field text NOT NULL,
reporting_time timestamptz NOT NULL,
tld text NOT NULL,
domain_repo_id text,
history_revision_id int8,
PRIMARY KEY (id)
);
ALTER TABLE IF EXISTS "DomainTransactionRecord"
ADD CONSTRAINT FKcjqe54u72kha71vkibvxhjye7
FOREIGN KEY (domain_repo_id, history_revision_id)
REFERENCES "DomainHistory";
@@ -342,6 +342,9 @@ create sequence temp_history_id_sequence start 1 increment 50;
last_epp_update_time timestamptz,
statuses text[],
update_timestamp timestamptz,
history_other_registrar_id text,
history_period_unit text,
history_period_value int4,
primary key (domain_repo_id, history_revision_id)
);
@@ -356,6 +359,17 @@ create sequence temp_history_id_sequence start 1 increment 50;
host_repo_id text
);
create table "DomainTransactionRecord" (
id bigserial not null,
report_amount int4 not null,
report_field text not null,
reporting_time timestamptz not null,
tld text not null,
domain_repo_id text,
history_revision_id int8,
primary key (id)
);
create table "GracePeriod" (
id bigserial not null,
billing_event_id int8,
@@ -580,6 +594,48 @@ create sequence temp_history_id_sequence start 1 increment 50;
primary key (id)
);
create table "Tld" (
tld_name text not null,
add_grace_period_length interval not null,
allowed_fully_qualified_host_names text[],
allowed_registrant_contact_ids text[],
anchor_tenant_add_grace_period_length interval not null,
auto_renew_grace_period_length interval not null,
automatic_transfer_length interval not null,
claims_period_end timestamptz not null,
create_billing_cost_amount numeric(19, 2),
create_billing_cost_currency text,
creation_time timestamptz not null,
currency text not null,
dns_paused boolean not null,
dns_writers text[] not null,
drive_folder_id text,
eap_fee_schedule hstore not null,
escrow_enabled boolean not null,
invoicing_enabled boolean not null,
lordn_username text,
num_dns_publish_locks int4 not null,
pending_delete_length interval not null,
premium_list_name text,
pricing_engine_class_name text,
redemption_grace_period_length interval not null,
registry_lock_or_unlock_cost_amount numeric(19, 2),
registry_lock_or_unlock_cost_currency text,
renew_billing_cost_transitions hstore not null,
renew_grace_period_length interval not null,
reserved_list_names text[] not null,
restore_billing_cost_amount numeric(19, 2),
restore_billing_cost_currency text,
roid_suffix text,
server_status_change_billing_cost_amount numeric(19, 2),
server_status_change_billing_cost_currency text,
tld_state_transitions hstore not null,
tld_type text not null,
tld_unicode text not null,
transfer_grace_period_length interval not null,
primary key (tld_name)
);
create table "Transaction" (
id bigserial not null,
contents bytea,
@@ -654,6 +710,11 @@ create index spec11threatmatch_check_date_idx on "Spec11ThreatMatch" (check_date
foreign key (domain_repo_id)
references "Domain";
alter table if exists "DomainTransactionRecord"
add constraint FKcjqe54u72kha71vkibvxhjye7
foreign key (domain_repo_id, history_revision_id)
references "DomainHistory";
alter table if exists "GracePeriod"
add constraint FK2mys4hojm6ev2g9tmy5aq6m7g
foreign key (domain_repo_id)
@@ -474,7 +474,10 @@ CREATE TABLE public."DomainHistory" (
statuses text[],
update_timestamp timestamp with time zone,
domain_repo_id text NOT NULL,
autorenew_end_time timestamp with time zone
autorenew_end_time timestamp with time zone,
history_other_registrar_id text,
history_period_unit text,
history_period_value integer
);
@@ -499,6 +502,40 @@ CREATE TABLE public."DomainHost" (
);
--
-- Name: DomainTransactionRecord; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public."DomainTransactionRecord" (
id bigint NOT NULL,
report_amount integer NOT NULL,
report_field text NOT NULL,
reporting_time timestamp with time zone NOT NULL,
tld text NOT NULL,
domain_repo_id text,
history_revision_id bigint
);
--
-- Name: DomainTransactionRecord_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE public."DomainTransactionRecord_id_seq"
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: DomainTransactionRecord_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE public."DomainTransactionRecord_id_seq" OWNED BY public."DomainTransactionRecord".id;
--
-- Name: GracePeriod; Type: TABLE; Schema: public; Owner: -
--
@@ -889,6 +926,52 @@ CREATE SEQUENCE public."SafeBrowsingThreat_id_seq"
ALTER SEQUENCE public."SafeBrowsingThreat_id_seq" OWNED BY public."Spec11ThreatMatch".id;
--
-- Name: Tld; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public."Tld" (
tld_name text NOT NULL,
add_grace_period_length interval NOT NULL,
allowed_fully_qualified_host_names text[],
allowed_registrant_contact_ids text[],
anchor_tenant_add_grace_period_length interval NOT NULL,
auto_renew_grace_period_length interval NOT NULL,
automatic_transfer_length interval NOT NULL,
claims_period_end timestamp with time zone NOT NULL,
create_billing_cost_amount numeric(19,2),
create_billing_cost_currency text,
creation_time timestamp with time zone NOT NULL,
currency text NOT NULL,
dns_paused boolean NOT NULL,
dns_writers text[] NOT NULL,
drive_folder_id text,
eap_fee_schedule public.hstore NOT NULL,
escrow_enabled boolean NOT NULL,
invoicing_enabled boolean NOT NULL,
lordn_username text,
num_dns_publish_locks integer NOT NULL,
pending_delete_length interval NOT NULL,
premium_list_name text,
pricing_engine_class_name text,
redemption_grace_period_length interval NOT NULL,
registry_lock_or_unlock_cost_amount numeric(19,2),
registry_lock_or_unlock_cost_currency text,
renew_billing_cost_transitions public.hstore NOT NULL,
renew_grace_period_length interval NOT NULL,
reserved_list_names text[] NOT NULL,
restore_billing_cost_amount numeric(19,2),
restore_billing_cost_currency text,
roid_suffix text,
server_status_change_billing_cost_amount numeric(19,2),
server_status_change_billing_cost_currency text,
tld_state_transitions public.hstore NOT NULL,
tld_type text NOT NULL,
tld_unicode text NOT NULL,
transfer_grace_period_length interval NOT NULL
);
--
-- Name: Transaction; Type: TABLE; Schema: public; Owner: -
--
@@ -970,6 +1053,13 @@ ALTER TABLE ONLY public."BillingRecurrence" ALTER COLUMN billing_recurrence_id S
ALTER TABLE ONLY public."ClaimsList" ALTER COLUMN revision_id SET DEFAULT nextval('public."ClaimsList_revision_id_seq"'::regclass);
--
-- Name: DomainTransactionRecord id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."DomainTransactionRecord" ALTER COLUMN id SET DEFAULT nextval('public."DomainTransactionRecord_id_seq"'::regclass);
--
-- Name: GracePeriod id; Type: DEFAULT; Schema: public; Owner: -
--
@@ -1099,6 +1189,14 @@ ALTER TABLE ONLY public."DomainHistory"
ADD CONSTRAINT "DomainHistory_pkey" PRIMARY KEY (domain_repo_id, history_revision_id);
--
-- Name: DomainTransactionRecord DomainTransactionRecord_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."DomainTransactionRecord"
ADD CONSTRAINT "DomainTransactionRecord_pkey" PRIMARY KEY (id);
--
-- Name: Domain Domain_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@@ -1211,6 +1309,14 @@ ALTER TABLE ONLY public."Spec11ThreatMatch"
ADD CONSTRAINT "SafeBrowsingThreat_pkey" PRIMARY KEY (id);
--
-- Name: Tld Tld_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."Tld"
ADD CONSTRAINT "Tld_pkey" PRIMARY KEY (tld_name);
--
-- Name: Transaction Transaction_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@@ -1929,6 +2035,14 @@ ALTER TABLE ONLY public."DomainHistoryHost"
ADD CONSTRAINT fka9woh3hu8gx5x0vly6bai327n FOREIGN KEY (domain_history_domain_repo_id, domain_history_history_revision_id) REFERENCES public."DomainHistory"(domain_repo_id, history_revision_id);
--
-- Name: DomainTransactionRecord fkcjqe54u72kha71vkibvxhjye7; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."DomainTransactionRecord"
ADD CONSTRAINT fkcjqe54u72kha71vkibvxhjye7 FOREIGN KEY (domain_repo_id, history_revision_id) REFERENCES public."DomainHistory"(domain_repo_id, history_revision_id);
--
-- Name: DomainHost fkfmi7bdink53swivs390m2btxg; Type: FK CONSTRAINT; Schema: public; Owner: -
--
+3 -1
View File
@@ -31,14 +31,16 @@ do
echo "Updating cluster ${parts[0]} in zone ${parts[1]}..."
gcloud container clusters get-credentials "${parts[0]}" \
--project "${project}" --zone "${parts[1]}"
# Kills all running pods, new pods created will be pulling the new image.
sed s/GCP_PROJECT/${project}/g "./kubernetes/proxy-deployment-${environment}.yaml" | \
kubectl replace -f -
kubectl replace -f "./kubernetes/proxy-service.yaml" --force
# Alpha does not have canary
if [[ ${environment} != "alpha" ]]; then
sed s/GCP_PROJECT/${project}/g "./kubernetes/proxy-deployment-${environment}-canary.yaml" | \
kubectl replace -f -
kubectl replace -f "./kubernetes/proxy-service-canary.yaml" --force
fi
# Kills all running pods, new pods created will be pulling the new image.
kubectl delete pods --all
done < <(gcloud container clusters list --project ${project} | grep proxy-cluster)
kubectl config use-context "$current_context"
+1 -1
View File
@@ -43,7 +43,7 @@ metadata:
app: proxy-canary
spec:
scaleTargetRef:
apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
name: proxy-deployment-canary
maxReplicas: 10
+1 -1
View File
@@ -43,7 +43,7 @@ metadata:
app: proxy
spec:
scaleTargetRef:
apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
name: proxy-deployment
maxReplicas: 10