mirror of
https://github.com/google/nomulus
synced 2026-06-09 16:33:02 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ec7f23e84 | |||
| 7a68b1b6f0 | |||
| 14e593d9e1 | |||
| 2d5de96fbd | |||
| 13d30b0bfb | |||
| b05f6b4ba3 | |||
| 17a1387184 | |||
| 2e230664fd | |||
| 299b093f78 | |||
| 61e7fa89f7 | |||
| 6ab69d4226 | |||
| 0f09a4a0ab | |||
| 95f6ccc657 | |||
| 77fabe4dc4 | |||
| 71fa12f773 | |||
| fd40a6a2b9 | |||
| 71f86c9970 | |||
| 6f75dfd116 | |||
| ad5a74fee9 | |||
| 29b1ec4211 | |||
| 553d5717cb | |||
| 1056fdbb64 |
+2
-2
@@ -191,7 +191,7 @@ allprojects {
|
||||
}
|
||||
|
||||
task runPresubmits(type: Exec) {
|
||||
executable '/usr/bin/python'
|
||||
executable '/usr/bin/python3'
|
||||
args('config/presubmits.py')
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ subprojects {
|
||||
// in the 'configurations' block, the following code must run after
|
||||
// project evaluation, when all configurations have been created.
|
||||
configurations.each {
|
||||
if (it.name != 'dependencyLicenseReport') {
|
||||
if (it.name != 'dependencyLicenseReport' && it.name != 'integration') {
|
||||
it.resolutionStrategy.activateDependencyLocking()
|
||||
}
|
||||
}
|
||||
|
||||
+7
-3
@@ -16,7 +16,7 @@
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import attr
|
||||
import dataclasses
|
||||
import io
|
||||
import os
|
||||
import shutil
|
||||
@@ -25,7 +25,7 @@ import sys
|
||||
from typing import List, Union
|
||||
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
@dataclasses.dataclass
|
||||
class Property:
|
||||
name : str = ''
|
||||
desc : str = ''
|
||||
@@ -39,7 +39,7 @@ class Property:
|
||||
raise ValidationError('value of {self.name} must be "true" or '
|
||||
'"false".')
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
@dataclasses.dataclass
|
||||
class GradleFlag:
|
||||
flags : Union[str, List[str]]
|
||||
desc : str
|
||||
@@ -75,6 +75,7 @@ Pseudo-commands:
|
||||
"""
|
||||
|
||||
# Define all of our special gradle properties here.
|
||||
# TODO(b/169318491): use consistent naming style for properties and variables.
|
||||
PROPERTIES = [
|
||||
Property('mavenUrl',
|
||||
'URL to use for the main maven repository (defaults to maven '
|
||||
@@ -124,6 +125,9 @@ PROPERTIES = [
|
||||
'server/schema integration tests. Please refer to <a '
|
||||
'href="./integration/README.md">integration project</a> for more '
|
||||
'information.'),
|
||||
Property('baseSchemaTag',
|
||||
'The nomulus version tag of the schema for use in the schema'
|
||||
'deployment integration test (:db:schemaIncrementalDeployTest)'),
|
||||
Property('schema_version',
|
||||
'The nomulus version tag of the schema for use in a database'
|
||||
'integration test.'),
|
||||
|
||||
@@ -18,6 +18,7 @@ Error Prone) so we must write them manually.
|
||||
"""
|
||||
|
||||
import os
|
||||
from typing import List, Tuple
|
||||
import sys
|
||||
import re
|
||||
|
||||
@@ -178,6 +179,90 @@ PRESUBMITS = {
|
||||
"JavaScript files should not include console logging."
|
||||
}
|
||||
|
||||
# Note that this regex only works for one kind of Flyway file. If we want to
|
||||
# start using "R" and "U" files we'll need to update this script.
|
||||
FLYWAY_FILE_RX = re.compile(r'V(\d+)__.*')
|
||||
|
||||
|
||||
def get_seqnum(filename: str, location: str) -> int:
|
||||
"""Extracts the sequence number from a filename."""
|
||||
m = FLYWAY_FILE_RX.match(filename)
|
||||
if m is None:
|
||||
raise ValueError('Illegal Flyway filename: %s in %s' % (filename, location))
|
||||
return int(m.group(1))
|
||||
|
||||
|
||||
def files_by_seqnum(files: List[str], location: str) -> List[Tuple[int, str]]:
|
||||
"""Returns the list of seqnum, filename sorted by sequence number."""
|
||||
return [(get_seqnum(filename, location), filename) for filename in files]
|
||||
|
||||
|
||||
def has_valid_order(indexed_files: List[Tuple[int, str]], location: str) -> bool:
|
||||
"""Verify that sequence numbers are in order without gaps or duplicates.
|
||||
|
||||
Args:
|
||||
files: List of seqnum, filename for a list of Flyway files.
|
||||
location: Where the list of files came from (for error reporting).
|
||||
|
||||
Returns:
|
||||
True if the file list is valid.
|
||||
"""
|
||||
last_index = 0
|
||||
valid = True
|
||||
for seqnum, filename in indexed_files:
|
||||
if seqnum == last_index:
|
||||
print('duplicate Flyway file sequence number found in %s: %s' %
|
||||
(location, filename))
|
||||
valid = False
|
||||
elif seqnum < last_index:
|
||||
print('File %s in %s is out of order.' % (filename, location))
|
||||
valid = False
|
||||
elif seqnum != last_index + 1:
|
||||
print('Missing Flyway sequence number %d in %s. Next file is %s' %
|
||||
(last_index + 1, location, filename))
|
||||
valid = False
|
||||
last_index = seqnum
|
||||
return valid
|
||||
|
||||
|
||||
def verify_flyway_index():
|
||||
"""Verifies that the Flyway index file is in sync with the directory."""
|
||||
success = True
|
||||
|
||||
# Sort the files in the Flyway directory by their sequence number.
|
||||
files = sorted(
|
||||
files_by_seqnum(os.listdir('db/src/main/resources/sql/flyway'),
|
||||
'Flyway directory'))
|
||||
|
||||
# Make sure that there are no gaps and no duplicate sequence numbers in the
|
||||
# files themselves.
|
||||
if not has_valid_order(files, 'Flyway directory'):
|
||||
success = False
|
||||
|
||||
# Remove the sequence numbers and compare against the index file contents.
|
||||
files = [filename[1] for filename in sorted(files)]
|
||||
with open('db/src/main/resources/sql/flyway.txt') as index:
|
||||
indexed_files = index.read().splitlines()
|
||||
if files != indexed_files:
|
||||
unindexed = set(files) - set(indexed_files)
|
||||
if unindexed:
|
||||
print('The following Flyway files are not in flyway.txt: %s' % unindexed)
|
||||
|
||||
nonexistent = set(indexed_files) - set(files)
|
||||
if nonexistent:
|
||||
print('The following files are in flyway.txt but not in the Flyway '
|
||||
'directory: %s' % nonexistent)
|
||||
|
||||
# Do an ordering check on the index file (ignore the result, we're failing
|
||||
# anyway).
|
||||
has_valid_order(files_by_seqnum(indexed_files, 'flyway.txt'), 'flyway.txt')
|
||||
success = False
|
||||
|
||||
if not success:
|
||||
print('Please fix any conflicts and run "./nom_build :db:generateFlywayIndex"')
|
||||
|
||||
return not success
|
||||
|
||||
|
||||
def get_files():
|
||||
for root, dirnames, filenames in os.walk("."):
|
||||
@@ -197,5 +282,10 @@ if __name__ == "__main__":
|
||||
failed = True
|
||||
print("%s had errors: \n %s" % (file, "\n ".join(error_messages)))
|
||||
|
||||
# And now for something completely different: check to see if the Flyway
|
||||
# index is up-to-date. It's quicker to do it here than in the unit tests:
|
||||
# when we put it here it fails fast before all of the tests are run.
|
||||
failed |= verify_flyway_index()
|
||||
|
||||
if failed:
|
||||
sys.exit(1)
|
||||
|
||||
@@ -245,6 +245,7 @@ dependencies {
|
||||
testCompile deps['org.apache.ftpserver:ftpserver-core']
|
||||
compile deps['org.apache.httpcomponents:httpclient']
|
||||
compile deps['org.apache.httpcomponents:httpcore']
|
||||
runtime deps['org.apache.logging.log4j:log4j-core']
|
||||
testCompile deps['org.apache.sshd:sshd-core']
|
||||
testCompile deps['org.apache.sshd:sshd-scp']
|
||||
testCompile deps['org.apache.sshd:sshd-sftp']
|
||||
@@ -269,6 +270,8 @@ dependencies {
|
||||
compile deps['org.testcontainers:postgresql']
|
||||
testCompile deps['org.testcontainers:selenium']
|
||||
testCompile deps['org.testcontainers:testcontainers']
|
||||
compile deps['us.fatehi:schemacrawler']
|
||||
compile deps['us.fatehi:schemacrawler-diagram']
|
||||
compile deps['xerces:xmlParserAPIs']
|
||||
compile deps['xpp3:xpp3']
|
||||
// This dependency must come after javax.mail:mail as it would otherwise
|
||||
|
||||
@@ -202,6 +202,7 @@ org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +250,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,6 +200,7 @@ org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -246,5 +247,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -201,8 +201,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -251,5 +253,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -202,6 +202,7 @@ org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +250,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -201,6 +201,7 @@ org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -248,5 +249,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -298,5 +298,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -297,5 +297,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -216,7 +216,8 @@ org.apache.ftpserver:ftplet-api:1.0.6
|
||||
org.apache.ftpserver:ftpserver-core:1.0.6
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.apache.mina:mina-core:2.0.4
|
||||
org.apache.sshd:sshd-core:2.0.0
|
||||
org.apache.sshd:sshd-scp:2.0.0
|
||||
@@ -301,5 +302,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -216,7 +216,8 @@ org.apache.ftpserver:ftplet-api:1.0.6
|
||||
org.apache.ftpserver:ftpserver-core:1.0.6
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.apache.mina:mina-core:2.0.4
|
||||
org.apache.sshd:sshd-core:2.0.0
|
||||
org.apache.sshd:sshd-scp:2.0.0
|
||||
@@ -302,5 +303,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -55,7 +55,7 @@ FROM (
|
||||
FROM
|
||||
`%PROJECT_ID%.%DATASTORE_EXPORT_DATA_SET%.%REGISTRY_TABLE%`
|
||||
WHERE
|
||||
enableInvoicing IS TRUE) ) AS BillingEvent
|
||||
invoicingEnabled IS TRUE) ) AS BillingEvent
|
||||
-- Gather billing ID from registrar table
|
||||
-- This is a 'JOIN' as opposed to 'LEFT JOIN' to filter out
|
||||
-- non-billable registrars
|
||||
|
||||
@@ -67,6 +67,7 @@ import google.registry.model.domain.DomainCommand.Update.AddRemove;
|
||||
import google.registry.model.domain.DomainCommand.Update.Change;
|
||||
import google.registry.model.domain.fee.FeeUpdateCommandExtension;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.domain.secdns.SecDnsUpdateExtension;
|
||||
import google.registry.model.domain.superuser.DomainUpdateSuperuserExtension;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
@@ -238,10 +239,16 @@ public final class DomainUpdateFlow implements TransactionalFlow {
|
||||
DomainBase.Builder domainBuilder =
|
||||
domain
|
||||
.asBuilder()
|
||||
// Handle the secDNS extension.
|
||||
// Handle the secDNS extension. As dsData in secDnsUpdate is read from EPP input and
|
||||
// does not have domainRepoId set, we create a copy of the existing dsData without
|
||||
// domainRepoId for comparison.
|
||||
.setDsData(
|
||||
secDnsUpdate.isPresent()
|
||||
? updateDsData(domain.getDsData(), secDnsUpdate.get())
|
||||
? updateDsData(
|
||||
domain.getDsData().stream()
|
||||
.map(DelegationSignerData::cloneWithoutDomainRepoId)
|
||||
.collect(toImmutableSet()),
|
||||
secDnsUpdate.get())
|
||||
: domain.getDsData())
|
||||
.setLastEppUpdateTime(now)
|
||||
.setLastEppUpdateClientId(clientId)
|
||||
|
||||
@@ -252,7 +252,8 @@ public final class OteAccountBuilder {
|
||||
private void saveAllEntities() {
|
||||
tm().assertInTransaction();
|
||||
|
||||
ImmutableList<Registry> registries = ImmutableList.of(sunriseTld, gaTld, eapTld);
|
||||
// use ImmutableObject instead of Registry so that the Key generation doesn't break
|
||||
ImmutableList<ImmutableObject> registries = ImmutableList.of(sunriseTld, gaTld, eapTld);
|
||||
ImmutableList<RegistrarContact> contacts = contactsBuilder.build();
|
||||
|
||||
if (!replaceExisting) {
|
||||
|
||||
@@ -33,12 +33,14 @@ import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.IgnoreSave;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import com.googlecode.objectify.annotation.OnLoad;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import com.googlecode.objectify.condition.IfNull;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.common.TimeOfYear;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
@@ -57,16 +59,14 @@ import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** A billable event in a domain's lifecycle. */
|
||||
@MappedSuperclass
|
||||
@WithLongVKey
|
||||
public abstract class BillingEvent extends ImmutableObject
|
||||
implements Buildable, TransferServerApproveEntity {
|
||||
|
||||
@@ -108,10 +108,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
}
|
||||
|
||||
/** Entity id. */
|
||||
@Id
|
||||
@javax.persistence.Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
Long id;
|
||||
@Id @javax.persistence.Id Long id;
|
||||
|
||||
@Parent @DoNotHydrate @Transient Key<HistoryEntry> parent;
|
||||
|
||||
@@ -149,6 +146,21 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
@Nullable
|
||||
Set<Flag> flags;
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
parent =
|
||||
Key.create(
|
||||
Key.create(DomainBase.class, domainRepoId),
|
||||
HistoryEntry.class,
|
||||
domainHistoryRevisionId);
|
||||
}
|
||||
|
||||
@OnLoad
|
||||
void onLoad() {
|
||||
domainHistoryRevisionId = parent.getId();
|
||||
domainRepoId = parent.getParent().getName();
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
@@ -245,7 +257,6 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
}
|
||||
|
||||
public B setParent(Key<HistoryEntry> parentKey) {
|
||||
// TODO(shicong): Figure out how to set domainHistoryRevisionId and domainRepoId
|
||||
getInstance().parent = parentKey;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
@@ -258,6 +269,11 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
checkNotNull(instance.eventTime, "Event time must be set");
|
||||
checkNotNull(instance.targetId, "Target ID must be set");
|
||||
checkNotNull(instance.parent, "Parent must be set");
|
||||
checkNotNull(instance.parent.getParent(), "parent.getParent() must be set");
|
||||
checkNotNull(
|
||||
instance.parent.getParent().getName(), "parent.getParent().getName() must be set");
|
||||
instance.domainHistoryRevisionId = instance.parent.getId();
|
||||
instance.domainRepoId = instance.parent.getParent().getName();
|
||||
return super.build();
|
||||
}
|
||||
}
|
||||
@@ -275,6 +291,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
@javax.persistence.Index(columnList = "allocation_token_id")
|
||||
})
|
||||
@AttributeOverride(name = "id", column = @Column(name = "billing_event_id"))
|
||||
@WithLongVKey
|
||||
public static class OneTime extends BillingEvent implements DatastoreAndSqlEntity {
|
||||
|
||||
/** The billable value. */
|
||||
@@ -310,7 +327,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
* Cancellation}s.
|
||||
*/
|
||||
@Column(name = "cancellation_matching_billing_recurrence_id")
|
||||
VKey<? extends BillingEvent> cancellationMatchingBillingEvent;
|
||||
VKey<Recurring> cancellationMatchingBillingEvent;
|
||||
|
||||
/**
|
||||
* The {@link AllocationToken} used in the creation of this event, or null if one was not used.
|
||||
@@ -392,7 +409,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
}
|
||||
|
||||
public Builder setCancellationMatchingBillingEvent(
|
||||
VKey<? extends BillingEvent> cancellationMatchingBillingEvent) {
|
||||
VKey<Recurring> cancellationMatchingBillingEvent) {
|
||||
getInstance().cancellationMatchingBillingEvent = cancellationMatchingBillingEvent;
|
||||
return this;
|
||||
}
|
||||
@@ -451,6 +468,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
@javax.persistence.Index(columnList = "recurrence_time_of_year")
|
||||
})
|
||||
@AttributeOverride(name = "id", column = @Column(name = "billing_recurrence_id"))
|
||||
@WithLongVKey
|
||||
public static class Recurring extends BillingEvent implements DatastoreAndSqlEntity {
|
||||
|
||||
/**
|
||||
@@ -545,6 +563,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
@javax.persistence.Index(columnList = "billingTime")
|
||||
})
|
||||
@AttributeOverride(name = "id", column = @Column(name = "billing_cancellation_id"))
|
||||
@WithLongVKey
|
||||
public static class Cancellation extends BillingEvent implements DatastoreAndSqlEntity {
|
||||
|
||||
/** The billing time of the charge that is being cancelled. */
|
||||
@@ -665,6 +684,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
/** An event representing a modification of an existing one-time billing event. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
@WithLongVKey
|
||||
public static class Modification extends BillingEvent implements DatastoreAndSqlEntity {
|
||||
|
||||
/** The change in cost that should be applied to the original billing event. */
|
||||
|
||||
@@ -14,20 +14,24 @@
|
||||
|
||||
package google.registry.model.contact;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.contact.ContactHistory.ContactHistoryId;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.schema.replay.DatastoreEntity;
|
||||
import google.registry.schema.replay.SqlEntity;
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.PostLoad;
|
||||
|
||||
/**
|
||||
@@ -47,16 +51,25 @@ import javax.persistence.PostLoad;
|
||||
})
|
||||
@EntitySubclass
|
||||
@Access(AccessType.FIELD)
|
||||
public class ContactHistory extends HistoryEntry {
|
||||
@IdClass(ContactHistoryId.class)
|
||||
public class ContactHistory extends HistoryEntry implements SqlEntity {
|
||||
|
||||
// Store ContactBase instead of ContactResource so we don't pick up its @Id
|
||||
@Nullable ContactBase contactBase;
|
||||
|
||||
@Column(nullable = false)
|
||||
VKey<ContactResource> contactRepoId;
|
||||
@Id
|
||||
@Access(AccessType.PROPERTY)
|
||||
public String getContactRepoId() {
|
||||
return parent.getName();
|
||||
}
|
||||
|
||||
/** This method is private because it is only used by Hibernate. */
|
||||
@SuppressWarnings("unused")
|
||||
private void setContactRepoId(String contactRepoId) {
|
||||
parent = Key.create(ContactResource.class, contactRepoId);
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TempHistorySequenceGenerator")
|
||||
@Column(name = "historyRevisionId")
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Override
|
||||
@@ -75,8 +88,14 @@ public class ContactHistory extends HistoryEntry {
|
||||
}
|
||||
|
||||
/** The key to the {@link ContactResource} this is based off of. */
|
||||
public VKey<ContactResource> getContactRepoId() {
|
||||
return contactRepoId;
|
||||
public VKey<ContactResource> getParentVKey() {
|
||||
return VKey.create(ContactResource.class, getContactRepoId());
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} instance for this entity. */
|
||||
public VKey<ContactHistory> createVKey() {
|
||||
return VKey.create(
|
||||
ContactHistory.class, new ContactHistoryId(getContactRepoId(), getId()), Key.create(this));
|
||||
}
|
||||
|
||||
@PostLoad
|
||||
@@ -86,11 +105,70 @@ public class ContactHistory extends HistoryEntry {
|
||||
if (contactBase != null && contactBase.getContactId() == null) {
|
||||
contactBase = null;
|
||||
}
|
||||
// Fill in the full, symmetric, parent repo ID key
|
||||
Key<ContactResource> parentKey =
|
||||
Key.create(ContactResource.class, (String) contactRepoId.getSqlKey());
|
||||
parent = parentKey;
|
||||
contactRepoId = VKey.create(ContactResource.class, contactRepoId.getSqlKey(), parentKey);
|
||||
}
|
||||
|
||||
// In Datastore, save as a HistoryEntry object regardless of this object's type
|
||||
@Override
|
||||
public ImmutableList<DatastoreEntity> toDatastoreEntities() {
|
||||
return ImmutableList.of(asHistoryEntry());
|
||||
}
|
||||
|
||||
/** Class to represent the composite primary key of {@link ContactHistory} entity. */
|
||||
static class ContactHistoryId extends ImmutableObject implements Serializable {
|
||||
|
||||
private String contactRepoId;
|
||||
|
||||
private Long id;
|
||||
|
||||
/** Hibernate requires this default constructor. */
|
||||
private ContactHistoryId() {}
|
||||
|
||||
ContactHistoryId(String contactRepoId, long id) {
|
||||
this.contactRepoId = contactRepoId;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contact repository id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private String getContactRepoId() {
|
||||
return contactRepoId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the history revision id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the contact repository id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate and should not be used
|
||||
* externally to keep immutability.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setContactRepoId(String contactRepoId) {
|
||||
this.contactRepoId = contactRepoId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the history revision id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate and should not be used
|
||||
* externally to keep immutability.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,18 +189,8 @@ public class ContactHistory extends HistoryEntry {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setContactRepoId(VKey<ContactResource> contactRepoId) {
|
||||
getInstance().contactRepoId = contactRepoId;
|
||||
contactRepoId.maybeGetOfyKey().ifPresent(parent -> getInstance().parent = parent);
|
||||
return this;
|
||||
}
|
||||
|
||||
// We can remove this once all HistoryEntries are converted to History objects
|
||||
@Override
|
||||
public Builder setParent(Key<? extends EppResource> parent) {
|
||||
super.setParent(parent);
|
||||
getInstance().contactRepoId =
|
||||
VKey.create(ContactResource.class, parent.getName(), (Key<ContactResource>) parent);
|
||||
public Builder setContactRepoId(String contactRepoId) {
|
||||
getInstance().parent = Key.create(ContactResource.class, contactRepoId);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ public class ContactResource extends ContactBase
|
||||
|
||||
@Override
|
||||
public VKey<ContactResource> createVKey() {
|
||||
// TODO(mmuller): create symmetric keys if we can ever reload both sides.
|
||||
return VKey.create(ContactResource.class, getRepoId(), Key.create(this));
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import google.registry.model.EppResource;
|
||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||
import google.registry.model.annotations.ExternalMessagingName;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithStringVKey;
|
||||
@@ -106,6 +107,32 @@ public class DomainBase extends DomainContent
|
||||
return gracePeriods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of {@link DelegationSignerData} associated with the domain.
|
||||
*
|
||||
* <p>This is the getter method specific for Hibernate to access the field so it is set to
|
||||
* private. The caller can use the public {@link #getDsData()} to get the DS data.
|
||||
*
|
||||
* <p>Note that we need to set `insertable = false, updatable = false` for @JoinColumn, otherwise
|
||||
* Hibernate would try to set the foreign key to null(through an UPDATE TABLE sql) instead of
|
||||
* deleting the whole entry from the table when the {@link DelegationSignerData} is removed from
|
||||
* the set.
|
||||
*/
|
||||
@Access(AccessType.PROPERTY)
|
||||
@OneToMany(
|
||||
cascade = {CascadeType.ALL},
|
||||
fetch = FetchType.EAGER,
|
||||
orphanRemoval = true)
|
||||
@JoinColumn(
|
||||
name = "domainRepoId",
|
||||
referencedColumnName = "repoId",
|
||||
insertable = false,
|
||||
updatable = false)
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private Set<DelegationSignerData> getInternalDelegationSignerData() {
|
||||
return dsData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VKey<DomainBase> createVKey() {
|
||||
return VKey.create(DomainBase.class, getRepoId(), Key.create(this));
|
||||
|
||||
@@ -35,11 +35,13 @@ import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
|
||||
import static google.registry.util.DomainNameUtils.getTldFromDomainName;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.IgnoreSave;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
@@ -49,6 +51,7 @@ import google.registry.flows.ResourceFlowUtils;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.EppResource.ResourceWithTransferData;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.launch.LaunchNotice;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
@@ -57,6 +60,7 @@ import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.DomainTransferData;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.persistence.VKey;
|
||||
@@ -65,7 +69,6 @@ import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
@@ -209,6 +212,15 @@ public class DomainContent extends EppResource
|
||||
@Column(name = "deletion_poll_message_id")
|
||||
VKey<PollMessage.OneTime> deletePollMessage;
|
||||
|
||||
/**
|
||||
* History record for the delete poll message.
|
||||
*
|
||||
* <p>Here so we can restore the original ofy key from sql.
|
||||
*/
|
||||
@Column(name = "deletion_poll_message_history_id")
|
||||
@Ignore
|
||||
Long deletePollMessageHistoryId;
|
||||
|
||||
/**
|
||||
* The recurring billing event associated with this domain's autorenewals.
|
||||
*
|
||||
@@ -220,6 +232,15 @@ public class DomainContent extends EppResource
|
||||
@Column(name = "billing_recurrence_id")
|
||||
VKey<BillingEvent.Recurring> autorenewBillingEvent;
|
||||
|
||||
/**
|
||||
* History record for the autorenew billing event.
|
||||
*
|
||||
* <p>Here so we can restore the original ofy key from sql.
|
||||
*/
|
||||
@Column(name = "billing_recurrence_history_id")
|
||||
@Ignore
|
||||
Long autorenewBillingEventHistoryId;
|
||||
|
||||
/**
|
||||
* The recurring poll message associated with this domain's autorenewals.
|
||||
*
|
||||
@@ -231,6 +252,13 @@ public class DomainContent extends EppResource
|
||||
@Column(name = "autorenew_poll_message_id")
|
||||
VKey<PollMessage.Autorenew> autorenewPollMessage;
|
||||
|
||||
/**
|
||||
* History record for the autorenew poll message.
|
||||
*
|
||||
* <p>Here so we can restore the original ofy key from sql.
|
||||
*/
|
||||
@Ignore Long autorenewPollMessageHistoryId;
|
||||
|
||||
/** The unexpired grace periods for this domain (some of which may not be active yet). */
|
||||
@Transient Set<GracePeriod> gracePeriods;
|
||||
|
||||
@@ -284,10 +312,20 @@ public class DomainContent extends EppResource
|
||||
nullToEmptyImmutableCopy(gracePeriods).stream()
|
||||
.map(gracePeriod -> gracePeriod.cloneWithDomainRepoId(getRepoId()))
|
||||
.collect(toImmutableSet());
|
||||
|
||||
// Restore history record ids.
|
||||
autorenewPollMessageHistoryId = getHistoryId(autorenewPollMessage);
|
||||
autorenewBillingEventHistoryId = getHistoryId(autorenewBillingEvent);
|
||||
deletePollMessageHistoryId = getHistoryId(deletePollMessage);
|
||||
dsData =
|
||||
nullToEmptyImmutableCopy(dsData).stream()
|
||||
.map(dsData -> dsData.cloneWithDomainRepoId(getRepoId()))
|
||||
.collect(toImmutableSet());
|
||||
}
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private final void postLoad() {
|
||||
// Reconstitute the contact list.
|
||||
ImmutableSet.Builder<DesignatedContact> contactsBuilder = new ImmutableSet.Builder<>();
|
||||
|
||||
@@ -306,6 +344,23 @@ public class DomainContent extends EppResource
|
||||
}
|
||||
|
||||
allContacts = contactsBuilder.build();
|
||||
|
||||
// Reconstitute the composite ofy keys from the SQL data.
|
||||
Key<DomainBase> myKey = Key.create(DomainBase.class, getRepoId());
|
||||
deletePollMessage = restoreOfyFrom(myKey, deletePollMessage, deletePollMessageHistoryId);
|
||||
autorenewBillingEvent =
|
||||
restoreOfyFrom(myKey, autorenewBillingEvent, autorenewBillingEventHistoryId);
|
||||
autorenewPollMessage =
|
||||
restoreOfyFrom(myKey, autorenewPollMessage, autorenewPollMessageHistoryId);
|
||||
}
|
||||
|
||||
private <T> VKey<T> restoreOfyFrom(Key<DomainBase> domainKey, VKey<T> key, Long historyId) {
|
||||
if (historyId == null) {
|
||||
// This is a legacy key (or a null key, in which case this works too)
|
||||
return VKey.restoreOfyFrom(key, EntityGroupRoot.class, "per-tld");
|
||||
} else {
|
||||
return VKey.restoreOfyFrom(key, domainKey, HistoryEntry.class, historyId);
|
||||
}
|
||||
}
|
||||
|
||||
public ImmutableSet<String> getSubordinateHosts() {
|
||||
@@ -387,6 +442,12 @@ public class DomainContent extends EppResource
|
||||
this.gracePeriods = gracePeriods;
|
||||
}
|
||||
|
||||
// Hibernate needs this in order to populate dsData but no one else should ever use it
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private void setInternalDelegationSignerData(Set<DelegationSignerData> dsData) {
|
||||
this.dsData = dsData;
|
||||
}
|
||||
|
||||
public final String getCurrentSponsorClientId() {
|
||||
return getPersistedCurrentSponsorClientId();
|
||||
}
|
||||
@@ -655,13 +716,24 @@ public class DomainContent extends EppResource
|
||||
+ " use DomainBase instead");
|
||||
}
|
||||
|
||||
private static Long getHistoryId(VKey<?> key) {
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
Key<?> parent = key.getOfyKey().getParent();
|
||||
if (parent == null || parent.getKind().equals("EntityGroupRoot")) {
|
||||
return null;
|
||||
}
|
||||
return parent.getId();
|
||||
}
|
||||
|
||||
/** Predicate to determine if a given {@link DesignatedContact} is the registrant. */
|
||||
static final Predicate<DesignatedContact> IS_REGISTRANT =
|
||||
(DesignatedContact contact) -> DesignatedContact.Type.REGISTRANT.equals(contact.type);
|
||||
|
||||
/** An override of {@link EppResource#asBuilder} with tighter typing. */
|
||||
@Override
|
||||
public Builder asBuilder() {
|
||||
public Builder<? extends DomainContent, ?> asBuilder() {
|
||||
return new Builder<>(clone(this));
|
||||
}
|
||||
|
||||
@@ -698,10 +770,16 @@ public class DomainContent extends EppResource
|
||||
instance.tld = getTldFromDomainName(instance.fullyQualifiedDomainName);
|
||||
|
||||
T newDomain = super.build();
|
||||
// Hibernate throws exception if gracePeriods is null because we enabled all cascadable
|
||||
// operations and orphan removal.
|
||||
// Hibernate throws exception if gracePeriods or dsData is null because we enabled all
|
||||
// cascadable operations and orphan removal.
|
||||
newDomain.gracePeriods =
|
||||
newDomain.gracePeriods == null ? ImmutableSet.of() : newDomain.gracePeriods;
|
||||
newDomain.dsData =
|
||||
newDomain.dsData == null
|
||||
? ImmutableSet.of()
|
||||
: newDomain.dsData.stream()
|
||||
.map(ds -> ds.cloneWithDomainRepoId(instance.getRepoId()))
|
||||
.collect(toImmutableSet());
|
||||
return newDomain;
|
||||
}
|
||||
|
||||
@@ -824,16 +902,19 @@ public class DomainContent extends EppResource
|
||||
|
||||
public B setDeletePollMessage(VKey<PollMessage.OneTime> deletePollMessage) {
|
||||
getInstance().deletePollMessage = deletePollMessage;
|
||||
getInstance().deletePollMessageHistoryId = getHistoryId(deletePollMessage);
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setAutorenewBillingEvent(VKey<BillingEvent.Recurring> autorenewBillingEvent) {
|
||||
getInstance().autorenewBillingEvent = autorenewBillingEvent;
|
||||
getInstance().autorenewBillingEventHistoryId = getHistoryId(autorenewBillingEvent);
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setAutorenewPollMessage(VKey<PollMessage.Autorenew> autorenewPollMessage) {
|
||||
getInstance().autorenewPollMessage = autorenewPollMessage;
|
||||
getInstance().autorenewPollMessageHistoryId = getHistoryId(autorenewPollMessage);
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,16 +16,18 @@ package google.registry.model.domain;
|
||||
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
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 google.registry.schema.replay.DatastoreEntity;
|
||||
import google.registry.schema.replay.SqlEntity;
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@@ -38,8 +40,6 @@ import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.Index;
|
||||
@@ -67,12 +67,22 @@ import javax.persistence.Table;
|
||||
@EntitySubclass
|
||||
@Access(AccessType.FIELD)
|
||||
@IdClass(DomainHistoryId.class)
|
||||
public class DomainHistory extends HistoryEntry {
|
||||
public class DomainHistory extends HistoryEntry implements SqlEntity {
|
||||
|
||||
// Store DomainContent instead of DomainBase so we don't pick up its @Id
|
||||
@Nullable DomainContent domainContent;
|
||||
|
||||
@Id String domainRepoId;
|
||||
@Id
|
||||
@Access(AccessType.PROPERTY)
|
||||
public String getDomainRepoId() {
|
||||
return parent.getName();
|
||||
}
|
||||
|
||||
/** This method is private because it is only used by Hibernate. */
|
||||
@SuppressWarnings("unused")
|
||||
private void setDomainRepoId(String domainRepoId) {
|
||||
parent = Key.create(DomainBase.class, domainRepoId);
|
||||
}
|
||||
|
||||
// We could have reused domainContent.nsHosts here, but Hibernate throws a weird exception after
|
||||
// we change to use a composite primary key.
|
||||
@@ -128,7 +138,6 @@ public class DomainHistory extends HistoryEntry {
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TempHistorySequenceGenerator")
|
||||
@Column(name = "historyRevisionId")
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Override
|
||||
@@ -152,12 +161,14 @@ public class DomainHistory extends HistoryEntry {
|
||||
}
|
||||
|
||||
/** The key to the {@link DomainBase} this is based off of. */
|
||||
public VKey<DomainBase> getDomainRepoId() {
|
||||
return VKey.create(DomainBase.class, domainRepoId, Key.create(DomainBase.class, domainRepoId));
|
||||
public VKey<DomainBase> getParentVKey() {
|
||||
return VKey.create(DomainBase.class, getDomainRepoId());
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} instance for this entity. */
|
||||
public VKey<DomainHistory> createVKey() {
|
||||
return VKey.createSql(DomainHistory.class, new DomainHistoryId(domainRepoId, getId()));
|
||||
return VKey.create(
|
||||
DomainHistory.class, new DomainHistoryId(getDomainRepoId(), getId()), Key.create(this));
|
||||
}
|
||||
|
||||
@PostLoad
|
||||
@@ -168,9 +179,18 @@ public class DomainHistory extends HistoryEntry {
|
||||
// domainContent with a null object. Unfortunately, the updateTimestamp is never null in SQL.
|
||||
if (domainContent.getDomainName() == null) {
|
||||
domainContent = null;
|
||||
} else {
|
||||
if (domainContent.getRepoId() == null) {
|
||||
domainContent = domainContent.asBuilder().setRepoId(parent.getName()).build();
|
||||
}
|
||||
}
|
||||
}
|
||||
parent = Key.create(DomainBase.class, domainRepoId);
|
||||
}
|
||||
|
||||
// In Datastore, save as a HistoryEntry object regardless of this object's type
|
||||
@Override
|
||||
public ImmutableList<DatastoreEntity> toDatastoreEntities() {
|
||||
return ImmutableList.of(asHistoryEntry());
|
||||
}
|
||||
|
||||
/** Class to represent the composite primary key of {@link DomainHistory} entity. */
|
||||
@@ -188,19 +208,45 @@ public class DomainHistory extends HistoryEntry {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
String getDomainRepoId() {
|
||||
/**
|
||||
* Returns the domain repository id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private String getDomainRepoId() {
|
||||
return domainRepoId;
|
||||
}
|
||||
|
||||
void setDomainRepoId(String domainRepoId) {
|
||||
this.domainRepoId = domainRepoId;
|
||||
}
|
||||
|
||||
long getId() {
|
||||
/**
|
||||
* Returns the history revision id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
void setId(long id) {
|
||||
/**
|
||||
* Sets the domain repository id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate and should not be used
|
||||
* externally to keep immutability.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setDomainRepoId(String domainRepoId) {
|
||||
this.domainRepoId = domainRepoId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the history revision id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate and should not be used
|
||||
* externally to keep immutability.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
@@ -227,17 +273,8 @@ public class DomainHistory extends HistoryEntry {
|
||||
}
|
||||
|
||||
public Builder setDomainRepoId(String domainRepoId) {
|
||||
getInstance().domainRepoId = domainRepoId;
|
||||
getInstance().parent = Key.create(DomainBase.class, domainRepoId);
|
||||
return this;
|
||||
}
|
||||
|
||||
// We can remove this once all HistoryEntries are converted to History objects
|
||||
@Override
|
||||
public Builder setParent(Key<? extends EppResource> parent) {
|
||||
super.setParent(parent);
|
||||
getInstance().domainRepoId = parent.getName();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Recurring;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Index;
|
||||
@@ -37,7 +38,7 @@ import org.joda.time.DateTime;
|
||||
@Embed
|
||||
@Entity
|
||||
@Table(indexes = @Index(columnList = "domainRepoId"))
|
||||
public class GracePeriod extends GracePeriodBase {
|
||||
public class GracePeriod extends GracePeriodBase implements DatastoreAndSqlEntity {
|
||||
|
||||
private static GracePeriod createInternal(
|
||||
GracePeriodStatus type,
|
||||
|
||||
@@ -14,10 +14,22 @@
|
||||
|
||||
package google.registry.model.domain.secdns;
|
||||
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData.DelegationSignerDataId;
|
||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
@@ -30,19 +42,26 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
*/
|
||||
@Embed
|
||||
@XmlType(name = "dsData")
|
||||
@javax.persistence.Entity
|
||||
public class DelegationSignerData extends ImmutableObject {
|
||||
@Entity
|
||||
@Table(indexes = @Index(columnList = "domainRepoId"))
|
||||
@IdClass(DelegationSignerDataId.class)
|
||||
public class DelegationSignerData extends ImmutableObject implements DatastoreAndSqlEntity {
|
||||
|
||||
private DelegationSignerData() {}
|
||||
|
||||
@Ignore @XmlTransient @javax.persistence.Id String domainRepoId;
|
||||
|
||||
/** The identifier for this particular key in the domain. */
|
||||
@javax.persistence.Id int keyTag;
|
||||
@javax.persistence.Id
|
||||
@Column(nullable = false)
|
||||
int keyTag;
|
||||
|
||||
/**
|
||||
* The algorithm used by this key.
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc4034#appendix-A.1">RFC 4034 Appendix A.1</a>
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
@XmlElement(name = "alg")
|
||||
int algorithm;
|
||||
|
||||
@@ -51,6 +70,7 @@ public class DelegationSignerData extends ImmutableObject {
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc4034#appendix-A.2">RFC 4034 Appendix A.2</a>
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
int digestType;
|
||||
|
||||
/**
|
||||
@@ -58,6 +78,7 @@ public class DelegationSignerData extends ImmutableObject {
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc4034#section-5.1.4">RFC 4034 Section 5.1.4</a>
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
@XmlJavaTypeAdapter(HexBinaryAdapter.class)
|
||||
byte[] digest;
|
||||
|
||||
@@ -81,16 +102,34 @@ public class DelegationSignerData extends ImmutableObject {
|
||||
return digest == null ? "" : DatatypeConverter.printHexBinary(digest);
|
||||
}
|
||||
|
||||
public DelegationSignerData cloneWithDomainRepoId(String domainRepoId) {
|
||||
DelegationSignerData clone = clone(this);
|
||||
clone.domainRepoId = checkArgumentNotNull(domainRepoId);
|
||||
return clone;
|
||||
}
|
||||
|
||||
public DelegationSignerData cloneWithoutDomainRepoId() {
|
||||
DelegationSignerData clone = clone(this);
|
||||
clone.domainRepoId = null;
|
||||
return clone;
|
||||
}
|
||||
|
||||
public static DelegationSignerData create(
|
||||
int keyTag, int algorithm, int digestType, byte[] digest) {
|
||||
int keyTag, int algorithm, int digestType, byte[] digest, String domainRepoId) {
|
||||
DelegationSignerData instance = new DelegationSignerData();
|
||||
instance.keyTag = keyTag;
|
||||
instance.algorithm = algorithm;
|
||||
instance.digestType = digestType;
|
||||
instance.digest = digest;
|
||||
instance.domainRepoId = domainRepoId;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static DelegationSignerData create(
|
||||
int keyTag, int algorithm, int digestType, byte[] digest) {
|
||||
return create(keyTag, algorithm, digestType, digest, null);
|
||||
}
|
||||
|
||||
public static DelegationSignerData create(
|
||||
int keyTag, int algorithm, int digestType, String digestAsHex) {
|
||||
return create(keyTag, algorithm, digestType, DatatypeConverter.parseHexBinary(digestAsHex));
|
||||
@@ -106,4 +145,20 @@ public class DelegationSignerData extends ImmutableObject {
|
||||
"%d %d %d %s",
|
||||
this.keyTag, this.algorithm, this.digestType, DatatypeConverter.printHexBinary(digest));
|
||||
}
|
||||
|
||||
static class DelegationSignerDataId extends ImmutableObject implements Serializable {
|
||||
String domainRepoId;
|
||||
int keyTag;
|
||||
|
||||
private DelegationSignerDataId() {}
|
||||
|
||||
private DelegationSignerDataId(String domainRepoId, int keyTag) {
|
||||
this.domainRepoId = domainRepoId;
|
||||
this.keyTag = keyTag;
|
||||
}
|
||||
|
||||
public static DelegationSignerDataId create(String domainRepoId, int keyTag) {
|
||||
return new DelegationSignerDataId(checkArgumentNotNull(domainRepoId), keyTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,10 @@ import static com.google.common.base.Strings.nullToEmpty;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.ContactBase;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainContent;
|
||||
import google.registry.model.host.HostBase;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.translators.EnumToAttributeAdapter.EppEnum;
|
||||
@@ -128,9 +130,15 @@ public enum StatusValue implements EppEnum {
|
||||
|
||||
/** Enum to help clearly list which resource types a status value is allowed to be present on. */
|
||||
private enum AllowedOn {
|
||||
ALL(ContactResource.class, DomainBase.class, HostBase.class, HostResource.class),
|
||||
ALL(
|
||||
ContactBase.class,
|
||||
ContactResource.class,
|
||||
DomainContent.class,
|
||||
DomainBase.class,
|
||||
HostBase.class,
|
||||
HostResource.class),
|
||||
NONE,
|
||||
DOMAINS(DomainBase.class);
|
||||
DOMAINS(DomainContent.class, DomainBase.class);
|
||||
|
||||
private final ImmutableSet<Class<? extends EppResource>> classes;
|
||||
|
||||
|
||||
@@ -14,20 +14,24 @@
|
||||
|
||||
package google.registry.model.host;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.host.HostHistory.HostHistoryId;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.schema.replay.DatastoreEntity;
|
||||
import google.registry.schema.replay.SqlEntity;
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.PostLoad;
|
||||
|
||||
/**
|
||||
@@ -48,16 +52,25 @@ import javax.persistence.PostLoad;
|
||||
})
|
||||
@EntitySubclass
|
||||
@Access(AccessType.FIELD)
|
||||
public class HostHistory extends HistoryEntry {
|
||||
@IdClass(HostHistoryId.class)
|
||||
public class HostHistory extends HistoryEntry implements SqlEntity {
|
||||
|
||||
// Store HostBase instead of HostResource so we don't pick up its @Id
|
||||
@Nullable HostBase hostBase;
|
||||
|
||||
@Column(nullable = false)
|
||||
VKey<HostResource> hostRepoId;
|
||||
@Id
|
||||
@Access(AccessType.PROPERTY)
|
||||
public String getHostRepoId() {
|
||||
return parent.getName();
|
||||
}
|
||||
|
||||
/** This method is private because it is only used by Hibernate. */
|
||||
@SuppressWarnings("unused")
|
||||
private void setHostRepoId(String hostRepoId) {
|
||||
parent = Key.create(HostResource.class, hostRepoId);
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TempHistorySequenceGenerator")
|
||||
@Column(name = "historyRevisionId")
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Override
|
||||
@@ -76,8 +89,14 @@ public class HostHistory extends HistoryEntry {
|
||||
}
|
||||
|
||||
/** The key to the {@link google.registry.model.host.HostResource} this is based off of. */
|
||||
public VKey<HostResource> getHostRepoId() {
|
||||
return hostRepoId;
|
||||
public VKey<HostResource> getParentVKey() {
|
||||
return VKey.create(HostResource.class, getHostRepoId());
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} instance for this entity. */
|
||||
public VKey<HostHistory> createVKey() {
|
||||
return VKey.create(
|
||||
HostHistory.class, new HostHistoryId(getHostRepoId(), getId()), Key.create(this));
|
||||
}
|
||||
|
||||
@PostLoad
|
||||
@@ -87,10 +106,70 @@ public class HostHistory extends HistoryEntry {
|
||||
if (hostBase != null && hostBase.getHostName() == null) {
|
||||
hostBase = null;
|
||||
}
|
||||
// Fill in the full, symmetric, parent repo ID key
|
||||
Key<HostResource> parentKey = Key.create(HostResource.class, (String) hostRepoId.getSqlKey());
|
||||
parent = parentKey;
|
||||
hostRepoId = VKey.create(HostResource.class, hostRepoId.getSqlKey(), parentKey);
|
||||
}
|
||||
|
||||
// In Datastore, save as a HistoryEntry object regardless of this object's type
|
||||
@Override
|
||||
public ImmutableList<DatastoreEntity> toDatastoreEntities() {
|
||||
return ImmutableList.of(asHistoryEntry());
|
||||
}
|
||||
|
||||
/** Class to represent the composite primary key of {@link HostHistory} entity. */
|
||||
static class HostHistoryId extends ImmutableObject implements Serializable {
|
||||
|
||||
private String hostRepoId;
|
||||
|
||||
private Long id;
|
||||
|
||||
/** Hibernate requires this default constructor. */
|
||||
private HostHistoryId() {}
|
||||
|
||||
HostHistoryId(String hostRepoId, long id) {
|
||||
this.hostRepoId = hostRepoId;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the host repository id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private String getHostRepoId() {
|
||||
return hostRepoId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the history revision id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the host repository id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate and should not be used
|
||||
* externally to keep immutability.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setHostRepoId(String hostRepoId) {
|
||||
this.hostRepoId = hostRepoId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the history revision id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate and should not be used
|
||||
* externally to keep immutability.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,18 +190,8 @@ public class HostHistory extends HistoryEntry {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setHostRepoId(VKey<HostResource> hostRepoId) {
|
||||
getInstance().hostRepoId = hostRepoId;
|
||||
hostRepoId.maybeGetOfyKey().ifPresent(parent -> getInstance().parent = parent);
|
||||
return this;
|
||||
}
|
||||
|
||||
// We can remove this once all HistoryEntries are converted to History objects
|
||||
@Override
|
||||
public Builder setParent(Key<? extends EppResource> parent) {
|
||||
super.setParent(parent);
|
||||
getInstance().hostRepoId =
|
||||
VKey.create(HostResource.class, parent.getName(), (Key<HostResource>) parent);
|
||||
public Builder setHostRepoId(String hostRepoId) {
|
||||
getInstance().parent = Key.create(HostResource.class, hostRepoId);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,14 +27,18 @@ import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import com.googlecode.objectify.annotation.OnLoad;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.ExternalMessagingName;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainRenewData;
|
||||
import google.registry.model.eppoutput.EppResponse.ResponseData;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse.ContactPendingActionNotificationResponse;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse.HostPendingActionNotificationResponse;
|
||||
@@ -54,10 +58,9 @@ import javax.persistence.Column;
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@@ -98,7 +101,6 @@ public abstract class PollMessage extends ImmutableObject
|
||||
/** Entity id. */
|
||||
@Id
|
||||
@javax.persistence.Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "poll_message_id")
|
||||
Long id;
|
||||
|
||||
@@ -124,11 +126,11 @@ public abstract class PollMessage extends ImmutableObject
|
||||
|
||||
@Ignore String hostRepoId;
|
||||
|
||||
@Ignore Long domainRevisionId;
|
||||
@Ignore Long domainHistoryRevisionId;
|
||||
|
||||
@Ignore Long contactRevisionId;
|
||||
@Ignore Long contactHistoryRevisionId;
|
||||
|
||||
@Ignore Long hostRevisionId;
|
||||
@Ignore Long hostHistoryRevisionId;
|
||||
|
||||
public Key<HistoryEntry> getParentKey() {
|
||||
return parent;
|
||||
@@ -152,6 +154,34 @@ public abstract class PollMessage extends ImmutableObject
|
||||
|
||||
public abstract ImmutableList<ResponseData> getResponseData();
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
if (domainRepoId != null) {
|
||||
parent =
|
||||
Key.create(
|
||||
Key.create(DomainBase.class, domainRepoId),
|
||||
HistoryEntry.class,
|
||||
domainHistoryRevisionId);
|
||||
} else if (contactRepoId != null) {
|
||||
parent =
|
||||
Key.create(
|
||||
Key.create(ContactResource.class, contactRepoId),
|
||||
HistoryEntry.class,
|
||||
contactHistoryRevisionId);
|
||||
} else if (hostHistoryRevisionId != null) {
|
||||
parent =
|
||||
Key.create(
|
||||
Key.create(HostResource.class, hostRepoId),
|
||||
HistoryEntry.class,
|
||||
hostHistoryRevisionId);
|
||||
}
|
||||
}
|
||||
|
||||
@OnLoad
|
||||
void onLoad() {
|
||||
setSqlForeignKeys(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract VKey<? extends PollMessage> createVKey();
|
||||
|
||||
@@ -217,10 +247,30 @@ public abstract class PollMessage extends ImmutableObject
|
||||
checkArgumentNotNull(instance.clientId, "clientId must be specified");
|
||||
checkArgumentNotNull(instance.eventTime, "eventTime must be specified");
|
||||
checkArgumentNotNull(instance.parent, "parent must be specified");
|
||||
checkArgumentNotNull(instance.parent.getParent(), "parent.getParent() must be specified");
|
||||
setSqlForeignKeys(instance);
|
||||
return super.build();
|
||||
}
|
||||
}
|
||||
|
||||
private static void setSqlForeignKeys(PollMessage pollMessage) {
|
||||
String grandparentKind = pollMessage.parent.getParent().getKind();
|
||||
String repoId = pollMessage.parent.getParent().getName();
|
||||
long historyRevisionId = pollMessage.parent.getId();
|
||||
if (Key.getKind(DomainBase.class).equals(grandparentKind)) {
|
||||
pollMessage.domainRepoId = repoId;
|
||||
pollMessage.domainHistoryRevisionId = historyRevisionId;
|
||||
} else if (Key.getKind(ContactResource.class).equals(grandparentKind)) {
|
||||
pollMessage.contactRepoId = repoId;
|
||||
pollMessage.contactHistoryRevisionId = historyRevisionId;
|
||||
} else if (Key.getKind(HostResource.class).equals(grandparentKind)) {
|
||||
pollMessage.hostRepoId = repoId;
|
||||
pollMessage.hostHistoryRevisionId = historyRevisionId;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown grandparent kind: " + grandparentKind);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A one-time poll message.
|
||||
*
|
||||
|
||||
@@ -62,6 +62,7 @@ import google.registry.model.domain.fee.BaseFee.FeeType;
|
||||
import google.registry.model.domain.fee.Fee;
|
||||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.model.registry.label.ReservedList;
|
||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||
import google.registry.util.Idn;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -86,7 +87,7 @@ import org.joda.time.Duration;
|
||||
@ReportedOn
|
||||
@Entity
|
||||
@javax.persistence.Entity(name = "Tld")
|
||||
public class Registry extends ImmutableObject implements Buildable {
|
||||
public class Registry extends ImmutableObject implements Buildable, DatastoreAndSqlEntity {
|
||||
|
||||
@Parent @Transient Key<EntityGroupRoot> parent = getCrossTldKey();
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
@@ -43,7 +44,8 @@ import org.joda.time.DateTime;
|
||||
*/
|
||||
@Embed
|
||||
@Entity
|
||||
public class DomainTransactionRecord extends ImmutableObject implements Buildable {
|
||||
public class DomainTransactionRecord extends ImmutableObject
|
||||
implements Buildable, DatastoreAndSqlEntity {
|
||||
|
||||
@Id
|
||||
@Ignore
|
||||
|
||||
@@ -62,7 +62,7 @@ import org.joda.time.DateTime;
|
||||
@MappedSuperclass
|
||||
@WithStringVKey // TODO(b/162229294): This should be resolved during the course of that bug
|
||||
@Access(AccessType.FIELD)
|
||||
public class HistoryEntry extends ImmutableObject implements Buildable, DatastoreEntity, SqlEntity {
|
||||
public class HistoryEntry extends ImmutableObject implements Buildable, DatastoreEntity {
|
||||
|
||||
/** Represents the type of history entry. */
|
||||
public enum Type {
|
||||
@@ -308,19 +308,10 @@ public class HistoryEntry extends ImmutableObject implements Buildable, Datastor
|
||||
new DomainHistory.Builder().copyFrom(this).setDomainRepoId(parent.getName()).build();
|
||||
} else if (parentKind.equals(getKind(HostResource.class))) {
|
||||
resultEntity =
|
||||
new HostHistory.Builder()
|
||||
.copyFrom(this)
|
||||
.setHostRepoId(
|
||||
VKey.create(HostResource.class, parent.getName(), (Key<HostResource>) parent))
|
||||
.build();
|
||||
new HostHistory.Builder().copyFrom(this).setHostRepoId(parent.getName()).build();
|
||||
} else if (parentKind.equals(getKind(ContactResource.class))) {
|
||||
resultEntity =
|
||||
new ContactHistory.Builder()
|
||||
.copyFrom(this)
|
||||
.setContactRepoId(
|
||||
VKey.create(
|
||||
ContactResource.class, parent.getName(), (Key<ContactResource>) parent))
|
||||
.build();
|
||||
new ContactHistory.Builder().copyFrom(this).setContactRepoId(parent.getName()).build();
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
String.format("Unknown kind of HistoryEntry parent %s", parentKind));
|
||||
@@ -331,13 +322,7 @@ public class HistoryEntry extends ImmutableObject implements Buildable, Datastor
|
||||
// In SQL, save the child type
|
||||
@Override
|
||||
public ImmutableList<SqlEntity> toSqlEntities() {
|
||||
return ImmutableList.of(toChildHistoryEntity());
|
||||
}
|
||||
|
||||
// In Datastore, save as a HistoryEntry object regardless of this object's type
|
||||
@Override
|
||||
public ImmutableList<DatastoreEntity> toDatastoreEntities() {
|
||||
return ImmutableList.of(asHistoryEntry());
|
||||
return ImmutableList.of((SqlEntity) toChildHistoryEntity());
|
||||
}
|
||||
|
||||
/** A builder for {@link HistoryEntry} since it is immutable */
|
||||
|
||||
@@ -46,6 +46,7 @@ import google.registry.model.annotations.NotBackedUp;
|
||||
import google.registry.model.annotations.NotBackedUp.Reason;
|
||||
import google.registry.model.annotations.VirtualEntity;
|
||||
import google.registry.model.common.CrossTldSingleton;
|
||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||
import google.registry.schema.replay.DatastoreEntity;
|
||||
import google.registry.schema.replay.SqlEntity;
|
||||
import google.registry.util.CollectionUtils;
|
||||
@@ -97,7 +98,7 @@ import org.joda.time.DateTime;
|
||||
@NotBackedUp(reason = Reason.EXTERNALLY_SOURCED)
|
||||
@javax.persistence.Entity(name = "ClaimsList")
|
||||
@Table
|
||||
public class ClaimsListShard extends ImmutableObject implements DatastoreEntity {
|
||||
public class ClaimsListShard extends ImmutableObject implements DatastoreAndSqlEntity {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -354,11 +355,6 @@ public class ClaimsListShard extends ImmutableObject implements DatastoreEntity
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<SqlEntity> toSqlEntities() {
|
||||
return ImmutableList.of(); // ClaimsLists are dually written
|
||||
}
|
||||
|
||||
/** Virtual parent entity for claims list shards of a specific revision. */
|
||||
@Entity
|
||||
@VirtualEntity
|
||||
|
||||
@@ -88,7 +88,7 @@ public class VKey<T> extends ImmutableObject implements Serializable {
|
||||
*/
|
||||
public static <T> VKey<T> create(Class<T> kind, long id) {
|
||||
checkArgument(
|
||||
kind.isAssignableFrom(BackupGroupRoot.class),
|
||||
BackupGroupRoot.class.isAssignableFrom(kind),
|
||||
"The kind %s is not a BackupGroupRoot and thus needs its entire entity group chain"
|
||||
+ " specified in a parent",
|
||||
kind.getCanonicalName());
|
||||
@@ -106,13 +106,90 @@ public class VKey<T> extends ImmutableObject implements Serializable {
|
||||
*/
|
||||
public static <T> VKey<T> create(Class<T> kind, String name) {
|
||||
checkArgument(
|
||||
kind.isAssignableFrom(BackupGroupRoot.class),
|
||||
BackupGroupRoot.class.isAssignableFrom(kind),
|
||||
"The kind %s is not a BackupGroupRoot and thus needs its entire entity group chain"
|
||||
+ " specified in a parent",
|
||||
kind.getCanonicalName());
|
||||
return new VKey<T>(kind, Key.create(kind, name), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a clone with an ofy key restored from {@code ancestors}.
|
||||
*
|
||||
* <p>The arguments should generally consist of pairs of Class and value, where the Class is the
|
||||
* kind of the ancestor key and the value is either a String or a Long.
|
||||
*
|
||||
* <p>For example, to restore the objectify key for
|
||||
* DomainBase("COM-1234")/HistoryEntry(123)/PollEvent(567), one might use:
|
||||
*
|
||||
* <pre>{@code
|
||||
* pollEvent.restoreOfy(DomainBase.class, "COM-1234", HistoryEntry.class, 567)
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The final key id or name is obtained from the SQL key. It is assumed that this value must be
|
||||
* either a long integer or a {@code String} and that this proper identifier for the objectify
|
||||
* key.
|
||||
*
|
||||
* <p>As a special case, an objectify Key may be used as the first ancestor instead of a Class,
|
||||
* value pair.
|
||||
*/
|
||||
public VKey<T> restoreOfy(Object... ancestors) {
|
||||
Class lastClass = null;
|
||||
Key<?> lastKey = null;
|
||||
for (Object ancestor : ancestors) {
|
||||
if (ancestor instanceof Class) {
|
||||
if (lastClass != null) {
|
||||
throw new IllegalArgumentException(ancestor + " used as a key value.");
|
||||
}
|
||||
lastClass = (Class) ancestor;
|
||||
continue;
|
||||
} else if (ancestor instanceof Key) {
|
||||
if (lastKey != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Objectify keys may only be used for the first argument");
|
||||
}
|
||||
lastKey = (Key) ancestor;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The argument should be a value.
|
||||
if (lastClass == null) {
|
||||
throw new IllegalArgumentException("Argument " + ancestor + " should be a class.");
|
||||
}
|
||||
if (ancestor instanceof Long) {
|
||||
lastKey = Key.create(lastKey, lastClass, (Long) ancestor);
|
||||
} else if (ancestor instanceof String) {
|
||||
lastKey = Key.create(lastKey, lastClass, (String) ancestor);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Key value " + ancestor + " must be a string or long.");
|
||||
}
|
||||
lastClass = null;
|
||||
}
|
||||
|
||||
// Make sure we didn't end up with a dangling class with no value.
|
||||
if (lastClass != null) {
|
||||
throw new IllegalArgumentException("Missing value for last key of type " + lastClass);
|
||||
}
|
||||
|
||||
Object sqlKey = getSqlKey();
|
||||
Key<T> ofyKey =
|
||||
sqlKey instanceof Long
|
||||
? Key.create(lastKey, getKind(), (Long) sqlKey)
|
||||
: Key.create(lastKey, getKind(), (String) sqlKey);
|
||||
|
||||
return VKey.create((Class<T>) getKind(), sqlKey, ofyKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a clone of {@code key} with an ofy key restored from {@code ancestors}.
|
||||
*
|
||||
* <p>This is the static form of the method restoreOfy() above. If {@code key} is null, it returns
|
||||
* null.
|
||||
*/
|
||||
public static <T> VKey<T> restoreOfyFrom(@Nullable VKey<T> key, Object... ancestors) {
|
||||
return key == null ? null : key.restoreOfy(ancestors);
|
||||
}
|
||||
|
||||
/** Returns the type of the entity. */
|
||||
public Class<? extends T> getKind() {
|
||||
return this.kind;
|
||||
|
||||
@@ -11,11 +11,6 @@
|
||||
</attributes>
|
||||
</embeddable>
|
||||
|
||||
<sequence-generator name="HistorySequenceGenerator" sequence-name="history_id_sequence"/>
|
||||
|
||||
<!-- TODO(shicong): Drop this sequence and change all history tables to use the above one. -->
|
||||
<sequence-generator name="TempHistorySequenceGenerator" sequence-name="temp_history_id_sequence"/>
|
||||
|
||||
<persistence-unit-metadata>
|
||||
<persistence-unit-defaults>
|
||||
<entity-listeners>
|
||||
|
||||
@@ -94,7 +94,10 @@
|
||||
<class>google.registry.persistence.converter.ZonedDateTimeConverter</class>
|
||||
|
||||
<!-- Generated converters for VKey -->
|
||||
<class>google.registry.model.billing.VKeyConverter_BillingEvent</class>
|
||||
<class>google.registry.model.billing.VKeyConverter_Cancellation</class>
|
||||
<class>google.registry.model.billing.VKeyConverter_Modification</class>
|
||||
<class>google.registry.model.billing.VKeyConverter_OneTime</class>
|
||||
<class>google.registry.model.billing.VKeyConverter_Recurring</class>
|
||||
<class>google.registry.model.contact.VKeyConverter_ContactResource</class>
|
||||
<class>google.registry.model.domain.VKeyConverter_DomainBase</class>
|
||||
<class>google.registry.model.domain.token.VKeyConverter_AllocationToken</class>
|
||||
|
||||
@@ -273,8 +273,11 @@ class InitSqlPipelineTest {
|
||||
"revisions",
|
||||
"updateTimestamp",
|
||||
"autorenewBillingEvent",
|
||||
"autorenewBillingEventHistoryId",
|
||||
"autorenewPollMessage",
|
||||
"autorenewPollMessageHistoryId",
|
||||
"deletePollMessage",
|
||||
"deletePollMessageHistoryId",
|
||||
"nsHosts",
|
||||
"transferData");
|
||||
assertThat(actual.getAdminContact().getSqlKey())
|
||||
|
||||
@@ -821,10 +821,12 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
setEppInput("domain_create_dsdata_no_maxsiglife.xml");
|
||||
persistContactsAndHosts("tld"); // For some reason this sample uses "tld".
|
||||
doSuccessfulTest("tld");
|
||||
DomainBase domain = reloadResourceByForeignKey();
|
||||
assertAboutDomains()
|
||||
.that(reloadResourceByForeignKey())
|
||||
.that(domain)
|
||||
.hasExactlyDsData(
|
||||
DelegationSignerData.create(12345, 3, 1, base16().decode("49FD46E6C4B45C55D4AC")));
|
||||
DelegationSignerData.create(12345, 3, 1, base16().decode("49FD46E6C4B45C55D4AC"))
|
||||
.cloneWithDomainRepoId(domain.getRepoId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.flows.domain;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.Sets.union;
|
||||
import static com.google.common.io.BaseEncoding.base16;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
@@ -470,7 +471,11 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
|
||||
.that(resource)
|
||||
.hasOnlyOneHistoryEntryWhich()
|
||||
.hasType(HistoryEntry.Type.DOMAIN_UPDATE);
|
||||
assertThat(resource.getDsData()).isEqualTo(expectedDsData);
|
||||
assertThat(resource.getDsData())
|
||||
.isEqualTo(
|
||||
expectedDsData.stream()
|
||||
.map(ds -> ds.cloneWithDomainRepoId(resource.getRepoId()))
|
||||
.collect(toImmutableSet()));
|
||||
assertDnsTasksEnqueued("example.tld");
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.util.DateTimeUtils;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -57,7 +56,6 @@ public class BillingEventTest extends EntityTestCase {
|
||||
private HistoryEntry historyEntry;
|
||||
private HistoryEntry historyEntry2;
|
||||
private DomainBase domain;
|
||||
private BillingEvent.OneTime sqlOneTime;
|
||||
private BillingEvent.OneTime oneTime;
|
||||
private BillingEvent.OneTime oneTimeSynthetic;
|
||||
private BillingEvent.Recurring recurring;
|
||||
@@ -107,16 +105,6 @@ public class BillingEventTest extends EntityTestCase {
|
||||
.setBillingTime(now.plusDays(5))
|
||||
.setAllocationToken(allocationToken.createVKey())));
|
||||
|
||||
sqlOneTime =
|
||||
oneTime
|
||||
.asBuilder()
|
||||
.setDomainRepoId(domain.getRepoId())
|
||||
.setDomainHistoryRevisionId(1L)
|
||||
.setAllocationToken(
|
||||
VKey.create(
|
||||
AllocationToken.class, allocationToken.getToken(), Key.create(allocationToken)))
|
||||
.build();
|
||||
|
||||
recurring =
|
||||
persistResource(
|
||||
commonInit(
|
||||
@@ -179,80 +167,43 @@ public class BillingEventTest extends EntityTestCase {
|
||||
}
|
||||
|
||||
private void saveNewBillingEvent(BillingEvent billingEvent) {
|
||||
billingEvent.id = null;
|
||||
jpaTm().transact(() -> jpaTm().insert(billingEvent));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCloudSqlPersistence_OneTime() {
|
||||
saveRegistrar("a registrar");
|
||||
saveNewBillingEvent(sqlOneTime);
|
||||
saveNewBillingEvent(oneTime);
|
||||
|
||||
BillingEvent.OneTime persisted =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> jpaTm().load(VKey.createSql(BillingEvent.OneTime.class, sqlOneTime.id)));
|
||||
// TODO(shicong): Remove these fixes after the entities are fully compatible
|
||||
BillingEvent.OneTime persisted = jpaTm().transact(() -> jpaTm().load(oneTime.createVKey()));
|
||||
// TODO(b/168325240): Remove this fix after VKeyConverter generates symmetric key for
|
||||
// AllocationToken.
|
||||
BillingEvent.OneTime fixed =
|
||||
persisted
|
||||
.asBuilder()
|
||||
.setParent(sqlOneTime.getParentKey())
|
||||
.setAllocationToken(sqlOneTime.getAllocationToken().get())
|
||||
.build();
|
||||
assertThat(fixed).isEqualTo(sqlOneTime);
|
||||
persisted.asBuilder().setAllocationToken(oneTime.getAllocationToken().get()).build();
|
||||
assertThat(fixed).isEqualTo(oneTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCloudSqlPersistence_Cancellation() {
|
||||
saveRegistrar("a registrar");
|
||||
saveNewBillingEvent(sqlOneTime);
|
||||
VKey<BillingEvent.OneTime> sqlVKey = VKey.createSql(BillingEvent.OneTime.class, sqlOneTime.id);
|
||||
BillingEvent sqlCancellationOneTime =
|
||||
cancellationOneTime
|
||||
.asBuilder()
|
||||
.setOneTimeEventKey(sqlVKey)
|
||||
.setDomainRepoId(domain.getRepoId())
|
||||
.setDomainHistoryRevisionId(1L)
|
||||
.build();
|
||||
saveNewBillingEvent(sqlCancellationOneTime);
|
||||
saveNewBillingEvent(oneTime);
|
||||
saveNewBillingEvent(cancellationOneTime);
|
||||
|
||||
BillingEvent.Cancellation persisted =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.load(
|
||||
VKey.createSql(
|
||||
BillingEvent.Cancellation.class, sqlCancellationOneTime.id)));
|
||||
// TODO(shicong): Remove these fixes after the entities are fully compatible
|
||||
jpaTm().transact(() -> jpaTm().load(cancellationOneTime.createVKey()));
|
||||
// TODO(b/168537779): Remove this fix after VKey<OneTime> can be reconstructed correctly.
|
||||
BillingEvent.Cancellation fixed =
|
||||
persisted
|
||||
.asBuilder()
|
||||
.setParent(sqlCancellationOneTime.getParentKey())
|
||||
.setOneTimeEventKey(sqlVKey)
|
||||
.build();
|
||||
assertThat(fixed).isEqualTo(sqlCancellationOneTime);
|
||||
persisted.asBuilder().setOneTimeEventKey(oneTime.createVKey()).build();
|
||||
assertThat(fixed).isEqualTo(cancellationOneTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCloudSqlPersistence_Recurring() {
|
||||
saveRegistrar("a registrar");
|
||||
BillingEvent.Recurring sqlRecurring =
|
||||
recurring
|
||||
.asBuilder()
|
||||
.setDomainRepoId(domain.getRepoId())
|
||||
.setDomainHistoryRevisionId(1L)
|
||||
.build();
|
||||
saveNewBillingEvent(sqlRecurring);
|
||||
saveNewBillingEvent(recurring);
|
||||
|
||||
BillingEvent.Recurring persisted =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> jpaTm().load(VKey.createSql(BillingEvent.Recurring.class, sqlRecurring.id)));
|
||||
// TODO(shicong): Remove these fixes after the entities are fully compatible
|
||||
BillingEvent.Recurring fixed =
|
||||
persisted.asBuilder().setParent(sqlRecurring.getParentKey()).build();
|
||||
assertThat(fixed).isEqualTo(sqlRecurring);
|
||||
BillingEvent.Recurring persisted = jpaTm().transact(() -> jpaTm().load(recurring.createVKey()));
|
||||
assertThat(persisted).isEqualTo(recurring);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -25,6 +25,12 @@ import static org.joda.time.DateTimeZone.UTC;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Flag;
|
||||
import google.registry.model.billing.BillingEvent.Reason;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DesignatedContact.Type;
|
||||
import google.registry.model.domain.launch.LaunchNotice;
|
||||
@@ -33,6 +39,8 @@ import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.ContactTransferData;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.JpaTestRules;
|
||||
@@ -60,6 +68,7 @@ public class DomainBaseSqlTest {
|
||||
new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageExtension();
|
||||
|
||||
private DomainBase domain;
|
||||
private DomainHistory historyEntry;
|
||||
private VKey<ContactResource> contactKey;
|
||||
private VKey<ContactResource> contact2Key;
|
||||
private VKey<HostResource> host1VKey;
|
||||
@@ -334,6 +343,50 @@ public class DomainBaseSqlTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testModifyDsData_addThenRemoveSuccessfully() {
|
||||
persistDomain();
|
||||
DelegationSignerData extraDsData =
|
||||
DelegationSignerData.create(2, 2, 3, new byte[] {0, 1, 2}, "4-COM");
|
||||
ImmutableSet<DelegationSignerData> unionDsData =
|
||||
Sets.union(domain.getDsData(), ImmutableSet.of(extraDsData)).immutableCopy();
|
||||
|
||||
// Add an extra DelegationSignerData to dsData set.
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
DomainBase persisted = jpaTm().load(domain.createVKey());
|
||||
assertThat(persisted.getDsData()).containsExactlyElementsIn(domain.getDsData());
|
||||
DomainBase modified = persisted.asBuilder().setDsData(unionDsData).build();
|
||||
jpaTm().put(modified);
|
||||
});
|
||||
|
||||
// Verify that the persisted domain entity contains both DelegationSignerData records.
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
DomainBase persisted = jpaTm().load(domain.createVKey());
|
||||
assertThat(persisted.getDsData()).containsExactlyElementsIn(unionDsData);
|
||||
assertEqualDomainExcept(persisted, "dsData");
|
||||
});
|
||||
|
||||
// Remove the extra DelegationSignerData record from dsData set.
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
DomainBase persisted = jpaTm().load(domain.createVKey());
|
||||
jpaTm().put(persisted.asBuilder().setDsData(domain.getDsData()).build());
|
||||
});
|
||||
|
||||
// Verify that the persisted domain is equal to the original domain.
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
DomainBase persisted = jpaTm().load(domain.createVKey());
|
||||
assertEqualDomainExcept(persisted);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdates() {
|
||||
jpaTm()
|
||||
@@ -350,16 +403,6 @@ public class DomainBaseSqlTest {
|
||||
.transact(
|
||||
() -> {
|
||||
DomainBase result = jpaTm().load(domain.createVKey());
|
||||
|
||||
// Fix DS data, since we can't persist that yet.
|
||||
result =
|
||||
result
|
||||
.asBuilder()
|
||||
.setDsData(
|
||||
ImmutableSet.of(
|
||||
DelegationSignerData.create(1, 2, 3, new byte[] {0, 1, 2})))
|
||||
.build();
|
||||
|
||||
assertAboutImmutableObjects()
|
||||
.that(result)
|
||||
.isEqualExceptFields(domain, "updateTimestamp", "creationTime");
|
||||
@@ -395,14 +438,175 @@ public class DomainBaseSqlTest {
|
||||
});
|
||||
}
|
||||
|
||||
private void assertEqualDomainExcept(DomainBase thatDomain, String... excepts) {
|
||||
// Fix DS data, since we can't persist it yet.
|
||||
thatDomain =
|
||||
thatDomain
|
||||
.asBuilder()
|
||||
.setDsData(ImmutableSet.of(DelegationSignerData.create(1, 2, 3, new byte[] {0, 1, 2})))
|
||||
.build();
|
||||
@Test
|
||||
void persistDomainWithCompositeVKeys() {
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
historyEntry =
|
||||
new DomainHistory.Builder()
|
||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||
.setPeriod(Period.create(1, Period.Unit.YEARS))
|
||||
.setModificationTime(DateTime.now(UTC))
|
||||
.setParent(Key.create(DomainBase.class, "4-COM"))
|
||||
.setDomainRepoId("4-COM")
|
||||
|
||||
// These are non-null, but I don't think some tests set them.
|
||||
.setReason("felt like it")
|
||||
.setRequestedByRegistrar(false)
|
||||
.setXmlBytes(new byte[0])
|
||||
.build();
|
||||
BillingEvent.Recurring billEvent =
|
||||
new BillingEvent.Recurring.Builder()
|
||||
.setReason(Reason.RENEW)
|
||||
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
||||
.setTargetId("example.com")
|
||||
.setClientId("registrar1")
|
||||
.setDomainRepoId("4-COM")
|
||||
.setDomainHistoryRevisionId(1L)
|
||||
.setEventTime(DateTime.now(UTC).plusYears(1))
|
||||
.setRecurrenceEndTime(END_OF_TIME)
|
||||
.setParent(historyEntry)
|
||||
.build();
|
||||
PollMessage.Autorenew autorenewPollMessage =
|
||||
new PollMessage.Autorenew.Builder()
|
||||
.setClientId("registrar1")
|
||||
.setEventTime(DateTime.now(UTC).plusYears(1))
|
||||
.setParent(historyEntry)
|
||||
.build();
|
||||
PollMessage.OneTime deletePollMessage =
|
||||
new PollMessage.OneTime.Builder()
|
||||
.setClientId("registrar1")
|
||||
.setEventTime(DateTime.now(UTC).plusYears(1))
|
||||
.setParent(historyEntry)
|
||||
.build();
|
||||
|
||||
jpaTm().insert(contact);
|
||||
jpaTm().insert(contact2);
|
||||
jpaTm().insert(host);
|
||||
domain =
|
||||
domain
|
||||
.asBuilder()
|
||||
.setAutorenewBillingEvent(billEvent.createVKey())
|
||||
.setAutorenewPollMessage(autorenewPollMessage.createVKey())
|
||||
.setDeletePollMessage(deletePollMessage.createVKey())
|
||||
.build();
|
||||
historyEntry = historyEntry.asBuilder().setDomainContent(domain).build();
|
||||
jpaTm().insert(historyEntry);
|
||||
jpaTm().insert(autorenewPollMessage);
|
||||
jpaTm().insert(billEvent);
|
||||
jpaTm().insert(deletePollMessage);
|
||||
jpaTm().insert(domain);
|
||||
});
|
||||
|
||||
// Store the existing BillingRecurrence VKey. This happens after the event has been persisted.
|
||||
DomainBase persisted = jpaTm().transact(() -> jpaTm().load(domain.createVKey()));
|
||||
|
||||
// Verify that the domain data has been persisted.
|
||||
// dsData still isn't persisted. gracePeriods appears to have the same values but for some
|
||||
// reason is showing up as different.
|
||||
assertEqualDomainExcept(persisted, "creationTime", "dsData", "gracePeriods");
|
||||
|
||||
// Verify that the DomainContent object from the history record sets the fields correctly.
|
||||
DomainHistory persistedHistoryEntry =
|
||||
jpaTm().transact(() -> jpaTm().load(historyEntry.createVKey()));
|
||||
assertThat(persistedHistoryEntry.getDomainContent().get().getAutorenewPollMessage())
|
||||
.isEqualTo(domain.getAutorenewPollMessage());
|
||||
assertThat(persistedHistoryEntry.getDomainContent().get().getAutorenewBillingEvent())
|
||||
.isEqualTo(domain.getAutorenewBillingEvent());
|
||||
assertThat(persistedHistoryEntry.getDomainContent().get().getDeletePollMessage())
|
||||
.isEqualTo(domain.getDeletePollMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void persistDomainWithLegacyVKeys() {
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
historyEntry =
|
||||
new DomainHistory.Builder()
|
||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||
.setPeriod(Period.create(1, Period.Unit.YEARS))
|
||||
.setModificationTime(DateTime.now(UTC))
|
||||
.setParent(Key.create(DomainBase.class, "4-COM"))
|
||||
.setDomainRepoId("4-COM")
|
||||
|
||||
// These are non-null, but I don't think some tests set them.
|
||||
.setReason("felt like it")
|
||||
.setRequestedByRegistrar(false)
|
||||
.setXmlBytes(new byte[0])
|
||||
.build();
|
||||
BillingEvent.Recurring billEvent =
|
||||
new BillingEvent.Recurring.Builder()
|
||||
.setReason(Reason.RENEW)
|
||||
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
||||
.setTargetId("example.com")
|
||||
.setClientId("registrar1")
|
||||
.setDomainRepoId("4-COM")
|
||||
.setDomainHistoryRevisionId(1L)
|
||||
.setEventTime(DateTime.now(UTC).plusYears(1))
|
||||
.setRecurrenceEndTime(END_OF_TIME)
|
||||
.setParent(historyEntry)
|
||||
.build();
|
||||
PollMessage.Autorenew autorenewPollMessage =
|
||||
new PollMessage.Autorenew.Builder()
|
||||
.setClientId("registrar1")
|
||||
.setEventTime(DateTime.now(UTC).plusYears(1))
|
||||
.setParent(historyEntry)
|
||||
.build();
|
||||
PollMessage.OneTime deletePollMessage =
|
||||
new PollMessage.OneTime.Builder()
|
||||
.setClientId("registrar1")
|
||||
.setEventTime(DateTime.now(UTC).plusYears(1))
|
||||
.setParent(historyEntry)
|
||||
.build();
|
||||
|
||||
jpaTm().insert(contact);
|
||||
jpaTm().insert(contact2);
|
||||
jpaTm().insert(host);
|
||||
domain =
|
||||
domain
|
||||
.asBuilder()
|
||||
.setAutorenewBillingEvent(
|
||||
createLegacyVKey(BillingEvent.Recurring.class, billEvent.getId()))
|
||||
.setAutorenewPollMessage(
|
||||
createLegacyVKey(PollMessage.Autorenew.class, deletePollMessage.getId()))
|
||||
.setDeletePollMessage(
|
||||
createLegacyVKey(PollMessage.OneTime.class, autorenewPollMessage.getId()))
|
||||
.build();
|
||||
historyEntry = historyEntry.asBuilder().setDomainContent(domain).build();
|
||||
jpaTm().insert(historyEntry);
|
||||
jpaTm().insert(autorenewPollMessage);
|
||||
jpaTm().insert(billEvent);
|
||||
jpaTm().insert(deletePollMessage);
|
||||
jpaTm().insert(domain);
|
||||
});
|
||||
|
||||
// Store the existing BillingRecurrence VKey. This happens after the event has been persisted.
|
||||
DomainBase persisted = jpaTm().transact(() -> jpaTm().load(domain.createVKey()));
|
||||
|
||||
// Verify that the domain data has been persisted.
|
||||
// dsData still isn't persisted. gracePeriods appears to have the same values but for some
|
||||
// reason is showing up as different.
|
||||
assertEqualDomainExcept(persisted, "creationTime", "dsData", "gracePeriods");
|
||||
|
||||
// Verify that the DomainContent object from the history record sets the fields correctly.
|
||||
DomainHistory persistedHistoryEntry =
|
||||
jpaTm().transact(() -> jpaTm().load(historyEntry.createVKey()));
|
||||
assertThat(persistedHistoryEntry.getDomainContent().get().getAutorenewPollMessage())
|
||||
.isEqualTo(domain.getAutorenewPollMessage());
|
||||
assertThat(persistedHistoryEntry.getDomainContent().get().getAutorenewBillingEvent())
|
||||
.isEqualTo(domain.getAutorenewBillingEvent());
|
||||
assertThat(persistedHistoryEntry.getDomainContent().get().getDeletePollMessage())
|
||||
.isEqualTo(domain.getDeletePollMessage());
|
||||
}
|
||||
|
||||
private <T> VKey<T> createLegacyVKey(Class<T> clazz, long id) {
|
||||
return VKey.create(
|
||||
clazz, id, Key.create(Key.create(EntityGroupRoot.class, "per-tld"), clazz, id));
|
||||
}
|
||||
|
||||
private void assertEqualDomainExcept(DomainBase thatDomain, String... excepts) {
|
||||
// Fix the original creation timestamp (this gets initialized on first write)
|
||||
DomainBase org = domain.asBuilder().setCreationTime(thatDomain.getCreationTime()).build();
|
||||
|
||||
|
||||
@@ -47,17 +47,14 @@ public class ContactHistoryTest extends EntityTestCase {
|
||||
jpaTm().transact(() -> jpaTm().insert(contact));
|
||||
VKey<ContactResource> contactVKey = contact.createVKey();
|
||||
ContactResource contactFromDb = jpaTm().transact(() -> jpaTm().load(contactVKey));
|
||||
ContactHistory contactHistory = createContactHistory(contactFromDb, contactVKey);
|
||||
contactHistory.id = null;
|
||||
ContactHistory contactHistory = createContactHistory(contactFromDb, contact.getRepoId());
|
||||
jpaTm().transact(() -> jpaTm().insert(contactHistory));
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
ContactHistory fromDatabase =
|
||||
jpaTm().load(VKey.createSql(ContactHistory.class, contactHistory.getId()));
|
||||
ContactHistory fromDatabase = jpaTm().load(contactHistory.createVKey());
|
||||
assertContactHistoriesEqual(fromDatabase, contactHistory);
|
||||
assertThat(fromDatabase.getContactRepoId().getSqlKey())
|
||||
.isEqualTo(contactHistory.getContactRepoId().getSqlKey());
|
||||
assertThat(fromDatabase.getParentVKey()).isEqualTo(contactHistory.getParentVKey());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -70,18 +67,18 @@ public class ContactHistoryTest extends EntityTestCase {
|
||||
VKey<ContactResource> contactVKey = contact.createVKey();
|
||||
ContactResource contactFromDb = jpaTm().transact(() -> jpaTm().load(contactVKey));
|
||||
ContactHistory contactHistory =
|
||||
createContactHistory(contactFromDb, contactVKey).asBuilder().setContactBase(null).build();
|
||||
contactHistory.id = null;
|
||||
createContactHistory(contactFromDb, contact.getRepoId())
|
||||
.asBuilder()
|
||||
.setContactBase(null)
|
||||
.build();
|
||||
jpaTm().transact(() -> jpaTm().insert(contactHistory));
|
||||
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
ContactHistory fromDatabase =
|
||||
jpaTm().load(VKey.createSql(ContactHistory.class, contactHistory.getId()));
|
||||
ContactHistory fromDatabase = jpaTm().load(contactHistory.createVKey());
|
||||
assertContactHistoriesEqual(fromDatabase, contactHistory);
|
||||
assertThat(fromDatabase.getContactRepoId().getSqlKey())
|
||||
.isEqualTo(contactHistory.getContactRepoId().getSqlKey());
|
||||
assertThat(fromDatabase.getParentVKey()).isEqualTo(contactHistory.getParentVKey());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -94,14 +91,13 @@ public class ContactHistoryTest extends EntityTestCase {
|
||||
VKey<ContactResource> contactVKey = contact.createVKey();
|
||||
ContactResource contactFromDb = tm().transact(() -> tm().load(contactVKey));
|
||||
fakeClock.advanceOneMilli();
|
||||
ContactHistory contactHistory = createContactHistory(contactFromDb, contactVKey);
|
||||
ContactHistory contactHistory = createContactHistory(contactFromDb, contact.getRepoId());
|
||||
tm().transact(() -> tm().insert(contactHistory));
|
||||
|
||||
// retrieving a HistoryEntry or a ContactHistory with the same key should return the same object
|
||||
// note: due to the @EntitySubclass annotation. all Keys for ContactHistory objects will have
|
||||
// type HistoryEntry
|
||||
VKey<ContactHistory> contactHistoryVKey =
|
||||
VKey.createOfy(ContactHistory.class, Key.create(contactHistory));
|
||||
VKey<ContactHistory> contactHistoryVKey = contactHistory.createVKey();
|
||||
VKey<HistoryEntry> historyEntryVKey =
|
||||
VKey.createOfy(HistoryEntry.class, Key.create(contactHistory.asHistoryEntry()));
|
||||
ContactHistory hostHistoryFromDb = tm().transact(() -> tm().load(contactHistoryVKey));
|
||||
@@ -110,8 +106,7 @@ public class ContactHistoryTest extends EntityTestCase {
|
||||
assertThat(hostHistoryFromDb).isEqualTo(historyEntryFromDb);
|
||||
}
|
||||
|
||||
private ContactHistory createContactHistory(
|
||||
ContactBase contact, VKey<ContactResource> contactVKey) {
|
||||
private ContactHistory createContactHistory(ContactBase contact, String contactRepoId) {
|
||||
return new ContactHistory.Builder()
|
||||
.setType(HistoryEntry.Type.HOST_CREATE)
|
||||
.setXmlBytes("<xml></xml>".getBytes(UTF_8))
|
||||
@@ -122,14 +117,14 @@ public class ContactHistoryTest extends EntityTestCase {
|
||||
.setReason("reason")
|
||||
.setRequestedByRegistrar(true)
|
||||
.setContactBase(contact)
|
||||
.setContactRepoId(contactVKey)
|
||||
.setContactRepoId(contactRepoId)
|
||||
.build();
|
||||
}
|
||||
|
||||
static void assertContactHistoriesEqual(ContactHistory one, ContactHistory two) {
|
||||
assertAboutImmutableObjects()
|
||||
.that(one)
|
||||
.isEqualExceptFields(two, "contactBase", "contactRepoId", "parent");
|
||||
.isEqualExceptFields(two, "contactBase", "contactRepoId");
|
||||
assertAboutImmutableObjects()
|
||||
.that(one.getContactBase().orElse(null))
|
||||
.isEqualExceptFields(two.getContactBase().orElse(null), "repoId");
|
||||
|
||||
@@ -59,7 +59,6 @@ public class DomainHistoryTest extends EntityTestCase {
|
||||
void testPersistence() {
|
||||
DomainBase domain = createDomainWithContactsAndHosts();
|
||||
DomainHistory domainHistory = createDomainHistory(domain);
|
||||
domainHistory.id = null;
|
||||
jpaTm().transact(() -> jpaTm().insert(domainHistory));
|
||||
|
||||
jpaTm()
|
||||
@@ -67,8 +66,7 @@ public class DomainHistoryTest extends EntityTestCase {
|
||||
() -> {
|
||||
DomainHistory fromDatabase = jpaTm().load(domainHistory.createVKey());
|
||||
assertDomainHistoriesEqual(fromDatabase, domainHistory);
|
||||
assertThat(fromDatabase.getDomainRepoId().getSqlKey())
|
||||
.isEqualTo(domainHistory.getDomainRepoId().getSqlKey());
|
||||
assertThat(fromDatabase.getParentVKey()).isEqualTo(domainHistory.getParentVKey());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -77,7 +75,6 @@ public class DomainHistoryTest extends EntityTestCase {
|
||||
DomainBase domain = createDomainWithContactsAndHosts();
|
||||
DomainHistory domainHistory =
|
||||
createDomainHistory(domain).asBuilder().setDomainContent(null).build();
|
||||
domainHistory.id = null;
|
||||
jpaTm().transact(() -> jpaTm().insert(domainHistory));
|
||||
|
||||
jpaTm()
|
||||
@@ -85,8 +82,7 @@ public class DomainHistoryTest extends EntityTestCase {
|
||||
() -> {
|
||||
DomainHistory fromDatabase = jpaTm().load(domainHistory.createVKey());
|
||||
assertDomainHistoriesEqual(fromDatabase, domainHistory);
|
||||
assertThat(fromDatabase.getDomainRepoId().getSqlKey())
|
||||
.isEqualTo(domainHistory.getDomainRepoId().getSqlKey());
|
||||
assertThat(fromDatabase.getParentVKey()).isEqualTo(domainHistory.getParentVKey());
|
||||
assertThat(fromDatabase.getNsHosts())
|
||||
.containsExactlyElementsIn(
|
||||
domainHistory.getNsHosts().stream()
|
||||
@@ -121,8 +117,7 @@ public class DomainHistoryTest extends EntityTestCase {
|
||||
// retrieving a HistoryEntry or a DomainHistory with the same key should return the same object
|
||||
// note: due to the @EntitySubclass annotation. all Keys for DomainHistory objects will have
|
||||
// type HistoryEntry
|
||||
VKey<DomainHistory> domainHistoryVKey =
|
||||
VKey.createOfy(DomainHistory.class, Key.create(domainHistory));
|
||||
VKey<DomainHistory> domainHistoryVKey = domainHistory.createVKey();
|
||||
VKey<HistoryEntry> historyEntryVKey =
|
||||
VKey.createOfy(HistoryEntry.class, Key.create(domainHistory.asHistoryEntry()));
|
||||
DomainHistory domainHistoryFromDb = tm().transact(() -> tm().load(domainHistoryVKey));
|
||||
@@ -155,7 +150,7 @@ public class DomainHistoryTest extends EntityTestCase {
|
||||
assertAboutImmutableObjects()
|
||||
.that(one)
|
||||
.isEqualExceptFields(
|
||||
two, "domainContent", "domainRepoId", "parent", "nsHosts", "domainTransactionRecords");
|
||||
two, "domainContent", "domainRepoId", "nsHosts", "domainTransactionRecords");
|
||||
assertThat(one.getDomainContent().map(DomainContent::getDomainName))
|
||||
.isEqualTo(two.getDomainContent().map(DomainContent::getDomainName));
|
||||
// NB: the record's ID gets reset by Hibernate, causing the hash code to differ so we have to
|
||||
|
||||
@@ -48,17 +48,14 @@ public class HostHistoryTest extends EntityTestCase {
|
||||
VKey<HostResource> hostVKey =
|
||||
VKey.create(HostResource.class, "host1", Key.create(HostResource.class, "host1"));
|
||||
HostResource hostFromDb = jpaTm().transact(() -> jpaTm().load(hostVKey));
|
||||
HostHistory hostHistory = createHostHistory(hostFromDb, hostVKey);
|
||||
hostHistory.id = null;
|
||||
HostHistory hostHistory = createHostHistory(hostFromDb, host.getRepoId());
|
||||
jpaTm().transact(() -> jpaTm().insert(hostHistory));
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
HostHistory fromDatabase =
|
||||
jpaTm().load(VKey.createSql(HostHistory.class, hostHistory.getId()));
|
||||
HostHistory fromDatabase = jpaTm().load(hostHistory.createVKey());
|
||||
assertHostHistoriesEqual(fromDatabase, hostHistory);
|
||||
assertThat(fromDatabase.getHostRepoId().getSqlKey())
|
||||
.isEqualTo(hostHistory.getHostRepoId().getSqlKey());
|
||||
assertThat(fromDatabase.getParentVKey()).isEqualTo(hostHistory.getParentVKey());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -68,23 +65,17 @@ public class HostHistoryTest extends EntityTestCase {
|
||||
HostResource host = newHostResourceWithRoid("ns1.example.com", "host1");
|
||||
jpaTm().transact(() -> jpaTm().insert(host));
|
||||
|
||||
VKey<HostResource> hostVKey =
|
||||
VKey.create(HostResource.class, "host1", Key.create(HostResource.class, "host1"));
|
||||
HostResource hostFromDb = jpaTm().transact(() -> jpaTm().load(hostVKey));
|
||||
|
||||
HostResource hostFromDb = jpaTm().transact(() -> jpaTm().load(host.createVKey()));
|
||||
HostHistory hostHistory =
|
||||
createHostHistory(hostFromDb, hostVKey).asBuilder().setHostBase(null).build();
|
||||
hostHistory.id = null;
|
||||
createHostHistory(hostFromDb, host.getRepoId()).asBuilder().setHostBase(null).build();
|
||||
jpaTm().transact(() -> jpaTm().insert(hostHistory));
|
||||
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
HostHistory fromDatabase =
|
||||
jpaTm().load(VKey.createSql(HostHistory.class, hostHistory.getId()));
|
||||
HostHistory fromDatabase = jpaTm().load(hostHistory.createVKey());
|
||||
assertHostHistoriesEqual(fromDatabase, hostHistory);
|
||||
assertThat(fromDatabase.getHostRepoId().getSqlKey())
|
||||
.isEqualTo(hostHistory.getHostRepoId().getSqlKey());
|
||||
assertThat(fromDatabase.getParentVKey()).isEqualTo(hostHistory.getParentVKey());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -97,14 +88,14 @@ public class HostHistoryTest extends EntityTestCase {
|
||||
VKey<HostResource> hostVKey =
|
||||
VKey.create(HostResource.class, "host1", Key.create(HostResource.class, "host1"));
|
||||
HostResource hostFromDb = tm().transact(() -> tm().load(hostVKey));
|
||||
HostHistory hostHistory = createHostHistory(hostFromDb, hostVKey);
|
||||
HostHistory hostHistory = createHostHistory(hostFromDb, host.getRepoId());
|
||||
fakeClock.advanceOneMilli();
|
||||
tm().transact(() -> tm().insert(hostHistory));
|
||||
|
||||
// retrieving a HistoryEntry or a HostHistory with the same key should return the same object
|
||||
// note: due to the @EntitySubclass annotation. all Keys for HostHistory objects will have
|
||||
// type HistoryEntry
|
||||
VKey<HostHistory> hostHistoryVKey = VKey.createOfy(HostHistory.class, Key.create(hostHistory));
|
||||
VKey<HostHistory> hostHistoryVKey = hostHistory.createVKey();
|
||||
VKey<HistoryEntry> historyEntryVKey =
|
||||
VKey.createOfy(HistoryEntry.class, Key.create(hostHistory.asHistoryEntry()));
|
||||
HostHistory hostHistoryFromDb = tm().transact(() -> tm().load(hostHistoryVKey));
|
||||
@@ -120,7 +111,7 @@ public class HostHistoryTest extends EntityTestCase {
|
||||
.isEqualExceptFields(two.getHostBase().orElse(null), "repoId");
|
||||
}
|
||||
|
||||
private HostHistory createHostHistory(HostBase hostBase, VKey<HostResource> hostVKey) {
|
||||
private HostHistory createHostHistory(HostBase hostBase, String hostRepoId) {
|
||||
return new HostHistory.Builder()
|
||||
.setType(HistoryEntry.Type.HOST_CREATE)
|
||||
.setXmlBytes("<xml></xml>".getBytes(UTF_8))
|
||||
@@ -131,7 +122,7 @@ public class HostHistoryTest extends EntityTestCase {
|
||||
.setReason("reason")
|
||||
.setRequestedByRegistrar(true)
|
||||
.setHostBase(hostBase)
|
||||
.setHostRepoId(hostVKey)
|
||||
.setHostRepoId(hostRepoId)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,6 @@ public class LegacyHistoryObjectTest extends EntityTestCase {
|
||||
ContactHistory legacyContactHistory = (ContactHistory) fromObjectify;
|
||||
|
||||
// Next, save that from-Datastore object in SQL and verify we can load it back in
|
||||
legacyContactHistory.id = null;
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
@@ -88,17 +87,13 @@ public class LegacyHistoryObjectTest extends EntityTestCase {
|
||||
jpaTm().insert(legacyContactHistory);
|
||||
});
|
||||
ContactHistory legacyHistoryFromSql =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.load(VKey.createSql(ContactHistory.class, legacyContactHistory.getId())));
|
||||
jpaTm().transact(() -> jpaTm().load(legacyContactHistory.createVKey()));
|
||||
assertAboutImmutableObjects()
|
||||
.that(legacyContactHistory)
|
||||
.isEqualExceptFields(legacyHistoryFromSql);
|
||||
// can't compare contactRepoId directly since it doesn't save the ofy key
|
||||
assertThat(legacyContactHistory.getContactRepoId().getSqlKey())
|
||||
.isEqualTo(legacyHistoryFromSql.getContactRepoId().getSqlKey());
|
||||
assertThat(legacyContactHistory.getParentVKey().getSqlKey())
|
||||
.isEqualTo(legacyHistoryFromSql.getParentVKey().getSqlKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -164,7 +159,6 @@ public class LegacyHistoryObjectTest extends EntityTestCase {
|
||||
HostHistory legacyHostHistory = (HostHistory) fromObjectify;
|
||||
|
||||
// Next, save that from-Datastore object in SQL and verify we can load it back in
|
||||
legacyHostHistory.id = null;
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
@@ -172,13 +166,11 @@ public class LegacyHistoryObjectTest extends EntityTestCase {
|
||||
jpaTm().insert(legacyHostHistory);
|
||||
});
|
||||
HostHistory legacyHistoryFromSql =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> jpaTm().load(VKey.createSql(HostHistory.class, legacyHostHistory.getId())));
|
||||
jpaTm().transact(() -> jpaTm().load(legacyHostHistory.createVKey()));
|
||||
assertAboutImmutableObjects().that(legacyHostHistory).isEqualExceptFields(legacyHistoryFromSql);
|
||||
// can't compare hostRepoId directly since it doesn't save the ofy key in SQL
|
||||
assertThat(legacyHostHistory.getHostRepoId().getSqlKey())
|
||||
.isEqualTo(legacyHistoryFromSql.getHostRepoId().getSqlKey());
|
||||
assertThat(legacyHostHistory.getParentVKey().getSqlKey())
|
||||
.isEqualTo(legacyHistoryFromSql.getParentVKey().getSqlKey());
|
||||
}
|
||||
|
||||
private HistoryEntry historyEntryForDomain(DomainBase domain) {
|
||||
|
||||
@@ -18,12 +18,15 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.testing.DatastoreHelper.createTld;
|
||||
import static google.registry.testing.DatastoreHelper.persistActiveDomain;
|
||||
import static google.registry.testing.DatastoreHelper.newDomainBase;
|
||||
import static google.registry.testing.DatastoreHelper.persistActiveContact;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
import static google.registry.testing.SqlHelper.saveRegistrar;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import google.registry.model.EntityTestCase;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
@@ -34,6 +37,7 @@ import org.junit.jupiter.api.Test;
|
||||
/** Unit tests for {@link PollMessage}. */
|
||||
public class PollMessageTest extends EntityTestCase {
|
||||
|
||||
private DomainBase domain;
|
||||
private HistoryEntry historyEntry;
|
||||
private PollMessage.OneTime oneTime;
|
||||
private PollMessage.Autorenew autoRenew;
|
||||
@@ -45,15 +49,17 @@ public class PollMessageTest extends EntityTestCase {
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
createTld("foobar");
|
||||
ContactResource contact = persistActiveContact("contact1234");
|
||||
domain = persistResource(newDomainBase("foo.foobar", contact));
|
||||
historyEntry =
|
||||
persistResource(
|
||||
new HistoryEntry.Builder()
|
||||
.setParent(persistActiveDomain("foo.foobar"))
|
||||
.setParent(domain)
|
||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||
.setPeriod(Period.create(1, Period.Unit.YEARS))
|
||||
.setXmlBytes("<xml></xml>".getBytes(UTF_8))
|
||||
.setModificationTime(fakeClock.nowUtc())
|
||||
.setClientId("foo")
|
||||
.setClientId("TheRegistrar")
|
||||
.setTrid(Trid.create("ABC-123", "server-trid"))
|
||||
.setBySuperuser(false)
|
||||
.setReason("reason")
|
||||
@@ -61,6 +67,7 @@ public class PollMessageTest extends EntityTestCase {
|
||||
.build());
|
||||
oneTime =
|
||||
new PollMessage.OneTime.Builder()
|
||||
.setId(100L)
|
||||
.setClientId("TheRegistrar")
|
||||
.setEventTime(fakeClock.nowUtc())
|
||||
.setMsg("Test poll message")
|
||||
@@ -68,6 +75,7 @@ public class PollMessageTest extends EntityTestCase {
|
||||
.build();
|
||||
autoRenew =
|
||||
new PollMessage.Autorenew.Builder()
|
||||
.setId(200L)
|
||||
.setClientId("TheRegistrar")
|
||||
.setEventTime(fakeClock.nowUtc())
|
||||
.setMsg("Test poll message")
|
||||
@@ -75,50 +83,46 @@ public class PollMessageTest extends EntityTestCase {
|
||||
.setAutorenewEndTime(fakeClock.nowUtc().plusDays(365))
|
||||
.setTargetId("foobar.foo")
|
||||
.build();
|
||||
// TODO(shicong): Remove these two lines after we use symmetric vkey and change the cloud sql
|
||||
// schema
|
||||
oneTime.id = null;
|
||||
autoRenew.id = null;
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
saveRegistrar("TheRegistrar");
|
||||
jpaTm().insert(contact);
|
||||
jpaTm().insert(domain);
|
||||
jpaTm().insert(historyEntry.toChildHistoryEntity());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCloudSqlPersistenceOneTime() {
|
||||
saveRegistrar("TheRegistrar");
|
||||
jpaTm().transact(() -> jpaTm().insert(oneTime));
|
||||
PollMessage.OneTime persisted =
|
||||
jpaTm().transact(() -> jpaTm().load(VKey.createSql(PollMessage.OneTime.class, oneTime.id)));
|
||||
persisted.parent = oneTime.parent;
|
||||
assertThat(persisted).isEqualTo(oneTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCloudSqlPersistenceAutorenew() {
|
||||
saveRegistrar("TheRegistrar");
|
||||
jpaTm().transact(() -> jpaTm().insert(autoRenew));
|
||||
PollMessage.Autorenew persisted =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> jpaTm().load(VKey.createSql(PollMessage.Autorenew.class, autoRenew.id)));
|
||||
persisted.parent = autoRenew.parent;
|
||||
assertThat(persisted).isEqualTo(autoRenew);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCloudSqlSupportForPolymorphicVKey() {
|
||||
saveRegistrar("TheRegistrar");
|
||||
|
||||
jpaTm().transact(() -> jpaTm().insert(oneTime));
|
||||
PollMessage persistedOneTime =
|
||||
jpaTm().transact(() -> jpaTm().load(VKey.createSql(PollMessage.class, oneTime.getId())));
|
||||
assertThat(persistedOneTime).isInstanceOf(PollMessage.OneTime.class);
|
||||
persistedOneTime.parent = oneTime.parent;
|
||||
assertThat(persistedOneTime).isEqualTo(oneTime);
|
||||
|
||||
jpaTm().transact(() -> jpaTm().insert(autoRenew));
|
||||
PollMessage persistedAutoRenew =
|
||||
jpaTm().transact(() -> jpaTm().load(VKey.createSql(PollMessage.class, autoRenew.getId())));
|
||||
assertThat(persistedAutoRenew).isInstanceOf(PollMessage.Autorenew.class);
|
||||
persistedAutoRenew.parent = oneTime.parent;
|
||||
assertThat(persistedAutoRenew).isEqualTo(autoRenew);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import static com.google.common.truth.Truth8.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import google.registry.model.billing.BillingEvent.OneTime;
|
||||
import google.registry.model.registrar.RegistrarContact;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
@@ -59,4 +60,60 @@ class VKeyTest {
|
||||
() -> VKey.create(RegistrarContact.class, "fake@example.com"));
|
||||
assertThat(thrown).hasMessageThat().contains("BackupGroupRoot");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRestoreOfy() {
|
||||
assertThat(VKey.restoreOfyFrom(null, TestObject.class, 100)).isNull();
|
||||
|
||||
VKey<TestObject> key = VKey.createSql(TestObject.class, "foo");
|
||||
VKey<TestObject> restored = key.restoreOfy(TestObject.class, "bar");
|
||||
assertThat(restored.getOfyKey())
|
||||
.isEqualTo(Key.create(Key.create(TestObject.class, "bar"), TestObject.class, "foo"));
|
||||
assertThat(restored.getSqlKey()).isEqualTo("foo");
|
||||
|
||||
assertThat(VKey.restoreOfyFrom(key).getOfyKey()).isEqualTo(Key.create(TestObject.class, "foo"));
|
||||
|
||||
restored = key.restoreOfy(OtherObject.class, "baz", TestObject.class, "bar");
|
||||
assertThat(restored.getOfyKey())
|
||||
.isEqualTo(
|
||||
Key.create(
|
||||
Key.create(Key.create(OtherObject.class, "baz"), TestObject.class, "bar"),
|
||||
TestObject.class,
|
||||
"foo"));
|
||||
|
||||
// Verify that we can use a key as the first argument.
|
||||
restored = key.restoreOfy(Key.create(TestObject.class, "bar"));
|
||||
assertThat(restored.getOfyKey())
|
||||
.isEqualTo(Key.create(Key.create(TestObject.class, "bar"), TestObject.class, "foo"));
|
||||
|
||||
// Verify that we get an exception when a key is not the first argument.
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> key.restoreOfy(TestObject.class, "foo", Key.create(TestObject.class, "bar")));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains("Objectify keys may only be used for the first argument");
|
||||
|
||||
// Verify other exception cases.
|
||||
thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> key.restoreOfy(TestObject.class, TestObject.class));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains("class google.registry.testing.TestObject used as a key value.");
|
||||
|
||||
thrown =
|
||||
assertThrows(IllegalArgumentException.class, () -> key.restoreOfy(TestObject.class, 1.5));
|
||||
assertThat(thrown).hasMessageThat().contains("Key value 1.5 must be a string or long.");
|
||||
|
||||
thrown = assertThrows(IllegalArgumentException.class, () -> key.restoreOfy(TestObject.class));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains("Missing value for last key of type class google.registry.testing.TestObject");
|
||||
}
|
||||
|
||||
@Entity
|
||||
static class OtherObject {}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import io.github.classgraph.ClassGraph;
|
||||
import io.github.classgraph.ClassInfo;
|
||||
import io.github.classgraph.ClassInfoList;
|
||||
@@ -72,6 +73,7 @@ public class EntityTest {
|
||||
.filter(ClassInfo::isStandardClass)
|
||||
.map(ClassInfo::loadClass)
|
||||
.filter(clazz -> !clazz.isAnnotationPresent(EntityForTesting.class))
|
||||
.filter(clazz -> !clazz.isAnnotationPresent(Embed.class))
|
||||
.map(Class::getName)
|
||||
.collect(toImmutableSet());
|
||||
}
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
|
||||
package google.registry.ui.server.registrar;
|
||||
|
||||
import static com.google.appengine.repackaged.com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static com.google.monitoring.metrics.contrib.LongMetricSubject.assertThat;
|
||||
import static google.registry.config.RegistryConfig.getGSuiteOutgoingEmailAddress;
|
||||
import static google.registry.config.RegistryConfig.getGSuiteOutgoingEmailDisplayName;
|
||||
|
||||
@@ -55,7 +55,7 @@ FROM (
|
||||
FROM
|
||||
`my-project-id.latest_datastore_export.Registry`
|
||||
WHERE
|
||||
enableInvoicing IS TRUE) ) AS BillingEvent
|
||||
invoicingEnabled IS TRUE) ) AS BillingEvent
|
||||
-- Gather billing ID from registrar table
|
||||
-- This is a 'JOIN' as opposed to 'LEFT JOIN' to filter out
|
||||
-- non-billable registrars
|
||||
|
||||
@@ -41,7 +41,7 @@ class google.registry.model.billing.BillingEvent$OneTime {
|
||||
@Id java.lang.Long id;
|
||||
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent;
|
||||
google.registry.model.billing.BillingEvent$Reason reason;
|
||||
google.registry.persistence.VKey<? extends google.registry.model.billing.BillingEvent> cancellationMatchingBillingEvent;
|
||||
google.registry.persistence.VKey<google.registry.model.billing.BillingEvent$Recurring> cancellationMatchingBillingEvent;
|
||||
google.registry.persistence.VKey<google.registry.model.domain.token.AllocationToken> allocationToken;
|
||||
java.lang.Integer periodYears;
|
||||
java.lang.String clientId;
|
||||
@@ -131,7 +131,6 @@ class google.registry.model.contact.ContactHistory {
|
||||
google.registry.model.domain.Period period;
|
||||
google.registry.model.eppcommon.Trid trid;
|
||||
google.registry.model.reporting.HistoryEntry$Type type;
|
||||
google.registry.persistence.VKey<google.registry.model.contact.ContactResource> contactRepoId;
|
||||
java.lang.Boolean requestedByRegistrar;
|
||||
java.lang.String clientId;
|
||||
java.lang.String otherClientId;
|
||||
@@ -272,7 +271,6 @@ class google.registry.model.domain.DomainHistory {
|
||||
google.registry.model.reporting.HistoryEntry$Type type;
|
||||
java.lang.Boolean requestedByRegistrar;
|
||||
java.lang.String clientId;
|
||||
java.lang.String domainRepoId;
|
||||
java.lang.String otherClientId;
|
||||
java.lang.String reason;
|
||||
java.util.Set<google.registry.model.reporting.DomainTransactionRecord> domainTransactionRecords;
|
||||
@@ -401,7 +399,6 @@ class google.registry.model.host.HostHistory {
|
||||
google.registry.model.eppcommon.Trid trid;
|
||||
google.registry.model.host.HostBase hostBase;
|
||||
google.registry.model.reporting.HistoryEntry$Type type;
|
||||
google.registry.persistence.VKey<google.registry.model.host.HostResource> hostRepoId;
|
||||
java.lang.Boolean requestedByRegistrar;
|
||||
java.lang.String clientId;
|
||||
java.lang.String otherClientId;
|
||||
|
||||
@@ -61,6 +61,11 @@ Below are the steps to submit a schema change:
|
||||
You'll want to have a look at the diffs in the golden schema to verify that
|
||||
all changes are intentional.
|
||||
|
||||
5. Run ./nom_build :db:generateFlywayIndex to regenerate the Flyway index.
|
||||
This is a file listing all of the current Flyway files. Its purpose is to
|
||||
produce a merge conflict when more than one person adds a Flyway file with
|
||||
the same sequence number.
|
||||
|
||||
Relevant files (under db/src/main/resources/sql/schema/):
|
||||
|
||||
* nomulus.golden.sql is the schema dump (pg_dump for postgres) of the final
|
||||
|
||||
+57
-1
@@ -59,8 +59,11 @@ ext {
|
||||
getJdbcAccessInfo = {
|
||||
if (allDbEnv.contains(dbServer)) {
|
||||
return getSocketFactoryAccessInfo(dbServer)
|
||||
} else {
|
||||
} else if (!dbServer.isEmpty()) {
|
||||
return getAccessInfoByHostPort(dbServer)
|
||||
} else {
|
||||
// Not connecting to a database. Return a dummy object for Flyway config.
|
||||
return [ url: '', user: '', password: '' ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +113,7 @@ task compileApiJar(type: Jar) {
|
||||
configurations {
|
||||
compileApi
|
||||
schema
|
||||
integration
|
||||
}
|
||||
|
||||
artifacts {
|
||||
@@ -166,6 +170,28 @@ dependencies {
|
||||
testCompile project(path: ':common', configuration: 'testing')
|
||||
}
|
||||
|
||||
task generateFlywayIndex {
|
||||
def flywayBase = "$projectDir/src/main/resources/sql/flyway"
|
||||
def filenamePattern = /V(\d+)__.*\.sql/
|
||||
|
||||
def getSeqNum = { file ->
|
||||
def match = file.getName() =~ filenamePattern
|
||||
if (match.size() != 1) {
|
||||
throw new IllegalArgumentException("Bad Flyway filename: $file")
|
||||
}
|
||||
return match[0][1] as int
|
||||
}
|
||||
|
||||
doLast {
|
||||
def files = new File(flywayBase).listFiles()
|
||||
def indexFile = new File("${flywayBase}.txt")
|
||||
indexFile.write ''
|
||||
for (def file : files.sort{a, b -> getSeqNum(a) <=> getSeqNum(b)}) {
|
||||
indexFile << "${file.name}\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flywayInfo.dependsOn('buildNeeded')
|
||||
flywayValidate.dependsOn('buildNeeded')
|
||||
|
||||
@@ -187,3 +213,33 @@ if (ext.isRestricted()) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (project.baseSchemaTag != '') {
|
||||
repositories {
|
||||
maven {
|
||||
url project.publish_repo
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
integration "google.registry:schema:${project.baseSchemaTag}"
|
||||
}
|
||||
|
||||
// Checks if Flyway scripts can be deployed to an existing database with
|
||||
// an older release. Please refer to SchemaTest.java for more information.
|
||||
task schemaIncrementalDeployTest(dependsOn: processResources, type: Test) {
|
||||
useJUnitPlatform()
|
||||
include 'google/registry/sql/flyway/SchemaTest.*'
|
||||
classpath = configurations.testRuntimeClasspath
|
||||
.plus(configurations.integration)
|
||||
.plus(files(sourceSets.test.output.classesDirs))
|
||||
.plus(files(sourceSets.test.output.resourcesDir))
|
||||
.plus(files(sourceSets.main.output.classesDirs))
|
||||
|
||||
// Declare test-runtime dependency on Flyway scripts in the resources dir.
|
||||
// They are not on classpath since they conflict with the base schema.
|
||||
inputs.dir sourceSets.main.output.resourcesDir
|
||||
|
||||
// Specifies which test to run using the following property
|
||||
systemProperty 'deploy_to_existing_db', 'true'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
V1__create_claims_list_and_entry.sql
|
||||
V2__create_premium_list_and_entry.sql
|
||||
V3__create_registry_lock.sql
|
||||
V4__registry_lock_add_index_on_verification_code.sql
|
||||
V5__update_premium_list.sql
|
||||
V6__premium_list_bloom_filter.sql
|
||||
V7__update_claims_list.sql
|
||||
V8__registry_lock_registrar_index.sql
|
||||
V9__premium_list_currency_type.sql
|
||||
V10__create_reserved_list_and_entry.sql
|
||||
V11__premium_entry_reorder_column.sql
|
||||
V12__create_cursor.sql
|
||||
V13__refactor_registry_lock.sql
|
||||
V14__load_extension_for_hstore.sql
|
||||
V15__add_epp_resources.sql
|
||||
V16__create_registrar.sql
|
||||
V17__create_registrar_poc.sql
|
||||
V18__create_lock.sql
|
||||
V19__add_registry_relock_reference.sql
|
||||
V20__add_relock_duration.sql
|
||||
V21__add_registry_lock_email_to_poc.sql
|
||||
V22__update_ns_hosts.sql
|
||||
V23__create_contact.sql
|
||||
V24__domain_base_contacts.sql
|
||||
V25__rename_vkey_fields.sql
|
||||
V26__create_billing_event.sql
|
||||
V27__create_pollmessage.sql
|
||||
V28__superordinate_domain_vkey.sql
|
||||
V29__add_columns_for_transfer_data.sql
|
||||
V30__inet_address_converter.sql
|
||||
V31__client_id_to_registrar_id.sql
|
||||
V32__drop_unused_transafer_data_columns_in_contact.sql
|
||||
V33__create_host_history.sql
|
||||
V34__rename_fully_qualified_names.sql
|
||||
V35__rename_allow_list.sql
|
||||
V36__create_safebrowsing_threats.sql
|
||||
V37__update_spec11threatmatch.sql
|
||||
V38__create_contact_history.sql
|
||||
V39__add_updatetime_column.sql
|
||||
V40__spec11threatmatch_remove_registrar_foreign_key.sql
|
||||
V41__add_columns_to_domain.sql
|
||||
V42__add_txn_table.sql
|
||||
V43__update_relock_duration_type.sql
|
||||
V44__create_domain_history.sql
|
||||
V45__add_grace_period_table.sql
|
||||
V46__Contact_contactId_index_to_non_unique.sql
|
||||
V47__remove_spec11_domain_foreign_key.sql
|
||||
V48__domain_add_autorenew_end_time_column.sql
|
||||
V49__create_allocation_token.sql
|
||||
V50__use_composite_key_for_registrar_poc.sql
|
||||
V51__use_composite_primary_key_for_domain_history_table.sql
|
||||
V52__update_billing_constraint.sql
|
||||
V53__add_temp_history_id_sequence.sql
|
||||
V54__add_tld_table.sql
|
||||
V55__domain_history_fields.sql
|
||||
V56__rename_host_table.sql
|
||||
V57__history_null_content.sql
|
||||
V58__drop_default_value_and_sequences_for_billing_event.sql
|
||||
V59__use_composite_primary_key_for_contact_and_host_history_table.sql
|
||||
V60__remove_pollmessage_sequence.sql
|
||||
V61__domain_hist_columns.sql
|
||||
V62__disable_key_auto_generation_for_history_tables.sql
|
||||
V63__add_schema_for_ds_data.sql
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
-- 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 "BillingCancellation" alter column billing_cancellation_id drop default;
|
||||
alter table "BillingEvent" alter column billing_event_id drop default;
|
||||
alter table "BillingRecurrence" alter column billing_recurrence_id drop default;
|
||||
|
||||
drop sequence "BillingCancellation_billing_cancellation_id_seq";
|
||||
drop sequence "BillingEvent_billing_event_id_seq";
|
||||
drop sequence "BillingRecurrence_billing_recurrence_id_seq";
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
-- 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 "ContactHistory" drop constraint "ContactHistory_pkey";
|
||||
|
||||
alter table "ContactHistory"
|
||||
add constraint "ContactHistory_pkey" primary key (contact_repo_id, history_revision_id);
|
||||
|
||||
alter table "HostHistory" drop constraint "HostHistory_pkey";
|
||||
|
||||
alter table "HostHistory"
|
||||
add constraint "HostHistory_pkey" primary key (host_repo_id, history_revision_id);
|
||||
@@ -0,0 +1,36 @@
|
||||
-- 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 "PollMessage" alter column poll_message_id drop default;
|
||||
|
||||
drop sequence "PollMessage_poll_message_id_seq";
|
||||
|
||||
alter table "PollMessage" rename column "domain_revision_id" to "domain_history_revision_id";
|
||||
alter table "PollMessage" rename column "contact_revision_id" to "contact_history_revision_id";
|
||||
alter table "PollMessage" rename column "host_revision_id" to "host_history_revision_id";
|
||||
|
||||
alter table if exists "PollMessage"
|
||||
add constraint fk_poll_message_domain_history
|
||||
foreign key (domain_repo_id, domain_history_revision_id)
|
||||
references "DomainHistory";
|
||||
|
||||
alter table if exists "PollMessage"
|
||||
add constraint fk_poll_message_contact_history
|
||||
foreign key (contact_repo_id, contact_history_revision_id)
|
||||
references "ContactHistory";
|
||||
|
||||
alter table if exists "PollMessage"
|
||||
add constraint fk_poll_message_host_history
|
||||
foreign key (host_repo_id, host_history_revision_id)
|
||||
references "HostHistory";
|
||||
@@ -0,0 +1,39 @@
|
||||
-- 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.
|
||||
|
||||
-- These history ids are technically foreign keys, we don't want to constrain
|
||||
-- them because they're temporary and we don't need to because they are
|
||||
-- already indirectly constrained by the relationships with the
|
||||
-- PollMessages/BillingEvents involved.
|
||||
ALTER TABLE "Domain" ADD COLUMN billing_recurrence_history_id int8;
|
||||
ALTER TABLE "Domain" ADD COLUMN autorenew_poll_message_history_id int8;
|
||||
ALTER TABLE "Domain" ADD COLUMN deletion_poll_message_history_id int8;
|
||||
ALTER TABLE "DomainHistory" ADD COLUMN billing_recurrence_history_id int8;
|
||||
ALTER TABLE "DomainHistory" ADD COLUMN autorenew_poll_message_history_id int8;
|
||||
ALTER TABLE "DomainHistory" ADD COLUMN deletion_poll_message_history_id int8;
|
||||
|
||||
-- Drop and re-add DomainHistory's Domain FK constraint to make it deferrable,
|
||||
-- this breaks a cycle with Domain -> PollMessage|BillingEvent -> History.
|
||||
ALTER TABLE "DomainHistory" DROP CONSTRAINT fk_domain_history_domain_repo_id;
|
||||
ALTER TABLE "DomainHistory"
|
||||
ADD CONSTRAINT fk_domain_history_domain_repo_id
|
||||
FOREIGN KEY (domain_repo_id) REFERENCES "Domain"(repo_id)
|
||||
DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
-- Same for PollMessage -> Domain, breaking Domain -> PollMessage -> Domain.
|
||||
ALTER TABLE "PollMessage" DROP CONSTRAINT fk_poll_message_domain_repo_id;
|
||||
ALTER TABLE "PollMessage"
|
||||
ADD CONSTRAINT fk_poll_message_domain_repo_id
|
||||
FOREIGN KEY (domain_repo_id) REFERENCES "Domain"(repo_id)
|
||||
DEFERRABLE INITIALLY DEFERRED;
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
-- 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.
|
||||
|
||||
drop sequence "history_id_sequence";
|
||||
|
||||
drop sequence "temp_history_id_sequence";
|
||||
@@ -0,0 +1,29 @@
|
||||
-- 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 "DelegationSignerData" (
|
||||
domain_repo_id text not null,
|
||||
key_tag int4 not null,
|
||||
algorithm int4 not null,
|
||||
digest bytea not null,
|
||||
digest_type int4 not null,
|
||||
primary key (domain_repo_id, key_tag)
|
||||
);
|
||||
|
||||
create index IDXhlqqd5uy98cjyos72d81x9j95 on "DelegationSignerData" (domain_repo_id);
|
||||
|
||||
alter table if exists "DelegationSignerData"
|
||||
add constraint FKtr24j9v14ph2mfuw2gsmt12kq
|
||||
foreign key (domain_repo_id)
|
||||
references "Domain";
|
||||
@@ -11,7 +11,6 @@
|
||||
-- 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 sequence temp_history_id_sequence start 1 increment 50;
|
||||
|
||||
create table "AllocationToken" (
|
||||
token text not null,
|
||||
@@ -30,7 +29,7 @@ create sequence temp_history_id_sequence start 1 increment 50;
|
||||
);
|
||||
|
||||
create table "BillingCancellation" (
|
||||
billing_cancellation_id bigserial not null,
|
||||
billing_cancellation_id int8 not null,
|
||||
registrar_id text not null,
|
||||
domain_history_revision_id int8 not null,
|
||||
domain_repo_id text not null,
|
||||
@@ -45,7 +44,7 @@ create sequence temp_history_id_sequence start 1 increment 50;
|
||||
);
|
||||
|
||||
create table "BillingEvent" (
|
||||
billing_event_id bigserial not null,
|
||||
billing_event_id int8 not null,
|
||||
registrar_id text not null,
|
||||
domain_history_revision_id int8 not null,
|
||||
domain_repo_id text not null,
|
||||
@@ -64,7 +63,7 @@ create sequence temp_history_id_sequence start 1 increment 50;
|
||||
);
|
||||
|
||||
create table "BillingRecurrence" (
|
||||
billing_recurrence_id bigserial not null,
|
||||
billing_recurrence_id int8 not null,
|
||||
registrar_id text not null,
|
||||
domain_history_revision_id int8 not null,
|
||||
domain_repo_id text not null,
|
||||
@@ -151,7 +150,8 @@ create sequence temp_history_id_sequence start 1 increment 50;
|
||||
);
|
||||
|
||||
create table "ContactHistory" (
|
||||
history_revision_id int8 not null,
|
||||
contact_repo_id text not null,
|
||||
history_revision_id int8 not null,
|
||||
history_by_superuser boolean not null,
|
||||
history_registrar_id text,
|
||||
history_modification_time timestamptz not null,
|
||||
@@ -215,8 +215,7 @@ create sequence temp_history_id_sequence start 1 increment 50;
|
||||
last_epp_update_time timestamptz,
|
||||
statuses text[],
|
||||
update_timestamp timestamptz,
|
||||
contact_repo_id text not null,
|
||||
primary key (history_revision_id)
|
||||
primary key (contact_repo_id, history_revision_id)
|
||||
);
|
||||
|
||||
create table "Cursor" (
|
||||
@@ -228,11 +227,12 @@ create sequence temp_history_id_sequence start 1 increment 50;
|
||||
);
|
||||
|
||||
create table "DelegationSignerData" (
|
||||
key_tag int4 not null,
|
||||
domain_repo_id text not null,
|
||||
key_tag int4 not null,
|
||||
algorithm int4 not null,
|
||||
digest bytea,
|
||||
digest bytea not null,
|
||||
digest_type int4 not null,
|
||||
primary key (key_tag)
|
||||
primary key (domain_repo_id, key_tag)
|
||||
);
|
||||
|
||||
create table "Domain" (
|
||||
@@ -249,10 +249,13 @@ create sequence temp_history_id_sequence start 1 increment 50;
|
||||
auth_info_repo_id text,
|
||||
auth_info_value text,
|
||||
billing_recurrence_id int8,
|
||||
billing_recurrence_history_id int8,
|
||||
autorenew_end_time timestamptz,
|
||||
autorenew_poll_message_id int8,
|
||||
autorenew_poll_message_history_id int8,
|
||||
billing_contact text,
|
||||
deletion_poll_message_id int8,
|
||||
deletion_poll_message_history_id int8,
|
||||
domain_name text,
|
||||
idn_table_name text,
|
||||
last_transfer_time timestamptz,
|
||||
@@ -301,10 +304,13 @@ create sequence temp_history_id_sequence start 1 increment 50;
|
||||
auth_info_repo_id text,
|
||||
auth_info_value text,
|
||||
billing_recurrence_id int8,
|
||||
billing_recurrence_history_id int8,
|
||||
autorenew_end_time timestamptz,
|
||||
autorenew_poll_message_id int8,
|
||||
autorenew_poll_message_history_id int8,
|
||||
billing_contact text,
|
||||
deletion_poll_message_id int8,
|
||||
deletion_poll_message_history_id int8,
|
||||
domain_name text,
|
||||
idn_table_name text,
|
||||
last_transfer_time timestamptz,
|
||||
@@ -400,7 +406,8 @@ create sequence temp_history_id_sequence start 1 increment 50;
|
||||
);
|
||||
|
||||
create table "HostHistory" (
|
||||
history_revision_id int8 not null,
|
||||
host_repo_id text not null,
|
||||
history_revision_id int8 not null,
|
||||
history_by_superuser boolean not null,
|
||||
history_registrar_id text,
|
||||
history_modification_time timestamptz not null,
|
||||
@@ -423,8 +430,7 @@ create sequence temp_history_id_sequence start 1 increment 50;
|
||||
last_epp_update_time timestamptz,
|
||||
statuses text[],
|
||||
update_timestamp timestamptz,
|
||||
host_repo_id text not null,
|
||||
primary key (history_revision_id)
|
||||
primary key (host_repo_id, history_revision_id)
|
||||
);
|
||||
|
||||
create table "Lock" (
|
||||
@@ -438,15 +444,15 @@ create sequence temp_history_id_sequence start 1 increment 50;
|
||||
|
||||
create table "PollMessage" (
|
||||
type text not null,
|
||||
poll_message_id bigserial not null,
|
||||
poll_message_id int8 not null,
|
||||
registrar_id text not null,
|
||||
contact_history_revision_id int8,
|
||||
contact_repo_id text,
|
||||
contact_revision_id int8,
|
||||
domain_history_revision_id int8,
|
||||
domain_repo_id text,
|
||||
domain_revision_id int8,
|
||||
event_time timestamptz not null,
|
||||
host_history_revision_id int8,
|
||||
host_repo_id text,
|
||||
host_revision_id int8,
|
||||
message text,
|
||||
transfer_response_contact_id text,
|
||||
transfer_response_domain_expiration_time timestamptz,
|
||||
@@ -663,6 +669,7 @@ create index IDXo1xdtpij2yryh0skxe9v91sep on "ContactHistory" (creation_time);
|
||||
create index IDXhp33wybmb6tbpr1bq7ttwk8je on "ContactHistory" (history_registrar_id);
|
||||
create index IDX9q53px6r302ftgisqifmc6put on "ContactHistory" (history_type);
|
||||
create index IDXsudwswtwqnfnx2o1hx4s0k0g5 on "ContactHistory" (history_modification_time);
|
||||
create index IDXhlqqd5uy98cjyos72d81x9j95 on "DelegationSignerData" (domain_repo_id);
|
||||
create index IDX8nr0ke9mrrx4ewj6pd2ag4rmr on "Domain" (creation_time);
|
||||
create index IDXhsjqiy2lyobfymplb28nm74lm on "Domain" (current_sponsor_registrar_id);
|
||||
create index IDX5mnf0wn20tno4b9do88j61klr on "Domain" (deletion_time);
|
||||
@@ -700,6 +707,11 @@ create index spec11threatmatch_check_date_idx on "Spec11ThreatMatch" (check_date
|
||||
foreign key (revision_id)
|
||||
references "ClaimsList";
|
||||
|
||||
alter table if exists "DelegationSignerData"
|
||||
add constraint FKtr24j9v14ph2mfuw2gsmt12kq
|
||||
foreign key (domain_repo_id)
|
||||
references "Domain";
|
||||
|
||||
alter table if exists "DomainHistoryHost"
|
||||
add constraint FKa9woh3hu8gx5x0vly6bai327n
|
||||
foreign key (domain_history_domain_repo_id, domain_history_history_revision_id)
|
||||
|
||||
@@ -73,25 +73,6 @@ CREATE TABLE public."BillingCancellation" (
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: BillingCancellation_billing_cancellation_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public."BillingCancellation_billing_cancellation_id_seq"
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: BillingCancellation_billing_cancellation_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public."BillingCancellation_billing_cancellation_id_seq" OWNED BY public."BillingCancellation".billing_cancellation_id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: BillingEvent; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
@@ -115,25 +96,6 @@ CREATE TABLE public."BillingEvent" (
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: BillingEvent_billing_event_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public."BillingEvent_billing_event_id_seq"
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: BillingEvent_billing_event_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public."BillingEvent_billing_event_id_seq" OWNED BY public."BillingEvent".billing_event_id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: BillingRecurrence; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
@@ -152,25 +114,6 @@ CREATE TABLE public."BillingRecurrence" (
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: BillingRecurrence_billing_recurrence_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public."BillingRecurrence_billing_recurrence_id_seq"
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: BillingRecurrence_billing_recurrence_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public."BillingRecurrence_billing_recurrence_id_seq" OWNED BY public."BillingRecurrence".billing_recurrence_id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: ClaimsEntry; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
@@ -360,6 +303,19 @@ CREATE TABLE public."Cursor" (
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: DelegationSignerData; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public."DelegationSignerData" (
|
||||
domain_repo_id text NOT NULL,
|
||||
key_tag integer NOT NULL,
|
||||
algorithm integer NOT NULL,
|
||||
digest bytea NOT NULL,
|
||||
digest_type integer NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Domain; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
@@ -410,7 +366,10 @@ CREATE TABLE public."Domain" (
|
||||
billing_recurrence_id bigint,
|
||||
autorenew_poll_message_id bigint,
|
||||
deletion_poll_message_id bigint,
|
||||
autorenew_end_time timestamp with time zone
|
||||
autorenew_end_time timestamp with time zone,
|
||||
billing_recurrence_history_id bigint,
|
||||
autorenew_poll_message_history_id bigint,
|
||||
deletion_poll_message_history_id bigint
|
||||
);
|
||||
|
||||
|
||||
@@ -477,7 +436,10 @@ CREATE TABLE public."DomainHistory" (
|
||||
autorenew_end_time timestamp with time zone,
|
||||
history_other_registrar_id text,
|
||||
history_period_unit text,
|
||||
history_period_value integer
|
||||
history_period_value integer,
|
||||
billing_recurrence_history_id bigint,
|
||||
autorenew_poll_message_history_id bigint,
|
||||
deletion_poll_message_history_id bigint
|
||||
);
|
||||
|
||||
|
||||
@@ -646,12 +608,12 @@ CREATE TABLE public."PollMessage" (
|
||||
poll_message_id bigint NOT NULL,
|
||||
registrar_id text NOT NULL,
|
||||
contact_repo_id text,
|
||||
contact_revision_id bigint,
|
||||
contact_history_revision_id bigint,
|
||||
domain_repo_id text,
|
||||
domain_revision_id bigint,
|
||||
domain_history_revision_id bigint,
|
||||
event_time timestamp with time zone NOT NULL,
|
||||
host_repo_id text,
|
||||
host_revision_id bigint,
|
||||
host_history_revision_id bigint,
|
||||
message text,
|
||||
transfer_response_contact_id text,
|
||||
transfer_response_domain_expiration_time timestamp with time zone,
|
||||
@@ -671,25 +633,6 @@ CREATE TABLE public."PollMessage" (
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: PollMessage_poll_message_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public."PollMessage_poll_message_id_seq"
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: PollMessage_poll_message_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public."PollMessage_poll_message_id_seq" OWNED BY public."PollMessage".poll_message_id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: PremiumEntry; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
@@ -1001,51 +944,6 @@ CREATE SEQUENCE public."Transaction_id_seq"
|
||||
ALTER SEQUENCE public."Transaction_id_seq" OWNED BY public."Transaction".id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: history_id_sequence; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.history_id_sequence
|
||||
START WITH 1
|
||||
INCREMENT BY 50
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: temp_history_id_sequence; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.temp_history_id_sequence
|
||||
START WITH 1
|
||||
INCREMENT BY 50
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: BillingCancellation billing_cancellation_id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."BillingCancellation" ALTER COLUMN billing_cancellation_id SET DEFAULT nextval('public."BillingCancellation_billing_cancellation_id_seq"'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: BillingEvent billing_event_id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."BillingEvent" ALTER COLUMN billing_event_id SET DEFAULT nextval('public."BillingEvent_billing_event_id_seq"'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: BillingRecurrence billing_recurrence_id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."BillingRecurrence" ALTER COLUMN billing_recurrence_id SET DEFAULT nextval('public."BillingRecurrence_billing_recurrence_id_seq"'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: ClaimsList revision_id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -1067,13 +965,6 @@ ALTER TABLE ONLY public."DomainTransactionRecord" ALTER COLUMN id SET DEFAULT ne
|
||||
ALTER TABLE ONLY public."GracePeriod" ALTER COLUMN id SET DEFAULT nextval('public."GracePeriod_id_seq"'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: PollMessage poll_message_id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."PollMessage" ALTER COLUMN poll_message_id SET DEFAULT nextval('public."PollMessage_poll_message_id_seq"'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: PremiumList revision_id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -1162,7 +1053,7 @@ ALTER TABLE ONLY public."ClaimsList"
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."ContactHistory"
|
||||
ADD CONSTRAINT "ContactHistory_pkey" PRIMARY KEY (history_revision_id);
|
||||
ADD CONSTRAINT "ContactHistory_pkey" PRIMARY KEY (contact_repo_id, history_revision_id);
|
||||
|
||||
|
||||
--
|
||||
@@ -1181,6 +1072,14 @@ ALTER TABLE ONLY public."Cursor"
|
||||
ADD CONSTRAINT "Cursor_pkey" PRIMARY KEY (scope, type);
|
||||
|
||||
|
||||
--
|
||||
-- Name: DelegationSignerData DelegationSignerData_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."DelegationSignerData"
|
||||
ADD CONSTRAINT "DelegationSignerData_pkey" PRIMARY KEY (domain_repo_id, key_tag);
|
||||
|
||||
|
||||
--
|
||||
-- Name: DomainHistory DomainHistory_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -1218,7 +1117,7 @@ ALTER TABLE ONLY public."GracePeriod"
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."HostHistory"
|
||||
ADD CONSTRAINT "HostHistory_pkey" PRIMARY KEY (history_revision_id);
|
||||
ADD CONSTRAINT "HostHistory_pkey" PRIMARY KEY (host_repo_id, history_revision_id);
|
||||
|
||||
|
||||
--
|
||||
@@ -1494,6 +1393,13 @@ CREATE INDEX idxeokttmxtpq2hohcioe5t2242b ON public."BillingCancellation" USING
|
||||
CREATE INDEX idxfg2nnjlujxo6cb9fha971bq2n ON public."HostHistory" USING btree (creation_time);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idxhlqqd5uy98cjyos72d81x9j95; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX idxhlqqd5uy98cjyos72d81x9j95 ON public."DelegationSignerData" USING btree (domain_repo_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idxhmv411mdqo5ibn4vy7ykxpmlv; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -1872,7 +1778,7 @@ ALTER TABLE ONLY public."Domain"
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."DomainHistory"
|
||||
ADD CONSTRAINT fk_domain_history_domain_repo_id FOREIGN KEY (domain_repo_id) REFERENCES public."Domain"(repo_id);
|
||||
ADD CONSTRAINT fk_domain_history_domain_repo_id FOREIGN KEY (domain_repo_id) REFERENCES public."Domain"(repo_id) DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
|
||||
--
|
||||
@@ -1979,6 +1885,14 @@ ALTER TABLE ONLY public."HostHistory"
|
||||
ADD CONSTRAINT fk_hosthistory_host FOREIGN KEY (host_repo_id) REFERENCES public."Host"(repo_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: PollMessage fk_poll_message_contact_history; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."PollMessage"
|
||||
ADD CONSTRAINT fk_poll_message_contact_history FOREIGN KEY (contact_repo_id, contact_history_revision_id) REFERENCES public."ContactHistory"(contact_repo_id, history_revision_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: PollMessage fk_poll_message_contact_repo_id; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -1987,12 +1901,28 @@ ALTER TABLE ONLY public."PollMessage"
|
||||
ADD CONSTRAINT fk_poll_message_contact_repo_id FOREIGN KEY (contact_repo_id) REFERENCES public."Contact"(repo_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: PollMessage fk_poll_message_domain_history; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."PollMessage"
|
||||
ADD CONSTRAINT fk_poll_message_domain_history FOREIGN KEY (domain_repo_id, domain_history_revision_id) REFERENCES public."DomainHistory"(domain_repo_id, history_revision_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: PollMessage fk_poll_message_domain_repo_id; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."PollMessage"
|
||||
ADD CONSTRAINT fk_poll_message_domain_repo_id FOREIGN KEY (domain_repo_id) REFERENCES public."Domain"(repo_id);
|
||||
ADD CONSTRAINT fk_poll_message_domain_repo_id FOREIGN KEY (domain_repo_id) REFERENCES public."Domain"(repo_id) DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
|
||||
--
|
||||
-- Name: PollMessage fk_poll_message_host_history; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."PollMessage"
|
||||
ADD CONSTRAINT fk_poll_message_host_history FOREIGN KEY (host_repo_id, host_history_revision_id) REFERENCES public."HostHistory"(host_repo_id, history_revision_id);
|
||||
|
||||
|
||||
--
|
||||
@@ -2083,6 +2013,14 @@ ALTER TABLE ONLY public."PremiumEntry"
|
||||
ADD CONSTRAINT fko0gw90lpo1tuee56l0nb6y6g5 FOREIGN KEY (revision_id) REFERENCES public."PremiumList"(revision_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: DelegationSignerData fktr24j9v14ph2mfuw2gsmt12kq; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."DelegationSignerData"
|
||||
ADD CONSTRAINT fktr24j9v14ph2mfuw2gsmt12kq FOREIGN KEY (domain_repo_id) REFERENCES public."Domain"(repo_id);
|
||||
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
||||
|
||||
@@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.truth.TextDiffSubject.assertThat;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.io.Resources;
|
||||
import google.registry.persistence.NomulusPostgreSql;
|
||||
import java.io.File;
|
||||
@@ -26,16 +27,41 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Paths;
|
||||
import org.flywaydb.core.Flyway;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
|
||||
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
|
||||
import org.testcontainers.containers.BindMode;
|
||||
import org.testcontainers.containers.Container.ExecResult;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
/** Unit tests about Cloud SQL schema. */
|
||||
/**
|
||||
* Schema deployment tests using Flyway.
|
||||
*
|
||||
* <p>This class has two test methods:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link #deploySchema_emptyDb()} is invoked only in UNIT tests (:db:test in Gradle). It
|
||||
* deploys the entire set of Flyway scripts (found on classpath) to an empty database and
|
||||
* compares the resulting schema with the golden schema.
|
||||
* <li>{@link #deploySchema_existingDb()} is invoked only in an integration test
|
||||
* (:db:schemaIncrementalDeployTest in Gradle). It first populates the test database with an
|
||||
* earlier release of the schema (found on the classpath), then deploys the latest Flyway
|
||||
* scripts (found on local filesystem under the resources directory) to that database. This
|
||||
* test detects all forbidden changes to deployed scripts including content change, file
|
||||
* renaming, and file deletion.
|
||||
* <p>This test also checks for out-of-order version numbers, i.e., new scripts with lower
|
||||
* numbers than that of the last deployed script. Out-of-order versions are confusing to
|
||||
* maintainers, however, Flyway does not provide ways to check before schema deployment. In
|
||||
* this test, out-of-order scripts are ignored in the incremental-deployment phase (default
|
||||
* Flyway behavior). The final validate call will fail on them.
|
||||
* </ul>
|
||||
*/
|
||||
@Testcontainers
|
||||
class SchemaTest {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
// Resource path that is mapped to the testcontainer instance.
|
||||
private static final String MOUNTED_RESOURCE_PATH = "testcontainer/mount";
|
||||
// The mount point in the container.
|
||||
@@ -57,7 +83,8 @@ class SchemaTest {
|
||||
MOUNTED_RESOURCE_PATH, CONTAINER_MOUNT_POINT, BindMode.READ_WRITE);
|
||||
|
||||
@Test
|
||||
void deploySchema_success() throws Exception {
|
||||
@DisabledIfSystemProperty(named = "deploy_to_existing_db", matches = ".*")
|
||||
void deploySchema_emptyDb() throws Exception {
|
||||
Flyway flyway =
|
||||
Flyway.configure()
|
||||
.locations("sql/flyway")
|
||||
@@ -86,6 +113,32 @@ class SchemaTest {
|
||||
.hasSameContentAs(Resources.getResource("sql/schema/nomulus.golden.sql"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnabledIfSystemProperty(named = "deploy_to_existing_db", matches = ".*")
|
||||
void deploySchema_existingDb() {
|
||||
// Initialize database with the base schema, which is on the classpath.
|
||||
Flyway flyway =
|
||||
Flyway.configure()
|
||||
.locations("sql/flyway")
|
||||
.dataSource(
|
||||
sqlContainer.getJdbcUrl(), sqlContainer.getUsername(), sqlContainer.getPassword())
|
||||
.load();
|
||||
flyway.migrate();
|
||||
logger.atInfo().log("Base schema version: %s", flyway.info().current().getVersion().toString());
|
||||
|
||||
// Deploy latest scripts from resources directory.
|
||||
flyway =
|
||||
Flyway.configure()
|
||||
.locations("filesystem:build/resources/main/sql/flyway")
|
||||
.dataSource(
|
||||
sqlContainer.getJdbcUrl(), sqlContainer.getUsername(), sqlContainer.getPassword())
|
||||
.load();
|
||||
flyway.migrate();
|
||||
flyway.validate();
|
||||
logger.atInfo().log(
|
||||
"Latest schema version: %s", flyway.info().current().getVersion().toString());
|
||||
}
|
||||
|
||||
private static String[] getSchemaDumpCommand(String username, String dbName) {
|
||||
return new String[] {
|
||||
"pg_dump",
|
||||
|
||||
@@ -124,6 +124,7 @@ ext {
|
||||
'org.apache.ftpserver:ftpserver-core:1.0.6',
|
||||
'org.apache.httpcomponents:httpclient:4.5.11',
|
||||
'org.apache.httpcomponents:httpcore:4.4.13',
|
||||
'org.apache.logging.log4j:log4j-core:2.13.3',
|
||||
'org.apache.sshd:sshd-core:2.0.0',
|
||||
'org.apache.sshd:sshd-scp:2.0.0',
|
||||
'org.apache.sshd:sshd-sftp:2.0.0',
|
||||
@@ -156,6 +157,8 @@ ext {
|
||||
'org.testcontainers:selenium:1.14.3',
|
||||
'org.testcontainers:testcontainers:1.14.3',
|
||||
'org.yaml:snakeyaml:1.17',
|
||||
'us.fatehi:schemacrawler:16.10.1',
|
||||
'us.fatehi:schemacrawler-diagram:16.10.1',
|
||||
'xerces:xmlParserAPIs:2.6.2',
|
||||
'xpp3:xpp3:1.1.4c'
|
||||
]
|
||||
|
||||
@@ -201,8 +201,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -251,5 +253,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -199,8 +199,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -247,5 +249,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -201,8 +201,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -251,5 +253,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -201,8 +201,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -251,5 +253,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -204,9 +204,11 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -261,5 +263,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -203,9 +203,11 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -259,5 +261,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -204,9 +204,11 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -261,5 +263,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -204,9 +204,11 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -261,5 +263,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -11,6 +11,7 @@ You will need the following programs installed on your local machine:
|
||||
* [Google App Engine SDK for Java][app-engine-sdk], and configure aliases to
|
||||
to the `gcloud` and `appcfg.sh` utilities (you'll use them a lot).
|
||||
* [Git](https://git-scm.com/) version control system.
|
||||
* Python version 3.7 or newer.
|
||||
|
||||
**Note:** App Engine does not yet support Java 9. Also, the instructions in this
|
||||
document have only been tested on Linux. They might work with some alterations
|
||||
|
||||
@@ -24,6 +24,7 @@ dbName=postgres
|
||||
dbUser=
|
||||
dbPassword=
|
||||
publish_repo=
|
||||
baseSchemaTag=
|
||||
schema_version=
|
||||
nomulus_version=
|
||||
dot_path=/usr/bin/dot
|
||||
|
||||
@@ -79,6 +79,8 @@ function runTest() {
|
||||
echo "Running test with -Pnomulus_version=${nomulus_version}" \
|
||||
"-Pschema_version=${schema_version}"
|
||||
|
||||
# The https scheme in the Maven repo URL below is required for Kokoro. See
|
||||
# ./run_schema_check.sh for more information.
|
||||
(cd ${SCRIPT_DIR}/..; \
|
||||
./gradlew :integration:sqlIntegrationTest \
|
||||
-PdevProject=${dev_project} \
|
||||
|
||||
@@ -25,12 +25,13 @@ $(basename "$0") OPTIONS
|
||||
Checks for post-deployment change to Flyway scripts.
|
||||
|
||||
With Flyway, once an incremental change script is deployed, it must not be
|
||||
changed. Even changes to comments or whitespaces would cause validation
|
||||
failures during future deployment. This script checks for changes (including
|
||||
removal and renaming which may happen due to incorrect merge conflict
|
||||
resolution) to scripts that have already been deployed to Sandbox. The
|
||||
assumption is that the schema in Sandbox is always newer than that in
|
||||
production.
|
||||
edited, renamed, or deleted. This script checks for changes to scripts that have
|
||||
already been deployed to Sandbox. The assumption is that the schema in Sandbox
|
||||
is always at least as recent as that in production. Please refer to Gradle task
|
||||
:db:schemaIncrementalDeployTest for more information.
|
||||
|
||||
Note that this test MAY fail to catch forbidden changes during the period when
|
||||
a new schema release is created but not yet deployed to Sandbox.
|
||||
|
||||
A side-effect of this check is that old branches missing recently deployed
|
||||
scripts must update first.
|
||||
@@ -65,16 +66,14 @@ fi
|
||||
|
||||
sandbox_tag=$(fetchVersion sql sandbox ${DEV_PROJECT})
|
||||
echo "Checking Flyway scripts against schema in Sandbox (${sandbox_tag})."
|
||||
modified_sqls=$(git diff --name-status ${sandbox_tag} \
|
||||
db/src/main/resources/sql/flyway | grep "^M\|^D\|^R" | grep \.sql$ | wc -l)
|
||||
|
||||
if [[ ${modified_sqls} = 0 ]]; then
|
||||
echo "No illegal change to deployed schema scripts."
|
||||
exit 0
|
||||
else
|
||||
echo "Changes to the following files are not allowed:"
|
||||
echo $(git diff --name-status ${sandbox_tag} \
|
||||
db/src/main/resources/sql/flyway | grep "^M\|^D\|^R" | grep \.sql$)
|
||||
echo "Make sure your branch is up to date with HEAD of master."
|
||||
exit 1
|
||||
fi
|
||||
# The URL of the Maven repo on GCS for the publish_repo parameter must use the
|
||||
# https scheme (https://storage.googleapis.com/{BUCKET}/{PATH}) in order to work
|
||||
# with Kokoro. Gradle's alternative gcs scheme does not work on Kokoro: a GCP
|
||||
# credential with proper scopes for GCS access is required even for public
|
||||
# buckets, however, Kokoro VM instances are not set up with such credentials.
|
||||
# Incidentally, gcs can be used on Cloud Build.
|
||||
(cd ${SCRIPT_DIR}/..; \
|
||||
./gradlew :db:schemaIncrementalDeployTest \
|
||||
-PbaseSchemaTag=${sandbox_tag} \
|
||||
-Ppublish_repo=https://storage.googleapis.com/${DEV_PROJECT}-deployed-tags/maven)
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import dagger.Lazy;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.networking.util.SelfSignedCaCertificate;
|
||||
import google.registry.util.SelfSignedCaCertificate;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import static google.registry.networking.handler.SslInitializerTestUtils.signKey
|
||||
import static google.registry.networking.handler.SslInitializerTestUtils.verifySslException;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.networking.util.SelfSignedCaCertificate;
|
||||
import google.registry.util.SelfSignedCaCertificate;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import google.registry.networking.util.SelfSignedCaCertificate;
|
||||
import google.registry.util.SelfSignedCaCertificate;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.handler.ssl.SslHandler;
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import static google.registry.networking.handler.SslServerInitializer.CLIENT_CER
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.networking.util.SelfSignedCaCertificate;
|
||||
import google.registry.util.SelfSignedCaCertificate;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ import dagger.Component;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.networking.module.CertificateSupplierModule.Mode;
|
||||
import google.registry.networking.util.SelfSignedCaCertificate;
|
||||
import google.registry.util.SelfSignedCaCertificate;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.security.KeyPair;
|
||||
|
||||
@@ -18,9 +18,6 @@ spec:
|
||||
containers:
|
||||
- name: proxy-canary
|
||||
image: gcr.io/GCP_PROJECT/proxy
|
||||
resources:
|
||||
requests:
|
||||
cpu: "101m"
|
||||
ports:
|
||||
- containerPort: 30000
|
||||
name: health-check
|
||||
|
||||
@@ -18,9 +18,6 @@ spec:
|
||||
containers:
|
||||
- name: proxy
|
||||
image: gcr.io/GCP_PROJECT/proxy
|
||||
resources:
|
||||
requests:
|
||||
cpu: "101m"
|
||||
ports:
|
||||
- containerPort: 30000
|
||||
name: health-check
|
||||
|
||||
@@ -23,9 +23,9 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import google.registry.networking.util.SelfSignedCaCertificate;
|
||||
import google.registry.proxy.handler.HttpsRelayServiceHandler.NonOkHttpResponseException;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.util.SelfSignedCaCertificate;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.embedded.EmbeddedChannel;
|
||||
|
||||
@@ -27,10 +27,10 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import google.registry.networking.util.SelfSignedCaCertificate;
|
||||
import google.registry.proxy.TestUtils;
|
||||
import google.registry.proxy.handler.HttpsRelayServiceHandler.NonOkHttpResponseException;
|
||||
import google.registry.proxy.metric.FrontendMetrics;
|
||||
import google.registry.util.SelfSignedCaCertificate;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
|
||||
@@ -63,17 +63,6 @@ steps:
|
||||
- --credential
|
||||
- tool-credential.json
|
||||
- deploy_invoicing_pipeline
|
||||
# Save the deployed tag for the current environment on GCS. Because of b/137891685
|
||||
# which causes the for-loop in the next step to fail, this may not be the last step.
|
||||
# TODO(weiminyu): do this in last step.
|
||||
- name: 'gcr.io/$PROJECT_ID/builder:latest'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
echo ${TAG_NAME} | \
|
||||
gsutil cp - gs://$PROJECT_ID-deployed-tags/nomulus.${_ENV}.tag
|
||||
# Deploy the GAE config files.
|
||||
# First authorize the gcloud tool to use the credential json file, then
|
||||
# download and unzip the tarball that contains the relevant config files
|
||||
@@ -97,6 +86,39 @@ steps:
|
||||
gcloud -q --project $project_id app deploy \
|
||||
default/WEB-INF/appengine-generated/$filename.yaml
|
||||
done
|
||||
# Save the deployed tag for the current environment on GCS, and update the
|
||||
# mappings from Nomulus releases to Appengine versions.
|
||||
- name: 'gcr.io/$PROJECT_ID/builder:latest'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
echo ${TAG_NAME} | \
|
||||
gsutil cp - gs://$PROJECT_ID-deployed-tags/nomulus.${_ENV}.tag
|
||||
# Update the release to AppEngine version mapping.
|
||||
if [ ${_ENV} == production ]; then
|
||||
project_id="domain-registry"
|
||||
else
|
||||
project_id="domain-registry-${_ENV}"
|
||||
fi
|
||||
local_map="nomulus.${_ENV}.tmp"
|
||||
gcloud app versions list \
|
||||
--project $project_id --hide-no-traffic \
|
||||
--format="csv[no-heading](SERVICE,VERSION.ID)" | \
|
||||
grep -e "^backend\|^default\|^pubapi\|^tools" |\
|
||||
while read line; do echo "${TAG_NAME},$line"; done | tee "$local_map"
|
||||
num_versions=$(cat "$local_map" | wc -l)
|
||||
if [ "$num_versions" -ne 4 ]; then
|
||||
echo "Expecting exactly four active services. Found $num_versions"
|
||||
exit 1
|
||||
fi
|
||||
gsutil cp "$local_map" gs://$PROJECT_ID-deployed-tags/nomulus.${_ENV}.tmp
|
||||
# Atomically append uploaded tmp file to nomulus.${_ENV}.versions
|
||||
gsutil compose \
|
||||
gs://$PROJECT_ID-deployed-tags/nomulus.${_ENV}.versions \
|
||||
gs://$PROJECT_ID-deployed-tags/nomulus.${_ENV}.tmp \
|
||||
gs://$PROJECT_ID-deployed-tags/nomulus.${_ENV}.versions
|
||||
|
||||
timeout: 3600s
|
||||
options:
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,8 +200,10 @@ org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user