diff options
author | Valerij Fredriksen <valerijf@verizonmedia.com> | 2021-09-27 14:57:08 +0200 |
---|---|---|
committer | Valerij Fredriksen <valerijf@verizonmedia.com> | 2021-09-27 14:57:08 +0200 |
commit | 8f527a35bc80ac3cd936db92d7b3ba4efde2d9ec (patch) | |
tree | aaba30a621487c1f536ec750d496d2baf89ddf25 /controller-server | |
parent | 1e630a4f57ba52f3194895837d2f17b8cbc56ada (diff) | |
parent | c4feaca0cfbf19b18c7b2ced33a1e18f80534b38 (diff) |
Merge branch 'master' into ogronnesby/create-application-on-deploy
Diffstat (limited to 'controller-server')
24 files changed, 89 insertions, 755 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/archive/CuratorArchiveBucketDb.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/archive/CuratorArchiveBucketDb.java index ca173437dd1..a7555307a59 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/archive/CuratorArchiveBucketDb.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/archive/CuratorArchiveBucketDb.java @@ -33,8 +33,6 @@ public class CuratorArchiveBucketDb { * Policy size limit is 20kb, about 550 bytes for non-tenant related policies. Each tenant * needs about 500 + len(role_arn) bytes, we limit role_arn to 100 characters, so we can * fit about (20k - 550) / 600 ~ 32 tenants per bucket. - * - * This limit is only enforced for public systems as non-public systems does not use tenant specific policies. */ private final static int TENANTS_PER_BUCKET = 30; @@ -86,7 +84,7 @@ public class CuratorArchiveBucketDb { .orElseGet(() -> { // If not, find an existing bucket with space Optional<ArchiveBucket> unfilledBucket = zoneBuckets.stream() - .filter(bucket -> !system.isPublic() || bucket.tenants().size() < TENANTS_PER_BUCKET) + .filter(bucket -> bucket.tenants().size() < TENANTS_PER_BUCKET) .findAny(); // And place the tenant in that bucket. diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java index 652f8630cb6..88d440b52b9 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java @@ -518,6 +518,8 @@ public class JobController { type, new Versions(platform.orElse(applicationPackage.deploymentSpec().majorVersion() .flatMap(controller.applications()::lastCompatibleVersion) + .or(() -> lastRun.map(run -> run.versions().targetPlatform()) + .filter(controller.readVersionStatus()::isActive)) .orElseGet(controller::readSystemVersion)), version, lastRun.map(run -> run.versions().targetPlatform()), diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArchiveAccessMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArchiveAccessMaintainer.java index b096a853541..6c4f5ffff9d 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArchiveAccessMaintainer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArchiveAccessMaintainer.java @@ -2,16 +2,25 @@ package com.yahoo.vespa.hosted.controller.maintenance; import com.google.common.collect.Maps; +import com.yahoo.config.provision.TenantName; +import com.yahoo.config.provision.zone.ZoneApi; +import com.yahoo.config.provision.zone.ZoneId; import com.yahoo.jdisc.Metric; +import com.yahoo.vespa.flags.BooleanFlag; +import com.yahoo.vespa.flags.FetchVector; +import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.api.integration.archive.ArchiveService; import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry; import com.yahoo.vespa.hosted.controller.archive.CuratorArchiveBucketDb; +import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant; import com.yahoo.vespa.hosted.controller.tenant.CloudTenant; import com.yahoo.vespa.hosted.controller.tenant.Tenant; import java.time.Duration; +import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -27,6 +36,8 @@ public class ArchiveAccessMaintainer extends ControllerMaintainer { private final ArchiveService archiveService; private final ZoneRegistry zoneRegistry; private final Metric metric; + private final BooleanFlag archiveEnabled; + private final BooleanFlag developerRoleEnabled; public ArchiveAccessMaintainer(Controller controller, Metric metric, Duration interval) { super(controller, interval); @@ -34,6 +45,8 @@ public class ArchiveAccessMaintainer extends ControllerMaintainer { this.archiveService = controller.serviceRegistry().archiveService(); this.zoneRegistry = controller().zoneRegistry(); this.metric = metric; + this.archiveEnabled = Flags.ENABLE_ONPREM_TENANT_S3_ARCHIVE.bindTo(controller().flagSource()); + this.developerRoleEnabled = Flags.ENABLE_TENANT_DEVELOPER_ROLE.bindTo(controller().flagSource()); } @Override @@ -43,22 +56,45 @@ public class ArchiveAccessMaintainer extends ControllerMaintainer { metric.set(bucketCountMetricName, archiveBucketDb.buckets(zoneId).size(), metric.createContext(Map.of("zone", zoneId.value())))); - var tenantArchiveAccessRoles = controller().tenants().asList().stream() - .filter(t -> t instanceof CloudTenant) - .map(t -> (CloudTenant) t) - .filter(t -> t.archiveAccessRole().isPresent()) - .collect(Collectors.toUnmodifiableMap( - Tenant::name, cloudTenant -> cloudTenant.archiveAccessRole().orElseThrow())); - zoneRegistry.zones().controllerUpgraded().ids().forEach(zoneId -> - archiveBucketDb.buckets(zoneId).forEach(archiveBucket -> - archiveService.updateBucketAndKeyPolicy(zoneId, archiveBucket, - Maps.filterEntries(tenantArchiveAccessRoles, - entry -> archiveBucket.tenants().contains(entry.getKey()))) - ) + zoneRegistry.zones().controllerUpgraded().zones().forEach(z -> { + ZoneId zoneId = z.getId(); + var tenantArchiveAccessRoles = tenantArchiveAccessRoles(z); + archiveBucketDb.buckets(zoneId).forEach(archiveBucket -> + archiveService.updateBucketAndKeyPolicy(zoneId, archiveBucket, + Maps.filterEntries(tenantArchiveAccessRoles, + entry -> archiveBucket.tenants().contains(entry.getKey()))) + ); + } ); return 1.0; } + private Map<TenantName, String> tenantArchiveAccessRoles(ZoneApi zone) { + List<Tenant> tenants = controller().tenants().asList(); + if (zoneRegistry.system().isPublic()) { + return tenants.stream() + .filter(t -> t instanceof CloudTenant) + .map(t -> (CloudTenant) t) + .filter(t -> t.archiveAccessRole().isPresent()) + .collect(Collectors.toUnmodifiableMap( + Tenant::name, cloudTenant -> cloudTenant.archiveAccessRole().orElseThrow())); + } else { + return tenants.stream() + .filter(t -> t instanceof AthenzTenant + && enabled(archiveEnabled, t, zone) && enabled(developerRoleEnabled, t, zone)) + .map(Tenant::name) + .collect(Collectors.toUnmodifiableMap( + Function.identity(), t -> zoneRegistry.tenantDeveloperRoleArn(t).orElseThrow())); + + } + } + + private boolean enabled(BooleanFlag flag, Tenant tenant, ZoneApi zone) { + return flag.with(FetchVector.Dimension.TENANT_ID, tenant.name().value()) + .with(FetchVector.Dimension.ZONE_ID, zone.getId().value()) + .value(); + } + } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentUpgrader.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentUpgrader.java index 97e9a233f9f..0bf47f85420 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentUpgrader.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentUpgrader.java @@ -46,7 +46,6 @@ public class DeploymentUpgrader extends ControllerMaintainer { Run last = controller().jobController().last(job).get(); Versions target = new Versions(systemVersion, last.versions().targetApplication(), Optional.of(last.versions().targetPlatform()), Optional.of(last.versions().targetApplication())); if ( ! deployment.version().isBefore(target.targetPlatform())) continue; - if ( controller().clock().instant().isBefore(last.start().plus(Duration.ofDays(1)))) continue; if ( ! isLikelyNightFor(job)) continue; log.log(Level.FINE, "Upgrading deployment of " + instance.id() + " in " + deployment.zone()); diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java index ce6f9c802d6..d2b43dc63d9 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java @@ -27,9 +27,7 @@ public class TenantRoleMaintainer extends ControllerMaintainer { var tenants = controller().tenants().asList(); // Create separate athenz service for all tenants - tenants.stream() - .map(Tenant::name) - .forEach(roleService::createTenantRole); + tenants.forEach(roleService::createTenantRole); // Until we have moved to separate athenz service per tenant, make sure we update the shared policy // to allow ssh logins for hosts in prod/perf with a separate tenant iam role. diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiHandler.java index 6619b2ff5c6..61bf8feae35 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiHandler.java @@ -14,8 +14,6 @@ import com.yahoo.vespa.flags.FetchVector; import com.yahoo.vespa.flags.FlagSource; import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.hosted.controller.Controller; -import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingController; -import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId; import com.yahoo.vespa.hosted.controller.api.integration.horizon.HorizonClient; import com.yahoo.vespa.hosted.controller.api.integration.horizon.HorizonResponse; import com.yahoo.vespa.hosted.controller.api.role.Role; @@ -28,7 +26,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.EnumSet; -import java.util.HashSet; import java.util.Optional; import java.util.Set; import java.util.logging.Level; @@ -41,7 +38,6 @@ import java.util.stream.Collectors; */ public class HorizonApiHandler extends LoggingRequestHandler { - private final BillingController billingController; private final SystemName systemName; private final HorizonClient client; private final BooleanFlag enabledHorizonDashboard; @@ -52,7 +48,6 @@ public class HorizonApiHandler extends LoggingRequestHandler { @Inject public HorizonApiHandler(LoggingRequestHandler.Context parentCtx, Controller controller, FlagSource flagSource) { super(parentCtx); - this.billingController = controller.serviceRegistry().billingController(); this.systemName = controller.system(); this.client = controller.serviceRegistry().horizonClient(); this.enabledHorizonDashboard = Flags.ENABLED_HORIZON_DASHBOARD.bindTo(flagSource); @@ -123,13 +118,11 @@ public class HorizonApiHandler extends LoggingRequestHandler { } private Set<TenantName> getAuthorizedTenants(Set<Role> roles) { - var horizonEnabled = roles.stream() + return roles.stream() .filter(TenantRole.class::isInstance) .map(role -> ((TenantRole) role).tenant()) .filter(tenant -> enabledHorizonDashboard.with(FetchVector.Dimension.TENANT_ID, tenant.value()).value()) - .collect(Collectors.toList()); - - return new HashSet<>(billingController.tenantsWithPlan(horizonEnabled, PlanId.from("pay-as-you-go"))); + .collect(Collectors.toSet()); } private static class JsonInputStreamResponse extends HttpResponse { diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java index 157f57b3bea..7e88f127026 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java @@ -20,10 +20,7 @@ import com.yahoo.slime.SlimeStream; import com.yahoo.slime.SlimeUtils; import com.yahoo.text.Text; import com.yahoo.vespa.configserver.flags.FlagsDb; -import com.yahoo.vespa.flags.BooleanFlag; -import com.yahoo.vespa.flags.FetchVector; import com.yahoo.vespa.flags.FlagSource; -import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.IntFlag; import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.hosted.controller.Controller; @@ -71,9 +68,7 @@ public class UserApiHandler extends LoggingRequestHandler { private final UserManagement users; private final Controller controller; private final FlagsDb flagsDb; - private final BooleanFlag enable_public_signup_flow; private final IntFlag maxTrialTenants; - private final BooleanFlag enabledHorizonDashboard; @Inject public UserApiHandler(Context parentCtx, UserManagement users, Controller controller, FlagSource flagSource, FlagsDb flagsDb) { @@ -81,9 +76,7 @@ public class UserApiHandler extends LoggingRequestHandler { this.users = users; this.controller = controller; this.flagsDb = flagsDb; - this.enable_public_signup_flow = PermanentFlags.ENABLE_PUBLIC_SIGNUP_FLOW.bindTo(flagSource); this.maxTrialTenants = PermanentFlags.MAX_TRIAL_TENANTS.bindTo(flagSource); - this.enabledHorizonDashboard = Flags.ENABLED_HORIZON_DASHBOARD.bindTo(flagSource); } @Override @@ -173,9 +166,6 @@ public class UserApiHandler extends LoggingRequestHandler { root.setBool("isPublic", controller.system().isPublic()); root.setBool("isCd", controller.system().isCd()); - // TODO (freva): Remove after users have migrated to use 'flags' - root.setBool(enable_public_signup_flow.id().toString(), - enable_public_signup_flow.with(FetchVector.Dimension.CONSOLE_USER_EMAIL, user.email()).value()); root.setBool("hasTrialCapacity", hasTrialCapacity()); toSlime(root.setObject("user"), user); @@ -190,10 +180,6 @@ public class UserApiHandler extends LoggingRequestHandler { Cursor tenantRolesObject = tenantObject.setArray("roles"); tenantRolesByTenantName.getOrDefault(tenant, List.of()) .forEach(role -> tenantRolesObject.addString(role.definition().name())); - if (controller.system().isPublic()) { - tenantObject.setBool(enabledHorizonDashboard.id().toString(), - enabledHorizonDashboard.with(FetchVector.Dimension.TENANT_ID, tenant.value()).value()); - } }); if (!operatorRoles.isEmpty()) { 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 deleted file mode 100644 index 7fa46031c98..00000000000 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/AthenzTenant.java +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.controller.tenant; - -import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.athenz.api.AthenzDomain; -import com.yahoo.vespa.hosted.controller.api.identifiers.Property; -import com.yahoo.vespa.hosted.controller.api.identifiers.PropertyId; -import com.yahoo.vespa.hosted.controller.api.integration.organization.Contact; - -import java.time.Instant; -import java.util.Objects; -import java.util.Optional; - -/** - * Represents an Athenz tenant in hosted Vespa. - * - * @author mpolden - */ -public class AthenzTenant extends Tenant { - - private final AthenzDomain domain; - private final Property property; - private final Optional<PropertyId> propertyId; - - /** - * This should only be used by serialization. - * Use {@link #create(TenantName, AthenzDomain, Property, Optional, Instant)}. - * */ - public AthenzTenant(TenantName name, AthenzDomain domain, Property property, Optional<PropertyId> propertyId, - 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"); - } - - /** Property name of this tenant */ - public Property property() { - return property; - } - - /** Property ID of the tenant, if any */ - public Optional<PropertyId> propertyId() { - return propertyId; - } - - /** Athenz domain of this tenant */ - public AthenzDomain domain() { - return domain; - } - - /** Returns true if tenant is in given domain */ - public boolean in(AthenzDomain domain) { - return this.domain.equals(domain); - } - - @Override - public String toString() { - return "athenz tenant '" + name() + "'"; - } - - /** 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, LastLoginInfo.EMPTY); - } - - @Override - public Type type() { - return Type.athenz; - } - -} 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 deleted file mode 100644 index 1060b118beb..00000000000 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.controller.tenant; - -import com.google.common.collect.BiMap; -import com.google.common.collect.ImmutableBiMap; -import com.yahoo.config.provision.TenantName; -import com.yahoo.text.Text; -import com.yahoo.vespa.hosted.controller.api.integration.secrets.TenantSecretStore; - -import java.security.Principal; -import java.security.PublicKey; -import java.time.Instant; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.regex.Pattern; - -/** - * A paying tenant in a Vespa cloud service. - * - * @author jonmv - */ -public class CloudTenant extends Tenant { - - private static final Pattern VALID_ARCHIVE_ACCESS_ROLE_PATTERN = Pattern.compile("arn:aws:iam::\\d{12}:.+"); - - private final Optional<Principal> creator; - private final BiMap<PublicKey, Principal> developerKeys; - private final TenantInfo info; - private final List<TenantSecretStore> tenantSecretStores; - private final Optional<String> archiveAccessRole; - - /** Public for the serialization layer — do not use! */ - public CloudTenant(TenantName name, Instant createdAt, LastLoginInfo lastLoginInfo, Optional<Principal> creator, - BiMap<PublicKey, Principal> developerKeys, TenantInfo info, - List<TenantSecretStore> tenantSecretStores, Optional<String> archiveAccessRole) { - super(name, createdAt, lastLoginInfo, Optional.empty()); - this.creator = creator; - this.developerKeys = developerKeys; - this.info = Objects.requireNonNull(info); - this.tenantSecretStores = tenantSecretStores; - this.archiveAccessRole = archiveAccessRole; - if (!archiveAccessRole.map(role -> VALID_ARCHIVE_ACCESS_ROLE_PATTERN.matcher(role).matches()).orElse(true)) - throw new IllegalArgumentException(Text.format("Invalid archive access role '%s': Must match expected pattern: '%s'", - archiveAccessRole.get(), VALID_ARCHIVE_ACCESS_ROLE_PATTERN.pattern())); - if (archiveAccessRole.map(role -> role.length() > 100).orElse(false)) - throw new IllegalArgumentException("Invalid archive access role too long, must be 100 or less characters"); - } - - /** Creates a tenant with the given name, provided it passes validation. */ - 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, List.of(), Optional.empty()); - } - - /** The user that created the tenant */ - public Optional<Principal> creator() { - return creator; - } - - /** Legal name, addresses etc */ - public TenantInfo info() { - return info; - } - - /** An iam role which is allowed to access the S3 (log, dump) archive) */ - public Optional<String> archiveAccessRole() { - return archiveAccessRole; - } - - /** Returns the set of developer keys and their corresponding developers for this tenant. */ - public BiMap<PublicKey, Principal> developerKeys() { return developerKeys; } - - /** List of configured secret stores */ - public List<TenantSecretStore> tenantSecretStores() { - return tenantSecretStores; - } - - @Override - public Type type() { - return Type.cloud; - } - -} diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/DeletedTenant.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/DeletedTenant.java deleted file mode 100644 index cf6d73cb8f8..00000000000 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/DeletedTenant.java +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.controller.tenant; - -import com.yahoo.config.provision.TenantName; - -import java.time.Instant; -import java.util.Objects; -import java.util.Optional; - -/** - * Represents a tenant that has been deleted. Exists to prevent creation of a new tenant with the same name. - * - * @author freva - */ -public class DeletedTenant extends Tenant { - - private final Instant deletedAt; - - public DeletedTenant(TenantName name, Instant createdAt, Instant deletedAt) { - super(name, createdAt, LastLoginInfo.EMPTY, Optional.empty()); - this.deletedAt = Objects.requireNonNull(deletedAt, "deletedAt must be non-null"); - } - - /** Instant when the tenant was deleted */ - public Instant deletedAt() { - return deletedAt; - } - - @Override - public String toString() { - return "deleted tenant '" + name() + "'"; - } - - @Override - public Type type() { - return Type.deleted; - } - -} 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 deleted file mode 100644 index 15f2f97e7d1..00000000000 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/LastLoginInfo.java +++ /dev/null @@ -1,55 +0,0 @@ -// 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 deleted file mode 100644 index 80982d70107..00000000000 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Tenant.java +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.controller.tenant; - -import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.hosted.controller.api.integration.organization.Contact; - -import java.time.Instant; -import java.util.Objects; -import java.util.Optional; - -/** - * A tenant in hosted Vespa. - * - * @author mpolden - */ -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, LastLoginInfo lastLoginInfo, Optional<Contact> contact) { - this.name = name; - this.createdAt = createdAt; - this.lastLoginInfo = lastLoginInfo; - this.contact = contact; - } - - /** Name of this tenant */ - public TenantName name() { - return name; - } - - /** Instant when the tenant was created */ - public Instant createdAt() { - return createdAt; - } - - /** Returns login information for this tenant */ - public LastLoginInfo lastLoginInfo() { - return lastLoginInfo; - } - - /** Contact information for this tenant */ - public Optional<Contact> contact() { - return contact; - } - - public abstract Type type(); - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Tenant tenant = (Tenant) o; - return Objects.equals(name, tenant.name); - } - - @Override - public int hashCode() { - return Objects.hash(name); - } - - public static TenantName requireName(TenantName name) { - if ( ! name.value().matches("^(?=.{1,20}$)[a-z](-?[a-z0-9]+)*$")) { - throw new IllegalArgumentException("New tenant or application names must start with a letter, may " + - "contain no more than 20 characters, and may only contain lowercase " + - "letters, digits or dashes, but no double-dashes."); - } - return name; - } - - - public enum Type { - - /** Tenant authenticated through Athenz. */ - athenz, - - /** Tenant authenticated through some cloud identity provider. */ - cloud, - - /** Tenant has been deleted. */ - deleted, - - } - -} diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfo.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfo.java deleted file mode 100644 index a20477d7aab..00000000000 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfo.java +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.controller.tenant; - -import com.yahoo.vespa.hosted.controller.api.integration.secrets.TenantSecretStore; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -/** - * Tenant information beyond technical tenant id and user authorizations. - * - * This info is used to capture generic support information and invoiced billing information. - * - * All fields are non null but strings can be empty - * - * @author smorgrav - */ -public class TenantInfo { - private final String name; - private final String email; - private final String website; - private final String contactName; - private final String contactEmail; - private final String invoiceEmail; - private final TenantInfoAddress address; - private final TenantInfoBillingContact billingContact; - - TenantInfo(String name, String email, String website, String contactName, String contactEmail, - String invoiceEmail, TenantInfoAddress address, TenantInfoBillingContact billingContact) { - this.name = Objects.requireNonNull(name); - this.email = Objects.requireNonNull(email); - this.website = Objects.requireNonNull(website); - this.contactName = Objects.requireNonNull(contactName); - this.contactEmail = Objects.requireNonNull(contactEmail); - this.invoiceEmail = Objects.requireNonNull(invoiceEmail); - this.address = Objects.requireNonNull(address); - this.billingContact = Objects.requireNonNull(billingContact); - } - - public static final TenantInfo EMPTY = new TenantInfo("","","", "", "", "", - TenantInfoAddress.EMPTY, TenantInfoBillingContact.EMPTY); - - public String name() { - return name; - } - - public String email() { - return email; - } - - public String website() { - return website; - } - - public String contactName() { - return contactName; - } - - public String contactEmail() { - return contactEmail; - } - - public String invoiceEmail() { - return invoiceEmail; - } - - public TenantInfoAddress address() { - return address; - } - - public TenantInfoBillingContact billingContact() { - return billingContact; - } - - public TenantInfo withName(String newName) { - return new TenantInfo(newName, email, website, contactName, contactEmail, invoiceEmail, address, billingContact); - } - - public TenantInfo withEmail(String newEmail) { - return new TenantInfo(name, newEmail, website, contactName, contactEmail, invoiceEmail, address, billingContact); - } - - public TenantInfo withWebsite(String newWebsite) { - return new TenantInfo(name, email, newWebsite, contactName, contactEmail, invoiceEmail, address, billingContact); - } - - public TenantInfo withContactName(String newContactName) { - return new TenantInfo(name, email, website, newContactName, contactEmail, invoiceEmail, address, billingContact); - } - - public TenantInfo withContactEmail(String newContactEmail) { - return new TenantInfo(name, email, website, contactName, newContactEmail, invoiceEmail, address, billingContact); - } - - public TenantInfo withInvoiceEmail(String newInvoiceEmail) { - return new TenantInfo(name, email, website, contactName, contactEmail, newInvoiceEmail, address, billingContact); - } - - public TenantInfo withAddress(TenantInfoAddress newAddress) { - return new TenantInfo(name, email, website, contactName, contactEmail, invoiceEmail, newAddress, billingContact); - } - - public TenantInfo withBillingContact(TenantInfoBillingContact newBillingContact) { - return new TenantInfo(name, email, website, contactName, contactEmail, invoiceEmail, address, newBillingContact); - } - - public boolean isEmpty() { - return this.equals(EMPTY); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TenantInfo that = (TenantInfo) o; - return name.equals(that.name) && - email.equals(that.email) && - website.equals(that.website) && - contactName.equals(that.contactName) && - contactEmail.equals(that.contactEmail) && - invoiceEmail.equals(that.invoiceEmail) && - address.equals(that.address) && - billingContact.equals(that.billingContact); - } - - @Override - public int hashCode() { - return Objects.hash(name, email, website, contactName, contactEmail, invoiceEmail, address, billingContact); - } -} diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoAddress.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoAddress.java deleted file mode 100644 index a12f351abd6..00000000000 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoAddress.java +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2020 Oath Inc. 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.util.Objects; - -/** - * Address formats are quite diverse across the world both in therms of what fields are used, named and - * the order of them. - * - * To be generic a little future proof the address fields here are a mix of free text (address lines) and fixed fields. - * The address lines can be street address, P.O box, c/o name, apartment, suite, unit, building floor etc etc. - * - * All fields are mandatory but can be an empty string (ie. not null) - * - * @author smorgrav - */ -public class TenantInfoAddress { - - private final String addressLines; - private final String postalCodeOrZip; - private final String city; - private final String stateRegionProvince; - private final String country; - - TenantInfoAddress(String addressLines, String postalCodeOrZip, String city, String country, String stateRegionProvince) { - this.addressLines = Objects.requireNonNull(addressLines);; - this.city = Objects.requireNonNull(city); - this.postalCodeOrZip = Objects.requireNonNull(postalCodeOrZip); - this.country = Objects.requireNonNull(country); - this.stateRegionProvince = Objects.requireNonNull(stateRegionProvince); - } - - public static final TenantInfoAddress EMPTY = new TenantInfoAddress("","","", "", ""); - - public String addressLines() { - return addressLines; - } - - public String postalCodeOrZip() { - return postalCodeOrZip; - } - - public String city() { - return city; - } - - public String country() { - return country; - } - - public String stateRegionProvince() { - return stateRegionProvince; - } - - public TenantInfoAddress withAddressLines(String newAddressLines) { - return new TenantInfoAddress(newAddressLines, postalCodeOrZip, city, country, stateRegionProvince); - } - - public TenantInfoAddress withPostalCodeOrZip(String newPostalCodeOrZip) { - return new TenantInfoAddress(addressLines, newPostalCodeOrZip, city, country, stateRegionProvince); - } - - public TenantInfoAddress withCity(String newCity) { - return new TenantInfoAddress(addressLines, postalCodeOrZip, newCity, country, stateRegionProvince); - } - - public TenantInfoAddress withCountry(String newCountry) { - return new TenantInfoAddress(addressLines, postalCodeOrZip, city, newCountry, stateRegionProvince); - } - - public TenantInfoAddress withStateRegionProvince(String newStateRegionProvince) { - return new TenantInfoAddress(addressLines, postalCodeOrZip, city, country, newStateRegionProvince); - } - - public boolean isEmpty() { - return this.equals(EMPTY); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TenantInfoAddress that = (TenantInfoAddress) o; - return addressLines.equals(that.addressLines) && - postalCodeOrZip.equals(that.postalCodeOrZip) && - city.equals(that.city) && - stateRegionProvince.equals(that.stateRegionProvince) && - country.equals(that.country); - } - - @Override - public int hashCode() { - return Objects.hash(addressLines, postalCodeOrZip, city, stateRegionProvince, country); - } -} diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoBillingContact.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoBillingContact.java deleted file mode 100644 index a00dd626f0a..00000000000 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoBillingContact.java +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2020 Oath Inc. 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.util.Objects; - -/** - * @author smorgrav - */ -public class TenantInfoBillingContact { - private final String name; - private final String email; - private final String phone; - private final TenantInfoAddress address; - - TenantInfoBillingContact(String name, String email, String phone, TenantInfoAddress address) { - this.name = Objects.requireNonNull(name); - this.email = Objects.requireNonNull(email); - this.phone = Objects.requireNonNull(phone); - this.address = Objects.requireNonNull(address); - } - - public static final TenantInfoBillingContact EMPTY = - new TenantInfoBillingContact("","", "", TenantInfoAddress.EMPTY); - - public String name() { - return name; - } - - public String email() { return email; } - - public String phone() { - return phone; - } - - public TenantInfoAddress address() { - return address; - } - - public TenantInfoBillingContact withName(String newName) { - return new TenantInfoBillingContact(newName, email, phone, address); - } - - public TenantInfoBillingContact withEmail(String newEmail) { - return new TenantInfoBillingContact(name, newEmail, phone, address); - } - - public TenantInfoBillingContact withPhone(String newPhone) { - return new TenantInfoBillingContact(name, email, newPhone, address); - } - - public TenantInfoBillingContact withAddress(TenantInfoAddress newAddress) { - return new TenantInfoBillingContact(name, email, phone, newAddress); - } - - public boolean isEmpty() { - return this.equals(EMPTY); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TenantInfoBillingContact that = (TenantInfoBillingContact) o; - return name.equals(that.name) && - email.equals(that.email) && - phone.equals(that.phone) && - address.equals(that.address); - } - - @Override - public int hashCode() { - return Objects.hash(name, email, phone, address); - } -} diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/package-info.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/package-info.java deleted file mode 100644 index 9218bfcd850..00000000000 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -/** - * @author mpolden - */ -@ExportPackage -package com.yahoo.vespa.hosted.controller.tenant; - -import com.yahoo.osgi.annotation.ExportPackage; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java index fe03b69a3fe..7ce17aff782 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java @@ -9,6 +9,7 @@ import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.NodeType; import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.SystemName; +import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.zone.RoutingMethod; import com.yahoo.config.provision.zone.UpgradePolicy; import com.yahoo.config.provision.zone.ZoneApi; @@ -216,6 +217,8 @@ public class ZoneRegistryMock extends AbstractComponent implements ZoneRegistry return URI.create("https://api.tld:4443/"); } + @Override public Optional<String> tenantDeveloperRoleArn(TenantName tenant) { return Optional.empty(); } + @Override public boolean hasZone(ZoneId zoneId) { return zones.stream().anyMatch(zone -> zone.getId().equals(zoneId)); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentUpgraderTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentUpgraderTest.java index ec33c8a7048..1c07a321953 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentUpgraderTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentUpgraderTest.java @@ -55,19 +55,13 @@ public class DeploymentUpgraderTest { assertEquals(start, tester.jobs().last(devApp.instanceId(), devUsEast1).get().start()); assertEquals(start, tester.jobs().last(prodApp.instanceId(), productionUsWest1).get().start()); - // 14 hours pass, but not upgraded before a day has passed since last deployment - tester.clock().advance(Duration.ofHours(14)); + // 11 hours pass, but not upgraded since it's not likely in the middle of the night + tester.clock().advance(Duration.ofHours(11)); upgrader.maintain(); assertEquals(start, tester.jobs().last(devApp.instanceId(), devUsEast1).get().start()); assertEquals(start, tester.jobs().last(prodApp.instanceId(), productionUsWest1).get().start()); - // 35 hours pass, but not upgraded since it's not likely in the middle of the night - tester.clock().advance(Duration.ofHours(21)); - upgrader.maintain(); - assertEquals(start, tester.jobs().last(devApp.instanceId(), devUsEast1).get().start()); - assertEquals(start, tester.jobs().last(prodApp.instanceId(), productionUsWest1).get().start()); - - // 38 hours pass, and the dev deployment, only, is upgraded + // 14 hours pass, and the dev deployment, only, is upgraded tester.clock().advance(Duration.ofHours(3)); upgrader.maintain(); assertEquals(tester.clock().instant().truncatedTo(MILLIS), tester.jobs().last(devApp.instanceId(), devUsEast1).get().start()); 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 cd73721ce4f..03a88c7a8c4 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 @@ -1,4 +1,4 @@ -// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.application; import ai.vespa.hosted.api.MultiPartStreamer; @@ -250,7 +250,7 @@ public class ApplicationApiTest extends ControllerContainerTest { var app1 = deploymentTester.newDeploymentContext(id); // POST (deploy) an application to start a manual deployment in prod is not allowed - MultiPartStreamer entity = createApplicationDeployData(applicationPackageInstance1, true); + MultiPartStreamer entity = createApplicationDeployData(applicationPackageInstance1); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploy/production-us-east-3/", POST) .data(entity) .userIdentity(USER_ID), @@ -289,7 +289,7 @@ public class ApplicationApiTest extends ControllerContainerTest { // POST an application package is not generally allowed under user instance tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/otheruser/deploy/dev-us-east-1", POST) .userIdentity(OTHER_USER_ID) - .data(createApplicationDeployData(applicationPackageInstance1, false)), + .data(createApplicationDeployData(applicationPackageInstance1)), accessDenied, 403); @@ -303,7 +303,7 @@ public class ApplicationApiTest extends ControllerContainerTest { // POST an application package is not allowed under user instance for tenant admins tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/myuser/deploy/dev-us-east-1", POST) .userIdentity(USER_ID) - .data(createApplicationDeployData(applicationPackageInstance1, false)), + .data(createApplicationDeployData(applicationPackageInstance1)), new File("deployment-job-accepted-2.json")); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/myuser/job/dev-us-east-1/diff/1", GET).userIdentity(HOSTED_VESPA_OPERATOR), @@ -1026,38 +1026,24 @@ public class ApplicationApiTest extends ControllerContainerTest { } @Test - public void testDeployDirectly() { + public void testDeployWithApplicationPackage() { // Setup - createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); addUserToHostedOperatorRole(HostedAthenzIdentities.from(HOSTED_VESPA_OPERATOR)); - // Create tenant - tester.assertResponse(request("/application/v4/tenant/tenant1", POST).userIdentity(USER_ID) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT), - new File("tenant-without-applications.json")); - - // Create application - tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST) - .userIdentity(USER_ID) - .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT), - new File("instance-reference.json")); - - // Add build service to operator role - addUserToHostedOperatorRole(HostedAthenzIdentities.from(SCREWDRIVER_ID)); - // POST (deploy) a system application with an application package - MultiPartStreamer noAppEntity = createApplicationDeployData(Optional.empty(), true); + MultiPartStreamer noAppEntity = createApplicationDeployData(Optional.empty()); tester.assertResponse(request("/application/v4/tenant/hosted-vespa/application/routing/environment/prod/region/us-central-1/instance/default/deploy", POST) .data(noAppEntity) .userIdentity(HOSTED_VESPA_OPERATOR), "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Deployment of system applications during a system upgrade is not allowed\"}", 400); - deploymentTester.controllerTester().upgradeSystem(deploymentTester.controller().readVersionStatus().controllerVersion().get().versionNumber()); + deploymentTester.controllerTester() + .upgradeSystem(deploymentTester.controller().readVersionStatus().controllerVersion().get() + .versionNumber()); tester.assertResponse(request("/application/v4/tenant/hosted-vespa/application/routing/environment/prod/region/us-central-1/instance/default/deploy", POST) - .data(noAppEntity) - .userIdentity(HOSTED_VESPA_OPERATOR), - new File("deploy-result.json")); + .data(noAppEntity) + .userIdentity(HOSTED_VESPA_OPERATOR), + new File("deploy-result.json")); } @Test @@ -1113,7 +1099,7 @@ public class ApplicationApiTest extends ControllerContainerTest { } @Test - public void testErrorResponses() throws Exception { + public void testErrorResponses() { createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); // PUT (update) non-existing tenant returns 403 as tenant access cannot be determined when the tenant does not exist @@ -1223,7 +1209,7 @@ public class ApplicationApiTest extends ControllerContainerTest { 400); // POST (deploy) an application to legacy deploy path - MultiPartStreamer entity = createApplicationDeployData(applicationPackageInstance1, true); + MultiPartStreamer entity = createApplicationDeployData(applicationPackageInstance1); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/dev/region/us-east-1/instance/instance1/deploy", POST) .data(entity) .userIdentity(USER_ID), @@ -1330,7 +1316,7 @@ public class ApplicationApiTest extends ControllerContainerTest { 200); // Deploy to an authorized zone by a user tenant is disallowed - MultiPartStreamer entity = createApplicationDeployData(applicationPackageDefault, true); + MultiPartStreamer entity = createApplicationDeployData(applicationPackageDefault); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-west-1/instance/default/deploy", POST) .data(entity) .userIdentity(USER_ID), @@ -1437,7 +1423,7 @@ public class ApplicationApiTest extends ControllerContainerTest { .build(); createTenantAndApplication(); - MultiPartStreamer entity = createApplicationDeployData(applicationPackage, true); + MultiPartStreamer entity = createApplicationDeployData(applicationPackage); // POST (deploy) an application to dev through a deployment job, with user instance and a proper tenant tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/new-user/deploy/dev-us-east-1", POST) .data(entity) @@ -1484,7 +1470,7 @@ public class ApplicationApiTest extends ControllerContainerTest { .build(); // deploy the application to a dev zone. Should fail since the developer is not authorized to launch the service - MultiPartStreamer entity = createApplicationDeployData(applicationPackage, true); + MultiPartStreamer entity = createApplicationDeployData(applicationPackage); tester.assertResponse(request("/application/v4/tenant/sandbox/application/myapp/instance/default/deploy/dev-us-east-1", POST) .data(entity) .userIdentity(developer), @@ -1646,7 +1632,7 @@ public class ApplicationApiTest extends ControllerContainerTest { } @Test - public void testServiceView() throws Exception { + public void testServiceView() { createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); String serviceApi="/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-central-1/instance/instance1/service"; // Not allowed to request apis not listed in feature flag allowed-service-view-apis. e.g /document/v1 @@ -1713,18 +1699,18 @@ public class ApplicationApiTest extends ControllerContainerTest { .build(); } - private MultiPartStreamer createApplicationDeployData(ApplicationPackage applicationPackage, boolean deployDirectly) { - return createApplicationDeployData(Optional.of(applicationPackage), deployDirectly); + private MultiPartStreamer createApplicationDeployData(ApplicationPackage applicationPackage) { + return createApplicationDeployData(Optional.of(applicationPackage)); } - private MultiPartStreamer createApplicationDeployData(Optional<ApplicationPackage> applicationPackage, boolean deployDirectly) { - return createApplicationDeployData(applicationPackage, Optional.empty(), deployDirectly); + private MultiPartStreamer createApplicationDeployData(Optional<ApplicationPackage> applicationPackage) { + return createApplicationDeployData(applicationPackage, Optional.empty()); } private MultiPartStreamer createApplicationDeployData(Optional<ApplicationPackage> applicationPackage, - Optional<ApplicationVersion> applicationVersion, boolean deployDirectly) { + Optional<ApplicationVersion> applicationVersion) { MultiPartStreamer streamer = new MultiPartStreamer(); - streamer.addJson("deployOptions", deployOptions(deployDirectly, applicationVersion)); + streamer.addJson("deployOptions", deployOptions(applicationVersion)); applicationPackage.ifPresent(ap -> streamer.addBytes("applicationZip", ap.zippedContent())); return streamer; } @@ -1736,10 +1722,9 @@ public class ApplicationApiTest extends ControllerContainerTest { .addBytes(EnvironmentResource.APPLICATION_TEST_ZIP, "content".getBytes()); } - private String deployOptions(boolean deployDirectly, Optional<ApplicationVersion> applicationVersion) { + private String deployOptions(Optional<ApplicationVersion> applicationVersion) { return "{\"vespaVersion\":null," + - "\"ignoreValidationErrors\":false," + - "\"deployDirectly\":" + deployDirectly + + "\"ignoreValidationErrors\":false" + applicationVersion.map(version -> "," + "\"buildNumber\":" + version.buildNumber().getAsLong() + "," + diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiTest.java index 8e51f8210c7..b2b5b2286f7 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiTest.java @@ -4,7 +4,6 @@ import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.TenantName; import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.InMemoryFlagSource; -import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId; import com.yahoo.vespa.hosted.controller.api.role.Role; import com.yahoo.vespa.hosted.controller.restapi.ContainerTester; import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerCloudTest; @@ -33,8 +32,6 @@ public class HorizonApiTest extends ControllerContainerCloudTest { ((InMemoryFlagSource) tester.controller().flagSource()) .withBooleanFlag(Flags.ENABLED_HORIZON_DASHBOARD.id(), true); - tester.controller().serviceRegistry().billingController().setPlan(tenantName, PlanId.from("pay-as-you-go"), true); - tester.assertResponse(request("/horizon/v1/config/dashboard/topFolders") .roles(Set.of(Role.reader(tenantName))), "", 200); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-athenz.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-athenz.json index 0a416600b2c..006c3b98a4d 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-athenz.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-athenz.json @@ -1,7 +1,6 @@ { "isPublic": false, "isCd": false, - "enable-public-signup-flow": (ignore), "hasTrialCapacity": (ignore), "user": { "name": "Joe Developer", diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-cloud.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-cloud.json index 4e179ad83c5..4ae55e97baa 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-cloud.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-cloud.json @@ -1,7 +1,6 @@ { "isPublic": true, "isCd": false, - "enable-public-signup-flow": (ignore), "hasTrialCapacity": true, "user": { "name": "Joe Developer", @@ -14,20 +13,17 @@ "roles": [ "developer", "reader" - ], - "enabled-horizon-dashboard":false + ] }, "tenant1": { "roles": [ "administrator" - ], - "enabled-horizon-dashboard":false + ] }, "tenant2": { "roles": [ "developer" - ], - "enabled-horizon-dashboard":false + ] } }, "flags": [{"id":"enable-public-signup-flow","rules":[{"value":false}]}] diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-without-applications.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-without-applications.json index 7eb445140e7..9f9578e6ed8 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-without-applications.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-without-applications.json @@ -1,7 +1,6 @@ { "isPublic": (ignore), "isCd": (ignore), - "enable-public-signup-flow": (ignore), "hasTrialCapacity": (ignore), "user": { "name": "Joe Developer", diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-without-trial-capacity-cloud.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-without-trial-capacity-cloud.json index 3c1edab8cfc..2b98a75068a 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-without-trial-capacity-cloud.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-without-trial-capacity-cloud.json @@ -1,7 +1,6 @@ { "isPublic": true, "isCd": false, - "enable-public-signup-flow": true, "hasTrialCapacity": false, "user": { "name": "Joe Developer", |