diff options
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 { |