aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--container-accesslogging/src/main/java/com/yahoo/container/logging/AccessLog.java3
-rw-r--r--container-core/src/main/java/com/yahoo/container/jdisc/ThreadedHttpRequestHandler.java1
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java20
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationList.java29
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java60
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java61
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java8
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java1
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OutstandingChangeDeployerTest.java6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/UpgraderTest.java55
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/root.json123
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java10
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServlet.java57
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SetMembershipNode.java1
14 files changed, 286 insertions, 149 deletions
diff --git a/container-accesslogging/src/main/java/com/yahoo/container/logging/AccessLog.java b/container-accesslogging/src/main/java/com/yahoo/container/logging/AccessLog.java
index 4356843ef3a..c22345bad79 100644
--- a/container-accesslogging/src/main/java/com/yahoo/container/logging/AccessLog.java
+++ b/container-accesslogging/src/main/java/com/yahoo/container/logging/AccessLog.java
@@ -10,6 +10,7 @@ import java.net.URI;
/**
* Logs to all the configured access logs.
+ *
* @author tonytv
*/
public class AccessLog {
@@ -25,7 +26,7 @@ public class AccessLog {
return new AccessLog(new ComponentRegistry<>());
}
- public void log(final AccessLogEntry accessLogEntry) {
+ public void log(AccessLogEntry accessLogEntry) {
for (AccessLogInterface log: implementers.allComponents()) {
log.log(accessLogEntry);
}
diff --git a/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedHttpRequestHandler.java b/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedHttpRequestHandler.java
index 802a7ce778c..670c48bb339 100644
--- a/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedHttpRequestHandler.java
+++ b/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedHttpRequestHandler.java
@@ -26,7 +26,6 @@ import java.util.logging.Logger;
* @author hmusum
* @author Steinar Knutsen
* @author bratseth
- * @since 5.1
*/
public abstract class ThreadedHttpRequestHandler extends ThreadedRequestHandler {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
index 12ebfa625ac..26debf3083f 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
@@ -337,11 +337,16 @@ public class ApplicationController {
store(application); // store missing information even if we fail deployment below
}
- // Ensure that the deploying change is tested
- if (! canDeployDirectlyTo(zone, options) &&
- ! application.deploymentJobs().isDeployableTo(zone.environment(), application.deploying()))
- throw new IllegalArgumentException("Rejecting deployment of " + application + " to " + zone +
- " as " + application.deploying().get() + " is not tested");
+ if ( ! canDeployDirectlyTo(zone, options)) { // validate automated deployment
+ if (!application.deploymentJobs().isDeployableTo(zone.environment(), application.deploying()))
+ throw new IllegalArgumentException("Rejecting deployment of " + application + " to " + zone +
+ " as " + application.deploying().get() + " is not tested");
+ Deployment existingDeployment = application.deployments().get(zone);
+ if (existingDeployment != null && existingDeployment.version().isAfter(version))
+ throw new IllegalArgumentException("Rejecting deployment of " + application + " to " + zone +
+ " as the requested version " + version + " is older than" +
+ " the current version " + existingDeployment.version());
+ }
// Carry out deployment
DeploymentId deploymentId = new DeploymentId(applicationId, zone);
@@ -356,7 +361,8 @@ public class ApplicationController {
// Use info from previous deployments is available
Deployment previousDeployment = application.deployments().getOrDefault(zone, new Deployment(zone, revision, version, clock.instant()));
Deployment newDeployment = new Deployment(zone, revision, version, clock.instant(),
- previousDeployment.clusterUtils(), previousDeployment.clusterInfo(), previousDeployment.metrics());
+ previousDeployment.clusterUtils(),
+ previousDeployment.clusterInfo(), previousDeployment.metrics());
application = application.with(newDeployment);
store(application);
@@ -623,7 +629,7 @@ public class ApplicationController {
/** Returns whether a direct deployment to given zone is allowed */
private static boolean canDeployDirectlyTo(Zone zone, DeployOptions options) {
- return !options.screwdriverBuildJob.isPresent() ||
+ return ! options.screwdriverBuildJob.isPresent() ||
options.screwdriverBuildJob.get().screwdriverId == null ||
zone.environment().isManuallyDeployed();
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationList.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationList.java
index a0d038c0e8d..710d2ad6492 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationList.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationList.java
@@ -11,6 +11,7 @@ import com.yahoo.vespa.hosted.controller.ApplicationController;
import java.time.Instant;
import java.util.Comparator;
import java.util.List;
+import java.util.Optional;
import java.util.stream.Stream;
/**
@@ -47,21 +48,35 @@ public class ApplicationList {
// ----------------------------------- Filters
- /** Returns the subset of applications which is currently upgrading to the given version */
+ /** Returns the subset of applications which are currently upgrading (to any version) */
+ public ApplicationList upgrading() {
+ return listOf(list.stream().filter(application -> isUpgrading(application)));
+ }
+
+ /** Returns the subset of applications which are currently upgrading to the given version */
public ApplicationList upgradingTo(Version version) {
return listOf(list.stream().filter(application -> isUpgradingTo(version, application)));
}
- /** Returns the subset of applications which is currently upgrading to a version lower than the given version */
+ /** Returns the subset of applications which are currently upgrading to a version lower than the given version */
public ApplicationList upgradingToLowerThan(Version version) {
return listOf(list.stream().filter(application -> isUpgradingToLowerThan(version, application)));
}
- /** Returns the subset of applications which is currently not upgrading to the given version */
+ /** Returns the subset of applications which are currently not upgrading to the given version */
public ApplicationList notUpgradingTo(Version version) {
return listOf(list.stream().filter(application -> ! isUpgradingTo(version, application)));
}
+ /**
+ * Returns the subset of applications which are currently not upgrading to the given version,
+ * or returns all if no version is specified
+ */
+ public ApplicationList notUpgradingTo(Optional<Version> version) {
+ if ( ! version.isPresent()) return this;
+ return notUpgradingTo(version.get());
+ }
+
/** Returns the subset of applications which is currently not deploying a new application revision */
public ApplicationList notDeployingApplication() {
return listOf(list.stream().filter(application -> ! isDeployingApplicationChange(application)));
@@ -155,7 +170,13 @@ public class ApplicationList {
}
// ----------------------------------- Internal helpers
-
+
+ private static boolean isUpgrading(Application application) {
+ if ( ! (application.deploying().isPresent()) ) return false;
+ if ( ! (application.deploying().get() instanceof Change.VersionChange) ) return false;
+ return true;
+ }
+
private static boolean isUpgradingTo(Version version, Application application) {
if ( ! (application.deploying().isPresent()) ) return false;
if ( ! (application.deploying().get() instanceof Change.VersionChange) ) return false;
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java
index 131d89fd650..21dc62ea789 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java
@@ -1,6 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.deployment;
+import com.yahoo.component.Version;
import com.yahoo.config.application.api.DeploymentSpec;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.SystemName;
@@ -12,6 +13,7 @@ import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.LockedApplication;
import com.yahoo.vespa.hosted.controller.application.ApplicationList;
import com.yahoo.vespa.hosted.controller.application.Change;
+import com.yahoo.vespa.hosted.controller.application.Deployment;
import com.yahoo.vespa.hosted.controller.application.DeploymentJobs;
import com.yahoo.vespa.hosted.controller.application.DeploymentJobs.JobError;
import com.yahoo.vespa.hosted.controller.application.DeploymentJobs.JobReport;
@@ -155,22 +157,28 @@ public class DeploymentTrigger {
* newer (different) than the one last completed successfully in next
*/
private boolean changesAvailable(Application application, JobStatus previous, JobStatus next) {
- if ( ! previous.lastSuccess().isPresent()) return false;
-
if ( ! application.deploying().isPresent()) return false;
Change change = application.deploying().get();
- if (change instanceof Change.VersionChange && // the last completed is out of date - don't continue with it
- ! ((Change.VersionChange)change).version().equals(previous.lastSuccess().get().version()))
- return false;
+
+ if ( ! previous.lastSuccess().isPresent() &&
+ ! productionJobHasSucceededFor(previous, change)) return false;
+
+ if (change instanceof Change.VersionChange) {
+ Version targetVersion = ((Change.VersionChange)change).version();
+ if ( ! (targetVersion.equals(previous.lastSuccess().get().version())) )
+ return false; // version is outdated
+ if (isOnNewerVersionInProductionThan(targetVersion, application, next.type()))
+ return false; // Don't downgrade
+ }
if (next == null) return true;
if ( ! next.lastSuccess().isPresent()) return true;
-
+
JobStatus.JobRun previousSuccess = previous.lastSuccess().get();
JobStatus.JobRun nextSuccess = next.lastSuccess().get();
if (previousSuccess.revision().isPresent() && ! previousSuccess.revision().get().equals(nextSuccess.revision().get()))
return true;
- if (! previousSuccess.version().equals(nextSuccess.version()))
+ if ( ! previousSuccess.version().equals(nextSuccess.version()))
return true;
return false;
}
@@ -396,6 +404,10 @@ public class DeploymentTrigger {
if ( ! deploysTo(application, jobType)) return false;
// Ignore applications that are not associated with a project
if ( ! application.deploymentJobs().projectId().isPresent()) return false;
+ if (application.deploying().isPresent() && application.deploying().get() instanceof Change.VersionChange) {
+ Version targetVersion = ((Change.VersionChange)application.deploying().get()).version();
+ if (isOnNewerVersionInProductionThan(targetVersion, application, jobType)) return false; // Don't downgrade
+ }
return true;
}
@@ -404,6 +416,40 @@ public class DeploymentTrigger {
return application.deploymentJobs().jobStatus().entrySet().stream()
.anyMatch(entry -> entry.getKey().isProduction() && entry.getValue().isRunning(jobTimeoutLimit()));
}
+
+ /**
+ * When upgrading it is ok to trigger the next job even if the previous failed if the previous has earlier succeeded
+ * on the version we are currently upgrading to
+ */
+ private boolean productionJobHasSucceededFor(JobStatus jobStatus, Change change) {
+ if ( ! (change instanceof Change.VersionChange) ) return false;
+ if ( ! isProduction(jobStatus.type())) return false;
+ Optional<JobStatus.JobRun> lastSuccess = jobStatus.lastSuccess();
+ if ( ! lastSuccess.isPresent()) return false;
+ return lastSuccess.get().version().equals(((Change.VersionChange)change).version());
+ }
+
+ /**
+ * Returns whether the current deployed version in the zone given by the job
+ * is newer than the given version. This may be the case even if the production job
+ * in question failed, if the failure happens after deployment.
+ * In that case we should never deploy an earlier version as that may potentially
+ * downgrade production nodes which we are not guaranteed to support.
+ */
+ private boolean isOnNewerVersionInProductionThan(Version version, Application application, JobType job) {
+ if ( ! isProduction(job)) return false;
+ Optional<Zone> zone = job.zone(controller.system());
+ if ( ! zone.isPresent()) return false;
+ Deployment existingDeployment = application.deployments().get(zone.get());
+ if (existingDeployment == null) return false;
+ return existingDeployment.version().isAfter(version);
+ }
+
+ private boolean isProduction(JobType job) {
+ Optional<Zone> zone = job.zone(controller.system());
+ if ( ! zone.isPresent()) return false; // arbitrary
+ return zone.get().environment() == Environment.prod;
+ }
private boolean acceptNewRevisionNow(LockedApplication application) {
if ( ! application.deploying().isPresent()) return true;
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java
index 44b15053a8c..36b87e4cead 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java
@@ -12,6 +12,9 @@ import com.yahoo.vespa.hosted.controller.versions.VespaVersion;
import com.yahoo.yolean.Exceptions;
import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -39,29 +42,36 @@ public class Upgrader extends Maintainer {
*/
@Override
public void maintain() {
- VespaVersion target = controller().versionStatus().version(controller().systemVersion());
- if (target == null) return; // we don't have information about the current system version at this time
-
- switch (target.confidence()) {
- case broken:
- ApplicationList toCancel = applications().upgradingTo(target.versionNumber())
- .without(UpgradePolicy.canary);
- if (toCancel.isEmpty()) break;
- log.info("Version " + target.versionNumber() + " is broken, cancelling upgrades of non-canaries");
- cancelUpgradesOf(toCancel);
- break;
- case low:
- upgrade(applications().with(UpgradePolicy.canary), target.versionNumber());
- break;
- case normal:
- upgrade(applications().with(UpgradePolicy.defaultPolicy), target.versionNumber());
- break;
- case high:
- upgrade(applications().with(UpgradePolicy.conservative), target.versionNumber());
- break;
- default:
- throw new IllegalArgumentException("Unknown version confidence " + target.confidence());
- }
+ ApplicationList applications = applications();
+
+ // Determine target versions for each upgrade policy
+ Optional<Version> canaryTarget = controller().versionStatus().systemVersion().map(VespaVersion::versionNumber);
+ Optional<Version> defaultTarget = newestVersionWithConfidence(VespaVersion.Confidence.normal);
+ Optional<Version> conservativeTarget = newestVersionWithConfidence(VespaVersion.Confidence.high);
+
+ // Cancel any upgrades to the wrong targets
+ cancelUpgradesOf(applications.with(UpgradePolicy.canary).upgrading().notUpgradingTo(canaryTarget));
+ cancelUpgradesOf(applications.with(UpgradePolicy.defaultPolicy).upgrading().notUpgradingTo(defaultTarget));
+ cancelUpgradesOf(applications.with(UpgradePolicy.conservative).upgrading().notUpgradingTo(conservativeTarget));
+
+ // Schedule the right upgrades
+ canaryTarget.ifPresent(target -> upgrade(applications.with(UpgradePolicy.canary), target));
+ defaultTarget.ifPresent(target -> upgrade(applications.with(UpgradePolicy.defaultPolicy), target));
+ conservativeTarget.ifPresent(target -> upgrade(applications.with(UpgradePolicy.conservative), target));
+ }
+
+ private Optional<Version> newestVersionWithConfidence(VespaVersion.Confidence confidence) {
+ return reversed(controller().versionStatus().versions()).stream()
+ .filter(v -> v.confidence().equalOrHigherThan(confidence))
+ .findFirst()
+ .map(VespaVersion::versionNumber);
+ }
+
+ private List<VespaVersion> reversed(List<VespaVersion> versions) {
+ List<VespaVersion> reversed = new ArrayList<>(versions.size());
+ for (int i = 0; i < versions.size(); i++)
+ reversed.add(versions.get(versions.size() - 1 - i));
+ return reversed;
}
/** Returns a list of all applications */
@@ -89,9 +99,10 @@ public class Upgrader extends Maintainer {
}
private void cancelUpgradesOf(ApplicationList applications) {
- for (Application application : applications.asList()) {
+ if (applications.isEmpty()) return;
+ log.info("Cancelling upgrading of " + applications.asList().size() + " applications");
+ for (Application application : applications.asList())
controller().applications().deploymentTrigger().cancelChange(application.id());
- }
}
/** Returns the number of applications to upgrade in this run */
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 1541e4d35f8..de42a9fba4e 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
@@ -120,6 +120,7 @@ public class VespaVersion implements Comparable<VespaVersion> {
return ((VespaVersion)other).versionNumber().equals(this.versionNumber());
}
+ /** The confidence of a version. */
public enum Confidence {
/** This version has been proven defective */
@@ -132,7 +133,12 @@ public class VespaVersion implements Comparable<VespaVersion> {
normal,
/** We have overwhelming evidence that this version is working */
- high
+ high;
+
+ /** Returns true if this confidence is at least as high as the given confidence */
+ public boolean equalOrHigherThan(Confidence other) {
+ return this.compareTo(other) >= 0;
+ }
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java
index 5af5dac714f..79fd717a24f 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java
@@ -96,6 +96,7 @@ public class DeploymentTester {
}
public void updateVersionStatus(Version currentVersion) {
+ configServer().setDefaultVersion(currentVersion);
controller().updateVersionStatus(VersionStatus.compute(controller(), currentVersion));
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OutstandingChangeDeployerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OutstandingChangeDeployerTest.java
index 78b4f7f895f..4886eba40b6 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OutstandingChangeDeployerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/OutstandingChangeDeployerTest.java
@@ -24,13 +24,13 @@ public class OutstandingChangeDeployerTest {
@Test
public void testChangeDeployer() {
DeploymentTester tester = new DeploymentTester();
+ tester.configServer().setDefaultVersion(new Version(6, 1));
OutstandingChangeDeployer deployer = new OutstandingChangeDeployer(tester.controller(), Duration.ofMinutes(10),
new JobControl(new MockCuratorDb()));
-
tester.createAndDeploy("app1", 11, "default");
tester.createAndDeploy("app2", 22, "default");
- Version version = new Version(5, 2);
+ Version version = new Version(6, 2);
tester.deploymentTrigger().triggerChange(tester.application("app1").id(), new Change.VersionChange(version));
assertEquals(new Change.VersionChange(version), tester.application("app1").deploying().get());
@@ -52,5 +52,5 @@ public class OutstandingChangeDeployerTest {
assertEquals(DeploymentJobs.JobType.systemTest.id(), jobs.get(0).jobName());
assertFalse(tester.application("app1").hasOutstandingChange());
}
-
+
}
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 7261bb3f61e..0414cda3f55 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
@@ -9,6 +9,7 @@ import com.yahoo.test.ManualClock;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.ControllerTester;
import com.yahoo.vespa.hosted.controller.application.ApplicationPackage;
+import com.yahoo.vespa.hosted.controller.application.Change;
import com.yahoo.vespa.hosted.controller.application.Deployment;
import com.yahoo.vespa.hosted.controller.application.DeploymentJobs;
import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder;
@@ -32,10 +33,8 @@ public class UpgraderTest {
public void testUpgrading() {
// --- Setup
DeploymentTester tester = new DeploymentTester();
- tester.upgrader().maintain();
- assertEquals("No system version: Nothing to do", 0, tester.buildSystem().jobs().size());
- Version version = Version.fromString("5.0"); // (lower than the hardcoded version in the config server client)
+ Version version = Version.fromString("5.0");
tester.updateVersionStatus(version);
tester.upgrader().maintain();
@@ -146,7 +145,55 @@ public class UpgraderTest {
tester.updateVersionStatus(version);
tester.upgrader().maintain();
- assertEquals("Nothing to do", 0, tester.buildSystem().jobs().size());
+ assertEquals("Applications are on 5.3 - nothing to do", 0, tester.buildSystem().jobs().size());
+
+ // --- Starting upgrading to a new version which breaks, causing upgrades to commence on the previous version
+ version = Version.fromString("5.4");
+ Application default3 = tester.createAndDeploy("default3", 5, "default"); // need 4 to break a version
+ Application default4 = tester.createAndDeploy("default4", 5, "default");
+ tester.updateVersionStatus(version);
+ tester.upgrader().maintain(); // cause canary upgrades to 5.4
+ tester.completeUpgrade(canary0, version, "canary");
+ tester.completeUpgrade(canary1, version, "canary");
+ tester.updateVersionStatus(version);
+ assertEquals(VespaVersion.Confidence.normal, tester.controller().versionStatus().systemVersion().get().confidence());
+ tester.upgrader().maintain();
+ assertEquals("Upgrade of defaults are scheduled", 5, tester.buildSystem().jobs().size());
+ assertEquals(version, ((Change.VersionChange)tester.application(default0.id()).deploying().get()).version());
+ assertEquals(version, ((Change.VersionChange)tester.application(default1.id()).deploying().get()).version());
+ assertEquals(version, ((Change.VersionChange)tester.application(default2.id()).deploying().get()).version());
+ assertEquals(version, ((Change.VersionChange)tester.application(default3.id()).deploying().get()).version());
+ assertEquals(version, ((Change.VersionChange)tester.application(default4.id()).deploying().get()).version());
+ tester.completeUpgrade(default0, version, "default");
+ // State: Default applications started upgrading to 5.4 (and one completed)
+ version = Version.fromString("5.5");
+ tester.updateVersionStatus(version);
+ tester.upgrader().maintain(); // cause canary upgrades to 5.5
+ tester.completeUpgrade(canary0, version, "canary");
+ tester.completeUpgrade(canary1, version, "canary");
+ tester.updateVersionStatus(version);
+ assertEquals(VespaVersion.Confidence.normal, tester.controller().versionStatus().systemVersion().get().confidence());
+ tester.upgrader().maintain();
+ assertEquals("Upgrade of defaults are scheduled", 5, tester.buildSystem().jobs().size());
+ assertEquals(version, ((Change.VersionChange)tester.application(default0.id()).deploying().get()).version());
+ assertEquals(version, ((Change.VersionChange)tester.application(default1.id()).deploying().get()).version());
+ assertEquals(version, ((Change.VersionChange)tester.application(default2.id()).deploying().get()).version());
+ assertEquals(version, ((Change.VersionChange)tester.application(default3.id()).deploying().get()).version());
+ assertEquals(version, ((Change.VersionChange)tester.application(default4.id()).deploying().get()).version());
+ // State: Default applications started upgrading to 5.5
+ tester.completeUpgradeWithError(default0, version, "default", DeploymentJobs.JobType.stagingTest);
+ tester.completeUpgradeWithError(default1, version, "default", DeploymentJobs.JobType.stagingTest);
+ tester.completeUpgradeWithError(default2, version, "default", DeploymentJobs.JobType.stagingTest);
+ tester.completeUpgradeWithError(default3, version, "default", DeploymentJobs.JobType.productionUsWest1);
+ tester.completeUpgrade(default4, version, "default");
+ tester.updateVersionStatus(version);
+ assertEquals(VespaVersion.Confidence.broken, tester.controller().versionStatus().systemVersion().get().confidence());
+ tester.upgrader().maintain();
+ assertEquals("Upgrade of defaults are scheduled on 5.4 instead, since 5.5 broken",
+ 3, tester.buildSystem().jobs().size());
+ assertEquals("5.4", ((Change.VersionChange)tester.application(default1.id()).deploying().get()).version().toString());
+ assertEquals("5.4", ((Change.VersionChange)tester.application(default2.id()).deploying().get()).version().toString());
+ assertEquals("5.4", ((Change.VersionChange)tester.application(default3.id()).deploying().get()).version().toString());
}
@Test
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 00bd1ed8208..7fd000b82c5 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
@@ -1,80 +1,79 @@
{
- "versions": [
+ "versions":[
{
- "version": "(ignore)",
- "confidence": "high",
- "commit": "(ignore)",
- "date": 0,
- "controllerVersion": false,
- "systemVersion": false,
- "configServers": [],
- "failingApplications": [],
- "productionApplications": [
+ "version":"(ignore)",
+ "confidence":"high",
+ "commit":"(ignore)",
+ "date":0,
+ "controllerVersion":false,
+ "systemVersion":false,
+ "configServers":[
+
+ ],
+ "failingApplications":[
+
+ ],
+ "productionApplications":[
{
- "tenant": "tenant1",
- "application": "application1",
- "instance": "default",
- "url": "http://localhost:8080/application/v4/tenant/tenant1/application/application1",
- "upgradePolicy": "default"
+ "tenant":"tenant1",
+ "application":"application1",
+ "instance":"default",
+ "url":"http://localhost:8080/application/v4/tenant/tenant1/application/application1",
+ "upgradePolicy":"default"
}
]
},
{
- "version": "(ignore)",
- "confidence": "normal",
- "commit": "(ignore)",
- "date": 0,
- "controllerVersion": false,
- "systemVersion": false,
- "configServers": [],
- "failingApplications": [
+ "version":"(ignore)",
+ "confidence":"normal",
+ "commit":"(ignore)",
+ "date":0,
+ "controllerVersion":false,
+ "systemVersion":true,
+ "configServers":[
+ {
+ "hostname":"config1.test"
+ },
{
- "tenant": "tenant1",
- "application": "application1",
- "instance": "default",
- "url": "http://localhost:8080/application/v4/tenant/tenant1/application/application1",
- "upgradePolicy": "default",
- "failingSince": "(ignore)"
+ "hostname":"config2.test"
}
],
- "productionApplications": [
+ "failingApplications":[
{
- "tenant": "tenant2",
- "application": "application2",
- "instance": "default",
- "url": "http://localhost:8080/application/v4/tenant/tenant2/application/application2",
- "upgradePolicy": "default"
+ "tenant":"tenant1",
+ "application":"application1",
+ "instance":"default",
+ "url":"http://localhost:8080/application/v4/tenant/tenant1/application/application1",
+ "upgradePolicy":"default",
+ "failingSince":"(ignore)"
}
- ]
- },
- {
- "version": "(ignore)",
- "confidence": "normal",
- "commit": "(ignore)",
- "date": 0,
- "controllerVersion": false,
- "systemVersion": true,
- "configServers": [
- {
- "hostname": "config1.test"
- },
+ ],
+ "productionApplications":[
{
- "hostname": "config2.test"
+ "tenant":"tenant2",
+ "application":"application2",
+ "instance":"default",
+ "url":"http://localhost:8080/application/v4/tenant/tenant2/application/application2",
+ "upgradePolicy":"default"
}
- ],
- "failingApplications": [],
- "productionApplications": []
+ ]
},
{
- "version": "(ignore)",
- "confidence": "normal",
- "commit": "(ignore)",
- "date": 0,
- "controllerVersion": true,
- "systemVersion": false,
- "configServers": [],
- "failingApplications": [],
- "productionApplications": []
+ "version":"(ignore)",
+ "confidence":"normal",
+ "commit":"(ignore)",
+ "date":0,
+ "controllerVersion":true,
+ "systemVersion":false,
+ "configServers":[
+
+ ],
+ "failingApplications":[
+
+ ],
+ "productionApplications":[
+
+ ]
}
]
-}
+} \ No newline at end of file
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 bc31079cfe0..519c457e73b 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
@@ -201,7 +201,7 @@ public class VersionStatusTest {
assertTrue("Status for version without applications is removed",
tester.controller().versionStatus().versions().stream()
.noneMatch(vespaVersion -> vespaVersion.versionNumber().equals(version1)));
-
+
// Another default application upgrades, raising confidence to high
tester.completeUpgrade(default8, version2, "default");
tester.updateVersionStatus();
@@ -231,8 +231,14 @@ public class VersionStatusTest {
Confidence.high, confidence(tester.controller(), version2));
assertEquals("40% of defaults failed: Broken",
VespaVersion.Confidence.broken, confidence(tester.controller(), version3));
- }
+ // Test version order
+ List<VespaVersion> versions = tester.controller().versionStatus().versions();
+ assertEquals(3, versions.size());
+ assertEquals("5", versions.get(0).versionNumber().toString());
+ assertEquals("5.2", versions.get(1).versionNumber().toString());
+ assertEquals("5.3", versions.get(2).versionNumber().toString());
+ }
@Test
public void testIgnoreConfigdeince() {
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServlet.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServlet.java
index f396d676afd..543cf8ab43e 100644
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServlet.java
+++ b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServlet.java
@@ -23,13 +23,13 @@ import static com.yahoo.jdisc.http.core.HttpServletRequestUtils.getConnection;
import static com.yahoo.jdisc.http.server.jetty.ConnectorFactory.JDiscServerConnector;
/**
- * @author <a href="mailto:simon@yahoo-inc.com">Simon Thoresen Hult</a>
+ * @author Simon Thoresen Hult
* @author bjorncs
*/
@WebServlet(asyncSupported = true, description = "Bridge between Servlet and JDisc APIs")
class JDiscHttpServlet extends HttpServlet {
- public static final String ATTRIBUTE_NAME_ACCESS_LOG_ENTRY
- = JDiscHttpServlet.class.getName() + "_access-log-entry";
+
+ public static final String ATTRIBUTE_NAME_ACCESS_LOG_ENTRY = JDiscHttpServlet.class.getName() + "_access-log-entry";
private final static Logger log = Logger.getLogger(JDiscHttpServlet.class.getName());
private final JDiscContext context;
@@ -39,49 +39,48 @@ class JDiscHttpServlet extends HttpServlet {
}
@Override
- protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
dispatchHttpRequest(request, response);
}
@Override
- protected void doPost(final HttpServletRequest request, final HttpServletResponse response)
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
dispatchHttpRequest(request, response);
}
@Override
- protected void doHead(final HttpServletRequest request, final HttpServletResponse response)
+ protected void doHead(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
dispatchHttpRequest(request, response);
}
@Override
- protected void doPut(final HttpServletRequest request, final HttpServletResponse response)
+ protected void doPut(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
dispatchHttpRequest(request, response);
}
@Override
- protected void doDelete(final HttpServletRequest request, final HttpServletResponse response)
+ protected void doDelete(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
dispatchHttpRequest(request, response);
}
@Override
- protected void doOptions(final HttpServletRequest request, final HttpServletResponse response)
+ protected void doOptions(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
dispatchHttpRequest(request, response);
}
@Override
- protected void doTrace(final HttpServletRequest request, final HttpServletResponse response)
+ protected void doTrace(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
dispatchHttpRequest(request, response);
}
- private static final Set<String> JETTY_UNSUPPORTED_METHODS = new HashSet<>(Arrays.asList(
- "PATCH"));
+ private static final Set<String> JETTY_UNSUPPORTED_METHODS = new HashSet<>(Arrays.asList("PATCH"));
/**
* Override to set connector attribute before the request becomes an upgrade request in the web socket case.
@@ -89,7 +88,8 @@ class JDiscHttpServlet extends HttpServlet {
*/
@SuppressWarnings("deprecation")
@Override
- protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ protected void service(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
request.setAttribute(JDiscServerConnector.REQUEST_ATTRIBUTE, getConnector(request));
Metric.Context metricContext = getMetricContext(request);
@@ -108,25 +108,21 @@ class JDiscHttpServlet extends HttpServlet {
return (JDiscServerConnector)getConnection(request).getConnector();
}
- private void dispatchHttpRequest(final HttpServletRequest request,
- final HttpServletResponse response) throws IOException {
- final AccessLogEntry accessLogEntry = new AccessLogEntry();
+ private void dispatchHttpRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ AccessLogEntry accessLogEntry = new AccessLogEntry();
AccessLogRequestLog.populateAccessLogEntryFromHttpServletRequest(request, accessLogEntry);
request.setAttribute(ATTRIBUTE_NAME_ACCESS_LOG_ENTRY, accessLogEntry);
try {
switch (request.getDispatcherType()) {
- case REQUEST:
- new HttpRequestDispatch(context,
- accessLogEntry,
- getMetricContext(request),
- request, response).dispatch();
- break;
- default:
- if (log.isLoggable(Level.INFO)) {
- log.info("Unexpected " + request.getDispatcherType() + "; "
- + formatAttributes(request));
- }
- break;
+ case REQUEST:
+ new HttpRequestDispatch(context, accessLogEntry, getMetricContext(request), request, response)
+ .dispatch();
+ break;
+ default:
+ if (log.isLoggable(Level.INFO)) {
+ log.info("Unexpected " + request.getDispatcherType() + "; " + formatAttributes(request));
+ }
+ break;
}
} catch (OverloadException e) {
// nop
@@ -136,12 +132,11 @@ class JDiscHttpServlet extends HttpServlet {
}
private static Metric.Context getMetricContext(ServletRequest request) {
- return JDiscServerConnector.fromRequest(request)
- .getMetricContext();
+ return JDiscServerConnector.fromRequest(request).getMetricContext();
}
private static String formatAttributes(final HttpServletRequest request) {
- final StringBuilder out = new StringBuilder();
+ StringBuilder out = new StringBuilder();
out.append("attributes = {");
for (Enumeration<String> names = request.getAttributeNames(); names.hasMoreElements(); ) {
String name = names.nextElement();
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SetMembershipNode.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SetMembershipNode.java
index de600cb7519..f8e44f1087c 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SetMembershipNode.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SetMembershipNode.java
@@ -12,7 +12,6 @@ import java.util.*;
* A node which returns true or false depending on a set membership test
*
* @author bratseth
- * @since 5.1.21
*/
public class SetMembershipNode extends BooleanNode {