diff options
author | Valerij Fredriksen <valerij92@gmail.com> | 2021-01-20 14:08:52 +0100 |
---|---|---|
committer | Valerij Fredriksen <valerij92@gmail.com> | 2021-01-20 14:08:52 +0100 |
commit | 9a768c486a9bbbb9c36f2d218ebf4d8de3dc590f (patch) | |
tree | 3930f41475f69b7fbb3188d2f02f7bf8d815362a /controller-server | |
parent | c68838b159e51eeb6810a1d8689d09f6494a9554 (diff) |
Store last login info in tenant
Diffstat (limited to 'controller-server')
9 files changed, 164 insertions, 30 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java index d27c585050b..e45bda0708e 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java @@ -13,6 +13,7 @@ import com.yahoo.vespa.hosted.controller.api.identifiers.PropertyId; import com.yahoo.vespa.hosted.controller.api.integration.organization.Contact; import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant; import com.yahoo.vespa.hosted.controller.tenant.CloudTenant; +import com.yahoo.vespa.hosted.controller.tenant.LastLoginInfo; import com.yahoo.vespa.hosted.controller.tenant.Tenant; import com.yahoo.vespa.hosted.controller.tenant.TenantInfo; @@ -33,10 +34,12 @@ public abstract class LockedTenant { final TenantName name; final Instant createdAt; + final LastLoginInfo lastLoginInfo; - private LockedTenant(TenantName name, Instant createdAt) { + private LockedTenant(TenantName name, Instant createdAt, LastLoginInfo lastLoginInfo) { this.name = requireNonNull(name); this.createdAt = requireNonNull(createdAt); + this.lastLoginInfo = requireNonNull(lastLoginInfo); } static LockedTenant of(Tenant tenant, Lock lock) { @@ -50,6 +53,8 @@ public abstract class LockedTenant { /** Returns a read-only copy of this */ public abstract Tenant get(); + public abstract LockedTenant with(LastLoginInfo lastLoginInfo); + @Override public String toString() { return "tenant '" + name + "'"; @@ -65,8 +70,8 @@ public abstract class LockedTenant { private final Optional<Contact> contact; private Athenz(TenantName name, AthenzDomain domain, Property property, Optional<PropertyId> propertyId, - Optional<Contact> contact, Instant createdAt) { - super(name, createdAt); + Optional<Contact> contact, Instant createdAt, LastLoginInfo lastLoginInfo) { + super(name, createdAt, lastLoginInfo); this.domain = domain; this.property = property; this.propertyId = propertyId; @@ -74,28 +79,33 @@ public abstract class LockedTenant { } private Athenz(AthenzTenant tenant) { - this(tenant.name(), tenant.domain(), tenant.property(), tenant.propertyId(), tenant.contact(), tenant.createdAt()); + this(tenant.name(), tenant.domain(), tenant.property(), tenant.propertyId(), tenant.contact(), tenant.createdAt(), tenant.lastLoginInfo()); } @Override public AthenzTenant get() { - return new AthenzTenant(name, domain, property, propertyId, contact, createdAt); + return new AthenzTenant(name, domain, property, propertyId, contact, createdAt, lastLoginInfo); } public Athenz with(AthenzDomain domain) { - return new Athenz(name, domain, property, propertyId, contact, createdAt); + return new Athenz(name, domain, property, propertyId, contact, createdAt, lastLoginInfo); } public Athenz with(Property property) { - return new Athenz(name, domain, property, propertyId, contact, createdAt); + return new Athenz(name, domain, property, propertyId, contact, createdAt, lastLoginInfo); } public Athenz with(PropertyId propertyId) { - return new Athenz(name, domain, property, Optional.of(propertyId), contact, createdAt); + return new Athenz(name, domain, property, Optional.of(propertyId), contact, createdAt, lastLoginInfo); } public Athenz with(Contact contact) { - return new Athenz(name, domain, property, propertyId, Optional.of(contact), createdAt); + return new Athenz(name, domain, property, propertyId, Optional.of(contact), createdAt, lastLoginInfo); + } + + @Override + public LockedTenant with(LastLoginInfo lastLoginInfo) { + return new Athenz(name, domain, property, propertyId, contact, createdAt, lastLoginInfo); } } @@ -108,20 +118,20 @@ public abstract class LockedTenant { private final BiMap<PublicKey, Principal> developerKeys; private final TenantInfo info; - private Cloud(TenantName name, Instant createdAt, Optional<Principal> creator, BiMap<PublicKey, Principal> developerKeys, TenantInfo info) { - super(name, createdAt); + private Cloud(TenantName name, Instant createdAt, LastLoginInfo lastLoginInfo, Optional<Principal> creator, BiMap<PublicKey, Principal> developerKeys, TenantInfo info) { + super(name, createdAt, lastLoginInfo); this.developerKeys = ImmutableBiMap.copyOf(developerKeys); this.creator = creator; this.info = info; } private Cloud(CloudTenant tenant) { - this(tenant.name(), tenant.createdAt(), Optional.empty(), tenant.developerKeys(), tenant.info()); + this(tenant.name(), tenant.createdAt(), tenant.lastLoginInfo(), Optional.empty(), tenant.developerKeys(), tenant.info()); } @Override public CloudTenant get() { - return new CloudTenant(name, createdAt, creator, developerKeys, info); + return new CloudTenant(name, createdAt, lastLoginInfo, creator, developerKeys, info); } public Cloud withDeveloperKey(PublicKey key, Principal principal) { @@ -129,17 +139,22 @@ public abstract class LockedTenant { if (keys.containsKey(key)) throw new IllegalArgumentException("Key " + KeyUtils.toPem(key) + " is already owned by " + keys.get(key)); keys.put(key, principal); - return new Cloud(name, createdAt, creator, keys, info); + return new Cloud(name, createdAt, lastLoginInfo, creator, keys, info); } public Cloud withoutDeveloperKey(PublicKey key) { BiMap<PublicKey, Principal> keys = HashBiMap.create(developerKeys); keys.remove(key); - return new Cloud(name, createdAt, creator, keys, info); + return new Cloud(name, createdAt, lastLoginInfo, creator, keys, info); } public Cloud withInfo(TenantInfo newInfo) { - return new Cloud(name, createdAt, creator, developerKeys, newInfo); + return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, newInfo); + } + + @Override + public LockedTenant with(LastLoginInfo lastLoginInfo) { + return new Cloud(name, createdAt, lastLoginInfo, creator, developerKeys, info); } } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java index 79dbcc23299..3b5b01d16aa 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java @@ -18,6 +18,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.organization.Contact; import com.yahoo.vespa.hosted.controller.api.integration.organization.BillingInfo; import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant; import com.yahoo.vespa.hosted.controller.tenant.CloudTenant; +import com.yahoo.vespa.hosted.controller.tenant.LastLoginInfo; import com.yahoo.vespa.hosted.controller.tenant.Tenant; import com.yahoo.vespa.hosted.controller.tenant.TenantInfo; import com.yahoo.vespa.hosted.controller.tenant.TenantInfoAddress; @@ -28,7 +29,9 @@ import java.security.Principal; import java.security.PublicKey; import java.time.Instant; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.function.Supplier; @@ -66,6 +69,7 @@ public class TenantSerializer { private static final String productCodeField = "productCode"; private static final String pemDeveloperKeysField = "pemDeveloperKeys"; private static final String tenantInfoField = "info"; + private static final String lastLoginInfoField = "lastLoginInfo"; public Slime toSlime(Tenant tenant) { Slime slime = new Slime(); @@ -73,6 +77,7 @@ public class TenantSerializer { tenantObject.setString(nameField, tenant.name().value()); tenantObject.setString(typeField, valueOf(tenant.type())); tenantObject.setLong(createdAtField, tenant.createdAt().toEpochMilli()); + toSlime(tenant.lastLoginInfo(), tenantObject.setObject(lastLoginInfoField)); switch (tenant.type()) { case athenz: toSlime((AthenzTenant) tenant, tenantObject); break; @@ -116,6 +121,13 @@ public class TenantSerializer { billingInfoObject.setString(productCodeField, billingInfo.productCode()); } + private void toSlime(LastLoginInfo lastLoginInfo, Cursor lastLoginInfoObject) { + for (LastLoginInfo.UserLevel userLevel: LastLoginInfo.UserLevel.values()) { + lastLoginInfo.get(userLevel).ifPresent(lastLoginAt -> + lastLoginInfoObject.setLong(valueOf(userLevel), lastLoginAt.toEpochMilli())); + } + } + public Tenant tenantFrom(Slime slime, Supplier<Instant> tenantCreateTimeSupplier) { Inspector tenantObject = slime.get(); Tenant.Type type = typeOf(tenantObject.field(typeField).asString()); @@ -134,16 +146,18 @@ public class TenantSerializer { Optional<PropertyId> propertyId = SlimeUtils.optionalString(tenantObject.field(propertyIdField)).map(PropertyId::new); Optional<Contact> contact = contactFrom(tenantObject.field(contactField)); Instant createdAt = SlimeUtils.optionalLong(tenantObject.field(createdAtField)).map(Instant::ofEpochMilli).orElseGet(tenantCreateTimeSupplier); - return new AthenzTenant(name, domain, property, propertyId, contact, createdAt); + LastLoginInfo lastLoginInfo = lastLoginInfoFromSlime(tenantObject.field(lastLoginInfoField)); + return new AthenzTenant(name, domain, property, propertyId, contact, createdAt, lastLoginInfo); } private CloudTenant cloudTenantFrom(Inspector tenantObject, Supplier<Instant> tenantCreateTimeSupplier) { TenantName name = TenantName.from(tenantObject.field(nameField).asString()); Instant createdAt = SlimeUtils.optionalLong(tenantObject.field(createdAtField)).map(Instant::ofEpochMilli).orElseGet(tenantCreateTimeSupplier); + LastLoginInfo lastLoginInfo = lastLoginInfoFromSlime(tenantObject.field(lastLoginInfoField)); Optional<Principal> creator = SlimeUtils.optionalString(tenantObject.field(creatorField)).map(SimplePrincipal::new); BiMap<PublicKey, Principal> developerKeys = developerKeysFromSlime(tenantObject.field(pemDeveloperKeysField)); TenantInfo info = tenantInfoFromSlime(tenantObject.field(tenantInfoField)); - return new CloudTenant(name, createdAt, creator, developerKeys, info); + return new CloudTenant(name, createdAt, lastLoginInfo, creator, developerKeys, info); } private BiMap<PublicKey, Principal> developerKeysFromSlime(Inspector array) { @@ -186,6 +200,13 @@ public class TenantSerializer { .withAddress(tenantInfoAddressFromSlime(billingObject.field("address"))); } + private LastLoginInfo lastLoginInfoFromSlime(Inspector lastLoginInfoObject) { + Map<LastLoginInfo.UserLevel, Instant> lastLoginByUserLevel = new HashMap<>(); + lastLoginInfoObject.traverse((String name, Inspector value) -> + lastLoginByUserLevel.put(userLevelOf(name), Instant.ofEpochMilli(value.asLong()))); + return new LastLoginInfo(lastLoginByUserLevel); + } + void toSlime(TenantInfo info, Cursor parentCursor) { if (info.isEmpty()) return; Cursor infoCursor = parentCursor.setObject("info"); @@ -283,4 +304,22 @@ public class TenantSerializer { default: throw new IllegalArgumentException("Unexpected tenant type '" + type + "'."); } } + + private static LastLoginInfo.UserLevel userLevelOf(String value) { + switch (value) { + case "user": return LastLoginInfo.UserLevel.user; + case "developer": return LastLoginInfo.UserLevel.developer; + case "administrator": return LastLoginInfo.UserLevel.administrator; + default: throw new IllegalArgumentException("Unknown user level '" + value + "'."); + } + } + + private static String valueOf(LastLoginInfo.UserLevel userLevel) { + switch (userLevel) { + case user: return "user"; + case developer: return "developer"; + case administrator: return "administrator"; + default: throw new IllegalArgumentException("Unexpected user level '" + userLevel + "'."); + } + } } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/AthenzTenant.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/AthenzTenant.java index 7c0e78337ee..7fa46031c98 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/AthenzTenant.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/AthenzTenant.java @@ -27,8 +27,8 @@ public class AthenzTenant extends Tenant { * Use {@link #create(TenantName, AthenzDomain, Property, Optional, Instant)}. * */ public AthenzTenant(TenantName name, AthenzDomain domain, Property property, Optional<PropertyId> propertyId, - Optional<Contact> contact, Instant createdAt) { - super(name, createdAt, contact); + Optional<Contact> contact, Instant createdAt, LastLoginInfo lastLoginInfo) { + super(name, createdAt, lastLoginInfo, contact); this.domain = Objects.requireNonNull(domain, "domain must be non-null"); this.property = Objects.requireNonNull(property, "property must be non-null"); this.propertyId = Objects.requireNonNull(propertyId, "propertyId must be non-null"); @@ -62,7 +62,7 @@ public class AthenzTenant extends Tenant { /** Create a new Athenz tenant */ public static AthenzTenant create(TenantName name, AthenzDomain domain, Property property, Optional<PropertyId> propertyId, Instant createdAt) { - return new AthenzTenant(requireName(name), domain, property, propertyId, Optional.empty(), createdAt); + return new AthenzTenant(requireName(name), domain, property, propertyId, Optional.empty(), createdAt, LastLoginInfo.EMPTY); } @Override diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java index 2ed1ddc40e1..5d0bb780c81 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java @@ -23,8 +23,9 @@ public class CloudTenant extends Tenant { private final TenantInfo info; /** Public for the serialization layer — do not use! */ - public CloudTenant(TenantName name, Instant createdAt, Optional<Principal> creator, BiMap<PublicKey, Principal> developerKeys, TenantInfo info) { - super(name, createdAt, Optional.empty()); + public CloudTenant(TenantName name, Instant createdAt, LastLoginInfo lastLoginInfo, Optional<Principal> creator, + BiMap<PublicKey, Principal> developerKeys, TenantInfo info) { + super(name, createdAt, lastLoginInfo, Optional.empty()); this.creator = creator; this.developerKeys = developerKeys; this.info = Objects.requireNonNull(info); @@ -34,6 +35,7 @@ public class CloudTenant extends Tenant { public static CloudTenant create(TenantName tenantName, Instant createdAt, Principal creator) { return new CloudTenant(requireName(tenantName), createdAt, + LastLoginInfo.EMPTY, Optional.ofNullable(creator), ImmutableBiMap.of(), TenantInfo.EMPTY); } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/LastLoginInfo.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/LastLoginInfo.java new file mode 100644 index 00000000000..15f2f97e7d1 --- /dev/null +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/LastLoginInfo.java @@ -0,0 +1,55 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.tenant; + +import java.time.Instant; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +/** + * @author freva + */ +public class LastLoginInfo { + + public static final LastLoginInfo EMPTY = new LastLoginInfo(Map.of()); + + private final Map<UserLevel, Instant> lastLoginByUserLevel; + + public LastLoginInfo(Map<UserLevel, Instant> lastLoginByUserLevel) { + this.lastLoginByUserLevel = Map.copyOf(lastLoginByUserLevel); + } + + public Optional<Instant> get(UserLevel userLevel) { + return Optional.ofNullable(lastLoginByUserLevel.get(userLevel)); + } + + /** + * Returns new instance with updated last login time if the given {@code loginAt} timestamp is after the current + * for the given {@code userLevel}, otherwise returns this + */ + public LastLoginInfo withLastLoginIfLater(UserLevel userLevel, Instant loginAt) { + Instant lastLogin = lastLoginByUserLevel.getOrDefault(userLevel, Instant.EPOCH); + if (loginAt.isAfter(lastLogin)) { + Map<UserLevel, Instant> lastLoginByUserLevel = new HashMap<>(this.lastLoginByUserLevel); + lastLoginByUserLevel.put(userLevel, loginAt); + return new LastLoginInfo(lastLoginByUserLevel); + } + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + LastLoginInfo lastLoginInfo = (LastLoginInfo) o; + return lastLoginByUserLevel.equals(lastLoginInfo.lastLoginByUserLevel); + } + + @Override + public int hashCode() { + return lastLoginByUserLevel.hashCode(); + } + + public enum UserLevel { user, developer, administrator }; +} diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Tenant.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Tenant.java index 7687796c697..f8b54e7eff3 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Tenant.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Tenant.java @@ -17,11 +17,13 @@ public abstract class Tenant { private final TenantName name; private final Instant createdAt; + private final LastLoginInfo lastLoginInfo; private final Optional<Contact> contact; - Tenant(TenantName name, Instant createdAt, Optional<Contact> contact) { + Tenant(TenantName name, Instant createdAt, LastLoginInfo lastLoginInfo, Optional<Contact> contact) { this.name = name; this.createdAt = createdAt; + this.lastLoginInfo = lastLoginInfo; this.contact = contact; } @@ -35,6 +37,11 @@ public abstract class Tenant { return createdAt; } + /** Returns login information for this tenant */ + public LastLoginInfo lastLoginInfo() { + return lastLoginInfo; + } + /** Contact information for this tenant */ public Optional<Contact> contact() { return contact; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java index c26e4db7996..4fcf4f344e3 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java @@ -13,6 +13,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.organization.Contact; import com.yahoo.vespa.hosted.controller.api.role.SimplePrincipal; import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant; import com.yahoo.vespa.hosted.controller.tenant.CloudTenant; +import com.yahoo.vespa.hosted.controller.tenant.LastLoginInfo; import com.yahoo.vespa.hosted.controller.tenant.TenantInfo; import com.yahoo.vespa.hosted.controller.tenant.TenantInfoAddress; import com.yahoo.vespa.hosted.controller.tenant.TenantInfoBillingContact; @@ -21,8 +22,9 @@ import org.junit.Test; import java.net.URI; import java.security.PublicKey; import java.time.Instant; -import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import static org.junit.Assert.assertEquals; @@ -79,7 +81,8 @@ public class TenantSerializerTest { new Property("property1"), Optional.of(new PropertyId("1")), Optional.of(contact()), - Instant.EPOCH); + Instant.EPOCH, + lastLoginInfo(321L, 654L, 987L)); AthenzTenant serialized = (AthenzTenant) serializer.tenantFrom(serializer.toSlime(tenant), () -> { throw new UnsupportedOperationException(); }); assertEquals(tenant.contact(), serialized.contact()); } @@ -88,6 +91,7 @@ public class TenantSerializerTest { public void cloud_tenant() { CloudTenant tenant = new CloudTenant(TenantName.from("elderly-lady"), Instant.ofEpochMilli(1234L), + lastLoginInfo(123L, 456L, null), Optional.of(new SimplePrincipal("foobar-user")), ImmutableBiMap.of(publicKey, new SimplePrincipal("joe"), otherPublicKey, new SimplePrincipal("jane")), @@ -103,6 +107,7 @@ public class TenantSerializerTest { public void cloud_tenant_with_info() { CloudTenant tenant = new CloudTenant(TenantName.from("elderly-lady"), Instant.EPOCH, + lastLoginInfo(null, 789L, 654L), Optional.of(new SimplePrincipal("foobar-user")), ImmutableBiMap.of(publicKey, new SimplePrincipal("joe"), otherPublicKey, new SimplePrincipal("jane")), @@ -156,18 +161,25 @@ public class TenantSerializerTest { assertEquals(fullInfo, roundTripInfo); } - private Contact contact() { + private static Contact contact() { return new Contact( URI.create("http://contact1.test"), URI.create("http://property1.test"), URI.create("http://issue-tracker-1.test"), List.of( - Collections.singletonList("person1"), - Collections.singletonList("person2") + List.of("person1"), + List.of("person2") ), "queue", Optional.empty() ); } + private static LastLoginInfo lastLoginInfo(Long user, Long developer, Long administrator) { + Map<LastLoginInfo.UserLevel, Instant> lastLogins = new HashMap<>(); + Optional.ofNullable(user).map(Instant::ofEpochMilli).ifPresent(i -> lastLogins.put(LastLoginInfo.UserLevel.user, i)); + Optional.ofNullable(developer).map(Instant::ofEpochMilli).ifPresent(i -> lastLogins.put(LastLoginInfo.UserLevel.developer, i)); + Optional.ofNullable(administrator).map(Instant::ofEpochMilli).ifPresent(i -> lastLogins.put(LastLoginInfo.UserLevel.administrator, i)); + return new LastLoginInfo(lastLogins); + } } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java index 32f43f57152..2dfcd331d4f 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java @@ -67,6 +67,7 @@ import com.yahoo.vespa.hosted.controller.routing.GlobalRouting; import com.yahoo.vespa.hosted.controller.security.AthenzCredentials; import com.yahoo.vespa.hosted.controller.security.AthenzTenantSpec; import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant; +import com.yahoo.vespa.hosted.controller.tenant.LastLoginInfo; import com.yahoo.vespa.hosted.controller.versions.VespaVersion; import com.yahoo.yolean.Exceptions; import org.junit.Before; @@ -1237,7 +1238,7 @@ public class ApplicationApiTest extends ControllerContainerTest { // Create legacy tenant name containing underscores tester.controller().curator().writeTenant(new AthenzTenant(TenantName.from("my_tenant"), ATHENZ_TENANT_DOMAIN, - new Property("property1"), Optional.empty(), Optional.empty(), Instant.EPOCH)); + new Property("property1"), Optional.empty(), Optional.empty(), Instant.EPOCH, LastLoginInfo.EMPTY)); // POST (add) a Athenz tenant with dashes duplicates existing one with underscores tester.assertResponse(request("/application/v4/tenant/my-tenant", POST) diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java index d1f8fbebdb6..2183563cb61 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java @@ -17,6 +17,7 @@ import com.yahoo.vespa.hosted.controller.api.role.SimplePrincipal; import com.yahoo.vespa.hosted.controller.application.TenantAndApplicationId; import com.yahoo.vespa.hosted.controller.restapi.ApplicationRequestToDiscFilterRequestWrapper; import com.yahoo.vespa.hosted.controller.tenant.CloudTenant; +import com.yahoo.vespa.hosted.controller.tenant.LastLoginInfo; import com.yahoo.vespa.hosted.controller.tenant.TenantInfo; import org.junit.Before; import org.junit.Test; @@ -69,6 +70,7 @@ public class SignatureFilterTest { tester.curator().writeTenant(new CloudTenant(appId.tenant(), Instant.EPOCH, + LastLoginInfo.EMPTY, Optional.empty(), ImmutableBiMap.of(), TenantInfo.EMPTY)); @@ -110,6 +112,7 @@ public class SignatureFilterTest { // Signed request gets a developer role when a matching developer key is stored for the tenant. tester.curator().writeTenant(new CloudTenant(appId.tenant(), Instant.EPOCH, + LastLoginInfo.EMPTY, Optional.empty(), ImmutableBiMap.of(publicKey, () -> "user"), TenantInfo.EMPTY)); |