diff options
author | Bjørn Christian Seime <bjorncs@vespa.ai> | 2023-10-13 15:25:47 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@vespa.ai> | 2023-10-16 10:23:06 +0200 |
commit | 4e98a3c331bb2b036c7a64f40fbf4251063294c1 (patch) | |
tree | dfe6e6b2928ccfda1735099cbacb97b0f19e7a1f | |
parent | 697439d4f22f4bd22b7806d57db71f8a39bc3829 (diff) |
Track trial account lifecycle in ZK
2 files changed, 68 insertions, 0 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java index a2a4cf809b1..cef62438a53 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java @@ -111,6 +111,7 @@ public class CuratorDb { private static final Path mailVerificationRoot = root.append("mailVerification"); private static final Path dataPlaneTokenRoot = root.append("dataplaneTokens"); private static final Path certificatePoolRoot = root.append("certificatePool"); + private static final Path trialNotificationsRoot = root.append("trialNotifications"); private final NodeVersionSerializer nodeVersionSerializer = new NodeVersionSerializer(); private final VersionStatusSerializer versionStatusSerializer = new VersionStatusSerializer(nodeVersionSerializer); @@ -816,6 +817,16 @@ public class CuratorDb { return curator.getChildren(certificatePoolRoot).stream().flatMap(id -> readUnassignedCertificate(id).stream()).toList(); } + // -------------- Cloud trial notification -------------------------------- + + public void writeTrialNotifications(TrialNotifications tn) { + curator.set(trialNotificationsRoot, asJson(tn.toSlime())); + } + + public Optional<TrialNotifications> readTrialNotifications() { + return readSlime(trialNotificationsRoot).map(TrialNotifications::fromSlime); + } + // -------------- Paths --------------------------------------------------- private static Path upgradesPerMinutePath() { diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TrialNotifications.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TrialNotifications.java new file mode 100644 index 00000000000..a205e6c4173 --- /dev/null +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TrialNotifications.java @@ -0,0 +1,57 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +package com.yahoo.vespa.hosted.controller.persistence; + +import com.yahoo.config.provision.TenantName; +import com.yahoo.slime.Slime; +import com.yahoo.slime.SlimeUtils; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Logger; + +/** + * @author bjorncs + */ +public record TrialNotifications(List<Status> tenants) { + private static final Logger log = Logger.getLogger(TrialNotifications.class.getName()); + + public TrialNotifications { tenants = List.copyOf(tenants); } + + public record Status(TenantName tenant, State state, Instant lastUpdate) {} + public enum State { SIGNED_UP, MID_CHECK_IN, EXPIRES_SOON, EXPIRES_IMMEDIATELY, EXPIRED, UNKNOWN } + + public Slime toSlime() { + var slime = new Slime(); + var rootCursor = slime.setObject(); + var tenantsCursor = rootCursor.setArray("tenants"); + for (Status t : tenants) { + var tenantCursor = tenantsCursor.addObject(); + tenantCursor.setString("tenant", t.tenant().value()); + tenantCursor.setString("state", t.state().name()); + tenantCursor.setString("lastUpdate", t.lastUpdate().toString()); + } + log.fine(() -> "Generated json '%s' from '%s'".formatted(SlimeUtils.toJson(slime), this)); + return slime; + } + + public static TrialNotifications fromSlime(Slime slime) { + var rootCursor = slime.get(); + var tenantsCursor = rootCursor.field("tenants"); + var tenants = new ArrayList<Status>(); + for (int i = 0; i < tenantsCursor.entries(); i++) { + var tenantCursor = tenantsCursor.entry(i); + var name = TenantName.from(tenantCursor.field("tenant").asString()); + var stateStr = tenantCursor.field("state").asString(); + var state = Arrays.stream(State.values()) + .filter(s -> s.name().equals(stateStr)).findFirst().orElse(State.UNKNOWN); + var lastUpdate = Instant.parse(tenantCursor.field("lastUpdate").asString()); + tenants.add(new Status(name, state, lastUpdate)); + } + var tn = new TrialNotifications(tenants); + log.fine(() -> "Parsed '%s' from '%s'".formatted(tn, SlimeUtils.toJson(slime))); + return tn; + } +} |