mirror of
https://github.com/google/nomulus
synced 2026-06-09 16:33:02 +00:00
Compare commits
20 Commits
nomulus-20
...
proxy-2019
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c584de9f72 | ||
|
|
9be5091c84 | ||
|
|
28499d23a0 | ||
|
|
961d7e88f4 | ||
|
|
215de62fa7 | ||
|
|
05d56fe1a2 | ||
|
|
e318f47fc6 | ||
|
|
cc5f62587e | ||
|
|
02846bcbdd | ||
|
|
c920f709ef | ||
|
|
ad9daac1ab | ||
|
|
9f0e24132a | ||
|
|
98414cb7cb | ||
|
|
6af1896362 | ||
|
|
68887d427f | ||
|
|
8a06ef09c0 | ||
|
|
9e0368b77c | ||
|
|
05c45da07a | ||
|
|
365c5da942 | ||
|
|
2cc2571375 |
3
buildSrc/gradle/dependency-locks/apt.lockfile
Normal file
3
buildSrc/gradle/dependency-locks/apt.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
3
buildSrc/gradle/dependency-locks/archives.lockfile
Normal file
3
buildSrc/gradle/dependency-locks/archives.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
61
buildSrc/gradle/dependency-locks/default.lockfile
Normal file
61
buildSrc/gradle/dependency-locks/default.lockfile
Normal file
@@ -0,0 +1,61 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
aopalliance:aopalliance:1.0
|
||||
args4j:args4j:2.0.23
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.google.api-client:google-api-client:1.27.0
|
||||
com.google.api.grpc:proto-google-common-protos:1.12.0
|
||||
com.google.api.grpc:proto-google-iam-v1:0.12.0
|
||||
com.google.api:api-common:1.7.0
|
||||
com.google.api:gax-httpjson:0.52.1
|
||||
com.google.api:gax:1.35.1
|
||||
com.google.apis:google-api-services-storage:v1-rev20181013-1.27.0
|
||||
com.google.auth:google-auth-library-credentials:0.16.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.16.1
|
||||
com.google.auto.value:auto-value-annotations:1.6.3
|
||||
com.google.cloud:google-cloud-core-http:1.59.0
|
||||
com.google.cloud:google-cloud-core:1.59.0
|
||||
com.google.cloud:google-cloud-storage:1.59.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.7
|
||||
com.google.common.html.types:types:1.0.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.8.0-beta1
|
||||
com.google.http-client:google-http-client-appengine:1.27.0
|
||||
com.google.http-client:google-http-client-jackson2:1.30.1
|
||||
com.google.http-client:google-http-client:1.30.1
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.template:soy:2018-03-14
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
io.grpc:grpc-context:1.19.0
|
||||
io.opencensus:opencensus-api:0.21.0
|
||||
io.opencensus:opencensus-contrib-http-util:0.21.0
|
||||
javax.annotation:javax.annotation-api:1.2
|
||||
javax.annotation:jsr250-api:1.0
|
||||
javax.inject:javax.inject:1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
joda-time:joda-time:2.9.2
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.commons:commons-text:1.6
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
org.apache.httpcomponents:httpcore:4.4.11
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
org.json:json:20160212
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
org.ow2.asm:asm-commons:6.0
|
||||
org.ow2.asm:asm-tree:6.0
|
||||
org.ow2.asm:asm-util:6.0
|
||||
org.ow2.asm:asm:6.0
|
||||
org.threeten:threetenbp:1.3.3
|
||||
24
buildSrc/gradle/dependency-locks/errorprone.lockfile
Normal file
24
buildSrc/gradle/dependency-locks/errorprone.lockfile
Normal file
@@ -0,0 +1,24 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
3
buildSrc/gradle/dependency-locks/testApt.lockfile
Normal file
3
buildSrc/gradle/dependency-locks/testApt.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
7
common/README.md
Normal file
7
common/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## Summary
|
||||
|
||||
This project holds some of the general-purpose utility classes that do not rely
|
||||
on the registry domain model.
|
||||
|
||||
This is an intermediate step in untangling the circular dependencies
|
||||
between :core and :util subprojects.
|
||||
52
common/build.gradle
Normal file
52
common/build.gradle
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
sourceSets {
|
||||
testing {
|
||||
java {
|
||||
compileClasspath += main.output
|
||||
runtimeClasspath += main.output
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
testingCompile.extendsFrom compile
|
||||
testingRuntime.extendsFrom runtime
|
||||
|
||||
// All testing util classes. Other projects may declare dependency as:
|
||||
// testCompile project(path: 'common', configuration: 'testing')
|
||||
testing
|
||||
}
|
||||
|
||||
task testingJar(type: Jar) {
|
||||
archiveBaseName = 'testing'
|
||||
from sourceSets.testing.output
|
||||
}
|
||||
|
||||
artifacts {
|
||||
testing testingJar
|
||||
}
|
||||
|
||||
dependencies {
|
||||
def deps = rootProject.dependencyMap
|
||||
|
||||
compile deps['com.google.code.findbugs:jsr305']
|
||||
compile deps['com.google.guava:guava']
|
||||
compile deps['javax.inject:javax.inject']
|
||||
compile deps['joda-time:joda-time']
|
||||
|
||||
testingCompile deps['com.google.flogger:flogger']
|
||||
testingRuntime deps['com.google.flogger:flogger-system-backend']
|
||||
}
|
||||
24
common/gradle/dependency-locks/annotationProcessor.lockfile
Normal file
24
common/gradle/dependency-locks/annotationProcessor.lockfile
Normal file
@@ -0,0 +1,24 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
3
common/gradle/dependency-locks/apt.lockfile
Normal file
3
common/gradle/dependency-locks/apt.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
3
common/gradle/dependency-locks/archives.lockfile
Normal file
3
common/gradle/dependency-locks/archives.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
18
common/gradle/dependency-locks/checkstyle.lockfile
Normal file
18
common/gradle/dependency-locks/checkstyle.lockfile
Normal file
@@ -0,0 +1,18 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
antlr:antlr:2.7.7
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.0-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.puppycrawl.tools:checkstyle:8.24
|
||||
commons-beanutils:commons-beanutils:1.9.4
|
||||
commons-collections:commons-collections:3.2.2
|
||||
info.picocli:picocli:4.0.3
|
||||
net.sf.saxon:Saxon-HE:9.9.1-4
|
||||
org.antlr:antlr4-runtime:4.7.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
13
common/gradle/dependency-locks/compile.lockfile
Normal file
13
common/gradle/dependency-locks/compile.lockfile
Normal file
@@ -0,0 +1,13 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
javax.inject:javax.inject:1
|
||||
joda-time:joda-time:2.9.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
13
common/gradle/dependency-locks/compileClasspath.lockfile
Normal file
13
common/gradle/dependency-locks/compileClasspath.lockfile
Normal file
@@ -0,0 +1,13 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
javax.inject:javax.inject:1
|
||||
joda-time:joda-time:2.9.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
3
common/gradle/dependency-locks/compileOnly.lockfile
Normal file
3
common/gradle/dependency-locks/compileOnly.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
13
common/gradle/dependency-locks/default.lockfile
Normal file
13
common/gradle/dependency-locks/default.lockfile
Normal file
@@ -0,0 +1,13 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
javax.inject:javax.inject:1
|
||||
joda-time:joda-time:2.9.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
24
common/gradle/dependency-locks/errorprone.lockfile
Normal file
24
common/gradle/dependency-locks/errorprone.lockfile
Normal file
@@ -0,0 +1,24 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
4
common/gradle/dependency-locks/errorproneJavac.lockfile
Normal file
4
common/gradle/dependency-locks/errorproneJavac.lockfile
Normal file
@@ -0,0 +1,4 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.errorprone:javac:9+181-r4173-1
|
||||
4
common/gradle/dependency-locks/jacocoAgent.lockfile
Normal file
4
common/gradle/dependency-locks/jacocoAgent.lockfile
Normal file
@@ -0,0 +1,4 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
org.jacoco:org.jacoco.agent:0.8.5
|
||||
11
common/gradle/dependency-locks/jacocoAnt.lockfile
Normal file
11
common/gradle/dependency-locks/jacocoAnt.lockfile
Normal file
@@ -0,0 +1,11 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
org.jacoco:org.jacoco.agent:0.8.5
|
||||
org.jacoco:org.jacoco.ant:0.8.5
|
||||
org.jacoco:org.jacoco.core:0.8.5
|
||||
org.jacoco:org.jacoco.report:0.8.5
|
||||
org.ow2.asm:asm-analysis:7.2
|
||||
org.ow2.asm:asm-commons:7.2
|
||||
org.ow2.asm:asm-tree:7.2
|
||||
org.ow2.asm:asm:7.2
|
||||
13
common/gradle/dependency-locks/runtime.lockfile
Normal file
13
common/gradle/dependency-locks/runtime.lockfile
Normal file
@@ -0,0 +1,13 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
javax.inject:javax.inject:1
|
||||
joda-time:joda-time:2.9.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
13
common/gradle/dependency-locks/runtimeClasspath.lockfile
Normal file
13
common/gradle/dependency-locks/runtimeClasspath.lockfile
Normal file
@@ -0,0 +1,13 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
javax.inject:javax.inject:1
|
||||
joda-time:joda-time:2.9.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
@@ -0,0 +1,24 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
3
common/gradle/dependency-locks/testApt.lockfile
Normal file
3
common/gradle/dependency-locks/testApt.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
13
common/gradle/dependency-locks/testCompile.lockfile
Normal file
13
common/gradle/dependency-locks/testCompile.lockfile
Normal file
@@ -0,0 +1,13 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
javax.inject:javax.inject:1
|
||||
joda-time:joda-time:2.9.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
13
common/gradle/dependency-locks/testCompileClasspath.lockfile
Normal file
13
common/gradle/dependency-locks/testCompileClasspath.lockfile
Normal file
@@ -0,0 +1,13 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
javax.inject:javax.inject:1
|
||||
joda-time:joda-time:2.9.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
3
common/gradle/dependency-locks/testCompileOnly.lockfile
Normal file
3
common/gradle/dependency-locks/testCompileOnly.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
13
common/gradle/dependency-locks/testRuntime.lockfile
Normal file
13
common/gradle/dependency-locks/testRuntime.lockfile
Normal file
@@ -0,0 +1,13 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
javax.inject:javax.inject:1
|
||||
joda-time:joda-time:2.9.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
13
common/gradle/dependency-locks/testRuntimeClasspath.lockfile
Normal file
13
common/gradle/dependency-locks/testRuntimeClasspath.lockfile
Normal file
@@ -0,0 +1,13 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
javax.inject:javax.inject:1
|
||||
joda-time:joda-time:2.9.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
3
common/gradle/dependency-locks/testing.lockfile
Normal file
3
common/gradle/dependency-locks/testing.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
@@ -0,0 +1,24 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
3
common/gradle/dependency-locks/testingApt.lockfile
Normal file
3
common/gradle/dependency-locks/testingApt.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
14
common/gradle/dependency-locks/testingCompile.lockfile
Normal file
14
common/gradle/dependency-locks/testingCompile.lockfile
Normal file
@@ -0,0 +1,14 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.flogger:flogger:0.1
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
javax.inject:javax.inject:1
|
||||
joda-time:joda-time:2.9.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
@@ -0,0 +1,14 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.flogger:flogger:0.1
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
javax.inject:javax.inject:1
|
||||
joda-time:joda-time:2.9.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
15
common/gradle/dependency-locks/testingRuntime.lockfile
Normal file
15
common/gradle/dependency-locks/testingRuntime.lockfile
Normal file
@@ -0,0 +1,15 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.flogger:flogger-system-backend:0.1
|
||||
com.google.flogger:flogger:0.1
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
javax.inject:javax.inject:1
|
||||
joda-time:joda-time:2.9.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
@@ -0,0 +1,15 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.flogger:flogger-system-backend:0.1
|
||||
com.google.flogger:flogger:0.1
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
javax.inject:javax.inject:1
|
||||
joda-time:joda-time:2.9.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
@@ -99,6 +99,12 @@ PRESUBMITS = {
|
||||
"System.(out|err).println is only allowed in tools/ packages. Please "
|
||||
"use a logger instead.",
|
||||
|
||||
# PostgreSQLContainer instantiation must specify docker tag
|
||||
PresubmitCheck(
|
||||
r"[\s\S]*new\s+PostgreSQLContainer(<[\s\S]*>)?\(\s*\)[\s\S]*",
|
||||
"java", {}):
|
||||
"PostgreSQLContainer instantiation must specify docker tag.",
|
||||
|
||||
# Various Soy linting checks
|
||||
PresubmitCheck(
|
||||
r".* (/\*)?\* {?@param ",
|
||||
|
||||
@@ -241,8 +241,12 @@ dependencies {
|
||||
compile deps['com.google.appengine:appengine-api-1.0-sdk']
|
||||
|
||||
// Known issue: nebula-lint misses inherited dependency.
|
||||
compile project(':common')
|
||||
testCompile project(path: ':common', configuration: 'testing')
|
||||
compile project(':third_party')
|
||||
compile project(':util')
|
||||
// Import NomulusPostreSql from ':db' for compile but exclude dependencies.
|
||||
compile project(path: ':db', configuration: 'compileApi')
|
||||
testRuntime project(':db')
|
||||
|
||||
// Include auto-value in compile until nebula-lint understands
|
||||
@@ -658,6 +662,8 @@ task outcastTest(type: FilteringTest) {
|
||||
|
||||
// Dedicated test suite for schema-dependent tests.
|
||||
task sqlIntegrationTest(type: FilteringTest) {
|
||||
systemProperties project.getProperties().subMap('sql_schema_resource_root')
|
||||
|
||||
excludeTestCases = false
|
||||
tests = ['google/registry/schema/integration/SqlIntegrationTestSuite.*']
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import static com.google.common.base.Predicates.equalTo;
|
||||
import static com.google.common.base.Predicates.in;
|
||||
import static com.google.common.base.Predicates.not;
|
||||
import static com.google.common.base.Strings.emptyToNull;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.Maps.filterValues;
|
||||
import static google.registry.model.CacheUtils.memoizeWithShortExpiration;
|
||||
@@ -31,9 +32,12 @@ import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.registry.Registry.TldType;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/** Utilities for finding and listing {@link Registry} entities. */
|
||||
@@ -53,16 +57,21 @@ public final class Registries {
|
||||
private static Supplier<ImmutableMap<String, TldType>> createFreshCache() {
|
||||
return memoizeWithShortExpiration(
|
||||
() ->
|
||||
tm()
|
||||
.doTransactionless(
|
||||
tm().doTransactionless(
|
||||
() -> {
|
||||
ImmutableMap.Builder<String, TldType> builder =
|
||||
new ImmutableMap.Builder<>();
|
||||
for (Registry registry :
|
||||
ofy().load().type(Registry.class).ancestor(getCrossTldKey())) {
|
||||
builder.put(registry.getTldStr(), registry.getTldType());
|
||||
}
|
||||
return builder.build();
|
||||
ImmutableSet<String> tlds =
|
||||
ofy()
|
||||
.load()
|
||||
.type(Registry.class)
|
||||
.ancestor(getCrossTldKey())
|
||||
.keys()
|
||||
.list()
|
||||
.stream()
|
||||
.map(Key::getName)
|
||||
.collect(toImmutableSet());
|
||||
return Registry.getAll(tlds).stream()
|
||||
.map(e -> Maps.immutableEntry(e.getTldStr(), e.getTldType()))
|
||||
.collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -80,6 +89,11 @@ public final class Registries {
|
||||
return ImmutableSet.copyOf(filterValues(cache.get(), equalTo(type)).keySet());
|
||||
}
|
||||
|
||||
/** Returns the Registry entities themselves of the given type loaded fresh from Datastore. */
|
||||
public static ImmutableSet<Registry> getTldEntitiesOfType(TldType type) {
|
||||
return Registry.getAll(filterValues(cache.get(), equalTo(type)).keySet());
|
||||
}
|
||||
|
||||
/** Pass-through check that the specified TLD exists, otherwise throw an IAE. */
|
||||
public static String assertTldExists(String tld) {
|
||||
checkArgument(
|
||||
|
||||
@@ -18,6 +18,8 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Predicates.equalTo;
|
||||
import static com.google.common.base.Predicates.not;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.Maps.toMap;
|
||||
import static google.registry.config.RegistryConfig.getSingletonCacheRefreshDuration;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
@@ -30,12 +32,15 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static org.joda.money.CurrencyUnit.USD;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.collect.Range;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
@@ -58,8 +63,10 @@ import google.registry.model.domain.fee.Fee;
|
||||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.model.registry.label.ReservedList;
|
||||
import google.registry.util.Idn;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -201,6 +208,25 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
return registry;
|
||||
}
|
||||
|
||||
/** Returns the registry entities for the given TLD strings, throwing if any don't exist. */
|
||||
static ImmutableSet<Registry> getAll(Set<String> tlds) {
|
||||
try {
|
||||
ImmutableMap<String, Optional<Registry>> registries = CACHE.getAll(tlds);
|
||||
ImmutableSet<String> missingRegistries =
|
||||
registries.entrySet().stream()
|
||||
.filter(e -> !e.getValue().isPresent())
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(toImmutableSet());
|
||||
if (missingRegistries.isEmpty()) {
|
||||
return registries.values().stream().map(Optional::get).collect(toImmutableSet());
|
||||
} else {
|
||||
throw new RegistryNotFoundException(missingRegistries);
|
||||
}
|
||||
} catch (ExecutionException e) {
|
||||
throw new RuntimeException("Unexpected error retrieving TLDs " + tlds, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the cache entry.
|
||||
*
|
||||
@@ -220,15 +246,27 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
new CacheLoader<String, Optional<Registry>>() {
|
||||
@Override
|
||||
public Optional<Registry> load(final String tld) {
|
||||
// Enter a transactionless context briefly; we don't want to enroll every TLD in a
|
||||
// transaction that might be wrapping this call.
|
||||
// Enter a transaction-less context briefly; we don't want to enroll every TLD in
|
||||
// a transaction that might be wrapping this call.
|
||||
return Optional.ofNullable(
|
||||
tm()
|
||||
.doTransactionless(
|
||||
() -> ofy()
|
||||
.load()
|
||||
.key(Key.create(getCrossTldKey(), Registry.class, tld))
|
||||
.now()));
|
||||
tm().doTransactionless(
|
||||
() ->
|
||||
ofy()
|
||||
.load()
|
||||
.key(Key.create(getCrossTldKey(), Registry.class, tld))
|
||||
.now()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Optional<Registry>> loadAll(Iterable<? extends String> tlds) {
|
||||
ImmutableMap<String, Key<Registry>> keysMap =
|
||||
toMap(
|
||||
ImmutableSet.copyOf(tlds),
|
||||
tld -> Key.create(getCrossTldKey(), Registry.class, tld));
|
||||
Map<Key<Registry>, Registry> entities =
|
||||
tm().doTransactionless(() -> ofy().load().keys(keysMap.values()));
|
||||
return Maps.transformEntries(
|
||||
keysMap, (k, v) -> Optional.ofNullable(entities.getOrDefault(v, null)));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -883,10 +921,14 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
}
|
||||
}
|
||||
|
||||
/** Exception to throw when no Registry is found for a given tld. */
|
||||
/** Exception to throw when no Registry entity is found for given TLD string(s). */
|
||||
public static class RegistryNotFoundException extends RuntimeException {
|
||||
RegistryNotFoundException(ImmutableSet<String> tlds) {
|
||||
super("No registry object(s) found for " + Joiner.on(", ").join(tlds));
|
||||
}
|
||||
|
||||
RegistryNotFoundException(String tld) {
|
||||
super("No registry object found for " + tld);
|
||||
this(ImmutableSet.of(tld));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,16 +14,13 @@
|
||||
|
||||
package google.registry.model.transaction;
|
||||
|
||||
import static google.registry.config.RegistryEnvironment.ALPHA;
|
||||
import static google.registry.config.RegistryEnvironment.CRASH;
|
||||
import static google.registry.config.RegistryEnvironment.SANDBOX;
|
||||
|
||||
import com.google.appengine.api.utils.SystemProperty;
|
||||
import com.google.appengine.api.utils.SystemProperty.Environment.Value;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.ofy.DatastoreTransactionManager;
|
||||
import google.registry.persistence.DaggerPersistenceComponent;
|
||||
import google.registry.tools.RegistryToolEnvironment;
|
||||
|
||||
/** Factory class to create {@link TransactionManager} instance. */
|
||||
// TODO: Rename this to PersistenceFactory and move to persistence package.
|
||||
@@ -35,8 +32,11 @@ public class TransactionManagerFactory {
|
||||
private TransactionManagerFactory() {}
|
||||
|
||||
private static JpaTransactionManager createJpaTransactionManager() {
|
||||
if (shouldEnableJpaTm() && isInAppEngine()) {
|
||||
if (isInAppEngine()) {
|
||||
return DaggerPersistenceComponent.create().appEngineJpaTransactionManager();
|
||||
} else if (RegistryToolEnvironment.isInRegistryTool()
|
||||
&& RegistryToolEnvironment.isJpaTmEnabled()) {
|
||||
return DaggerPersistenceComponent.create().nomulusToolJpaTransactionManager();
|
||||
} else {
|
||||
return DummyJpaTransactionManager.create();
|
||||
}
|
||||
@@ -49,23 +49,6 @@ public class TransactionManagerFactory {
|
||||
return new DatastoreTransactionManager(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets jpaTm to the implementation for Nomulus tool. Note that this method should be only used by
|
||||
* {@link google.registry.tools.RegistryCli} to initialize jpaTm.
|
||||
*/
|
||||
public static void initForTool() {
|
||||
if (shouldEnableJpaTm()) {
|
||||
jpaTm = DaggerPersistenceComponent.create().nomulusToolJpaTransactionManager();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(shicong): Enable JpaTm for all environments and remove this function
|
||||
private static boolean shouldEnableJpaTm() {
|
||||
return RegistryEnvironment.get() == ALPHA
|
||||
|| RegistryEnvironment.get() == CRASH
|
||||
|| RegistryEnvironment.get() == SANDBOX;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function uses App Engine API to determine if the current runtime environment is App
|
||||
* Engine.
|
||||
|
||||
@@ -15,34 +15,51 @@
|
||||
package google.registry.reporting.icann;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
|
||||
import static google.registry.model.common.Cursor.getCursorTimeOrStartOfTime;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.reporting.icann.IcannReportingModule.MANIFEST_FILE_NAME;
|
||||
import static google.registry.reporting.icann.IcannReportingModule.PARAM_SUBDIR;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.appengine.tools.cloudstorage.GcsFilename;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.common.Cursor.CursorType;
|
||||
import google.registry.model.registry.Registries;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.Registry.TldType;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.HttpException.ServiceUnavailableException;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.request.lock.LockHandler;
|
||||
import google.registry.util.Clock;
|
||||
import google.registry.util.EmailMessage;
|
||||
import google.registry.util.Retrier;
|
||||
import google.registry.util.SendEmailService;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* Action that uploads the monthly activity/transactions reports from GCS to ICANN via an HTTP PUT.
|
||||
@@ -81,44 +98,175 @@ public final class IcannReportingUploadAction implements Runnable {
|
||||
@Inject @Config("gSuiteOutgoingEmailAddress") InternetAddress sender;
|
||||
@Inject @Config("alertRecipientEmailAddress") InternetAddress recipient;
|
||||
@Inject SendEmailService emailService;
|
||||
@Inject Clock clock;
|
||||
@Inject LockHandler lockHandler;
|
||||
|
||||
@Inject
|
||||
IcannReportingUploadAction() {}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
String reportBucketname = String.format("%s/%s", reportingBucket, subdir);
|
||||
ImmutableList<String> manifestedFiles = getManifestedFiles(reportBucketname);
|
||||
ImmutableMap.Builder<String, Boolean> reportSummaryBuilder = new ImmutableMap.Builder<>();
|
||||
// Report on all manifested files
|
||||
for (String reportFilename : manifestedFiles) {
|
||||
logger.atInfo().log(
|
||||
"Reading ICANN report %s from bucket %s", reportFilename, reportBucketname);
|
||||
final GcsFilename gcsFilename = new GcsFilename(reportBucketname, reportFilename);
|
||||
verifyFileExists(gcsFilename);
|
||||
boolean success = false;
|
||||
try {
|
||||
success =
|
||||
retrier.callWithRetry(
|
||||
() -> {
|
||||
final byte[] payload = readBytesFromGcs(gcsFilename);
|
||||
return icannReporter.send(payload, reportFilename);
|
||||
},
|
||||
IcannReportingUploadAction::isUploadFailureRetryable);
|
||||
} catch (RuntimeException e) {
|
||||
logger.atWarning().withCause(e).log("Upload to %s failed.", gcsFilename);
|
||||
}
|
||||
reportSummaryBuilder.put(reportFilename, success);
|
||||
Callable<Void> lockRunner =
|
||||
() -> {
|
||||
ImmutableMap.Builder<String, Boolean> reportSummaryBuilder = new ImmutableMap.Builder<>();
|
||||
|
||||
ImmutableMap<Cursor, CursorInfo> cursors = loadCursors();
|
||||
|
||||
// If cursor time is before now, upload the corresponding report
|
||||
cursors.entrySet().stream()
|
||||
.filter(entry -> getCursorTimeOrStartOfTime(entry.getKey()).isBefore(clock.nowUtc()))
|
||||
.forEach(
|
||||
entry -> {
|
||||
DateTime cursorTime = getCursorTimeOrStartOfTime(entry.getKey());
|
||||
uploadReport(
|
||||
cursorTime,
|
||||
entry.getValue().getType(),
|
||||
entry.getValue().getTld(),
|
||||
reportSummaryBuilder);
|
||||
});
|
||||
// Send email of which reports were uploaded
|
||||
emailUploadResults(reportSummaryBuilder.build());
|
||||
response.setStatus(SC_OK);
|
||||
response.setContentType(PLAIN_TEXT_UTF_8);
|
||||
return null;
|
||||
};
|
||||
|
||||
String lockname = "IcannReportingUploadAction";
|
||||
if (!lockHandler.executeWithLocks(lockRunner, null, Duration.standardHours(2), lockname)) {
|
||||
throw new ServiceUnavailableException("Lock for IcannReportingUploadAction already in use");
|
||||
}
|
||||
emailUploadResults(reportSummaryBuilder.build());
|
||||
response.setStatus(SC_OK);
|
||||
response.setContentType(PLAIN_TEXT_UTF_8);
|
||||
response.setPayload(
|
||||
String.format("OK, attempted uploading %d reports", manifestedFiles.size()));
|
||||
}
|
||||
|
||||
/** Uploads the report and rolls forward the cursor for that report. */
|
||||
private void uploadReport(
|
||||
DateTime cursorTime,
|
||||
CursorType cursorType,
|
||||
String tldStr,
|
||||
ImmutableMap.Builder<String, Boolean> reportSummaryBuilder) {
|
||||
String reportBucketname = String.format("%s/%s", reportingBucket, subdir);
|
||||
String filename = getFileName(cursorType, cursorTime, tldStr);
|
||||
final GcsFilename gcsFilename = new GcsFilename(reportBucketname, filename);
|
||||
logger.atInfo().log("Reading ICANN report %s from bucket %s", filename, reportBucketname);
|
||||
// Check that the report exists
|
||||
try {
|
||||
verifyFileExists(gcsFilename);
|
||||
} catch (IllegalArgumentException e) {
|
||||
String logMessage =
|
||||
String.format(
|
||||
"Could not upload %s report for %s because file %s did not exist.",
|
||||
cursorType, tldStr, filename);
|
||||
if (clock.nowUtc().dayOfMonth().get() == 1) {
|
||||
logger.atInfo().withCause(e).log(logMessage + " This report may not have been staged yet.");
|
||||
} else {
|
||||
logger.atSevere().withCause(e).log(logMessage);
|
||||
}
|
||||
reportSummaryBuilder.put(filename, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Upload the report
|
||||
boolean success = false;
|
||||
try {
|
||||
success =
|
||||
retrier.callWithRetry(
|
||||
() -> {
|
||||
final byte[] payload = readBytesFromGcs(gcsFilename);
|
||||
return icannReporter.send(payload, filename);
|
||||
},
|
||||
IcannReportingUploadAction::isUploadFailureRetryable);
|
||||
} catch (RuntimeException e) {
|
||||
logger.atWarning().withCause(e).log("Upload to %s failed", gcsFilename);
|
||||
}
|
||||
reportSummaryBuilder.put(filename, success);
|
||||
|
||||
// Set cursor to first day of next month if the upload succeeded
|
||||
if (success) {
|
||||
Cursor newCursor;
|
||||
if (cursorType.equals(CursorType.ICANN_UPLOAD_MANIFEST)) {
|
||||
newCursor =
|
||||
Cursor.createGlobal(
|
||||
cursorType, cursorTime.withTimeAtStartOfDay().withDayOfMonth(1).plusMonths(1));
|
||||
} else {
|
||||
newCursor =
|
||||
Cursor.create(
|
||||
cursorType,
|
||||
cursorTime.withTimeAtStartOfDay().withDayOfMonth(1).plusMonths(1),
|
||||
Registry.get(tldStr));
|
||||
}
|
||||
tm().transact(() -> ofy().save().entity(newCursor));
|
||||
}
|
||||
}
|
||||
|
||||
private String getFileName(CursorType cursorType, DateTime cursorTime, String tld) {
|
||||
if (cursorType.equals(CursorType.ICANN_UPLOAD_MANIFEST)) {
|
||||
return MANIFEST_FILE_NAME;
|
||||
}
|
||||
return String.format(
|
||||
"%s%s%d%02d.csv",
|
||||
tld,
|
||||
(cursorType.equals(CursorType.ICANN_UPLOAD_ACTIVITY) ? "-activity-" : "-transactions-"),
|
||||
cursorTime.year().get(),
|
||||
cursorTime.monthOfYear().get());
|
||||
}
|
||||
|
||||
/** Returns a map of each cursor to the CursorType and tld. */
|
||||
private ImmutableMap<Cursor, CursorInfo> loadCursors() {
|
||||
|
||||
ImmutableSet<Registry> registries = Registries.getTldEntitiesOfType(TldType.REAL);
|
||||
|
||||
Map<Key<Cursor>, Registry> activityKeyMap =
|
||||
loadKeyMap(registries, CursorType.ICANN_UPLOAD_ACTIVITY);
|
||||
Map<Key<Cursor>, Registry> transactionKeyMap =
|
||||
loadKeyMap(registries, CursorType.ICANN_UPLOAD_TX);
|
||||
|
||||
ImmutableSet.Builder<Key<Cursor>> keys = new ImmutableSet.Builder<>();
|
||||
keys.addAll(activityKeyMap.keySet());
|
||||
keys.addAll(transactionKeyMap.keySet());
|
||||
keys.add(Cursor.createGlobalKey(CursorType.ICANN_UPLOAD_MANIFEST));
|
||||
|
||||
Map<Key<Cursor>, Cursor> cursorMap = ofy().load().keys(keys.build());
|
||||
ImmutableMap.Builder<Cursor, CursorInfo> cursors = new ImmutableMap.Builder<>();
|
||||
defaultNullCursorsToNextMonthAndAddToMap(
|
||||
activityKeyMap, CursorType.ICANN_UPLOAD_ACTIVITY, cursorMap, cursors);
|
||||
defaultNullCursorsToNextMonthAndAddToMap(
|
||||
transactionKeyMap, CursorType.ICANN_UPLOAD_TX, cursorMap, cursors);
|
||||
Cursor manifestCursor =
|
||||
cursorMap.getOrDefault(
|
||||
Cursor.createGlobalKey(CursorType.ICANN_UPLOAD_MANIFEST),
|
||||
Cursor.createGlobal(CursorType.ICANN_UPLOAD_MANIFEST, clock.nowUtc().minusDays(1)));
|
||||
cursors.put(manifestCursor, CursorInfo.create(CursorType.ICANN_UPLOAD_MANIFEST, null));
|
||||
return cursors.build();
|
||||
}
|
||||
|
||||
private Map<Key<Cursor>, Registry> loadKeyMap(
|
||||
ImmutableSet<Registry> registries, CursorType type) {
|
||||
return registries.stream().collect(toImmutableMap(r -> Cursor.createKey(type, r), r -> r));
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the cursors map with the Cursor and CursorInfo for each key in the keyMap. If the key
|
||||
* from the keyMap does not have an existing cursor, create a new cursor with a default cursorTime
|
||||
* of the first of next month.
|
||||
*/
|
||||
private void defaultNullCursorsToNextMonthAndAddToMap(
|
||||
Map<Key<Cursor>, Registry> keyMap,
|
||||
CursorType type,
|
||||
Map<Key<Cursor>, Cursor> cursorMap,
|
||||
ImmutableMap.Builder<Cursor, CursorInfo> cursors) {
|
||||
keyMap.forEach(
|
||||
(key, registry) -> {
|
||||
// Cursor time is defaulted to the first of next month since a new tld will not yet have a
|
||||
// report staged for upload.
|
||||
Cursor cursor =
|
||||
cursorMap.getOrDefault(
|
||||
key, Cursor.create(type, clock.nowUtc().minusDays(1), registry));
|
||||
cursors.put(cursor, CursorInfo.create(type, registry.getTldStr()));
|
||||
});
|
||||
}
|
||||
|
||||
/** Don't retry when reports are already uploaded or can't be uploaded. */
|
||||
private static final String ICANN_UPLOAD_PERMANENT_ERROR_MESSAGE =
|
||||
"A report for that month already exists, the cut-off date already passed.";
|
||||
"A report for that month already exists, the cut-off date already passed";
|
||||
|
||||
/** Don't retry when the IP address isn't whitelisted, as retries go through the same IP. */
|
||||
private static final Pattern ICANN_UPLOAD_WHITELIST_ERROR =
|
||||
@@ -146,18 +294,6 @@ public final class IcannReportingUploadAction implements Runnable {
|
||||
emailService.sendEmail(EmailMessage.create(subject, body, recipient, sender));
|
||||
}
|
||||
|
||||
private ImmutableList<String> getManifestedFiles(String reportBucketname) {
|
||||
GcsFilename manifestFilename = new GcsFilename(reportBucketname, MANIFEST_FILE_NAME);
|
||||
verifyFileExists(manifestFilename);
|
||||
return retrier.callWithRetry(
|
||||
() ->
|
||||
ImmutableList.copyOf(
|
||||
Splitter.on('\n')
|
||||
.omitEmptyStrings()
|
||||
.split(new String(readBytesFromGcs(manifestFilename), UTF_8))),
|
||||
IOException.class);
|
||||
}
|
||||
|
||||
private byte[] readBytesFromGcs(GcsFilename reportFilename) throws IOException {
|
||||
try (InputStream gcsInput = gcsUtils.openInputStream(reportFilename)) {
|
||||
return ByteStreams.toByteArray(gcsInput);
|
||||
@@ -171,4 +307,16 @@ public final class IcannReportingUploadAction implements Runnable {
|
||||
gcsFilename.getObjectName(),
|
||||
gcsFilename.getBucketName());
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
abstract static class CursorInfo {
|
||||
static CursorInfo create(CursorType type, @Nullable String tld) {
|
||||
return new AutoValue_IcannReportingUploadAction_CursorInfo(type, tld);
|
||||
}
|
||||
|
||||
public abstract CursorType getType();
|
||||
|
||||
@Nullable
|
||||
abstract String getTld();
|
||||
}
|
||||
}
|
||||
|
||||
147
core/src/main/java/google/registry/schema/tld/ReservedList.java
Normal file
147
core/src/main/java/google/registry/schema/tld/ReservedList.java
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.schema.tld;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.registry.label.ReservationType;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.MapKeyColumn;
|
||||
import javax.persistence.Table;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* A list of reserved domain labels that are blocked from being registered for various reasons.
|
||||
*
|
||||
* <p>Note that the primary key of this entity is {@link #revisionId}, which is auto-generated by
|
||||
* the database. So, if a retry of insertion happens after the previous attempt unexpectedly
|
||||
* succeeds, we will end up with having two exact same reserved lists that differ only by
|
||||
* revisionId. This is fine though, because we only use the list with the highest revisionId.
|
||||
*/
|
||||
@Entity
|
||||
@Table(indexes = {@Index(columnList = "name", name = "reservedlist_name_idx")})
|
||||
public class ReservedList extends ImmutableObject {
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(nullable = false)
|
||||
private Long revisionId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private CreateAutoTimestamp creationTimestamp = CreateAutoTimestamp.create(null);
|
||||
|
||||
@Column(nullable = false)
|
||||
private Boolean shouldPublish;
|
||||
|
||||
@ElementCollection
|
||||
@CollectionTable(
|
||||
name = "ReservedEntry",
|
||||
joinColumns = @JoinColumn(name = "revisionId", referencedColumnName = "revisionId"))
|
||||
@MapKeyColumn(name = "domainLabel")
|
||||
private Map<String, ReservedEntry> labelsToReservations;
|
||||
|
||||
@Embeddable
|
||||
public static class ReservedEntry extends ImmutableObject {
|
||||
@Column(nullable = false)
|
||||
private ReservationType reservationType;
|
||||
|
||||
@Column(nullable = true)
|
||||
private String comment;
|
||||
|
||||
private ReservedEntry(ReservationType reservationType, @Nullable String comment) {
|
||||
this.reservationType = reservationType;
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
// Hibernate requires this default constructor.
|
||||
private ReservedEntry() {}
|
||||
|
||||
/** Constructs a {@link ReservedEntry} object. */
|
||||
public static ReservedEntry create(ReservationType reservationType, @Nullable String comment) {
|
||||
return new ReservedEntry(reservationType, comment);
|
||||
}
|
||||
|
||||
/** Returns the reservation type for this entry. */
|
||||
public ReservationType getReservationType() {
|
||||
return reservationType;
|
||||
}
|
||||
|
||||
/** Returns the comment for this entry. Retruns null if there is no comment. */
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
}
|
||||
|
||||
private ReservedList(
|
||||
String name, Boolean shouldPublish, Map<String, ReservedEntry> labelsToReservations) {
|
||||
this.name = name;
|
||||
this.shouldPublish = shouldPublish;
|
||||
this.labelsToReservations = labelsToReservations;
|
||||
}
|
||||
|
||||
// Hibernate requires this default constructor.
|
||||
private ReservedList() {}
|
||||
|
||||
/** Constructs a {@link ReservedList} object. */
|
||||
public static ReservedList create(
|
||||
String name, Boolean shouldPublish, Map<String, ReservedEntry> labelsToReservations) {
|
||||
return new ReservedList(name, shouldPublish, labelsToReservations);
|
||||
}
|
||||
|
||||
/** Returns the name of the reserved list. */
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/** Returns the ID of this revision, or throws if null. */
|
||||
public Long getRevisionId() {
|
||||
checkState(
|
||||
revisionId != null,
|
||||
"revisionId is null because this object has not been persisted to the database yet");
|
||||
return revisionId;
|
||||
}
|
||||
|
||||
/** Returns the creation time of this revision of the reserved list. */
|
||||
public DateTime getCreationTimestamp() {
|
||||
return creationTimestamp.getTimestamp();
|
||||
}
|
||||
|
||||
/** Returns a {@link Map} of domain labels to {@link ReservedEntry}. */
|
||||
public ImmutableMap<String, ReservedEntry> getLabelsToReservations() {
|
||||
return ImmutableMap.copyOf(labelsToReservations);
|
||||
}
|
||||
|
||||
/** Returns true if the reserved list should be published. */
|
||||
public Boolean getShouldPublish() {
|
||||
return shouldPublish;
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import google.registry.persistence.HibernateSchemaExporter;
|
||||
import google.registry.persistence.NomulusPostgreSql;
|
||||
import google.registry.persistence.PersistenceXmlUtility;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -83,7 +84,7 @@ public class GenerateSqlSchemaCommand implements Command {
|
||||
|
||||
// Start the container and store the address information.
|
||||
postgresContainer =
|
||||
new PostgreSQLContainer()
|
||||
new PostgreSQLContainer(NomulusPostgreSql.getDockerTag())
|
||||
.withDatabaseName(DB_NAME)
|
||||
.withUsername(DB_USERNAME)
|
||||
.withPassword(DB_PASSWORD);
|
||||
|
||||
@@ -31,7 +31,6 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.model.ofy.ObjectifyService;
|
||||
import google.registry.model.transaction.TransactionManagerFactory;
|
||||
import google.registry.tools.AuthModule.LoginRequiredException;
|
||||
import google.registry.tools.params.ParameterFactory;
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -237,7 +236,7 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
||||
}
|
||||
|
||||
if (command instanceof CommandWithCloudSql) {
|
||||
TransactionManagerFactory.initForTool();
|
||||
RegistryToolEnvironment.get().enableJpaTm();
|
||||
}
|
||||
|
||||
command.run();
|
||||
|
||||
@@ -25,7 +25,7 @@ import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.config.SystemPropertySetter;
|
||||
|
||||
/** Enum of production environments, used for the {@code --environment} flag. */
|
||||
enum RegistryToolEnvironment {
|
||||
public enum RegistryToolEnvironment {
|
||||
PRODUCTION(RegistryEnvironment.PRODUCTION),
|
||||
ALPHA(RegistryEnvironment.ALPHA),
|
||||
CRASH(RegistryEnvironment.CRASH),
|
||||
@@ -39,6 +39,7 @@ enum RegistryToolEnvironment {
|
||||
|
||||
private static final ImmutableList<String> FLAGS = ImmutableList.of("-e", "--environment");
|
||||
private static RegistryToolEnvironment instance;
|
||||
private static boolean isJpaTmEnabled = false;
|
||||
private final RegistryEnvironment actualEnvironment;
|
||||
private final ImmutableMap<String, String> extraProperties;
|
||||
|
||||
@@ -72,7 +73,7 @@ enum RegistryToolEnvironment {
|
||||
*
|
||||
* <p>This should be called after {@link #parseFromArgs(String[])}.
|
||||
*/
|
||||
static RegistryToolEnvironment get() {
|
||||
public static RegistryToolEnvironment get() {
|
||||
checkState(instance != null, "No RegistryToolEnvironment has been set up");
|
||||
return instance;
|
||||
}
|
||||
@@ -98,6 +99,26 @@ enum RegistryToolEnvironment {
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true if the RegistryToolEnvironment is set up. */
|
||||
public static boolean isInRegistryTool() {
|
||||
return instance != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the flag to indicate that the running command needs JpaTransactionManager to be enabled.
|
||||
*/
|
||||
public static void enableJpaTm() {
|
||||
isJpaTmEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the JpaTransactionManager is enabled. Note that JpaTm is actually enabled in
|
||||
* {@link google.registry.model.transaction.TransactionManagerFactory} by reading this flag.
|
||||
*/
|
||||
public static boolean isJpaTmEnabled() {
|
||||
return isJpaTmEnabled;
|
||||
}
|
||||
|
||||
/** Extracts value from command-line arguments associated with any {@code flags}. */
|
||||
private static String getFlagValue(String[] args, Iterable<String> flags) {
|
||||
for (String flag : flags) {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
<class>google.registry.schema.tmch.ClaimsList</class>
|
||||
<class>google.registry.model.transfer.BaseTransferObject</class>
|
||||
<class>google.registry.schema.tld.PremiumList</class>
|
||||
<class>google.registry.schema.tld.ReservedList</class>
|
||||
<class>google.registry.model.domain.secdns.DelegationSignerData</class>
|
||||
<class>google.registry.model.domain.DesignatedContact</class>
|
||||
<class>google.registry.model.domain.DomainBase</class>
|
||||
|
||||
@@ -48,10 +48,7 @@ import org.junit.runners.JUnit4;
|
||||
@RunWith(JUnit4.class)
|
||||
public class ExportReservedTermsActionTest {
|
||||
|
||||
@Rule
|
||||
public final AppEngineRule appEngine = AppEngineRule.builder()
|
||||
.withDatastore()
|
||||
.build();
|
||||
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
|
||||
|
||||
private final DriveConnection driveConnection = mock(DriveConnection.class);
|
||||
private final Response response = mock(Response.class);
|
||||
@@ -133,6 +130,6 @@ public class ExportReservedTermsActionTest {
|
||||
assertThat(thrown)
|
||||
.hasCauseThat()
|
||||
.hasMessageThat()
|
||||
.isEqualTo("No registry object found for fakeTld");
|
||||
.isEqualTo("No registry object(s) found for fakeTld");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,12 @@ package google.registry.model.registry;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.testing.DatastoreHelper.createTlds;
|
||||
import static google.registry.testing.DatastoreHelper.newRegistry;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import google.registry.model.registry.Registry.TldType;
|
||||
import google.registry.testing.AppEngineRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -32,6 +35,7 @@ public class RegistriesTest {
|
||||
|
||||
@Rule
|
||||
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
|
||||
|
||||
private void initTestTlds() {
|
||||
createTlds("foo", "a.b.c"); // Test a multipart tld.
|
||||
}
|
||||
@@ -42,6 +46,16 @@ public class RegistriesTest {
|
||||
assertThat(Registries.getTlds()).containsExactly("foo", "a.b.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_getTldEntities() {
|
||||
initTestTlds();
|
||||
persistResource(newRegistry("testtld", "TESTTLD").asBuilder().setTldType(TldType.TEST).build());
|
||||
assertThat(Registries.getTldEntitiesOfType(TldType.REAL))
|
||||
.containsExactly(Registry.get("foo"), Registry.get("a.b.c"));
|
||||
assertThat(Registries.getTldEntitiesOfType(TldType.TEST))
|
||||
.containsExactly(Registry.get("testtld"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTlds_withNoRegistriesPersisted_returnsEmptySet() {
|
||||
assertThat(Registries.getTlds()).isEmpty();
|
||||
|
||||
@@ -51,6 +51,7 @@ import org.junit.Test;
|
||||
|
||||
/** Unit tests for {@link Registry}. */
|
||||
public class RegistryTest extends EntityTestCase {
|
||||
|
||||
Registry registry;
|
||||
|
||||
@Before
|
||||
@@ -146,6 +147,19 @@ public class RegistryTest extends EntityTestCase {
|
||||
assertThat(registry.getReservedLists()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAll() {
|
||||
createTld("foo");
|
||||
assertThat(Registry.getAll(ImmutableSet.of("foo", "tld")))
|
||||
.containsExactlyElementsIn(
|
||||
ofy()
|
||||
.load()
|
||||
.keys(
|
||||
Key.create(getCrossTldKey(), Registry.class, "foo"),
|
||||
Key.create(getCrossTldKey(), Registry.class, "tld"))
|
||||
.values());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetReservedLists() {
|
||||
ReservedList rl5 = persistReservedList(
|
||||
|
||||
@@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
import static org.testcontainers.containers.PostgreSQLContainer.POSTGRESQL_PORT;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
@@ -25,12 +26,14 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.io.Resources;
|
||||
import google.registry.persistence.HibernateSchemaExporter;
|
||||
import google.registry.persistence.NomulusPostgreSql;
|
||||
import google.registry.persistence.PersistenceModule;
|
||||
import google.registry.persistence.PersistenceXmlUtility;
|
||||
import google.registry.testing.FakeClock;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.sql.Connection;
|
||||
@@ -42,6 +45,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import org.hibernate.cfg.Environment;
|
||||
@@ -59,6 +63,19 @@ import org.testcontainers.containers.PostgreSQLContainer;
|
||||
* TransactionManagerFactory} with the {@link JpaTransactionManagerImpl} generated by the rule
|
||||
* itself, so that all SQL queries will be sent to the database instance created by {@link
|
||||
* PostgreSQLContainer} to achieve test purpose.
|
||||
*
|
||||
* <p>The location of the Nomulus golden schema may be overridden with the {@code
|
||||
* "sql_schema_resource_root} system property. This feature is needed by the server/schema
|
||||
* compatibility tests, which need to use different versions of the schema off the classpath.
|
||||
*
|
||||
* <p>If defined, the value of the {@code "sql_schema_resource_root} should be an URL string that
|
||||
* points to the jar or resource root directory. Here are some examples:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Absolute path to local directory: [file://]/path/to/resources
|
||||
* <li>Absolute path to local jar: [file://]/path/to/schema.jar
|
||||
* <li>URL to remote jar: https://host/path/to/schema.jar
|
||||
* </ul>
|
||||
*/
|
||||
public class JpaTransactionManagerRule extends ExternalResource {
|
||||
private static final String GOLDEN_SCHEMA_SQL_PATH = "sql/schema/nomulus.golden.sql";
|
||||
@@ -67,6 +84,10 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
private static final String MANAGEMENT_DB_NAME = "management";
|
||||
private static final String POSTGRES_DB_NAME = "postgres";
|
||||
|
||||
// Name of the optional property that specifies the root path of the golden schema.
|
||||
@VisibleForTesting
|
||||
static final String GOLDEN_SCHEMA_RESOURCE_ROOT_PROP = "sql_schema_resource_root";
|
||||
|
||||
private final DateTime now = DateTime.now(UTC);
|
||||
private final FakeClock clock = new FakeClock(now);
|
||||
private final String initScriptPath;
|
||||
@@ -74,6 +95,9 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
private final ImmutableMap userProperties;
|
||||
|
||||
private static final JdbcDatabaseContainer database = create();
|
||||
private static final long ACTIVE_CONNECTIONS_BASELINE =
|
||||
getActiveConnectionCountByUser(database.getUsername());
|
||||
;
|
||||
private static final HibernateSchemaExporter exporter =
|
||||
HibernateSchemaExporter.create(
|
||||
database.getJdbcUrl(), database.getUsername(), database.getPassword());
|
||||
@@ -90,7 +114,9 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
}
|
||||
|
||||
private static JdbcDatabaseContainer create() {
|
||||
PostgreSQLContainer container = new PostgreSQLContainer().withDatabaseName(MANAGEMENT_DB_NAME);
|
||||
PostgreSQLContainer container =
|
||||
new PostgreSQLContainer(NomulusPostgreSql.getDockerTag())
|
||||
.withDatabaseName(MANAGEMENT_DB_NAME);
|
||||
container.start();
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> container.close()));
|
||||
return container;
|
||||
@@ -99,7 +125,7 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
@Override
|
||||
public void before() throws Exception {
|
||||
executeSql(MANAGEMENT_DB_NAME, readSqlInClassPath(DB_CLEANUP_SQL_PATH));
|
||||
executeSql(POSTGRES_DB_NAME, readSqlInClassPath(initScriptPath));
|
||||
executeSql(POSTGRES_DB_NAME, readInitialScript());
|
||||
if (!extraEntityClasses.isEmpty()) {
|
||||
File tempSqlFile = File.createTempFile("tempSqlFile", ".sql");
|
||||
tempSqlFile.deleteOnExit();
|
||||
@@ -140,27 +166,28 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
assertNormalActiveConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function throws exception if it detects connection leak by checking the metadata table
|
||||
* pg_stat_activity.
|
||||
*/
|
||||
private void assertNormalActiveConnection() {
|
||||
private static long getActiveConnectionCountByUser(String userName) {
|
||||
try (Connection conn = createConnection(POSTGRES_DB_NAME);
|
||||
Statement statement = conn.createStatement()) {
|
||||
ResultSet rs =
|
||||
statement.executeQuery(
|
||||
"SELECT COUNT(1) FROM pg_stat_activity WHERE usename = '"
|
||||
+ database.getUsername()
|
||||
+ "'");
|
||||
"SELECT COUNT(1) FROM pg_stat_activity WHERE usename = '" + userName + "'");
|
||||
rs.next();
|
||||
long activeConns = rs.getLong(1);
|
||||
// There should be only 1 active connection which is executing this query
|
||||
assertThat(activeConns).isEqualTo(1L);
|
||||
return rs.getLong(1);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function throws exception if it detects connection leak by checking the metadata table
|
||||
* pg_stat_activity.
|
||||
*/
|
||||
private void assertNormalActiveConnection() {
|
||||
assertThat(getActiveConnectionCountByUser(database.getUsername()))
|
||||
.isEqualTo(ACTIVE_CONNECTIONS_BASELINE);
|
||||
}
|
||||
|
||||
private static String readSqlInClassPath(String sqlScriptPath) {
|
||||
try {
|
||||
return Resources.toString(Resources.getResource(sqlScriptPath), Charsets.UTF_8);
|
||||
@@ -169,6 +196,38 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Optional<String> getInitScriptUrlOverride() {
|
||||
String schemaRootPath = System.getProperty(GOLDEN_SCHEMA_RESOURCE_ROOT_PROP, "").trim();
|
||||
if (schemaRootPath.isEmpty() || !initScriptPath.equals(GOLDEN_SCHEMA_SQL_PATH)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (schemaRootPath.startsWith("/")) {
|
||||
schemaRootPath = "file://" + schemaRootPath;
|
||||
}
|
||||
if (schemaRootPath.endsWith(".jar") && !schemaRootPath.startsWith("jar:")) {
|
||||
schemaRootPath = "jar:" + schemaRootPath;
|
||||
}
|
||||
if (schemaRootPath.endsWith(".jar")) {
|
||||
schemaRootPath += "!/" + GOLDEN_SCHEMA_SQL_PATH;
|
||||
} else {
|
||||
schemaRootPath += "/" + GOLDEN_SCHEMA_SQL_PATH;
|
||||
}
|
||||
return Optional.of(schemaRootPath);
|
||||
}
|
||||
|
||||
private String readInitialScript() {
|
||||
Optional<String> schemaUrlOverride = getInitScriptUrlOverride();
|
||||
if (!schemaUrlOverride.isPresent()) {
|
||||
return readSqlInClassPath(initScriptPath);
|
||||
}
|
||||
try {
|
||||
return Resources.toString(new URL(schemaUrlOverride.get()), StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeSql(String dbName, String sqlScript) {
|
||||
try (Connection conn = createConnection(dbName);
|
||||
Statement statement = conn.createStatement()) {
|
||||
@@ -178,7 +237,7 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
}
|
||||
}
|
||||
|
||||
private String getJdbcUrlFor(String dbName) {
|
||||
private static String getJdbcUrlFor(String dbName) {
|
||||
// Disable Postgres driver use of java.util.logging to reduce noise at startup time
|
||||
return "jdbc:postgresql://"
|
||||
+ database.getContainerIpAddress()
|
||||
@@ -189,7 +248,7 @@ public class JpaTransactionManagerRule extends ExternalResource {
|
||||
+ "?loggerLevel=OFF";
|
||||
}
|
||||
|
||||
private Connection createConnection(String dbName) {
|
||||
private static Connection createConnection(String dbName) {
|
||||
final Properties info = new Properties();
|
||||
info.put("user", database.getUsername());
|
||||
info.put("password", database.getPassword());
|
||||
|
||||
@@ -15,10 +15,13 @@
|
||||
package google.registry.model.transaction;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.model.transaction.JpaTransactionManagerRule.GOLDEN_SCHEMA_RESOURCE_ROOT_PROP;
|
||||
import static google.registry.model.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.testing.SystemPropertyRule;
|
||||
import java.util.List;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
@@ -38,6 +41,8 @@ public class JpaTransactionManagerRuleTest {
|
||||
.withEntityClass(TestEntity.class)
|
||||
.build();
|
||||
|
||||
@Rule public final SystemPropertyRule systemPropertyRule = new SystemPropertyRule();
|
||||
|
||||
@Test
|
||||
public void verifiesRuleWorks() {
|
||||
assertThrows(
|
||||
@@ -73,6 +78,57 @@ public class JpaTransactionManagerRuleTest {
|
||||
assertThat(retrieved).isEqualTo(original);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitScriptUrl_noOverride() {
|
||||
assertThat(jpaTmRule.getInitScriptUrlOverride()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitScriptUrl_localDir_noProtocol() {
|
||||
systemPropertyRule.setProperty(GOLDEN_SCHEMA_RESOURCE_ROOT_PROP, "/path/to/resources");
|
||||
assertThat(jpaTmRule.getInitScriptUrlOverride())
|
||||
.hasValue("file:///path/to/resources/sql/schema/nomulus.golden.sql");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitScriptUrl_localDir_hasProtocol() {
|
||||
systemPropertyRule.setProperty(GOLDEN_SCHEMA_RESOURCE_ROOT_PROP, "file:///path/to/resources");
|
||||
assertThat(jpaTmRule.getInitScriptUrlOverride())
|
||||
.hasValue("file:///path/to/resources/sql/schema/nomulus.golden.sql");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitScriptUrl_localJar_noProtocol() {
|
||||
systemPropertyRule.setProperty(
|
||||
GOLDEN_SCHEMA_RESOURCE_ROOT_PROP, "/path/to/resources/schema.jar");
|
||||
assertThat(jpaTmRule.getInitScriptUrlOverride())
|
||||
.hasValue("jar:file:///path/to/resources/schema.jar!/sql/schema/nomulus.golden.sql");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitScriptUrl_localJar_hasPartialProtocol() {
|
||||
systemPropertyRule.setProperty(
|
||||
GOLDEN_SCHEMA_RESOURCE_ROOT_PROP, "file:///path/to/resources/schema.jar");
|
||||
assertThat(jpaTmRule.getInitScriptUrlOverride())
|
||||
.hasValue("jar:file:///path/to/resources/schema.jar!/sql/schema/nomulus.golden.sql");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitScriptUrl_localJar_hasFullProtocol() {
|
||||
systemPropertyRule.setProperty(
|
||||
GOLDEN_SCHEMA_RESOURCE_ROOT_PROP, "jar:file:///path/to/resources/schema.jar");
|
||||
assertThat(jpaTmRule.getInitScriptUrlOverride())
|
||||
.hasValue("jar:file:///path/to/resources/schema.jar!/sql/schema/nomulus.golden.sql");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitScriptUrl_remoteJar() {
|
||||
systemPropertyRule.setProperty(
|
||||
GOLDEN_SCHEMA_RESOURCE_ROOT_PROP, "http://host/path/to/resources/schema.jar");
|
||||
assertThat(jpaTmRule.getInitScriptUrlOverride())
|
||||
.hasValue("jar:http://host/path/to/resources/schema.jar!/sql/schema/nomulus.golden.sql");
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity") // Specify name to avoid nested class naming issues.
|
||||
static class TestEntity extends ImmutableObject {
|
||||
@Id String key;
|
||||
|
||||
@@ -36,7 +36,10 @@ import org.testcontainers.containers.PostgreSQLContainer;
|
||||
/** Unit tests for {@link HibernateSchemaExporter}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class HibernateSchemaExporterTest {
|
||||
@ClassRule public static final PostgreSQLContainer database = new PostgreSQLContainer();
|
||||
@ClassRule
|
||||
public static final PostgreSQLContainer database =
|
||||
new PostgreSQLContainer(NomulusPostgreSql.getDockerTag());
|
||||
|
||||
private static HibernateSchemaExporter exporter;
|
||||
|
||||
@Rule public final TemporaryFolder tempFolder = new TemporaryFolder();
|
||||
|
||||
@@ -29,7 +29,8 @@ import org.testcontainers.containers.PostgreSQLContainer;
|
||||
/** Unit tests for {@link PersistenceModule}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class PersistenceModuleTest {
|
||||
@Rule public PostgreSQLContainer database = new PostgreSQLContainer();
|
||||
@Rule
|
||||
public PostgreSQLContainer database = new PostgreSQLContainer(NomulusPostgreSql.getDockerTag());
|
||||
|
||||
private EntityManagerFactory emf;
|
||||
|
||||
|
||||
@@ -15,8 +15,12 @@
|
||||
package google.registry.reporting.icann;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.testing.DatastoreHelper.createTlds;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
import static google.registry.testing.GcsTestingUtils.writeGcsFile;
|
||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
import static google.registry.testing.LogsSubject.assertAboutLogs;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -27,16 +31,25 @@ import static org.mockito.Mockito.when;
|
||||
import com.google.appengine.tools.cloudstorage.GcsFilename;
|
||||
import com.google.appengine.tools.cloudstorage.GcsService;
|
||||
import com.google.appengine.tools.cloudstorage.GcsServiceFactory;
|
||||
import com.google.common.testing.TestLogHandler;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.common.Cursor.CursorType;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.request.HttpException.ServiceUnavailableException;
|
||||
import google.registry.testing.AppEngineRule;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeLockHandler;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.FakeSleeper;
|
||||
import google.registry.util.EmailMessage;
|
||||
import google.registry.util.Retrier;
|
||||
import google.registry.util.SendEmailService;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -52,105 +65,175 @@ public class IcannReportingUploadActionTest {
|
||||
private static final byte[] PAYLOAD_SUCCESS = "test,csv\n13,37".getBytes(UTF_8);
|
||||
private static final byte[] PAYLOAD_FAIL = "ahah,csv\n12,34".getBytes(UTF_8);
|
||||
private static final byte[] MANIFEST_PAYLOAD =
|
||||
"test-transactions-201706.csv\na-activity-201706.csv\n".getBytes(UTF_8);
|
||||
"tld-transactions-200606.csv\ntld-activity-200606.csv\nfoo-transactions-200606.csv\nfoo-activity-200606.csv\n"
|
||||
.getBytes(UTF_8);
|
||||
private final IcannHttpReporter mockReporter = mock(IcannHttpReporter.class);
|
||||
private final SendEmailService emailService = mock(SendEmailService.class);
|
||||
private final FakeResponse response = new FakeResponse();
|
||||
private final GcsService gcsService = GcsServiceFactory.createGcsService();
|
||||
private final TestLogHandler logHandler = new TestLogHandler();
|
||||
private final Logger loggerToIntercept =
|
||||
Logger.getLogger(IcannReportingUploadAction.class.getCanonicalName());
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2000-01-01TZ"));
|
||||
|
||||
private IcannReportingUploadAction createAction() throws Exception {
|
||||
IcannReportingUploadAction action = new IcannReportingUploadAction();
|
||||
action.icannReporter = mockReporter;
|
||||
action.gcsUtils = new GcsUtils(gcsService, 1024);
|
||||
action.retrier = new Retrier(new FakeSleeper(new FakeClock()), 3);
|
||||
action.subdir = "icann/monthly/2017-06";
|
||||
action.subdir = "icann/monthly/2006-06";
|
||||
action.reportingBucket = "basin";
|
||||
action.emailService = emailService;
|
||||
action.sender = new InternetAddress("sender@example.com");
|
||||
action.recipient = new InternetAddress("recipient@example.com");
|
||||
action.response = response;
|
||||
action.clock = clock;
|
||||
action.lockHandler = new FakeLockHandler(true);
|
||||
return action;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
createTlds("tld", "foo");
|
||||
writeGcsFile(
|
||||
gcsService,
|
||||
new GcsFilename("basin/icann/monthly/2017-06", "test-transactions-201706.csv"),
|
||||
new GcsFilename("basin/icann/monthly/2006-06", "tld-transactions-200606.csv"),
|
||||
PAYLOAD_SUCCESS);
|
||||
writeGcsFile(
|
||||
gcsService,
|
||||
new GcsFilename("basin/icann/monthly/2017-06", "a-activity-201706.csv"),
|
||||
new GcsFilename("basin/icann/monthly/2006-06", "tld-activity-200606.csv"),
|
||||
PAYLOAD_FAIL);
|
||||
writeGcsFile(
|
||||
gcsService,
|
||||
new GcsFilename("basin/icann/monthly/2017-06", "MANIFEST.txt"),
|
||||
new GcsFilename("basin/icann/monthly/2006-06", "foo-transactions-200606.csv"),
|
||||
PAYLOAD_SUCCESS);
|
||||
writeGcsFile(
|
||||
gcsService,
|
||||
new GcsFilename("basin/icann/monthly/2006-06", "foo-activity-200606.csv"),
|
||||
PAYLOAD_SUCCESS);
|
||||
writeGcsFile(
|
||||
gcsService,
|
||||
new GcsFilename("basin/icann/monthly/2006-06", "MANIFEST.txt"),
|
||||
MANIFEST_PAYLOAD);
|
||||
when(mockReporter.send(PAYLOAD_SUCCESS, "test-transactions-201706.csv")).thenReturn(true);
|
||||
when(mockReporter.send(PAYLOAD_FAIL, "a-activity-201706.csv")).thenReturn(false);
|
||||
when(mockReporter.send(PAYLOAD_SUCCESS, "tld-transactions-200606.csv")).thenReturn(true);
|
||||
when(mockReporter.send(PAYLOAD_SUCCESS, "foo-transactions-200606.csv")).thenReturn(true);
|
||||
when(mockReporter.send(PAYLOAD_FAIL, "tld-activity-200606.csv")).thenReturn(false);
|
||||
when(mockReporter.send(PAYLOAD_SUCCESS, "foo-activity-200606.csv")).thenReturn(true);
|
||||
when(mockReporter.send(MANIFEST_PAYLOAD, "MANIFEST.txt")).thenReturn(true);
|
||||
clock.setTo(DateTime.parse("2006-06-06T00:30:00Z"));
|
||||
persistResource(
|
||||
Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, DateTime.parse("2006-06-06TZ"), Registry.get("tld")));
|
||||
persistResource(
|
||||
Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_TX, DateTime.parse("2006-06-06TZ"), Registry.get("tld")));
|
||||
persistResource(
|
||||
Cursor.createGlobal(CursorType.ICANN_UPLOAD_MANIFEST, DateTime.parse("2006-07-06TZ")));
|
||||
persistResource(
|
||||
Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, DateTime.parse("2006-06-06TZ"), Registry.get("foo")));
|
||||
persistResource(
|
||||
Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_TX, DateTime.parse("2006-06-06TZ"), Registry.get("foo")));
|
||||
loggerToIntercept.addHandler(logHandler);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess() throws Exception {
|
||||
IcannReportingUploadAction action = createAction();
|
||||
action.run();
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "test-transactions-201706.csv");
|
||||
verify(mockReporter).send(PAYLOAD_FAIL, "a-activity-201706.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "foo-activity-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_FAIL, "tld-activity-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "foo-transactions-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "tld-transactions-200606.csv");
|
||||
|
||||
verifyNoMoreInteractions(mockReporter);
|
||||
assertThat(((FakeResponse) action.response).getPayload())
|
||||
.isEqualTo("OK, attempted uploading 2 reports");
|
||||
verify(emailService)
|
||||
.sendEmail(
|
||||
EmailMessage.create(
|
||||
"ICANN Monthly report upload summary: 1/2 succeeded",
|
||||
"ICANN Monthly report upload summary: 3/4 succeeded",
|
||||
"Report Filename - Upload status:\n"
|
||||
+ "test-transactions-201706.csv - SUCCESS\n"
|
||||
+ "a-activity-201706.csv - FAILURE",
|
||||
+ "foo-activity-200606.csv - SUCCESS\n"
|
||||
+ "tld-activity-200606.csv - FAILURE\n"
|
||||
+ "foo-transactions-200606.csv - SUCCESS\n"
|
||||
+ "tld-transactions-200606.csv - SUCCESS",
|
||||
new InternetAddress("recipient@example.com"),
|
||||
new InternetAddress("sender@example.com")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_WithRetry() throws Exception {
|
||||
public void testSuccess_advancesCursor() throws Exception {
|
||||
writeGcsFile(
|
||||
gcsService,
|
||||
new GcsFilename("basin/icann/monthly/2006-06", "tld-activity-200606.csv"),
|
||||
PAYLOAD_SUCCESS);
|
||||
when(mockReporter.send(PAYLOAD_SUCCESS, "tld-activity-200606.csv")).thenReturn(true);
|
||||
IcannReportingUploadAction action = createAction();
|
||||
when(mockReporter.send(PAYLOAD_SUCCESS, "test-transactions-201706.csv"))
|
||||
action.run();
|
||||
ofy().clearSessionCache();
|
||||
Cursor cursor =
|
||||
ofy()
|
||||
.load()
|
||||
.key(Cursor.createKey(CursorType.ICANN_UPLOAD_ACTIVITY, Registry.get("tld")))
|
||||
.now();
|
||||
assertThat(cursor.getCursorTime()).isEqualTo(DateTime.parse("2006-07-01TZ"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_noUploadsNeeded() throws Exception {
|
||||
clock.setTo(DateTime.parse("2006-5-01T00:30:00Z"));
|
||||
IcannReportingUploadAction action = createAction();
|
||||
action.run();
|
||||
ofy().clearSessionCache();
|
||||
verifyNoMoreInteractions(mockReporter);
|
||||
verify(emailService)
|
||||
.sendEmail(
|
||||
EmailMessage.create(
|
||||
"ICANN Monthly report upload summary: 0/0 succeeded",
|
||||
"Report Filename - Upload status:\n",
|
||||
new InternetAddress("recipient@example.com"),
|
||||
new InternetAddress("sender@example.com")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_uploadManifest() throws Exception {
|
||||
persistResource(
|
||||
Cursor.createGlobal(CursorType.ICANN_UPLOAD_MANIFEST, DateTime.parse("2006-06-06TZ")));
|
||||
IcannReportingUploadAction action = createAction();
|
||||
action.run();
|
||||
ofy().clearSessionCache();
|
||||
Cursor cursor =
|
||||
ofy().load().key(Cursor.createGlobalKey(CursorType.ICANN_UPLOAD_MANIFEST)).now();
|
||||
assertThat(cursor.getCursorTime()).isEqualTo(DateTime.parse("2006-07-01TZ"));
|
||||
verify(mockReporter).send(PAYLOAD_FAIL, "tld-activity-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "foo-activity-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "foo-transactions-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "tld-transactions-200606.csv");
|
||||
verify(mockReporter).send(MANIFEST_PAYLOAD, "MANIFEST.txt");
|
||||
verifyNoMoreInteractions(mockReporter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_withRetry() throws Exception {
|
||||
IcannReportingUploadAction action = createAction();
|
||||
when(mockReporter.send(PAYLOAD_SUCCESS, "tld-transactions-200606.csv"))
|
||||
.thenThrow(new IOException("Expected exception."))
|
||||
.thenReturn(true);
|
||||
action.run();
|
||||
verify(mockReporter, times(2)).send(PAYLOAD_SUCCESS, "test-transactions-201706.csv");
|
||||
verify(mockReporter).send(PAYLOAD_FAIL, "a-activity-201706.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "foo-activity-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_FAIL, "tld-activity-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "foo-transactions-200606.csv");
|
||||
verify(mockReporter, times(2)).send(PAYLOAD_SUCCESS, "tld-transactions-200606.csv");
|
||||
verifyNoMoreInteractions(mockReporter);
|
||||
assertThat(((FakeResponse) action.response).getPayload())
|
||||
.isEqualTo("OK, attempted uploading 2 reports");
|
||||
verify(emailService)
|
||||
.sendEmail(
|
||||
EmailMessage.create(
|
||||
"ICANN Monthly report upload summary: 1/2 succeeded",
|
||||
"ICANN Monthly report upload summary: 3/4 succeeded",
|
||||
"Report Filename - Upload status:\n"
|
||||
+ "test-transactions-201706.csv - SUCCESS\n"
|
||||
+ "a-activity-201706.csv - FAILURE",
|
||||
new InternetAddress("recipient@example.com"),
|
||||
new InternetAddress("sender@example.com")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_firstUnrecoverable_stillAttemptsUploadingBoth() throws Exception {
|
||||
IcannReportingUploadAction action = createAction();
|
||||
when(mockReporter.send(PAYLOAD_SUCCESS, "test-transactions-201706.csv"))
|
||||
.thenThrow(new IOException("Expected exception"));
|
||||
action.run();
|
||||
verify(mockReporter, times(3)).send(PAYLOAD_SUCCESS, "test-transactions-201706.csv");
|
||||
verify(mockReporter).send(PAYLOAD_FAIL, "a-activity-201706.csv");
|
||||
verifyNoMoreInteractions(mockReporter);
|
||||
assertThat(((FakeResponse) action.response).getPayload())
|
||||
.isEqualTo("OK, attempted uploading 2 reports");
|
||||
verify(emailService)
|
||||
.sendEmail(
|
||||
EmailMessage.create(
|
||||
"ICANN Monthly report upload summary: 0/2 succeeded",
|
||||
"Report Filename - Upload status:\n"
|
||||
+ "test-transactions-201706.csv - FAILURE\n"
|
||||
+ "a-activity-201706.csv - FAILURE",
|
||||
+ "foo-activity-200606.csv - SUCCESS\n"
|
||||
+ "tld-activity-200606.csv - FAILURE\n"
|
||||
+ "foo-transactions-200606.csv - SUCCESS\n"
|
||||
+ "tld-transactions-200606.csv - SUCCESS",
|
||||
new InternetAddress("recipient@example.com"),
|
||||
new InternetAddress("sender@example.com")));
|
||||
}
|
||||
@@ -169,38 +252,149 @@ public class IcannReportingUploadActionTest {
|
||||
new IOException("Your IP address 25.147.130.158 is not allowed to connect"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_cursorIsNotAdvancedForward() throws Exception {
|
||||
runTest_nonRetryableException(
|
||||
new IOException("Your IP address 25.147.130.158 is not allowed to connect"));
|
||||
ofy().clearSessionCache();
|
||||
Cursor cursor =
|
||||
ofy()
|
||||
.load()
|
||||
.key(Cursor.createKey(CursorType.ICANN_UPLOAD_ACTIVITY, Registry.get("tld")))
|
||||
.now();
|
||||
assertThat(cursor.getCursorTime()).isEqualTo(DateTime.parse("2006-06-06TZ"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotRunIfCursorDateIsAfterToday() throws Exception {
|
||||
clock.setTo(DateTime.parse("2006-05-01T00:30:00Z"));
|
||||
IcannReportingUploadAction action = createAction();
|
||||
action.run();
|
||||
ofy().clearSessionCache();
|
||||
Cursor cursor =
|
||||
ofy()
|
||||
.load()
|
||||
.key(Cursor.createKey(CursorType.ICANN_UPLOAD_ACTIVITY, Registry.get("foo")))
|
||||
.now();
|
||||
assertThat(cursor.getCursorTime()).isEqualTo(DateTime.parse("2006-06-06TZ"));
|
||||
verifyNoMoreInteractions(mockReporter);
|
||||
}
|
||||
|
||||
private void runTest_nonRetryableException(Exception nonRetryableException) throws Exception {
|
||||
IcannReportingUploadAction action = createAction();
|
||||
when(mockReporter.send(PAYLOAD_FAIL, "a-activity-201706.csv"))
|
||||
when(mockReporter.send(PAYLOAD_FAIL, "tld-activity-200606.csv"))
|
||||
.thenThrow(nonRetryableException)
|
||||
.thenThrow(
|
||||
new AssertionError(
|
||||
"This should never be thrown because the previous exception isn't retryable"));
|
||||
action.run();
|
||||
verify(mockReporter, times(1)).send(PAYLOAD_FAIL, "a-activity-201706.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "test-transactions-201706.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "foo-activity-200606.csv");
|
||||
verify(mockReporter, times(1)).send(PAYLOAD_FAIL, "tld-activity-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "foo-transactions-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "tld-transactions-200606.csv");
|
||||
verifyNoMoreInteractions(mockReporter);
|
||||
assertThat(((FakeResponse) action.response).getPayload())
|
||||
.isEqualTo("OK, attempted uploading 2 reports");
|
||||
verify(emailService)
|
||||
.sendEmail(
|
||||
EmailMessage.create(
|
||||
"ICANN Monthly report upload summary: 1/2 succeeded",
|
||||
"ICANN Monthly report upload summary: 3/4 succeeded",
|
||||
"Report Filename - Upload status:\n"
|
||||
+ "test-transactions-201706.csv - SUCCESS\n"
|
||||
+ "a-activity-201706.csv - FAILURE",
|
||||
+ "foo-activity-200606.csv - SUCCESS\n"
|
||||
+ "tld-activity-200606.csv - FAILURE\n"
|
||||
+ "foo-transactions-200606.csv - SUCCESS\n"
|
||||
+ "tld-transactions-200606.csv - SUCCESS",
|
||||
new InternetAddress("recipient@example.com"),
|
||||
new InternetAddress("sender@example.com")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFail_FileNotFound() throws Exception {
|
||||
public void testFail_fileNotFound() throws Exception {
|
||||
IcannReportingUploadAction action = createAction();
|
||||
action.subdir = "somewhere/else";
|
||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, action::run);
|
||||
action.run();
|
||||
assertAboutLogs()
|
||||
.that(logHandler)
|
||||
.hasLogAtLevelWithMessage(
|
||||
Level.SEVERE,
|
||||
"Could not upload ICANN_UPLOAD_ACTIVITY report for foo because file"
|
||||
+ " foo-activity-200606.csv did not exist");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWarning_fileNotStagedYet() throws Exception {
|
||||
persistResource(
|
||||
Cursor.create(
|
||||
CursorType.ICANN_UPLOAD_ACTIVITY, DateTime.parse("2006-07-01TZ"), Registry.get("foo")));
|
||||
clock.setTo(DateTime.parse("2006-07-01T00:30:00Z"));
|
||||
IcannReportingUploadAction action = createAction();
|
||||
action.subdir = "icann/monthly/2006-07";
|
||||
action.run();
|
||||
assertAboutLogs()
|
||||
.that(logHandler)
|
||||
.hasLogAtLevelWithMessage(
|
||||
Level.INFO,
|
||||
"Could not upload ICANN_UPLOAD_ACTIVITY report for foo because file"
|
||||
+ " foo-activity-200607.csv did not exist. This report may not have been staged"
|
||||
+ " yet.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_lockIsntAvailable() throws Exception {
|
||||
IcannReportingUploadAction action = createAction();
|
||||
action.lockHandler = new FakeLockHandler(false);
|
||||
ServiceUnavailableException thrown =
|
||||
assertThrows(ServiceUnavailableException.class, () -> action.run());
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Object MANIFEST.txt in bucket basin/somewhere/else not found");
|
||||
.contains("Lock for IcannReportingUploadAction already in use");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_nullCursors() throws Exception {
|
||||
createTlds("new");
|
||||
writeGcsFile(
|
||||
gcsService,
|
||||
new GcsFilename("basin/icann/monthly/2006-06", "new-transactions-200606.csv"),
|
||||
PAYLOAD_SUCCESS);
|
||||
writeGcsFile(
|
||||
gcsService,
|
||||
new GcsFilename("basin/icann/monthly/2006-06", "new-activity-200606.csv"),
|
||||
PAYLOAD_SUCCESS);
|
||||
when(mockReporter.send(PAYLOAD_SUCCESS, "new-transactions-200606.csv")).thenReturn(true);
|
||||
when(mockReporter.send(PAYLOAD_SUCCESS, "new-activity-200606.csv")).thenReturn(true);
|
||||
|
||||
IcannReportingUploadAction action = createAction();
|
||||
action.run();
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "foo-activity-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_FAIL, "tld-activity-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "new-activity-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "foo-transactions-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "tld-transactions-200606.csv");
|
||||
verify(mockReporter).send(PAYLOAD_SUCCESS, "new-transactions-200606.csv");
|
||||
verifyNoMoreInteractions(mockReporter);
|
||||
|
||||
verify(emailService)
|
||||
.sendEmail(
|
||||
EmailMessage.create(
|
||||
"ICANN Monthly report upload summary: 5/6 succeeded",
|
||||
"Report Filename - Upload status:\n"
|
||||
+ "foo-activity-200606.csv - SUCCESS\n"
|
||||
+ "new-activity-200606.csv - SUCCESS\n"
|
||||
+ "tld-activity-200606.csv - FAILURE\n"
|
||||
+ "foo-transactions-200606.csv - SUCCESS\n"
|
||||
+ "new-transactions-200606.csv - SUCCESS\n"
|
||||
+ "tld-transactions-200606.csv - SUCCESS",
|
||||
new InternetAddress("recipient@example.com"),
|
||||
new InternetAddress("sender@example.com")));
|
||||
|
||||
Cursor newActivityCursor =
|
||||
ofy()
|
||||
.load()
|
||||
.key(Cursor.createKey(CursorType.ICANN_UPLOAD_ACTIVITY, Registry.get("new")))
|
||||
.now();
|
||||
assertThat(newActivityCursor.getCursorTime()).isEqualTo(DateTime.parse("2006-07-01TZ"));
|
||||
Cursor newTransactionCursor =
|
||||
ofy().load().key(Cursor.createKey(CursorType.ICANN_UPLOAD_TX, Registry.get("new"))).now();
|
||||
assertThat(newTransactionCursor.getCursorTime()).isEqualTo(DateTime.parse("2006-07-01TZ"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.schema.tld;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.registry.label.ReservationType;
|
||||
import google.registry.schema.tld.ReservedList.ReservedEntry;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/** Unit tests for {@link ReservedList} */
|
||||
@RunWith(JUnit4.class)
|
||||
public class ReservedListTest {
|
||||
|
||||
@Test
|
||||
public void verifyConstructorAndGetters_workCorrectly() {
|
||||
ReservedList reservedList =
|
||||
ReservedList.create(
|
||||
"app",
|
||||
false,
|
||||
ImmutableMap.of(
|
||||
"book",
|
||||
ReservedEntry.create(ReservationType.ALLOWED_IN_SUNRISE, null),
|
||||
"music",
|
||||
ReservedEntry.create(
|
||||
ReservationType.RESERVED_FOR_ANCHOR_TENANT, "reserved for anchor tenant")));
|
||||
|
||||
assertThat(reservedList.getName()).isEqualTo("app");
|
||||
assertThat(reservedList.getShouldPublish()).isFalse();
|
||||
assertThat(reservedList.getLabelsToReservations())
|
||||
.containsExactly(
|
||||
"book",
|
||||
ReservedEntry.create(ReservationType.ALLOWED_IN_SUNRISE, null),
|
||||
"music",
|
||||
ReservedEntry.create(
|
||||
ReservationType.RESERVED_FOR_ANCHOR_TENANT, "reserved for anchor tenant"));
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,10 @@ package google.registry.tools;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.common.io.Resources;
|
||||
import google.registry.persistence.NomulusPostgreSql;
|
||||
import java.io.File;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
@@ -37,8 +40,9 @@ public class GenerateSqlSchemaCommandTest extends CommandTestCase<GenerateSqlSch
|
||||
|
||||
@Rule public TemporaryFolder tmp = new TemporaryFolder();
|
||||
|
||||
@ClassRule public static PostgreSQLContainer postgres =
|
||||
new PostgreSQLContainer()
|
||||
@ClassRule
|
||||
public static PostgreSQLContainer postgres =
|
||||
new PostgreSQLContainer(NomulusPostgreSql.getDockerTag())
|
||||
.withDatabaseName("postgres")
|
||||
.withUsername("postgres")
|
||||
.withPassword("domain-registry");
|
||||
@@ -84,4 +88,14 @@ public class GenerateSqlSchemaCommandTest extends CommandTestCase<GenerateSqlSch
|
||||
"--start_postgresql", "--out_file=" + tmp.getRoot() + File.separatorChar + "schema.sql");
|
||||
assertThat(new File(tmp.getRoot(), "schema.sql").exists()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateGeneratedSchemaIsSameAsSchemaInFile() throws Exception {
|
||||
runCommand(
|
||||
"--start_postgresql", "--out_file=" + tmp.getRoot() + File.separatorChar + "schema.sql");
|
||||
assertThat(Files.readLines(new File(tmp.getRoot(), "schema.sql"), Charsets.UTF_8))
|
||||
.isEqualTo(
|
||||
Resources.readLines(
|
||||
Resources.getResource("sql/schema/db-schema.sql.generated"), Charsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
104
db/README.md
104
db/README.md
@@ -9,16 +9,16 @@ Nomulus uses the 'postgres' database in the 'public' schema. The following
|
||||
users/roles are defined:
|
||||
|
||||
* postgres: the initial user is used for admin and schema deployment.
|
||||
* In Cloud SQL, we do not control superusers. The initial 'postgres' user
|
||||
is a regular user with create-role/create-db privileges. Therefore,
|
||||
it is not possible to separate admin user and schema-deployment user.
|
||||
* In Cloud SQL, we do not control superusers. The initial 'postgres' user
|
||||
is a regular user with create-role/create-db privileges. Therefore, it
|
||||
is not possible to separate admin user and schema-deployment user.
|
||||
* readwrite is a role with read-write privileges on all data tables and
|
||||
sequences. However, it does not have write access to admin tables. Nor
|
||||
can it create new tables.
|
||||
sequences. However, it does not have write access to admin tables. Nor can
|
||||
it create new tables.
|
||||
* The Registry server user is granted this role.
|
||||
* readonly is a role with SELECT privileges on all tables.
|
||||
* Reporting job user and individual human readers may be granted
|
||||
this role.
|
||||
* Reporting job user and individual human readers may be granted this
|
||||
role.
|
||||
|
||||
### Schema DDL Scripts
|
||||
|
||||
@@ -33,23 +33,29 @@ Below are the steps to submit a schema change:
|
||||
`core/src/main/resources/META-INF/persistence.xml` so they'll be picked up.
|
||||
2. Run the `nomulus generate_sql_schema` command to generate a new version of
|
||||
`db-schema.sql.generated`. The full command line to do this is:
|
||||
|
||||
`./gradlew registryTool --args="-e localhost generate_sql_schema --start_postgresql -o /path/to/nomulus/db/src/main/resources/sql/schema/db-schema.sql.generated"`
|
||||
3. Write an incremental DDL script that changes the existing schema to your
|
||||
new one. The generated SQL file from the previous step should help. New
|
||||
create table statements can be used as is, whereas alter table statements
|
||||
should be written to change any existing tables.
|
||||
|
||||
|
||||
`./gradlew registryTool --args="-e localhost generate_sql_schema
|
||||
--start_postgresql -o
|
||||
/path/to/nomulus/db/src/main/resources/sql/schema/db-schema.sql.generated"`
|
||||
|
||||
3. Write an incremental DDL script that changes the existing schema to your new
|
||||
one. The generated SQL file from the previous step should help. New create
|
||||
table statements can be used as is, whereas alter table statements should be
|
||||
written to change any existing tables.
|
||||
|
||||
This script should be stored in a new file in the
|
||||
`db/src/main/resources/sql/flyway` folder using the naming pattern
|
||||
`V{id}__{description text}.sql`, where `{id}` is the next highest number
|
||||
following the existing scripts in that folder. Note the double underscore in
|
||||
the naming pattern.
|
||||
|
||||
4. Run the `:db:test` task from the Gradle root project. The SchemaTest will
|
||||
fail because the new schema does not match the golden file.
|
||||
5. Copy `db/build/resources/test/testcontainer/mount/dump.txt` to the golden file
|
||||
`db/src/main/resources/sql/schema/nomulus.golden.sql`. Diff it against the
|
||||
old version and verify that all changes are expected.
|
||||
|
||||
5. Copy `db/build/resources/test/testcontainer/mount/dump.txt` to the golden
|
||||
file `db/src/main/resources/sql/schema/nomulus.golden.sql`. Diff it against
|
||||
the old version and verify that all changes are expected.
|
||||
|
||||
6. Re-run the `:db:test` task. This time all tests should pass.
|
||||
|
||||
Relevant files (under db/src/main/resources/sql/schema/):
|
||||
@@ -66,23 +72,63 @@ example, when adding a new column to a table, we would deploy the change before
|
||||
adding it to the relevant ORM class. Therefore, for a short time the golden file
|
||||
will contain the new column while the generated one does not.
|
||||
|
||||
### Non-production Schema Push
|
||||
### Schema Push
|
||||
|
||||
To manage schema in a non-production environment, use the 'flywayMigration'
|
||||
task. You will need Cloud SDK and login once.
|
||||
Currently Cloud SQL schema is released with the Nomulus server, and shares the
|
||||
server release's tag (e.g., nomulus-20191101-RC00). Automatic schema push
|
||||
process (to apply new changes in a released schema to the databases) has not
|
||||
been set up yet, and new schema may be pushed manually on demand.
|
||||
|
||||
Presubmit and continuous-integration tests are being implemented to ensure
|
||||
server/schema compatibility. Before the tests are activated, please look for
|
||||
breaking changes before deploying a schema.
|
||||
|
||||
Released schema may be deployed using Cloud Build. Use the root project
|
||||
directory as working directory, run the following shell snippets:
|
||||
|
||||
```shell
|
||||
# Tags exist as folder names under gs://domain-registry-dev-deploy.
|
||||
SCHEMA_TAG=
|
||||
# Recognized environments are alpha, crash, sandbox and production
|
||||
SQL_ENV=
|
||||
# Deploy on cloud build. The --project is optional if domain-registry-dev
|
||||
# is already your default project.
|
||||
gcloud builds submit --config=release/cloudbuild-schema-deploy.yaml \
|
||||
--substitutions=TAG_NAME=${SCHEMA_TAG},_ENV=${SQL_ENV} \
|
||||
--project domain-registry-dev
|
||||
# Verify by checking Flyway Schema History:
|
||||
./gradlew :db:flywayInfo -PdbServer=${SQL_ENV}
|
||||
```
|
||||
|
||||
#### Glass Breaking
|
||||
|
||||
If you need to deploy a schema off-cycle, try making a release first, then
|
||||
deploy that release schema to Cloud SQL.
|
||||
|
||||
TODO(weiminyu): elaborate on different ways to push schema without a full
|
||||
release.
|
||||
|
||||
#### Notes On Flyway
|
||||
|
||||
Please note: to run Flyway commands, you need Cloud SDK and need to log in once.
|
||||
|
||||
```shell
|
||||
# One time login
|
||||
gcloud auth login
|
||||
|
||||
# Deploy the current schema to alpha
|
||||
gradlew :db:flywayMigrate -PdbServer=alpha
|
||||
|
||||
# Delete the entire schema in alpha
|
||||
gradlew :db:flywayClean -PdbServer=alpha
|
||||
```
|
||||
|
||||
The flywayMigrate task is idempotent. Repeated runs will not introduce problems.
|
||||
The Flyway-based Cloud Build schema push process is safe in common scenarios:
|
||||
|
||||
* Repeatedly deploying the latest schema is safe. All duplicate runs become
|
||||
NOP.
|
||||
|
||||
* Accidentally deploying a past schema is safe. Flyway will not undo
|
||||
incremental changes not reflected in the deployed schema.
|
||||
|
||||
* Concurrent deployment runs are safe. Flyway locks its own metadata table,
|
||||
serializing deployment runs without affecting normal accesses.
|
||||
|
||||
#### Schema Push to Local Database
|
||||
|
||||
The Flyway tasks may also be used to deploy to local instances, e.g, your own
|
||||
test instance. E.g.,
|
||||
@@ -95,7 +141,3 @@ gradlew :db:flywayMigrate -PdbServer=192.168.9.2 -PdbPassword=domain-registry
|
||||
gradlew :db:flywayMigrate -PdbServer=192.168.9.2:5432 -PdbUser=postgres \
|
||||
-PdbPassword=domain-registry
|
||||
```
|
||||
|
||||
### Production Schema Deployment
|
||||
|
||||
Schema deployment to production and sandbox is under development.
|
||||
|
||||
@@ -31,24 +31,8 @@ ext {
|
||||
def dbServer = findProperty(dbServerProperty).toString().toLowerCase()
|
||||
def dbName = findProperty(dbNameProperty)
|
||||
|
||||
reconfirmRestrictedDbEnv = {
|
||||
if (!restrictedDbEnv.contains(dbServer)) {
|
||||
return
|
||||
}
|
||||
// For restricted environments, ask the user to type again to confirm.
|
||||
// The following statement uses Gradle internal API to get around the
|
||||
// missing console bug when Gradle Daemon is in use. Another option is
|
||||
// to use the ant.input task. For details please refer to
|
||||
// https://github.com/gradle/gradle/issues/1251.
|
||||
def dbServerAgain = services.get(UserInputHandler.class).askQuestion(
|
||||
"""\
|
||||
Are you sure? Operating on ${dbServer} from desktop is unsafe.
|
||||
Please type '${dbServer}' again to proceed: """.stripIndent(),
|
||||
'').trim()
|
||||
if (dbServer != dbServerAgain) {
|
||||
throw new RuntimeException(
|
||||
"Failed to confirm for restricted database environment. Operation aborted.")
|
||||
}
|
||||
isCloudSql = {
|
||||
return allDbEnv.contains(dbServer)
|
||||
}
|
||||
|
||||
getAccessInfoByHostPort = { hostAndPort ->
|
||||
@@ -87,18 +71,14 @@ ext {
|
||||
// production. The role parameter may be superuser. (More roles will be added
|
||||
// later).
|
||||
getCloudSqlCredential = { env, role ->
|
||||
env = env == 'production' ? '' : "-${env}"
|
||||
def keyProject = env == '-crash'
|
||||
? 'domain-registry-crash-kms-keys'
|
||||
: "domain-registry${env}-keys"
|
||||
def command =
|
||||
"""gsutil cp \
|
||||
gs://domain-registry${env}-cloudsql-credentials/${role}_credential.enc - | \
|
||||
gs://${rootProject.devProject}-deploy/cloudsql-credentials/${env}/${role}_credential.enc - | \
|
||||
base64 -d | \
|
||||
gcloud kms decrypt --location global --keyring nomulus \
|
||||
--key sql-credentials-on-gcs-key --plaintext-file=- \
|
||||
gcloud kms decrypt --location global --keyring nomulus-tool-keyring \
|
||||
--key nomulus-tool-key --plaintext-file=- \
|
||||
--ciphertext-file=- \
|
||||
--project=${keyProject}"""
|
||||
--project=${rootProject.devProject}"""
|
||||
|
||||
return execInBash(command, '/tmp')
|
||||
}
|
||||
@@ -112,8 +92,23 @@ task schemaJar(type: Jar) {
|
||||
}
|
||||
}
|
||||
|
||||
// Expose NomulusPostgreSql class to ':core' for compile, without leaking
|
||||
// unnecessary dependencies to the release artifacts through ':core'.
|
||||
// Jar is put in the 'compileApi' configuration.
|
||||
task compileApiJar(type: Jar) {
|
||||
archiveBaseName = 'compile'
|
||||
from(sourceSets.main.output) {
|
||||
include 'google/registry/persistence/NomulusPostgreSql**'
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
compileApi
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives schemaJar
|
||||
compileApi compileApiJar
|
||||
}
|
||||
|
||||
publishing {
|
||||
@@ -132,7 +127,6 @@ publishing {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
flyway {
|
||||
def accessInfo = project.ext.getJdbcAccessInfo()
|
||||
|
||||
@@ -144,13 +138,6 @@ flyway {
|
||||
locations = [ "classpath:sql/flyway" ]
|
||||
}
|
||||
|
||||
tasks.flywayMigrate.dependsOn(
|
||||
tasks.create('confirmMigrateOnRestrictedDb') {
|
||||
doLast {
|
||||
project.ext.reconfirmRestrictedDbEnv()
|
||||
}
|
||||
})
|
||||
|
||||
dependencies {
|
||||
def deps = rootProject.dependencyMap
|
||||
|
||||
@@ -170,7 +157,23 @@ dependencies {
|
||||
testCompile project(':third_party')
|
||||
}
|
||||
|
||||
// Ensure that resources are rebuilt before running Flyway tasks
|
||||
tasks
|
||||
.findAll { task -> task.group.equals('Flyway')}
|
||||
.collect { task -> task.dependsOn('buildNeeded') }
|
||||
flywayValidate.dependsOn('buildNeeded')
|
||||
|
||||
if (ext.isCloudSql()) {
|
||||
// Disable dangerous Flyway tasks. Only allow info and validate.
|
||||
tasks.findAll { task -> task.group.equals('Flyway')}.each {
|
||||
if (it.name == 'flywayMigrate') {
|
||||
it.doFirst {
|
||||
throw new UnsupportedOperationException(
|
||||
""" \
|
||||
FlywayMigrate is disabled. See README.md for schema deployment
|
||||
instructions.""".stripIndent())
|
||||
}
|
||||
} else if (it.name != 'flywayInfo' && it.name != 'flywayValidate') {
|
||||
it.doFirst {
|
||||
throw new UnsupportedOperationException(
|
||||
"${it.name} from commandline is not allowed.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
3
db/gradle/dependency-locks/compileApi.lockfile
Normal file
3
db/gradle/dependency-locks/compileApi.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
// Copyright 2019 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.
|
||||
@@ -11,22 +11,17 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package google.registry.persistence;
|
||||
|
||||
package google.registry.util;
|
||||
/** Information about Nomulus' Cloud SQL PostgreSql instance. */
|
||||
public class NomulusPostgreSql {
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
/** The current PostgreSql version in Cloud SQL. */
|
||||
// TODO(weiminyu): setup periodic checks to detect version changes in Cloud SQL.
|
||||
private static final String TARGET_VERSION = "11.5";
|
||||
|
||||
/** A simple clock that always returns a fixed time. */
|
||||
public class FixedClock implements Clock {
|
||||
private final DateTime nowUtc;
|
||||
|
||||
public FixedClock(long millisSinceEpoch) {
|
||||
this.nowUtc = new DateTime(millisSinceEpoch, DateTimeZone.UTC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateTime nowUtc() {
|
||||
return nowUtc;
|
||||
/** Returns the docker image tag of the targeted Postgresql server version. */
|
||||
public static String getDockerTag() {
|
||||
return "postgres:" + TARGET_VERSION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
-- Copyright 2019 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 "ReservedEntry" (
|
||||
revision_id int8 not null,
|
||||
comment text,
|
||||
reservation_type int4 not null,
|
||||
domain_label text not null,
|
||||
primary key (revision_id, domain_label)
|
||||
);
|
||||
|
||||
create table "ReservedList" (
|
||||
revision_id bigserial not null,
|
||||
creation_timestamp timestamptz not null,
|
||||
name text not null,
|
||||
should_publish boolean not null,
|
||||
primary key (revision_id)
|
||||
);
|
||||
|
||||
create index reservedlist_name_idx on "ReservedList" (name);
|
||||
|
||||
alter table if exists "ReservedEntry"
|
||||
add constraint FKgq03rk0bt1hb915dnyvd3vnfc
|
||||
foreign key (revision_id)
|
||||
references "ReservedList";
|
||||
@@ -44,9 +44,9 @@
|
||||
repo_id text not null,
|
||||
creation_client_id text,
|
||||
current_sponsor_client_id text,
|
||||
deletion_time bytea,
|
||||
deletion_time timestamptz,
|
||||
last_epp_update_client_id text,
|
||||
last_epp_update_time bytea,
|
||||
last_epp_update_time timestamptz,
|
||||
revisions bytea,
|
||||
auth_info_repo_id text,
|
||||
auth_info_value text,
|
||||
@@ -55,12 +55,12 @@
|
||||
delete_poll_message bytea,
|
||||
fully_qualified_domain_name text,
|
||||
idn_table_name text,
|
||||
last_transfer_time bytea,
|
||||
launch_notice_accepted_time bytea,
|
||||
launch_notice_expiration_time bytea,
|
||||
last_transfer_time timestamptz,
|
||||
launch_notice_accepted_time timestamptz,
|
||||
launch_notice_expiration_time timestamptz,
|
||||
launch_notice_tcn_id text,
|
||||
launch_notice_validator_id text,
|
||||
registration_expiration_time bytea,
|
||||
registration_expiration_time timestamptz,
|
||||
smd_id text,
|
||||
tld text,
|
||||
transfer_data_server_approve_autorenrew_event bytea,
|
||||
@@ -70,11 +70,11 @@
|
||||
value int4,
|
||||
client_transaction_id text,
|
||||
server_transaction_id text,
|
||||
transfer_data_registration_expiration_time bytea,
|
||||
transfer_data_registration_expiration_time timestamptz,
|
||||
gaining_client_id text,
|
||||
losing_client_id text,
|
||||
pending_transfer_expiration_time bytea,
|
||||
transfer_request_time bytea,
|
||||
pending_transfer_expiration_time timestamptz,
|
||||
transfer_request_time timestamptz,
|
||||
transfer_status int4,
|
||||
primary key (repo_id)
|
||||
);
|
||||
@@ -117,7 +117,7 @@
|
||||
billing_event_one_time bytea,
|
||||
billing_event_recurring bytea,
|
||||
client_id text,
|
||||
expiration_time bytea,
|
||||
expiration_time timestamptz,
|
||||
type int4,
|
||||
primary key (id)
|
||||
);
|
||||
@@ -152,6 +152,22 @@
|
||||
primary key (revision_id)
|
||||
);
|
||||
|
||||
create table "ReservedEntry" (
|
||||
revision_id int8 not null,
|
||||
comment text,
|
||||
reservation_type int4 not null,
|
||||
domain_label text not null,
|
||||
primary key (revision_id, domain_label)
|
||||
);
|
||||
|
||||
create table "ReservedList" (
|
||||
revision_id bigserial not null,
|
||||
creation_timestamp timestamptz not null,
|
||||
name text not null,
|
||||
should_publish boolean not null,
|
||||
primary key (revision_id)
|
||||
);
|
||||
|
||||
alter table if exists "Domain_DelegationSignerData"
|
||||
add constraint UK_2yp55erx1i51pa7gnb8bu7tjn unique (ds_data_key_tag);
|
||||
|
||||
@@ -166,6 +182,7 @@ create index idx_registry_lock_registrar_id on "RegistryLock" (registrar_id);
|
||||
|
||||
alter table if exists "RegistryLock"
|
||||
add constraint idx_registry_lock_repo_id_revision_id unique (repo_id, revision_id);
|
||||
create index reservedlist_name_idx on "ReservedList" (name);
|
||||
|
||||
alter table if exists "ClaimsEntry"
|
||||
add constraint FK6sc6at5hedffc0nhdcab6ivuq
|
||||
@@ -221,3 +238,8 @@ create index idx_registry_lock_registrar_id on "RegistryLock" (registrar_id);
|
||||
add constraint FKo0gw90lpo1tuee56l0nb6y6g5
|
||||
foreign key (revision_id)
|
||||
references "PremiumList";
|
||||
|
||||
alter table if exists "ReservedEntry"
|
||||
add constraint FKgq03rk0bt1hb915dnyvd3vnfc
|
||||
foreign key (revision_id)
|
||||
references "ReservedList";
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
-- PostgreSQL database dump
|
||||
--
|
||||
|
||||
-- Dumped from database version 9.6.12
|
||||
-- Dumped by pg_dump version 9.6.12
|
||||
-- Dumped from database version 11.5 (Debian 11.5-3.pgdg90+1)
|
||||
-- Dumped by pg_dump version 11.5 (Debian 11.5-3.pgdg90+1)
|
||||
|
||||
SET statement_timeout = 0;
|
||||
SET lock_timeout = 0;
|
||||
@@ -12,23 +12,10 @@ SET client_encoding = 'UTF8';
|
||||
SET standard_conforming_strings = on;
|
||||
SELECT pg_catalog.set_config('search_path', '', false);
|
||||
SET check_function_bodies = false;
|
||||
SET xmloption = content;
|
||||
SET client_min_messages = warning;
|
||||
SET row_security = off;
|
||||
|
||||
--
|
||||
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -
|
||||
--
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
|
||||
|
||||
|
||||
--
|
||||
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: -
|
||||
--
|
||||
|
||||
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
|
||||
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
SET default_with_oids = false;
|
||||
@@ -154,6 +141,49 @@ CREATE SEQUENCE public."RegistryLock_revision_id_seq"
|
||||
ALTER SEQUENCE public."RegistryLock_revision_id_seq" OWNED BY public."RegistryLock".revision_id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: ReservedEntry; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public."ReservedEntry" (
|
||||
revision_id bigint NOT NULL,
|
||||
comment text,
|
||||
reservation_type integer NOT NULL,
|
||||
domain_label text NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: ReservedList; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public."ReservedList" (
|
||||
revision_id bigint NOT NULL,
|
||||
creation_timestamp timestamp with time zone NOT NULL,
|
||||
name text NOT NULL,
|
||||
should_publish boolean NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: ReservedList_revision_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public."ReservedList_revision_id_seq"
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: ReservedList_revision_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public."ReservedList_revision_id_seq" OWNED BY public."ReservedList".revision_id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: ClaimsList revision_id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -175,6 +205,13 @@ ALTER TABLE ONLY public."PremiumList" ALTER COLUMN revision_id SET DEFAULT nextv
|
||||
ALTER TABLE ONLY public."RegistryLock" ALTER COLUMN revision_id SET DEFAULT nextval('public."RegistryLock_revision_id_seq"'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: ReservedList revision_id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."ReservedList" ALTER COLUMN revision_id SET DEFAULT nextval('public."ReservedList_revision_id_seq"'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: ClaimsEntry ClaimsEntry_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -215,6 +252,22 @@ ALTER TABLE ONLY public."RegistryLock"
|
||||
ADD CONSTRAINT "RegistryLock_pkey" PRIMARY KEY (revision_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: ReservedEntry ReservedEntry_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."ReservedEntry"
|
||||
ADD CONSTRAINT "ReservedEntry_pkey" PRIMARY KEY (revision_id, domain_label);
|
||||
|
||||
|
||||
--
|
||||
-- Name: ReservedList ReservedList_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."ReservedList"
|
||||
ADD CONSTRAINT "ReservedList_pkey" PRIMARY KEY (revision_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: RegistryLock idx_registry_lock_repo_id_revision_id; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -244,6 +297,13 @@ CREATE INDEX idx_registry_lock_verification_code ON public."RegistryLock" USING
|
||||
CREATE INDEX premiumlist_name_idx ON public."PremiumList" USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- Name: reservedlist_name_idx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX reservedlist_name_idx ON public."ReservedList" USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- Name: ClaimsEntry fk6sc6at5hedffc0nhdcab6ivuq; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -252,6 +312,14 @@ ALTER TABLE ONLY public."ClaimsEntry"
|
||||
ADD CONSTRAINT fk6sc6at5hedffc0nhdcab6ivuq FOREIGN KEY (revision_id) REFERENCES public."ClaimsList"(revision_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: ReservedEntry fkgq03rk0bt1hb915dnyvd3vnfc; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."ReservedEntry"
|
||||
ADD CONSTRAINT fkgq03rk0bt1hb915dnyvd3vnfc FOREIGN KEY (revision_id) REFERENCES public."ReservedList"(revision_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: PremiumEntry fko0gw90lpo1tuee56l0nb6y6g5; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
@@ -19,6 +19,7 @@ import static google.registry.testing.TextDiffSubject.assertThat;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.io.Resources;
|
||||
import google.registry.persistence.NomulusPostgreSql;
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -54,7 +55,7 @@ public class SchemaTest {
|
||||
*/
|
||||
@Rule
|
||||
public PostgreSQLContainer sqlContainer =
|
||||
new PostgreSQLContainer<>("postgres:9.6.12")
|
||||
new PostgreSQLContainer<>(NomulusPostgreSql.getDockerTag())
|
||||
.withClasspathResourceMapping(
|
||||
MOUNTED_RESOURCE_PATH, CONTAINER_MOUNT_POINT, BindMode.READ_WRITE);
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ reconstruct a premium list .txt file from the premium list that is loaded into
|
||||
Datastore (though in principle it would be easy to do by writing a tool to do
|
||||
so), so don't lose those .txt files.
|
||||
|
||||
An example premium list can be found at
|
||||
`java/google/registry/model/registry/config/files/premium/example.txt`.
|
||||
The nomulus repository contains an
|
||||
[example premium list file](https://github.com/google/nomulus/blob/master/core/src/main/java/google/registry/config/files/premium/example.txt).
|
||||
|
||||
## Creating a premium list
|
||||
|
||||
@@ -52,6 +52,9 @@ that the convention of naming premium lists after the TLD they are intended to
|
||||
be used for is enforced unless the override parameter `-o` is passed, which
|
||||
allows premium lists to be created with any name.
|
||||
|
||||
You're not done yet! After creating the premium list you must the apply it to
|
||||
one or more TLDs (see below) for it to actually be used.
|
||||
|
||||
## Updating a premium list
|
||||
|
||||
If the premium list already exists and you want to update it with new prices
|
||||
@@ -66,6 +69,10 @@ Perform this command? (y/N): y
|
||||
Successfully saved premium list exampletld
|
||||
```
|
||||
|
||||
If this premium list is already applied to a TLD, then changes will take up to
|
||||
60 minutes to take effect (depending on how you've configured the relevant
|
||||
caching interval; 60 minutes is the default).
|
||||
|
||||
## Applying a premium list to a TLD
|
||||
|
||||
Separate from the management of the contents of individual premium lists, a
|
||||
@@ -92,9 +99,9 @@ all other information about a TLD). It is used as follows:
|
||||
|
||||
```shell
|
||||
$ nomulus -e {ENVIRONMENT} get_tld exampletld
|
||||
[ ... snip ... ]
|
||||
[ ... snip output ... ]
|
||||
premiumList=Key<?>(EntityGroupRoot("cross-tld")/PremiumList("exampletld"))
|
||||
[ ... snip ... ]
|
||||
[ ... snip output ... ]
|
||||
```
|
||||
|
||||
## Listing all available premium lists
|
||||
@@ -107,3 +114,22 @@ $ nomulus -e {ENVIRONMENT} list_premium_lists
|
||||
exampletld
|
||||
someotherlist
|
||||
```
|
||||
|
||||
## Verifying premium list updates
|
||||
|
||||
To verify that the changes have actually been applied, you can run a domain
|
||||
check on a modified entry using the `nomulus check_domain` command and verify
|
||||
that the domain now has the correct price.
|
||||
|
||||
```shell
|
||||
$ nomulus -e production check_domain {domain_name}
|
||||
[ ... snip output ... ]
|
||||
```
|
||||
|
||||
**Note that the list can be cached for up to 60 minutes, so the old value may
|
||||
still be returned for a little while**. If it is urgent that the new pricing
|
||||
changes be applied, and it's OK to potentially interrupt client connections,
|
||||
then you can use the App Engine web console to kill instances of the `default`
|
||||
service, as the cache is per-instance. Once you've killed all the existing
|
||||
instances (don't kill them all at once!), all of the newly spun up instances
|
||||
will now be using the new values you've configured.
|
||||
|
||||
@@ -65,14 +65,19 @@ acmecorp,RESERVED_FOR_ANCHOR_TENANT
|
||||
internaldomain,NAMESERVER_RESTRICTED,ns1.internal.tld:ns1.internal.tld
|
||||
```
|
||||
|
||||
# Reserved list file name format
|
||||
|
||||
There are two types of reserved lists: Those that are intended to apply to a
|
||||
specifc TLD, and are thus prefixed with the name of the TLD followed by an
|
||||
specific TLD, and are thus prefixed with the name of the TLD followed by an
|
||||
underscore, and those that can be applied to any TLD, and are prefixed with
|
||||
`common_`. For example, a list of reserved labels on the TLD `exampletld` might
|
||||
be named `exampletld_blocked-names.txt`, whereas a similar list intended to
|
||||
apply to multiple TLDs might be named `common_blocked-names.txt`. Note that
|
||||
these naming conventions are enforced by the tooling used to create and apply
|
||||
reserved lists (see subsequent sections).
|
||||
reserved lists (see subsequent sections). The two naming patterns are thus:
|
||||
|
||||
* `common_list-name.txt`
|
||||
* `tldname_list-name.txt`
|
||||
|
||||
## Creating a reserved list
|
||||
|
||||
@@ -82,17 +87,20 @@ purposes of this example, we are creating a common reserved list named
|
||||
"common_bad-words".
|
||||
|
||||
```shell
|
||||
$ nomulus -e {ENVIRONMENT} create_reserved_list -n common_bad-words \
|
||||
-i common_bad-words.txt
|
||||
$ nomulus -e {ENVIRONMENT} create_reserved_list -i common_bad-words.txt
|
||||
[ ... snip long confirmation prompt ... ]
|
||||
Perform this command? (y/N): y
|
||||
Updated 1 entities.
|
||||
```
|
||||
|
||||
`-n` is the name of the reserved list to create, and `-i` is the input file
|
||||
containing the list. Note that if `-n` is omitted, the list name is inferred
|
||||
from the input of the filename minus its file extension. It is recommended to
|
||||
store all lists such that the filename and list name are identical.
|
||||
Note that `-i` is the input file containing the list. You can optionally specify
|
||||
the name of the reserved list using `-n`, but when it's omitted as above the
|
||||
list name is inferred from the name of the filename (minus the file extension).
|
||||
For ease of tracking track of things, it is recommended to store all lists such
|
||||
that the filename and list name are identical.
|
||||
|
||||
You're not done yet! After creating the reserved list you must the apply it to
|
||||
one or more TLDs (see below) for it to actually be used.
|
||||
|
||||
## Updating a reserved list
|
||||
|
||||
@@ -101,15 +109,14 @@ file containing the reserved list entries, then pass it as input to the
|
||||
`update_reserved_list` command as follows:
|
||||
|
||||
```shell
|
||||
$ nomulus -e {ENVIRONMENT} update_reserved_list -n common_bad-words \
|
||||
-i common_bad-words.txt
|
||||
$ nomulus -e {ENVIRONMENT} update_reserved_list -i common_bad-words.txt
|
||||
[ ... snip diff of changes to list entries ... ]
|
||||
Perform this command? (y/N): y
|
||||
Updated 1 entities.
|
||||
```
|
||||
|
||||
Note that, like the create command, the name of the list is inferred from the
|
||||
filename if the `-n` parameter is omitted.
|
||||
filename unless you specify the `-n` parameter (not generally recommended).
|
||||
|
||||
## Applying a reserved list to a TLD
|
||||
|
||||
@@ -149,9 +156,9 @@ purposes here. It is used as follows:
|
||||
|
||||
```shell
|
||||
$ nomulus -e {ENVIRONMENT} get_tld exampletld
|
||||
[ ... snip ... ]
|
||||
[ ... snip output ... ]
|
||||
reservedLists=[Key<?>(EntityGroupRoot("cross-tld")/ReservedList("common_bad-words"))]
|
||||
[ ... snip ... ]
|
||||
[ ... snip output ... ]
|
||||
```
|
||||
|
||||
## Listing all available reserved lists
|
||||
@@ -165,3 +172,22 @@ $ nomulus -e {ENVIRONMENT} list_reserved_lists
|
||||
common_bad-words
|
||||
exampletld_some-other-list
|
||||
```
|
||||
|
||||
## Verifying reserved list updates
|
||||
|
||||
To verify that the changes have actually been applied, you can run a domain
|
||||
check on a modified entry using the `nomulus check_domain` command and verify
|
||||
that the domain now has the correct reservation status.
|
||||
|
||||
```shell
|
||||
$ nomulus -e production check_domain {domain_name}
|
||||
[ ... snip output ... ]
|
||||
```
|
||||
|
||||
**Note that the list can be cached for up to 60 minutes, so changes may not
|
||||
take place immediately**. If it is urgent that the new changes be applied, and
|
||||
it's OK to potentially interrupt client connections, then you can use the App
|
||||
Engine web console to kill instances of the `default` service, as the cache is
|
||||
per-instance. Once you've killed all the existing instances (don't kill them all
|
||||
at once!), all of the newly spun up instances will now be using the new values
|
||||
you've configured.
|
||||
|
||||
@@ -41,6 +41,16 @@ where:
|
||||
|
||||
SCRIPT_DIR="$(realpath $(dirname $0))"
|
||||
|
||||
function showNoncompliantFiles() {
|
||||
local forkPoint="$1"
|
||||
local message="$2"
|
||||
|
||||
git diff -U0 ${forkPoint} | \
|
||||
${SCRIPT_DIR}/google-java-format-diff.py -p1 | \
|
||||
awk -v "message=$message" \
|
||||
'/\+\+\+ ([^ ]*)/ { print message $2 }' 1>&2
|
||||
}
|
||||
|
||||
function callGoogleJavaFormatDiff() {
|
||||
local forkPoint
|
||||
forkPoint=$(git merge-base --fork-point origin/master)
|
||||
@@ -48,10 +58,12 @@ function callGoogleJavaFormatDiff() {
|
||||
local callResult
|
||||
case "$1" in
|
||||
"check")
|
||||
showNoncompliantFiles "$forkPoint" "\033[1mNeeds formatting: "
|
||||
callResult=$(git diff -U0 ${forkPoint} | \
|
||||
${SCRIPT_DIR}/google-java-format-diff.py -p1 | wc -l)
|
||||
;;
|
||||
"format")
|
||||
showNoncompliantFiles "$forkPoint" "\033[1mReformatting: "
|
||||
callResult=$(git diff -U0 ${forkPoint} | \
|
||||
${SCRIPT_DIR}/google-java-format-diff.py -p1 -i)
|
||||
;;
|
||||
@@ -60,6 +72,7 @@ function callGoogleJavaFormatDiff() {
|
||||
${SCRIPT_DIR}/google-java-format-diff.py -p1)
|
||||
;;
|
||||
esac
|
||||
echo -e "\033[0m" 1>&2
|
||||
echo "${callResult}"
|
||||
exit 0
|
||||
}
|
||||
|
||||
@@ -94,8 +94,8 @@ task initCoverageMinimums {
|
||||
].asImmutable()
|
||||
|
||||
rootProject.ext.getMinCoverage = { key ->
|
||||
if (rootProject.ext.coverageMinimums.containsKey(key)) {
|
||||
return rootProject.ext.coverageMinimums.get(key)
|
||||
if (rootProject.coverageMinimums.containsKey(key)) {
|
||||
return rootProject.coverageMinimums.get(key)
|
||||
}
|
||||
return 0.0
|
||||
}
|
||||
@@ -117,7 +117,7 @@ jacocoTestCoverageVerification {
|
||||
// or MISSEDRATIO
|
||||
// - The 'minimum' threshold, given as a fraction or a percentage (including '%')
|
||||
limit {
|
||||
minimum = rootProject.ext.getMinCoverage(project.getName())
|
||||
minimum = rootProject.getMinCoverage(project.getName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
47
networking/build.gradle
Normal file
47
networking/build.gradle
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
dependencies {
|
||||
def deps = rootProject.dependencyMap
|
||||
|
||||
compile deps['com.google.flogger:flogger']
|
||||
compile deps['com.google.guava:guava']
|
||||
compile deps['io.netty:netty-buffer']
|
||||
compile deps['io.netty:netty-codec']
|
||||
compile deps['io.netty:netty-codec-http']
|
||||
compile deps['io.netty:netty-common']
|
||||
compile deps['io.netty:netty-handler']
|
||||
compile deps['io.netty:netty-transport']
|
||||
compile deps['javax.inject:javax.inject']
|
||||
compile project(':util')
|
||||
|
||||
runtime deps['com.google.flogger:flogger-system-backend']
|
||||
runtime deps['io.netty:netty-tcnative-boringssl-static']
|
||||
|
||||
testCompile deps['com.google.truth:truth']
|
||||
testCompile deps['junit:junit']
|
||||
testCompile deps['org.bouncycastle:bcpkix-jdk15on']
|
||||
testCompile deps['org.bouncycastle:bcprov-jdk15on']
|
||||
testCompile project(':third_party')
|
||||
}
|
||||
|
||||
// Make testing artifacts available to be depended up on by other projects.
|
||||
task testJar(type: Jar) {
|
||||
classifier = 'test'
|
||||
from sourceSets.test.output
|
||||
}
|
||||
|
||||
artifacts {
|
||||
testRuntime testJar
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
3
networking/gradle/dependency-locks/apt.lockfile
Normal file
3
networking/gradle/dependency-locks/apt.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
3
networking/gradle/dependency-locks/archives.lockfile
Normal file
3
networking/gradle/dependency-locks/archives.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
18
networking/gradle/dependency-locks/checkstyle.lockfile
Normal file
18
networking/gradle/dependency-locks/checkstyle.lockfile
Normal file
@@ -0,0 +1,18 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
antlr:antlr:2.7.7
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.0-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.puppycrawl.tools:checkstyle:8.24
|
||||
commons-beanutils:commons-beanutils:1.9.4
|
||||
commons-collections:commons-collections:3.2.2
|
||||
info.picocli:picocli:4.0.3
|
||||
net.sf.saxon:Saxon-HE:9.9.1-4
|
||||
org.antlr:antlr4-runtime:4.7.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
46
networking/gradle/dependency-locks/compile.lockfile
Normal file
46
networking/gradle/dependency-locks/compile.lockfile
Normal file
@@ -0,0 +1,46 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.google.api-client:google-api-client:1.29.2
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.48
|
||||
com.google.appengine:appengine-testing:1.9.58
|
||||
com.google.auth:google-auth-library-credentials:0.16.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.16.1
|
||||
com.google.auto.value:auto-value-annotations:1.6.3
|
||||
com.google.auto.value:auto-value:1.6.3
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.dagger:dagger:2.21
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.flogger:flogger:0.1
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.http-client:google-http-client-jackson2:1.30.1
|
||||
com.google.http-client:google-http-client:1.30.1
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.29.2
|
||||
com.google.re2j:re2j:1.1
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
io.grpc:grpc-context:1.19.0
|
||||
io.netty:netty-buffer:4.1.31.Final
|
||||
io.netty:netty-codec-http:4.1.31.Final
|
||||
io.netty:netty-codec:4.1.31.Final
|
||||
io.netty:netty-common:4.1.31.Final
|
||||
io.netty:netty-handler:4.1.31.Final
|
||||
io.netty:netty-resolver:4.1.31.Final
|
||||
io.netty:netty-transport:4.1.31.Final
|
||||
io.opencensus:opencensus-api:0.21.0
|
||||
io.opencensus:opencensus-contrib-http-util:0.21.0
|
||||
javax.activation:activation:1.1
|
||||
javax.inject:javax.inject:1
|
||||
javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
org.apache.httpcomponents:httpcore:4.4.11
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
org.yaml:snakeyaml:1.17
|
||||
46
networking/gradle/dependency-locks/compileClasspath.lockfile
Normal file
46
networking/gradle/dependency-locks/compileClasspath.lockfile
Normal file
@@ -0,0 +1,46 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.google.api-client:google-api-client:1.29.2
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.48
|
||||
com.google.appengine:appengine-testing:1.9.58
|
||||
com.google.auth:google-auth-library-credentials:0.16.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.16.1
|
||||
com.google.auto.value:auto-value-annotations:1.6.3
|
||||
com.google.auto.value:auto-value:1.6.3
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.dagger:dagger:2.21
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.flogger:flogger:0.1
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.http-client:google-http-client-jackson2:1.30.1
|
||||
com.google.http-client:google-http-client:1.30.1
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.29.2
|
||||
com.google.re2j:re2j:1.1
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
io.grpc:grpc-context:1.19.0
|
||||
io.netty:netty-buffer:4.1.31.Final
|
||||
io.netty:netty-codec-http:4.1.31.Final
|
||||
io.netty:netty-codec:4.1.31.Final
|
||||
io.netty:netty-common:4.1.31.Final
|
||||
io.netty:netty-handler:4.1.31.Final
|
||||
io.netty:netty-resolver:4.1.31.Final
|
||||
io.netty:netty-transport:4.1.31.Final
|
||||
io.opencensus:opencensus-api:0.21.0
|
||||
io.opencensus:opencensus-contrib-http-util:0.21.0
|
||||
javax.activation:activation:1.1
|
||||
javax.inject:javax.inject:1
|
||||
javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
org.apache.httpcomponents:httpcore:4.4.11
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
org.yaml:snakeyaml:1.17
|
||||
3
networking/gradle/dependency-locks/compileOnly.lockfile
Normal file
3
networking/gradle/dependency-locks/compileOnly.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
48
networking/gradle/dependency-locks/default.lockfile
Normal file
48
networking/gradle/dependency-locks/default.lockfile
Normal file
@@ -0,0 +1,48 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.google.api-client:google-api-client:1.29.2
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.48
|
||||
com.google.appengine:appengine-testing:1.9.58
|
||||
com.google.auth:google-auth-library-credentials:0.16.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.16.1
|
||||
com.google.auto.value:auto-value-annotations:1.6.3
|
||||
com.google.auto.value:auto-value:1.6.3
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.dagger:dagger:2.21
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.flogger:flogger-system-backend:0.1
|
||||
com.google.flogger:flogger:0.1
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.http-client:google-http-client-jackson2:1.30.1
|
||||
com.google.http-client:google-http-client:1.30.1
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.29.2
|
||||
com.google.re2j:re2j:1.1
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
io.grpc:grpc-context:1.19.0
|
||||
io.netty:netty-buffer:4.1.31.Final
|
||||
io.netty:netty-codec-http:4.1.31.Final
|
||||
io.netty:netty-codec:4.1.31.Final
|
||||
io.netty:netty-common:4.1.31.Final
|
||||
io.netty:netty-handler:4.1.31.Final
|
||||
io.netty:netty-resolver:4.1.31.Final
|
||||
io.netty:netty-tcnative-boringssl-static:2.0.22.Final
|
||||
io.netty:netty-transport:4.1.31.Final
|
||||
io.opencensus:opencensus-api:0.21.0
|
||||
io.opencensus:opencensus-contrib-http-util:0.21.0
|
||||
javax.activation:activation:1.1
|
||||
javax.inject:javax.inject:1
|
||||
javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
org.apache.httpcomponents:httpcore:4.4.11
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
org.yaml:snakeyaml:1.17
|
||||
24
networking/gradle/dependency-locks/errorprone.lockfile
Normal file
24
networking/gradle/dependency-locks/errorprone.lockfile
Normal file
@@ -0,0 +1,24 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
@@ -0,0 +1,4 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.errorprone:javac:9+181-r4173-1
|
||||
4
networking/gradle/dependency-locks/jacocoAgent.lockfile
Normal file
4
networking/gradle/dependency-locks/jacocoAgent.lockfile
Normal file
@@ -0,0 +1,4 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
org.jacoco:org.jacoco.agent:0.8.5
|
||||
11
networking/gradle/dependency-locks/jacocoAnt.lockfile
Normal file
11
networking/gradle/dependency-locks/jacocoAnt.lockfile
Normal file
@@ -0,0 +1,11 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
org.jacoco:org.jacoco.agent:0.8.5
|
||||
org.jacoco:org.jacoco.ant:0.8.5
|
||||
org.jacoco:org.jacoco.core:0.8.5
|
||||
org.jacoco:org.jacoco.report:0.8.5
|
||||
org.ow2.asm:asm-analysis:7.2
|
||||
org.ow2.asm:asm-commons:7.2
|
||||
org.ow2.asm:asm-tree:7.2
|
||||
org.ow2.asm:asm:7.2
|
||||
48
networking/gradle/dependency-locks/runtime.lockfile
Normal file
48
networking/gradle/dependency-locks/runtime.lockfile
Normal file
@@ -0,0 +1,48 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.google.api-client:google-api-client:1.29.2
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.48
|
||||
com.google.appengine:appengine-testing:1.9.58
|
||||
com.google.auth:google-auth-library-credentials:0.16.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.16.1
|
||||
com.google.auto.value:auto-value-annotations:1.6.3
|
||||
com.google.auto.value:auto-value:1.6.3
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.dagger:dagger:2.21
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.flogger:flogger-system-backend:0.1
|
||||
com.google.flogger:flogger:0.1
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.http-client:google-http-client-jackson2:1.30.1
|
||||
com.google.http-client:google-http-client:1.30.1
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.29.2
|
||||
com.google.re2j:re2j:1.1
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
io.grpc:grpc-context:1.19.0
|
||||
io.netty:netty-buffer:4.1.31.Final
|
||||
io.netty:netty-codec-http:4.1.31.Final
|
||||
io.netty:netty-codec:4.1.31.Final
|
||||
io.netty:netty-common:4.1.31.Final
|
||||
io.netty:netty-handler:4.1.31.Final
|
||||
io.netty:netty-resolver:4.1.31.Final
|
||||
io.netty:netty-tcnative-boringssl-static:2.0.22.Final
|
||||
io.netty:netty-transport:4.1.31.Final
|
||||
io.opencensus:opencensus-api:0.21.0
|
||||
io.opencensus:opencensus-contrib-http-util:0.21.0
|
||||
javax.activation:activation:1.1
|
||||
javax.inject:javax.inject:1
|
||||
javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
org.apache.httpcomponents:httpcore:4.4.11
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
org.yaml:snakeyaml:1.17
|
||||
48
networking/gradle/dependency-locks/runtimeClasspath.lockfile
Normal file
48
networking/gradle/dependency-locks/runtimeClasspath.lockfile
Normal file
@@ -0,0 +1,48 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.google.api-client:google-api-client:1.29.2
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.48
|
||||
com.google.appengine:appengine-testing:1.9.58
|
||||
com.google.auth:google-auth-library-credentials:0.16.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.16.1
|
||||
com.google.auto.value:auto-value-annotations:1.6.3
|
||||
com.google.auto.value:auto-value:1.6.3
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.dagger:dagger:2.21
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.flogger:flogger-system-backend:0.1
|
||||
com.google.flogger:flogger:0.1
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.http-client:google-http-client-jackson2:1.30.1
|
||||
com.google.http-client:google-http-client:1.30.1
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.29.2
|
||||
com.google.re2j:re2j:1.1
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
io.grpc:grpc-context:1.19.0
|
||||
io.netty:netty-buffer:4.1.31.Final
|
||||
io.netty:netty-codec-http:4.1.31.Final
|
||||
io.netty:netty-codec:4.1.31.Final
|
||||
io.netty:netty-common:4.1.31.Final
|
||||
io.netty:netty-handler:4.1.31.Final
|
||||
io.netty:netty-resolver:4.1.31.Final
|
||||
io.netty:netty-tcnative-boringssl-static:2.0.22.Final
|
||||
io.netty:netty-transport:4.1.31.Final
|
||||
io.opencensus:opencensus-api:0.21.0
|
||||
io.opencensus:opencensus-contrib-http-util:0.21.0
|
||||
javax.activation:activation:1.1
|
||||
javax.inject:javax.inject:1
|
||||
javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
org.apache.httpcomponents:httpcore:4.4.11
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
org.yaml:snakeyaml:1.17
|
||||
@@ -0,0 +1,24 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
3
networking/gradle/dependency-locks/testApt.lockfile
Normal file
3
networking/gradle/dependency-locks/testApt.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user