mirror of
https://github.com/google/nomulus
synced 2026-07-26 01:53:16 +00:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d30cc202d2 | ||
|
|
0998d5485c | ||
|
|
1bff89085b | ||
|
|
d9d83205c7 |
Generated
+123
@@ -628,6 +628,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/build/node_modules/@types/node": {
|
||||
"version": "25.7.0",
|
||||
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/@types/node/-/node-25.7.0.tgz",
|
||||
"integrity": "sha512-z+pdZyxE+RTQE9AcboAZCb4otwcrvgHD+GlBpPgn0emDVt0ohrTMhAwlr2Wd9nZ+nihhYFxO2pThz3C5qSu2Eg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~7.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/build/node_modules/@vitejs/plugin-basic-ssl": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.1.0.tgz",
|
||||
@@ -641,6 +653,24 @@
|
||||
"vite": "^6.0.0 || ^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/build/node_modules/chokidar": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/chokidar/-/chokidar-5.0.0.tgz",
|
||||
"integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"readdirp": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/build/node_modules/magic-string": {
|
||||
"version": "0.30.21",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
||||
@@ -664,6 +694,22 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/build/node_modules/readdirp": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/readdirp/-/readdirp-5.0.0.tgz",
|
||||
"integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 20.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/build/node_modules/rxjs": {
|
||||
"version": "7.8.2",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
|
||||
@@ -697,6 +743,15 @@
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/build/node_modules/undici-types": {
|
||||
"version": "7.21.0",
|
||||
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/undici-types/-/undici-types-7.21.0.tgz",
|
||||
"integrity": "sha512-w9IMgQrz4O0YN1LtB7K5P63vhlIOvC7opSmouCJ+ZywlPAlO9gIkJ+otk6LvGpAs2wg4econaCz3TvQ9xPoyuQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@angular/build/node_modules/vite": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz",
|
||||
@@ -916,6 +971,24 @@
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/cli/node_modules/chokidar": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/chokidar/-/chokidar-5.0.0.tgz",
|
||||
"integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"readdirp": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/cli/node_modules/cli-spinners": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-3.4.0.tgz",
|
||||
@@ -1019,6 +1092,22 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/cli/node_modules/readdirp": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/readdirp/-/readdirp-5.0.0.tgz",
|
||||
"integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 20.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/cli/node_modules/rxjs": {
|
||||
"version": "7.8.2",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
|
||||
@@ -4606,6 +4695,24 @@
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@schematics/angular/node_modules/chokidar": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/chokidar/-/chokidar-5.0.0.tgz",
|
||||
"integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"readdirp": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@schematics/angular/node_modules/cli-spinners": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-3.4.0.tgz",
|
||||
@@ -4709,6 +4816,22 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/@schematics/angular/node_modules/readdirp": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/readdirp/-/readdirp-5.0.0.tgz",
|
||||
"integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 20.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@schematics/angular/node_modules/rxjs": {
|
||||
"version": "7.8.2",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
|
||||
|
||||
@@ -23,7 +23,11 @@ import { MaterialModule } from './material.module';
|
||||
|
||||
import { BackendService } from './shared/services/backend.service';
|
||||
|
||||
import { provideHttpClient } from '@angular/common/http';
|
||||
import {
|
||||
HttpClientXsrfModule,
|
||||
provideHttpClient,
|
||||
withInterceptorsFromDi,
|
||||
} from '@angular/common/http';
|
||||
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
|
||||
import { BillingInfoComponent } from './billingInfo/billingInfo.component';
|
||||
import {
|
||||
@@ -118,6 +122,10 @@ export class SelectedRegistrarModule {}
|
||||
MaterialModule,
|
||||
SelectedRegistrarModule,
|
||||
SnackBarModule,
|
||||
HttpClientXsrfModule.withOptions({
|
||||
cookieName: 'X-CSRF-Token',
|
||||
headerName: 'X-CSRF-Token',
|
||||
}),
|
||||
],
|
||||
providers: [
|
||||
BackendService,
|
||||
@@ -130,7 +138,7 @@ export class SelectedRegistrarModule {}
|
||||
subscriptSizing: 'dynamic',
|
||||
},
|
||||
},
|
||||
provideHttpClient(),
|
||||
provideHttpClient(withInterceptorsFromDi()),
|
||||
],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
@@ -54,9 +54,15 @@ public class BatchModule {
|
||||
static final int DEFAULT_MAX_QPS = 10;
|
||||
|
||||
@Provides
|
||||
@Parameter("url")
|
||||
static String provideUrl(HttpServletRequest req) {
|
||||
return extractRequiredParameter(req, "url");
|
||||
@Parameter("sender")
|
||||
static String provideSender(HttpServletRequest req) {
|
||||
return extractRequiredParameter(req, "sender");
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Parameter("receiver")
|
||||
static String provideReceiver(HttpServletRequest req) {
|
||||
return extractRequiredParameter(req, "receiver");
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -16,30 +16,32 @@ package google.registry.batch;
|
||||
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.api.services.gmail.Gmail;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import dagger.Lazy;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.groups.GmailClient;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.UrlConnectionService;
|
||||
import google.registry.request.UrlConnectionUtils;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.util.EmailMessage;
|
||||
import google.registry.util.Retrier;
|
||||
import jakarta.inject.Inject;
|
||||
import java.net.URL;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import jakarta.mail.internet.AddressException;
|
||||
import jakarta.mail.internet.InternetAddress;
|
||||
|
||||
/**
|
||||
* Action that executes a canned script specified by the caller.
|
||||
*
|
||||
* <p>This class provides a hook for invoking hard-coded methods. The main use case is to verify in
|
||||
* Sandbox and Production environments new features that depend on environment-specific
|
||||
* configurations. For example, the {@code DelegatedCredential}, which requires correct GWorkspace
|
||||
* configuration, has been tested this way. Since it is a hassle to add or remove endpoints, we keep
|
||||
* this class all the time.
|
||||
* configurations.
|
||||
*
|
||||
* <p>This action can be invoked using the Nomulus CLI command: {@code nomulus -e ${env} curl
|
||||
* --service BACKEND -X POST -u '/_dr/task/executeCannedScript}'}
|
||||
* --service BACKEND -X POST -d 'sender=sender@example.com' -d 'receiver=receiver@example.com' -u
|
||||
* '/_dr/task/executeCannedScript'}
|
||||
*/
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
@@ -50,39 +52,50 @@ import javax.net.ssl.HttpsURLConnection;
|
||||
public class CannedScriptExecutionAction implements Runnable {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@Inject UrlConnectionService urlConnectionService;
|
||||
@Inject Lazy<Gmail> gmail;
|
||||
@Inject Retrier retrier;
|
||||
|
||||
@Inject
|
||||
@Config("isEmailSendingEnabled")
|
||||
boolean isEmailSendingEnabled;
|
||||
|
||||
@Inject Response response;
|
||||
|
||||
@Inject
|
||||
@Parameter("url")
|
||||
String url;
|
||||
@Parameter("sender")
|
||||
String sender;
|
||||
|
||||
@Inject
|
||||
@Parameter("receiver")
|
||||
String receiver;
|
||||
|
||||
@Inject
|
||||
CannedScriptExecutionAction() {}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Integer responseCode = null;
|
||||
String responseContent = null;
|
||||
// For b/510340944, validating a new G Workspace user can send email. Code below can be
|
||||
// removed or changed afterward.
|
||||
try {
|
||||
logger.atInfo().log("Connecting to: %s", url);
|
||||
HttpsURLConnection connection =
|
||||
(HttpsURLConnection) urlConnectionService.createConnection(new URL(url));
|
||||
responseCode = connection.getResponseCode();
|
||||
logger.atInfo().log("Code: %d", responseCode);
|
||||
logger.atInfo().log("Headers: %s", connection.getHeaderFields());
|
||||
responseContent = new String(UrlConnectionUtils.getResponseBytes(connection), UTF_8);
|
||||
logger.atInfo().log("Response: %s", responseContent);
|
||||
logger.atInfo().log("Sending email from %s to %s", sender, receiver);
|
||||
GmailClient gmailClient =
|
||||
new GmailClient(
|
||||
gmail, retrier, isEmailSendingEnabled, sender, sender, new InternetAddress(sender));
|
||||
gmailClient.sendEmail(
|
||||
EmailMessage.newBuilder()
|
||||
.addRecipient(new InternetAddress(receiver))
|
||||
.setSubject(String.format("Email send test from %s", sender))
|
||||
.setBody(String.format("This is a test email sent from %s to %s.", sender, receiver))
|
||||
.build());
|
||||
response.setPayload("Email sent successfully.");
|
||||
} catch (AddressException e) {
|
||||
logger.atWarning().withCause(e).log(
|
||||
"Invalid email address: sender=%s, receiver=%s", sender, receiver);
|
||||
response.setStatus(400);
|
||||
response.setPayload("Invalid email address provided.");
|
||||
} catch (Exception e) {
|
||||
logger.atWarning().withCause(e).log("Connection to %s failed", url);
|
||||
logger.atSevere().withCause(e).log("Failed to send email");
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
if (responseCode != null) {
|
||||
response.setStatus(responseCode);
|
||||
}
|
||||
if (responseContent != null) {
|
||||
response.setPayload(responseContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,8 +56,9 @@ public final class GmailClient {
|
||||
private final InternetAddress outgoingEmailAddressWithUsername;
|
||||
private final InternetAddress replyToEmailAddress;
|
||||
|
||||
// TODO(b/510340944): make package private after feature is rolled out
|
||||
@Inject
|
||||
GmailClient(
|
||||
public GmailClient(
|
||||
Lazy<Gmail> gmail,
|
||||
Retrier retrier,
|
||||
@Config("isEmailSendingEnabled") boolean isEmailSendingEnabled,
|
||||
|
||||
@@ -46,11 +46,8 @@ import google.registry.security.XsrfTokenManager;
|
||||
import google.registry.util.DiffUtils;
|
||||
import google.registry.util.RegistryEnvironment;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -143,14 +140,10 @@ public abstract class ConsoleApiAction implements Runnable {
|
||||
}
|
||||
|
||||
private boolean verifyXSRF(User user) {
|
||||
Optional<Cookie> maybeCookie =
|
||||
Arrays.stream(consoleApiParams.request().getCookies())
|
||||
.filter(c -> XsrfTokenManager.X_CSRF_TOKEN.equals(c.getName()))
|
||||
.findFirst();
|
||||
if (maybeCookie.isEmpty()
|
||||
|| !consoleApiParams
|
||||
.xsrfTokenManager()
|
||||
.validateToken(user.getEmailAddress(), maybeCookie.get().getValue())) {
|
||||
String xsrfToken = consoleApiParams.request().getHeader(XsrfTokenManager.X_CSRF_TOKEN);
|
||||
if (xsrfToken == null
|
||||
|| xsrfToken.isEmpty()
|
||||
|| !consoleApiParams.xsrfTokenManager().validateToken(user.getEmailAddress(), xsrfToken)) {
|
||||
consoleApiParams.response().setStatus(SC_UNAUTHORIZED);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ public class ConsoleUserDataAction extends ConsoleApiAction {
|
||||
XsrfTokenManager.X_CSRF_TOKEN,
|
||||
consoleApiParams.xsrfTokenManager().generateToken(user.getEmailAddress()));
|
||||
xsrfCookie.setSecure(true);
|
||||
xsrfCookie.setPath("/");
|
||||
consoleApiParams.response().addCookie(xsrfCookie);
|
||||
|
||||
JSONObject json =
|
||||
|
||||
@@ -38,14 +38,11 @@ public final class ConsoleApiParamsUtils {
|
||||
new SendEmailUtils(ImmutableList.of("notification@test.example"), gmailClient);
|
||||
XsrfTokenManager xsrfTokenManager =
|
||||
new XsrfTokenManager(new FakeClock(Instant.parse("2020-02-02T01:23:45Z")));
|
||||
String token =
|
||||
xsrfTokenManager.generateToken(authResult.user().map(User::getEmailAddress).orElse(""));
|
||||
when(request.getCookies())
|
||||
.thenReturn(
|
||||
new Cookie[] {
|
||||
new Cookie(
|
||||
XsrfTokenManager.X_CSRF_TOKEN,
|
||||
xsrfTokenManager.generateToken(
|
||||
authResult.user().map(User::getEmailAddress).orElse("")))
|
||||
});
|
||||
.thenReturn(new Cookie[] {new Cookie(XsrfTokenManager.X_CSRF_TOKEN, token)});
|
||||
when(request.getHeader(XsrfTokenManager.X_CSRF_TOKEN)).thenReturn(token);
|
||||
when(request.getRequestURI()).thenReturn("/console/fake-url");
|
||||
return ConsoleApiParams.create(
|
||||
request,
|
||||
|
||||
@@ -12,6 +12,7 @@ spec:
|
||||
metadata:
|
||||
labels:
|
||||
service: backend
|
||||
traffic: backend-all
|
||||
spec:
|
||||
serviceAccountName: nomulus
|
||||
nodeSelector:
|
||||
|
||||
@@ -12,6 +12,7 @@ spec:
|
||||
metadata:
|
||||
labels:
|
||||
service: console
|
||||
traffic: console-all
|
||||
spec:
|
||||
serviceAccountName: nomulus
|
||||
containers:
|
||||
|
||||
@@ -12,6 +12,7 @@ spec:
|
||||
metadata:
|
||||
labels:
|
||||
service: frontend
|
||||
traffic: frontend-all
|
||||
spec:
|
||||
serviceAccountName: nomulus
|
||||
nodeSelector:
|
||||
|
||||
@@ -12,6 +12,7 @@ spec:
|
||||
metadata:
|
||||
labels:
|
||||
service: pubapi
|
||||
traffic: pubapi-all
|
||||
spec:
|
||||
serviceAccountName: nomulus
|
||||
containers:
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
# This Cloud Build job prepares and applies Google Cloud Deploy configurations.
|
||||
# It merges the internal repository and populates stableDeploymentAlertPolicyChecks
|
||||
# in delivery-pipeline.yaml based on environment-specific configuration files.
|
||||
#
|
||||
# To manually trigger a build on GCB, run:
|
||||
# gcloud builds submit --config release/cloudbuild-clouddeploy.yaml --substitutions \
|
||||
# _INTERNAL_REPO_URL=[URL],PROJECT_ID=[PROJECT_ID] ..
|
||||
|
||||
steps:
|
||||
# Check the out internal repo.
|
||||
- name: 'gcr.io/cloud-builders/git'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
git clone https://gerrit.googlesource.com/gcompute-tools
|
||||
sed -i s@/usr/bin/python@/usr/bin/python3@g ./gcompute-tools/git-cookie-authdaemon
|
||||
./gcompute-tools/git-cookie-authdaemon
|
||||
git clone ${_INTERNAL_REPO_URL} nomulus-internal
|
||||
|
||||
# Merge the repos.
|
||||
- name: 'gcr.io/cloud-builders/git'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
shopt -s dotglob
|
||||
rm -rf .git && rm -rf nomulus-internal/.git
|
||||
cp -rf nomulus-internal/* .
|
||||
rm -rf nomulus-internal
|
||||
|
||||
# Populate stableDeploymentAlertPolicyChecks in delivery-pipeline.yaml and variables in targets
|
||||
- name: 'gcr.io/cloud-builders/gcloud'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
for env in crash; do
|
||||
config_file="release/clouddeploy/${env}-config.yaml"
|
||||
if [ -f "$config_file" ]; then
|
||||
echo "Extracting checks from $config_file..."
|
||||
# Extract only the indented block under stableDeploymentAlertPolicyChecks.
|
||||
awk '
|
||||
/^stableDeploymentAlertPolicyChecks:/ { capture = 1; next }
|
||||
capture {
|
||||
if ($0 ~ /^[^[:space:]]/ && $0 != "") { capture = 0; exit }
|
||||
print " " $0
|
||||
}
|
||||
' "$config_file" > checks.tmp
|
||||
|
||||
# Insert the checks where the placeholder is located and remove the placeholder
|
||||
sed -i '/stableDeploymentAlertPolicyChecks/r checks.tmp' release/clouddeploy/delivery-pipeline.yaml
|
||||
sed -i '/stableDeploymentAlertPolicyChecks/d' release/clouddeploy/delivery-pipeline.yaml
|
||||
rm -f checks.tmp
|
||||
|
||||
# Populate variables in target file
|
||||
target_file="release/clouddeploy/${env}-target.yaml"
|
||||
if [ -f "$target_file" ]; then
|
||||
echo "Populating variables in $target_file..."
|
||||
artifact_storage=$(sed -n 's/^artifactStorage: //p' "$config_file")
|
||||
service_account=$(sed -n 's/^serviceAccount: //p' "$config_file")
|
||||
cluster_val=$(sed -n 's/^cluster: //p' "$config_file")
|
||||
|
||||
sed -i "s|artifactStorage: artifactStorage|artifactStorage: $artifact_storage|" "$target_file"
|
||||
sed -i "s|serviceAccount: serviceAccount|serviceAccount: $service_account|" "$target_file"
|
||||
sed -i "s|cluster: cluster|cluster: $cluster_val|" "$target_file"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Apply Cloud Deploy configuration
|
||||
- name: 'gcr.io/cloud-builders/gcloud'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
for env in crash; do
|
||||
target_file="release/clouddeploy/${env}-target.yaml"
|
||||
if [ -f "$target_file" ]; then
|
||||
echo "Applying target $target_file..."
|
||||
gcloud deploy apply --file="$target_file" --region=us-central1 --project=${PROJECT_ID}
|
||||
fi
|
||||
done
|
||||
echo 'Applying delivery-pipeline.yaml...'
|
||||
gcloud deploy apply --file=release/clouddeploy/delivery-pipeline.yaml --region=us-central1 --project=${PROJECT_ID}
|
||||
|
||||
timeout: 3600s
|
||||
options:
|
||||
machineType: 'E2_HIGHCPU_32'
|
||||
@@ -10,12 +10,30 @@ Defines the `DeliveryPipeline` resource named `deploy-nomulus`. It sets up the s
|
||||
### Target Configurations (e.g., `crash-target.yaml`)
|
||||
Files matching this format define the `Target` resources for Cloud Deploy. They specify the GKE cluster and other environment-specific settings for deployment.
|
||||
|
||||
### Environment Configurations (e.g., `crash-config.yaml`)
|
||||
Configuration files containing environment-specific parameters and SLA-based alert policy checks (such as EPP and RDAP success metrics) used for automated analysis and target population.
|
||||
|
||||
### `skaffold.yaml`
|
||||
Defines the Skaffold configuration used by Cloud Deploy to render and deploy the application manifests.
|
||||
|
||||
## Usage
|
||||
## Automated Configuration and Deployment Process
|
||||
|
||||
You can apply or modify these configurations in Google Cloud by using the `gcloud` CLI. For example:
|
||||
The preparation and application of Cloud Deploy configurations is automated via Cloud Build using `release/cloudbuild-clouddeploy.yaml`.
|
||||
|
||||
When executed, the Cloud Build job performs the following workflow:
|
||||
1. **Repository Merge**: Clones the internal repository (`nomulus-internal`) and merges internal configurations into the workspace.
|
||||
2. **Dynamic Configuration Population**: Reads variables and alert policy checks specified in the configuration file for the environment from the internal repository, populating them into `delivery-pipeline.yaml` and the corresponding target files.
|
||||
3. **Apply Configurations**: Runs `gcloud deploy apply` to register the updated targets and delivery pipeline in Google Cloud Deploy.
|
||||
|
||||
### Manual Execution on Cloud Build
|
||||
To manually trigger this configuration pipeline on Google Cloud Build, run:
|
||||
```bash
|
||||
gcloud builds submit --config release/cloudbuild-clouddeploy.yaml --substitutions _INTERNAL_REPO_URL=[URL],PROJECT_ID=[PROJECT_ID]
|
||||
```
|
||||
|
||||
## Manual Local Usage
|
||||
|
||||
You can also apply or modify rendered configurations directly using the `gcloud` CLI:
|
||||
|
||||
```bash
|
||||
gcloud deploy apply --file=<config-file>.yaml --project=<project-id> --region=<region>
|
||||
|
||||
@@ -13,9 +13,9 @@ executionConfigs:
|
||||
executionTimeout: 3600s
|
||||
defaultPool:
|
||||
# Placeholder: Replace with artifact bucket name.
|
||||
artifactStorage: gs://_artifact_bucket_
|
||||
artifactStorage: artifactStorage
|
||||
# Placeholder: Replace with project number.
|
||||
serviceAccount: _project_number_-compute@developer.gserviceaccount.com
|
||||
serviceAccount: serviceAccount
|
||||
gke:
|
||||
# Placeholder: Replace with project ID, location, and cluster name.
|
||||
cluster: projects/_project_id_/locations/_location_/clusters/_cluster_name_
|
||||
cluster: cluster
|
||||
|
||||
@@ -9,3 +9,11 @@ serialPipeline:
|
||||
- targetId: crash
|
||||
profiles:
|
||||
- crash
|
||||
strategy:
|
||||
standard:
|
||||
analysis:
|
||||
# 10 minutes.
|
||||
duration: 600s
|
||||
googleCloud:
|
||||
alertPolicyChecks:
|
||||
stableDeploymentAlertPolicyChecks
|
||||
|
||||
Reference in New Issue
Block a user