diff options
author | Bjørn Christian Seime <bjorn.christian@seime.no> | 2023-10-25 11:09:03 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-25 11:09:03 +0200 |
commit | 9a0b0d7b2480d125d3ae624c32dd5a8535dbf3d3 (patch) | |
tree | 3d1e86d05f9ed596b9552807b9911e0d03d69b29 | |
parent | 2695d14822d91b0e00c4c46ae4fbdcca707a327f (diff) | |
parent | b914d3e315a421c724f8e5d3e990c4afb86b9475 (diff) |
Merge pull request #29089 from vespa-engine/bjorncs/trial-notifications
Bjorncs/trial notifications
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"); } |