diff options
author | Arnstein Ressem <aressem@gmail.com> | 2016-06-23 19:57:21 +0200 |
---|---|---|
committer | Arnstein Ressem <aressem@gmail.com> | 2016-06-23 19:57:21 +0200 |
commit | df405ef07648824ffabf9b58ad1bfd748cfdfe59 (patch) | |
tree | 327364e06af2308b069395bbd0c6bbfe3dc50e18 | |
parent | db4c6902603fce39000aabc79c8265f8a687412d (diff) | |
parent | 521f3b8266a1386c44550ceac93a8a41a5ba4f4d (diff) |
Merge branch 'master' into aressem/make-rpm-installation-work-the-way-it-is-described-in-doc
92 files changed, 336 insertions, 247 deletions
diff --git a/.gitignore b/.gitignore index c9bd860bf2f..8f47a77af57 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ CMakeCache.txt CTestTestfile.cmake cmake_install.cmake Makefile +Testing diff --git a/bootstrap.sh b/bootstrap.sh index 2c896ec868d..940179ef020 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,10 +1,28 @@ #!/bin/bash -e # Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -FULL=false +usage() { + echo "Usage: $0 [full | java | default]" >&2 +} -if [ "$1" = "full" ]; then - FULL=true +if [ $# -eq 0 ]; then + # Build minimal set of java modules required to run cmake + MODE=default +elif [ "$1" = "full" ]; then + # Build all java modules required by C++ testing + MODE=full +elif [ "$1" = "java" ]; then + # Build minial set of java modules requires to run mvn install from the source root + MODE=java +elif [ "$1" = "default" ]; then + : +elif [ "$1" = "-h" -o "$1" = "--help" ]; then + usage + exit 0 +else + echo "Unknown argument: $1" >&2 + usage + exit 1 fi mvn_install() { @@ -29,10 +47,14 @@ for module in $MODULES; do done mvn_install -am -pl config-class-plugin -rf configgen -if $FULL; then - # Build all java modules required by C++ testing - mvn_install -am -pl filedistributionmanager,jrt,linguistics,messagebus -rf yolean -else - # Build minimal set of java modules required to run cmake - mvn_install -am -pl filedistributionmanager -rf yolean -fi + +case "$MODE" in + java) + ;; + full) + mvn_install -am -pl filedistributionmanager,jrt,linguistics,messagebus -rf yolean + ;; + default) + mvn_install -am -pl filedistributionmanager -rf yolean + ;; +esac diff --git a/config-application-package/pom.xml b/config-application-package/pom.xml index d280af8dc28..7f49e9fb8b6 100644 --- a/config-application-package/pom.xml +++ b/config-application-package/pom.xml @@ -92,11 +92,6 @@ <artifactId>jackson-databind</artifactId> </dependency> <dependency> - <groupId>com.google.guava</groupId> - <artifactId>guava</artifactId> - <scope>provided</scope> - </dependency> - <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> @@ -121,7 +116,6 @@ <configuration> <compilerArgs> <arg>-Xlint:all</arg> - <arg>-Xlint:-try</arg> <arg>-Werror</arg> </compilerArgs> </configuration> diff --git a/config-application-package/src/main/java/com/yahoo/config/model/application/provider/Bundle.java b/config-application-package/src/main/java/com/yahoo/config/model/application/provider/Bundle.java index 8f2026afc66..b7e80a6abe8 100644 --- a/config-application-package/src/main/java/com/yahoo/config/model/application/provider/Bundle.java +++ b/config-application-package/src/main/java/com/yahoo/config/model/application/provider/Bundle.java @@ -1,16 +1,14 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.model.application.provider; -import com.google.common.base.Charsets; import com.yahoo.collections.Tuple2; -import com.yahoo.config.codegen.CNode; import com.yahoo.vespa.config.util.ConfigUtils; import java.io.*; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipException; @@ -171,7 +169,7 @@ public class Bundle { return new StringReader(""); } try { - return new InputStreamReader(bundle.jarFile.getInputStream(zipEntry), Charsets.UTF_8); + return new InputStreamReader(bundle.jarFile.getInputStream(zipEntry), StandardCharsets.UTF_8); } catch (IOException e) { throw new IllegalArgumentException("IOException", e); } diff --git a/config-application-package/src/test/java/com/yahoo/config/application/ConfigDefinitionDirTest.java b/config-application-package/src/test/java/com/yahoo/config/application/ConfigDefinitionDirTest.java index ada517c9a5c..5d0766229e4 100644 --- a/config-application-package/src/test/java/com/yahoo/config/application/ConfigDefinitionDirTest.java +++ b/config-application-package/src/test/java/com/yahoo/config/application/ConfigDefinitionDirTest.java @@ -1,10 +1,11 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.application; -import com.google.common.io.Files; import com.yahoo.config.model.application.provider.Bundle; import com.yahoo.io.IOUtils; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; @@ -23,9 +24,12 @@ public class ConfigDefinitionDirTest { private static final String bundleFileName = "com.yahoo.searcher1.jar"; private static final File bundleFile = new File("src/test/resources/defdircomponent/" + bundleFileName); + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Test public void require_that_defs_are_added() throws IOException { - File defDir = Files.createTempDir(); + File defDir = temporaryFolder.newFolder(); ConfigDefinitionDir dir = new ConfigDefinitionDir(defDir); Bundle bundle = new Bundle(new JarFile(bundleFile), bundleFile); assertThat(defDir.listFiles().length, is(0)); @@ -36,7 +40,7 @@ public class ConfigDefinitionDirTest { @Test public void require_that_conflicting_defs_are_not_added() throws IOException { - File defDir = Files.createTempDir(); + File defDir = temporaryFolder.newFolder(); IOUtils.writeFile(new File(defDir, "foo.def"), "alreadyexists", false); ConfigDefinitionDir dir = new ConfigDefinitionDir(defDir); Bundle bundle = new Bundle(new JarFile(bundleFile), bundleFile); diff --git a/config-application-package/src/test/java/com/yahoo/config/model/application/provider/FilesApplicationFileTest.java b/config-application-package/src/test/java/com/yahoo/config/model/application/provider/FilesApplicationFileTest.java index ac207de7231..b1c0d78b299 100644 --- a/config-application-package/src/test/java/com/yahoo/config/model/application/provider/FilesApplicationFileTest.java +++ b/config-application-package/src/test/java/com/yahoo/config/model/application/provider/FilesApplicationFileTest.java @@ -1,10 +1,11 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.model.application.provider; -import com.google.common.io.Files; import com.yahoo.config.application.api.ApplicationFile; import com.yahoo.config.application.api.ApplicationFileTest; import com.yahoo.path.Path; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; import java.io.File; @@ -14,9 +15,12 @@ import java.io.File; */ public class FilesApplicationFileTest extends ApplicationFileTest { + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Override public ApplicationFile getApplicationFile(Path path) throws Exception { - File tmp = Files.createTempDir(); + File tmp = temporaryFolder.newFolder(); writeAppTo(tmp); return new FilesApplicationFile(path, new File(tmp, path.getRelative())); } diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ApplicationId.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ApplicationId.java index c326e6d25c1..c068af49b5f 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/ApplicationId.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ApplicationId.java @@ -1,7 +1,6 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.provision; -import com.google.inject.Inject; import com.yahoo.cloud.config.ApplicationIdConfig; /** diff --git a/config/.gitignore b/config/.gitignore index 170b98b585f..f2098c8a392 100644 --- a/config/.gitignore +++ b/config/.gitignore @@ -1,4 +1,3 @@ /pom.xml.build /target Makefile -Testing diff --git a/configd/.gitignore b/configd/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/configd/.gitignore +++ b/configd/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/configdefinitions/.gitignore b/configdefinitions/.gitignore index aa75679bac6..7f99529b963 100644 --- a/configdefinitions/.gitignore +++ b/configdefinitions/.gitignore @@ -2,4 +2,3 @@ configdefinitions.iml target /pom.xml.build Makefile -Testing diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/GetConfigProcessor.java b/configserver/src/main/java/com/yahoo/vespa/config/server/GetConfigProcessor.java index 95a84629881..1861965947c 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/GetConfigProcessor.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/GetConfigProcessor.java @@ -13,7 +13,6 @@ import com.yahoo.vespa.config.UnknownConfigIdException; import com.yahoo.vespa.config.protocol.*; import com.yahoo.vespa.config.util.ConfigUtils; -import java.net.UnknownHostException; import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/RpcServer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/RpcServer.java index 53c54045bf6..a1c17a93022 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/RpcServer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/RpcServer.java @@ -20,7 +20,6 @@ import com.yahoo.log.LogLevel; import com.yahoo.vespa.config.ErrorCode; import com.yahoo.vespa.config.JRTMethods; import com.yahoo.vespa.config.protocol.ConfigResponse; -import com.yahoo.vespa.config.protocol.JRTConfigRequest; import com.yahoo.vespa.config.protocol.JRTServerConfigRequest; import com.yahoo.vespa.config.protocol.JRTServerConfigRequestV3; import com.yahoo.vespa.config.protocol.Trace; @@ -289,7 +288,6 @@ public class RpcServer implements Runnable, ReloadListener, TenantListener { } RequestHandler handler = context.requestHandler(); return handler.resolveConfig(context.applicationId(), request, vespaVersion); - } protected Supervisor getSupervisor() { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/model/SuperModel.java b/configserver/src/main/java/com/yahoo/vespa/config/server/model/SuperModel.java index 1d34d4a0c00..c6aa5ed7f8e 100755 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/model/SuperModel.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/model/SuperModel.java @@ -45,7 +45,7 @@ public class SuperModel implements LbServicesConfig.Producer, RoutingConfig.Prod getConfig(builder); return ConfigPayload.fromInstance(new RoutingConfig(builder)); } else { - return null; + throw new RuntimeException(configKey + " is not valid when asking for config from SuperModel"); } } diff --git a/configutil/.gitignore b/configutil/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/configutil/.gitignore +++ b/configutil/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/defaults/.gitignore b/defaults/.gitignore index d2a86c8103d..12d711807b0 100644 --- a/defaults/.gitignore +++ b/defaults/.gitignore @@ -10,4 +10,3 @@ target *.iws /pom.xml.build Makefile -Testing diff --git a/document/.gitignore b/document/.gitignore index e23d1d9f4e9..7a18138fa03 100644 --- a/document/.gitignore +++ b/document/.gitignore @@ -11,4 +11,3 @@ libexec target /pom.xml.build Makefile -Testing diff --git a/documentapi/.gitignore b/documentapi/.gitignore index 9690261769a..57e44062f77 100644 --- a/documentapi/.gitignore +++ b/documentapi/.gitignore @@ -2,4 +2,3 @@ documentapi.iml target /pom.xml.build Makefile -Testing diff --git a/fastlib/.gitignore b/fastlib/.gitignore index d94143dba02..d52d93b8dda 100644 --- a/fastlib/.gitignore +++ b/fastlib/.gitignore @@ -11,4 +11,3 @@ include lib update.log Makefile -Testing diff --git a/fastos/.gitignore b/fastos/.gitignore index 70fbbb55a20..54e2680a6d8 100644 --- a/fastos/.gitignore +++ b/fastos/.gitignore @@ -9,4 +9,3 @@ include lib update.log Makefile -Testing diff --git a/fbench/.gitignore b/fbench/.gitignore index 069dac5c201..2b7330e0c48 100644 --- a/fbench/.gitignore +++ b/fbench/.gitignore @@ -4,4 +4,3 @@ doc include lib Makefile -Testing diff --git a/filedistribution/.gitignore b/filedistribution/.gitignore index 542ce6cebef..77f7a1d62f2 100644 --- a/filedistribution/.gitignore +++ b/filedistribution/.gitignore @@ -4,4 +4,3 @@ project.dsw /pom.xml.build /target Makefile -Testing diff --git a/filedistribution/src/vespa/filedistribution/distributor/filedownloader.cpp b/filedistribution/src/vespa/filedistribution/distributor/filedownloader.cpp index 57fae9df6ee..1af58514fb9 100644 --- a/filedistribution/src/vespa/filedistribution/distributor/filedownloader.cpp +++ b/filedistribution/src/vespa/filedistribution/distributor/filedownloader.cpp @@ -141,7 +141,7 @@ struct FileDownloader::EventHandler BOOST_THROW_EXCEPTION(std::runtime_error(alert.message())); } void operator()(const libtorrent::fastresume_rejected_alert& alert) const { - LOG(info, "alert %s: %s", alert.what(), alert.message().c_str()); + LOG(debug, "alert %s: %s", alert.what(), alert.message().c_str()); } void operator()(const libtorrent::torrent_delete_failed_alert& alert) const { LOG(warning, "alert %s: %s", alert.what(), alert.message().c_str()); diff --git a/fnet/.gitignore b/fnet/.gitignore index 1ec479be9bc..b5f5f1915cd 100644 --- a/fnet/.gitignore +++ b/fnet/.gitignore @@ -7,4 +7,3 @@ include lib update.log Makefile -Testing diff --git a/frtstream/.gitignore b/frtstream/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/frtstream/.gitignore +++ b/frtstream/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/fsa/.gitignore b/fsa/.gitignore index be0452bed21..4b160dd6a2e 100644 --- a/fsa/.gitignore +++ b/fsa/.gitignore @@ -1,4 +1,3 @@ /target /pom.xml.build Makefile -Testing diff --git a/jrt_test/.gitignore b/jrt_test/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/jrt_test/.gitignore +++ b/jrt_test/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/jrt_test/src/java/.gitignore b/jrt_test/src/java/.gitignore index c7d02fa8c22..ce75892238c 100644 --- a/jrt_test/src/java/.gitignore +++ b/jrt_test/src/java/.gitignore @@ -1,3 +1,4 @@ build.inc classes jrt-test.jar +/java_code_compiled diff --git a/juniper/.gitignore b/juniper/.gitignore index 92af948a4ce..0c9cc229d0e 100644 --- a/juniper/.gitignore +++ b/juniper/.gitignore @@ -6,4 +6,3 @@ juniper.mak lib project.dsw Makefile -Testing diff --git a/logd/.gitignore b/logd/.gitignore index fd963ca589b..91220ac384b 100644 --- a/logd/.gitignore +++ b/logd/.gitignore @@ -3,4 +3,3 @@ conf /target /pom.xml.build Makefile -Testing diff --git a/lowercasing_test/.gitignore b/lowercasing_test/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/lowercasing_test/.gitignore +++ b/lowercasing_test/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/memfilepersistence/.gitignore b/memfilepersistence/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/memfilepersistence/.gitignore +++ b/memfilepersistence/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/messagebus/.gitignore b/messagebus/.gitignore index b79b059b0a7..a5c2cde721d 100644 --- a/messagebus/.gitignore +++ b/messagebus/.gitignore @@ -4,4 +4,3 @@ messagebus-lib.iml target /pom.xml.build Makefile -Testing diff --git a/metrics/.gitignore b/metrics/.gitignore index cb87b051cf2..a9b9304101f 100644 --- a/metrics/.gitignore +++ b/metrics/.gitignore @@ -2,4 +2,3 @@ /target /pom.xml.build Makefile -Testing diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java index d4a955cf746..a88fb016e23 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java @@ -244,11 +244,18 @@ public final class Node { dirty, /** This node has failed and must be repaired or removed. The node retains any allocation data for diagnosis. */ - failed; + failed, + + /** + * This node should not currently be used. + * This state follows the same rules as failed except that it will never be automatically moved out of + * this state. + */ + parked; /** Returns whether this is a state where the node is assigned to an application */ public boolean isAllocated() { - return this == reserved || this == active || this == inactive || this == failed; + return this == reserved || this == active || this == inactive || this == failed || this == parked; } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java index aff65652399..11892c69c1c 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java @@ -49,7 +49,7 @@ import java.util.stream.Collectors; // 1) (new) - > provisioned -> ready -> reserved -> active -> inactive -> dirty -> ready // 2) inactive -> reserved // 3) reserved -> dirty -// 3) * -> failed -> dirty | active | (removed) +// 3) * -> failed | parked -> dirty | active | (removed) // Nodes have an application assigned when in states reserved, active and inactive. // Nodes might have an application assigned in dirty. public class NodeRepository extends AbstractComponent { @@ -180,11 +180,16 @@ public class NodeRepository extends AbstractComponent { return performOn(NodeListFilter.from(nodes), node -> zkClient.writeTo(Node.State.dirty, node)); } - /** Deallocate a node which is in the failed state. Use this to recycle failed nodes which have been repaired. */ + /** + * Deallocate a node which is in the failed or parked state. + * Use this to recycle failed nodes which have been repaired or put on hold. + */ public Node deallocate(String hostname) { Optional<Node> nodeToDeallocate = getNode(Node.State.failed, hostname); if ( ! nodeToDeallocate.isPresent()) - throw new IllegalArgumentException("Could not deallocate " + hostname + ": Node not found in the failed state"); + nodeToDeallocate = getNode(Node.State.parked, hostname); + if ( ! nodeToDeallocate.isPresent()) + throw new IllegalArgumentException("Could not deallocate " + hostname + ": No such node in the failed or parked state"); return deallocate(Collections.singletonList(nodeToDeallocate.get())).get(0); } @@ -199,12 +204,22 @@ public class NodeRepository extends AbstractComponent { } /** - * Moves a previously failed node back to the active state. + * Parks this node and returns it in its new state. + * + * @return the node in its new state + * @throws IllegalArgumentException if the node is not found + */ + public Node park(String hostname) { + return move(hostname, Node.State.parked); + } + + /** + * Moves a previously failed or parked node back to the active state. * * @return the node in its new state * @throws IllegalArgumentException if the node is not found */ - public Node unfail(String hostname) { + public Node reactivate(String hostname) { return move(hostname, Node.State.active); } @@ -218,15 +233,18 @@ public class NodeRepository extends AbstractComponent { } /** - * Removes a node. A node must be in the failed state before it can be removed. + * Removes a node. A node must be in the failed or parked state before it can be removed. * * @return true if the node was removed, false if it was not found */ public boolean remove(String hostname) { Optional<Node> nodeToRemove = getNode(Node.State.failed, hostname); - if ( ! nodeToRemove.isPresent()) return false; + if ( ! nodeToRemove.isPresent()) + nodeToRemove = getNode(Node.State.parked, hostname); + if ( ! nodeToRemove.isPresent()) + return false; try (Mutex lock = lock(nodeToRemove.get())) { - return zkClient.removeNode(Node.State.failed, hostname); + return zkClient.removeNode(nodeToRemove.get().state(), hostname); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ApplicationMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ApplicationMaintainer.java index d12c7f2a5ae..ce7ae429c40 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ApplicationMaintainer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ApplicationMaintainer.java @@ -18,7 +18,7 @@ import java.util.stream.Collectors; * The application maintainer regularly redeploys all applications. * This is necessary because applications may gain and lose active nodes due to nodes being moved to and from the * failed state. This is corrected by redeploying the applications periodically. - * It can not (at this point) be done reliably synchronously as part of the fail/unfail call due to the need for this + * It can not (at this point) be done reliably synchronously as part of the fail/reactivate call due to the need for this * to happen at a node having the deployer. * * @author bratseth diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailer.java index c18aacea284..ba2586a95fd 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailer.java @@ -3,7 +3,6 @@ package com.yahoo.vespa.hosted.provision.maintenance; import com.yahoo.config.provision.Deployer; import com.yahoo.config.provision.Deployment; -import com.yahoo.log.LogLevel; import com.yahoo.transaction.Mutex; import com.yahoo.vespa.applicationmodel.ApplicationInstance; import com.yahoo.vespa.applicationmodel.ServiceCluster; @@ -25,6 +24,7 @@ import java.util.List; import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.stream.Collectors; /** * Maintains information in the node repo about when this node last responded to ping @@ -59,17 +59,23 @@ public class NodeFailer extends Maintainer { @Override protected void maintain() { - List<Node> downNodes = maintainDownStatus(); - - for (Node node : downNodes) { - // Grace time before failing the node + for (Node node : determineActiveNodeDownStatus()) { Instant graceTimeEnd = node.history().event(History.Event.Type.down).get().at().plus(downTimeLimit); - if (graceTimeEnd.isBefore(clock.instant()) && ! applicationSuspended(node)) - fail(node); + failActive(node); + } + + for (Node node : readyNodesWithHardwareFailure()) { + nodeRepository().fail(node.hostname()); } } + private List<Node> readyNodesWithHardwareFailure() { + return nodeRepository().getNodes(Node.Type.tenant, Node.State.ready).stream() + .filter(n -> n.status().hardwareFailure()) + .collect(Collectors.toList()); + } + private boolean applicationSuspended(Node node) { try { return orchestrator.getApplicationInstanceStatus(node.allocation().get().owner()) @@ -86,7 +92,7 @@ public class NodeFailer extends Maintainer { * * @return a list of all nodes which are positively currently in the down state */ - private List<Node> maintainDownStatus() { + private List<Node> determineActiveNodeDownStatus() { List<Node> downNodes = new ArrayList<>(); for (ApplicationInstance<ServiceMonitorStatus> application : serviceMonitor.queryStatusOfAllApplicationInstances().values()) { for (ServiceCluster<ServiceMonitorStatus> cluster : application.serviceClusters()) { @@ -133,7 +139,7 @@ public class NodeFailer extends Maintainer { * which is when the node repo has available capacity to replace the node. * Otherwise not replacing the node ensures (by Orchestrator check) that no further action will be taken. */ - private void fail(Node node) { + private void failActive(Node node) { Optional<Deployment> deployment = deployer.deployFromLocalActive(node.allocation().get().owner(), Duration.ofMinutes(30)); if ( ! deployment.isPresent()) return; // this will be done at another config server @@ -147,7 +153,7 @@ public class NodeFailer extends Maintainer { catch (RuntimeException e) { // The expected reason for deployment to fail here is that there is no capacity available to redeploy. // In that case we should leave the node in the active state to avoid failing additional nodes. - nodeRepository().unfail(node.hostname()); + nodeRepository().reactivate(node.hostname()); log.log(Level.WARNING, "Attempted to fail " + node + " for " + node.allocation().get().owner() + ", but redeploying without the node failed", e); } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/filter/StateFilter.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/filter/StateFilter.java index a605835c11c..e7368e7770c 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/filter/StateFilter.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/filter/StateFilter.java @@ -48,5 +48,4 @@ public class StateFilter extends NodeFilter { return new StateFilter(HostFilter.split(states).stream().map(Node.State::valueOf).collect(Collectors.toSet()), next); } - } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java index 6805862baf3..813941de1eb 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java @@ -228,13 +228,14 @@ public class CuratorDatabaseClient { private String toDir(Node.State state) { switch (state) { - case provisioned: return "provisioned"; - case ready: return "ready"; - case reserved: return "reserved"; case active: return "allocated"; // legacy name - case inactive: return "deallocated"; // legacy name case dirty: return "dirty"; case failed: return "failed"; + case inactive: return "deallocated"; // legacy name + case parked : return "parked"; + case provisioned: return "provisioned"; + case ready: return "ready"; + case reserved: return "reserved"; default: throw new RuntimeException("Node state " + state + " does not map to a directory name"); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java index 004cceee7cb..e4b745bcfd2 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java @@ -212,7 +212,7 @@ public class NodeSerializer { switch (typeString) { case nodeTypeTenant : return Node.Type.tenant; case nodeTypeHost : return Node.Type.host; - // TODO: Remove this when all data is converted + // TODO: Remove this when 6.13 is released everywhere case "" : return Node.Type.tenant; } throw new IllegalArgumentException("Unknown node type '" + typeString + "'"); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodeStateSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodeStateSerializer.java index 321a75421a2..fa74605b32f 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodeStateSerializer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodeStateSerializer.java @@ -28,6 +28,7 @@ public class NodeStateSerializer { addMapping(Node.State.dirty, "dirty"); addMapping(Node.State.failed, "failed"); addMapping(Node.State.inactive, "inactive"); + addMapping(Node.State.parked, "parked"); addMapping(Node.State.provisioned, "provisioned"); addMapping(Node.State.ready, "ready"); addMapping(Node.State.reserved, "reserved"); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesApiHandler.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesApiHandler.java index 8c388fbd4db..2ce682a36af 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesApiHandler.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesApiHandler.java @@ -14,10 +14,10 @@ import com.yahoo.vespa.config.SlimeUtils; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.node.Configuration; +import com.yahoo.vespa.hosted.provision.node.NodeFlavors; import com.yahoo.vespa.hosted.provision.node.filter.ApplicationFilter; import com.yahoo.vespa.hosted.provision.node.filter.NodeFilter; import com.yahoo.vespa.hosted.provision.node.filter.NodeHostFilter; -import com.yahoo.vespa.hosted.provision.node.NodeFlavors; import com.yahoo.vespa.hosted.provision.node.filter.ParentHostFilter; import com.yahoo.vespa.hosted.provision.node.filter.StateFilter; import com.yahoo.vespa.hosted.provision.restapi.v2.NodesResponse.ResponseType; @@ -59,7 +59,7 @@ public class NodesApiHandler extends LoggingRequestHandler { switch (request.getMethod()) { case GET: return handleGET(request); case PUT: return handlePUT(request); - case POST: return handlePOST(request); + case POST: return isPatchOverride(request) ? handlePATCH(request) : handlePOST(request); case DELETE: return handleDELETE(request); case PATCH: return handlePATCH(request); default: return ErrorResponse.methodNotAllowed("Method '" + request.getMethod() + "' is not supported"); @@ -99,12 +99,16 @@ public class NodesApiHandler extends LoggingRequestHandler { nodeRepository.fail(lastElement(path)); return new MessageResponse("Moved " + lastElement(path) + " to failed"); } + else if (path.startsWith("/nodes/v2/state/parked/")) { + nodeRepository.park(lastElement(path)); + return new MessageResponse("Moved " + lastElement(path) + " to parked"); + } else if (path.startsWith("/nodes/v2/state/dirty/")) { nodeRepository.deallocate(lastElement(path)); return new MessageResponse("Moved " + lastElement(path) + " to dirty"); } else if (path.startsWith("/nodes/v2/state/active/")) { - nodeRepository.unfail(lastElement(path)); + nodeRepository.reactivate(lastElement(path)); return new MessageResponse("Moved " + lastElement(path) + " to active"); } else { @@ -221,7 +225,12 @@ public class NodesApiHandler extends LoggingRequestHandler { if ( ! node.isPresent()) node = nodeRepository.getNode(Node.State.failed, hostname); if ( ! node.isPresent()) - throw new IllegalArgumentException("Could not set " + hostname + " ready: Not registered as provisioned, dirty or failed"); + node = nodeRepository.getNode(Node.State.parked, hostname); + if ( ! node.isPresent()) + throw new IllegalArgumentException("Could not set " + hostname + " ready: Not registered as provisioned, dirty, failed or parked"); + + if (node.get().allocation().isPresent()) + throw new IllegalArgumentException("Could not set " + hostname + " ready: Node is allocated and must be moved to dirty instead"); nodeRepository.setReady(Collections.singletonList(node.get())); return "Moved " + hostname + " to ready"; @@ -246,4 +255,17 @@ public class NodesApiHandler extends LoggingRequestHandler { return path.substring(lastSlash + 1, path.length()); } + private boolean isPatchOverride(HttpRequest request) { + //Since Jersey's HttpUrlConnector does not support PATCH we support this by override this on POST requests. + String override = request.getHeader("X-HTTP-Method-Override"); + if (override != null) { + if (override.equals("PATCH")) { + return true; + } else { + String msg = String.format("Illegal X-HTTP-Method-Override header for POST request. Accepts 'PATCH' but got '%s'", override); + throw new IllegalArgumentException(msg); + } + } + return false; + } } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ApplicationMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ApplicationMaintainerTest.java index 636d56da1df..e034b185a02 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ApplicationMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ApplicationMaintainerTest.java @@ -56,43 +56,42 @@ public class ApplicationMaintainerTest { // Create applications fixture.activate(); - // Fail some nodes + // Fail and park some nodes nodeRepository.fail(nodeRepository.getNodes(fixture.app1).get(3).hostname()); nodeRepository.fail(nodeRepository.getNodes(fixture.app2).get(0).hostname()); - nodeRepository.fail(nodeRepository.getNodes(fixture.app2).get(4).hostname()); + nodeRepository.park(nodeRepository.getNodes(fixture.app2).get(4).hostname()); int failedInApp1 = 1; - int failedInApp2 = 2; + int failedOrParkedInApp2 = 2; assertEquals(fixture.wantedNodesApp1 - failedInApp1, nodeRepository.getNodes(fixture.app1, Node.State.active).size()); - assertEquals(fixture.wantedNodesApp2 - failedInApp2, nodeRepository.getNodes(fixture.app2, Node.State.active).size()); - assertEquals(failedInApp1 + failedInApp2, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); + assertEquals(fixture.wantedNodesApp2 - failedOrParkedInApp2, nodeRepository.getNodes(fixture.app2, Node.State.active).size()); + assertEquals(failedInApp1 + failedOrParkedInApp2, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed, Node.State.parked).size()); assertEquals(3, nodeRepository.getNodes(Node.Type.tenant, Node.State.ready).size()); assertEquals(2, nodeRepository.getNodes(Node.Type.host, Node.State.ready).size()); - // Cause maintenance deployment which will allocate replacement nodes fixture.runApplicationMaintainer(); assertEquals(fixture.wantedNodesApp1, nodeRepository.getNodes(fixture.app1, Node.State.active).size()); assertEquals(fixture.wantedNodesApp2, nodeRepository.getNodes(fixture.app2, Node.State.active).size()); assertEquals(0, nodeRepository.getNodes(Node.Type.tenant, Node.State.ready).size()); - // Unfail the previously failed nodes - nodeRepository.unfail(nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).get(0).hostname()); - nodeRepository.unfail(nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).get(0).hostname()); - nodeRepository.unfail(nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).get(0).hostname()); - int unfailedInApp1 = 1; - int unfailedInApp2 = 2; + // Reactivate the previously failed nodes + nodeRepository.reactivate(nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).get(0).hostname()); + nodeRepository.reactivate(nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).get(0).hostname()); + nodeRepository.reactivate(nodeRepository.getNodes(Node.Type.tenant, Node.State.parked).get(0).hostname()); + int reactivatedInApp1 = 1; + int reactivatedInApp2 = 2; assertEquals(0, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); - assertEquals(fixture.wantedNodesApp1 + unfailedInApp1, nodeRepository.getNodes(fixture.app1, Node.State.active).size()); - assertEquals(fixture.wantedNodesApp2 + unfailedInApp2, nodeRepository.getNodes(fixture.app2, Node.State.active).size()); - assertEquals("The unfailed nodes are now active but not part of the application", + assertEquals(fixture.wantedNodesApp1 + reactivatedInApp1, nodeRepository.getNodes(fixture.app1, Node.State.active).size()); + assertEquals(fixture.wantedNodesApp2 + reactivatedInApp2, nodeRepository.getNodes(fixture.app2, Node.State.active).size()); + assertEquals("The reactivated nodes are now active but not part of the application", 0, fixture.getNodes(Node.State.active).retired().size()); // Cause maintenance deployment which will update the applications with the re-activated nodes fixture.runApplicationMaintainer(); assertEquals("Superflous content nodes are retired", - unfailedInApp2, fixture.getNodes(Node.State.active).retired().size()); + reactivatedInApp2, fixture.getNodes(Node.State.active).retired().size()); assertEquals("Superflous container nodes are deactivated (this makes little point for container nodes)", - unfailedInApp1, fixture.getNodes(Node.State.inactive).size()); + reactivatedInApp1, fixture.getNodes(Node.State.inactive).size()); } private void createReadyNodes(int count, NodeRepository nodeRepository, NodeFlavors nodeFlavors) { diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailerTest.java index c194f8f88d1..c568b9db2a7 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailerTest.java @@ -89,7 +89,7 @@ public class NodeFailerTest { nodeRepository = new NodeRepository(NODE_FLAVORS, curator, clock); NodeRepositoryProvisioner provisioner = new NodeRepositoryProvisioner(nodeRepository, NODE_FLAVORS, ZONE); - createReadyNodes(14, nodeRepository, NODE_FLAVORS); + createReadyNodes(16, nodeRepository, NODE_FLAVORS); createHostNodes(3, nodeRepository, NODE_FLAVORS); // Create applications @@ -142,9 +142,20 @@ public class NodeFailerTest { assertEquals( 0, deployer.redeployments); assertEquals(12, nodeRepository.getNodes(Node.Type.tenant, Node.State.active).size()); assertEquals( 0, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); - assertEquals( 2, nodeRepository.getNodes(Node.Type.tenant, Node.State.ready).size()); + assertEquals( 4, nodeRepository.getNodes(Node.Type.tenant, Node.State.ready).size()); } + // Failures are detected on two ready nodes, which are then failed + Node readyFail1 = nodeRepository.getNodes(Node.Type.tenant, Node.State.ready).get(2); + Node readyFail2 = nodeRepository.getNodes(Node.Type.tenant, Node.State.ready).get(3); + nodeRepository.write(readyFail1.setStatus(readyFail1.status().setHardwareFailure(true))); + nodeRepository.write(readyFail2.setStatus(readyFail2.status().setHardwareFailure(true))); + assertEquals(4, nodeRepository.getNodes(Node.Type.tenant, Node.State.ready).size()); + failer.run(); + assertEquals(2, nodeRepository.getNodes(Node.Type.tenant, Node.State.ready).size()); + assertEquals(Node.State.failed, nodeRepository.getNode(readyFail1.hostname()).get().state()); + assertEquals(Node.State.failed, nodeRepository.getNode(readyFail2.hostname()).get().state()); + String downHost1 = nodeRepository.getNodes(APP_1, Node.State.active).get(1).hostname(); String downHost2 = nodeRepository.getNodes(APP_2, Node.State.active).get(3).hostname(); serviceMonitor.setHostDown(downHost1); @@ -155,7 +166,7 @@ public class NodeFailerTest { clock.advance(Duration.ofMinutes(5)); assertEquals( 0, deployer.redeployments); assertEquals(12, nodeRepository.getNodes(Node.Type.tenant, Node.State.active).size()); - assertEquals( 0, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); + assertEquals( 2, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); assertEquals( 2, nodeRepository.getNodes(Node.Type.tenant, Node.State.ready).size()); } serviceMonitor.setHostUp(downHost1); @@ -167,7 +178,7 @@ public class NodeFailerTest { // downHost2 should now be failed and replaced, but not downHost1 assertEquals( 1, deployer.redeployments); assertEquals(12, nodeRepository.getNodes(Node.Type.tenant, Node.State.active).size()); - assertEquals( 1, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); + assertEquals( 3, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); assertEquals( 1, nodeRepository.getNodes(Node.Type.tenant, Node.State.ready).size()); assertEquals(downHost2, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).get(0).hostname()); @@ -182,7 +193,7 @@ public class NodeFailerTest { // due to this, nothing is failed assertEquals( 1, deployer.redeployments); assertEquals(12, nodeRepository.getNodes(Node.Type.tenant, Node.State.active).size()); - assertEquals( 1, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); + assertEquals( 3, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); assertEquals( 1, nodeRepository.getNodes(Node.Type.tenant, Node.State.ready).size()); // when status becomes known, and the host is still down, it is failed clock.advance(Duration.ofMinutes(5)); @@ -190,7 +201,7 @@ public class NodeFailerTest { failer.run(); assertEquals( 2, deployer.redeployments); assertEquals(12, nodeRepository.getNodes(Node.Type.tenant, Node.State.active).size()); - assertEquals( 2, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); + assertEquals( 4, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); assertEquals( 0, nodeRepository.getNodes(Node.Type.tenant, Node.State.ready).size()); // the last host goes down @@ -202,17 +213,17 @@ public class NodeFailerTest { clock.advance(Duration.ofMinutes(5)); assertEquals( 2, deployer.redeployments); assertEquals(12, nodeRepository.getNodes(Node.Type.tenant, Node.State.active).size()); - assertEquals( 2, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); + assertEquals( 4, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); assertEquals( 0, nodeRepository.getNodes(Node.Type.tenant, Node.State.ready).size()); } // A new node is available - createReadyNodes(1, 14, nodeRepository, NODE_FLAVORS); + createReadyNodes(1, 16, nodeRepository, NODE_FLAVORS); failer.run(); // The node is now failed assertEquals( 3, deployer.redeployments); assertEquals(12, nodeRepository.getNodes(Node.Type.tenant, Node.State.active).size()); - assertEquals( 3, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); + assertEquals( 5, nodeRepository.getNodes(Node.Type.tenant, Node.State.failed).size()); assertEquals( 0, nodeRepository.getNodes(Node.Type.tenant, Node.State.ready).size()); assertTrue("The index of the last failed node is not reused", highestIndex(nodeRepository.getNodes(APP_1, Node.State.active)).allocation().get().membership().index() diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/monitoring/ProvisionMetricsTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/monitoring/ProvisionMetricsTest.java index ac6532b1b4a..0fe507edbe5 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/monitoring/ProvisionMetricsTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/monitoring/ProvisionMetricsTest.java @@ -35,6 +35,7 @@ public class ProvisionMetricsTest { final Map<String, Number> expectedMetrics = new HashMap<>(); expectedMetrics.put("hostedVespa.provisionedHosts", 1); + expectedMetrics.put("hostedVespa.parkedHosts", 0); expectedMetrics.put("hostedVespa.readyHosts", 0); expectedMetrics.put("hostedVespa.reservedHosts", 0); expectedMetrics.put("hostedVespa.activeHosts", 0); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java index fb7209fb308..3992e808830 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java @@ -101,12 +101,12 @@ public class RestApiTest { new byte[0], Request.Method.PUT), "{\"message\":\"Moved host8.yahoo.com to active\"}"); - // PUT a node in failed ... - assertResponse(new Request("http://localhost:8080/nodes/v2/state/failed/host8.yahoo.com", + // PUT a node in parked ... + assertResponse(new Request("http://localhost:8080/nodes/v2/state/parked/host8.yahoo.com", new byte[0], Request.Method.PUT), - "{\"message\":\"Moved host8.yahoo.com to failed\"}"); + "{\"message\":\"Moved host8.yahoo.com to parked\"}"); assertResponseContains(new Request("http://localhost:8080()/nodes/v2/node/host8.yahoo.com"), - "\"state\":\"failed\""); + "\"state\":\"parked\""); // ... and delete it assertResponse(new Request("http://localhost:8080/nodes/v2/node/host8.yahoo.com", new byte[0], Request.Method.DELETE), @@ -153,7 +153,53 @@ public class RestApiTest { } @Test + public void post_with_patch_method_override_in_header_is_handled_as_patch() throws IOException { + Request req = new Request("http://localhost:8080/nodes/v2/node/host4.yahoo.com", + Utf8.toBytes("{\"currentRestartGeneration\": 1}"), Request.Method.POST); + req.getHeaders().add("X-HTTP-Method-Override", "PATCH"); + assertResponse(req, "{\"message\":\"Updated host4.yahoo.com\"}"); + } + + @Test + public void post_with_invalid_method_override_in_header_gives_sane_error_message() throws IOException { + Request req = new Request("http://localhost:8080/nodes/v2/node/host4.yahoo.com", + Utf8.toBytes("{\"currentRestartGeneration\": 1}"), Request.Method.POST); + req.getHeaders().add("X-HTTP-Method-Override", "GET"); + assertResponse(req, 400, "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Illegal X-HTTP-Method-Override header for POST request. Accepts 'PATCH' but got 'GET'\"}"); + } + + @Test public void testInvalidRequests() throws IOException { + // Attempt to fail and ready an allocated node without going through dirty + assertResponse(new Request("http://localhost:8080/nodes/v2/state/failed/host1.yahoo.com", + new byte[0], Request.Method.PUT), + "{\"message\":\"Moved host1.yahoo.com to failed\"}"); + assertResponse(new Request("http://localhost:8080/nodes/v2/state/ready/host1.yahoo.com", + new byte[0], Request.Method.PUT), + 400, "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Could not set host1.yahoo.com ready: Node is allocated and must be moved to dirty instead\"}"); + // (... while dirty then ready works (the ready move will be initiated by node maintenance)) + assertResponse(new Request("http://localhost:8080/nodes/v2/state/dirty/host1.yahoo.com", + new byte[0], Request.Method.PUT), + "{\"message\":\"Moved host1.yahoo.com to dirty\"}"); + assertResponse(new Request("http://localhost:8080/nodes/v2/state/ready/host1.yahoo.com", + new byte[0], Request.Method.PUT), + "{\"message\":\"Moved host1.yahoo.com to ready\"}"); + + // Attempt to park and ready an allocated node without going through dirty + assertResponse(new Request("http://localhost:8080/nodes/v2/state/parked/host2.yahoo.com", + new byte[0], Request.Method.PUT), + "{\"message\":\"Moved host2.yahoo.com to parked\"}"); + assertResponse(new Request("http://localhost:8080/nodes/v2/state/ready/host2.yahoo.com", + new byte[0], Request.Method.PUT), + 400, "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Could not set host2.yahoo.com ready: Node is allocated and must be moved to dirty instead\"}"); + // (... while dirty then ready works (the ready move will be initiated by node maintenance)) + assertResponse(new Request("http://localhost:8080/nodes/v2/state/dirty/host2.yahoo.com", + new byte[0], Request.Method.PUT), + "{\"message\":\"Moved host2.yahoo.com to dirty\"}"); + assertResponse(new Request("http://localhost:8080/nodes/v2/state/ready/host2.yahoo.com", + new byte[0], Request.Method.PUT), + "{\"message\":\"Moved host2.yahoo.com to ready\"}"); + // Attempt to DELETE a node which is not put in failed first assertResponse(new Request("http://localhost:8080/nodes/v2/node/host8.yahoo.com", new byte[0], Request.Method.DELETE), diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/parent-nodes.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/parent-nodes.json index 28a17b03cc6..7352c4f4455 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/parent-nodes.json +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/parent-nodes.json @@ -1,5 +1,5 @@ { "nodes": [ @include(node10.json) -] + ] }
\ No newline at end of file diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/parent1.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/parent1.json index d6369fa51d3..c2d663fcb15 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/parent1.json +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/parent1.json @@ -1 +1,25 @@ -{"url":"http://localhost:8080/nodes/v2/node/parent1.yahoo.com","id":"parent1.yahoo.com","state":"ready","type":"host","hostname":"parent1.yahoo.com","openStackId":"parent1","flavor":"default","minDiskAvailableGb":400.0,"minMainMemoryAvailableGb":16.0,"description":"Flavor-name-is-default","minCpuCores":2.0,"canonicalFlavor":"default","environment":"env","rebootGeneration":0,"currentRebootGeneration":0,"failCount":0,"hardwareFailure":false,"history":[{"event":"readied","at":123}]} +{ + "url": "http://localhost:8080/nodes/v2/node/parent1.yahoo.com", + "id": "parent1.yahoo.com", + "state": "ready", + "type": "host", + "hostname": "parent1.yahoo.com", + "openStackId": "parent1", + "flavor": "default", + "minDiskAvailableGb": 400.0, + "minMainMemoryAvailableGb": 16.0, + "description": "Flavor-name-is-default", + "minCpuCores": 2.0, + "canonicalFlavor": "default", + "environment": "env", + "rebootGeneration": 0, + "currentRebootGeneration": 0, + "failCount": 0, + "hardwareFailure": false, + "history": [ + { + "event": "readied", + "at": 123 + } + ] +} diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/states-recursive.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/states-recursive.json index 9dd85385f4c..02d8e473f27 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/states-recursive.json +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/states-recursive.json @@ -43,6 +43,11 @@ "nodes": [ @include(node5.json) ] + }, + "parked": { + "url": "http://localhost:8080/nodes/v2/state/parked", + "nodes": [ + ] } } } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/states.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/states.json index b2d7354a6c9..4b2de7532dd 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/states.json +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/states.json @@ -20,6 +20,9 @@ }, "failed": { "url": "http://localhost:8080/nodes/v2/state/failed" + }, + "parked": { + "url": "http://localhost:8080/nodes/v2/state/parked" } } }
\ No newline at end of file diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/ApplicationIdNotFoundException.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/ApplicationIdNotFoundException.java index 55fc720307e..d12bd66bc86 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/ApplicationIdNotFoundException.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/ApplicationIdNotFoundException.java @@ -7,4 +7,12 @@ package com.yahoo.vespa.orchestrator; * @author smorgrav */ public class ApplicationIdNotFoundException extends Exception { + + public ApplicationIdNotFoundException() { + super(); + } + + public ApplicationIdNotFoundException(String reason) { + super(reason); + } } diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java index 0033de1288f..7197c9bcd43 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java @@ -136,7 +136,7 @@ public class OrchestratorImpl implements Orchestrator { @Override public ApplicationInstanceStatus getApplicationInstanceStatus( final ApplicationId appId) throws ApplicationIdNotFoundException { - ApplicationInstanceReference appRef = OrchestratorUtil.toApplicationInstanceReference(appId); + ApplicationInstanceReference appRef = OrchestratorUtil.toApplicationInstanceReference(appId,instanceLookupService); return statusService.forApplicationInstance(appRef).getApplicationInstanceStatus(); } @@ -271,7 +271,8 @@ public class OrchestratorImpl implements Orchestrator { final ApplicationId appId, final ApplicationInstanceStatus status) throws ApplicationStateChangeDeniedException, ApplicationIdNotFoundException{ - ApplicationInstanceReference appRef = OrchestratorUtil.toApplicationInstanceReference(appId); + + ApplicationInstanceReference appRef = OrchestratorUtil.toApplicationInstanceReference(appId, instanceLookupService); try (MutableStatusRegistry statusRegistry = statusService.lockApplicationInstance_forCurrentThreadOnly(appRef)) { diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorUtil.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorUtil.java index ca7bd058169..fff69cfd17b 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorUtil.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorUtil.java @@ -5,8 +5,6 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.orchestrator.status.HostStatus; -import com.yahoo.vespa.orchestrator.status.ReadOnlyStatusRegistry; import com.yahoo.vespa.applicationmodel.ApplicationInstance; import com.yahoo.vespa.applicationmodel.ApplicationInstanceId; import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference; @@ -14,8 +12,11 @@ import com.yahoo.vespa.applicationmodel.HostName; import com.yahoo.vespa.applicationmodel.ServiceCluster; import com.yahoo.vespa.applicationmodel.ServiceInstance; import com.yahoo.vespa.applicationmodel.TenantId; +import com.yahoo.vespa.orchestrator.status.HostStatus; +import com.yahoo.vespa.orchestrator.status.ReadOnlyStatusRegistry; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Function; @@ -108,37 +109,38 @@ public class OrchestratorUtil { } - public static ApplicationInstanceReference toApplicationInstanceReference(ApplicationId appId) { - TenantId tenantId = new TenantId(appId.tenant().toString()); + public static ApplicationInstanceReference toApplicationInstanceReference(ApplicationId appId, + InstanceLookupService instanceLookupService) + throws ApplicationIdNotFoundException { + + Set<ApplicationInstanceReference> appRefs = instanceLookupService.knownInstances(); + List<ApplicationInstanceReference> appRefList = appRefs.stream() + .filter(a -> OrchestratorUtil.toApplicationId(a).equals(appId)) + .collect(Collectors.toList()); - String appName = appId.application().toString(); - String instanceName = appId.instance().toString(); - ApplicationInstanceId appInstanceId = new ApplicationInstanceId(appName + ":" + instanceName); + if (appRefList.size() > 1) { + String msg = String.format("ApplicationId '%s' was not unique but mapped to '%s'", appId, appRefList); + throw new ApplicationIdNotFoundException(msg); + } - return new ApplicationInstanceReference(tenantId,appInstanceId); + if (appRefList.size() == 0) { + throw new ApplicationIdNotFoundException(); + } + + return appRefList.get(0); } public static ApplicationId toApplicationId(ApplicationInstanceReference appRef) { - TenantName tenantName = TenantName.from(appRef.tenantId().toString()); - // Now for the application/instance pair we need to split this - String appNameStr = appRef.applicationInstanceId().toString(); + String appNameStr = appRef.toString(); String[] appNameParts = appNameStr.split(":"); - - // We assume a valid application reference has at lest two parts appname:instancename - // TODO is this assumption valid? - if (appNameParts.length < 2) { - // TODO Since this is used internally we should perhapes use another exception type? - throw new IllegalArgumentException("Application reference not valid: " + appRef); + // TODO model ApplicationInstanceReference properly and validate this there + if (appNameParts.length != 5) { + throw new IllegalArgumentException("Application reference not valid (not 5 parts): " + appRef); } - // Last part of string is the instance name - InstanceName instanceName = InstanceName.from(appNameParts[appNameParts.length-1]); - - // The rest is application - int whereAppNameEnds = appNameStr.lastIndexOf(":"); - ApplicationName appName = ApplicationName.from(appNameStr.substring(0, whereAppNameEnds)); - - return ApplicationId.from(tenantName, appName, instanceName); + return ApplicationId.from(TenantName.from(appNameParts[0]), + ApplicationName.from(appNameParts[1]), + InstanceName.from(appNameParts[4])); } } diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/DummyInstanceLookupService.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/DummyInstanceLookupService.java index e1b73c1fe65..d48bc1f302b 100644 --- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/DummyInstanceLookupService.java +++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/DummyInstanceLookupService.java @@ -37,7 +37,7 @@ public class DummyInstanceLookupService implements InstanceLookupService { static { apps.add(new ApplicationInstance<>( new TenantId("test-tenant-id"), - new ApplicationInstanceId("application:instance"), + new ApplicationInstanceId("application:prod:utopia-1:instance"), TestUtil.makeServiceClusterSet( new ServiceCluster<>( new ClusterId("test-cluster-id-1"), @@ -49,7 +49,7 @@ public class DummyInstanceLookupService implements InstanceLookupService { ServiceMonitorStatus.UP), new ServiceInstance<>( new ConfigId("storage/storage/2"), - new HostName("test2.prod.utpoia-1.vespahosted.ut1.yahoo.com"), + new HostName("test2.prod.utopoia-1.vespahosted.ut1.yahoo.com"), ServiceMonitorStatus.UP))), new ServiceCluster<>( new ClusterId("clustercontroller"), @@ -65,7 +65,7 @@ public class DummyInstanceLookupService implements InstanceLookupService { apps.add(new ApplicationInstance<>( new TenantId("mediasearch"), - new ApplicationInstanceId("imagesearch:default"), + new ApplicationInstanceId("imagesearch:prod:utopia-1:default"), TestUtil.makeServiceClusterSet( new ServiceCluster<>( new ClusterId("image"), @@ -93,7 +93,7 @@ public class DummyInstanceLookupService implements InstanceLookupService { apps.add(new ApplicationInstance<>( new TenantId("tenant-id-3"), - new ApplicationInstanceId("application-instance-3:default"), + new ApplicationInstanceId("application-instance-3:prod:utopia-1:default"), TestUtil.makeServiceClusterSet( new ServiceCluster<>( new ClusterId("cluster-id-3"), diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java index b9812ac7ab6..548d67689d2 100644 --- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java +++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java @@ -216,7 +216,7 @@ public class OrchestratorImplTest { InstanceLookupService service = new DummyInstanceLookupService(); String applicationInstanceId = service.findInstanceByHost(DummyInstanceLookupService.TEST1_HOST_NAME).get() .reference().toString(); - assertEquals("test-tenant-id:application:instance", applicationInstanceId); + assertEquals("test-tenant-id:application:prod:utopia-1:instance", applicationInstanceId); } @Test @@ -291,7 +291,7 @@ public class OrchestratorImplTest { private boolean isInMaintenance(ApplicationId appId, HostName hostName) throws ApplicationIdNotFoundException { for (ApplicationInstance<ServiceMonitorStatus> app : DummyInstanceLookupService.getApplications()) { - if (app.reference().equals(OrchestratorUtil.toApplicationInstanceReference(appId))) { + if (app.reference().equals(OrchestratorUtil.toApplicationInstanceReference(appId,new DummyInstanceLookupService()))) { return clustercontroller.isInMaintenance(app, hostName); } } diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorUtilTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorUtilTest.java index 41daef34c25..2655f6b2b49 100644 --- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorUtilTest.java +++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorUtilTest.java @@ -18,12 +18,12 @@ public class OrchestratorUtilTest { private static final ApplicationId APPID_1 = ApplicationId.from( TenantName.from("mediasearch"), - ApplicationName.from("tumblr-search"), + ApplicationName.from("imagesearch"), InstanceName.defaultName()); private static final ApplicationInstanceReference APPREF_1 = new ApplicationInstanceReference( - new TenantId("test-tenant"), - new ApplicationInstanceId("test-application:test-environment:test-region:test-instance-key")); + new TenantId("test-tenant-id"), + new ApplicationInstanceId("application:prod:utopia-1:instance")); /** * Here we don't care how the internal of the different application @@ -35,14 +35,14 @@ public class OrchestratorUtilTest { public void applicationid_conversion_are_symmetric() throws Exception { // From appId to appRef and back - ApplicationInstanceReference appRef = OrchestratorUtil.toApplicationInstanceReference(APPID_1); + ApplicationInstanceReference appRef = OrchestratorUtil.toApplicationInstanceReference(APPID_1, new DummyInstanceLookupService()); ApplicationId appIdRoundTrip = OrchestratorUtil.toApplicationId(appRef); Assert.assertEquals(APPID_1, appIdRoundTrip); // From appRef to appId and back ApplicationId appId = OrchestratorUtil.toApplicationId(APPREF_1); - ApplicationInstanceReference appRefRoundTrip = OrchestratorUtil.toApplicationInstanceReference(appId); + ApplicationInstanceReference appRefRoundTrip = OrchestratorUtil.toApplicationInstanceReference(appId, new DummyInstanceLookupService()); Assert.assertEquals(APPREF_1, appRefRoundTrip); } diff --git a/persistence/.gitignore b/persistence/.gitignore index be0452bed21..4b160dd6a2e 100644 --- a/persistence/.gitignore +++ b/persistence/.gitignore @@ -1,4 +1,3 @@ /target /pom.xml.build Makefile -Testing diff --git a/persistencetypes/.gitignore b/persistencetypes/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/persistencetypes/.gitignore +++ b/persistencetypes/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/searchcommon/.gitignore b/searchcommon/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/searchcommon/.gitignore +++ b/searchcommon/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/searchcommon/src/tests/schema/.gitignore b/searchcommon/src/tests/schema/.gitignore index 79e714aa5a2..ae6d9596934 100644 --- a/searchcommon/src/tests/schema/.gitignore +++ b/searchcommon/src/tests/schema/.gitignore @@ -2,3 +2,7 @@ /Makefile /schema_test searchcommon_schema_test_app +/schema-with-timestamps.txt +/schema-without-timestamps.txt +/schema.txt +/schema2.txt diff --git a/searchcore/.gitignore b/searchcore/.gitignore index bb01e126e8c..6f79fc39b2d 100644 --- a/searchcore/.gitignore +++ b/searchcore/.gitignore @@ -12,4 +12,3 @@ update.log /target /pom.xml.build Makefile -Testing diff --git a/searchcore/src/tests/proton/flushengine/prepare_restart_flush_strategy/.gitignore b/searchcore/src/tests/proton/flushengine/prepare_restart_flush_strategy/.gitignore new file mode 100644 index 00000000000..d06d6be719a --- /dev/null +++ b/searchcore/src/tests/proton/flushengine/prepare_restart_flush_strategy/.gitignore @@ -0,0 +1 @@ +/searchcore_flushengine_prepare_restart_flush_strategy_test_app diff --git a/searchcorespi/.gitignore b/searchcorespi/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/searchcorespi/.gitignore +++ b/searchcorespi/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/searchlib/.gitignore b/searchlib/.gitignore index ef6cddb9800..a58e2e56d5e 100644 --- a/searchlib/.gitignore +++ b/searchlib/.gitignore @@ -6,4 +6,3 @@ target *.iws /pom.xml.build Makefile -Testing diff --git a/searchlib/src/tests/fileheaderinspect/fileheaderinspect.cpp b/searchlib/src/tests/fileheaderinspect/fileheaderinspect.cpp index 75ad526e2f7..351d19737aa 100644 --- a/searchlib/src/tests/fileheaderinspect/fileheaderinspect.cpp +++ b/searchlib/src/tests/fileheaderinspect/fileheaderinspect.cpp @@ -1,44 +1,12 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/fastos/fastos.h> -#include <vespa/log/log.h> -LOG_SETUP("fileheaderinspect_test"); +#include <vespa/vespalib/testkit/test_kit.h> #include <vespa/searchlib/util/fileheadertk.h> -#include <vespa/vespalib/testkit/testapp.h> using namespace search; using namespace vespalib; -class Test : public vespalib::TestApp { -private: - bool writeHeader(const FileHeader &header, const vespalib::string &fileName); - vespalib::string readFile(const vespalib::string &fileName); - - void testError(); - void testEscape(); - void testDelimiter(); - void testQuiet(); - void testVerbose(); - -public: - int Main() { - TEST_INIT("fileheaderinspect_test"); - - testError(); TEST_FLUSH(); - testEscape(); TEST_FLUSH(); - testDelimiter(); TEST_FLUSH(); - testQuiet(); TEST_FLUSH(); - testVerbose(); TEST_FLUSH(); - - TEST_DONE(); - } -}; - -TEST_APPHOOK(Test); - -bool -Test::writeHeader(const FileHeader &header, const vespalib::string &fileName) -{ +bool writeHeader(const FileHeader &header, const vespalib::string &fileName) { FastOS_File file; if (!EXPECT_TRUE(file.OpenWriteOnlyTruncate(fileName.c_str()))) { return false; @@ -50,30 +18,24 @@ Test::writeHeader(const FileHeader &header, const vespalib::string &fileName) return true; } -vespalib::string -Test::readFile(const vespalib::string &fileName) -{ +vespalib::string readFile(const vespalib::string &fileName) { FastOS_File file; ASSERT_TRUE(file.OpenReadOnly(fileName.c_str())); - char buf[1024]; - uint32_t len = file.Read(buf, 1024); - EXPECT_TRUE(len != 1024); // make sure we got everything + char buf[4096]; + uint32_t len = file.Read(buf, sizeof(buf)); + EXPECT_LESS(len, sizeof(buf)); // make sure we got everything vespalib::string str(buf, len); file.Close(); return str; } -void -Test::testError() -{ +TEST("testError") { EXPECT_TRUE(system("../../apps/fileheaderinspect/vespa-header-inspect notfound.dat") != 0); } -void -Test::testEscape() -{ +TEST("testEscape") { FileHeader header; header.putTag(FileHeader::Tag("fanart", "\fa\na\r\t")); ASSERT_TRUE(writeHeader(header, "fileheader.dat")); @@ -81,9 +43,7 @@ Test::testEscape() EXPECT_EQUAL("fanart;string;\\fa\\na\\r\\t\n", readFile("out")); } -void -Test::testDelimiter() -{ +TEST("testDelimiter") { FileHeader header; header.putTag(FileHeader::Tag("string", "string")); ASSERT_TRUE(writeHeader(header, "fileheader.dat")); @@ -91,41 +51,39 @@ Test::testDelimiter() EXPECT_EQUAL("str\\ingistr\\ingistr\\ing\n", readFile("out")); } -void -Test::testVerbose() -{ +TEST("testQuiet") { FileHeader header; FileHeaderTk::addVersionTags(header); ASSERT_TRUE(writeHeader(header, "fileheader.dat")); - EXPECT_TRUE(system("../../apps/fileheaderinspect/vespa-header-inspect fileheader.dat > out") == 0); + EXPECT_TRUE(system("../../apps/fileheaderinspect/vespa-header-inspect -q fileheader.dat > out") == 0); vespalib::string str = readFile("out"); EXPECT_TRUE(!str.empty()); for (uint32_t i = 0, numTags = header.getNumTags(); i < numTags; ++i) { const FileHeader::Tag &tag = header.getTag(i); - EXPECT_TRUE(str.find(tag.getName()) != vespalib::string::npos); + size_t pos = str.find(tag.getName()); + EXPECT_TRUE(pos != vespalib::string::npos); vespalib::asciistream out; - out << tag; - EXPECT_TRUE(str.find(out.str()) != vespalib::string::npos); + out << ";" << tag; + EXPECT_TRUE(str.find(out.str(), pos) != vespalib::string::npos); } } -void -Test::testQuiet() -{ +TEST("testVerbose") { FileHeader header; FileHeaderTk::addVersionTags(header); ASSERT_TRUE(writeHeader(header, "fileheader.dat")); - EXPECT_TRUE(system("../../apps/fileheaderinspect/vespa-header-inspect -q fileheader.dat > out") == 0); + EXPECT_TRUE(system("../../apps/fileheaderinspect/vespa-header-inspect fileheader.dat > out") == 0); vespalib::string str = readFile("out"); EXPECT_TRUE(!str.empty()); for (uint32_t i = 0, numTags = header.getNumTags(); i < numTags; ++i) { const FileHeader::Tag &tag = header.getTag(i); - size_t pos = str.find(tag.getName()); - EXPECT_TRUE(pos != vespalib::string::npos); + EXPECT_TRUE(str.find(tag.getName()) != vespalib::string::npos); vespalib::asciistream out; - out << ";" << tag; - EXPECT_TRUE(str.find(out.str(), pos) != vespalib::string::npos); + out << tag; + EXPECT_TRUE(str.find(out.str()) != vespalib::string::npos); } } + +TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/searchlib/src/tests/queryeval/blueprint/.gitignore b/searchlib/src/tests/queryeval/blueprint/.gitignore index da4bf633103..9bd9a86271b 100644 --- a/searchlib/src/tests/queryeval/blueprint/.gitignore +++ b/searchlib/src/tests/queryeval/blueprint/.gitignore @@ -6,3 +6,4 @@ rhs.out searchlib_blueprint_test_app searchlib_intermediate_blueprints_test_app searchlib_leaf_blueprints_test_app +/index diff --git a/searchlib/src/tests/transactionlogstress/.gitignore b/searchlib/src/tests/transactionlogstress/.gitignore index 5913613b455..bdfe824be8b 100644 --- a/searchlib/src/tests/transactionlogstress/.gitignore +++ b/searchlib/src/tests/transactionlogstress/.gitignore @@ -2,3 +2,4 @@ Makefile server translogstress +/searchlib_translogstress_app diff --git a/searchsummary/.gitignore b/searchsummary/.gitignore index be0452bed21..4b160dd6a2e 100644 --- a/searchsummary/.gitignore +++ b/searchsummary/.gitignore @@ -1,4 +1,3 @@ /target /pom.xml.build Makefile -Testing diff --git a/slobrok/.gitignore b/slobrok/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/slobrok/.gitignore +++ b/slobrok/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/staging_vespalib/.gitignore b/staging_vespalib/.gitignore index 727ed8ec9e8..65e000de4f0 100644 --- a/staging_vespalib/.gitignore +++ b/staging_vespalib/.gitignore @@ -2,4 +2,3 @@ bin doc lib Makefile -Testing diff --git a/storage/.gitignore b/storage/.gitignore index 3b41f121299..7d50a4f9b88 100644 --- a/storage/.gitignore +++ b/storage/.gitignore @@ -9,4 +9,3 @@ testLogs /target /pom.xml.build Makefile -Testing diff --git a/storageapi/.gitignore b/storageapi/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/storageapi/.gitignore +++ b/storageapi/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/storageframework/.gitignore b/storageframework/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/storageframework/.gitignore +++ b/storageframework/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/storageserver/.gitignore b/storageserver/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/storageserver/.gitignore +++ b/storageserver/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/streamingvisitors/.gitignore b/streamingvisitors/.gitignore index 31d449f16ee..ad59e5b91d2 100644 --- a/streamingvisitors/.gitignore +++ b/streamingvisitors/.gitignore @@ -1,3 +1,2 @@ testrun Makefile -Testing diff --git a/vbench/.gitignore b/vbench/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/vbench/.gitignore +++ b/vbench/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/vdslib/.gitignore b/vdslib/.gitignore index 96c62777acb..b0a64672599 100644 --- a/vdslib/.gitignore +++ b/vdslib/.gitignore @@ -2,4 +2,3 @@ target vdslib-lib.iml /pom.xml.build Makefile -Testing diff --git a/vdstestlib/.gitignore b/vdstestlib/.gitignore index a9b20e8992d..f3c7a7c5da6 100644 --- a/vdstestlib/.gitignore +++ b/vdstestlib/.gitignore @@ -1,2 +1 @@ Makefile -Testing diff --git a/vespaclient/.gitignore b/vespaclient/.gitignore index 235d7663475..afee18213d5 100644 --- a/vespaclient/.gitignore +++ b/vespaclient/.gitignore @@ -6,4 +6,3 @@ target /tmp /pom.xml.build Makefile -Testing diff --git a/vespalib/.gitignore b/vespalib/.gitignore index 727ed8ec9e8..65e000de4f0 100644 --- a/vespalib/.gitignore +++ b/vespalib/.gitignore @@ -2,4 +2,3 @@ bin doc lib Makefile -Testing diff --git a/vespalib/src/tests/barrier/.gitignore b/vespalib/src/tests/barrier/.gitignore index c34ea278112..f15a24ef252 100644 --- a/vespalib/src/tests/barrier/.gitignore +++ b/vespalib/src/tests/barrier/.gitignore @@ -1,2 +1 @@ vespalib_barrier_test_app -Testing diff --git a/vespalib/src/tests/box/.gitignore b/vespalib/src/tests/box/.gitignore index 76ae8a62fd2..d3a9d8db21c 100644 --- a/vespalib/src/tests/box/.gitignore +++ b/vespalib/src/tests/box/.gitignore @@ -1,2 +1 @@ vespalib_box_test_app -Testing diff --git a/vespalib/src/tests/dual_merge_director/.gitignore b/vespalib/src/tests/dual_merge_director/.gitignore index b190240063a..6d65b032c84 100644 --- a/vespalib/src/tests/dual_merge_director/.gitignore +++ b/vespalib/src/tests/dual_merge_director/.gitignore @@ -1,2 +1 @@ vespalib_dual_merge_director_test_app -Testing diff --git a/vespalib/src/tests/testkit-subset/.gitignore b/vespalib/src/tests/testkit-subset/.gitignore index 1007cdc2b36..fc843d3776f 100644 --- a/vespalib/src/tests/testkit-subset/.gitignore +++ b/vespalib/src/tests/testkit-subset/.gitignore @@ -1,2 +1,3 @@ /out.txt vespalib_testkit-subset_test_app +/out.relpath.txt diff --git a/vespalib/src/tests/tutorial/checks/.gitignore b/vespalib/src/tests/tutorial/checks/.gitignore index bd3d3565773..6cc70e1c25a 100644 --- a/vespalib/src/tests/tutorial/checks/.gitignore +++ b/vespalib/src/tests/tutorial/checks/.gitignore @@ -1,2 +1 @@ vespalib_checks_test_app -Testing diff --git a/vespalib/src/tests/tutorial/fixtures/.gitignore b/vespalib/src/tests/tutorial/fixtures/.gitignore index 049a39ac736..98e7131620a 100644 --- a/vespalib/src/tests/tutorial/fixtures/.gitignore +++ b/vespalib/src/tests/tutorial/fixtures/.gitignore @@ -1,2 +1 @@ vespalib_fixtures_test_app -Testing diff --git a/vespalib/src/tests/tutorial/minimal/.gitignore b/vespalib/src/tests/tutorial/minimal/.gitignore index bb09f68684f..48d49394413 100644 --- a/vespalib/src/tests/tutorial/minimal/.gitignore +++ b/vespalib/src/tests/tutorial/minimal/.gitignore @@ -1,2 +1 @@ vespalib_minimal_test_app -Testing diff --git a/vespalib/src/tests/tutorial/simple/.gitignore b/vespalib/src/tests/tutorial/simple/.gitignore index 42594074945..aa48ba3f011 100644 --- a/vespalib/src/tests/tutorial/simple/.gitignore +++ b/vespalib/src/tests/tutorial/simple/.gitignore @@ -1,2 +1 @@ vespalib_simple_test_app -Testing diff --git a/vespalib/src/tests/tutorial/threads/.gitignore b/vespalib/src/tests/tutorial/threads/.gitignore index a90822b0e7c..7668f1b3384 100644 --- a/vespalib/src/tests/tutorial/threads/.gitignore +++ b/vespalib/src/tests/tutorial/threads/.gitignore @@ -1,2 +1 @@ vespalib_threads_test_app -Testing diff --git a/vespalog/.gitignore b/vespalog/.gitignore index ad5e60bcc0f..efdf6e430c8 100644 --- a/vespalog/.gitignore +++ b/vespalog/.gitignore @@ -12,4 +12,3 @@ testLogs vespalog.iml /pom.xml.build Makefile -Testing diff --git a/vespamalloc/.gitignore b/vespamalloc/.gitignore index e273b5725de..08001c737d7 100644 --- a/vespamalloc/.gitignore +++ b/vespamalloc/.gitignore @@ -1,3 +1,2 @@ test Makefile -Testing diff --git a/vsm/.gitignore b/vsm/.gitignore index 2f5c05fd2c2..3969348a427 100644 --- a/vsm/.gitignore +++ b/vsm/.gitignore @@ -3,4 +3,3 @@ lib /target /pom.xml.build Makefile -Testing |