mirror of
https://github.com/google/nomulus
synced 2026-05-17 13:21:48 +00:00
Compare commits
26 Commits
proxy-2019
...
nomulus-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e00f85f60 | ||
|
|
3cc8d83396 | ||
|
|
0a779612f6 | ||
|
|
545a03618b | ||
|
|
bcdacc88d3 | ||
|
|
56b10ea136 | ||
|
|
9479e1e8b9 | ||
|
|
110bd9c057 | ||
|
|
2ae5aba7ff | ||
|
|
b878e5acc1 | ||
|
|
4d0409c924 | ||
|
|
0292887cb9 | ||
|
|
464f6ba90a | ||
|
|
0ab0a8c2e6 | ||
|
|
2cc4e5fa94 | ||
|
|
47a890253e | ||
|
|
b452b0628d | ||
|
|
5dfd96d26d | ||
|
|
e2a673d914 | ||
|
|
bf29d159f9 | ||
|
|
e17cb52bf7 | ||
|
|
7352f9b4a6 | ||
|
|
5da48184f9 | ||
|
|
5bd2ccd210 | ||
|
|
8fd5ab2bec | ||
|
|
30f6113b05 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -100,3 +100,9 @@ nomulus.iws
|
||||
node_modules/**
|
||||
!node_modules/soyutils_usegoog.js
|
||||
/repos/
|
||||
|
||||
# Compiled JS/CSS code
|
||||
core/**/registrar_bin*.js
|
||||
core/**/registrar_dbg*.js
|
||||
core/**/registrar_bin*.css
|
||||
core/**/registrar_dbg*.css
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Nomulus
|
||||
|
||||
| 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/google/nomulus/blob/master/LICENSE)|[](https://sourcegraph.com/github.com/google/nomulus)|
|
||||
| Internal Build | FOSS Build | LGTM | License | Code Search |
|
||||
|----------------|------------|------|---------|-------------|
|
||||
|[](https://storage.googleapis.com/domain-registry-kokoro/index.html)|[](https://travis-ci.org/google/nomulus)|[](https://lgtm.com/projects/g/google/nomulus/alerts/)|[](https://github.com/google/nomulus/blob/master/LICENSE)|[](https://sourcegraph.com/github.com/google/nomulus)|
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -75,6 +75,12 @@ if (project.path == ":services:default") {
|
||||
|
||||
appengine {
|
||||
deploy {
|
||||
// appengineDeployAll task requires the version to be set. So,
|
||||
// this config lets gcloud select a version name when deploying
|
||||
// to alpha from our workstation.
|
||||
if (environment != 'production' && environment != 'sandbox') {
|
||||
version = 'GCLOUD_CONFIG'
|
||||
}
|
||||
projectId = gcpProject
|
||||
}
|
||||
}
|
||||
|
||||
12
build.gradle
12
build.gradle
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
buildscript {
|
||||
if (project.disableDependencyLocking.toBoolean() == false) {
|
||||
if (rootProject.enableDependencyLocking.toBoolean()) {
|
||||
// Lock buildscript dependencies.
|
||||
configurations.classpath {
|
||||
resolutionStrategy.activateDependencyLocking()
|
||||
@@ -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,7 +75,7 @@ reportUploader {
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
apply from: 'dependency_license.gradle'
|
||||
apply from: 'dependency_lic.gradle'
|
||||
|
||||
// Custom task to run checkLicense in buildSrc, which is not triggered
|
||||
// by root project tasks. A shell task is used because buildSrc tasks
|
||||
@@ -165,7 +169,7 @@ subprojects {
|
||||
}
|
||||
}
|
||||
|
||||
if (rootProject.disableDependencyLocking.toBoolean() == false) {
|
||||
if (rootProject.enableDependencyLocking.toBoolean()) {
|
||||
buildscript {
|
||||
// Lock buildscript dependencies.
|
||||
configurations.classpath {
|
||||
@@ -173,7 +177,7 @@ subprojects {
|
||||
}
|
||||
}
|
||||
// Lock application dependencies except for the gradle-license-report
|
||||
// plugin. See dependency_license.gradle for more information.
|
||||
// plugin. See dependency_lic.gradle for more information.
|
||||
configurations.findAll { it.name != 'dependencyLicenseReport' }.each {
|
||||
it.resolutionStrategy.activateDependencyLocking()
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
buildscript {
|
||||
if (rootProject.disableDependencyLocking.toBoolean() == false) {
|
||||
if (project.enableDependencyLocking.toBoolean()) {
|
||||
// Lock buildscript dependencies.
|
||||
configurations.classpath {
|
||||
resolutionStrategy.activateDependencyLocking()
|
||||
@@ -32,7 +32,7 @@ plugins {
|
||||
id 'com.diffplug.gradle.spotless' version '3.18.0'
|
||||
}
|
||||
|
||||
if (rootProject.disableDependencyLocking.toBoolean() == false) {
|
||||
if (rootProject.enableDependencyLocking.toBoolean()) {
|
||||
// Lock application dependencies.
|
||||
dependencyLocking {
|
||||
lockAllConfigurations()
|
||||
@@ -52,7 +52,7 @@ repositories {
|
||||
}
|
||||
|
||||
apply from: '../dependencies.gradle'
|
||||
apply from: '../dependency_license.gradle'
|
||||
apply from: '../dependency_lic.gradle'
|
||||
apply from: '../java_common.gradle'
|
||||
|
||||
sourceSets {
|
||||
|
||||
@@ -1 +1 @@
|
||||
disableDependencyLocking=false
|
||||
enableDependencyLocking=false
|
||||
|
||||
@@ -78,7 +78,7 @@ PRESUBMITS = {
|
||||
r".*Copyright 20\d{2} The Nomulus Authors\. All Rights Reserved\.",
|
||||
("java", "js", "soy", "sql", "py", "sh", "gradle"), {
|
||||
".git", "/build/", "/generated/", "node_modules/",
|
||||
"JUnitBackports.java"
|
||||
"JUnitBackports.java", "registrar_bin.", "registrar_dbg."
|
||||
}, REQUIRED):
|
||||
"File did not include the license header.",
|
||||
|
||||
@@ -148,7 +148,7 @@ PRESUBMITS = {
|
||||
PresubmitCheck(
|
||||
r".*(innerHTML|outerHTML)\s*(=|[+]=)([^=]|$)",
|
||||
"js",
|
||||
{"/node_modules/"},
|
||||
{"/node_modules/", "registrar_bin."},
|
||||
):
|
||||
"Do not assign directly to the dom. Use goog.dom.setTextContent to set"
|
||||
" to plain text, goog.dom.removeChildren to clear, or "
|
||||
@@ -156,14 +156,13 @@ PRESUBMITS = {
|
||||
PresubmitCheck(
|
||||
r".*console\.(log|info|warn|error)",
|
||||
"js",
|
||||
{"/node_modules/", "google/registry/ui/js/util.js"},
|
||||
{"/node_modules/", "google/registry/ui/js/util.js", "registrar_bin."},
|
||||
):
|
||||
"JavaScript files should not include console logging."
|
||||
}
|
||||
|
||||
|
||||
def get_files():
|
||||
result = []
|
||||
for root, dirnames, filenames in os.walk("."):
|
||||
for filename in filenames:
|
||||
yield os.path.join(root, filename)
|
||||
|
||||
@@ -651,5 +651,19 @@ task buildToolImage(dependsOn: nomulus, type: Exec) {
|
||||
commandLine 'docker', 'build', '-t', 'nomulus-tool', '.'
|
||||
}
|
||||
|
||||
task copyJsFilesForTestServer(dependsOn: assemble, type: Copy) {
|
||||
// Unfortunately the test server relies on having some compiled JS/CSS
|
||||
// in place, so copy it over here
|
||||
from "${resourcesDir}/google/registry/ui/"
|
||||
include '**/*.js'
|
||||
include '**/*.css'
|
||||
into "${project.projectDir}/src/main/resources/google/registry/ui/"
|
||||
}
|
||||
|
||||
task runTestServer(dependsOn: copyJsFilesForTestServer, type: JavaExec) {
|
||||
main = 'google.registry.server.RegistryTestServerMain'
|
||||
classpath = sourceSets.test.runtimeClasspath
|
||||
}
|
||||
|
||||
project.build.dependsOn buildToolImage
|
||||
project.build.dependsOn ':stage'
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.config;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import dagger.Module;
|
||||
@@ -68,6 +69,29 @@ public abstract class CredentialModule {
|
||||
return GoogleCredentialsBundle.create(credential);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the default {@link GoogleCredential} from the Google Cloud runtime for G Suite
|
||||
* Drive API.
|
||||
* TODO(b/138195359): Deprecate this credential once we figure out how to use
|
||||
* {@link GoogleCredentials} for G Suite Drive API.
|
||||
*/
|
||||
@GSuiteDriveCredential
|
||||
@Provides
|
||||
@Singleton
|
||||
public static GoogleCredential provideGSuiteDriveCredential(
|
||||
@Config("defaultCredentialOauthScopes") ImmutableList<String> requiredScopes) {
|
||||
GoogleCredential credential;
|
||||
try {
|
||||
credential = GoogleCredential.getApplicationDefault();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (credential.createScopedRequired()) {
|
||||
credential = credential.createScoped(requiredScopes);
|
||||
}
|
||||
return credential;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a {@link GoogleCredentialsBundle} from the service account's JSON key file.
|
||||
*
|
||||
@@ -118,6 +142,13 @@ public abstract class CredentialModule {
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DefaultCredential {}
|
||||
|
||||
|
||||
/** Dagger qualifier for the credential for G Suite Drive API. */
|
||||
@Qualifier
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface GSuiteDriveCredential {}
|
||||
|
||||
/**
|
||||
* Dagger qualifier for a credential from a service account's JSON key, to be used in non-request
|
||||
* threads.
|
||||
|
||||
@@ -894,9 +894,9 @@ public final class RegistryConfig {
|
||||
* @see google.registry.reporting.spec11.Spec11EmailUtils
|
||||
*/
|
||||
@Provides
|
||||
@Config("spec11ReplyToEmailAddress")
|
||||
public static InternetAddress provideSpec11ReplyToEmailAddress(RegistryConfigSettings config) {
|
||||
return parseEmailAddress(config.misc.spec11ReplyToEmailAddress);
|
||||
@Config("spec11OutgoingEmailAddress")
|
||||
public static InternetAddress provideSpec11OutgoingEmailAddress(RegistryConfigSettings config) {
|
||||
return parseEmailAddress(config.misc.spec11OutgoingEmailAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -173,7 +173,7 @@ public class RegistryConfigSettings {
|
||||
public static class Misc {
|
||||
public String sheetExportId;
|
||||
public String alertRecipientEmailAddress;
|
||||
public String spec11ReplyToEmailAddress;
|
||||
public String spec11OutgoingEmailAddress;
|
||||
public int asyncDeleteDelaySeconds;
|
||||
public int transientFailureRetries;
|
||||
}
|
||||
|
||||
@@ -357,9 +357,9 @@ misc:
|
||||
# Address we send alert summary emails to.
|
||||
alertRecipientEmailAddress: email@example.com
|
||||
|
||||
# Address to which the Spec 11 emails to registrars should be replied. This needs
|
||||
# to be a deliverable email address in case the registrars want to contact us.
|
||||
spec11ReplyToEmailAddress: reply-to@example.com
|
||||
# Address from which Spec 11 emails to registrars are sent. This needs
|
||||
# to be a deliverable email address to handle replies from registrars as well.
|
||||
spec11OutgoingEmailAddress: abuse@example.com
|
||||
|
||||
# How long to delay processing of asynchronous deletions. This should always
|
||||
# be longer than eppResourceCachingSeconds, to prevent deleted contacts or
|
||||
|
||||
@@ -13,11 +13,6 @@
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>backend-servlet</servlet-name>
|
||||
<url-pattern>/_dr/task/metrics</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- RDE -->
|
||||
|
||||
<!--
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
|
||||
package google.registry.export;
|
||||
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.services.drive.Drive;
|
||||
import dagger.Component;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule;
|
||||
import google.registry.config.CredentialModule.DefaultCredential;
|
||||
import google.registry.config.CredentialModule.GSuiteDriveCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.config.RegistryConfig.ConfigModule;
|
||||
import google.registry.storage.drive.DriveConnection;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/** Dagger module for Google {@link Drive} service connection objects. */
|
||||
@@ -32,13 +32,13 @@ public final class DriveModule {
|
||||
|
||||
@Provides
|
||||
static Drive provideDrive(
|
||||
@DefaultCredential GoogleCredentialsBundle credentialsBundle,
|
||||
@GSuiteDriveCredential GoogleCredential googleCredential,
|
||||
@Config("projectId") String projectId) {
|
||||
|
||||
return new Drive.Builder(
|
||||
credentialsBundle.getHttpTransport(),
|
||||
credentialsBundle.getJsonFactory(),
|
||||
credentialsBundle.getHttpRequestInitializer())
|
||||
googleCredential.getTransport(),
|
||||
googleCredential.getJsonFactory(),
|
||||
googleCredential)
|
||||
.setApplicationName(projectId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -62,24 +62,6 @@ public class EppMetrics {
|
||||
"count",
|
||||
LABEL_DESCRIPTORS_BY_TLD);
|
||||
|
||||
private static final EventMetric processingTimeByRegistrar =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newEventMetric(
|
||||
"/epp/processing_time",
|
||||
"EPP Processing Time By Registrar",
|
||||
"milliseconds",
|
||||
LABEL_DESCRIPTORS_BY_REGISTRAR,
|
||||
DEFAULT_FITTER);
|
||||
|
||||
private static final EventMetric processingTimeByTld =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newEventMetric(
|
||||
"/epp/processing_time_by_tld",
|
||||
"EPP Processing Time By TLD",
|
||||
"milliseconds",
|
||||
LABEL_DESCRIPTORS_BY_TLD,
|
||||
DEFAULT_FITTER);
|
||||
|
||||
private static final EventMetric requestTime =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newEventMetric(
|
||||
@@ -118,10 +100,7 @@ public class EppMetrics {
|
||||
long processingTime =
|
||||
metric.getEndTimestamp().getMillis() - metric.getStartTimestamp().getMillis();
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -92,27 +92,23 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
@Inject
|
||||
UpdateRegistrarRdapBaseUrlsAction() {}
|
||||
|
||||
private String loginAndGetId(HttpRequestFactory requestFactory, String tld) {
|
||||
try {
|
||||
logger.atInfo().log("Logging in to MoSAPI");
|
||||
HttpRequest request =
|
||||
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGIN_URL, tld)));
|
||||
request.getHeaders().setBasicAuthentication(String.format("%s_ry", tld), password);
|
||||
HttpResponse response = request.execute();
|
||||
private String loginAndGetId(HttpRequestFactory requestFactory, String tld) throws IOException {
|
||||
logger.atInfo().log("Logging in to MoSAPI");
|
||||
HttpRequest request =
|
||||
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGIN_URL, tld)));
|
||||
request.getHeaders().setBasicAuthentication(String.format("%s_ry", tld), password);
|
||||
HttpResponse response = request.execute();
|
||||
|
||||
Optional<HttpCookie> idCookie =
|
||||
HttpCookie.parse(response.getHeaders().getFirstHeaderStringValue("Set-Cookie")).stream()
|
||||
.filter(cookie -> cookie.getName().equals(COOKIE_ID))
|
||||
.findAny();
|
||||
checkState(
|
||||
idCookie.isPresent(),
|
||||
"Didn't get the ID cookie from the login response. Code: %s, headers: %s",
|
||||
response.getStatusCode(),
|
||||
response.getHeaders());
|
||||
return idCookie.get().getValue();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Error logging in to MoSAPI server: " + e.getMessage(), e);
|
||||
}
|
||||
Optional<HttpCookie> idCookie =
|
||||
HttpCookie.parse(response.getHeaders().getFirstHeaderStringValue("Set-Cookie")).stream()
|
||||
.filter(cookie -> cookie.getName().equals(COOKIE_ID))
|
||||
.findAny();
|
||||
checkState(
|
||||
idCookie.isPresent(),
|
||||
"Didn't get the ID cookie from the login response. Code: %s, headers: %s",
|
||||
response.getStatusCode(),
|
||||
response.getHeaders());
|
||||
return idCookie.get().getValue();
|
||||
}
|
||||
|
||||
private void logout(HttpRequestFactory requestFactory, String id, String tld) {
|
||||
@@ -128,9 +124,8 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaIdWithTld(String tld) {
|
||||
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
|
||||
String id = loginAndGetId(requestFactory, tld);
|
||||
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaIdWithTld(
|
||||
String tld, String id, HttpRequestFactory requestFactory) {
|
||||
String content;
|
||||
try {
|
||||
HttpRequest request =
|
||||
@@ -173,11 +168,22 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||
checkArgument(!tlds.isEmpty(), "There must exist at least one REAL TLD.");
|
||||
Throwable finalThrowable = null;
|
||||
for (String tld : tlds) {
|
||||
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
|
||||
String id;
|
||||
try {
|
||||
return getRdapBaseUrlsPerIanaIdWithTld(tld);
|
||||
id = loginAndGetId(requestFactory, tld);
|
||||
} catch (Throwable e) {
|
||||
// Login failures are bad but not unexpected for certain TLDs. We shouldn't store those
|
||||
// but rather should only store useful Throwables.
|
||||
logger.atWarning().log("Error logging in to MoSAPI server: " + e.getMessage(), e);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
return getRdapBaseUrlsPerIanaIdWithTld(tld, id, requestFactory);
|
||||
} catch (Throwable throwable) {
|
||||
logger.atWarning().log(String
|
||||
.format("Error retrieving RDAP urls with TLD %s: %s", tld, throwable.getMessage()));
|
||||
logger.atWarning().log(
|
||||
String.format(
|
||||
"Error retrieving RDAP urls with TLD %s: %s", tld, throwable.getMessage()));
|
||||
finalThrowable = throwable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,22 +59,19 @@ public class Spec11EmailUtils {
|
||||
private final SendEmailService emailService;
|
||||
private final InternetAddress outgoingEmailAddress;
|
||||
private final InternetAddress alertRecipientAddress;
|
||||
private final InternetAddress spec11ReplyToAddress;
|
||||
private final ImmutableList<String> spec11WebResources;
|
||||
private final String registryName;
|
||||
|
||||
@Inject
|
||||
Spec11EmailUtils(
|
||||
SendEmailService emailService,
|
||||
@Config("gSuiteOutgoingEmailAddress") InternetAddress outgoingEmailAddress,
|
||||
@Config("alertRecipientEmailAddress") InternetAddress alertRecipientAddress,
|
||||
@Config("spec11ReplyToEmailAddress") InternetAddress spec11ReplyToAddress,
|
||||
@Config("spec11OutgoingEmailAddress") InternetAddress spec11OutgoingEmailAddress,
|
||||
@Config("spec11WebResources") ImmutableList<String> spec11WebResources,
|
||||
@Config("registryName") String registryName) {
|
||||
this.emailService = emailService;
|
||||
this.outgoingEmailAddress = outgoingEmailAddress;
|
||||
this.outgoingEmailAddress = spec11OutgoingEmailAddress;
|
||||
this.alertRecipientAddress = alertRecipientAddress;
|
||||
this.spec11ReplyToAddress = spec11ReplyToAddress;
|
||||
this.spec11WebResources = spec11WebResources;
|
||||
this.registryName = registryName;
|
||||
}
|
||||
@@ -149,7 +146,7 @@ public class Spec11EmailUtils {
|
||||
.setContentType(MediaType.HTML_UTF_8)
|
||||
.setFrom(outgoingEmailAddress)
|
||||
.addRecipient(getEmailAddressForRegistrar(registrarThreatMatches.clientId()))
|
||||
.setBcc(spec11ReplyToAddress)
|
||||
.setBcc(outgoingEmailAddress)
|
||||
.build());
|
||||
}
|
||||
|
||||
@@ -172,7 +169,7 @@ public class Spec11EmailUtils {
|
||||
ImmutableMap.of(
|
||||
"date", date.toString(),
|
||||
"registry", registryName,
|
||||
"replyToEmail", spec11ReplyToAddress.getAddress(),
|
||||
"replyToEmail", outgoingEmailAddress.getAddress(),
|
||||
"threats", threatMatchMap,
|
||||
"resources", spec11WebResources);
|
||||
renderer.setData(data);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -52,7 +52,7 @@ final class CreateAnchorTenantCommand extends MutatingEppToolCommand {
|
||||
|
||||
@Parameter(
|
||||
names = {"--contact"},
|
||||
description = "Contact ID for the request. This will be used for registrant, admin contact,"
|
||||
description = "Contact ID for the request. This will be used for registrant, admin contact, "
|
||||
+ "and tech contact.",
|
||||
required = true)
|
||||
private String contact;
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
<!doctype html>
|
||||
<meta http-equiv="refresh" content="0;URL=/registrar">
|
||||
<title>Nomulus</title>
|
||||
<body>
|
||||
<body lang="en-US">
|
||||
If this page doesn't change automatically, please go
|
||||
to <a href="/registrar">https://www.registry.google/registrar</a>
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
a:hover, a:focus {
|
||||
text-decoration: underline
|
||||
}
|
||||
|
||||
.whoAreYou {
|
||||
width: 50%;
|
||||
margin: 5em auto;
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
{@param logoutUrl: string}
|
||||
{@param logoFilename: string}
|
||||
{@param productName: string}
|
||||
<div id="kd-googlebar" role="banner">
|
||||
<div id="kd-googlebar" role="banner" lang="en-US">
|
||||
<a class="{css('logo')}" href="/registrar">
|
||||
<img src="/assets/images/{$logoFilename}" alt="{$productName}">
|
||||
</a>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
{param analyticsConfig: $analyticsConfig /}
|
||||
{/call}
|
||||
{call registry.soy.console.googlebar data="all" /}
|
||||
<div id="reg-app">
|
||||
<div id="reg-app" lang="en-US">
|
||||
<div id="reg-appbar" class="{css('kd-appbar')}">
|
||||
<div class="{css('kd-description')}">
|
||||
Accessing <span class="{css('kd-value')}">{$clientId}</span> as{sp}
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.google.api.client.testing.http.MockLowLevelHttpRequest;
|
||||
import com.google.api.client.testing.http.MockLowLevelHttpResponse;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarAddress;
|
||||
import google.registry.model.registry.Registry;
|
||||
@@ -276,6 +277,44 @@ public final class UpdateRegistrarRdapBaseUrlsActionTest extends ShardableTestCa
|
||||
.isEqualTo("Error contacting MosAPI server. Tried TLDs [secondtld, tld]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailureCause_ignoresLoginFailure() {
|
||||
// Login failures aren't particularly interesting so we should log them, but the final
|
||||
// throwable should be some other failure if one existed
|
||||
createTld("secondtld");
|
||||
httpTransport = new TestHttpTransport();
|
||||
action.httpTransport = 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 badListResponse = new MockLowLevelHttpResponse();
|
||||
String badListReply = JSON_LIST_REPLY.substring(50);
|
||||
badListResponse.setContent(badListReply);
|
||||
|
||||
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");
|
||||
|
||||
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(loginResponse);
|
||||
httpTransport.addNextResponse(badListResponse);
|
||||
httpTransport.addNextResponse(logoutResponse);
|
||||
httpTransport.addNextResponse(badLoginResponse);
|
||||
|
||||
assertThat(assertThrows(RuntimeException.class, action::run))
|
||||
.hasCauseThat()
|
||||
.isInstanceOf(JsonSyntaxException.class);
|
||||
}
|
||||
|
||||
private static void addValidResponses(TestHttpTransport httpTransport) {
|
||||
MockLowLevelHttpResponse loginResponse = new MockLowLevelHttpResponse();
|
||||
loginResponse.addHeader(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -87,7 +87,7 @@ public class Spec11EmailUtilsTest {
|
||||
+ "update your abuse contact using your registrar portal account.</p>"
|
||||
+ ""
|
||||
+ "<p>If you have any questions regarding this notice, please contact "
|
||||
+ "my-reply-to@test.com.</p>";
|
||||
+ "abuse@test.com.</p>";
|
||||
private static final String MONTHLY_EMAIL_FORMAT =
|
||||
"Dear registrar partner,"
|
||||
+ ""
|
||||
@@ -117,7 +117,7 @@ public class Spec11EmailUtilsTest {
|
||||
+ "our monthly reporting.</p>"
|
||||
+ ""
|
||||
+ "<p>If you have any questions regarding this notice, please contact "
|
||||
+ "my-reply-to@test.com.</p>";
|
||||
+ "abuse@test.com.</p>";
|
||||
|
||||
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
|
||||
|
||||
@@ -139,9 +139,8 @@ public class Spec11EmailUtilsTest {
|
||||
emailUtils =
|
||||
new Spec11EmailUtils(
|
||||
emailService,
|
||||
new InternetAddress("my-sender@test.com"),
|
||||
new InternetAddress("my-receiver@test.com"),
|
||||
new InternetAddress("my-reply-to@test.com"),
|
||||
new InternetAddress("abuse@test.com"),
|
||||
FAKE_RESOURCES,
|
||||
"Super Cool Registry");
|
||||
|
||||
@@ -164,17 +163,17 @@ public class Spec11EmailUtilsTest {
|
||||
List<EmailMessage> capturedContents = contentCaptor.getAllValues();
|
||||
validateMessage(
|
||||
capturedContents.get(0),
|
||||
"my-sender@test.com",
|
||||
"abuse@test.com",
|
||||
"the.registrar@example.com",
|
||||
Optional.of("my-reply-to@test.com"),
|
||||
Optional.of("abuse@test.com"),
|
||||
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
|
||||
String.format(MONTHLY_EMAIL_FORMAT, "<tr><td>a.com</td><td>MALWARE</td></tr>"),
|
||||
Optional.of(MediaType.HTML_UTF_8));
|
||||
validateMessage(
|
||||
capturedContents.get(1),
|
||||
"my-sender@test.com",
|
||||
"abuse@test.com",
|
||||
"new.registrar@example.com",
|
||||
Optional.of("my-reply-to@test.com"),
|
||||
Optional.of("abuse@test.com"),
|
||||
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
|
||||
String.format(
|
||||
MONTHLY_EMAIL_FORMAT,
|
||||
@@ -182,7 +181,7 @@ public class Spec11EmailUtilsTest {
|
||||
Optional.of(MediaType.HTML_UTF_8));
|
||||
validateMessage(
|
||||
capturedContents.get(2),
|
||||
"my-sender@test.com",
|
||||
"abuse@test.com",
|
||||
"my-receiver@test.com",
|
||||
Optional.empty(),
|
||||
"Spec11 Pipeline Success 2018-07-15",
|
||||
@@ -202,17 +201,17 @@ public class Spec11EmailUtilsTest {
|
||||
List<EmailMessage> capturedMessages = contentCaptor.getAllValues();
|
||||
validateMessage(
|
||||
capturedMessages.get(0),
|
||||
"my-sender@test.com",
|
||||
"abuse@test.com",
|
||||
"the.registrar@example.com",
|
||||
Optional.of("my-reply-to@test.com"),
|
||||
Optional.of("abuse@test.com"),
|
||||
"Super Cool Registry Daily Threat Detector [2018-07-15]",
|
||||
String.format(DAILY_EMAIL_FORMAT, "<tr><td>a.com</td><td>MALWARE</td></tr>"),
|
||||
Optional.of(MediaType.HTML_UTF_8));
|
||||
validateMessage(
|
||||
capturedMessages.get(1),
|
||||
"my-sender@test.com",
|
||||
"abuse@test.com",
|
||||
"new.registrar@example.com",
|
||||
Optional.of("my-reply-to@test.com"),
|
||||
Optional.of("abuse@test.com"),
|
||||
"Super Cool Registry Daily Threat Detector [2018-07-15]",
|
||||
String.format(
|
||||
DAILY_EMAIL_FORMAT,
|
||||
@@ -220,7 +219,7 @@ public class Spec11EmailUtilsTest {
|
||||
Optional.of(MediaType.HTML_UTF_8));
|
||||
validateMessage(
|
||||
capturedMessages.get(2),
|
||||
"my-sender@test.com",
|
||||
"abuse@test.com",
|
||||
"my-receiver@test.com",
|
||||
Optional.empty(),
|
||||
"Spec11 Pipeline Success 2018-07-15",
|
||||
@@ -247,15 +246,15 @@ public class Spec11EmailUtilsTest {
|
||||
List<EmailMessage> capturedContents = contentCaptor.getAllValues();
|
||||
validateMessage(
|
||||
capturedContents.get(0),
|
||||
"my-sender@test.com",
|
||||
"abuse@test.com",
|
||||
"new.registrar@example.com",
|
||||
Optional.of("my-reply-to@test.com"),
|
||||
Optional.of("abuse@test.com"),
|
||||
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
|
||||
String.format(MONTHLY_EMAIL_FORMAT, "<tr><td>c.com</td><td>MALWARE</td></tr>"),
|
||||
Optional.of(MediaType.HTML_UTF_8));
|
||||
validateMessage(
|
||||
capturedContents.get(1),
|
||||
"my-sender@test.com",
|
||||
"abuse@test.com",
|
||||
"my-receiver@test.com",
|
||||
Optional.empty(),
|
||||
"Spec11 Pipeline Success 2018-07-15",
|
||||
@@ -292,17 +291,17 @@ public class Spec11EmailUtilsTest {
|
||||
List<EmailMessage> capturedMessages = contentCaptor.getAllValues();
|
||||
validateMessage(
|
||||
capturedMessages.get(0),
|
||||
"my-sender@test.com",
|
||||
"abuse@test.com",
|
||||
"the.registrar@example.com",
|
||||
Optional.of("my-reply-to@test.com"),
|
||||
Optional.of("abuse@test.com"),
|
||||
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
|
||||
String.format(MONTHLY_EMAIL_FORMAT, "<tr><td>a.com</td><td>MALWARE</td></tr>"),
|
||||
Optional.of(MediaType.HTML_UTF_8));
|
||||
validateMessage(
|
||||
capturedMessages.get(1),
|
||||
"my-sender@test.com",
|
||||
"abuse@test.com",
|
||||
"new.registrar@example.com",
|
||||
Optional.of("my-reply-to@test.com"),
|
||||
Optional.of("abuse@test.com"),
|
||||
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
|
||||
String.format(
|
||||
MONTHLY_EMAIL_FORMAT,
|
||||
@@ -310,7 +309,7 @@ public class Spec11EmailUtilsTest {
|
||||
Optional.of(MediaType.HTML_UTF_8));
|
||||
validateMessage(
|
||||
capturedMessages.get(2),
|
||||
"my-sender@test.com",
|
||||
"abuse@test.com",
|
||||
"my-receiver@test.com",
|
||||
Optional.empty(),
|
||||
"Spec11 Emailing Failure 2018-07-15",
|
||||
@@ -324,7 +323,7 @@ public class Spec11EmailUtilsTest {
|
||||
verify(emailService).sendEmail(contentCaptor.capture());
|
||||
validateMessage(
|
||||
contentCaptor.getValue(),
|
||||
"my-sender@test.com",
|
||||
"abuse@test.com",
|
||||
"my-receiver@test.com",
|
||||
Optional.empty(),
|
||||
"Spec11 Pipeline Alert: 2018-07",
|
||||
|
||||
@@ -41,7 +41,7 @@ public final class RegistryTestServerMain {
|
||||
@Parameter(
|
||||
names = "--mode",
|
||||
description = "UI console debug mode. RAW allows live editing; DEBUG allows rename testing.")
|
||||
private ConsoleDebug mode = ConsoleDebug.RAW;
|
||||
private ConsoleDebug mode = ConsoleDebug.PRODUCTION;
|
||||
|
||||
@Parameter(
|
||||
names = "--address",
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.chrome.ChromeOptions;
|
||||
import org.openqa.selenium.remote.RemoteWebDriver;
|
||||
import org.testcontainers.containers.BindMode;
|
||||
import org.testcontainers.containers.BrowserWebDriverContainer;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.wait.strategy.Wait;
|
||||
|
||||
@@ -41,10 +40,9 @@ class DockerWebDriverRule extends ExternalResource {
|
||||
|
||||
private static URL getWebDriverUrl() {
|
||||
|
||||
// BrowserWebDriverContainer will try and match the version of the Dockerized
|
||||
// browser to whichever version of Selenium is found on the classpath
|
||||
// TODO(#209): Find a way to automatically detect the version of docker image
|
||||
GenericContainer container =
|
||||
new BrowserWebDriverContainer()
|
||||
new GenericContainer("selenium/standalone-chrome:3.141.59-mercury")
|
||||
.withFileSystemBind("/dev/shm", "/dev/shm", BindMode.READ_WRITE)
|
||||
.withExposedPorts(CHROME_DRIVER_SERVICE_PORT)
|
||||
.waitingFor(Wait.forHttp("/").withStartupTimeout(Duration.of(20, ChronoUnit.SECONDS)));
|
||||
|
||||
@@ -4,4 +4,6 @@ uploaderDestination=
|
||||
uploaderCredentialsFile=
|
||||
uploaderMultithreadedUpload=
|
||||
flowDocsFile=
|
||||
disableDependencyLocking=false
|
||||
enableDependencyLocking=true
|
||||
# TODO(b/138857168): Swtich back to Google JDK8 when the fix is released.
|
||||
org.gradle.java.home=/usr/lib/jvm/java-8-openjdk-amd64
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
2
gradlew
vendored
2
gradlew
vendored
@@ -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,
|
||||
|
||||
2
gradlew.bat
vendored
2
gradlew.bat
vendored
@@ -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,
|
||||
|
||||
@@ -16,7 +16,11 @@ apply plugin: 'java'
|
||||
|
||||
createUberJar('deployJar', 'proxy_server', 'google.registry.proxy.ProxyServer')
|
||||
|
||||
project.build.dependsOn deployJar
|
||||
task buildProxyImage(dependsOn: deployJar, type: Exec) {
|
||||
commandLine 'docker', 'build', '-t', 'proxy', '.'
|
||||
}
|
||||
|
||||
project.build.dependsOn buildProxyImage
|
||||
|
||||
dependencies {
|
||||
def deps = rootProject.dependencyMap
|
||||
|
||||
@@ -25,8 +25,6 @@ import com.google.api.services.cloudkms.v1.model.DecryptRequest;
|
||||
import com.google.api.services.storage.Storage;
|
||||
import com.google.auth.oauth2.AccessToken;
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.flogger.LoggerConfig;
|
||||
import com.google.monitoring.metrics.MetricReporter;
|
||||
import dagger.Component;
|
||||
@@ -185,12 +183,6 @@ public class ProxyModule {
|
||||
return Optional.ofNullable(httpsWhoisPort).orElse(config.webWhois.httpsPort);
|
||||
}
|
||||
|
||||
@Provides
|
||||
ImmutableMap<Integer, FrontendProtocol> providePortToProtocolMap(
|
||||
Set<FrontendProtocol> protocolSet) {
|
||||
return Maps.uniqueIndex(protocolSet, Protocol::port);
|
||||
}
|
||||
|
||||
@Provides
|
||||
Environment provideEnvironment() {
|
||||
return env;
|
||||
@@ -359,7 +351,7 @@ public class ProxyModule {
|
||||
})
|
||||
interface ProxyComponent {
|
||||
|
||||
ImmutableMap<Integer, FrontendProtocol> portToProtocolMap();
|
||||
Set<FrontendProtocol> protocols();
|
||||
|
||||
MetricReporter metricReporter();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import static google.registry.proxy.handler.RelayHandler.RELAY_CHANNEL_KEY;
|
||||
import static google.registry.proxy.handler.RelayHandler.writeToRelayChannel;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.monitoring.metrics.MetricReporter;
|
||||
import google.registry.proxy.Protocol.BackendProtocol;
|
||||
@@ -51,28 +51,27 @@ import java.util.concurrent.TimeoutException;
|
||||
import javax.inject.Provider;
|
||||
|
||||
/**
|
||||
* A multi-protocol proxy server that listens on port(s) specified in {@link
|
||||
* ProxyModule.ProxyComponent#portToProtocolMap()} }.
|
||||
* A multi-protocol proxy server that listens for protocols in {@link
|
||||
* ProxyModule.ProxyComponent#protocols()} }.
|
||||
*/
|
||||
public class ProxyServer implements Runnable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
/** Maximum length of the queue of incoming connections. */
|
||||
private static final int MAX_SOCKET_BACKLOG = 128;
|
||||
|
||||
private final ImmutableMap<Integer, FrontendProtocol> portToProtocolMap;
|
||||
private final ImmutableSet<FrontendProtocol> protocols;
|
||||
private final HashMap<Integer, Channel> portToChannelMap = new HashMap<>();
|
||||
private final EventLoopGroup eventGroup = new NioEventLoopGroup();
|
||||
|
||||
ProxyServer(ProxyComponent proxyComponent) {
|
||||
this.portToProtocolMap = proxyComponent.portToProtocolMap();
|
||||
this.protocols = ImmutableSet.copyOf(proxyComponent.protocols());
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link ChannelInitializer} for connections from a client of a certain protocol.
|
||||
*
|
||||
* <p>The {@link #initChannel} method does the following:
|
||||
* <p>The {@link #initChannel(NioSocketChannel)} method does the following:
|
||||
*
|
||||
* <ol>
|
||||
* <li>Determine the {@link FrontendProtocol} of the inbound {@link Channel} from its parent
|
||||
@@ -263,8 +262,9 @@ public class ProxyServer implements Runnable {
|
||||
.childOption(ChannelOption.AUTO_READ, false);
|
||||
|
||||
// Bind to each port specified in portToHandlersMap.
|
||||
portToProtocolMap.forEach(
|
||||
(port, protocol) -> {
|
||||
protocols.forEach(
|
||||
protocol -> {
|
||||
int port = protocol.port();
|
||||
try {
|
||||
// Wait for binding to be established for each listening port.
|
||||
ChannelFuture serverChannelFuture = serverBootstrap.bind(port).sync();
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
# To run the build locally, install cloud-build-local first.
|
||||
# Then run:
|
||||
# cloud-build-local --config=cloudbuild-deploy-beam.yaml --dryrun=false \
|
||||
# --substitutions=TAG_NAME=[TAG],_ENV=[ENV] ..
|
||||
#
|
||||
# This will deploy Beam pipelines to GCS for the PROJECT_ID defined in gcloud
|
||||
# tool.
|
||||
#
|
||||
# To manually trigger a build on GCB, run:
|
||||
# gcloud builds submit --config=cloudbuild-deploy-beam.yaml \
|
||||
# --substitutions=TAG_NAME=[TAG],_ENV=[ENV] ..
|
||||
#
|
||||
# To trigger a build automatically, follow the instructions below and add a trigger:
|
||||
# https://cloud.google.com/cloud-build/docs/running-builds/automate-builds
|
||||
steps:
|
||||
# Pull the latest nomulus.jar to local
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
args:
|
||||
- gsutil
|
||||
- cp
|
||||
- gs://${PROJECT_ID}-deploy/${TAG_NAME}/nomulus.jar
|
||||
- .
|
||||
# Pull the credential for nomulus tool
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
args:
|
||||
- gsutil
|
||||
- cp
|
||||
- gs://${PROJECT_ID}-deploy/secrets/tool-credential.json.enc
|
||||
- .
|
||||
# Decrypt the credential
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
cat tool-credential.json.enc | base64 -d | gcloud kms decrypt \
|
||||
--ciphertext-file=- --plaintext-file=tool-credential.json \
|
||||
--location=global --keyring=nomulus-tool-keyring --key=nomulus-tool-key
|
||||
# Deploy spec11 and invoicing pipeline to GCS
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
java -jar nomulus.jar -e ${_ENV} --credential tool-credential.json \
|
||||
deploy_spec11_pipeline
|
||||
java -jar nomulus.jar -e ${_ENV} --credential tool-credential.json \
|
||||
deploy_invoicing_pipeline
|
||||
timeout: 3600s
|
||||
options:
|
||||
machineType: 'N1_HIGHCPU_8'
|
||||
75
release/cloudbuild-deploy.yaml
Normal file
75
release/cloudbuild-deploy.yaml
Normal file
@@ -0,0 +1,75 @@
|
||||
# To run the build locally, install cloud-build-local first.
|
||||
# Then run:
|
||||
# cloud-build-local --config=cloudbuild-deploy-beam.yaml --dryrun=false \
|
||||
# --substitutions=TAG_NAME=[TAG],_ENV=[ENV] ..
|
||||
#
|
||||
# This will deploy Beam pipelines to GCS for the PROJECT_ID defined in gcloud
|
||||
# tool.
|
||||
#
|
||||
# To manually trigger a build on GCB, run:
|
||||
# gcloud builds submit --config=cloudbuild-deploy-beam.yaml \
|
||||
# --substitutions=TAG_NAME=[TAG],_ENV=[ENV] ..
|
||||
#
|
||||
# To trigger a build automatically, follow the instructions below and add a trigger:
|
||||
# https://cloud.google.com/cloud-build/docs/running-builds/automate-builds
|
||||
steps:
|
||||
# Pull the credential for nomulus tool.
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
args:
|
||||
- gsutil
|
||||
- cp
|
||||
- gs://${PROJECT_ID}-deploy/secrets/tool-credential.json.enc
|
||||
- .
|
||||
# Decrypt the credential.
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
cat tool-credential.json.enc | base64 -d | gcloud kms decrypt \
|
||||
--ciphertext-file=- --plaintext-file=tool-credential.json \
|
||||
--location=global --keyring=nomulus-tool-keyring --key=nomulus-tool-key
|
||||
# Deploy the Spec11 pipeline to GCS.
|
||||
- name: 'gcr.io/${PROJECT_ID}/nomulus-tool:latest'
|
||||
args:
|
||||
- -e
|
||||
- ${_ENV}
|
||||
- --credential
|
||||
- tool-credential.json
|
||||
- deploy_spec11_pipeline
|
||||
# Deploy the invoicing pipeline to GCS.
|
||||
- name: 'gcr.io/${PROJECT_ID}/nomulus-tool:latest'
|
||||
args:
|
||||
- -e
|
||||
- ${_ENV}
|
||||
- --credential
|
||||
- tool-credential.json
|
||||
- deploy_invoicing_pipeline
|
||||
# Deploy the GAE config files.
|
||||
# First authorize the gcloud tool to use the credential json file, then
|
||||
# download and unzip the tarball that contains the relevant config files
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
gcloud auth activate-service-account --key-file=tool-credential.json
|
||||
if [ ${_ENV} == production ]; then
|
||||
project_id="domain-registry"
|
||||
else
|
||||
project_id="domain-registry-${_ENV}"
|
||||
fi
|
||||
gsutil cp gs://${PROJECT_ID}-deploy/${TAG_NAME}/${_ENV}.tar .
|
||||
tar -xvf ${_ENV}.tar
|
||||
# Note that this currently does not work for google.com projects that
|
||||
# we use due to b/137891685. External projects are likely to work.
|
||||
for filename in cron dispatch dos index queue; do
|
||||
gcloud -q --project ${project_id} app deploy \
|
||||
default/WEB-INF/appengine-generated/${filename}.yaml
|
||||
done
|
||||
|
||||
timeout: 3600s
|
||||
options:
|
||||
machineType: 'N1_HIGHCPU_8'
|
||||
@@ -29,20 +29,25 @@ steps:
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
docker tag nomulus-tool gcr.io/${PROJECT_ID}/nomulus-tool:${TAG_NAME}
|
||||
docker push gcr.io/${PROJECT_ID}/nomulus-tool:${TAG_NAME}
|
||||
# Get the tool image digest and substitute in the digest in the tagging yaml file.
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
docker tag nomulus-tool gcr.io/${PROJECT_ID}/nomulus-tool:${TAG_NAME}
|
||||
docker tag nomulus-tool gcr.io/${PROJECT_ID}/nomulus-tool:latest
|
||||
docker push gcr.io/${PROJECT_ID}/nomulus-tool:${TAG_NAME}
|
||||
docker push gcr.io/${PROJECT_ID}/nomulus-tool:latest
|
||||
# Get the tool image digest and substitute in the digest in other GCB files.
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
digest=$(gcloud container images list-tags gcr.io/${PROJECT_ID}/nomulus-tool \
|
||||
--format="get(digest)" --filter="tags = ${TAG_NAME}")
|
||||
sed -i s/'$${_IMAGE}'/nomulus-tool/g release/cloudbuild-tag.yaml
|
||||
sed -i s/':$${TAG_NAME}'/@$digest/g release/cloudbuild-tag.yaml
|
||||
sed -i s/'nomulus-tool:latest'/nomulus-tool@$digest/g release/cloudbuild-deploy-*.yaml
|
||||
# Build and package the deployment files for alpha.
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
args: ['release/build_nomulus_for_env.sh', 'alpha', 'output']
|
||||
@@ -64,7 +69,8 @@ artifacts:
|
||||
- 'output/nomulus.jar'
|
||||
- 'release/cloudbuild-tag.yaml'
|
||||
- 'release/cloudbuild-sync.yaml'
|
||||
- 'release/cloudbuild-beam.yaml'
|
||||
- 'release/cloudbuild-deploy-*.yaml'
|
||||
|
||||
timeout: 3600s
|
||||
options:
|
||||
machineType: 'N1_HIGHCPU_8'
|
||||
|
||||
@@ -13,30 +13,34 @@
|
||||
# To trigger a build automatically, follow the instructions below and add a trigger:
|
||||
# https://cloud.google.com/cloud-build/docs/running-builds/automate-builds
|
||||
steps:
|
||||
# Set permissions correctly. Not sure why it is necessary, but it is.
|
||||
# Build the deploy jar.
|
||||
# Build the proxy docker image.
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
args:
|
||||
- './gradlew'
|
||||
- ':proxy:test'
|
||||
- ':proxy:deployJar'
|
||||
- '-PmavenUrl=https://storage.googleapis.com/domain-registry-maven-repository/maven'
|
||||
- '-PpluginsUrl=https://storage.googleapis.com/domain-registry-maven-repository/plugins'
|
||||
# Build the docker image.
|
||||
- ./gradlew
|
||||
- :proxy:test
|
||||
- :proxy:buildProxyImage
|
||||
- -PmavenUrl=https://storage.googleapis.com/domain-registry-maven-repository/maven
|
||||
- -PpluginsUrl=https://storage.googleapis.com/domain-registry-maven-repository/plugins
|
||||
# Tag and push the image. We can't let Cloud Build's default processing do that for us
|
||||
# because we need to push the image before we can sign it in the following step.
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
args: ['docker', 'build', '--tag', 'gcr.io/${PROJECT_ID}/proxy:${TAG_NAME}', '.']
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
docker tag proxy gcr.io/${PROJECT_ID}/proxy:${TAG_NAME}
|
||||
docker tag proxy gcr.io/${PROJECT_ID}/proxy:latest
|
||||
docker push gcr.io/${PROJECT_ID}/proxy:${TAG_NAME}
|
||||
docker push gcr.io/${PROJECT_ID}/proxy:latest
|
||||
dir: 'proxy'
|
||||
# Push the image. We can't let Cloud Build's default processing do that for us
|
||||
# because we need to push the image before we can sign it in the following
|
||||
# step.
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
args: ['docker', 'push', 'gcr.io/${PROJECT_ID}/proxy:${TAG_NAME}']
|
||||
# Get the image digest, sign it and substitute in the digest in the tagging yaml file.
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
digest=$(gcloud container images list-tags gcr.io/${PROJECT_ID}/proxy \
|
||||
--format="get(digest)" --filter="tags = ${TAG_NAME}")
|
||||
gcloud --project=${PROJECT_ID} alpha container binauthz attestations \
|
||||
|
||||
@@ -24,6 +24,7 @@ steps:
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
git clone https://gerrit.googlesource.com/gcompute-tools
|
||||
./gcompute-tools/git-cookie-authdaemon
|
||||
git clone ${_INTERNAL_REPO_URL} nomulus-internal
|
||||
@@ -33,6 +34,7 @@ steps:
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
git tag ${TAG_NAME}
|
||||
git push origin ${TAG_NAME}
|
||||
dir: 'nomulus-internal'
|
||||
@@ -42,6 +44,7 @@ steps:
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
shopt -s dotglob
|
||||
rm -rf .git && rm -rf nomulus-internal/.git
|
||||
cp -rf nomulus-internal/* .
|
||||
@@ -52,6 +55,7 @@ steps:
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
docker build -t gcr.io/${PROJECT_ID}/builder:${TAG_NAME} .
|
||||
docker tag gcr.io/${PROJECT_ID}/builder:${TAG_NAME} gcr.io/${PROJECT_ID}/builder:latest
|
||||
docker pull gcr.io/distroless/java
|
||||
@@ -73,6 +77,7 @@ steps:
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
builder_digest=$(gcloud container images list-tags gcr.io/${PROJECT_ID}/builder \
|
||||
--format='get(digest)' --filter='tags = ${TAG_NAME}')
|
||||
base_digest=$(gcloud container images list-tags gcr.io/${PROJECT_ID}/base \
|
||||
@@ -83,19 +88,23 @@ steps:
|
||||
sed -i s%distroless/java:debug%${PROJECT_ID}/base-debug@$debug_digest% core/Dockerfile
|
||||
sed -i s/builder:latest/builder@$builder_digest/g release/cloudbuild-proxy.yaml
|
||||
sed -i s/builder:latest/builder@$builder_digest/g release/cloudbuild-nomulus.yaml
|
||||
sed -i s/builder:latest/builder@$builder_digest/g release/cloudbuild-beam.yaml
|
||||
sed -i s/builder:latest/builder@$builder_digest/g release/cloudbuild-deploy.yaml
|
||||
sed -i s/builder:latest/builder@$builder_digest/g release/cloudbuild-sync.yaml
|
||||
sed -i s/builder:latest/builder@$builder_digest/g release/cloudbuild-tag.yaml
|
||||
sed -i s/GCP_PROJECT/${PROJECT_ID}/ proxy/kubernetes/proxy-*.yaml
|
||||
sed -i s/'$${TAG_NAME}'/${TAG_NAME}/g release/cloudbuild-sync.yaml
|
||||
sed -i s/'$${TAG_NAME}'/${TAG_NAME}/g release/cloudbuild-beam.yaml
|
||||
sed -i s/'$${_ENV}'/${_ENV}/g release/cloudbuild-beam.yaml
|
||||
sed -i s/'$${TAG_NAME}'/${TAG_NAME}/g release/cloudbuild-deploy.yaml
|
||||
for environment in alpha crash sandbox production; do
|
||||
sed s/'$${_ENV}'/${environment}/g release/cloudbuild-deploy.yaml \
|
||||
> release/cloudbuild-deploy-${environment}.yaml
|
||||
done
|
||||
# Upload the gradle binary to GCS if it does not exist and point URL in gradle wrapper to it.
|
||||
- name: 'gcr.io/cloud-builders/gsutil'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
gradle_url=$(grep distributionUrl gradle/wrapper/gradle-wrapper.properties \
|
||||
| awk -F = '{print $2}' | sed 's/\\//g')
|
||||
gradle_bin=$(basename $gradle_url)
|
||||
@@ -125,6 +134,7 @@ steps:
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
cp -rf nomulus-release/.git .
|
||||
rm -rf nomulus-release
|
||||
git config --global user.name "Cloud Build"
|
||||
|
||||
@@ -13,12 +13,12 @@ steps:
|
||||
# Rsync the folder.
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
args:
|
||||
- 'gsutil'
|
||||
- '-m'
|
||||
- 'rsync'
|
||||
- '-d'
|
||||
- 'gs://${PROJECT_ID}-deploy/${TAG_NAME}'
|
||||
- 'gs://${PROJECT_ID}-deploy/live'
|
||||
- gsutil
|
||||
- -m
|
||||
- rsync
|
||||
- -d
|
||||
- gs://${PROJECT_ID}-deploy/${TAG_NAME}
|
||||
- gs://${PROJECT_ID}-deploy/live
|
||||
timeout: 3600s
|
||||
options:
|
||||
machineType: 'N1_HIGHCPU_8'
|
||||
|
||||
Reference in New Issue
Block a user