aboutsummaryrefslogtreecommitdiffstats
path: root/controller-api
diff options
context:
space:
mode:
authorValerij Fredriksen <valerijf@yahooinc.com>2023-10-22 21:05:14 +0200
committerValerij Fredriksen <valerijf@yahooinc.com>2023-10-23 11:58:19 +0200
commitdeeaaa25850bf36c9c73840290c8686a40843756 (patch)
tree3636d5d677b1327342dda26f67532432a4107cfc /controller-api
parent863ae59568e80256cb2ba28a15900694b5885451 (diff)
Create service to generate Console URLs
Diffstat (limited to 'controller-api')
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrls.java87
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java4
-rw-r--r--controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrlsTest.java43
3 files changed, 133 insertions, 1 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrls.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrls.java
new file mode 100644
index 00000000000..872cbd67780
--- /dev/null
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrls.java
@@ -0,0 +1,87 @@
+// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.controller.api.integration;
+
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.ApplicationName;
+import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.TenantName;
+import com.yahoo.config.provision.zone.ZoneId;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
+
+import java.net.URI;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Generates URLs to various views in the Console. Prefer to create new methods and return
+ * String instead of URI to make it easier to track which views are linked from where.
+ *
+ * @author freva
+ */
+public class ConsoleUrls {
+ private final String root;
+ public ConsoleUrls(URI root) {
+ this.root = root.toString().replaceFirst("/$", ""); // Remove trailing slash
+ }
+
+ public String root() {
+ return root;
+ }
+
+ public String tenantOverview(TenantName tenantName) {
+ return "%s/tenant/%s".formatted(root, tenantName.value());
+ }
+
+ /** Returns URL to notification settings view for the given tenant */
+ public String tenantNotifications(TenantName tenantName) {
+ return "%s/tenant/%s/account/notifications".formatted(root, tenantName.value());
+ }
+
+ public String prodApplicationOverview(TenantName tenantName, ApplicationName applicationName) {
+ return "%s/tenant/%s/application/%s/prod/instance".formatted(root, tenantName.value(), applicationName.value());
+ }
+
+ public String instanceOverview(ApplicationId application, Environment environment) {
+ return "%s/tenant/%s/application/%s/%s/instance/%s".formatted(root,
+ application.tenant().value(),
+ application.application().value(),
+ environment.isManuallyDeployed() ? environment.value() : "prod",
+ application.instance().value());
+ }
+
+ public String clusterOverview(ApplicationId application, ZoneId zone, ClusterSpec.Id clusterId) {
+ return cluster(application, zone, clusterId, null);
+ }
+
+ public String clusterReindexing(ApplicationId application, ZoneId zone, ClusterSpec.Id clusterId) {
+ return cluster(application, zone, clusterId, "reindexing");
+ }
+
+ public String deploymentRun(RunId id) {
+ return "%s/job/%s/run/%s".formatted(
+ instanceOverview(id.application(), id.type().environment()), id.type().jobName(), id.number());
+ }
+
+ /** Returns URL used to request support from the Vespa team. */
+ public String support() {
+ return root + "/support";
+ }
+
+ /** Returns URL to verify an email address with the given verification code */
+ public String verifyEmail(String verifyCode) {
+ return "%s/verify?%s".formatted(root, queryParam("code", verifyCode));
+ }
+
+ public String termsOfService() { return root + "/terms-of-service-trial.html"; }
+
+ private String cluster(ApplicationId application, ZoneId zone, ClusterSpec.Id clusterId, String viewOrNull) {
+ return instanceOverview(application, zone.environment()) + '?' +
+ queryParam("%s.%s.%s".formatted(application.instance().value(), zone.environment().value(), zone.region().value()),
+ "clusters," + clusterId.value() + (viewOrNull == null ? "" : '=' + viewOrNull));
+ }
+
+ private static String queryParam(String key, String value) {
+ return URLEncoder.encode(key, StandardCharsets.UTF_8) + '=' + URLEncoder.encode(value, StandardCharsets.UTF_8);
+ }
+}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java
index 0eead322df5..e39a8cf38b7 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java
@@ -32,8 +32,8 @@ import com.yahoo.vespa.hosted.controller.api.integration.organization.OwnershipI
import com.yahoo.vespa.hosted.controller.api.integration.organization.SystemMonitor;
import com.yahoo.vespa.hosted.controller.api.integration.resource.CostReportConsumer;
import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceDatabaseClient;
-import com.yahoo.vespa.hosted.controller.api.integration.secrets.GcpSecretStore;
import com.yahoo.vespa.hosted.controller.api.integration.secrets.EndpointSecretManager;
+import com.yahoo.vespa.hosted.controller.api.integration.secrets.GcpSecretStore;
import com.yahoo.vespa.hosted.controller.api.integration.secrets.TenantSecretService;
import com.yahoo.vespa.hosted.controller.api.integration.user.RoleMaintainer;
import com.yahoo.vespa.hosted.controller.api.integration.vcmr.ChangeRequestClient;
@@ -90,6 +90,8 @@ public interface ServiceRegistry {
ZoneRegistry zoneRegistry();
+ ConsoleUrls consoleUrls();
+
ResourceTagger resourceTagger();
EnclaveAccessService enclaveAccessService();
diff --git a/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrlsTest.java b/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrlsTest.java
new file mode 100644
index 00000000000..62e79c3be50
--- /dev/null
+++ b/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrlsTest.java
@@ -0,0 +1,43 @@
+// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.controller.api.integration;
+
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.zone.ZoneId;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
+import org.junit.jupiter.api.Test;
+
+import java.net.URI;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author freva
+ */
+class ConsoleUrlsTest {
+
+ private final ConsoleUrls urls = new ConsoleUrls(URI.create("https://console.tld/"));
+
+ @Test
+ void urls() {
+ ApplicationId app = ApplicationId.from("t1", "a1", "i1");
+ ZoneId prod = ZoneId.from("prod", "us-north-1");
+ ZoneId dev = ZoneId.from("dev", "eu-west-2");
+ ZoneId test = ZoneId.from("test", "ap-east-3");
+ ClusterSpec.Id cluster = ClusterSpec.Id.from("c1");
+
+ assertEquals("https://console.tld", urls.root());
+ assertEquals("https://console.tld/tenant/t1", urls.tenantOverview(app.tenant()));
+ assertEquals("https://console.tld/tenant/t1/account/notifications", urls.tenantNotifications(app.tenant()));
+ assertEquals("https://console.tld/tenant/t1/application/a1/prod/instance", urls.prodApplicationOverview(app.tenant(), app.application()));
+ assertEquals("https://console.tld/tenant/t1/application/a1/prod/instance/i1", urls.instanceOverview(app, Environment.test));
+ assertEquals("https://console.tld/tenant/t1/application/a1/dev/instance/i1?i1.dev.eu-west-2=clusters%2Cc1", urls.clusterOverview(app, dev, cluster));
+ assertEquals("https://console.tld/tenant/t1/application/a1/prod/instance/i1?i1.prod.us-north-1=clusters%2Cc1%3Dreindexing", urls.clusterReindexing(app, prod, cluster));
+ assertEquals("https://console.tld/tenant/t1/application/a1/prod/instance/i1/job/production-us-north-1/run/1", urls.deploymentRun(new RunId(app, JobType.deploymentTo(prod), 1)));
+ assertEquals("https://console.tld/tenant/t1/application/a1/prod/instance/i1/job/system-test/run/1", urls.deploymentRun(new RunId(app, JobType.deploymentTo(test), 1)));
+ assertEquals("https://console.tld/tenant/t1/application/a1/dev/instance/i1/job/dev-eu-west-2/run/1", urls.deploymentRun(new RunId(app, JobType.deploymentTo(dev), 1)));
+ assertEquals("https://console.tld/verify?code=test123", urls.verifyEmail("test123"));
+ }
+}