mirror of
https://github.com/google/nomulus
synced 2026-06-09 16:33:02 +00:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bf29d159f9 | |||
| e17cb52bf7 | |||
| 7352f9b4a6 | |||
| 5da48184f9 | |||
| 5bd2ccd210 | |||
| 8fd5ab2bec | |||
| 30f6113b05 | |||
| bd48041961 | |||
| 39ceda628c | |||
| 0e9b75e5e9 | |||
| c1207464d8 | |||
| 62eab98921 | |||
| 633dd887f4 | |||
| 650f1fdd52 | |||
| b0f6a498fd | |||
| 77590dcd8e | |||
| 29e4d8de05 | |||
| 242a560f20 | |||
| 3903abd9de | |||
| 8371cb838c | |||
| 8dd6797614 | |||
| 730f108e13 | |||
| e5bafddd2f | |||
| 82f51accbd | |||
| 6536631857 | |||
| 1be92968bf | |||
| 0564b207f2 | |||
| 8afc4f4d3d |
@@ -4,3 +4,6 @@ python/
|
||||
.*/
|
||||
repos/**
|
||||
**/.idea/
|
||||
*.jar
|
||||
!third_party/**/*.jar
|
||||
!/gradle/wrapper/**/*.jar
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
| Internal Build | FOSS Build | License | Code Search |
|
||||
|----------------|------------|---------|-------------|
|
||||
|[](https://storage.googleapis.com/domain-registry-kokoro/index.html)|[](https://travis-ci.org/google/nomulus)|[](https://github.com/jianglai/nomulus/blob/master/LICENSE)|[](https://sourcegraph.com/github.com/google/nomulus)|
|
||||
|[](https://storage.googleapis.com/domain-registry-kokoro/index.html)|[](https://travis-ci.org/google/nomulus)|[](https://github.com/google/nomulus/blob/master/LICENSE)|[](https://sourcegraph.com/github.com/google/nomulus)|
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ if (project.path == ":services:default") {
|
||||
|
||||
appengine {
|
||||
deploy {
|
||||
project = gcpProject
|
||||
projectId = gcpProject
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +83,6 @@ dependencies {
|
||||
compile project(':core')
|
||||
}
|
||||
|
||||
rootProject.deploy.dependsOn appengineDeploy
|
||||
rootProject.deploy.dependsOn appengineDeployAll
|
||||
rootProject.stage.dependsOn appengineStage
|
||||
appengineDeploy.dependsOn rootProject.verifyDeployment
|
||||
|
||||
+68
-4
@@ -21,7 +21,7 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.google.cloud.tools:appengine-gradle-plugin:1.3.3'
|
||||
classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.0.1'
|
||||
classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.6.1"
|
||||
classpath 'org.sonatype.aether:aether-api:1.13.1'
|
||||
classpath 'org.sonatype.aether:aether-impl:1.13.1'
|
||||
@@ -46,6 +46,10 @@ plugins {
|
||||
id 'com.diffplug.gradle.spotless' version '3.18.0'
|
||||
}
|
||||
|
||||
wrapper {
|
||||
distributionType = Wrapper.DistributionType.ALL
|
||||
}
|
||||
|
||||
apply plugin: google.registry.gradle.plugin.ReportUploaderPlugin
|
||||
|
||||
reportUploader {
|
||||
@@ -71,6 +75,19 @@ reportUploader {
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
apply from: 'dependency_license.gradle'
|
||||
|
||||
// Custom task to run checkLicense in buildSrc, which is not triggered
|
||||
// by root project tasks. A shell task is used because buildSrc tasks
|
||||
// cannot be referenced in the same way as tasks from a regular included
|
||||
// build.
|
||||
task checkBuildSrcLicense(type:Exec) {
|
||||
workingDir "${rootDir}/buildSrc"
|
||||
commandLine '../gradlew', 'checkLicense'
|
||||
}
|
||||
tasks.checkLicense.dependsOn(tasks.checkBuildSrcLicense)
|
||||
tasks.build.dependsOn(tasks.checkLicense)
|
||||
|
||||
// Provide defaults for all of the project properties.
|
||||
|
||||
// showAllOutput: boolean. If true, dump all test output during the build.
|
||||
@@ -159,9 +176,10 @@ subprojects {
|
||||
resolutionStrategy.activateDependencyLocking()
|
||||
}
|
||||
}
|
||||
// Lock application dependencies.
|
||||
dependencyLocking {
|
||||
lockAllConfigurations()
|
||||
// Lock application dependencies except for the gradle-license-report
|
||||
// plugin. See dependency_license.gradle for more information.
|
||||
configurations.findAll { it.name != 'dependencyLicenseReport' }.each {
|
||||
it.resolutionStrategy.activateDependencyLocking()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,3 +255,49 @@ subprojects {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task checkDependenciesDotGradle {
|
||||
def buildSrcDepsFile = File.createTempFile('buildSrc', 'deps')
|
||||
buildSrcDepsFile.deleteOnExit()
|
||||
dependsOn createGetBuildSrcDirectDepsTask(buildSrcDepsFile)
|
||||
|
||||
doLast {
|
||||
Set<String> depsInUse = []
|
||||
allprojects {
|
||||
configurations.all {
|
||||
it.dependencies.findAll { it.group != null }.each {
|
||||
// Note: .toString() is required since GString should
|
||||
// not be mixed with Java Strings.
|
||||
depsInUse.add("${it.group}:${it.name}".toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
if (buildSrcDepsFile.exists()) {
|
||||
depsInUse.addAll(buildSrcDepsFile.readLines())
|
||||
}
|
||||
def unusedDeps =
|
||||
rootProject.dependencyMap.keySet()
|
||||
.findAll { !depsInUse.contains(it) }
|
||||
.toSorted()
|
||||
|
||||
if (unusedDeps.isEmpty()) {
|
||||
return
|
||||
}
|
||||
logger.error(
|
||||
"Unused dependencies in dependencies.gradle:\n${unusedDeps.toListString()}")
|
||||
throw new IllegalStateException(
|
||||
"The dependencies.gradle file should only contain direct dependencies.")
|
||||
}
|
||||
}
|
||||
tasks.build.dependsOn(tasks.checkDependenciesDotGradle)
|
||||
|
||||
def createGetBuildSrcDirectDepsTask(outputFileName) {
|
||||
return tasks
|
||||
.create(
|
||||
"getBuildSrcDeps_${java.util.UUID.randomUUID()}".toString(),
|
||||
Exec) {
|
||||
workingDir "${rootDir}/buildSrc"
|
||||
commandLine '../gradlew', 'exportDenpendencies',
|
||||
"-PdependencyExportFile=${outputFileName}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ repositories {
|
||||
}
|
||||
|
||||
apply from: '../dependencies.gradle'
|
||||
apply from: '../dependency_license.gradle'
|
||||
apply from: '../java_common.gradle'
|
||||
|
||||
sourceSets {
|
||||
@@ -88,3 +89,21 @@ gradle.projectsEvaluated {
|
||||
options.compilerArgs << "-Xlint:unchecked"
|
||||
}
|
||||
}
|
||||
|
||||
task exportDenpendencies {
|
||||
def outputFileProperty = 'dependencyExportFile'
|
||||
def output = project.hasProperty(outputFileProperty)
|
||||
? new PrintStream(
|
||||
new File(project.getProperty(outputFileProperty)))
|
||||
: System.out
|
||||
|
||||
doLast {
|
||||
project.configurations.all {
|
||||
it.dependencies.findAll {
|
||||
it.group != null
|
||||
}.each {
|
||||
output.println("${it.group}:${it.name}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
{
|
||||
"allowedLicenses": [
|
||||
{
|
||||
"moduleLicense": "Apache Software License, Version 1.1"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache 2"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache-2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache License 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache License v2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache License, Version 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache Software License - Version 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The Apache License, Version 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The Apache Software License, Version 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The Apache Software License, version 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Bouncy Castle Licence"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD 2-Clause License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD 2-Clause license"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD 3-clause"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD 3-Clause"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD 3-Clause License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The 3-Clause BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD New License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD New license"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD style"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "New BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Revised BSD"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "CC0 1.0 Universal License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "CDDL 1.1"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "CDDL + GPLv2 with classpath exception"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "https://glassfish.java.net/public/CDDL+GPL_1_1.html, https://glassfish.java.net/public/CDDL+GPL_1_1.html"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "CDDL+GPL License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "\\n Dual license consisting of the CDDL v1.1 and GPL v2\\n "
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License - Version 1.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License - v 1.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License 1.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Google App Engine Terms of Service"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU General Public License, version 2, with the Classpath Exception"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU GENERAL PUBLIC LICENSE, Version 2 + Classpath Exception"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GPL2 w/ CPE"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU Lesser Public License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The Go license"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GWT Terms"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "ICU License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The JSON License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "LGPL-2.1+"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "LGPL, version 2.1"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "MIT"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "MIT License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "MIT license"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The MIT License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The MIT license"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Mozilla Public License Version 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Public Domain"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "PUBLIC DOMAIN"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The W3C Software License"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"bundles" : [
|
||||
{
|
||||
"bundleName" : "Apache 2.0",
|
||||
"licenseName" : "Apache 2.0",
|
||||
"licenseUrl" : "http://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"bundleName" : "MIT License",
|
||||
"licenseName" : "MIT License",
|
||||
"licenseUrl" : "http://www.opensource.org/licenses/mit-license.php"
|
||||
}
|
||||
],
|
||||
"transformationRules" : [
|
||||
{
|
||||
"bundleName" : "Apache 2.0",
|
||||
"licenseUrlPattern" : "http://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"bundleName" : "Apache 2.0",
|
||||
"licenseUrlPattern" : "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"bundleName" : "MIT License",
|
||||
"licenseUrlPattern" : "http://www.opensource.org/licenses/mit-license.php"
|
||||
},
|
||||
{
|
||||
"bundleName" : "MIT License",
|
||||
"licenseUrlPattern" : "http://www.opensource.org/licenses/MIT"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -82,6 +82,11 @@ PRESUBMITS = {
|
||||
}, REQUIRED):
|
||||
"File did not include the license header.",
|
||||
|
||||
# Files must end in a newline
|
||||
PresubmitCheck(r".*\n$", ("java", "js", "soy", "sql", "py", "sh", "gradle"),
|
||||
{"node_modules/"}, REQUIRED):
|
||||
"Source files must end in a newline.",
|
||||
|
||||
# System.(out|err).println should only appear in tools/
|
||||
PresubmitCheck(
|
||||
r".*\bSystem\.(out|err)\.print", "java", {
|
||||
@@ -158,7 +163,6 @@ PRESUBMITS = {
|
||||
|
||||
|
||||
def get_files():
|
||||
result = []
|
||||
for root, dirnames, filenames in os.walk("."):
|
||||
for filename in filenames:
|
||||
yield os.path.join(root, filename)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
FROM gcr.io/distroless/java:debug
|
||||
ADD build/libs/nomulus.jar /nomulus.jar
|
||||
ENTRYPOINT ["/usr/bin/java", "-jar", "/nomulus.jar"]
|
||||
+15
-69
@@ -25,6 +25,7 @@ def screenshotsForGoldensDir = "${project.buildDir}/screenshots_for_goldens"
|
||||
def newGoldensDir = "${project.buildDir}/new_golden_images"
|
||||
def goldensDir =
|
||||
"${javaTestDir}/google/registry/webdriver/goldens/chrome-linux"
|
||||
def jsDir = "${project.projectDir}/src/main/javascript"
|
||||
|
||||
// Tests that conflict with (mostly unidentified) members of the main test
|
||||
// suite. It is unclear if they are offenders (i.e., those that pollute global
|
||||
@@ -96,14 +97,14 @@ sourceSets {
|
||||
}
|
||||
}
|
||||
|
||||
processTestResources {
|
||||
exclude '**/webdriver/*'
|
||||
}
|
||||
|
||||
configurations {
|
||||
css
|
||||
jaxb
|
||||
soy
|
||||
// Label for all dependencies inherited from Bazel build but not used in
|
||||
// either compile or testRuntime. However, they may be needed at runtime.
|
||||
// TODO(weiminyu): identify runtime dependencies and remove the rest.
|
||||
maybeRuntime
|
||||
closureCompiler
|
||||
|
||||
// Exclude non-canonical servlet-api jars. Our AppEngine deployment uses
|
||||
@@ -139,53 +140,38 @@ dependencies {
|
||||
"${rootDir}/third_party/objectify/v4_1/objectify-4.1.3.jar")
|
||||
testImplementation project(':third_party')
|
||||
|
||||
testRuntime files(sourceSets.test.resources.srcDirs)
|
||||
|
||||
compile deps['com.beust:jcommander']
|
||||
compile deps['com.google.api-client:google-api-client']
|
||||
maybeRuntime deps['com.google.api-client:google-api-client-appengine']
|
||||
maybeRuntime deps['com.google.api-client:google-api-client-jackson2']
|
||||
compile deps['com.google.monitoring-client:metrics']
|
||||
compile deps['com.google.monitoring-client:stackdriver']
|
||||
compile deps['com.google.api-client:google-api-client-java6']
|
||||
maybeRuntime deps['com.google.api-client:google-api-client-servlet']
|
||||
compile deps['com.google.apis:google-api-services-admin-directory']
|
||||
compile deps['com.google.apis:google-api-services-appengine']
|
||||
compile deps['com.google.apis:google-api-services-bigquery']
|
||||
maybeRuntime deps['com.google.apis:google-api-services-clouddebugger']
|
||||
compile deps['com.google.apis:google-api-services-cloudkms']
|
||||
maybeRuntime deps['com.google.apis:google-api-services-cloudresourcemanager']
|
||||
compile deps['com.google.apis:google-api-services-dataflow']
|
||||
compile deps['com.google.apis:google-api-services-dns']
|
||||
compile deps['com.google.apis:google-api-services-drive']
|
||||
compile deps['com.google.apis:google-api-services-groupssettings']
|
||||
compile deps['com.google.apis:google-api-services-monitoring']
|
||||
compile deps['com.google.apis:google-api-services-sheets']
|
||||
maybeRuntime deps['com.google.apis:google-api-services-storage']
|
||||
testCompileOnly deps['com.google.appengine:appengine-api-1.0-sdk']
|
||||
maybeRuntime deps['com.google.appengine:appengine-api-labs']
|
||||
maybeRuntime deps['com.google.appengine:appengine-api-stubs']
|
||||
testCompile deps['com.google.appengine:appengine-api-stubs']
|
||||
compile deps['com.google.appengine.tools:appengine-gcs-client']
|
||||
compile deps['com.google.appengine.tools:appengine-mapreduce']
|
||||
compile deps['com.google.appengine.tools:appengine-pipeline']
|
||||
compile deps['com.google.appengine:appengine-remote-api']
|
||||
maybeRuntime deps['com.google.appengine:appengine-tools-sdk']
|
||||
compile deps['com.google.auth:google-auth-library-credentials']
|
||||
compile deps['com.google.auth:google-auth-library-oauth2-http']
|
||||
maybeRuntime deps['com.google.auto:auto-common']
|
||||
maybeRuntime deps['com.google.auto.factory:auto-factory']
|
||||
compile deps['com.google.code.gson:gson']
|
||||
compile deps['com.google.auto.value:auto-value-annotations']
|
||||
maybeRuntime deps['com.google.cloud.bigdataoss:gcsio']
|
||||
maybeRuntime deps['com.google.cloud.bigdataoss:util']
|
||||
compile deps['com.google.code.findbugs:jsr305']
|
||||
compile deps['com.google.dagger:dagger']
|
||||
maybeRuntime deps['com.google.dagger:dagger-producers']
|
||||
compile deps['com.google.errorprone:error_prone_annotations']
|
||||
maybeRuntime deps['com.google.errorprone:javac-shaded']
|
||||
compile deps['com.google.flogger:flogger']
|
||||
runtime deps['com.google.flogger:flogger-system-backend']
|
||||
maybeRuntime deps['com.google.gdata:core']
|
||||
maybeRuntime deps['com.google.googlejavaformat:google-java-format']
|
||||
compile deps['com.google.guava:guava']
|
||||
gradleLint.ignore('unused-dependency') {
|
||||
compile deps['com.google.gwt:gwt-user']
|
||||
@@ -194,89 +180,48 @@ dependencies {
|
||||
compile deps['com.google.http-client:google-http-client-appengine']
|
||||
compile deps['com.google.http-client:google-http-client-jackson2']
|
||||
compile deps['com.google.oauth-client:google-oauth-client']
|
||||
maybeRuntime deps['com.google.oauth-client:google-oauth-client-appengine']
|
||||
compile deps['com.google.oauth-client:google-oauth-client-java6']
|
||||
compile deps['com.google.oauth-client:google-oauth-client-jetty']
|
||||
maybeRuntime deps['com.google.oauth-client:google-oauth-client-servlet']
|
||||
maybeRuntime deps['com.google.protobuf:protobuf-java']
|
||||
compile deps['com.google.re2j:re2j']
|
||||
compile deps['com.google.template:soy']
|
||||
maybeRuntime deps['com.googlecode.charts4j:charts4j']
|
||||
compile deps['com.googlecode.json-simple:json-simple']
|
||||
compile deps['com.jcraft:jsch']
|
||||
maybeRuntime deps['com.jcraft:jzlib']
|
||||
maybeRuntime deps['com.squareup:javapoet']
|
||||
maybeRuntime deps['com.squareup:javawriter']
|
||||
maybeRuntime deps['com.sun.activation:javax.activation']
|
||||
maybeRuntime deps['com.thoughtworks.paranamer:paranamer']
|
||||
testCompile deps['com.thoughtworks.qdox:qdox']
|
||||
maybeRuntime deps['commons-codec:commons-codec']
|
||||
maybeRuntime deps['commons-logging:commons-logging']
|
||||
compile deps['dnsjava:dnsjava']
|
||||
maybeRuntime deps['io.netty:netty-buffer']
|
||||
maybeRuntime deps['io.netty:netty-codec']
|
||||
maybeRuntime deps['io.netty:netty-codec-http']
|
||||
maybeRuntime deps['io.netty:netty-common']
|
||||
maybeRuntime deps['io.netty:netty-handler']
|
||||
maybeRuntime deps['io.netty:netty-resolver']
|
||||
maybeRuntime deps['io.netty:netty-tcnative']
|
||||
maybeRuntime deps['io.netty:netty-tcnative-boringssl-static']
|
||||
maybeRuntime deps['io.netty:netty-transport']
|
||||
maybeRuntime deps['it.unimi.dsi:fastutil']
|
||||
maybeRuntime deps['javax.annotation:jsr250-api']
|
||||
runtime deps['org.glassfish.jaxb:jaxb-runtime']
|
||||
testCompile deps['javax.annotation:jsr250-api']
|
||||
compile deps['javax.inject:javax.inject']
|
||||
compile deps['javax.mail:mail']
|
||||
compile deps['javax.servlet:servlet-api']
|
||||
compile deps['javax.xml.bind:jaxb-api']
|
||||
maybeRuntime deps['javax.xml.soap:javax.xml.soap-api']
|
||||
compile deps['jline:jline']
|
||||
compile deps['joda-time:joda-time']
|
||||
compile deps['org.apache.avro:avro']
|
||||
maybeRuntime deps['org.apache.beam:beam-runners-direct-java']
|
||||
testCompile deps['org.apache.beam:beam-runners-direct-java']
|
||||
compile deps['org.apache.beam:beam-runners-google-cloud-dataflow-java']
|
||||
maybeRuntime deps['org.apache.beam:beam-sdks-common-runner-api']
|
||||
compile deps['org.apache.beam:beam-sdks-java-core']
|
||||
compile deps['org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core']
|
||||
compile deps['org.apache.beam:beam-sdks-java-io-google-cloud-platform']
|
||||
maybeRuntime deps['org.apache.commons:commons-compress']
|
||||
testCompile deps['org.apache.commons:commons-text']
|
||||
maybeRuntime deps['org.apache.ftpserver:ftplet-api']
|
||||
testCompile deps['org.apache.ftpserver:ftplet-api']
|
||||
maybeRuntime deps['org.apache.ftpserver:ftpserver-core']
|
||||
testCompile deps['org.apache.ftpserver:ftpserver-core']
|
||||
compile deps['org.apache.httpcomponents:httpclient']
|
||||
compile deps['org.apache.httpcomponents:httpcore']
|
||||
maybeRuntime deps['org.apache.mina:mina-core']
|
||||
maybeRuntime deps['org.apache.sshd:sshd-core']
|
||||
testCompile deps['org.apache.sshd:sshd-core']
|
||||
maybeRuntime deps['org.apache.sshd:sshd-scp']
|
||||
testCompile deps['org.apache.sshd:sshd-scp']
|
||||
maybeRuntime deps['org.apache.sshd:sshd-sftp']
|
||||
testCompile deps['org.apache.sshd:sshd-sftp']
|
||||
maybeRuntime deps['org.apache.tomcat:tomcat-annotations-api']
|
||||
testCompile deps['org.apache.tomcat:tomcat-annotations-api']
|
||||
compile deps['org.bouncycastle:bcpg-jdk15on']
|
||||
testCompile deps['org.bouncycastle:bcpkix-jdk15on']
|
||||
compile deps['org.bouncycastle:bcprov-jdk15on']
|
||||
maybeRuntime deps['org.codehaus.jackson:jackson-core-asl']
|
||||
maybeRuntime deps['org.codehaus.jackson:jackson-mapper-asl']
|
||||
compile deps['org.joda:joda-money']
|
||||
compile deps['org.json:json']
|
||||
maybeRuntime deps['org.khronos:opengl-api']
|
||||
maybeRuntime deps['org.mortbay.jetty:jetty']
|
||||
testCompile deps['org.mortbay.jetty:jetty']
|
||||
maybeRuntime deps['org.mortbay.jetty:jetty-util']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-api']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-chrome-driver']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-java']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-remote-driver']
|
||||
maybeRuntime deps['org.slf4j:slf4j-api']
|
||||
testCompile deps['org.testcontainers:selenium']
|
||||
maybeRuntime deps['org.tukaani:xz']
|
||||
maybeRuntime deps['org.xerial.snappy:snappy-java']
|
||||
compile deps['xerces:xmlParserAPIs']
|
||||
compile deps['xpp3:xpp3']
|
||||
|
||||
@@ -480,7 +425,7 @@ task soyToJS {
|
||||
}
|
||||
|
||||
task stylesheetsToJavascript {
|
||||
def cssSourceDir = "${javaDir}/google/registry/ui/css"
|
||||
def cssSourceDir = "${jsDir}/google/registry/ui/css"
|
||||
def outputDir = "${resourcesDir}/google/registry/ui/css"
|
||||
inputs.dir cssSourceDir
|
||||
outputs.dir outputDir
|
||||
@@ -533,8 +478,8 @@ task compileProdJS(type: JavaExec) {
|
||||
def outputDir = "${resourcesDir}/google/registry/ui"
|
||||
def nodeModulesDir = "${rootDir}/node_modules"
|
||||
def cssSourceDir = "${resourcesDir}/google/registry/ui/css"
|
||||
def jsSourceDir = "${javaDir}/google/registry/ui/js"
|
||||
def externsDir = "${javaDir}/google/registry/ui/externs"
|
||||
def jsSourceDir = "${jsDir}/google/registry/ui/js"
|
||||
def externsDir = "${jsDir}/google/registry/ui/externs"
|
||||
def soySourceDir = "${generatedDir}/google/registry/ui/soy"
|
||||
|
||||
[nodeModulesDir, cssSourceDir, jsSourceDir, externsDir, soySourceDir].each {
|
||||
@@ -700,10 +645,11 @@ test {
|
||||
}.dependsOn(fragileTest, outcastTest)
|
||||
|
||||
createUberJar('nomulus', 'nomulus', 'google.registry.tools.RegistryTool')
|
||||
createUberJar('gtechTool', 'gtech_tool', 'google.registry.tools.GtechTool')
|
||||
project.nomulus.dependsOn project(':third_party').jar
|
||||
project.gtechTool.dependsOn project(':third_party').jar
|
||||
|
||||
project.build.dependsOn nomulus
|
||||
project.build.dependsOn gtechTool
|
||||
task buildToolImage(dependsOn: nomulus, type: Exec) {
|
||||
commandLine 'docker', 'build', '-t', 'nomulus-tool', '.'
|
||||
}
|
||||
|
||||
project.build.dependsOn buildToolImage
|
||||
project.build.dependsOn ':stage'
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.beam.invoicing;
|
||||
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import google.registry.beam.invoicing.BillingEvent.InvoiceGroupingKey;
|
||||
import google.registry.beam.invoicing.BillingEvent.InvoiceGroupingKey.InvoiceGroupingKeyCoder;
|
||||
import google.registry.config.CredentialModule.LocalCredential;
|
||||
@@ -57,35 +58,31 @@ import org.apache.beam.sdk.values.TypeDescriptors;
|
||||
*/
|
||||
public class InvoicingPipeline implements Serializable {
|
||||
|
||||
@Inject
|
||||
@Config("projectId")
|
||||
String projectId;
|
||||
private final String projectId;
|
||||
private final String beamBucketUrl;
|
||||
private final String invoiceTemplateUrl;
|
||||
private final String beamStagingUrl;
|
||||
private final String billingBucketUrl;
|
||||
private final String invoiceFilePrefix;
|
||||
private final GoogleCredentials googleCredentials;
|
||||
|
||||
@Inject
|
||||
@Config("apacheBeamBucketUrl")
|
||||
String beamBucketUrl;
|
||||
|
||||
@Inject
|
||||
@Config("invoiceTemplateUrl")
|
||||
String invoiceTemplateUrl;
|
||||
|
||||
@Inject
|
||||
@Config("beamStagingUrl")
|
||||
String beamStagingUrl;
|
||||
|
||||
@Inject
|
||||
@Config("billingBucketUrl")
|
||||
String billingBucketUrl;
|
||||
|
||||
@Inject
|
||||
@Config("invoiceFilePrefix")
|
||||
String invoiceFilePrefix;
|
||||
|
||||
@Inject @LocalCredential
|
||||
GoogleCredentialsBundle credentialsBundle;
|
||||
|
||||
@Inject
|
||||
InvoicingPipeline() {}
|
||||
public InvoicingPipeline(
|
||||
@Config("projectId") String projectId,
|
||||
@Config("apacheBeamBucketUrl") String beamBucketUrl,
|
||||
@Config("invoiceTemplateUrl") String invoiceTemplateUrl,
|
||||
@Config("beamStagingUrl") String beamStagingUrl,
|
||||
@Config("billingBucketUrl") String billingBucketUrl,
|
||||
@Config("invoiceFilePrefix") String invoiceFilePrefix,
|
||||
@LocalCredential GoogleCredentialsBundle googleCredentialsBundle) {
|
||||
this.projectId = projectId;
|
||||
this.beamBucketUrl = beamBucketUrl;
|
||||
this.invoiceTemplateUrl = invoiceTemplateUrl;
|
||||
this.beamStagingUrl = beamStagingUrl;
|
||||
this.billingBucketUrl = billingBucketUrl;
|
||||
this.invoiceFilePrefix = invoiceFilePrefix;
|
||||
this.googleCredentials = googleCredentialsBundle.getGoogleCredentials();
|
||||
}
|
||||
|
||||
/** Custom options for running the invoicing pipeline. */
|
||||
interface InvoicingPipelineOptions extends DataflowPipelineOptions {
|
||||
@@ -105,12 +102,15 @@ public class InvoicingPipeline implements Serializable {
|
||||
public void deploy() {
|
||||
// We can't store options as a member variable due to serialization concerns.
|
||||
InvoicingPipelineOptions options = PipelineOptionsFactory.as(InvoicingPipelineOptions.class);
|
||||
options.setGcpCredential(credentialsBundle.getGoogleCredentials());
|
||||
options.setProject(projectId);
|
||||
options.setRunner(DataflowRunner.class);
|
||||
// This causes p.run() to stage the pipeline as a template on GCS, as opposed to running it.
|
||||
options.setTemplateLocation(invoiceTemplateUrl);
|
||||
options.setStagingLocation(beamStagingUrl);
|
||||
// This credential is used when Dataflow deploys the template to GCS in target GCP project.
|
||||
// So, make sure the credential has write permission to GCS in that project.
|
||||
options.setGcpCredential(googleCredentials);
|
||||
|
||||
Pipeline p = Pipeline.create(options);
|
||||
|
||||
PCollection<BillingEvent> billingEvents =
|
||||
|
||||
@@ -17,9 +17,12 @@ package google.registry.beam.spec11;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.beam.BeamUtils.getQueryFromFile;
|
||||
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.auto.value.AutoValue;
|
||||
import google.registry.beam.spec11.SafeBrowsingTransforms.EvaluateSafeBrowsingFn;
|
||||
import google.registry.config.CredentialModule.LocalCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import google.registry.util.Retrier;
|
||||
import google.registry.util.SqlTemplate;
|
||||
import java.io.Serializable;
|
||||
@@ -77,26 +80,29 @@ public class Spec11Pipeline implements Serializable {
|
||||
/** The JSON object field we put the threat match array for Spec11 reports. */
|
||||
public static final String THREAT_MATCHES_FIELD = "threatMatches";
|
||||
|
||||
@Inject
|
||||
@Config("projectId")
|
||||
String projectId;
|
||||
private final String projectId;
|
||||
private final String beamStagingUrl;
|
||||
private final String spec11TemplateUrl;
|
||||
private final String reportingBucketUrl;
|
||||
private final GoogleCredentials googleCredentials;
|
||||
private final Retrier retrier;
|
||||
|
||||
@Inject
|
||||
@Config("beamStagingUrl")
|
||||
String beamStagingUrl;
|
||||
|
||||
@Inject
|
||||
@Config("spec11TemplateUrl")
|
||||
String spec11TemplateUrl;
|
||||
|
||||
@Inject
|
||||
@Config("reportingBucketUrl")
|
||||
String reportingBucketUrl;
|
||||
|
||||
@Inject Retrier retrier;
|
||||
|
||||
@Inject
|
||||
Spec11Pipeline() {}
|
||||
public Spec11Pipeline(
|
||||
@Config("projectId") String projectId,
|
||||
@Config("beamStagingUrl") String beamStagingUrl,
|
||||
@Config("spec11TemplateUrl") String spec11TemplateUrl,
|
||||
@Config("reportingBucketUrl") String reportingBucketUrl,
|
||||
@LocalCredential GoogleCredentialsBundle googleCredentialsBundle,
|
||||
Retrier retrier
|
||||
) {
|
||||
this.projectId = projectId;
|
||||
this.beamStagingUrl = beamStagingUrl;
|
||||
this.spec11TemplateUrl = spec11TemplateUrl;
|
||||
this.reportingBucketUrl = reportingBucketUrl;
|
||||
this.googleCredentials = googleCredentialsBundle.getGoogleCredentials();
|
||||
this.retrier = retrier;
|
||||
}
|
||||
|
||||
/** Custom options for running the spec11 pipeline. */
|
||||
interface Spec11PipelineOptions extends DataflowPipelineOptions {
|
||||
@@ -134,6 +140,9 @@ public class Spec11Pipeline implements Serializable {
|
||||
// This causes p.run() to stage the pipeline as a template on GCS, as opposed to running it.
|
||||
options.setTemplateLocation(spec11TemplateUrl);
|
||||
options.setStagingLocation(beamStagingUrl);
|
||||
// This credential is used when Dataflow deploys the template to GCS in target GCP project.
|
||||
// So, make sure the credential has write permission to GCS in that project.
|
||||
options.setGcpCredential(googleCredentials);
|
||||
|
||||
Pipeline p = Pipeline.create(options);
|
||||
PCollection<Subdomain> domains =
|
||||
|
||||
@@ -112,8 +112,6 @@
|
||||
<target>backend</target>
|
||||
</cron>
|
||||
|
||||
<!--
|
||||
TODO(b/134576418) enable this cron job once we're sure the Action works
|
||||
<cron>
|
||||
<url><![CDATA[/_dr/task/updateRegistrarRdapBaseUrls]]></url>
|
||||
<description>
|
||||
@@ -122,7 +120,6 @@
|
||||
<schedule>every day 02:34</schedule>
|
||||
<target>backend</target>
|
||||
</cron>
|
||||
-->
|
||||
|
||||
<cron>
|
||||
<url><![CDATA[/_dr/task/deleteOldCommitLogs]]></url>
|
||||
|
||||
@@ -39,6 +39,13 @@ public class EppMetrics {
|
||||
LabelDescriptor.create("tld", "The TLD acted on by the command (if applicable)."),
|
||||
LabelDescriptor.create("status", "The return status of the command."));
|
||||
|
||||
private static final ImmutableSet<LabelDescriptor> LABEL_DESCRIPTORS =
|
||||
ImmutableSet.of(
|
||||
LabelDescriptor.create("command", "The name of the command."),
|
||||
LabelDescriptor.create("traffic_type",
|
||||
"The traffic type of the command; one of CANARY, PROBER, or REAL."),
|
||||
LabelDescriptor.create("status", "The return status of the command."));
|
||||
|
||||
private static final IncrementableMetric eppRequestsByRegistrar =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newIncrementableMetric(
|
||||
@@ -73,6 +80,19 @@ public class EppMetrics {
|
||||
LABEL_DESCRIPTORS_BY_TLD,
|
||||
DEFAULT_FITTER);
|
||||
|
||||
private static final EventMetric requestTime =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newEventMetric(
|
||||
"/epp/request_time",
|
||||
"EPP Request Time",
|
||||
"milliseconds",
|
||||
LABEL_DESCRIPTORS,
|
||||
DEFAULT_FITTER);
|
||||
|
||||
private enum TrafficType {
|
||||
CANARY, PROBER, REAL
|
||||
}
|
||||
|
||||
@Inject
|
||||
public EppMetrics() {}
|
||||
|
||||
@@ -97,15 +117,21 @@ public class EppMetrics {
|
||||
metric.getStatus().isPresent() ? String.valueOf(metric.getStatus().get().code) : "";
|
||||
long processingTime =
|
||||
metric.getEndTimestamp().getMillis() - metric.getStartTimestamp().getMillis();
|
||||
processingTimeByRegistrar.record(
|
||||
processingTime,
|
||||
metric.getCommandName().orElse(""),
|
||||
metric.getClientId().orElse(""),
|
||||
eppStatusCode);
|
||||
processingTimeByTld.record(
|
||||
processingTime,
|
||||
metric.getCommandName().orElse(""),
|
||||
metric.getTld().orElse(""),
|
||||
eppStatusCode);
|
||||
String commandName = metric.getCommandName().orElse("");
|
||||
processingTimeByRegistrar
|
||||
.record(processingTime, commandName, metric.getClientId().orElse(""), eppStatusCode);
|
||||
String tld = metric.getTld().orElse("");
|
||||
processingTimeByTld.record(processingTime, commandName, tld, eppStatusCode);
|
||||
requestTime.record(processingTime, commandName, getTrafficType(tld).toString(), eppStatusCode);
|
||||
}
|
||||
|
||||
private static TrafficType getTrafficType(String tld) {
|
||||
if (tld.endsWith("canary.test")) {
|
||||
return TrafficType.CANARY;
|
||||
} else if (tld.endsWith(".test")) {
|
||||
return TrafficType.PROBER;
|
||||
} else {
|
||||
return TrafficType.REAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import static google.registry.util.CollectionUtils.forceEmptyToNull;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
import static google.registry.util.CollectionUtils.union;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.earliestOf;
|
||||
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
|
||||
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
|
||||
@@ -376,10 +377,10 @@ public class DomainBase extends EppResource
|
||||
|
||||
Optional<DateTime> newLastEppUpdateTime = Optional.empty();
|
||||
|
||||
// There is no transfer. Do any necessary autorenews.
|
||||
// There is no transfer. Do any necessary autorenews for active domains.
|
||||
|
||||
Builder builder = asBuilder();
|
||||
if (isBeforeOrAt(registrationExpirationTime, now)) {
|
||||
if (isBeforeOrAt(registrationExpirationTime, now) && END_OF_TIME.equals(getDeletionTime())) {
|
||||
// Autorenew by the number of years between the old expiration time and now.
|
||||
DateTime lastAutorenewTime = leapSafeAddYears(
|
||||
registrationExpirationTime,
|
||||
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
package google.registry.model.domain.fee;
|
||||
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName;
|
||||
import java.util.Locale;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlValue;
|
||||
|
||||
@@ -47,7 +47,7 @@ public class FeeExtensionCommandDescriptor extends ImmutableObject {
|
||||
|
||||
public CommandName getCommand() {
|
||||
// Require the xml string to be lowercase.
|
||||
if (command != null && CharMatcher.javaLowerCase().matchesAllOf(command)) {
|
||||
if (command != null && command.toLowerCase(Locale.ENGLISH).equals(command)) {
|
||||
try {
|
||||
return CommandName.valueOf(Ascii.toUpperCase(command));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
package google.registry.model.domain.fee12;
|
||||
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.domain.fee.FeeCheckCommandExtensionItem;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
@@ -83,7 +83,7 @@ public class FeeCheckCommandExtensionItemV12 extends FeeCheckCommandExtensionIte
|
||||
@Override
|
||||
public CommandName getCommandName() {
|
||||
// Require the xml string to be lowercase.
|
||||
if (commandName != null && CharMatcher.javaLowerCase().matchesAllOf(commandName)) {
|
||||
if (commandName != null && commandName.toLowerCase(Locale.ENGLISH).equals(commandName)) {
|
||||
try {
|
||||
return CommandName.valueOf(Ascii.toUpperCase(commandName));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
@@ -868,7 +868,9 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDriveFolderId(String driveFolderId) {
|
||||
public Builder setDriveFolderId(@Nullable String driveFolderId) {
|
||||
checkArgument(driveFolderId == null || !driveFolderId.contains("/"),
|
||||
"Drive folder ID must not be a full URL");
|
||||
getInstance().driveFolderId = driveFolderId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.rdap;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
@@ -23,6 +24,7 @@ import com.google.api.client.http.HttpRequest;
|
||||
import com.google.api.client.http.HttpRequestFactory;
|
||||
import com.google.api.client.http.HttpResponse;
|
||||
import com.google.api.client.http.HttpTransport;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
@@ -34,8 +36,9 @@ import com.google.gson.JsonObject;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.keyring.api.KeyModule;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registry.Registries;
|
||||
import google.registry.model.registry.Registry.TldType;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.auth.Auth;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -56,8 +59,6 @@ import javax.inject.Inject;
|
||||
* <p>It is a "login/query/logout" system where you login using the ICANN Reporting credentials, get
|
||||
* a cookie you then send to get the list and finally logout.
|
||||
*
|
||||
* <p>The username is [TLD]_ry. It could be any "real" TLD.
|
||||
*
|
||||
* <p>For clarity, this is how one would contact this endpoint "manually", from a whitelisted IP
|
||||
* server:
|
||||
*
|
||||
@@ -88,18 +89,10 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
@Inject HttpTransport httpTransport;
|
||||
@Inject @KeyModule.Key("icannReportingPassword") String password;
|
||||
|
||||
/**
|
||||
* The TLD for which we make the request.
|
||||
*
|
||||
* <p>The actual value doesn't matter, as long as it's a TLD that has access to the ICANN
|
||||
* Reporter. It's just used to login.
|
||||
*/
|
||||
@Inject @Parameter("tld") String tld;
|
||||
|
||||
@Inject
|
||||
UpdateRegistrarRdapBaseUrlsAction() {}
|
||||
|
||||
private String loginAndGetId(HttpRequestFactory requestFactory) {
|
||||
private String loginAndGetId(HttpRequestFactory requestFactory, String tld) {
|
||||
try {
|
||||
logger.atInfo().log("Logging in to MoSAPI");
|
||||
HttpRequest request =
|
||||
@@ -122,7 +115,7 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private void logout(HttpRequestFactory requestFactory, String id) {
|
||||
private void logout(HttpRequestFactory requestFactory, String id, String tld) {
|
||||
try {
|
||||
HttpRequest request =
|
||||
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGOUT_URL, tld)));
|
||||
@@ -135,9 +128,9 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaId() {
|
||||
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaIdWithTld(String tld) {
|
||||
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
|
||||
String id = loginAndGetId(requestFactory);
|
||||
String id = loginAndGetId(requestFactory, tld);
|
||||
String content;
|
||||
try {
|
||||
HttpRequest request =
|
||||
@@ -152,7 +145,7 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
throw new UncheckedIOException(
|
||||
"Error reading RDAP list from MoSAPI server: " + e.getMessage(), e);
|
||||
} finally {
|
||||
logout(requestFactory, id);
|
||||
logout(requestFactory, id, tld);
|
||||
}
|
||||
|
||||
logger.atInfo().log("list reply: '%s'", content);
|
||||
@@ -173,6 +166,25 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaId() {
|
||||
// All TLDs have the same data, so just keep trying until one works
|
||||
// (the expectation is that all / any should work)
|
||||
ImmutableList<String> tlds = ImmutableList.sortedCopyOf(Registries.getTldsOfType(TldType.REAL));
|
||||
checkArgument(!tlds.isEmpty(), "There must exist at least one REAL TLD.");
|
||||
Throwable finalThrowable = null;
|
||||
for (String tld : tlds) {
|
||||
try {
|
||||
return getRdapBaseUrlsPerIanaIdWithTld(tld);
|
||||
} catch (Throwable throwable) {
|
||||
logger.atWarning().log(String
|
||||
.format("Error retrieving RDAP urls with TLD %s: %s", tld, throwable.getMessage()));
|
||||
finalThrowable = throwable;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException(
|
||||
String.format("Error contacting MosAPI server. Tried TLDs %s", tlds), finalThrowable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
ImmutableSetMultimap<String, String> ianaToBaseUrls = getRdapBaseUrlsPerIanaId();
|
||||
|
||||
@@ -22,6 +22,7 @@ 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.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.io.ByteStreams;
|
||||
@@ -38,6 +39,7 @@ import google.registry.util.Retrier;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Copy all registrar detail reports in a given bucket's subdirectory from GCS to Drive. */
|
||||
@@ -95,6 +97,8 @@ public final class CopyDetailReportsAction implements Runnable {
|
||||
response.setPayload(String.format("Failure, encountered %s", e.getMessage()));
|
||||
return;
|
||||
}
|
||||
ImmutableMap.Builder<String, Throwable> copyErrorsBuilder =
|
||||
new ImmutableMap.Builder<String, Throwable>();
|
||||
for (String detailReportName : detailReportObjectNames) {
|
||||
// The standard report format is "invoice_details_yyyy-MM_registrarId_tld.csv
|
||||
// TODO(larryruili): Determine a safer way of enforcing this.
|
||||
@@ -117,7 +121,7 @@ public final class CopyDetailReportsAction implements Runnable {
|
||||
try (InputStream input =
|
||||
gcsUtils.openInputStream(
|
||||
new GcsFilename(billingBucket, invoiceDirectoryPrefix + detailReportName))) {
|
||||
driveConnection.createFile(
|
||||
driveConnection.createOrUpdateFile(
|
||||
detailReportName,
|
||||
MediaType.CSV_UTF_8,
|
||||
driveFolderId,
|
||||
@@ -129,15 +133,31 @@ public final class CopyDetailReportsAction implements Runnable {
|
||||
},
|
||||
IOException.class);
|
||||
} catch (Throwable e) {
|
||||
emailUtils.sendAlertEmail(
|
||||
String alertMessage =
|
||||
String.format(
|
||||
"Warning: CopyDetailReportsAction failed.\nEncountered: %s on file: %s",
|
||||
getRootCause(e).getMessage(), detailReportName));
|
||||
throw e;
|
||||
"Warning: CopyDetailReportsAction failed for registrar %s.\n"
|
||||
+ "Encountered: %s on file: %s",
|
||||
registrarId, getRootCause(e).getMessage(), detailReportName);
|
||||
copyErrorsBuilder.put(registrarId, e);
|
||||
logger.atSevere().withCause(e).log(alertMessage);
|
||||
}
|
||||
}
|
||||
response.setStatus(SC_OK);
|
||||
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
|
||||
response.setPayload("Copied detail reports.");
|
||||
StringBuilder payload = new StringBuilder().append("Copied detail reports.\n");
|
||||
ImmutableMap<String, Throwable> copyErrors = copyErrorsBuilder.build();
|
||||
if (!copyErrors.isEmpty()) {
|
||||
payload.append("The following errors were encountered:\n");
|
||||
payload.append(
|
||||
copyErrors.entrySet().stream()
|
||||
.map(
|
||||
entrySet ->
|
||||
String.format(
|
||||
"Registrar: %s\nError: %s\n",
|
||||
entrySet.getKey(), entrySet.getValue().getMessage()))
|
||||
.collect(Collectors.joining()));
|
||||
}
|
||||
response.setPayload(payload.toString());
|
||||
emailUtils.sendAlertEmail(payload.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,10 @@ public class DriveConnection {
|
||||
/**
|
||||
* Creates a file with the given parent.
|
||||
*
|
||||
* <p>If a file with the same path already exists, a duplicate is created. If overwriting the
|
||||
* existing file is the desired behavior, use {@link #createOrUpdateFile(String, MediaType,
|
||||
* String, byte[])} instead.
|
||||
*
|
||||
* @returns the file id.
|
||||
*/
|
||||
public String createFile(String title, MediaType mimeType, String parentFolderId, byte[] bytes)
|
||||
|
||||
@@ -100,7 +100,7 @@ public class AuthModule {
|
||||
AbstractDataStoreFactory dataStoreFactory) {
|
||||
try {
|
||||
return new GoogleAuthorizationCodeFlow.Builder(
|
||||
new NetHttpTransport(), jsonFactory, clientSecrets, requiredOauthScopes)
|
||||
new NetHttpTransport(), jsonFactory, clientSecrets, requiredOauthScopes)
|
||||
.setDataStoreFactory(dataStoreFactory)
|
||||
.build();
|
||||
} catch (IOException ex) {
|
||||
|
||||
@@ -237,7 +237,7 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand {
|
||||
@Nullable
|
||||
@Parameter(
|
||||
names = "--drive_folder_id",
|
||||
description = "Id of this registrar's folder in Drive",
|
||||
description = "Id (not full URL) of this registrar's folder in Drive",
|
||||
converter = OptionalStringParameter.class,
|
||||
validateWith = OptionalStringParameter.class)
|
||||
Optional<String> driveFolderId;
|
||||
|
||||
@@ -19,7 +19,6 @@ import static google.registry.util.CollectionUtils.findDuplicates;
|
||||
import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -255,7 +254,7 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
|
||||
tld,
|
||||
canonicalizeDomainName(tld));
|
||||
checkArgument(
|
||||
!CharMatcher.javaDigit().matches(tld.charAt(0)),
|
||||
!Character.isDigit(tld.charAt(0)),
|
||||
"TLDs cannot begin with a number");
|
||||
Registry oldRegistry = getOldRegistry(tld);
|
||||
// TODO(b/26901539): Add a flag to set the pricing engine once we have more than one option.
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
# -*-protobuf-*-
|
||||
|
||||
requirement: {
|
||||
type: BANNED_PROPERTY_WRITE
|
||||
error_message: 'Assignment to Element.prototype.innerHTML is not allowed. '
|
||||
'Use goog.dom.safe.setInnerHtml instead. '
|
||||
value: 'Element.prototype.innerHTML'
|
||||
}
|
||||
@@ -240,12 +240,12 @@
|
||||
{param required: true /}
|
||||
{/call}
|
||||
{call registry.soy.forms.inputFieldRowWithValue}
|
||||
{param label: 'DRIVE ID' /}
|
||||
{param label: 'Drive ID' /}
|
||||
{param name: 'driveId' /}
|
||||
{param value: $driveId /}
|
||||
{param placeholder: 'required' /}
|
||||
{param description kind="text"}
|
||||
Id of this registrar's folder in Drive.
|
||||
ID (not full URL) of this registrar's folder in Google Drive.
|
||||
{/param}
|
||||
{param required: true /}
|
||||
{/call}
|
||||
|
||||
@@ -16,8 +16,10 @@ package google.registry.beam.invoicing;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import google.registry.util.ResourceUtils;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -58,15 +60,17 @@ public class InvoicingPipelineTest {
|
||||
|
||||
@Before
|
||||
public void initializePipeline() throws IOException {
|
||||
invoicingPipeline = new InvoicingPipeline();
|
||||
invoicingPipeline.projectId = "test-project";
|
||||
File beamTempFolder = tempFolder.newFolder();
|
||||
invoicingPipeline.beamBucketUrl = beamTempFolder.getAbsolutePath();
|
||||
invoicingPipeline.invoiceFilePrefix = "REG-INV";
|
||||
invoicingPipeline.beamStagingUrl = beamTempFolder.getAbsolutePath() + "/staging";
|
||||
invoicingPipeline.invoiceTemplateUrl =
|
||||
beamTempFolder.getAbsolutePath() + "/templates/invoicing";
|
||||
invoicingPipeline.billingBucketUrl = tempFolder.getRoot().getAbsolutePath();
|
||||
String beamTempFolderPath = beamTempFolder.getAbsolutePath();
|
||||
invoicingPipeline = new InvoicingPipeline(
|
||||
"test-project",
|
||||
beamTempFolderPath,
|
||||
beamTempFolderPath + "/templates/invoicing",
|
||||
beamTempFolderPath + "/staging",
|
||||
tempFolder.getRoot().getAbsolutePath(),
|
||||
"REG-INV",
|
||||
GoogleCredentialsBundle.create(GoogleCredentials.create(null))
|
||||
);
|
||||
}
|
||||
|
||||
private ImmutableList<BillingEvent> getInputEvents() {
|
||||
|
||||
@@ -21,11 +21,13 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.withSettings;
|
||||
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.io.CharStreams;
|
||||
import google.registry.beam.spec11.SafeBrowsingTransforms.EvaluateSafeBrowsingFn;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeSleeper;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import google.registry.util.ResourceUtils;
|
||||
import google.registry.util.Retrier;
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -50,6 +52,7 @@ import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.BasicHttpEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
import org.joda.time.DateTime;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@@ -78,16 +81,21 @@ public class Spec11PipelineTest {
|
||||
@Rule public final transient TestPipeline p = TestPipeline.fromOptions(pipelineOptions);
|
||||
@Rule public final TemporaryFolder tempFolder = new TemporaryFolder();
|
||||
|
||||
private final Retrier retrier = new Retrier(
|
||||
new FakeSleeper(new FakeClock(DateTime.parse("2019-07-15TZ"))), 1);
|
||||
private Spec11Pipeline spec11Pipeline;
|
||||
|
||||
@Before
|
||||
public void initializePipeline() throws IOException {
|
||||
spec11Pipeline = new Spec11Pipeline();
|
||||
spec11Pipeline.projectId = "test-project";
|
||||
spec11Pipeline.reportingBucketUrl = tempFolder.getRoot().getAbsolutePath();
|
||||
File beamTempFolder = tempFolder.newFolder();
|
||||
spec11Pipeline.beamStagingUrl = beamTempFolder.getAbsolutePath() + "/staging";
|
||||
spec11Pipeline.spec11TemplateUrl = beamTempFolder.getAbsolutePath() + "/templates/invoicing";
|
||||
spec11Pipeline = new Spec11Pipeline(
|
||||
"test-project",
|
||||
beamTempFolder.getAbsolutePath() + "/staging",
|
||||
beamTempFolder.getAbsolutePath() + "/templates/invoicing",
|
||||
tempFolder.getRoot().getAbsolutePath(),
|
||||
GoogleCredentialsBundle.create(GoogleCredentials.create(null)),
|
||||
retrier
|
||||
);
|
||||
}
|
||||
|
||||
private static final ImmutableList<String> BAD_DOMAINS =
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
hello
|
||||
@@ -1 +0,0 @@
|
||||
OMG IM AN OVERRIDE
|
||||
@@ -1 +0,0 @@
|
||||
world
|
||||
@@ -33,6 +33,7 @@ import static org.joda.money.CurrencyUnit.USD;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.truth.Truth;
|
||||
import com.google.re2j.Matcher;
|
||||
import com.google.re2j.Pattern;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
@@ -197,6 +198,11 @@ public class EppLifecycleDomainTest extends EppTestCase {
|
||||
makeRecurringCreateBillingEvent(domain, createTime.plusYears(2), deleteTime));
|
||||
|
||||
assertThatLogoutSucceeds();
|
||||
|
||||
// Make sure that in the future, the domain expiration is unchanged after deletion
|
||||
DomainBase clonedDomain = domain.cloneProjectedAtTime(deleteTime.plusYears(5));
|
||||
Truth.assertThat(clonedDomain.getRegistrationExpirationTime())
|
||||
.isEqualTo(createTime.plusYears(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -28,6 +28,7 @@ import static google.registry.testing.DomainBaseSubject.assertAboutDomains;
|
||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static org.joda.money.CurrencyUnit.USD;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -61,34 +62,40 @@ import org.junit.Test;
|
||||
/** Unit tests for {@link DomainBase}. */
|
||||
public class DomainBaseTest extends EntityTestCase {
|
||||
|
||||
DomainBase domain;
|
||||
private DomainBase domain;
|
||||
private Key<BillingEvent.OneTime> oneTimeBillKey;
|
||||
private Key<BillingEvent.Recurring> recurringBillKey;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
createTld("com");
|
||||
Key<DomainBase> domainKey = Key.create(null, DomainBase.class, "4-COM");
|
||||
Key<HostResource> hostKey = Key.create(persistResource(
|
||||
new HostResource.Builder()
|
||||
.setFullyQualifiedHostName("ns1.example.com")
|
||||
.setSuperordinateDomain(domainKey)
|
||||
.setRepoId("1-COM")
|
||||
.build()));
|
||||
Key<ContactResource> contact1Key = Key.create(persistResource(
|
||||
new ContactResource.Builder()
|
||||
.setContactId("contact_id1")
|
||||
.setRepoId("2-COM")
|
||||
.build()));
|
||||
Key<ContactResource> contact2Key = Key.create(persistResource(
|
||||
new ContactResource.Builder()
|
||||
.setContactId("contact_id2")
|
||||
.setRepoId("3-COM")
|
||||
.build()));
|
||||
Key<HostResource> hostKey =
|
||||
Key.create(
|
||||
persistResource(
|
||||
new HostResource.Builder()
|
||||
.setFullyQualifiedHostName("ns1.example.com")
|
||||
.setSuperordinateDomain(domainKey)
|
||||
.setRepoId("1-COM")
|
||||
.build()));
|
||||
Key<ContactResource> contact1Key =
|
||||
Key.create(
|
||||
persistResource(
|
||||
new ContactResource.Builder()
|
||||
.setContactId("contact_id1")
|
||||
.setRepoId("2-COM")
|
||||
.build()));
|
||||
Key<ContactResource> contact2Key =
|
||||
Key.create(
|
||||
persistResource(
|
||||
new ContactResource.Builder()
|
||||
.setContactId("contact_id2")
|
||||
.setRepoId("3-COM")
|
||||
.build()));
|
||||
Key<HistoryEntry> historyEntryKey =
|
||||
Key.create(persistResource(new HistoryEntry.Builder().setParent(domainKey).build()));
|
||||
Key<BillingEvent.OneTime> oneTimeBillKey =
|
||||
Key.create(historyEntryKey, BillingEvent.OneTime.class, 1);
|
||||
Key<BillingEvent.Recurring> recurringBillKey =
|
||||
Key.create(historyEntryKey, BillingEvent.Recurring.class, 2);
|
||||
oneTimeBillKey = Key.create(historyEntryKey, BillingEvent.OneTime.class, 1);
|
||||
recurringBillKey = Key.create(historyEntryKey, BillingEvent.Recurring.class, 2);
|
||||
Key<PollMessage.Autorenew> autorenewPollKey =
|
||||
Key.create(historyEntryKey, PollMessage.Autorenew.class, 3);
|
||||
Key<PollMessage.OneTime> onetimePollKey =
|
||||
@@ -168,21 +175,27 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
|
||||
@Test
|
||||
public void testEmptyStringsBecomeNull() {
|
||||
assertThat(newDomainBase("example.com").asBuilder()
|
||||
.setPersistedCurrentSponsorClientId(null)
|
||||
.build()
|
||||
.getCurrentSponsorClientId())
|
||||
.isNull();
|
||||
assertThat(newDomainBase("example.com").asBuilder()
|
||||
.setPersistedCurrentSponsorClientId("")
|
||||
.build()
|
||||
assertThat(
|
||||
newDomainBase("example.com")
|
||||
.asBuilder()
|
||||
.setPersistedCurrentSponsorClientId(null)
|
||||
.build()
|
||||
.getCurrentSponsorClientId())
|
||||
.isNull();
|
||||
assertThat(newDomainBase("example.com").asBuilder()
|
||||
.setPersistedCurrentSponsorClientId(" ")
|
||||
.build()
|
||||
.getCurrentSponsorClientId())
|
||||
.isNotNull();
|
||||
.isNull();
|
||||
assertThat(
|
||||
newDomainBase("example.com")
|
||||
.asBuilder()
|
||||
.setPersistedCurrentSponsorClientId("")
|
||||
.build()
|
||||
.getCurrentSponsorClientId())
|
||||
.isNull();
|
||||
assertThat(
|
||||
newDomainBase("example.com")
|
||||
.asBuilder()
|
||||
.setPersistedCurrentSponsorClientId(" ")
|
||||
.build()
|
||||
.getCurrentSponsorClientId())
|
||||
.isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -201,29 +214,49 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
.build()
|
||||
.nsHosts)
|
||||
.isNull();
|
||||
assertThat(newDomainBase("example.com").asBuilder()
|
||||
.setNameservers(ImmutableSet.of(Key.create(newHostResource("foo.example.tld"))))
|
||||
.build().nsHosts)
|
||||
.isNotNull();
|
||||
assertThat(
|
||||
newDomainBase("example.com")
|
||||
.asBuilder()
|
||||
.setNameservers(ImmutableSet.of(Key.create(newHostResource("foo.example.tld"))))
|
||||
.build()
|
||||
.nsHosts)
|
||||
.isNotNull();
|
||||
// This behavior should also hold true for ImmutableObjects nested in collections.
|
||||
assertThat(newDomainBase("example.com").asBuilder()
|
||||
.setDsData(ImmutableSet.of(DelegationSignerData.create(1, 1, 1, (byte[]) null)))
|
||||
.build().getDsData().asList().get(0).getDigest())
|
||||
.isNull();
|
||||
assertThat(newDomainBase("example.com").asBuilder()
|
||||
.setDsData(ImmutableSet.of(DelegationSignerData.create(1, 1, 1, new byte[]{})))
|
||||
.build().getDsData().asList().get(0).getDigest())
|
||||
.isNull();
|
||||
assertThat(newDomainBase("example.com").asBuilder()
|
||||
.setDsData(ImmutableSet.of(DelegationSignerData.create(1, 1, 1, new byte[]{1})))
|
||||
.build().getDsData().asList().get(0).getDigest())
|
||||
.isNotNull();
|
||||
assertThat(
|
||||
newDomainBase("example.com")
|
||||
.asBuilder()
|
||||
.setDsData(ImmutableSet.of(DelegationSignerData.create(1, 1, 1, (byte[]) null)))
|
||||
.build()
|
||||
.getDsData()
|
||||
.asList()
|
||||
.get(0)
|
||||
.getDigest())
|
||||
.isNull();
|
||||
assertThat(
|
||||
newDomainBase("example.com")
|
||||
.asBuilder()
|
||||
.setDsData(ImmutableSet.of(DelegationSignerData.create(1, 1, 1, new byte[] {})))
|
||||
.build()
|
||||
.getDsData()
|
||||
.asList()
|
||||
.get(0)
|
||||
.getDigest())
|
||||
.isNull();
|
||||
assertThat(
|
||||
newDomainBase("example.com")
|
||||
.asBuilder()
|
||||
.setDsData(ImmutableSet.of(DelegationSignerData.create(1, 1, 1, new byte[] {1})))
|
||||
.build()
|
||||
.getDsData()
|
||||
.asList()
|
||||
.get(0)
|
||||
.getDigest())
|
||||
.isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyTransferDataBecomesNull() {
|
||||
DomainBase withNull =
|
||||
newDomainBase("example.com").asBuilder().setTransferData(null).build();
|
||||
DomainBase withNull = newDomainBase("example.com").asBuilder().setTransferData(null).build();
|
||||
DomainBase withEmpty = withNull.asBuilder().setTransferData(TransferData.EMPTY).build();
|
||||
assertThat(withNull).isEqualTo(withEmpty);
|
||||
assertThat(withEmpty.transferData).isNull();
|
||||
@@ -241,18 +274,22 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
StatusValue[] statuses1 = {StatusValue.CLIENT_HOLD};
|
||||
// If there are other status values, OK should be suppressed. (Domains can't be LINKED.)
|
||||
assertAboutDomains()
|
||||
.that(newDomainBase("example.com").asBuilder()
|
||||
.setNameservers(nameservers)
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_HOLD))
|
||||
.build())
|
||||
.that(
|
||||
newDomainBase("example.com")
|
||||
.asBuilder()
|
||||
.setNameservers(nameservers)
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_HOLD))
|
||||
.build())
|
||||
.hasExactlyStatusValues(statuses1);
|
||||
StatusValue[] statuses2 = {StatusValue.CLIENT_HOLD};
|
||||
// When OK is suppressed, it should be removed even if it was originally there.
|
||||
assertAboutDomains()
|
||||
.that(newDomainBase("example.com").asBuilder()
|
||||
.setNameservers(nameservers)
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.OK, StatusValue.CLIENT_HOLD))
|
||||
.build())
|
||||
.that(
|
||||
newDomainBase("example.com")
|
||||
.asBuilder()
|
||||
.setNameservers(nameservers)
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.OK, StatusValue.CLIENT_HOLD))
|
||||
.build())
|
||||
.hasExactlyStatusValues(statuses2);
|
||||
StatusValue[] statuses3 = {StatusValue.INACTIVE};
|
||||
// If there are no nameservers, INACTIVE should be added, which suppresses OK.
|
||||
@@ -262,17 +299,21 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
StatusValue[] statuses4 = {StatusValue.CLIENT_HOLD, StatusValue.INACTIVE};
|
||||
// If there are no nameservers but there are status values, INACTIVE should still be added.
|
||||
assertAboutDomains()
|
||||
.that(newDomainBase("example.com").asBuilder()
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_HOLD))
|
||||
.build())
|
||||
.that(
|
||||
newDomainBase("example.com")
|
||||
.asBuilder()
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_HOLD))
|
||||
.build())
|
||||
.hasExactlyStatusValues(statuses4);
|
||||
StatusValue[] statuses5 = {StatusValue.CLIENT_HOLD};
|
||||
// If there are nameservers, INACTIVE should be removed even if it was originally there.
|
||||
assertAboutDomains()
|
||||
.that(newDomainBase("example.com").asBuilder()
|
||||
.setNameservers(nameservers)
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.INACTIVE, StatusValue.CLIENT_HOLD))
|
||||
.build())
|
||||
.that(
|
||||
newDomainBase("example.com")
|
||||
.asBuilder()
|
||||
.setNameservers(nameservers)
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.INACTIVE, StatusValue.CLIENT_HOLD))
|
||||
.build())
|
||||
.hasExactlyStatusValues(statuses5);
|
||||
}
|
||||
|
||||
@@ -290,18 +331,22 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
|
||||
private void doExpiredTransferTest(DateTime oldExpirationTime) {
|
||||
HistoryEntry historyEntry = new HistoryEntry.Builder().setParent(domain).build();
|
||||
BillingEvent.OneTime transferBillingEvent = persistResource(
|
||||
new BillingEvent.OneTime.Builder()
|
||||
.setReason(Reason.TRANSFER)
|
||||
.setClientId("winner")
|
||||
.setTargetId("example.com")
|
||||
.setEventTime(clock.nowUtc())
|
||||
.setBillingTime(
|
||||
clock.nowUtc().plusDays(1).plus(Registry.get("com").getTransferGracePeriodLength()))
|
||||
.setCost(Money.of(USD, 11))
|
||||
.setPeriodYears(1)
|
||||
.setParent(historyEntry)
|
||||
.build());
|
||||
BillingEvent.OneTime transferBillingEvent =
|
||||
persistResource(
|
||||
new BillingEvent.OneTime.Builder()
|
||||
.setReason(Reason.TRANSFER)
|
||||
.setClientId("winner")
|
||||
.setTargetId("example.com")
|
||||
.setEventTime(clock.nowUtc())
|
||||
.setBillingTime(
|
||||
clock
|
||||
.nowUtc()
|
||||
.plusDays(1)
|
||||
.plus(Registry.get("com").getTransferGracePeriodLength()))
|
||||
.setCost(Money.of(USD, 11))
|
||||
.setPeriodYears(1)
|
||||
.setParent(historyEntry)
|
||||
.build());
|
||||
domain =
|
||||
domain
|
||||
.asBuilder()
|
||||
@@ -329,14 +374,16 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
domain.getTransferData().getServerApproveAutorenewEvent();
|
||||
assertTransferred(afterTransfer, newExpirationTime, serverApproveAutorenewEvent);
|
||||
assertThat(afterTransfer.getGracePeriods())
|
||||
.containsExactly(GracePeriod.create(
|
||||
GracePeriodStatus.TRANSFER,
|
||||
clock.nowUtc().plusDays(1).plus(Registry.get("com").getTransferGracePeriodLength()),
|
||||
"winner",
|
||||
Key.create(transferBillingEvent)));
|
||||
.containsExactly(
|
||||
GracePeriod.create(
|
||||
GracePeriodStatus.TRANSFER,
|
||||
clock.nowUtc().plusDays(1).plus(Registry.get("com").getTransferGracePeriodLength()),
|
||||
"winner",
|
||||
Key.create(transferBillingEvent)));
|
||||
// If we project after the grace period expires all should be the same except the grace period.
|
||||
DomainBase afterGracePeriod = domain.cloneProjectedAtTime(
|
||||
clock.nowUtc().plusDays(2).plus(Registry.get("com").getTransferGracePeriodLength()));
|
||||
DomainBase afterGracePeriod =
|
||||
domain.cloneProjectedAtTime(
|
||||
clock.nowUtc().plusDays(2).plus(Registry.get("com").getTransferGracePeriodLength()));
|
||||
assertTransferred(afterGracePeriod, newExpirationTime, serverApproveAutorenewEvent);
|
||||
assertThat(afterGracePeriod.getGracePeriods()).isEmpty();
|
||||
}
|
||||
@@ -439,10 +486,11 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
|
||||
@Test
|
||||
public void testStackedGracePeriods() {
|
||||
ImmutableList<GracePeriod> gracePeriods = ImmutableList.of(
|
||||
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(3), "foo", null),
|
||||
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(2), "bar", null),
|
||||
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(1), "baz", null));
|
||||
ImmutableList<GracePeriod> gracePeriods =
|
||||
ImmutableList.of(
|
||||
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(3), "foo", null),
|
||||
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(2), "bar", null),
|
||||
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(1), "baz", null));
|
||||
domain = domain.asBuilder().setGracePeriods(ImmutableSet.copyOf(gracePeriods)).build();
|
||||
for (int i = 1; i < 3; ++i) {
|
||||
assertThat(domain.cloneProjectedAtTime(clock.nowUtc().plusDays(i)).getGracePeriods())
|
||||
@@ -452,12 +500,14 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
|
||||
@Test
|
||||
public void testGracePeriodsByType() {
|
||||
ImmutableSet<GracePeriod> addGracePeriods = ImmutableSet.of(
|
||||
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(3), "foo", null),
|
||||
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(1), "baz", null));
|
||||
ImmutableSet<GracePeriod> renewGracePeriods = ImmutableSet.of(
|
||||
GracePeriod.create(GracePeriodStatus.RENEW, clock.nowUtc().plusDays(3), "foo", null),
|
||||
GracePeriod.create(GracePeriodStatus.RENEW, clock.nowUtc().plusDays(1), "baz", null));
|
||||
ImmutableSet<GracePeriod> addGracePeriods =
|
||||
ImmutableSet.of(
|
||||
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(3), "foo", null),
|
||||
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(1), "baz", null));
|
||||
ImmutableSet<GracePeriod> renewGracePeriods =
|
||||
ImmutableSet.of(
|
||||
GracePeriod.create(GracePeriodStatus.RENEW, clock.nowUtc().plusDays(3), "foo", null),
|
||||
GracePeriod.create(GracePeriodStatus.RENEW, clock.nowUtc().plusDays(1), "baz", null));
|
||||
domain =
|
||||
domain
|
||||
.asBuilder()
|
||||
@@ -472,8 +522,7 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
|
||||
@Test
|
||||
public void testRenewalsHappenAtExpiration() {
|
||||
DomainBase renewed =
|
||||
domain.cloneProjectedAtTime(domain.getRegistrationExpirationTime());
|
||||
DomainBase renewed = domain.cloneProjectedAtTime(domain.getRegistrationExpirationTime());
|
||||
assertThat(renewed.getRegistrationExpirationTime())
|
||||
.isEqualTo(domain.getRegistrationExpirationTime().plusYears(1));
|
||||
assertThat(renewed.getLastEppUpdateTime()).isEqualTo(domain.getRegistrationExpirationTime());
|
||||
@@ -490,9 +539,11 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
|
||||
@Test
|
||||
public void testRenewalsDontHappenOnFebruary29() {
|
||||
domain = domain.asBuilder()
|
||||
.setRegistrationExpirationTime(DateTime.parse("2004-02-29T22:00:00.0Z"))
|
||||
.build();
|
||||
domain =
|
||||
domain
|
||||
.asBuilder()
|
||||
.setRegistrationExpirationTime(DateTime.parse("2004-02-29T22:00:00.0Z"))
|
||||
.build();
|
||||
DomainBase renewed =
|
||||
domain.cloneProjectedAtTime(domain.getRegistrationExpirationTime().plusYears(4));
|
||||
assertThat(renewed.getRegistrationExpirationTime().getDayOfMonth()).isEqualTo(28);
|
||||
@@ -517,23 +568,24 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
.put(oldExpirationTime.plusYears(2).plusMillis(1), Money.of(USD, 5))
|
||||
.build())
|
||||
.build());
|
||||
DomainBase renewedThreeTimes =
|
||||
domain.cloneProjectedAtTime(oldExpirationTime.plusYears(2));
|
||||
DomainBase renewedThreeTimes = domain.cloneProjectedAtTime(oldExpirationTime.plusYears(2));
|
||||
assertThat(renewedThreeTimes.getRegistrationExpirationTime())
|
||||
.isEqualTo(oldExpirationTime.plusYears(3));
|
||||
assertThat(renewedThreeTimes.getLastEppUpdateTime()).isEqualTo(oldExpirationTime.plusYears(2));
|
||||
assertThat(renewedThreeTimes.getGracePeriods())
|
||||
.containsExactly(GracePeriod.createForRecurring(
|
||||
GracePeriodStatus.AUTO_RENEW,
|
||||
oldExpirationTime.plusYears(2).plus(
|
||||
Registry.get("com").getAutoRenewGracePeriodLength()),
|
||||
renewedThreeTimes.getCurrentSponsorClientId(),
|
||||
renewedThreeTimes.autorenewBillingEvent));
|
||||
.containsExactly(
|
||||
GracePeriod.createForRecurring(
|
||||
GracePeriodStatus.AUTO_RENEW,
|
||||
oldExpirationTime
|
||||
.plusYears(2)
|
||||
.plus(Registry.get("com").getAutoRenewGracePeriodLength()),
|
||||
renewedThreeTimes.getCurrentSponsorClientId(),
|
||||
renewedThreeTimes.autorenewBillingEvent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToHydratedString_notCircular() {
|
||||
domain.toHydratedString(); // If there are circular references, this will overflow the stack.
|
||||
domain.toHydratedString(); // If there are circular references, this will overflow the stack.
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -557,4 +609,154 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
.hasMessageThat()
|
||||
.contains("Domain name must be in puny-coded, lower-case form");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClone_doNotExtendExpirationOnDeletedDomain() {
|
||||
DateTime now = DateTime.now(UTC);
|
||||
domain =
|
||||
persistResource(
|
||||
domain
|
||||
.asBuilder()
|
||||
.setRegistrationExpirationTime(now.minusDays(1))
|
||||
.setDeletionTime(now.minusDays(10))
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE, StatusValue.INACTIVE))
|
||||
.build());
|
||||
assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationTime())
|
||||
.isEqualTo(now.minusDays(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClone_doNotExtendExpirationOnFutureDeletedDomain() {
|
||||
// if a domain is in pending deletion (StatusValue.PENDING_DELETE), don't extend expiration
|
||||
DateTime now = DateTime.now(UTC);
|
||||
domain =
|
||||
persistResource(
|
||||
domain
|
||||
.asBuilder()
|
||||
.setRegistrationExpirationTime(now.plusDays(1))
|
||||
.setDeletionTime(now.plusDays(20))
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE, StatusValue.INACTIVE))
|
||||
.build());
|
||||
assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationTime())
|
||||
.isEqualTo(now.plusDays(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClone_extendsExpirationForExpiredTransferredDomain() {
|
||||
// If the transfer implicitly succeeded, the expiration time should be extended
|
||||
DateTime now = DateTime.now(UTC);
|
||||
DateTime transferExpirationTime = now.minusDays(1);
|
||||
DateTime previousExpiration = now.minusDays(2);
|
||||
|
||||
TransferData transferData =
|
||||
new TransferData.Builder()
|
||||
.setPendingTransferExpirationTime(transferExpirationTime)
|
||||
.setTransferStatus(TransferStatus.PENDING)
|
||||
.setGainingClientId("TheRegistrar")
|
||||
.build();
|
||||
Period extensionPeriod = transferData.getTransferPeriod();
|
||||
DateTime newExpiration = previousExpiration.plusYears(extensionPeriod.getValue());
|
||||
domain =
|
||||
persistResource(
|
||||
domain
|
||||
.asBuilder()
|
||||
.setRegistrationExpirationTime(previousExpiration)
|
||||
.setTransferData(transferData)
|
||||
.build());
|
||||
|
||||
assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationTime())
|
||||
.isEqualTo(newExpiration);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClone_extendsExpirationForNonExpiredTransferredDomain() {
|
||||
// If the transfer implicitly succeeded, the expiration time should be extended even if it
|
||||
// hadn't already expired
|
||||
DateTime now = DateTime.now(UTC);
|
||||
DateTime transferExpirationTime = now.minusDays(1);
|
||||
DateTime previousExpiration = now.plusWeeks(2);
|
||||
|
||||
TransferData transferData =
|
||||
new TransferData.Builder()
|
||||
.setPendingTransferExpirationTime(transferExpirationTime)
|
||||
.setTransferStatus(TransferStatus.PENDING)
|
||||
.setGainingClientId("TheRegistrar")
|
||||
.build();
|
||||
Period extensionPeriod = transferData.getTransferPeriod();
|
||||
DateTime newExpiration = previousExpiration.plusYears(extensionPeriod.getValue());
|
||||
domain =
|
||||
persistResource(
|
||||
domain
|
||||
.asBuilder()
|
||||
.setRegistrationExpirationTime(previousExpiration)
|
||||
.setTransferData(transferData)
|
||||
.build());
|
||||
|
||||
assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationTime())
|
||||
.isEqualTo(newExpiration);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClone_doesNotExtendExpirationForPendingTransfer() {
|
||||
// Pending transfers shouldn't affect the expiration time
|
||||
DateTime now = DateTime.now(UTC);
|
||||
DateTime transferExpirationTime = now.plusDays(1);
|
||||
DateTime previousExpiration = now.plusWeeks(2);
|
||||
|
||||
TransferData transferData =
|
||||
new TransferData.Builder()
|
||||
.setPendingTransferExpirationTime(transferExpirationTime)
|
||||
.setTransferStatus(TransferStatus.PENDING)
|
||||
.setGainingClientId("TheRegistrar")
|
||||
.build();
|
||||
domain =
|
||||
persistResource(
|
||||
domain
|
||||
.asBuilder()
|
||||
.setRegistrationExpirationTime(previousExpiration)
|
||||
.setTransferData(transferData)
|
||||
.build());
|
||||
|
||||
assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationTime())
|
||||
.isEqualTo(previousExpiration);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClone_transferDuringAutorenew() {
|
||||
// When the domain is an an autorenew grace period, we should not extend the registration
|
||||
// expiration by a further year--it should just be whatever the autorenew was
|
||||
DateTime now = DateTime.now(UTC);
|
||||
DateTime transferExpirationTime = now.minusDays(1);
|
||||
DateTime previousExpiration = now.minusDays(2);
|
||||
|
||||
TransferData transferData =
|
||||
new TransferData.Builder()
|
||||
.setPendingTransferExpirationTime(transferExpirationTime)
|
||||
.setTransferStatus(TransferStatus.PENDING)
|
||||
.setGainingClientId("TheRegistrar")
|
||||
.setServerApproveAutorenewEvent(recurringBillKey)
|
||||
.setServerApproveBillingEvent(oneTimeBillKey)
|
||||
.build();
|
||||
domain =
|
||||
persistResource(
|
||||
domain
|
||||
.asBuilder()
|
||||
.setRegistrationExpirationTime(previousExpiration)
|
||||
.setGracePeriods(
|
||||
ImmutableSet.of(
|
||||
GracePeriod.createForRecurring(
|
||||
GracePeriodStatus.AUTO_RENEW,
|
||||
now.plusDays(1),
|
||||
"NewRegistrar",
|
||||
recurringBillKey)))
|
||||
.setTransferData(transferData)
|
||||
.setAutorenewBillingEvent(recurringBillKey)
|
||||
.build());
|
||||
DomainBase clone = domain.cloneProjectedAtTime(now);
|
||||
assertThat(clone.getRegistrationExpirationTime())
|
||||
.isEqualTo(domain.getRegistrationExpirationTime().plusYears(1));
|
||||
// Transferring removes the AUTORENEW grace period and adds a TRANSFER grace period
|
||||
assertThat(getOnlyElement(clone.getGracePeriods()).getType())
|
||||
.isEqualTo(GracePeriodStatus.TRANSFER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,6 +452,14 @@ public class RegistrarTest extends EntityTestCase {
|
||||
() -> registrar.asBuilder().setAllowedTldsUncached(ImmutableSet.of("bad")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_driveFolderId_asFullUrl() {
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(IllegalArgumentException.class, () -> registrar.asBuilder().setDriveFolderId(
|
||||
"https://drive.google.com/drive/folders/1j3v7RZkU25DjbTx2-Q93H04zKOBau89M"));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Drive folder ID must not be a full URL");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_nullEmail() {
|
||||
NullPointerException thrown =
|
||||
|
||||
+78
-21
@@ -16,8 +16,12 @@ package google.registry.rdap;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.testing.DatastoreHelper.createTld;
|
||||
import static google.registry.testing.DatastoreHelper.deleteTld;
|
||||
import static google.registry.testing.DatastoreHelper.loadRegistrar;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
import static google.registry.testing.DatastoreHelper.persistSimpleResource;
|
||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
|
||||
import com.google.api.client.http.LowLevelHttpRequest;
|
||||
import com.google.api.client.testing.http.MockHttpTransport;
|
||||
@@ -27,6 +31,8 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarAddress;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.Registry.TldType;
|
||||
import google.registry.testing.AppEngineRule;
|
||||
import google.registry.testing.ShardableTestCase;
|
||||
import java.util.ArrayList;
|
||||
@@ -95,8 +101,8 @@ public final class UpdateRegistrarRdapBaseUrlsActionTest extends ShardableTestCa
|
||||
}
|
||||
}
|
||||
|
||||
TestHttpTransport httpTransport;
|
||||
UpdateRegistrarRdapBaseUrlsAction action;
|
||||
private TestHttpTransport httpTransport;
|
||||
private UpdateRegistrarRdapBaseUrlsAction action;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -104,27 +110,10 @@ public final class UpdateRegistrarRdapBaseUrlsActionTest extends ShardableTestCa
|
||||
action = new UpdateRegistrarRdapBaseUrlsAction();
|
||||
|
||||
action.password = "myPassword";
|
||||
action.tld = "tld";
|
||||
action.httpTransport = httpTransport;
|
||||
addValidResponses(httpTransport);
|
||||
|
||||
MockLowLevelHttpResponse loginResponse = new MockLowLevelHttpResponse();
|
||||
loginResponse.addHeader(
|
||||
"Set-Cookie",
|
||||
"id=myAuthenticationId; "
|
||||
+ "Expires=Tue, 11-Jun-2019 16:34:21 GMT; Path=/mosapi/v1/app; Secure; HttpOnly");
|
||||
|
||||
MockLowLevelHttpResponse listResponse = new MockLowLevelHttpResponse();
|
||||
listResponse.setContent(JSON_LIST_REPLY);
|
||||
|
||||
MockLowLevelHttpResponse logoutResponse = new MockLowLevelHttpResponse();
|
||||
loginResponse.addHeader(
|
||||
"Set-Cookie",
|
||||
"id=id; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/mosapi/v1/app; Secure; HttpOnly");
|
||||
|
||||
httpTransport.addNextResponse(loginResponse);
|
||||
httpTransport.addNextResponse(listResponse);
|
||||
httpTransport.addNextResponse(logoutResponse);
|
||||
|
||||
createTld("tld");
|
||||
}
|
||||
|
||||
private void assertCorrectRequestsSent() {
|
||||
@@ -237,4 +226,72 @@ public final class UpdateRegistrarRdapBaseUrlsActionTest extends ShardableTestCa
|
||||
assertThat(loadRegistrar("registrar4001").getRdapBaseUrls())
|
||||
.containsExactly("https://rdap.example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoTlds() {
|
||||
deleteTld("tld");
|
||||
assertThat(assertThrows(IllegalArgumentException.class, action::run)).hasMessageThat()
|
||||
.isEqualTo("There must exist at least one REAL TLD.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyTestTlds() {
|
||||
persistResource(Registry.get("tld").asBuilder().setTldType(TldType.TEST).build());
|
||||
assertThat(assertThrows(IllegalArgumentException.class, action::run)).hasMessageThat()
|
||||
.isEqualTo("There must exist at least one REAL TLD.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecondTldSucceeds() {
|
||||
createTld("secondtld");
|
||||
httpTransport = new TestHttpTransport();
|
||||
action.httpTransport = httpTransport;
|
||||
|
||||
// the first TLD request will return a bad cookie but the second will succeed
|
||||
MockLowLevelHttpResponse badLoginResponse = new MockLowLevelHttpResponse();
|
||||
badLoginResponse.addHeader("Set-Cookie",
|
||||
"Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/mosapi/v1/app; Secure; HttpOnly");
|
||||
|
||||
httpTransport.addNextResponse(badLoginResponse);
|
||||
addValidResponses(httpTransport);
|
||||
|
||||
action.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBothFail() {
|
||||
createTld("secondtld");
|
||||
httpTransport = new TestHttpTransport();
|
||||
action.httpTransport = httpTransport;
|
||||
|
||||
MockLowLevelHttpResponse badLoginResponse = new MockLowLevelHttpResponse();
|
||||
badLoginResponse.addHeader("Set-Cookie",
|
||||
"Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/mosapi/v1/app; Secure; HttpOnly");
|
||||
|
||||
// it should fail for both TLDs
|
||||
httpTransport.addNextResponse(badLoginResponse);
|
||||
httpTransport.addNextResponse(badLoginResponse);
|
||||
|
||||
assertThat(assertThrows(RuntimeException.class, action::run)).hasMessageThat()
|
||||
.isEqualTo("Error contacting MosAPI server. Tried TLDs [secondtld, tld]");
|
||||
}
|
||||
|
||||
private static void addValidResponses(TestHttpTransport httpTransport) {
|
||||
MockLowLevelHttpResponse loginResponse = new MockLowLevelHttpResponse();
|
||||
loginResponse.addHeader(
|
||||
"Set-Cookie",
|
||||
"id=myAuthenticationId; "
|
||||
+ "Expires=Tue, 11-Jun-2019 16:34:21 GMT; Path=/mosapi/v1/app; Secure; HttpOnly");
|
||||
|
||||
MockLowLevelHttpResponse listResponse = new MockLowLevelHttpResponse();
|
||||
listResponse.setContent(JSON_LIST_REPLY);
|
||||
|
||||
MockLowLevelHttpResponse logoutResponse = new MockLowLevelHttpResponse();
|
||||
logoutResponse.addHeader(
|
||||
"Set-Cookie",
|
||||
"id=id; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/mosapi/v1/app; Secure; HttpOnly");
|
||||
httpTransport.addNextResponse(loginResponse);
|
||||
httpTransport.addNextResponse(listResponse);
|
||||
httpTransport.addNextResponse(logoutResponse);
|
||||
}
|
||||
}
|
||||
|
||||
+39
-16
@@ -18,10 +18,10 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.DatastoreHelper.loadRegistrar;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
import static google.registry.testing.GcsTestingUtils.writeGcsFile;
|
||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -68,6 +68,7 @@ public class CopyDetailReportsActionTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
persistResource(loadRegistrar("TheRegistrar").asBuilder().setDriveFolderId("0B-12345").build());
|
||||
persistResource(loadRegistrar("NewRegistrar").asBuilder().setDriveFolderId("0B-54321").build());
|
||||
response = new FakeResponse();
|
||||
driveConnection = mock(DriveConnection.class);
|
||||
emailUtils = mock(BillingEmailUtils.class);
|
||||
@@ -96,21 +97,21 @@ public class CopyDetailReportsActionTest {
|
||||
|
||||
action.run();
|
||||
verify(driveConnection)
|
||||
.createFile(
|
||||
.createOrUpdateFile(
|
||||
"invoice_details_2017-10_TheRegistrar_test.csv",
|
||||
MediaType.CSV_UTF_8,
|
||||
"0B-12345",
|
||||
"hello,world\n1,2".getBytes(UTF_8));
|
||||
|
||||
verify(driveConnection)
|
||||
.createFile(
|
||||
.createOrUpdateFile(
|
||||
"invoice_details_2017-10_TheRegistrar_hello.csv",
|
||||
MediaType.CSV_UTF_8,
|
||||
"0B-12345",
|
||||
"hola,mundo\n3,4".getBytes(UTF_8));
|
||||
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||
assertThat(response.getContentType()).isEqualTo(MediaType.PLAIN_TEXT_UTF_8);
|
||||
assertThat(response.getPayload()).isEqualTo("Copied detail reports.");
|
||||
assertThat(response.getPayload()).isEqualTo("Copied detail reports.\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -126,7 +127,7 @@ public class CopyDetailReportsActionTest {
|
||||
"hello,world\n1,2".getBytes(UTF_8));
|
||||
action.run();
|
||||
verify(driveConnection)
|
||||
.createFile(
|
||||
.createOrUpdateFile(
|
||||
"invoice_details_2017-10_TheRegistrar_hello.csv",
|
||||
MediaType.CSV_UTF_8,
|
||||
"0B-12345",
|
||||
@@ -135,7 +136,7 @@ public class CopyDetailReportsActionTest {
|
||||
verifyNoMoreInteractions(driveConnection);
|
||||
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||
assertThat(response.getContentType()).isEqualTo(MediaType.PLAIN_TEXT_UTF_8);
|
||||
assertThat(response.getPayload()).isEqualTo("Copied detail reports.");
|
||||
assertThat(response.getPayload()).isEqualTo("Copied detail reports.\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -144,41 +145,63 @@ public class CopyDetailReportsActionTest {
|
||||
gcsService,
|
||||
new GcsFilename("test-bucket", "results/invoice_details_2017-10_TheRegistrar_hello.csv"),
|
||||
"hola,mundo\n3,4".getBytes(UTF_8));
|
||||
when(driveConnection.createFile(any(), any(), any(), any()))
|
||||
when(driveConnection.createOrUpdateFile(any(), any(), any(), any()))
|
||||
.thenThrow(new IOException("expected"))
|
||||
.thenReturn("success");
|
||||
|
||||
action.run();
|
||||
verify(driveConnection, times(2))
|
||||
.createFile(
|
||||
.createOrUpdateFile(
|
||||
"invoice_details_2017-10_TheRegistrar_hello.csv",
|
||||
MediaType.CSV_UTF_8,
|
||||
"0B-12345",
|
||||
"hola,mundo\n3,4".getBytes(UTF_8));
|
||||
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||
assertThat(response.getContentType()).isEqualTo(MediaType.PLAIN_TEXT_UTF_8);
|
||||
assertThat(response.getPayload()).isEqualTo("Copied detail reports.");
|
||||
assertThat(response.getPayload()).isEqualTo("Copied detail reports.\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFail_tooManyFailures_sendsAlertEmail() throws IOException {
|
||||
public void testFail_tooManyFailures_sendsAlertEmail_continues() throws IOException {
|
||||
writeGcsFile(
|
||||
gcsService,
|
||||
new GcsFilename("test-bucket", "results/invoice_details_2017-10_TheRegistrar_hello.csv"),
|
||||
"hola,mundo\n3,4".getBytes(UTF_8));
|
||||
when(driveConnection.createFile(any(), any(), any(), any()))
|
||||
writeGcsFile(
|
||||
gcsService,
|
||||
new GcsFilename("test-bucket", "results/invoice_details_2017-10_NewRegistrar_test.csv"),
|
||||
"hello,world\n1,2".getBytes(UTF_8));
|
||||
when(driveConnection.createOrUpdateFile(
|
||||
eq("invoice_details_2017-10_TheRegistrar_hello.csv"), any(), any(), any()))
|
||||
.thenThrow(new IOException("expected"));
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class, action::run);
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("java.io.IOException: expected");
|
||||
action.run();
|
||||
verify(driveConnection, times(3))
|
||||
.createFile(
|
||||
.createOrUpdateFile(
|
||||
"invoice_details_2017-10_TheRegistrar_hello.csv",
|
||||
MediaType.CSV_UTF_8,
|
||||
"0B-12345",
|
||||
"hola,mundo\n3,4".getBytes(UTF_8));
|
||||
verify(emailUtils).sendAlertEmail("Warning: CopyDetailReportsAction failed.\nEncountered: "
|
||||
+ "expected on file: invoice_details_2017-10_TheRegistrar_hello.csv");
|
||||
verify(driveConnection)
|
||||
.createOrUpdateFile(
|
||||
"invoice_details_2017-10_NewRegistrar_test.csv",
|
||||
MediaType.CSV_UTF_8,
|
||||
"0B-54321",
|
||||
"hello,world\n1,2".getBytes(UTF_8));
|
||||
verify(emailUtils)
|
||||
.sendAlertEmail(
|
||||
"Copied detail reports.\n"
|
||||
+ "The following errors were encountered:\n"
|
||||
+ "Registrar: TheRegistrar\n"
|
||||
+ "Error: java.io.IOException: expected\n");
|
||||
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||
assertThat(response.getContentType()).isEqualTo(MediaType.PLAIN_TEXT_UTF_8);
|
||||
assertThat(response.getPayload())
|
||||
.isEqualTo(
|
||||
"Copied detail reports.\n"
|
||||
+ "The following errors were encountered:\n"
|
||||
+ "Registrar: TheRegistrar\n"
|
||||
+ "Error: java.io.IOException: expected\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -141,7 +141,15 @@ public class RepeatableRunner extends BlockJUnit4ClassRunner {
|
||||
int numSuccess = 0, numFailure = 0;
|
||||
Throwable lastException = null;
|
||||
for (int attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
||||
attemptNumber.set(attempt);
|
||||
// attemptNumber would be null if any exception happens during the
|
||||
// instantiation of test class object(including test rules). However,
|
||||
// those exceptions would not be actually thrown until statement.evaluate()
|
||||
// is invoked. So, we should just skip the setter and let the statement
|
||||
// be evaluated. Then we should be able to find the stack trace of
|
||||
// root cause in the test reports.
|
||||
if (attemptNumber != null) {
|
||||
attemptNumber.set(attempt);
|
||||
}
|
||||
try {
|
||||
statement.evaluate();
|
||||
numSuccess++;
|
||||
|
||||
@@ -17,6 +17,7 @@ package google.registry.webdriver;
|
||||
import google.registry.webdriver.RepeatableRunner.AttemptNumber;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.Timeout;
|
||||
|
||||
/** Base class for tests that needs a {@link WebDriverPlusScreenDifferRule}. */
|
||||
public class WebDriverTestCase {
|
||||
@@ -27,4 +28,7 @@ public class WebDriverTestCase {
|
||||
@Rule
|
||||
public final WebDriverPlusScreenDifferRule driver =
|
||||
new WebDriverPlusScreenDifferRule(webDriverProvider::getWebDriver, attemptNumber);
|
||||
|
||||
@Rule
|
||||
public final Timeout timeout = Timeout.seconds(30);
|
||||
}
|
||||
|
||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 94 KiB |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 86 KiB |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 93 KiB |
+2
-39
@@ -13,20 +13,17 @@
|
||||
// limitations under the License.
|
||||
|
||||
ext {
|
||||
// Direct dependencies and compile-time transitive dependencies (i.e.,
|
||||
// those flagged as undeclared-dependency by Nebula-lint).
|
||||
dependencyList = [
|
||||
'args4j:args4j:2.0.26',
|
||||
'com.beust:jcommander:1.60',
|
||||
'com.google.api-client:google-api-client:1.29.2',
|
||||
'com.google.api-client:google-api-client-appengine:1.29.2',
|
||||
'com.google.api-client:google-api-client-jackson2:1.20.0',
|
||||
'com.google.api-client:google-api-client-java6:1.27.0',
|
||||
'com.google.api-client:google-api-client-servlet:1.29.2',
|
||||
'com.google.apis:google-api-services-admin-directory:directory_v1-rev72-1.22.0',
|
||||
'com.google.apis:google-api-services-appengine:v1-rev101-1.25.0',
|
||||
'com.google.apis:google-api-services-bigquery:v2-rev325-1.22.0',
|
||||
'com.google.apis:google-api-services-clouddebugger:v2-rev8-1.22.0',
|
||||
'com.google.apis:google-api-services-cloudkms:v1-rev12-1.22.0',
|
||||
'com.google.apis:google-api-services-cloudresourcemanager:v1-rev6-1.22.0',
|
||||
'com.google.apis:google-api-services-dataflow:v1b3-rev196-1.22.0',
|
||||
'com.google.apis:google-api-services-dns:v2beta1-rev6-1.22.0',
|
||||
'com.google.apis:google-api-services-drive:v2-rev160-1.19.1',
|
||||
@@ -35,38 +32,27 @@ ext {
|
||||
'com.google.apis:google-api-services-sheets:v4-rev483-1.22.0',
|
||||
'com.google.apis:google-api-services-storage:v1-rev150-1.22.0',
|
||||
'com.google.appengine:appengine-api-1.0-sdk:1.9.48',
|
||||
'com.google.appengine:appengine-api-labs:1.9.48',
|
||||
'com.google.appengine:appengine-api-stubs:1.9.48',
|
||||
'com.google.appengine:appengine-remote-api:1.9.48',
|
||||
'com.google.appengine:appengine-testing:1.9.58',
|
||||
'com.google.appengine:appengine-tools-sdk:1.9.48',
|
||||
'com.google.appengine.tools:appengine-gcs-client:0.6',
|
||||
'com.google.appengine.tools:appengine-mapreduce:0.9',
|
||||
'com.google.appengine.tools:appengine-pipeline:0.2.13',
|
||||
'com.google.auth:google-auth-library-credentials:0.16.1',
|
||||
'com.google.auth:google-auth-library-oauth2-http:0.16.1',
|
||||
'com.google.auto:auto-common:0.8',
|
||||
'com.google.auto.factory:auto-factory:1.0-beta3',
|
||||
'com.google.auto.value:auto-value:1.6.3',
|
||||
'com.google.auto.value:auto-value-annotations:1.6.3',
|
||||
'com.google.closure-stylesheets:closure-stylesheets:1.5.0',
|
||||
'com.google.cloud:google-cloud-core:1.59.0',
|
||||
'com.google.cloud:google-cloud-storage:1.59.0',
|
||||
'com.google.cloud.bigdataoss:gcsio:1.4.5',
|
||||
'com.google.cloud.bigdataoss:util:1.4.5',
|
||||
'com.googlecode.charts4j:charts4j:1.3',
|
||||
'com.google.code.findbugs:jsr305:3.0.2',
|
||||
'com.google.code.gson:gson:2.8.5',
|
||||
'com.googlecode.json-simple:json-simple:1.1.1',
|
||||
'com.google.dagger:dagger:2.21',
|
||||
'com.google.dagger:dagger-compiler:2.21',
|
||||
'com.google.dagger:dagger-producers:2.21',
|
||||
'com.google.errorprone:error_prone_annotations:2.3.3',
|
||||
'com.google.errorprone:javac-shaded:9-dev-r4023-3',
|
||||
'com.google.flogger:flogger:0.1',
|
||||
'com.google.flogger:flogger-system-backend:0.1',
|
||||
'com.google.gdata:core:1.47.1',
|
||||
'com.google.googlejavaformat:google-java-format:1.4',
|
||||
'com.google.guava:guava:27.1-jre',
|
||||
'com.google.guava:guava-testlib:25.0-jre',
|
||||
'com.google.gwt:gwt-user:2.8.2',
|
||||
@@ -78,27 +64,18 @@ ext {
|
||||
'com.google.monitoring-client:metrics:1.0.4',
|
||||
'com.google.monitoring-client:stackdriver:1.0.4',
|
||||
'com.google.oauth-client:google-oauth-client:1.29.2',
|
||||
'com.google.oauth-client:google-oauth-client-appengine:1.29.2',
|
||||
'com.google.oauth-client:google-oauth-client-java6:1.27.0',
|
||||
'com.google.oauth-client:google-oauth-client-jetty:1.28.0',
|
||||
'com.google.oauth-client:google-oauth-client-servlet:1.29.2',
|
||||
'com.google.protobuf:protobuf-java:2.6.0',
|
||||
'com.google.re2j:re2j:1.1',
|
||||
'com.google.template:soy:2018-03-14',
|
||||
'com.google.truth.extensions:truth-java8-extension:0.45',
|
||||
'com.google.truth:truth:0.45',
|
||||
'com.ibm.icu:icu4j:57.1',
|
||||
'com.jcraft:jsch:0.1.55',
|
||||
'com.jcraft:jzlib:1.1.3',
|
||||
'commons-codec:commons-codec:1.10',
|
||||
'commons-logging:commons-logging:1.2',
|
||||
'com.squareup:javapoet:1.8.0',
|
||||
'com.squareup:javawriter:2.5.1',
|
||||
'com.sun.activation:javax.activation:1.2.0',
|
||||
'com.sun.xml.bind:jaxb-impl:2.2.11',
|
||||
'com.sun.xml.bind:jaxb-osgi:2.2.11',
|
||||
'com.sun.xml.bind:jaxb-xjc:2.2.11',
|
||||
'com.thoughtworks.paranamer:paranamer:2.7',
|
||||
'com.thoughtworks.qdox:qdox:1.12.1',
|
||||
'dnsjava:dnsjava:2.1.7',
|
||||
'io.netty:netty-buffer:4.1.31.Final',
|
||||
@@ -106,34 +83,27 @@ ext {
|
||||
'io.netty:netty-codec-http: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.28.Final',
|
||||
'io.netty:netty-tcnative:2.0.22.Final',
|
||||
'io.netty:netty-tcnative-boringssl-static:2.0.22.Final',
|
||||
'io.netty:netty-transport:4.1.31.Final',
|
||||
'it.unimi.dsi:fastutil:6.5.16',
|
||||
'javax.annotation:jsr250-api:1.0',
|
||||
'javax.inject:javax.inject:1',
|
||||
'javax.mail:mail:1.4',
|
||||
'javax.servlet:servlet-api:2.5',
|
||||
'javax.xml.bind:jaxb-api:2.3.0',
|
||||
'javax.xml.soap:javax.xml.soap-api:1.4.0',
|
||||
'jline:jline:1.0',
|
||||
'joda-time:joda-time:2.9.2',
|
||||
'junit:junit:4.12',
|
||||
'org.apache.avro:avro:1.8.2',
|
||||
'org.apache.beam:beam-runners-direct-java:2.11.0',
|
||||
'org.apache.beam:beam-runners-google-cloud-dataflow-java:2.11.0',
|
||||
'org.apache.beam:beam-sdks-common-runner-api:2.2.0',
|
||||
'org.apache.beam:beam-sdks-java-core:2.11.0',
|
||||
'org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.11.0',
|
||||
'org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.11.0',
|
||||
'org.apache.commons:commons-compress:1.8.1',
|
||||
'org.apache.commons:commons-text:1.6',
|
||||
'org.apache.ftpserver:ftplet-api:1.0.6',
|
||||
'org.apache.ftpserver:ftpserver-core:1.0.6',
|
||||
'org.apache.httpcomponents:httpclient:4.5.2',
|
||||
'org.apache.httpcomponents:httpcore:4.4.4',
|
||||
'org.apache.mina:mina-core:2.0.4',
|
||||
'org.apache.sshd:sshd-core:2.0.0',
|
||||
'org.apache.sshd:sshd-scp:2.0.0',
|
||||
'org.apache.sshd:sshd-sftp:2.0.0',
|
||||
@@ -141,26 +111,19 @@ ext {
|
||||
'org.bouncycastle:bcpg-jdk15on:1.61',
|
||||
'org.bouncycastle:bcpkix-jdk15on:1.61',
|
||||
'org.bouncycastle:bcprov-jdk15on:1.61',
|
||||
'org.codehaus.jackson:jackson-core-asl:1.9.13',
|
||||
'org.codehaus.jackson:jackson-mapper-asl:1.9.13',
|
||||
'org.glassfish.jaxb:jaxb-runtime:2.3.0',
|
||||
'org.hamcrest:hamcrest-all:1.3',
|
||||
'org.hamcrest:hamcrest-core:1.3',
|
||||
'org.hamcrest:hamcrest-library:1.3',
|
||||
'org.joda:joda-money:0.10.0',
|
||||
'org.json:json:20160810',
|
||||
'org.khronos:opengl-api:gl1.1-android-2.1_r1',
|
||||
'org.mockito:mockito-core:2.25.0',
|
||||
'org.mortbay.jetty:jetty:6.1.26',
|
||||
'org.mortbay.jetty:jetty-util:6.1.26',
|
||||
'org.seleniumhq.selenium:selenium-api:3.141.59',
|
||||
'org.seleniumhq.selenium:selenium-chrome-driver:3.141.59',
|
||||
'org.seleniumhq.selenium:selenium-java:3.141.59',
|
||||
'org.seleniumhq.selenium:selenium-remote-driver:3.141.59',
|
||||
'org.slf4j:slf4j-api:1.7.16',
|
||||
'org.testcontainers:selenium:1.10.7',
|
||||
'org.tukaani:xz:1.8',
|
||||
'org.xerial.snappy:snappy-java:1.1.4-M3',
|
||||
'org.yaml:snakeyaml:1.17',
|
||||
'xerces:xmlParserAPIs:2.6.2',
|
||||
'xpp3:xpp3:1.1.4c'
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
// 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.
|
||||
|
||||
// Legacy-style declaration of the gradle-license-report plugin, which is necessary
|
||||
// in shared scripts.
|
||||
// Note that the 'apply plugin' line does not use string literal. It references directly the
|
||||
// main class of the plugin.
|
||||
buildscript {
|
||||
repositories {
|
||||
maven {
|
||||
url 'https://plugins.gradle.org/m2/'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.github.jk1:gradle-license-report:1.8'
|
||||
}
|
||||
}
|
||||
apply plugin: com.github.jk1.license.LicenseReportPlugin
|
||||
|
||||
// Configures the checkLicense task.
|
||||
//
|
||||
// This task discovers license information for each dependency including a
|
||||
// name phrase and possibly additional details, such as an http link or relative
|
||||
// path of a file in the jar. This information is saved in json format under
|
||||
// build/reports/dependency-license. It is not used right now, but may be useful
|
||||
// if we want to check the content of the licenses.
|
||||
//
|
||||
// The required 'allowedLicensesFile' contains the acceptable license name phrases.
|
||||
// If a phrase not in this file is found, the checkLicense task will fail. Exact
|
||||
// string match is used, so they are case-sensitive and preceding/trailing whitespaces are important.
|
||||
//
|
||||
// This plugin also generates an html report under build/reports/dependency-license.
|
||||
// The optional 'filters' parameter accepts custom name-normalization rules. This
|
||||
// report is not currently in use.
|
||||
//
|
||||
// Note that this task needs to be explicitly invoked on buildSrc.
|
||||
//
|
||||
// Also note that dependencies of buildscript classpath and 'official' Gradle plugins are
|
||||
// not checked.
|
||||
//
|
||||
// Due to a bug/feature of this plugin, the Nomulus project can not lock all dependencies.
|
||||
// The 'dependencyLicenseReport' configuration must be excluded from locking.
|
||||
// TODO(weiminyu): add github issue number after reporting to author.
|
||||
licenseReport {
|
||||
ext.toFullFilePath = { relativePath ->
|
||||
if (rootDir.path.endsWith('buildSrc')) {
|
||||
return "${rootDir.path}/../${relativePath}"
|
||||
}
|
||||
return "${rootDir.path}/${relativePath}"
|
||||
}
|
||||
|
||||
// Check licenses dependencies in all configurations. This does not include
|
||||
// buildscript-classpath.
|
||||
configurations = ALL
|
||||
|
||||
def configFolder = 'config/dependency-license'
|
||||
|
||||
allowedLicensesFile = file(toFullFilePath("${configFolder}/allowed_licenses.json"))
|
||||
|
||||
filters = new com.github.jk1.license.filter.LicenseBundleNormalizer(
|
||||
bundlePath: toFullFilePath("${configFolder}/license_normalizer_bundle.json"),
|
||||
createDefaultTransformationRules: false)
|
||||
|
||||
// The following dependency jars do not contain license info.
|
||||
// Investigation results are documented inline.
|
||||
excludes = [
|
||||
// BSD: https://github.com/javacc/javacc/blob/master/LICENSE
|
||||
'javacc:javacc',
|
||||
// CDDL+GPL2.0 according to Maven Central:
|
||||
// https://mvnrepository.com/artifact/javax.servlet/servlet-api/2.5
|
||||
'javax.servlet:servlet-api',
|
||||
// Presumed free since this is from Apache:
|
||||
// http://www.apache.org/licenses/
|
||||
'xerces:xmlParserAPIs'
|
||||
]
|
||||
}
|
||||
@@ -11,10 +11,15 @@ com.diffplug.spotless:spotless-lib:1.18.0
|
||||
com.diffplug.spotless:spotless-plugin-gradle:3.18.0
|
||||
com.github.jengelman.gradle.plugins:shadow:5.0.0
|
||||
com.github.johnrengelman.shadow:com.github.johnrengelman.shadow.gradle.plugin:5.0.0
|
||||
com.google.cloud.tools:appengine-gradle-plugin:1.3.3
|
||||
com.google.cloud.tools:appengine-plugins-core:0.3.2
|
||||
com.google.code.gson:gson:2.7
|
||||
com.google.guava:guava:20.0
|
||||
com.google.cloud.tools:appengine-gradle-plugin:2.0.1
|
||||
com.google.cloud.tools:appengine-plugins-core:0.7.5
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.8.5
|
||||
com.google.errorprone:error_prone_annotations:2.2.0
|
||||
com.google.guava:failureaccess:1.0
|
||||
com.google.guava:guava:27.0-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.googlecode.concurrent-trees:concurrent-trees:2.6.1
|
||||
com.googlecode.javaewah:JavaEWAH:1.1.6
|
||||
com.jcraft:jsch:0.1.54
|
||||
@@ -39,6 +44,7 @@ org.apache.ant:ant-antlr:1.8.4
|
||||
org.apache.ant:ant-junit:1.8.4
|
||||
org.apache.ant:ant-launcher:1.9.7
|
||||
org.apache.ant:ant:1.9.7
|
||||
org.apache.commons:commons-compress:1.18
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.httpcomponents:httpclient:4.5.2
|
||||
org.apache.httpcomponents:httpcore:4.4.4
|
||||
@@ -48,6 +54,7 @@ org.apache.maven:maven-artifact:3.6.1
|
||||
org.apache.maven:maven-builder-support:3.6.1
|
||||
org.apache.maven:maven-model-builder:3.6.1
|
||||
org.apache.maven:maven-model:3.6.1
|
||||
org.checkerframework:checker-qual:2.5.2
|
||||
org.codehaus.gpars:gpars:1.2.1
|
||||
org.codehaus.groovy:groovy-all:2.4.9
|
||||
org.codehaus.groovy:groovy-ant:2.1.8
|
||||
@@ -56,12 +63,14 @@ org.codehaus.groovy:groovy-templates:2.1.8
|
||||
org.codehaus.groovy:groovy-xml:2.4.7
|
||||
org.codehaus.groovy:groovy:2.4.7
|
||||
org.codehaus.jsr166-mirror:jsr166y:1.7.0
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.codehaus.plexus:plexus-component-annotations:1.7.1
|
||||
org.codehaus.plexus:plexus-interpolation:1.25
|
||||
org.codehaus.plexus:plexus-utils:3.2.0
|
||||
org.codenarc:CodeNarc:0.25.2
|
||||
org.eclipse.jdt:core:3.1.1
|
||||
org.eclipse.jgit:org.eclipse.jgit:5.0.1.201806211838-r
|
||||
org.glassfish:javax.json:1.0.4
|
||||
org.gmetrics:GMetrics:0.7
|
||||
org.hamcrest:hamcrest-core:1.3
|
||||
org.jdom:jdom2:2.0.6
|
||||
@@ -82,4 +91,4 @@ org.sonatype.aether:aether-spi:1.13.1
|
||||
org.sonatype.aether:aether-util:1.13.1
|
||||
org.spockframework:spock-core:1.1-groovy-2.4-rc-4
|
||||
org.vafer:jdependency:2.1.1
|
||||
org.yaml:snakeyaml:1.17
|
||||
org.yaml:snakeyaml:1.21
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
#Tue Jun 18 15:57:55 EDT 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# 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
|
||||
# https://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,
|
||||
|
||||
Vendored
+1
-1
@@ -5,7 +5,7 @@
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem http://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
+4
-6
@@ -28,13 +28,13 @@ module.exports = function(config) {
|
||||
autoWatch: false,
|
||||
files: [
|
||||
'node_modules/google-closure-library/closure/goog/base.js',
|
||||
'core/build/resources/test/**/*_test.js',
|
||||
'core/src/test/javascript/**/*_test.js',
|
||||
{
|
||||
pattern: 'core/build/resources/test/**/!(*_test).js',
|
||||
pattern: 'core/src/test/javascript/**/!(*_test).js',
|
||||
included: false
|
||||
},
|
||||
{
|
||||
pattern: 'core/build/resources/main/**/*.js',
|
||||
pattern: 'core/src/main/javascript/**/*.js',
|
||||
included: false
|
||||
},
|
||||
{
|
||||
@@ -63,9 +63,7 @@ module.exports = function(config) {
|
||||
'node_modules/google-closure-library/closure/goog/deps.js': ['closure', 'closure-deps'],
|
||||
'node_modules/google-closure-library/closure/goog/base.js': ['closure'],
|
||||
'node_modules/google-closure-library/closure/**/*.js': ['closure'],
|
||||
'core/build/resources/test/**/*_test.js': ['closure'],
|
||||
'core/build/resources/test/**/!(*_test).js': ['closure'],
|
||||
'core/build/resources/main/**/*.js': ['closure'],
|
||||
'core/src/*/javascript/**/*.js': ['closure'],
|
||||
'core/build/generated/source/custom/main/**/*.soy.js': ['closure'],
|
||||
'node_modules/soyutils_usegoog.js': ['closure']
|
||||
},
|
||||
|
||||
Generated
+33
-14
@@ -1007,7 +1007,8 @@
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
@@ -1028,12 +1029,14 @@
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@@ -1048,17 +1051,20 @@
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
@@ -1175,7 +1181,8 @@
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
@@ -1187,6 +1194,7 @@
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
@@ -1201,6 +1209,7 @@
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
@@ -1208,12 +1217,14 @@
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
@@ -1232,6 +1243,7 @@
|
||||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
@@ -1312,7 +1324,8 @@
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
@@ -1324,6 +1337,7 @@
|
||||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
@@ -1409,7 +1423,8 @@
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
@@ -1445,6 +1460,7 @@
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
@@ -1464,6 +1480,7 @@
|
||||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
@@ -1507,12 +1524,14 @@
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1935,9 +1954,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
|
||||
"version": "4.17.14",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz",
|
||||
"integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==",
|
||||
"dev": true
|
||||
},
|
||||
"log4js": {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
out/
|
||||
@@ -0,0 +1,49 @@
|
||||
// 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.
|
||||
|
||||
apply plugin: 'java'
|
||||
|
||||
createUberJar('deployJar', 'prober', 'google.registry.monitoring.blackbox.Prober')
|
||||
|
||||
dependencies {
|
||||
def deps = rootProject.dependencyMap
|
||||
|
||||
compile deps['com.google.auto.value:auto-value-annotations']
|
||||
compile deps['com.google.dagger:dagger']
|
||||
compile deps['com.google.flogger:flogger']
|
||||
compile deps['com.google.guava:guava']
|
||||
compile deps['io.netty:netty-buffer']
|
||||
compile deps['io.netty:netty-codec-http']
|
||||
compile deps['io.netty:netty-codec']
|
||||
compile deps['io.netty:netty-common']
|
||||
compile deps['io.netty:netty-handler']
|
||||
compile deps['io.netty:netty-transport']
|
||||
compile deps['javax.inject:javax.inject']
|
||||
|
||||
runtime deps['com.google.flogger:flogger-system-backend']
|
||||
runtime deps['com.google.auto.value:auto-value']
|
||||
runtime deps['io.netty:netty-tcnative-boringssl-static']
|
||||
|
||||
testCompile deps['com.google.truth:truth']
|
||||
testCompile deps['junit:junit']
|
||||
testCompile deps['org.mockito:mockito-core']
|
||||
testCompile project(':third_party')
|
||||
|
||||
// Include auto-value in compile until nebula-lint understands
|
||||
// annotationProcessor
|
||||
annotationProcessor deps['com.google.auto.value:auto-value']
|
||||
testAnnotationProcessor deps['com.google.auto.value:auto-value']
|
||||
annotationProcessor deps['com.google.dagger:dagger-compiler']
|
||||
testAnnotationProcessor deps['com.google.dagger:dagger-compiler']
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// 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.monitoring.blackbox;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import javax.inject.Provider;
|
||||
|
||||
/**
|
||||
* {@link AutoValue} class that stores all unchanged variables necessary for type of connection
|
||||
*/
|
||||
@AutoValue
|
||||
public abstract class Protocol {
|
||||
|
||||
abstract String name();
|
||||
|
||||
public abstract int port();
|
||||
|
||||
/** The {@link ChannelHandler} providers to use for the protocol, in order. */
|
||||
abstract ImmutableList<Provider<? extends ChannelHandler>> handlerProviders();
|
||||
|
||||
/** Boolean that notes if connection associated with Protocol is persistent.*/
|
||||
abstract boolean persistentConnection();
|
||||
|
||||
public abstract Builder toBuilder();
|
||||
|
||||
public static Builder builder() {
|
||||
return new AutoValue_Protocol.Builder();
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
public static abstract class Builder {
|
||||
|
||||
public abstract Builder name(String value);
|
||||
|
||||
public abstract Builder port(int num);
|
||||
|
||||
public abstract Builder handlerProviders(ImmutableList<Provider<? extends ChannelHandler>> providers);
|
||||
|
||||
public abstract Builder persistentConnection(boolean value);
|
||||
|
||||
public abstract Protocol build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// 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.monitoring.blackbox.handlers;
|
||||
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.monitoring.blackbox.messages.InboundMessageType;
|
||||
import google.registry.monitoring.blackbox.messages.OutboundMessageType;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
|
||||
/**
|
||||
*Superclass of all {@link ChannelHandler}s placed at end of channel pipeline
|
||||
*
|
||||
* <p> {@code ActionHandler} inherits from {@link SimpleChannelInboundHandler< InboundMessageType >}, as it should only be passed in
|
||||
* messages that implement the {@link InboundMessageType} interface. </p>
|
||||
*
|
||||
* <p> The {@code ActionHandler} skeleton exists for a few main purposes. First, it returns a {@link ChannelPromise},
|
||||
* which informs the {@link ProbingAction} in charge that a response has been read. Second, it stores the {@link OutboundMessageType}
|
||||
* passed down the pipeline, so that subclasses can use that information for their own processes. Lastly, with any exception
|
||||
* thrown, the connection is closed, and the ProbingAction governing this channel is informed of the error. Subclasses
|
||||
* specify further work to be done for specific kinds of channel pipelines. </p>
|
||||
*/
|
||||
public abstract class ActionHandler extends SimpleChannelInboundHandler<InboundMessageType> {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
protected ChannelPromise finished;
|
||||
|
||||
/** Takes in {@link OutboundMessageType} type and saves for subclasses. Then returns initialized {@link ChannelPromise}*/
|
||||
public ChannelFuture getFuture() {
|
||||
return finished;
|
||||
}
|
||||
|
||||
/** Initializes new {@link ChannelPromise} */
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) {
|
||||
//Once handler is added to channel pipeline, initialize channel and future for this handler
|
||||
finished = ctx.newPromise();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead0(ChannelHandlerContext ctx, InboundMessageType inboundMessage) throws Exception {
|
||||
//simply marks finished as success
|
||||
finished.setSuccess();
|
||||
}
|
||||
|
||||
/** Logs the channel and pipeline that caused error, closes channel, then informs {@link ProbingAction} listeners of error */
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
logger.atSevere().withCause(cause).log(String.format(
|
||||
"Attempted Action was unsuccessful with channel: %s, having pipeline: %s",
|
||||
ctx.channel().toString(),
|
||||
ctx.channel().pipeline().toString()));
|
||||
|
||||
finished.setFailure(cause);
|
||||
ChannelFuture closedFuture = ctx.channel().close();
|
||||
closedFuture.addListener(f -> logger.atInfo().log("Unsuccessful channel connection closed"));
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user