aboutsummaryrefslogtreecommitdiffstats
path: root/controller-server/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'controller-server/src/test')
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java55
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java36
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java14
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java281
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java4
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/RetriggerMaintainerTest.java3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/UpgraderTest.java24
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/root.json5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java29
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java8
16 files changed, 409 insertions, 70 deletions
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
index e09e42c9900..dede0c8dec8 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
@@ -67,6 +67,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.yahoo.config.provision.SystemName.main;
+import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.devUsEast1;
import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.productionUsEast3;
import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.productionUsWest1;
import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.stagingTest;
@@ -92,6 +93,7 @@ public class ControllerTest {
void testDeployment() {
// Setup system
ApplicationPackage applicationPackage = new ApplicationPackageBuilder()
+ .explicitEnvironment(Environment.dev, Environment.perf)
.region("us-west-1")
.region("us-east-3")
.build();
@@ -694,7 +696,8 @@ public class ControllerTest {
@Test
void testDevDeployment() {
- ApplicationPackage applicationPackage = new ApplicationPackageBuilder().build();
+ // A package without deployment.xml is considered valid
+ ApplicationPackage applicationPackage = new ApplicationPackage(new byte[0]);
// Create application
var context = tester.newDeploymentContext();
@@ -1166,7 +1169,12 @@ public class ControllerTest {
tester.controllerTester().upgradeSystem(version0);
tester.upgrader().overrideConfidence(version0, Confidence.normal);
tester.controllerTester().computeVersionStatus();
+ assertEquals(version0, tester.applications().compileVersion(application, OptionalInt.of(7)));
assertEquals(version0, tester.applications().compileVersion(application, OptionalInt.empty()));
+ assertEquals("this system has no available versions on specified major: 8",
+ assertThrows(IllegalArgumentException.class,
+ () -> tester.applications().compileVersion(application, OptionalInt.of(8)))
+ .getMessage());
context.submit(applicationPackage).deploy();
// System is upgraded
@@ -1266,33 +1274,38 @@ public class ControllerTest {
@Test
void testCloudAccount() {
DeploymentContext context = tester.newDeploymentContext();
- ZoneId zone = ZoneId.from("prod", "us-west-1");
+ ZoneId devZone = devUsEast1.zone();
+ ZoneId prodZone = productionUsWest1.zone();
String cloudAccount = "012345678912";
var applicationPackage = new ApplicationPackageBuilder()
.cloudAccount(cloudAccount)
- .region(zone.region())
+ .region(prodZone.region())
.build();
- // Deployment fails because cloud account is not declared for this tenant
- try {
- context.submit(applicationPackage).deploy();
- fail("Expected exception");
- } catch (IllegalArgumentException e) {
- assertEquals("Cloud account '012345678912' is not valid for tenant 'tenant'", e.getMessage());
- }
+ // Prod and dev deployments fail because cloud account is not declared for this tenant
+ context.submit(applicationPackage).runJobExpectingFailure(systemTest, "Requested cloud account '012345678912' is not valid for tenant 'tenant'");
- // Deployment fails because requested region is not configured in cloud account
+ // Deployment fails because zone is not configured in requested cloud account
tester.controllerTester().flagSource().withListFlag(PermanentFlags.CLOUD_ACCOUNTS.id(), List.of(cloudAccount), String.class);
- try {
- context.submit(applicationPackage).deploy();
- fail("Expected exception");
- } catch (IllegalArgumentException e) {
- assertEquals("Zone prod.us-west-1 in deployment spec is not configured for use in cloud account '012345678912', in this system", e.getMessage());
- }
-
- // Deployment succeeds
- tester.controllerTester().zoneRegistry().setCloudAccountZones(new CloudAccount(cloudAccount), zone);
+ context.runJobExpectingFailure(systemTest, "Zone test.us-east-1 is not configured in requested cloud account '012345678912'")
+ .abortJob(stagingTest);
+
+ // Deployment to prod succeeds once all zones are configured in requested account
+ tester.controllerTester().zoneRegistry().configureCloudAccount(new CloudAccount(cloudAccount),
+ systemTest.zone(),
+ stagingTest.zone(),
+ prodZone);
context.submit(applicationPackage).deploy();
- assertEquals(cloudAccount, tester.controllerTester().configServer().cloudAccount(context.deploymentIdIn(zone)).get().value());
+
+ // Dev zone is added as a configured zone and deployment succeeds
+ tester.controllerTester().zoneRegistry().configureCloudAccount(new CloudAccount(cloudAccount), devZone);
+ context.runJob(devZone, applicationPackage);
+
+ // All deployments use the custom account
+ for (var zoneId : List.of(systemTest.zone(), stagingTest.zone(), devZone, prodZone)) {
+ assertEquals(cloudAccount, tester.controllerTester().configServer()
+ .cloudAccount(context.deploymentIdIn(zoneId))
+ .get().value());
+ }
}
@Test
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
index 10fd57ce032..5380cf4ee27 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
@@ -344,7 +344,7 @@ public final class ControllerTester {
private TenantName createCloudTenant(String tenantName) {
TenantName tenant = TenantName.from(tenantName);
TenantSpec spec = new CloudTenantSpec(tenant, "token");
- controller().tenants().create(spec, new Auth0Credentials(new SimplePrincipal("dev"), Set.of(Role.administrator(tenant))));
+ controller().tenants().create(spec, new Auth0Credentials(new SimplePrincipal("dev-" + tenantName), Set.of(Role.administrator(tenant))));
return tenant;
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java
index 146135491a3..8ddd0ef2be3 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java
@@ -5,6 +5,7 @@ import com.yahoo.component.Version;
import com.yahoo.config.application.api.ValidationId;
import com.yahoo.config.provision.AthenzDomain;
import com.yahoo.config.provision.AthenzService;
+import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.RegionName;
import com.yahoo.security.SignatureAlgorithm;
@@ -26,6 +27,7 @@ import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.OptionalInt;
@@ -55,6 +57,7 @@ public class ApplicationPackageBuilder {
private final StringBuilder endpointsBody = new StringBuilder();
private final StringBuilder applicationEndpointsBody = new StringBuilder();
private final List<X509Certificate> trustedCertificates = new ArrayList<>();
+ private final Map<Environment, Map<String, String>> nonProductionEnvironments = new LinkedHashMap<>();
private OptionalInt majorVersion = OptionalInt.empty();
private String instances = "default";
@@ -65,8 +68,6 @@ public class ApplicationPackageBuilder {
private String globalServiceId = null;
private String athenzIdentityAttributes = "athenz-domain='domain' athenz-service='service'";
private String searchDefinition = "search test { }";
- private boolean explicitSystemTest = false;
- private boolean explicitStagingTest = false;
private Version compileVersion = Version.fromString("6.1");
private String cloudAccount = null;
@@ -135,12 +136,22 @@ public class ApplicationPackageBuilder {
}
public ApplicationPackageBuilder systemTest() {
- explicitSystemTest = true;
- return this;
+ return explicitEnvironment(Environment.test);
}
public ApplicationPackageBuilder stagingTest() {
- explicitStagingTest = true;
+ return explicitEnvironment(Environment.staging);
+ }
+
+ public ApplicationPackageBuilder explicitEnvironment(Environment environment, Environment... rest) {
+ Stream.concat(Stream.of(environment), Arrays.stream(rest))
+ .forEach(env -> nonProductionEnvironment(env, Map.of()));
+ return this;
+ }
+
+ private ApplicationPackageBuilder nonProductionEnvironment(Environment environment, Map<String, String> attributes) {
+ if (environment.isProduction()) throw new IllegalArgumentException("Expected non-production environment, got " + environment);
+ nonProductionEnvironments.put(environment, attributes);
return this;
}
@@ -267,6 +278,10 @@ public class ApplicationPackageBuilder {
return this;
}
+ public ApplicationPackageBuilder cloudAccount(Environment environment, String cloudAccount) {
+ return nonProductionEnvironment(environment, Map.of("cloud-account", cloudAccount));
+ }
+
private byte[] deploymentSpec() {
StringBuilder xml = new StringBuilder();
xml.append("<deployment version='1.0' ");
@@ -291,10 +306,13 @@ public class ApplicationPackageBuilder {
xml.append("/>\n");
}
xml.append(notifications);
- if (explicitSystemTest)
- xml.append(" <test />\n");
- if (explicitStagingTest)
- xml.append(" <staging />\n");
+ nonProductionEnvironments.forEach((environment, attributes) -> {
+ xml.append(" <").append(environment.value());
+ attributes.forEach((attribute, value) -> {
+ xml.append(" ").append(attribute).append("='").append(value).append("'");
+ });
+ xml.append(" />\n");
+ });
xml.append(blockChange);
xml.append(" <prod");
if (globalServiceId != null) {
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java
index 934c6b07c29..f0402eb764b 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java
@@ -338,18 +338,18 @@ public class DeploymentContext {
/** Fail current deployment in given job */
public DeploymentContext failDeployment(JobType type) {
- return failDeployment(type, new IllegalArgumentException("Exception from test code"));
+ return failDeployment(type, new RuntimeException("Exception from test code"));
}
/** Fail current deployment in given job */
private DeploymentContext failDeployment(JobType type, RuntimeException exception) {
configServer().throwOnNextPrepare(exception);
- runJobExpectingFailure(type, Optional.empty());
+ runJobExpectingFailure(type, null);
return this;
}
/** Run given job and expect it to fail with given message, if any */
- public DeploymentContext runJobExpectingFailure(JobType type, Optional<String> messagePart) {
+ public DeploymentContext runJobExpectingFailure(JobType type, String messagePart) {
triggerJobs();
var job = jobId(type);
RunId id = currentRun(job).id();
@@ -357,7 +357,7 @@ public class DeploymentContext {
Run run = jobs.run(id);
assertTrue(run.hasFailed());
assertTrue(run.hasEnded());
- if (messagePart.isPresent()) {
+ if (messagePart != null) {
Optional<Step> firstFailing = run.stepStatuses().entrySet().stream()
.filter(kv -> kv.getValue() == failed)
.map(Entry::getKey)
@@ -366,8 +366,8 @@ public class DeploymentContext {
Optional<RunLog> details = jobs.details(id);
assertTrue(details.isPresent(), "Found log entries for run " + id);
assertTrue(details.get().get(firstFailing.get()).stream()
- .anyMatch(entry -> entry.message().contains(messagePart.get())),
- "Found log message containing '" + messagePart.get() + "'");
+ .anyMatch(entry -> entry.message().contains(messagePart)),
+ "Found log message containing '" + messagePart + "'");
}
return this;
}
@@ -406,7 +406,7 @@ public class DeploymentContext {
/** Runs a deployment of the given package to the given dev/perf job, on the given version. */
public DeploymentContext runJob(JobType type, ApplicationPackage applicationPackage, Version vespaVersion) {
- jobs.deploy(instanceId, type, Optional.ofNullable(vespaVersion), applicationPackage, false);
+ jobs.deploy(instanceId, type, Optional.ofNullable(vespaVersion), applicationPackage, false, true);
return runJob(type);
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java
index 3b8d0374a45..89b6f6ca606 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java
@@ -2,6 +2,7 @@
package com.yahoo.vespa.hosted.controller.deployment;
import com.yahoo.component.Version;
+import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.InstanceName;
@@ -23,6 +24,7 @@ import com.yahoo.vespa.hosted.controller.application.SystemApplication;
import com.yahoo.vespa.hosted.controller.application.pkg.ApplicationPackage;
import com.yahoo.vespa.hosted.controller.integration.ZoneApiMock;
import com.yahoo.vespa.hosted.controller.integration.ZoneRegistryMock;
+import com.yahoo.vespa.hosted.controller.maintenance.DeploymentUpgrader;
import com.yahoo.vespa.hosted.controller.versions.VespaVersion;
import com.yahoo.vespa.hosted.controller.versions.VespaVersion.Confidence;
import org.junit.jupiter.api.Test;
@@ -41,6 +43,7 @@ import java.util.stream.Collectors;
import static ai.vespa.validation.Validation.require;
import static com.yahoo.config.provision.SystemName.cd;
+import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.applicationPackage;
import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.productionApNortheast1;
import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.productionApNortheast2;
import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.productionApSoutheast1;
@@ -64,8 +67,10 @@ import static java.util.Collections.emptyList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
/**
* Tests a wide variety of deployment scenarios and configurations
@@ -1189,6 +1194,7 @@ public class DeploymentTriggerTest {
.region("us-central-1")
.test("us-central-1")
.test("us-west-1")
+ .region("eu-west-1")
.build();
var app = tester.newDeploymentContext().submit(applicationPackage);
@@ -1197,15 +1203,18 @@ public class DeploymentTriggerTest {
tester.clock().advance(Duration.ofMinutes(1));
app.runJob(testUsEast3)
- .runJob(productionUsWest1).runJob(productionUsCentral1)
- .runJob(testUsCentral1).runJob(testUsWest1);
+ .runJob(productionUsWest1).runJob(productionUsCentral1)
+ .runJob(testUsCentral1).runJob(testUsWest1)
+ .runJob(productionEuWest1);
assertEquals(Change.empty(), app.instance().change());
- // Application starts upgrade, but is confidence is broken cancelled after first zone. Tests won't run.
+ // Application starts upgrade, but confidence is broken after first zone. Tests won't run.
Version version0 = app.application().oldestDeployedPlatform().get();
Version version1 = Version.fromString("6.7");
+ Version version2 = Version.fromString("6.8");
tester.controllerTester().upgradeSystem(version1);
tester.upgrader().maintain();
+ tester.newDeploymentContext("keep", "version1", "alive").submit().deploy();
app.runJob(systemTest).runJob(stagingTest).runJob(productionUsEast3);
tester.clock().advance(Duration.ofMinutes(1));
@@ -1229,12 +1238,17 @@ public class DeploymentTriggerTest {
app.runJob(testUsEast3);
assertEquals(Change.empty().withPin(), app.instance().change());
- // Same upgrade is attempted, and production tests wait for redeployment.
+ // A new upgrade is attempted, and production tests wait for redeployment.
+ tester.controllerTester().upgradeSystem(version2);
tester.deploymentTrigger().cancelChange(app.instanceId(), ALL);
+
tester.upgrader().overrideConfidence(version1, VespaVersion.Confidence.high);
tester.controllerTester().computeVersionStatus();
- tester.upgrader().maintain();
+ tester.upgrader().maintain(); // App should target version2.
+ assertEquals(Change.of(version2), app.instance().change());
+ // App partially upgrades to version2.
+ app.runJob(systemTest).runJob(stagingTest);
app.triggerJobs();
app.assertRunning(productionUsEast3);
app.assertNotRunning(testUsEast3);
@@ -1245,6 +1259,20 @@ public class DeploymentTriggerTest {
tester.runner().run();
app.triggerJobs();
app.assertNotRunning(testUsCentral1);
+ app.assertNotRunning(testUsWest1);
+
+ // Version2 gets broken, but Version1 has high confidence now, and is the new target.
+ // Since us-east-3 is already on Version2, both deployment and tests to it should be skipped.
+ tester.upgrader().overrideConfidence(version2, VespaVersion.Confidence.broken);
+ tester.controllerTester().computeVersionStatus();
+ tester.upgrader().maintain(); // App should target version2.
+ assertEquals(Change.of(version1), app.instance().change());
+ app.triggerJobs();
+
+ // Deployment to 6.8 already happened, so a downgrade to 6.7 won't, but production tests will still run.
+ app.timeOutConvergence(productionUsCentral1);
+ app.runJob(testUsCentral1).runJob(testUsWest1).runJob(productionEuWest1);
+ assertEquals(version1, app.instance().deployments().get(ZoneId.from("prod.eu-west-1")).version());
}
@Test
@@ -2027,16 +2055,16 @@ public class DeploymentTriggerTest {
var conservative = tester.newDeploymentContext("t", "a", "default");
canary.runJob(systemTest)
- .runJob(stagingTest);
+ .runJob(stagingTest);
conservative.runJob(productionEuWest1)
- .runJob(testEuWest1);
+ .runJob(testEuWest1);
canary.submit(applicationPackage)
- .runJob(systemTest)
- .runJob(stagingTest);
+ .runJob(systemTest)
+ .runJob(stagingTest);
tester.outstandingChangeDeployer().run();
conservative.runJob(productionEuWest1)
- .runJob(testEuWest1);
+ .runJob(testEuWest1);
tester.controllerTester().upgradeSystem(new Version("6.7.7"));
tester.upgrader().maintain();
@@ -2045,7 +2073,7 @@ public class DeploymentTriggerTest {
.runJob(stagingTest);
tester.upgrader().maintain();
conservative.runJob(productionEuWest1)
- .runJob(testEuWest1);
+ .runJob(testEuWest1);
}
@@ -2178,6 +2206,7 @@ public class DeploymentTriggerTest {
app.submit(new ApplicationPackageBuilder().region("us-east-3")
.compileVersion(version2)
.build());
+ tester.upgrader().overrideConfidence(version2, Confidence.normal);
tester.upgrader().overrideConfidence(version3, Confidence.broken);
tester.controllerTester().computeVersionStatus();
tester.upgrader().run();
@@ -2222,6 +2251,143 @@ public class DeploymentTriggerTest {
newApp.deploy();
assertEquals(version2, tester.jobs().last(newApp.instanceId(), productionUsEast3).get().versions().targetPlatform());
assertEquals(version2, newApp.application().revisions().get(tester.jobs().last(newApp.instanceId(), productionUsEast3).get().versions().targetRevision()).compileVersion().get());
+
+ // New app compiles against old major, and downgrades when a pin is also applied.
+ newApp.submit(new ApplicationPackageBuilder().compileVersion(version1)
+ .systemTest()
+ .region("us-east-3")
+ .build());
+ newRevision = newApp.lastSubmission().get();
+
+ assertEquals(Change.of(newRevision).with(version1), newApp.instance().change());
+ tester.triggerJobs();
+ newApp.assertNotRunning(systemTest); // Without a pin, the platform won't downgrade, and 8 is incompatible with compiled 7.
+
+ tester.outstandingChangeDeployer().run();
+ assertEquals(Change.of(newRevision).with(version1), newApp.instance().change());
+ tester.upgrader().run();
+ assertEquals(Change.of(newRevision).with(version1), newApp.instance().change());
+
+ tester.deploymentTrigger().forceChange(newApp.instanceId(), newApp.instance().change().withPin());
+ tester.outstandingChangeDeployer().run();
+ assertEquals(Change.of(newRevision).with(version1).withPin(), newApp.instance().change());
+ tester.upgrader().run();
+ assertEquals(Change.of(newRevision).with(version1).withPin(), newApp.instance().change());
+
+ newApp.deploy();
+ assertEquals(version1, tester.jobs().last(newApp.instanceId(), productionUsEast3).get().versions().targetPlatform());
+ assertEquals(version1, newApp.application().revisions().get(tester.jobs().last(newApp.instanceId(), productionUsEast3).get().versions().targetRevision()).compileVersion().get());
+ }
+
+ @Test
+ void testOutdatedMajorIsIllegal() {
+ Version version0 = new Version("6.2");
+ Version version1 = new Version("7.1");
+ tester.controllerTester().upgradeSystem(version0);
+ DeploymentContext old = tester.newDeploymentContext("t", "a", "default").submit()
+ .runJob(systemTest).runJob(stagingTest).runJob(productionUsCentral1);
+ old.runJob(JobType.dev("us-east-1"), applicationPackage());
+
+ tester.controllerTester().upgradeSystem(version1);
+ tester.upgrader().overrideConfidence(version1, Confidence.high);
+ tester.controllerTester().computeVersionStatus();
+
+ // New app can't deploy to 6.2
+ DeploymentContext app = tester.newDeploymentContext("t", "b", "default");
+ assertEquals("platform version 6.2 is not on a current major version in this system",
+ assertThrows(IllegalArgumentException.class,
+ () -> tester.jobs().deploy(app.instanceId(),
+ JobType.dev("us-east-1"),
+ Optional.of(version0),
+ DeploymentContext.applicationPackage()))
+ .getMessage());
+
+ // App which already deployed to 6.2 can still do so.
+ tester.jobs().deploy(old.instanceId(),
+ JobType.dev("us-east-1"),
+ Optional.of(version0),
+ DeploymentContext.applicationPackage());
+
+ app.submit();
+ assertEquals("platform version 6.2 is not on a current major version in this system",
+ assertThrows(IllegalArgumentException.class,
+ () -> tester.deploymentTrigger().forceChange(app.instanceId(), Change.of(version0), false))
+ .getMessage());
+
+ tester.deploymentTrigger().forceChange(old.instanceId(), Change.of(version0), false);
+
+ // Not even version incompatibility tricks the system.
+ tester.controllerTester().flagSource().withListFlag(PermanentFlags.INCOMPATIBLE_VERSIONS.id(), List.of("7"), String.class);
+ assertEquals("compile version 6.2 is incompatible with the current major version of this system",
+ assertThrows(IllegalArgumentException.class,
+ () ->
+ app.submit(new ApplicationPackageBuilder().region("us-central-1").region("us-east-3").region("us-west-1")
+ .compileVersion(version0)
+ .build()))
+ .getMessage());
+
+ // Upgrade.
+ old.submit(new ApplicationPackageBuilder().region("us-central-1").region("us-east-3").region("us-west-1")
+ .compileVersion(version1)
+ .build())
+ .deploy();
+
+ // And downgrade again.
+ old.submit(new ApplicationPackageBuilder().region("us-central-1").region("us-east-3").region("us-west-1")
+ .compileVersion(version0)
+ .build());
+
+ assertEquals(Change.of(version0).with(old.lastSubmission().get()), old.instance().change());
+
+ // An operator can still trigger roll-out of the otherwise illegal submission.
+ tester.deploymentTrigger().forceChange(app.instanceId(), Change.of(app.lastSubmission().get()));
+ assertEquals(Change.of(app.lastSubmission().get()), app.instance().change());
+ }
+
+ @Test
+ void testInitialDeploymentPlatform() {
+ Version version0 = tester.controllerTester().controller().readSystemVersion();
+ Version version1 = new Version("6.2");
+ Version version2 = new Version("6.3");
+ assertEquals(version0, tester.newDeploymentContext("t", "a1", "default").submit().deploy().application().oldestDeployedPlatform().get());
+
+ // A new version, with normal confidence, is the default for a new app.
+ tester.controllerTester().upgradeSystem(version1);
+ tester.upgrader().overrideConfidence(version1, Confidence.normal);
+ tester.controllerTester().computeVersionStatus();
+ assertEquals(version1, tester.newDeploymentContext("t", "a2", "default").submit().deploy().application().oldestDeployedPlatform().get());
+
+ // A newer version has broken confidence, leaving the previous version as the default.
+ tester.controllerTester().upgradeSystem(version2);
+ tester.upgrader().overrideConfidence(version2, Confidence.broken);
+ tester.controllerTester().computeVersionStatus();
+ assertEquals(version1, tester.newDeploymentContext("t", "a3", "default").submit().deploy().application().oldestDeployedPlatform().get());
+
+ DeploymentContext dev1 = tester.newDeploymentContext("t", "d1", "default");
+ DeploymentContext dev2 = tester.newDeploymentContext("t", "d2", "default");
+ assertEquals(version1, dev1.runJob(JobType.dev("us-east-1"), DeploymentContext.applicationPackage()).deployment(ZoneId.from("dev", "us-east-1")).version());
+
+ DeploymentUpgrader devUpgrader = new DeploymentUpgrader(tester.controller(), Duration.ofHours(1));
+ for (int i = 0; i < 24; i++) {
+ tester.clock().advance(Duration.ofHours(1));
+ devUpgrader.run();
+ }
+ dev1.assertNotRunning(JobType.dev("us-east-1"));
+
+ // Normal confidence lets the newest version be the default again.
+ tester.upgrader().overrideConfidence(version2, Confidence.normal);
+ tester.controllerTester().computeVersionStatus();
+ assertEquals(version2, tester.newDeploymentContext("t", "a4", "default").submit().deploy().application().oldestDeployedPlatform().get());
+ assertEquals(version1, dev1.runJob(JobType.dev("us-east-1"), DeploymentContext.applicationPackage()).deployment(ZoneId.from("dev", "us-east-1")).version());
+ assertEquals(version2, dev2.runJob(JobType.dev("us-east-1"), DeploymentContext.applicationPackage()).deployment(ZoneId.from("dev", "us-east-1")).version());
+
+ for (int i = 0; i < 24; i++) {
+ tester.clock().advance(Duration.ofHours(1));
+ devUpgrader.run();
+ }
+ dev1.assertRunning(JobType.dev("us-east-1"));
+ dev1.runJob(JobType.dev("us-east-1"));
+ assertEquals(version2, dev1.deployment(ZoneId.from("dev", "us-east-1")).version());
}
@Test
@@ -2300,7 +2466,7 @@ public class DeploymentTriggerTest {
Version version3 = new Version("6.4");
tester.controllerTester().upgradeSystem(version3);
tests.runJob(systemTest) // Success in default cloud.
- .failDeployment(systemTest); // Failure in centauri cloud.
+ .failDeployment(systemTest); // Failure in centauri cloud.
tester.upgrader().run();
assertEquals(Change.of(version3), tests.instance().change());
@@ -2397,6 +2563,97 @@ public class DeploymentTriggerTest {
}
@Test
+ void testInstancesWithMultipleClouds() {
+ String spec = """
+ <deployment>
+ <parallel>
+ <instance id='separate'>
+ <test />
+ <staging />
+ <prod>
+ <region>alpha-centauri</region>
+ </prod>
+ </instance>
+ <instance id='independent'>
+ <test />
+ </instance>
+ <steps>
+ <parallel>
+ <instance id='alpha'>
+ <test />
+ <prod>
+ <region>us-east-3</region>
+ </prod>
+ </instance>
+ <instance id='beta'>
+ <test />
+ <prod>
+ <region>alpha-centauri</region>
+ </prod>
+ </instance>
+ <instance id='gamma'>
+ <test />
+ </instance>
+ </parallel>
+ <instance id='nu'>
+ <staging />
+ </instance>
+ <instance id='omega'>
+ <prod>
+ <region>alpha-centauri</region>
+ </prod>
+ </instance>
+ </steps>
+ <instance id='dependent'>
+ <prod>
+ <region>us-east-3</region>
+ </prod>
+ </instance>
+ </parallel>
+ </deployment>
+ """;
+
+ RegionName alphaCentauri = RegionName.from("alpha-centauri");
+ ZoneApiMock.Builder builder = ZoneApiMock.newBuilder().withCloud("centauri").withSystem(tester.controller().system());
+ ZoneApi testAlphaCentauri = builder.with(ZoneId.from(Environment.test, alphaCentauri)).build();
+ ZoneApi stagingAlphaCentauri = builder.with(ZoneId.from(Environment.staging, alphaCentauri)).build();
+ ZoneApi prodAlphaCentauri = builder.with(ZoneId.from(Environment.prod, alphaCentauri)).build();
+
+ tester.controllerTester().zoneRegistry().addZones(testAlphaCentauri, stagingAlphaCentauri, prodAlphaCentauri);
+ tester.controllerTester().setRoutingMethod(tester.controllerTester().zoneRegistry().zones().all().ids(), RoutingMethod.sharedLayer4);
+ tester.configServer().bootstrap(tester.controllerTester().zoneRegistry().zones().all().ids(), SystemApplication.notController());
+
+ ApplicationPackage appPackage = ApplicationPackageBuilder.fromDeploymentXml(spec);
+ DeploymentContext app = tester.newDeploymentContext("tenant", "application", "alpha").submit(appPackage).deploy();
+ app.submit(appPackage);
+ Map<JobId, List<DeploymentStatus.Job>> jobs = app.deploymentStatus().jobsToRun();
+
+ JobType centauriTest = JobType.systemTest(tester.controller().zoneRegistry(), CloudName.from("centauri"));
+ JobType centauriStaging = JobType.stagingTest(tester.controller().zoneRegistry(), CloudName.from("centauri"));
+ assertQueued("separate", jobs, centauriTest);
+ assertQueued("separate", jobs, stagingTest, centauriStaging);
+ assertQueued("independent", jobs, systemTest, centauriTest);
+ assertQueued("alpha", jobs, systemTest);
+ assertQueued("beta", jobs, centauriTest);
+ assertQueued("gamma", jobs, centauriTest);
+
+ // Once alpha runs its default system test, it also runs the centauri system test, as omega depends on it.
+ app.runJob(systemTest);
+ assertQueued("alpha", app.deploymentStatus().jobsToRun(), centauriTest);
+ }
+
+ private static void assertQueued(String instance, Map<JobId, List<DeploymentStatus.Job>> jobs, JobType... expected) {
+ List<DeploymentStatus.Job> queued = jobs.get(new JobId(ApplicationId.from("tenant", "application", instance), expected[0]));
+ Set<ZoneId> remaining = new HashSet<>();
+ for (JobType ex : expected) remaining.add(ex.zone());
+ for (DeploymentStatus.Job q : queued)
+ if ( ! remaining.remove(q.type().zone()))
+ fail("unexpected queued job for " + instance + ": " + q.type());
+ if ( ! remaining.isEmpty())
+ fail("expected tests for " + instance + " were not queued in : " + remaining);
+ }
+
+ @Test
void testNoTests() {
DeploymentContext app = tester.newDeploymentContext();
app.submit(new ApplicationPackageBuilder().systemTest().region("us-east-3").build());
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 680e69998b6..0211a052f76 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
@@ -148,8 +148,8 @@ public class ZoneRegistryMock extends AbstractComponent implements ZoneRegistry
return this;
}
- public ZoneRegistryMock setCloudAccountZones(CloudAccount cloudAccount, ZoneId... zones) {
- this.cloudAccountZones.put(cloudAccount, Set.of(zones));
+ public ZoneRegistryMock configureCloudAccount(CloudAccount cloudAccount, ZoneId... zones) {
+ this.cloudAccountZones.computeIfAbsent(cloudAccount, (k) -> new HashSet<>()).addAll(Set.of(zones));
return this;
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/RetriggerMaintainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/RetriggerMaintainerTest.java
index 69301ea91ef..174cf93286c 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/RetriggerMaintainerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/RetriggerMaintainerTest.java
@@ -11,7 +11,6 @@ import com.yahoo.vespa.hosted.controller.deployment.DeploymentTester;
import com.yahoo.vespa.hosted.controller.deployment.RetriggerEntry;
import org.junit.jupiter.api.Test;
-import java.io.IOException;
import java.time.Duration;
import java.util.List;
@@ -25,7 +24,7 @@ public class RetriggerMaintainerTest {
private final DeploymentTester tester = new DeploymentTester();
@Test
- void processes_queue() throws IOException {
+ void processes_queue() {
RetriggerMaintainer maintainer = new RetriggerMaintainer(tester.controller(), Duration.ofDays(1));
ApplicationId applicationId = ApplicationId.from("tenant", "app", "default");
var devApp = tester.newDeploymentContext(applicationId);
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/UpgraderTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/UpgraderTest.java
index 76f0cacb7c5..35ccc86d465 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/UpgraderTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/UpgraderTest.java
@@ -5,6 +5,7 @@ import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.test.ManualClock;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RevisionId;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
import com.yahoo.vespa.hosted.controller.application.Change;
@@ -41,6 +42,7 @@ import static com.yahoo.vespa.hosted.controller.deployment.DeploymentTrigger.Cha
import static com.yahoo.vespa.hosted.controller.deployment.DeploymentTrigger.ChangesToCancel.PLATFORM;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
@@ -661,8 +663,8 @@ public class UpgraderTest {
@Test
void testPinningMajorVersionInDeploymentXml() {
- Version version = Version.fromString("6.2");
- tester.controllerTester().upgradeSystem(version);
+ Version version0 = Version.fromString("6.2");
+ tester.controllerTester().upgradeSystem(version0);
ApplicationPackageBuilder builder = new ApplicationPackageBuilder().region("us-west-1").majorVersion(7);
ApplicationPackage defaultPackage = new ApplicationPackageBuilder().region("us-west-1").build();
@@ -674,7 +676,7 @@ public class UpgraderTest {
var lazyApp = tester.newDeploymentContext().submit(defaultPackage).deploy();
// New major version is released; more apps upgrade with increasing confidence.
- version = Version.fromString("7.0");
+ Version version = Version.fromString("7.0");
tester.controllerTester().upgradeSystem(version);
tester.upgrader().overrideConfidence(version, Confidence.broken);
tester.controllerTester().computeVersionStatus();
@@ -921,8 +923,20 @@ public class UpgraderTest {
instance -> instance.withChange(instance.change().withoutPin()))));
tester.upgrader().maintain();
assertEquals(version1,
- app1.instance().change().platform().orElseThrow(),
- "Application upgrades to latest allowed major");
+ app1.instance().change().platform().orElseThrow(),
+ "Application upgrades to latest allowed major");
+
+ // Version on old major becomes legacy, so app upgrades once it does not specify the old major in deployment spec.
+ app1.runJob(systemTest).runJob(stagingTest).runJob(productionUsWest1).runJob(productionUsEast3);
+ app1.submit(new ApplicationPackageBuilder().majorVersion(6).region("us-east-3").region("us-west-1").build()).deploy();
+ tester.upgrader().maintain();
+ assertEquals(Change.empty(), app1.instance().change());
+
+ app1.submit(new ApplicationPackageBuilder().region("us-east-3").region("us-west-1").build()).deploy();
+ tester.upgrader().overrideConfidence(version1, Confidence.legacy);
+ tester.controllerTester().computeVersionStatus();
+ tester.upgrader().maintain();
+ assertEquals(Change.of(version2), app1.instance().change());
}
@Test
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java
index 88da698b3f2..849261d5ae4 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java
@@ -92,6 +92,7 @@ public class ApplicationSerializerTest {
Optional.of(new SourceRevision("git@github:org/repo.git", "branch1", "commit1")),
Optional.of("william@shakespeare"),
Optional.of(Version.fromString("1.2.3")),
+ Optional.of(123),
Optional.of(Instant.ofEpochMilli(666)),
Optional.empty(),
Optional.of("best commit"),
@@ -161,6 +162,8 @@ public class ApplicationSerializerTest {
assertEquals(applicationVersion1, serialized.revisions().last().get());
assertEquals(applicationVersion1, serialized.revisions().get(serialized.instances().get(id1.instance()).deployments().get(zone1).revision()));
assertEquals(original.revisions().last(), serialized.revisions().last());
+ assertEquals(original.revisions().last().get().compileVersion(), serialized.revisions().last().get().compileVersion());
+ assertEquals(original.revisions().last().get().allowedMajor(), serialized.revisions().last().get().allowedMajor());
assertEquals(original.revisions().last().get().authorEmail(), serialized.revisions().last().get().authorEmail());
assertEquals(original.revisions().last().get().buildTime(), serialized.revisions().last().get().buildTime());
assertEquals(original.revisions().last().get().sourceUrl(), serialized.revisions().last().get().sourceUrl());
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java
index 539d6cff06d..4194131e7fb 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java
@@ -16,6 +16,7 @@ import com.yahoo.vespa.flags.InMemoryFlagSource;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.api.integration.athenz.ApplicationAction;
import com.yahoo.vespa.hosted.controller.api.integration.athenz.AthenzClientFactoryMock;
+import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockUserManagement;
import com.yahoo.vespa.hosted.controller.integration.ServiceRegistryMock;
import java.io.File;
@@ -64,6 +65,10 @@ public class ContainerTester {
return (ServiceRegistryMock) container.components().getComponent(ServiceRegistryMock.class.getName());
}
+ public MockUserManagement userManagement() {
+ return (MockUserManagement) container.components().getComponent(MockUserManagement.class.getName());
+ }
+
public void authorize(AthenzDomain tenantDomain, AthenzIdentity identity, ApplicationAction action, ApplicationName application) {
athenzClientFactory().getSetup()
.domains.get(tenantDomain)
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java
index 3b90be40a32..af0a85f1a90 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java
@@ -422,7 +422,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest {
@Test
void create_application_on_deploy() {
var application = ApplicationName.from("unique");
- var applicationPackage = new ApplicationPackageBuilder().withoutAthenzIdentity().build();
+ var applicationPackage = new ApplicationPackageBuilder().trustDefaultCertificate().withoutAthenzIdentity().build();
new ControllerTester(tester).upgradeSystem(new Version("6.1"));
assertTrue(tester.controller().applications().getApplication(TenantAndApplicationId.from(tenantName, application)).isEmpty());
@@ -482,6 +482,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest {
private void deployApplication() {
var applicationPackage = new ApplicationPackageBuilder()
+ .trustDefaultCertificate()
.instances("default")
.globalServiceId("foo")
.region("aws-us-east-1c")
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java
index 168b9b374f3..71e3607983c 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java
@@ -192,7 +192,7 @@ public class JobControllerApiHandlerHelperTest {
var region = "us-west-1";
var applicationPackage = new ApplicationPackageBuilder().region(region).build();
// Deploy directly to production zone, like integration tests, with dryRun.
- tester.controller().jobController().deploy(tester.instance().id(), productionUsWest1, Optional.empty(), applicationPackage, true);
+ tester.controller().jobController().deploy(tester.instance().id(), productionUsWest1, Optional.empty(), applicationPackage, true, true);
assertResponse(JobControllerApiHandlerHelper.jobTypeResponse(tester.controller(), app.instanceId(), URI.create("https://some.url:43/root/")),
"jobs-direct-deployment.json");
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/root.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/root.json
index 13a6391d5da..df682cf8e1b 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/root.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/root.json
@@ -37,6 +37,7 @@
"instance": "default",
"upgrading": false,
"upgradePolicy": "default",
+ "compileVersion": "6.1.0",
"jobs": [
{
"name": "system-test",
@@ -77,6 +78,7 @@
"instance": "i2",
"upgrading": false,
"upgradePolicy": "default",
+ "compileVersion": "6.1.0",
"jobs": [
{
"name": "production-us-west-1"
@@ -184,6 +186,7 @@
"instance": "default",
"upgrading": true,
"upgradePolicy": "default",
+ "compileVersion": "6.1.0",
"jobs": [
{
"name": "system-test",
@@ -263,6 +266,7 @@
"instance": "i1",
"upgrading": false,
"upgradePolicy": "default",
+ "compileVersion": "6.1.0",
"jobs": [
{
"name": "system-test",
@@ -322,6 +326,7 @@
"instance": "i2",
"upgrading": true,
"upgradePolicy": "default",
+ "compileVersion": "6.1.0",
"jobs": [
{
"name": "production-us-west-1",
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java
index f34dd3fe629..b573940d150 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java
@@ -10,6 +10,8 @@ import com.yahoo.vespa.flags.PermanentFlags;
import com.yahoo.vespa.hosted.controller.ControllerTester;
import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId;
import com.yahoo.jdisc.http.filter.security.misc.User;
+import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockUserManagement;
+import com.yahoo.vespa.hosted.controller.api.integration.user.UserId;
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;
@@ -253,6 +255,33 @@ public class UserApiTest extends ControllerContainerCloudTest {
}
@Test
+ void findUser() {
+ try (Flags.Replacer ignored = Flags.clearFlagsForTesting(PermanentFlags.MAX_TRIAL_TENANTS.id(), PermanentFlags.ENABLE_PUBLIC_SIGNUP_FLOW.id())) {
+ ContainerTester tester = new ContainerTester(container, responseFiles);
+ ((InMemoryFlagSource) tester.controller().flagSource())
+ .withBooleanFlag(PermanentFlags.ENABLE_PUBLIC_SIGNUP_FLOW.id(), true);
+ Set<Role> operator = Set.of(Role.hostedOperator(), Role.hostedSupporter(), Role.hostedAccountant());
+ User user = new User("dev@domail", "Joe Developer", "dev", null);
+
+ Role developer = Role.developer(TenantName.from("scoober"));
+ tester.userManagement().createRole(developer);
+ tester.userManagement().addToRoles(new UserId("dev@domail"), Set.of(developer));
+
+ tester.assertResponse(request("/user/v1/find?email=dev@domail")
+ .roles(operator)
+ .user(user),
+ """
+ {"users":[{"isPublic":true,"isCd":false,"hasTrialCapacity":true,"user":{"name":"dev@domail","email":"dev@domail","verified":false},"tenants":{"scoober":{"supported":false,"roles":["developer"]}},"flags":[{"id":"enable-public-signup-flow","rules":[{"value":false}]}]}]}""");
+
+ tester.assertResponse(request("/user/v1/find?query=email:dev@domail")
+ .roles(operator)
+ .user(user),
+ """
+ {"users":[]}""");
+ }
+ }
+
+ @Test
void maxTrialTenants() {
try (Flags.Replacer ignored = Flags.clearFlagsForTesting(PermanentFlags.MAX_TRIAL_TENANTS.id(), PermanentFlags.ENABLE_PUBLIC_SIGNUP_FLOW.id())) {
ContainerTester tester = new ContainerTester(container, responseFiles);
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java
index 7477b94e3f4..cd8a9e72051 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java
@@ -17,7 +17,6 @@ import org.junit.jupiter.api.Test;
import java.net.URI;
import java.util.List;
-import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -114,7 +113,7 @@ public class RotationRepositoryTest {
// We're now out of rotations and next deployment fails
var application3 = tester.newDeploymentContext("tenant3", "app3", "default");
application3.submit(applicationPackage)
- .runJobExpectingFailure(DeploymentContext.systemTest, Optional.of("out of rotations"));
+ .runJobExpectingFailure(DeploymentContext.systemTest, "out of rotations");
}
@Test
@@ -123,7 +122,7 @@ public class RotationRepositoryTest {
.globalServiceId("foo")
.region("us-east-3")
.build();
- application.submit(applicationPackage).runJobExpectingFailure(DeploymentContext.systemTest, Optional.of("less than 2 prod zones are defined"));
+ application.submit(applicationPackage).runJobExpectingFailure(DeploymentContext.systemTest, "less than 2 prod zones are defined");
}
@Test
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java
index 6cb7c059b1d..a0e3c63e58b 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java
@@ -4,7 +4,6 @@ package com.yahoo.vespa.hosted.controller.versions;
import com.yahoo.component.Version;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.HostName;
-import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.zone.ZoneApi;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.ControllerTester;
@@ -28,7 +27,6 @@ import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.Map;
-import java.util.OptionalInt;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -91,8 +89,7 @@ public class VersionStatusTest {
HostName controller3 = HostName.of("controller-3");
MockCuratorDb db = new MockCuratorDb(Stream.of(controller1, controller2, controller3)
.map(hostName -> hostName.value() + ":2222")
- .collect(Collectors.joining(",")),
- SystemName.main);
+ .collect(Collectors.joining(",")));
ControllerTester tester = new ControllerTester(db);
writeControllerVersion(controller1, Version.fromString("6.2"), db);
@@ -525,8 +522,7 @@ public class VersionStatusTest {
HostName controller3 = HostName.of("controller-3");
MockCuratorDb db = new MockCuratorDb(Stream.of(controller1, controller2, controller3)
.map(hostName -> hostName.value() + ":2222")
- .collect(Collectors.joining(",")),
- SystemName.main);
+ .collect(Collectors.joining(",")));
DeploymentTester tester = new DeploymentTester(new ControllerTester(db));
// Commit details are set for initial version