aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorn.christian@seime.no>2023-10-25 11:09:03 +0200
committerGitHub <noreply@github.com>2023-10-25 11:09:03 +0200
commit9a0b0d7b2480d125d3ae624c32dd5a8535dbf3d3 (patch)
tree3d1e86d05f9ed596b9552807b9911e0d03d69b29
parent2695d14822d91b0e00c4c46ae4fbdcca707a327f (diff)
parentb914d3e315a421c724f8e5d3e990c4afb86b9475 (diff)
Merge pull request #29089 from vespa-engine/bjorncs/trial-notifications
Bjorncs/trial notifications
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrls.java2
-rw-r--r--controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrlsTest.java1
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirer.java57
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirerTest.java15
4 files changed, 55 insertions, 20 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
index 872cbd67780..82cddb46d9a 100644
--- 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
@@ -38,6 +38,8 @@ public class ConsoleUrls {
return "%s/tenant/%s/account/notifications".formatted(root, tenantName.value());
}
+ public String tenantBilling(TenantName t) { return "%s/tenant/%s/account/billing".formatted(root, t.value()); }
+
public String prodApplicationOverview(TenantName tenantName, ApplicationName applicationName) {
return "%s/tenant/%s/application/%s/prod/instance".formatted(root, tenantName.value(), applicationName.value());
}
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
index 62e79c3be50..259a279671b 100644
--- 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
@@ -31,6 +31,7 @@ class ConsoleUrlsTest {
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/account/billing", urls.tenantBilling(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));
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirer.java
index 9121c139b00..55428e80493 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirer.java
@@ -121,32 +121,22 @@ public class CloudTrialExpirer extends ControllerMaintainer {
// Ignore tenants that are on a paid plan and skip from inclusion in updated data structure
} else if (status == null && "trial".equals(plan) && ageInDays <= 1) {
updatedStatus.add(updatedStatus(tenant, now, SIGNED_UP));
- queueNotification(tenant, "Welcome to Vespa Cloud", "Welcome to Vespa Cloud",
- "Welcome to Vespa Cloud! We hope you will enjoy your trial. " +
- "Please reach out to us if you have any questions or feedback.");
+ notifySignup(tenant);
} else if ("none".equals(plan) && !List.of(EXPIRED).contains(state)) {
updatedStatus.add(updatedStatus(tenant, now, EXPIRED));
- queueNotification(tenant, "Your Vespa Cloud trial has expired", "Your Vespa Cloud trial has expired",
- "Your Vespa Cloud trial has expired. " +
- "Please reach out to us if you have any questions or feedback.");
+ notifyExpired(tenant);
} else if ("trial".equals(plan) && ageInDays >= 13
&& !List.of(EXPIRES_IMMEDIATELY, EXPIRED).contains(state)) {
updatedStatus.add(updatedStatus(tenant, now, EXPIRES_IMMEDIATELY));
- queueNotification(tenant, "Your Vespa Cloud trial expires tomorrow", "Your Vespa Cloud trial expires tomorrow",
- "Your Vespa Cloud trial expires tomorrow. " +
- "Please reach out to us if you have any questions or feedback.");
+ notifyExpiresImmediately(tenant);
} else if ("trial".equals(plan) && ageInDays >= 12
&& !List.of(EXPIRES_SOON, EXPIRES_IMMEDIATELY, EXPIRED).contains(state)) {
updatedStatus.add(updatedStatus(tenant, now, EXPIRES_SOON));
- queueNotification(tenant, "Your Vespa Cloud trial expires in 2 days", "Your Vespa Cloud trial expires in 2 days",
- "Your Vespa Cloud trial expires in 2 days. " +
- "Please reach out to us if you have any questions or feedback.");
+ notifyExpiresSoon(tenant);
} else if ("trial".equals(plan) && ageInDays >= 7
&& !List.of(MID_CHECK_IN, EXPIRES_SOON, EXPIRES_IMMEDIATELY, EXPIRED).contains(state)) {
updatedStatus.add(updatedStatus(tenant, now, MID_CHECK_IN));
- queueNotification(tenant, "How is your Vespa Cloud trial going?", "How is your Vespa Cloud trial going?",
- "How is your Vespa Cloud trial going? " +
- "Please reach out to us if you have any questions or feedback.");
+ notifyMidCheckIn(tenant);
} else {
updatedStatus.add(status);
}
@@ -160,6 +150,41 @@ public class CloudTrialExpirer extends ControllerMaintainer {
}
}
+ private void notifySignup(Tenant tenant) {
+ var consoleMsg = "Welcome to Vespa Cloud trial! [Manage plan](%s)".formatted(billingUrl(tenant));
+ queueNotification(tenant, consoleMsg, "Welcome to Vespa Cloud",
+ "Welcome to Vespa Cloud! We hope you will enjoy your trial. " +
+ "Please reach out to us if you have any questions or feedback.");
+ }
+
+ private void notifyMidCheckIn(Tenant tenant) {
+ var consoleMsg = "You're halfway through the **14 day** trial period. [Manage plan](%s)".formatted(billingUrl(tenant));
+ queueNotification(tenant, consoleMsg, "How is your Vespa Cloud trial going?",
+ "How is your Vespa Cloud trial going? " +
+ "Please reach out to us if you have any questions or feedback.");
+ }
+
+ private void notifyExpiresSoon(Tenant tenant) {
+ var consoleMsg = "Your Vespa Cloud trial expires in **2** days. [Manage plan](%s)".formatted(billingUrl(tenant));
+ queueNotification(tenant, consoleMsg, "Your Vespa Cloud trial expires in 2 days",
+ "Your Vespa Cloud trial expires in 2 days. " +
+ "Please reach out to us if you have any questions or feedback.");
+ }
+
+ private void notifyExpiresImmediately(Tenant tenant) {
+ var consoleMsg = "Your Vespa Cloud trial expires **tomorrow**. [Manage plan](%s)".formatted(billingUrl(tenant));
+ queueNotification(tenant, consoleMsg, "Your Vespa Cloud trial expires tomorrow",
+ "Your Vespa Cloud trial expires tomorrow. " +
+ "Please reach out to us if you have any questions or feedback.");
+ }
+
+ private void notifyExpired(Tenant tenant) {
+ var consoleMsg = "Your Vespa Cloud trial has expired. [Upgrade plan](%s)".formatted(billingUrl(tenant));
+ queueNotification(tenant, consoleMsg, "Your Vespa Cloud trial has expired",
+ "Your Vespa Cloud trial has expired. " +
+ "Please reach out to us if you have any questions or feedback.");
+ }
+
private void queueNotification(Tenant tenant, String consoleMsg, String emailSubject, String emailMsg) {
var mail = Optional.of(Notification.MailContent.fromTemplate(MailTemplating.Template.DEFAULT_MAIL_CONTENT)
.subject(emailSubject)
@@ -175,6 +200,8 @@ public class CloudTrialExpirer extends ControllerMaintainer {
source, Notification.Type.account, Notification.Level.info, consoleMsg, List.of(), mail);
}
+ private String billingUrl(Tenant t) { return controller().serviceRegistry().consoleUrls().tenantBilling(t.name()); }
+
private static TrialNotifications.Status updatedStatus(Tenant t, Instant i, TrialNotifications.State s) {
return new TrialNotifications.Status(t.name(), s, i);
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirerTest.java
index 07ce2e415a7..4056459c532 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirerTest.java
@@ -110,27 +110,32 @@ public class CloudTrialExpirerTest {
.withBooleanFlag(Flags.CLOUD_TRIAL_NOTIFICATIONS.id(), true);
registerTenant(tenant.value(), "trial", Duration.ZERO);
assertEquals(0.0, expirer.maintain());
- assertEquals("Welcome to Vespa Cloud", lastAccountLevelNotificationTitle(tenant));
+ var expected = "Welcome to Vespa Cloud trial! [Manage plan](https://console.tld/tenant/trial-tenant/account/billing)";
+ assertEquals(expected, lastAccountLevelNotificationTitle(tenant));
assertLastEmailEquals(mailer, "welcome.html");
+ expected = "You're halfway through the **14 day** trial period. [Manage plan](https://console.tld/tenant/trial-tenant/account/billing)";
clock.advance(Duration.ofDays(7));
assertEquals(0.0, expirer.maintain());
- assertEquals("How is your Vespa Cloud trial going?", lastAccountLevelNotificationTitle(tenant));
+ assertEquals(expected, lastAccountLevelNotificationTitle(tenant));
assertLastEmailEquals(mailer, "trial-reminder.html");
+ expected = "Your Vespa Cloud trial expires in **2** days. [Manage plan](https://console.tld/tenant/trial-tenant/account/billing)";
clock.advance(Duration.ofDays(5));
assertEquals(0.0, expirer.maintain());
- assertEquals("Your Vespa Cloud trial expires in 2 days", lastAccountLevelNotificationTitle(tenant));
+ assertEquals(expected, lastAccountLevelNotificationTitle(tenant));
assertLastEmailEquals(mailer, "trial-expiring-soon.html");
+ expected = "Your Vespa Cloud trial expires **tomorrow**. [Manage plan](https://console.tld/tenant/trial-tenant/account/billing)";
clock.advance(Duration.ofDays(1));
assertEquals(0.0, expirer.maintain());
- assertEquals("Your Vespa Cloud trial expires tomorrow", lastAccountLevelNotificationTitle(tenant));
+ assertEquals(expected, lastAccountLevelNotificationTitle(tenant));
assertLastEmailEquals(mailer, "trial-expiring-immediately.html");
+ expected = "Your Vespa Cloud trial has expired. [Upgrade plan](https://console.tld/tenant/trial-tenant/account/billing)";
clock.advance(Duration.ofDays(2));
assertEquals(0.0, expirer.maintain());
- assertEquals("Your Vespa Cloud trial has expired", lastAccountLevelNotificationTitle(tenant));
+ assertEquals(expected, lastAccountLevelNotificationTitle(tenant));
assertLastEmailEquals(mailer, "trial-expired.html");
}