diff options
25 files changed, 407 insertions, 226 deletions
diff --git a/document/src/test/java/com/yahoo/document/DocumentTypeManagerTestCase.java b/document/src/test/java/com/yahoo/document/DocumentTypeManagerTestCase.java index 4363a704ad7..e6c020e6688 100644 --- a/document/src/test/java/com/yahoo/document/DocumentTypeManagerTestCase.java +++ b/document/src/test/java/com/yahoo/document/DocumentTypeManagerTestCase.java @@ -10,15 +10,11 @@ import org.junit.Test; import java.util.Iterator; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.sameInstance; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; /** @@ -125,7 +121,7 @@ public class DocumentTypeManagerTestCase { @Test public void testReverseMapOrder() { - final DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.map.cfg"); + DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.map.cfg"); assertNotNull(manager.getDataType(1000)); assertNotNull(manager.getDataType(1001)); @@ -134,7 +130,7 @@ public class DocumentTypeManagerTestCase { @SuppressWarnings("deprecation") @Test public void testConfigure() { - final DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.cfg"); + DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.cfg"); Iterator typeIt = manager.documentTypeIterator(); DocumentType type = null; @@ -215,7 +211,7 @@ public class DocumentTypeManagerTestCase { @Test public void testConfigureUpdate() { - final DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.cfg"); + DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.cfg"); DocumentType banana = manager.getDocumentType(new DataTypeName("banana")); DocumentType customtypes = manager.getDocumentType(new DataTypeName("customtypes")); @@ -234,7 +230,7 @@ public class DocumentTypeManagerTestCase { @Test public void testConfigureWithAnnotations() { - final DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.annotationtypes1.cfg"); + DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.annotationtypes1.cfg"); /* annotation banana { @@ -294,7 +290,7 @@ public class DocumentTypeManagerTestCase { @Test public void testConfigureWithAnnotationsWithInheritance() { - final DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.annotationtypes2.cfg"); + DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.annotationtypes2.cfg"); /* annotation fruit { @@ -419,7 +415,7 @@ search annotationsimplicitstruct { } */ - final DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.structsanyorder.cfg"); + DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.structsanyorder.cfg"); StructDataType foo = (StructDataType) manager.getDataType("foo"); assertNotNull(foo); @@ -442,7 +438,7 @@ search annotationsimplicitstruct { @Test public void testSombrero1() { - final DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.sombrero1.cfg"); + DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.sombrero1.cfg"); { StringFieldValue sfv = new StringFieldValue("ballooooo"); @@ -482,7 +478,7 @@ search annotationsimplicitstruct { */ - final DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.annotationspolymorphy.cfg"); + DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.annotationspolymorphy.cfg"); AnnotationType suuper = manager.getAnnotationTypeRegistry().getType("super"); AnnotationType sub = manager.getAnnotationTypeRegistry().getType("sub"); @@ -509,23 +505,23 @@ search annotationsimplicitstruct { private static void assertReferenceTypePresentInManager(DocumentTypeManager manager, int refTypeId, String refTargetTypeName) { - final DataType type = manager.getDataType(refTypeId); - assertThat(type, instanceOf(ReferenceDataType.class)); - final ReferenceDataType refType = (ReferenceDataType) type; + DataType type = manager.getDataType(refTypeId); + assertTrue(type instanceof ReferenceDataType); + ReferenceDataType refType = (ReferenceDataType) type; - final DocumentType targetDocType = manager.getDocumentType(refTargetTypeName); - assertThat(refType.getTargetType(), sameInstance(targetDocType)); + DocumentType targetDocType = manager.getDocumentType(refTargetTypeName); + assertTrue(refType.getTargetType() == targetDocType); } private static DocumentTypeManager createConfiguredManager(String configFilePath) { - final DocumentTypeManager manager = new DocumentTypeManager(); + DocumentTypeManager manager = new DocumentTypeManager(); DocumentTypeManagerConfigurer.configure(manager, configFilePath); return manager; } @Test public void multiple_reference_types_are_mapped_to_correct_document_target_types() { - final DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.multiplereferences.cfg"); + DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.multiplereferences.cfg"); assertReferenceTypePresentInManager(manager, 12345678, "referenced_type"); assertReferenceTypePresentInManager(manager, 87654321, "referenced_type2"); @@ -533,23 +529,23 @@ search annotationsimplicitstruct { @Test public void can_have_reference_type_pointing_to_own_document_type() { - final DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.selfreference.cfg"); + DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.selfreference.cfg"); assertReferenceTypePresentInManager(manager, 12345678, "type_with_ref"); } @Test public void reference_field_has_correct_reference_type() { - final DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.singlereference.cfg"); + DocumentTypeManager manager = createConfiguredManager("file:src/test/document/documentmanager.singlereference.cfg"); - final DocumentType docType = manager.getDocumentType("type_with_ref"); - final Field field = docType.getField("my_ref_field"); + DocumentType docType = manager.getDocumentType("type_with_ref"); + Field field = docType.getField("my_ref_field"); - assertThat(field.getDataType(), instanceOf(ReferenceDataType.class)); - final ReferenceDataType fieldRefType = (ReferenceDataType) field.getDataType(); + assertTrue(field.getDataType() instanceof ReferenceDataType); + ReferenceDataType fieldRefType = (ReferenceDataType) field.getDataType(); - final DocumentType targetDocType = manager.getDocumentType("referenced_type"); - assertThat(fieldRefType.getTargetType(), sameInstance(targetDocType)); + DocumentType targetDocType = manager.getDocumentType("referenced_type"); + assertTrue(fieldRefType.getTargetType() == targetDocType); } // TODO test reference to own doc type diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/JobControl.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/JobControl.java index 93c626c8b81..197c173e639 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/JobControl.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/JobControl.java @@ -35,21 +35,24 @@ public class JobControl { * Each job is represented by its simple (omitting package) class name. */ public Set<String> jobs() { return new HashSet<>(startedJobs); } + + /** Returns a snapshot containing the currently inactive jobs in this */ + public Set<String> inactiveJobs() { return db.readInactiveJobs(); } /** Returns true if this job is not currently deactivated */ public boolean isActive(String jobSimpleClassName) { - return ! db.readDeactivatedJobs().contains(jobSimpleClassName); + return ! db.readInactiveJobs().contains(jobSimpleClassName); } /** Set a job active or inactive */ public void setActive(String jobSimpleClassName, boolean active) { - try (CuratorMutex lock = db.lockDeactivatedJobs()) { - Set<String> deactivatedJobs = db.readDeactivatedJobs(); + try (CuratorMutex lock = db.lockInactiveJobs()) { + Set<String> inactiveJobs = db.readInactiveJobs(); if (active) - deactivatedJobs.remove(jobSimpleClassName); + inactiveJobs.remove(jobSimpleClassName); else - deactivatedJobs.add(jobSimpleClassName); - db.writeDeactivatedJobs(deactivatedJobs); + inactiveJobs.add(jobSimpleClassName); + db.writeInactiveJobs(inactiveJobs); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java index 970dbde9cc8..95466d1d4b1 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java @@ -83,6 +83,8 @@ public class NodeRepositoryMaintenance extends AbstractComponent { metricsReporter.deconstruct(); } + public JobControl jobControl() { return jobControl; } + private static Optional<Duration> durationFromEnv(String envVariable) { return Optional.ofNullable(System.getenv(envPrefix + envVariable)).map(Long::parseLong).map(Duration::ofSeconds); } 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 08d56c9cb42..544772ecb8f 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 @@ -68,7 +68,7 @@ public class CuratorDatabaseClient { curatorDatabase.create(root); for (Node.State state : Node.State.values()) curatorDatabase.create(toPath(state)); - curatorDatabase.create(deactivatedJobsPath()); + curatorDatabase.create(inactiveJobsPath()); } /** @@ -308,26 +308,26 @@ public class CuratorDatabaseClient { return root.append("defaultFlavor").append(applicationId.serializedForm()); } - public Set<String> readDeactivatedJobs() { - return curatorDatabase.getData(deactivatedJobsPath()) + public Set<String> readInactiveJobs() { + return curatorDatabase.getData(inactiveJobsPath()) .map(data -> stringSetSerializer.fromJson(data)) .orElse(Collections.emptySet()); } - public void writeDeactivatedJobs(Set<String> deactivatedJobs) { + public void writeInactiveJobs(Set<String> inactiveJobs) { NestedTransaction transaction = new NestedTransaction(); CuratorTransaction curatorTransaction = curatorDatabase.newCuratorTransactionIn(transaction); - curatorTransaction.add(CuratorOperations.setData(deactivatedJobsPath().getAbsolute(), - stringSetSerializer.toJson(deactivatedJobs))); + curatorTransaction.add(CuratorOperations.setData(inactiveJobsPath().getAbsolute(), + stringSetSerializer.toJson(inactiveJobs))); transaction.commit(); } - public CuratorMutex lockDeactivatedJobs() { - return lock(deactivatedJobsPath(), defaultLockTimeout); + public CuratorMutex lockInactiveJobs() { + return lock(inactiveJobsPath(), defaultLockTimeout); } - private Path deactivatedJobsPath() { - return root.append("deactivatedJobs"); + private Path inactiveJobsPath() { + return root.append("inactiveJobs"); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/JobsResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/JobsResponse.java new file mode 100644 index 00000000000..aa1f1438fb7 --- /dev/null +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/JobsResponse.java @@ -0,0 +1,43 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.provision.restapi.v2; + +import com.yahoo.container.jdisc.HttpResponse; +import com.yahoo.slime.Cursor; +import com.yahoo.slime.JsonFormat; +import com.yahoo.slime.Slime; +import com.yahoo.vespa.hosted.provision.maintenance.JobControl; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; + +/** A response containing maintenance job status */ +public class JobsResponse extends HttpResponse { + + private final JobControl jobControl; + + public JobsResponse(JobControl jobControl) { + super(200); + this.jobControl = jobControl; + } + + @Override + public void render(OutputStream stream) throws IOException { + Slime slime = new Slime(); + Cursor root = slime.setObject(); + + Cursor jobArray = root.setArray("jobs"); + for (String jobName : jobControl.jobs()) + jobArray.addObject().setString("name", jobName); + + Cursor inactiveArray = root.setArray("inactive"); + for (String jobName : jobControl.inactiveJobs()) + inactiveArray.addString(jobName); + + new JsonFormat(true).encode(stream, slime); + } + + @Override + public String getContentType() { return "application/json"; } + +} 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 c126a1f29ec..1498ff10a81 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 @@ -16,6 +16,7 @@ import com.yahoo.vespa.hosted.provision.NoSuchNodeException; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.config.provision.NodeFlavors; +import com.yahoo.vespa.hosted.provision.maintenance.NodeRepositoryMaintenance; import com.yahoo.vespa.hosted.provision.node.Agent; import com.yahoo.vespa.hosted.provision.node.filter.ApplicationFilter; import com.yahoo.vespa.hosted.provision.node.filter.NodeFilter; @@ -48,13 +49,16 @@ import static com.yahoo.vespa.config.SlimeUtils.optionalString; public class NodesApiHandler extends LoggingRequestHandler { private final NodeRepository nodeRepository; + private final NodeRepositoryMaintenance maintenance; private final NodeFlavors nodeFlavors; private static final String nodeTypeKey = "type"; - public NodesApiHandler(Executor executor, AccessLog accessLog, NodeRepository nodeRepository, NodeFlavors flavors) { + public NodesApiHandler(Executor executor, AccessLog accessLog, NodeRepository nodeRepository, + NodeRepositoryMaintenance maintenance, NodeFlavors flavors) { super(executor, accessLog); this.nodeRepository = nodeRepository; + this.maintenance = maintenance; this.nodeFlavors = flavors; } @@ -84,13 +88,14 @@ public class NodesApiHandler extends LoggingRequestHandler { private HttpResponse handleGET(HttpRequest request) { String path = request.getUri().getPath(); - if (path.equals( "/nodes/v2/")) return ResourcesResponse.fromStrings(request.getUri(), "state", "node", "command"); + if (path.equals( "/nodes/v2/")) return ResourcesResponse.fromStrings(request.getUri(), "state", "node", "command", "maintenance"); if (path.equals( "/nodes/v2/node/")) return new NodesResponse(ResponseType.nodeList, request, nodeRepository); if (path.startsWith("/nodes/v2/node/")) return new NodesResponse(ResponseType.singleNode, request, nodeRepository); if (path.equals( "/nodes/v2/state/")) return new NodesResponse(ResponseType.stateList, request, nodeRepository); if (path.startsWith("/nodes/v2/state/")) return new NodesResponse(ResponseType.nodesInStateList, request, nodeRepository); if (path.startsWith("/nodes/v2/acl/")) return new NodeAclResponse(request, nodeRepository); if (path.equals( "/nodes/v2/command/")) return ResourcesResponse.fromStrings(request.getUri(), "restart", "reboot"); + if (path.equals( "/nodes/v2/maintenance/")) return new JobsResponse(maintenance.jobControl()); throw new NotFoundException("Nothing at path '" + path + "'"); } @@ -132,21 +137,34 @@ public class NodesApiHandler extends LoggingRequestHandler { } private HttpResponse handlePOST(HttpRequest request) { - switch (request.getUri().getPath()) { - case "/nodes/v2/command/restart" : - int restartCount = nodeRepository.restart(toNodeFilter(request)).size(); - return new MessageResponse("Scheduled restart of " + restartCount + " matching nodes"); - case "/nodes/v2/command/reboot" : - int rebootCount = nodeRepository.reboot(toNodeFilter(request)).size(); - return new MessageResponse("Scheduled reboot of " + rebootCount + " matching nodes"); - case "/nodes/v2/node" : - int addedNodes = addNodes(request.getData()); - return new MessageResponse("Added " + addedNodes + " nodes to the provisioned state"); - default: - throw new NotFoundException("Nothing at path '" + request.getUri().getPath() + "'"); + String path = request.getUri().getPath(); + if (path.equals("/nodes/v2/command/restart")) { + int restartCount = nodeRepository.restart(toNodeFilter(request)).size(); + return new MessageResponse("Scheduled restart of " + restartCount + " matching nodes"); + } + else if (path.equals("/nodes/v2/command/reboot")) { + int rebootCount = nodeRepository.reboot(toNodeFilter(request)).size(); + return new MessageResponse("Scheduled reboot of " + rebootCount + " matching nodes"); + } + else if (path.equals("/nodes/v2/node")) { + int addedNodes = addNodes(request.getData()); + return new MessageResponse("Added " + addedNodes + " nodes to the provisioned state"); + } + else if (path.startsWith("/nodes/v2/maintenance/inactive/")) { + return setActive(lastElement(path), false); + } + else { + throw new NotFoundException("Nothing at path '" + request.getUri().getPath() + "'"); } } + private MessageResponse setActive(String jobName, boolean active) { + if ( ! maintenance.jobControl().jobs().contains(jobName)) + throw new NotFoundException("No job named '" + jobName + "'"); + maintenance.jobControl().setActive(jobName, active); + return new MessageResponse((active ? "Re-activated" : "Deactivated" ) + " job '" + jobName + "'"); + } + private HttpResponse handleDELETE(HttpRequest request) { String path = request.getUri().getPath(); if (path.startsWith("/nodes/v2/node/")) { @@ -156,8 +174,13 @@ public class NodesApiHandler extends LoggingRequestHandler { else throw new NotFoundException("No node in the provisioned, parked or failed state with hostname " + hostname); } - - throw new NotFoundException("Nothing at path '" + request.getUri().getPath() + "'"); + else if (path.startsWith("/nodes/v2/maintenance/inactive/")) { + setActive(lastElement(path), true); + return new MessageResponse("Reactivated job '" + lastElement(path) + "'"); + } + else { + throw new NotFoundException("Nothing at path '" + request.getUri().getPath() + "'"); + } } private Node nodeFromRequest(HttpRequest request) { diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ContainerConfig.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ContainerConfig.java index 1239069c1a0..d383e90d184 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ContainerConfig.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ContainerConfig.java @@ -12,8 +12,15 @@ public class ContainerConfig { public static final String servicesXmlV2(int port) { return "<jdisc version='1.0'>" + + " <component id='com.yahoo.test.ManualClock'/>" + + " <component id='com.yahoo.vespa.curator.mock.MockCurator'/>" + + " <component id='com.yahoo.vespa.hosted.provision.testutils.OrchestratorMock'/>" + + " <component id='com.yahoo.vespa.hosted.provision.testutils.MockDeployer'/>" + + " <component id='com.yahoo.vespa.hosted.provision.testutils.TestHostLivenessTracker'/>" + + " <component id='com.yahoo.vespa.hosted.provision.testutils.ServiceMonitorStub'/>" + " <component id='com.yahoo.vespa.hosted.provision.testutils.MockNodeFlavors'/>" + " <component id='com.yahoo.vespa.hosted.provision.testutils.MockNodeRepository'/>" + + " <component id='com.yahoo.vespa.hosted.provision.maintenance.NodeRepositoryMaintenance'/>" + " <handler id='com.yahoo.vespa.hosted.provision.restapi.v2.NodesApiHandler'>" + " <binding>http://*/nodes/v2/*</binding>" + " </handler>" + diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MockDeployer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockDeployer.java index 377cb2e4443..e46797240f2 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MockDeployer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockDeployer.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.provision.maintenance; +package com.yahoo.vespa.hosted.provision.testutils; +import com.google.inject.Inject; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.ClusterSpec; @@ -12,6 +13,7 @@ import com.yahoo.transaction.NestedTransaction; import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner; import java.time.Duration; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -27,6 +29,12 @@ public class MockDeployer implements Deployer { /** The number of redeployments done to this */ public int redeployments = 0; + @Inject + @SuppressWarnings("unused") + public MockDeployer() { + this(null, Collections.emptyMap()); + } + /** * Create a mock deployer which contains a substitute for an application repository, fullfilled to * be able to call provision with the right parameters. diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java index a8490076d5b..adfccd1f874 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java @@ -43,19 +43,14 @@ public class MockNodeRepository extends NodeRepository { * Constructor * @param flavors flavors to have in node repo */ - public MockNodeRepository(NodeFlavors flavors) throws Exception { - super(flavors, mockCurator(), Clock.fixed(Instant.ofEpochMilli(123), ZoneId.of("Z")), Zone.defaultZone(), + public MockNodeRepository(MockCurator curator, NodeFlavors flavors) throws Exception { + super(flavors, curator, Clock.fixed(Instant.ofEpochMilli(123), ZoneId.of("Z")), Zone.defaultZone(), new MockNameResolver().mockAnyLookup()); this.flavors = flavors; + curator.setConnectionSpec("cfg1:1234,cfg2:1234,cfg3:1234"); populate(); } - private static Curator mockCurator() { - MockCurator mockCurator = new MockCurator(); - mockCurator.setConnectionSpec("cfg1:1234,cfg2:1234,cfg3:1234"); - return mockCurator; - } - private void populate() { NodeRepositoryProvisioner provisioner = new NodeRepositoryProvisioner(this, flavors, Zone.defaultZone()); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/OrchestratorMock.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/OrchestratorMock.java new file mode 100644 index 00000000000..3de5278cd41 --- /dev/null +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/OrchestratorMock.java @@ -0,0 +1,64 @@ +package com.yahoo.vespa.hosted.provision.testutils; + +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.vespa.applicationmodel.HostName; +import com.yahoo.vespa.orchestrator.ApplicationIdNotFoundException; +import com.yahoo.vespa.orchestrator.ApplicationStateChangeDeniedException; +import com.yahoo.vespa.orchestrator.BatchHostNameNotFoundException; +import com.yahoo.vespa.orchestrator.BatchInternalErrorException; +import com.yahoo.vespa.orchestrator.HostNameNotFoundException; +import com.yahoo.vespa.orchestrator.Orchestrator; +import com.yahoo.vespa.orchestrator.policy.BatchHostStateChangeDeniedException; +import com.yahoo.vespa.orchestrator.policy.HostStateChangeDeniedException; +import com.yahoo.vespa.orchestrator.status.ApplicationInstanceStatus; +import com.yahoo.vespa.orchestrator.status.HostStatus; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author bratseth + */ +public class OrchestratorMock implements Orchestrator { + + Set<ApplicationId> suspendedApplications = new HashSet<>(); + + @Override + public HostStatus getNodeStatus(HostName hostName) throws HostNameNotFoundException { + return null; + } + + @Override + public void resume(HostName hostName) throws HostStateChangeDeniedException, HostNameNotFoundException {} + + @Override + public void suspend(HostName hostName) throws HostStateChangeDeniedException, HostNameNotFoundException {} + + @Override + public ApplicationInstanceStatus getApplicationInstanceStatus(ApplicationId appId) throws ApplicationIdNotFoundException { + return suspendedApplications.contains(appId) + ? ApplicationInstanceStatus.ALLOWED_TO_BE_DOWN : ApplicationInstanceStatus.NO_REMARKS; + } + + @Override + public Set<ApplicationId> getAllSuspendedApplications() { + return null; + } + + @Override + public void resume(ApplicationId appId) throws ApplicationStateChangeDeniedException, ApplicationIdNotFoundException { + suspendedApplications.remove(appId); + } + + @Override + public void suspend(ApplicationId appId) throws ApplicationStateChangeDeniedException, ApplicationIdNotFoundException { + suspendedApplications.add(appId); + } + + @Override + public void suspendAll(HostName parentHostname, List<HostName> hostNames) throws BatchInternalErrorException, BatchHostStateChangeDeniedException, BatchHostNameNotFoundException { + throw new RuntimeException("Not implemented"); + } + +} diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ServiceMonitorStub.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ServiceMonitorStub.java new file mode 100644 index 00000000000..983f81be126 --- /dev/null +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ServiceMonitorStub.java @@ -0,0 +1,91 @@ +package com.yahoo.vespa.hosted.provision.testutils; + +import com.google.inject.Inject; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.vespa.applicationmodel.ApplicationInstance; +import com.yahoo.vespa.applicationmodel.ApplicationInstanceId; +import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference; +import com.yahoo.vespa.applicationmodel.ClusterId; +import com.yahoo.vespa.applicationmodel.ConfigId; +import com.yahoo.vespa.applicationmodel.HostName; +import com.yahoo.vespa.applicationmodel.ServiceCluster; +import com.yahoo.vespa.applicationmodel.ServiceInstance; +import com.yahoo.vespa.applicationmodel.ServiceType; +import com.yahoo.vespa.applicationmodel.TenantId; +import com.yahoo.vespa.hosted.provision.Node; +import com.yahoo.vespa.hosted.provision.NodeRepository; +import com.yahoo.vespa.service.monitor.ServiceMonitor; +import com.yahoo.vespa.service.monitor.ServiceMonitorStatus; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author bratseth + */ +public class ServiceMonitorStub implements ServiceMonitor { + + private final Map<ApplicationId, MockDeployer.ApplicationContext> apps; + private final NodeRepository nodeRepository; + + private Set<String> downHosts = new HashSet<>(); + private boolean statusIsKnown = true; + + /** Create a service monitor where all nodes are initially up */ + @Inject + @SuppressWarnings("unused") + public ServiceMonitorStub(NodeRepository nodeRepository) { + this(Collections.emptyMap(), nodeRepository); + } + + /** Create a service monitor where all nodes are initially up */ + public ServiceMonitorStub(Map<ApplicationId, MockDeployer.ApplicationContext> apps, NodeRepository nodeRepository) { + this.apps = apps; + this.nodeRepository = nodeRepository; + } + + public void setHostDown(String hostname) { + downHosts.add(hostname); + } + + public void setHostUp(String hostname) { + downHosts.remove(hostname); + } + + public void setStatusIsKnown(boolean statusIsKnown) { + this.statusIsKnown = statusIsKnown; + } + + private ServiceMonitorStatus getHostStatus(String hostname) { + if (!statusIsKnown) return ServiceMonitorStatus.NOT_CHECKED; + if (downHosts.contains(hostname)) return ServiceMonitorStatus.DOWN; + return ServiceMonitorStatus.UP; + } + + @Override + public Map<ApplicationInstanceReference, ApplicationInstance<ServiceMonitorStatus>> queryStatusOfAllApplicationInstances() { + // Convert apps information to the response payload to return + Map<ApplicationInstanceReference, ApplicationInstance<ServiceMonitorStatus>> status = new HashMap<>(); + for (Map.Entry<ApplicationId, MockDeployer.ApplicationContext> app : apps.entrySet()) { + Set<ServiceInstance<ServiceMonitorStatus>> serviceInstances = new HashSet<>(); + for (Node node : nodeRepository.getNodes(app.getValue().id(), Node.State.active)) { + serviceInstances.add(new ServiceInstance<>(new ConfigId("configid"), + new HostName(node.hostname()), + getHostStatus(node.hostname()))); + } + Set<ServiceCluster<ServiceMonitorStatus>> serviceClusters = new HashSet<>(); + serviceClusters.add(new ServiceCluster<>(new ClusterId(app.getValue().cluster().id().value()), + new ServiceType("serviceType"), + serviceInstances)); + TenantId tenantId = new TenantId(app.getKey().tenant().value()); + ApplicationInstanceId applicationInstanceId = new ApplicationInstanceId(app.getKey().application().value()); + status.put(new ApplicationInstanceReference(tenantId, applicationInstanceId), + new ApplicationInstance<>(tenantId, applicationInstanceId, serviceClusters)); + } + return status; + } + +} diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/TestHostLivenessTracker.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/TestHostLivenessTracker.java new file mode 100644 index 00000000000..e0ad7238f4a --- /dev/null +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/TestHostLivenessTracker.java @@ -0,0 +1,31 @@ +package com.yahoo.vespa.hosted.provision.testutils; + +import com.yahoo.config.provision.HostLivenessTracker; + +import java.time.Clock; +import java.time.Instant; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +/** This is a fully functional implementation */ +public class TestHostLivenessTracker implements HostLivenessTracker { + + private final Clock clock; + private final Map<String, Instant> lastRequestFromHost = new HashMap<>(); + + public TestHostLivenessTracker(Clock clock) { + this.clock = clock; + } + + @Override + public void receivedRequestFrom(String hostname) { + lastRequestFromHost.put(hostname, clock.instant()); + } + + @Override + public Optional<Instant> lastRequestFrom(String hostname) { + return Optional.ofNullable(lastRequestFromHost.get(hostname)); + } + +} diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java index a07deff3543..47055af075e 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java @@ -16,6 +16,7 @@ import com.yahoo.config.provision.Zone; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.node.History; import com.yahoo.vespa.hosted.provision.provisioning.ProvisioningTester; +import com.yahoo.vespa.hosted.provision.testutils.MockDeployer; import org.junit.Test; import java.time.Duration; diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java index 4e51138eceb..378c1bf554b 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java @@ -7,7 +7,6 @@ import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.Flavor; -import com.yahoo.config.provision.HostLivenessTracker; import com.yahoo.config.provision.HostSpec; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.NodeFlavors; @@ -17,16 +16,6 @@ import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.Zone; import com.yahoo.test.ManualClock; import com.yahoo.transaction.NestedTransaction; -import com.yahoo.vespa.applicationmodel.ApplicationInstance; -import com.yahoo.vespa.applicationmodel.ApplicationInstanceId; -import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference; -import com.yahoo.vespa.applicationmodel.ClusterId; -import com.yahoo.vespa.applicationmodel.ConfigId; -import com.yahoo.vespa.applicationmodel.HostName; -import com.yahoo.vespa.applicationmodel.ServiceCluster; -import com.yahoo.vespa.applicationmodel.ServiceInstance; -import com.yahoo.vespa.applicationmodel.ServiceType; -import com.yahoo.vespa.applicationmodel.TenantId; import com.yahoo.vespa.curator.Curator; import com.yahoo.vespa.curator.mock.MockCurator; import com.yahoo.vespa.curator.transaction.CuratorTransaction; @@ -34,23 +23,14 @@ import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner; import com.yahoo.vespa.hosted.provision.testutils.FlavorConfigBuilder; +import com.yahoo.vespa.hosted.provision.testutils.MockDeployer; import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver; -import com.yahoo.vespa.orchestrator.ApplicationIdNotFoundException; -import com.yahoo.vespa.orchestrator.ApplicationStateChangeDeniedException; -import com.yahoo.vespa.orchestrator.BatchHostNameNotFoundException; -import com.yahoo.vespa.orchestrator.BatchInternalErrorException; -import com.yahoo.vespa.orchestrator.HostNameNotFoundException; +import com.yahoo.vespa.hosted.provision.testutils.OrchestratorMock; +import com.yahoo.vespa.hosted.provision.testutils.ServiceMonitorStub; +import com.yahoo.vespa.hosted.provision.testutils.TestHostLivenessTracker; import com.yahoo.vespa.orchestrator.Orchestrator; -import com.yahoo.vespa.orchestrator.policy.BatchHostStateChangeDeniedException; -import com.yahoo.vespa.orchestrator.policy.HostStateChangeDeniedException; -import com.yahoo.vespa.orchestrator.status.ApplicationInstanceStatus; -import com.yahoo.vespa.orchestrator.status.HostStatus; -import com.yahoo.vespa.service.monitor.ServiceMonitor; -import com.yahoo.vespa.service.monitor.ServiceMonitorStatus; - -import java.time.Clock; + import java.time.Duration; -import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -59,7 +39,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Set; import static org.junit.Assert.assertEquals; @@ -265,125 +244,4 @@ public class NodeFailTester { return highestIndex; } - /** This is a fully functional implementation */ - private static class TestHostLivenessTracker implements HostLivenessTracker { - - private final Clock clock; - private final Map<String, Instant> lastRequestFromHost = new HashMap<>(); - - public TestHostLivenessTracker(Clock clock) { - this.clock = clock; - } - - @Override - public void receivedRequestFrom(String hostname) { - lastRequestFromHost.put(hostname, clock.instant()); - } - - @Override - public Optional<Instant> lastRequestFrom(String hostname) { - return Optional.ofNullable(lastRequestFromHost.get(hostname)); - } - - } - - public static class ServiceMonitorStub implements ServiceMonitor { - - private final Map<ApplicationId, MockDeployer.ApplicationContext> apps; - private final NodeRepository nodeRepository; - - private Set<String> downHosts = new HashSet<>(); - private boolean statusIsKnown = true; - - /** Create a service monitor where all nodes are initially up */ - public ServiceMonitorStub(Map<ApplicationId, MockDeployer.ApplicationContext> apps, NodeRepository nodeRepository) { - this.apps = apps; - this.nodeRepository = nodeRepository; - } - - public void setHostDown(String hostname) { - downHosts.add(hostname); - } - - public void setHostUp(String hostname) { - downHosts.remove(hostname); - } - - public void setStatusIsKnown(boolean statusIsKnown) { - this.statusIsKnown = statusIsKnown; - } - - private ServiceMonitorStatus getHostStatus(String hostname) { - if ( ! statusIsKnown) return ServiceMonitorStatus.NOT_CHECKED; - if (downHosts.contains(hostname)) return ServiceMonitorStatus.DOWN; - return ServiceMonitorStatus.UP; - } - - @Override - public Map<ApplicationInstanceReference, ApplicationInstance<ServiceMonitorStatus>> queryStatusOfAllApplicationInstances() { - // Convert apps information to the response payload to return - Map<ApplicationInstanceReference, ApplicationInstance<ServiceMonitorStatus>> status = new HashMap<>(); - for (Map.Entry<ApplicationId, MockDeployer.ApplicationContext> app : apps.entrySet()) { - Set<ServiceInstance<ServiceMonitorStatus>> serviceInstances = new HashSet<>(); - for (Node node : nodeRepository.getNodes(app.getValue().id(), Node.State.active)) { - serviceInstances.add(new ServiceInstance<>(new ConfigId("configid"), - new HostName(node.hostname()), - getHostStatus(node.hostname()))); - } - Set<ServiceCluster<ServiceMonitorStatus>> serviceClusters = new HashSet<>(); - serviceClusters.add(new ServiceCluster<>(new ClusterId(app.getValue().cluster().id().value()), - new ServiceType("serviceType"), - serviceInstances)); - TenantId tenantId = new TenantId(app.getKey().tenant().value()); - ApplicationInstanceId applicationInstanceId = new ApplicationInstanceId(app.getKey().application().value()); - status.put(new ApplicationInstanceReference(tenantId, applicationInstanceId), - new ApplicationInstance<>(tenantId, applicationInstanceId, serviceClusters)); - } - return status; - } - - } - - class OrchestratorMock implements Orchestrator { - - Set<ApplicationId> suspendedApplications = new HashSet<>(); - - @Override - public HostStatus getNodeStatus(HostName hostName) throws HostNameNotFoundException { - return null; - } - - @Override - public void resume(HostName hostName) throws HostStateChangeDeniedException, HostNameNotFoundException {} - - @Override - public void suspend(HostName hostName) throws HostStateChangeDeniedException, HostNameNotFoundException {} - - @Override - public ApplicationInstanceStatus getApplicationInstanceStatus(ApplicationId appId) throws ApplicationIdNotFoundException { - return suspendedApplications.contains(appId) - ? ApplicationInstanceStatus.ALLOWED_TO_BE_DOWN : ApplicationInstanceStatus.NO_REMARKS; - } - - @Override - public Set<ApplicationId> getAllSuspendedApplications() { - return null; - } - - @Override - public void resume(ApplicationId appId) throws ApplicationStateChangeDeniedException, ApplicationIdNotFoundException { - suspendedApplications.remove(appId); - } - - @Override - public void suspend(ApplicationId appId) throws ApplicationStateChangeDeniedException, ApplicationIdNotFoundException { - suspendedApplications.add(appId); - } - - @Override - public void suspendAll(HostName parentHostname, List<HostName> hostNames) throws BatchInternalErrorException, BatchHostStateChangeDeniedException, BatchHostNameNotFoundException { - throw new RuntimeException("Not implemented"); - } - } - } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java index 5ce876bf12c..91ce0a8ef59 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java @@ -25,6 +25,7 @@ import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.node.Agent; import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner; import com.yahoo.vespa.hosted.provision.testutils.FlavorConfigBuilder; +import com.yahoo.vespa.hosted.provision.testutils.MockDeployer; import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver; import org.junit.Test; diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java index 844571acce5..69ef4744001 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java @@ -27,6 +27,7 @@ import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.node.Agent; import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner; import com.yahoo.vespa.hosted.provision.testutils.FlavorConfigBuilder; +import com.yahoo.vespa.hosted.provision.testutils.MockDeployer; import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver; import org.junit.Before; import org.junit.Test; diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java index 085f711058b..f034490b3f7 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java @@ -23,6 +23,7 @@ import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.config.provision.NodeFlavors; import com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner; import com.yahoo.vespa.hosted.provision.testutils.FlavorConfigBuilder; +import com.yahoo.vespa.hosted.provision.testutils.MockDeployer; import com.yahoo.vespa.hosted.provision.testutils.MockNameResolver; import org.junit.Test; diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java index b4f17cc003c..6ef0e6ab01f 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java @@ -11,7 +11,7 @@ import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.Zone; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.maintenance.JobControl; -import com.yahoo.vespa.hosted.provision.maintenance.MockDeployer; +import com.yahoo.vespa.hosted.provision.testutils.MockDeployer; import com.yahoo.vespa.hosted.provision.maintenance.RetiredExpirer; import org.junit.Ignore; import org.junit.Test; diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodeStateSerializerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodeStateSerializerTest.java index c4f96b0709a..de7a9bac878 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodeStateSerializerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodeStateSerializerTest.java @@ -8,38 +8,39 @@ import org.junit.Test; import java.util.HashSet; import java.util.Set; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; /** * @author bakksjo */ public class NodeStateSerializerTest { + @Test public void allStatesHaveASerializedForm() { for (Node.State nodeState : Node.State.values()) { - assertThat(NodeStateSerializer.wireNameOf(nodeState), is(notNullValue())); + assertNotNull(NodeStateSerializer.wireNameOf(nodeState)); } } @Test public void wireNamesDoNotOverlap() { - final Set<String> wireNames = new HashSet<>(); + Set<String> wireNames = new HashSet<>(); for (Node.State nodeState : Node.State.values()) { wireNames.add(NodeStateSerializer.wireNameOf(nodeState)); } - assertThat(wireNames.size(), is(Node.State.values().length)); + assertEquals(Node.State.values().length, wireNames.size()); } @Test public void serializationAndDeserializationIsSymmetric() { for (Node.State nodeState : Node.State.values()) { - final String serialized = NodeStateSerializer.wireNameOf(nodeState); - final Node.State deserialized = NodeStateSerializer.fromWireName(serialized) + String serialized = NodeStateSerializer.wireNameOf(nodeState); + Node.State deserialized = NodeStateSerializer.fromWireName(serialized) .orElseThrow(() -> new RuntimeException( "Cannot deserialize '" + serialized + "', serialized form of " + nodeState.name())); - assertThat(deserialized, is(nodeState)); + assertEquals(nodeState, deserialized); } } + } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/maintenance.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/maintenance.json new file mode 100644 index 00000000000..3ee004d1e29 --- /dev/null +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/maintenance.json @@ -0,0 +1,10 @@ +{ + "jobs": [ + { + "name" : "Job1" + } + ], + "inactive" : [ + + ] +}
\ No newline at end of file diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/root.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/root.json index 9648c059af6..4224718ab06 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/root.json +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/root.json @@ -8,6 +8,9 @@ }, { "url": "http://localhost:8080/nodes/v2/command/" + }, + { + "url": "http://localhost:8080/nodes/v2/maintenance/" } ] }
\ No newline at end of file diff --git a/testutil/pom.xml b/testutil/pom.xml index bd46d2e4c16..8d132737852 100644 --- a/testutil/pom.xml +++ b/testutil/pom.xml @@ -20,6 +20,11 @@ <scope>provided</scope> </dependency> <dependency> + <groupId>com.google.inject</groupId> + <artifactId>inject</artifactId> + <scope>provided</scope> + </dependency> + <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId> <scope>compile</scope> diff --git a/testutil/src/main/java/com/yahoo/test/ManualClock.java b/testutil/src/main/java/com/yahoo/test/ManualClock.java index 1ffc7aa77da..e3ed647e03b 100644 --- a/testutil/src/main/java/com/yahoo/test/ManualClock.java +++ b/testutil/src/main/java/com/yahoo/test/ManualClock.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.test; +import com.google.inject.Inject; import java.time.Clock; import java.time.Instant; import java.time.LocalDateTime; @@ -14,6 +15,7 @@ public class ManualClock extends Clock { private Instant currentTime = Instant.now(); + @Inject public ManualClock() {} public ManualClock(String utcIsoTime) { diff --git a/vespalog/src/main/java/com/yahoo/log/VespaFormatter.java b/vespalog/src/main/java/com/yahoo/log/VespaFormatter.java index ee0f6e90b7c..b6a63c52321 100644 --- a/vespalog/src/main/java/com/yahoo/log/VespaFormatter.java +++ b/vespalog/src/main/java/com/yahoo/log/VespaFormatter.java @@ -137,7 +137,8 @@ public class VespaFormatter extends SimpleFormatter { private void appendException(Throwable throwable, StringBuilder builder) { if (throwable == null) return; - +//throwable.printStackTrace(); +if (1==1) return; String escapedStackTrace = VespaFormat.escape(stackTrace(throwable)); builder.append("\\n").append("exception=").append("\\n").append(escapedStackTrace); } @@ -169,4 +170,36 @@ public class VespaFormatter extends SimpleFormatter { public String getServiceName () { return serviceName; } + + + public static String toMessageString(Throwable t) { + StringBuilder b = new StringBuilder(); + String lastMessage = null; + String message; + for (; t != null; t = t.getCause()) { + message = getMessage(t); + if (message == null) continue; + if (message.equals(lastMessage)) continue; + if (b.length() > 0) { + b.append(": "); + } + b.append(message); + lastMessage = message; + } + return b.toString(); + } + + /** Returns a useful message from *this* exception, or null if there is nothing useful to return */ + private static String getMessage(Throwable t) { + String message = t.getMessage(); + if (t.getCause() == null) { + if (message == null) return t.getClass().getSimpleName(); + } else { + if (message == null) return null; + //if (message.equals(t.getCause().getClass().getName() + ": " + t.getCause().getMessage())) return null; + } + return message; + } + + } diff --git a/zkfacade/src/main/java/com/yahoo/vespa/curator/mock/MockCurator.java b/zkfacade/src/main/java/com/yahoo/vespa/curator/mock/MockCurator.java index 4615eb4e34a..2e70d1d736b 100644 --- a/zkfacade/src/main/java/com/yahoo/vespa/curator/mock/MockCurator.java +++ b/zkfacade/src/main/java/com/yahoo/vespa/curator/mock/MockCurator.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.curator.mock; +import com.google.inject.Inject; import com.yahoo.collections.Pair; import com.yahoo.path.Path; import static com.yahoo.vespa.curator.mock.MemoryFileSystem.Node; @@ -115,6 +116,7 @@ public class MockCurator extends Curator { private final CuratorFramework curatorFramework; /** Creates a mock curator with stable ordering */ + @Inject public MockCurator() { this(true); } |