summaryrefslogtreecommitdiffstats
path: root/controller-server
diff options
context:
space:
mode:
Diffstat (limited to 'controller-server')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java20
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/UpgraderTest.java37
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java36
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java4
5 files changed, 82 insertions, 21 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index 2f0a7f6196c..10bf0d2aa4f 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -3043,9 +3043,23 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
private void ensureApplicationExists(TenantAndApplicationId id, HttpRequest request) {
if (controller.applications().getApplication(id).isEmpty()) {
- log.fine("Application does not exist in public, creating: " + id);
- var credentials = accessControlRequests.credentials(id.tenant(), null /* not used on public */ , request.getJDiscRequest());
- controller.applications().createApplication(id, credentials);
+ if (controller.system().isPublic() || hasOktaContext(request)) {
+ log.fine("Application does not exist in public, creating: " + id);
+ var credentials = accessControlRequests.credentials(id.tenant(), null /* not used on public */ , request.getJDiscRequest());
+ controller.applications().createApplication(id, credentials);
+ } else {
+ log.fine("Application does not exist in hosted, failing: " + id);
+ throw new IllegalArgumentException("Application does not exist. Create application in Console first.");
+ }
+ }
+ }
+
+ private boolean hasOktaContext(HttpRequest request) {
+ try {
+ OAuthCredentials.fromOktaRequestContext(request.getJDiscRequest().context());
+ return true;
+ } catch (IllegalArgumentException e) {
+ return false;
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java
index 0814e9ea6ec..46bcd3b85c0 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java
@@ -44,7 +44,7 @@ public record VespaVersion(Version version,
if ( ! failingOnThis.with(UpgradePolicy.canary).isEmpty())
return Confidence.broken;
- // 'broken' if 4 non-canary was broken by this, and that is at least 5% of all
+ // 'broken' if 6 non-canary was broken by this, and that is at least 5% of all
if (nonCanaryApplicationsBroken(statistics.version(), failingOnThis, productionOnThis))
return Confidence.broken;
@@ -161,9 +161,9 @@ public record VespaVersion(Version version,
if (productionNonCanaries.size() + failingNonCanaries.size() == 0) return false;
- // 'broken' if 4 non-canary was broken by this, and that is at least 5% of all
+ // 'broken' if 6 non-canary was broken by this, and that is at least 5% of all
int brokenByThisVersion = failingNonCanaries.size();
- return brokenByThisVersion >= 4 && brokenByThisVersion >= productionOnThis.size() * 0.05;
+ return brokenByThisVersion >= 6 && brokenByThisVersion >= productionOnThis.size() * 0.05;
}
}
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 35ccc86d465..45038fc4a63 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
@@ -189,6 +189,7 @@ public class UpgraderTest {
// --- Starting upgrading to a new version which breaks, causing upgrades to commence on the previous version
var default3 = createAndDeploy("default3", "default");
var default4 = createAndDeploy("default4", "default");
+ var default5 = createAndDeploy("default5", "default");
Version version4 = Version.fromString("6.6");
tester.controllerTester().upgradeSystem(version4);
tester.upgrader().maintain(); // cause canary upgrades to new version
@@ -200,8 +201,8 @@ public class UpgraderTest {
tester.upgrader().maintain();
tester.triggerJobs();
- assertEquals(10, tester.jobs().active().size(), "Upgrade of defaults are scheduled");
- for (var context : List.of(default0, default1, default2, default3, default4))
+ assertEquals(12, tester.jobs().active().size(), "Upgrade of defaults are scheduled");
+ for (var context : List.of(default0, default1, default2, default3, default4, default5))
assertEquals(version4, context.instance().change().platform().get());
default0.deployPlatform(version4);
@@ -218,9 +219,9 @@ public class UpgraderTest {
tester.upgrader().maintain();
tester.triggerJobs();
- assertEquals(10, tester.jobs().active().size(), "Upgrade of defaults are scheduled");
+ assertEquals(12, tester.jobs().active().size(), "Upgrade of defaults are scheduled");
assertEquals(version5, default0.instance().change().platform().get());
- for (var context : List.of(default1, default2, default3, default4))
+ for (var context : List.of(default1, default2, default3, default4, default5))
assertEquals(version4, context.instance().change().platform().get());
default1.deployPlatform(version4);
@@ -233,6 +234,10 @@ public class UpgraderTest {
.runJob(stagingTest)
.failDeployment(productionUsWest1);
+ default5.runJob(systemTest)
+ .runJob(stagingTest)
+ .failDeployment(productionUsWest1);
+
// State: Default applications started upgrading to version5
tester.clock().advance(Duration.ofHours(1));
tester.upgrader().maintain();
@@ -247,10 +252,12 @@ public class UpgraderTest {
default3.runJob(systemTest)
.runJob(stagingTest)
.failDeployment(productionUsWest1);
+ default4.failDeployment(systemTest);
+ default5.failDeployment(systemTest);
+
tester.controllerTester().computeVersionStatus();
assertEquals(VespaVersion.Confidence.broken, tester.controller().readVersionStatus().systemVersion().get().confidence());
-
tester.upgrader().maintain();
assertEquals(version4, default3.instance().change().platform().get());
}
@@ -311,10 +318,10 @@ public class UpgraderTest {
assertEquals(20, tester.jobs().active().size(), "Canaries done: Should upgrade defaults");
default0.deployPlatform(version);
- for (var context : List.of(default1, default2, default3, default4))
+ for (var context : List.of(default1, default2, default3, default4, default5, default6))
context.failDeployment(systemTest);
- // > 40% and at least 4 failed - version is broken
+ // > 60% and at least 6 failed - version is broken
tester.controllerTester().computeVersionStatus();
tester.upgrader().maintain();
tester.abortAll();
@@ -342,6 +349,8 @@ public class UpgraderTest {
var default2 = createAndDeploy("default2", "default");
var default3 = createAndDeploy("default3", "default");
var default4 = createAndDeploy("default4", "default");
+ var default5 = createAndDeploy("default5", "default");
+ var default6 = createAndDeploy("default6", "default");
// V1 is released
Version v1 = Version.fromString("6.3");
@@ -372,27 +381,33 @@ public class UpgraderTest {
assertEquals(VespaVersion.Confidence.normal, tester.controller().readVersionStatus().systemVersion().get().confidence());
// We "manually" cancel upgrades to V1 so that we can use the applications to make V2 fail instead
- // But we keep one (default4) to avoid V1 being garbage collected
+ // But we keep one (default6) to avoid V1 being garbage collected
tester.deploymentTrigger().cancelChange(default0.instanceId(), ALL);
tester.deploymentTrigger().cancelChange(default1.instanceId(), ALL);
tester.deploymentTrigger().cancelChange(default2.instanceId(), ALL);
tester.deploymentTrigger().cancelChange(default3.instanceId(), ALL);
+ tester.deploymentTrigger().cancelChange(default4.instanceId(), ALL);
+ tester.deploymentTrigger().cancelChange(default5.instanceId(), ALL);
default0.abortJob(systemTest).abortJob(stagingTest);
default1.abortJob(systemTest).abortJob(stagingTest);
default2.abortJob(systemTest).abortJob(stagingTest);
default3.abortJob(systemTest).abortJob(stagingTest);
+ default4.abortJob(systemTest).abortJob(stagingTest);
+ default5.abortJob(systemTest).abortJob(stagingTest);
// Applications with default policy start upgrading to V2
tester.upgrader().maintain();
tester.triggerJobs();
- assertEquals(10, tester.jobs().active().size(), "Upgrade scheduled for remaining apps");
- assertEquals(v1, default4.instance().change().platform().get(), "default4 is still upgrading to 6.3");
+ assertEquals(14, tester.jobs().active().size(), "Upgrade scheduled for remaining apps");
+ assertEquals(v1, default6.instance().change().platform().get(), "default6 is still upgrading to 6.3");
// 4/5 applications fail (in the last prod zone) and lowers confidence
default0.runJob(systemTest).runJob(stagingTest).runJob(productionUsWest1).failDeployment(productionUsEast3);
default1.runJob(systemTest).runJob(stagingTest).runJob(productionUsWest1).failDeployment(productionUsEast3);
default2.runJob(systemTest).runJob(stagingTest).runJob(productionUsWest1).failDeployment(productionUsEast3);
default3.runJob(systemTest).runJob(stagingTest).runJob(productionUsWest1).failDeployment(productionUsEast3);
+ default4.runJob(systemTest).runJob(stagingTest).runJob(productionUsWest1).failDeployment(productionUsEast3);
+ default5.runJob(systemTest).runJob(stagingTest).runJob(productionUsWest1).failDeployment(productionUsEast3);
tester.controllerTester().computeVersionStatus();
assertEquals(VespaVersion.Confidence.broken, tester.controller().readVersionStatus().systemVersion().get().confidence());
@@ -402,7 +417,7 @@ public class UpgraderTest {
tester.abortAll();
tester.triggerJobs();
- assertEquals(10, tester.jobs().active().size(), "Upgrade to 5.1 scheduled for apps not completely on 5.1 or 5.2");
+ assertEquals(14, tester.jobs().active().size(), "Upgrade to 5.1 scheduled for apps not completely on 5.1 or 5.2");
// prod zone on 5.2 (usWest1) is skipped, but we still trigger the next zone from triggerReadyJobs:
default0.runJob(systemTest).runJob(stagingTest).runJob(productionUsEast3);
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 ed4f0597fad..0f03333146f 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
@@ -102,6 +102,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.joining;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
@@ -1647,7 +1648,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
}
@Test
- void create_application_on_deploy() {
+ void create_application_on_deploy_with_okta() {
// Setup
createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID);
addUserToHostedOperatorRole(HostedAthenzIdentities.from(HOSTED_VESPA_OPERATOR));
@@ -1669,13 +1670,42 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploy/dev-us-east-1/", POST)
.data(entity)
.oAuthCredentials(OKTA_CREDENTIALS)
-
.userIdentity(USER_ID),
- "{\"message\":\"Deployment started in run 1 of dev-us-east-1 for tenant1.application1.instance1. This may take about 15 minutes the first time.\",\"run\":1}");
+ """
+ {"message":"Deployment started in run 1 of dev-us-east-1 for tenant1.application1.instance1. This may take about 15 minutes the first time.","run":1}""");
assertTrue(tester.controller().applications().getApplication(appId).isPresent());
}
+ @Test
+ void create_application_on_deploy_with_athenz() {
+ // 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\"}")
+ .oAuthCredentials(OKTA_CREDENTIALS),
+ new File("tenant-without-applications.json"));
+
+ // Deploy application
+ var id = ApplicationId.from("tenant1", "application1", "instance1");
+ var appId = TenantAndApplicationId.from(id);
+ var entity = createApplicationDeployData(applicationPackageInstance1);
+
+ assertTrue(tester.controller().applications().getApplication(appId).isEmpty());
+
+ // POST (deploy) an application to start a manual deployment to dev
+ tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploy/dev-us-east-1/", POST)
+ .data(entity)
+ .userIdentity(USER_ID),
+ """
+ {"error-code":"BAD_REQUEST","message":"Application does not exist. Create application in Console first."}""", 400);
+
+ assertFalse(tester.controller().applications().getApplication(appId).isPresent());
+ }
+
private static String serializeInstant(Instant i) {
return DateTimeFormatter.ISO_INSTANT.format(i.truncatedTo(ChronoUnit.SECONDS));
}
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 ab262a1a3c5..72179aa669c 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
@@ -367,11 +367,13 @@ public class VersionStatusTest {
default1.failDeployment(stagingTest);
default2.failDeployment(stagingTest);
default3.failDeployment(stagingTest);
+ default4.failDeployment(stagingTest);
+ default5.failDeployment(stagingTest);
tester.controllerTester().computeVersionStatus();
assertEquals(Confidence.high, confidence(tester.controller(), version0), "Confidence remains unchanged for version0: High");
assertEquals(Confidence.high, confidence(tester.controller(), version2), "Confidence remains unchanged for version2: High");
- assertEquals(VespaVersion.Confidence.broken, confidence(tester.controller(), version3), "40% of defaults failed: Broken");
+ assertEquals(VespaVersion.Confidence.broken, confidence(tester.controller(), version3), "60% of defaults failed: Broken");
// Test version order
List<VespaVersion> versions = tester.controller().readVersionStatus().versions();