aboutsummaryrefslogtreecommitdiffstats
path: root/orchestrator
diff options
context:
space:
mode:
authorHåkon Hallingstad <hakon@oath.com>2017-10-25 17:36:20 +0200
committerHåkon Hallingstad <hakon@oath.com>2017-10-25 17:36:20 +0200
commit37ce355370e8483c05bd9a7ce9f4f248e19ad4fb (patch)
treea8f0ec831ee667ecd909fad6b5206fdae5307821 /orchestrator
parent9606e88b7ca082f36eb38b0e197a0513f76ef6eb (diff)
Provide more info in host Orchestrator REST API
Diffstat (limited to 'orchestrator')
-rw-r--r--orchestrator/src/main/java/com/yahoo/vespa/orchestrator/Host.java42
-rw-r--r--orchestrator/src/main/java/com/yahoo/vespa/orchestrator/Orchestrator.java6
-rw-r--r--orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java15
-rw-r--r--orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java30
-rw-r--r--orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java74
5 files changed, 163 insertions, 4 deletions
diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/Host.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/Host.java
new file mode 100644
index 00000000000..8e06f3b342a
--- /dev/null
+++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/Host.java
@@ -0,0 +1,42 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.orchestrator;
+
+import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference;
+import com.yahoo.vespa.applicationmodel.HostName;
+import com.yahoo.vespa.applicationmodel.ServiceInstance;
+import com.yahoo.vespa.orchestrator.status.HostStatus;
+
+import java.util.List;
+
+public class Host {
+ private final HostName hostName;
+ private final HostStatus hostStatus;
+ private final ApplicationInstanceReference applicationInstanceReference;
+ private final List<ServiceInstance> serviceInstances;
+
+ public Host(HostName hostName,
+ HostStatus hostStatus,
+ ApplicationInstanceReference applicationInstanceReference,
+ List<ServiceInstance> serviceInstances) {
+ this.hostName = hostName;
+ this.hostStatus = hostStatus;
+ this.applicationInstanceReference = applicationInstanceReference;
+ this.serviceInstances = serviceInstances;
+ }
+
+ public HostName getHostName() {
+ return hostName;
+ }
+
+ public HostStatus getHostStatus() {
+ return hostStatus;
+ }
+
+ public ApplicationInstanceReference getApplicationInstanceReference() {
+ return applicationInstanceReference;
+ }
+
+ public List<ServiceInstance> getServiceInstances() {
+ return serviceInstances;
+ }
+}
diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/Orchestrator.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/Orchestrator.java
index 9702b97dc28..ab61a51c418 100644
--- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/Orchestrator.java
+++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/Orchestrator.java
@@ -32,6 +32,12 @@ import java.util.Set;
public interface Orchestrator {
/**
+ * Get orchestrator information related to a host.
+ * @throws HostNameNotFoundException
+ */
+ Host getHost(HostName hostName) throws HostNameNotFoundException;
+
+ /**
* Get the status of a given node. If no state is recorded
* then this will return the status 'No Remarks'
*
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 ef81a45fefe..dbc526bdf03 100644
--- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java
+++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java
@@ -9,6 +9,7 @@ import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference;
import com.yahoo.vespa.applicationmodel.ClusterId;
import com.yahoo.vespa.applicationmodel.HostName;
import com.yahoo.vespa.applicationmodel.ServiceCluster;
+import com.yahoo.vespa.applicationmodel.ServiceInstance;
import com.yahoo.vespa.orchestrator.config.OrchestratorConfig;
import com.yahoo.vespa.orchestrator.controller.ClusterControllerClient;
import com.yahoo.vespa.orchestrator.controller.ClusterControllerClientFactory;
@@ -78,6 +79,20 @@ public class OrchestratorImpl implements Orchestrator {
}
@Override
+ public Host getHost(HostName hostName) throws HostNameNotFoundException {
+ ApplicationInstance applicationInstance = getApplicationInstance(hostName);
+ List<ServiceInstance> serviceInstances = applicationInstance
+ .serviceClusters().stream()
+ .flatMap(cluster -> cluster.serviceInstances().stream())
+ .filter(serviceInstance -> hostName.equals(serviceInstance.hostName()))
+ .collect(Collectors.toList());
+
+ HostStatus hostStatus = getNodeStatus(applicationInstance.reference(), hostName);
+
+ return new Host(hostName, hostStatus, applicationInstance.reference(), serviceInstances);
+ }
+
+ @Override
public HostStatus getNodeStatus(HostName hostName) throws HostNameNotFoundException {
return getNodeStatus(getApplicationInstance(hostName).reference(), hostName);
}
diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java
index b5ef2822761..198f291266b 100644
--- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java
+++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java
@@ -4,12 +4,14 @@ package com.yahoo.vespa.orchestrator.resources;
import com.yahoo.container.jaxrs.annotation.Component;
import com.yahoo.log.LogLevel;
import com.yahoo.vespa.applicationmodel.HostName;
+import com.yahoo.vespa.orchestrator.Host;
import com.yahoo.vespa.orchestrator.HostNameNotFoundException;
import com.yahoo.vespa.orchestrator.OrchestrationException;
import com.yahoo.vespa.orchestrator.Orchestrator;
import com.yahoo.vespa.orchestrator.policy.HostStateChangeDeniedException;
import com.yahoo.vespa.orchestrator.restapi.HostApi;
import com.yahoo.vespa.orchestrator.restapi.wire.GetHostResponse;
+import com.yahoo.vespa.orchestrator.restapi.wire.HostService;
import com.yahoo.vespa.orchestrator.restapi.wire.HostStateChangeDenialReason;
import com.yahoo.vespa.orchestrator.restapi.wire.PatchHostRequest;
import com.yahoo.vespa.orchestrator.restapi.wire.PatchHostResponse;
@@ -24,7 +26,11 @@ import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.net.URI;
+import java.util.List;
import java.util.logging.Logger;
+import java.util.stream.Collectors;
/**
* @author oyving
@@ -41,11 +47,29 @@ public class HostResource implements HostApi {
}
@Override
- public GetHostResponse getHost(String hostNameString) {
+ public GetHostResponse getHost(UriInfo uriInfo, String hostNameString) {
HostName hostName = new HostName(hostNameString);
try {
- HostStatus status = orchestrator.getNodeStatus(hostName);
- return new GetHostResponse(hostName.s(), status.name());
+ Host host = orchestrator.getHost(hostName);
+
+ URI applicationUri = uriInfo.getBaseUriBuilder()
+ .path(InstanceResource.class)
+ .path(host.getApplicationInstanceReference().asString())
+ .build();
+
+ List<HostService> hostServices = host.getServiceInstances().stream()
+ .map(serviceInstance -> new HostService(
+ serviceInstance.getServiceCluster().clusterId().s(),
+ serviceInstance.getServiceCluster().serviceType().s(),
+ serviceInstance.configId().s(),
+ serviceInstance.serviceStatus().name()))
+ .collect(Collectors.toList());
+
+ return new GetHostResponse(
+ host.getHostName().s(),
+ host.getHostStatus().name(),
+ applicationUri.toString(),
+ hostServices);
} catch (HostNameNotFoundException e) {
log.log(LogLevel.INFO, "Host not found: " + hostName);
throw new NotFoundException(e);
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 8cf9d343134..76d9398c44e 100644
--- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java
+++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java
@@ -3,14 +3,25 @@ package com.yahoo.vespa.orchestrator;
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.ServiceStatus;
+import com.yahoo.vespa.applicationmodel.ServiceType;
+import com.yahoo.vespa.applicationmodel.TenantId;
import com.yahoo.vespa.orchestrator.config.OrchestratorConfig;
+import com.yahoo.vespa.orchestrator.controller.ClusterControllerClientFactory;
import com.yahoo.vespa.orchestrator.controller.ClusterControllerClientFactoryMock;
import com.yahoo.vespa.orchestrator.policy.BatchHostStateChangeDeniedException;
import com.yahoo.vespa.orchestrator.policy.HostStateChangeDeniedException;
import com.yahoo.vespa.orchestrator.status.HostStatus;
import com.yahoo.vespa.orchestrator.status.InMemoryStatusService;
+import com.yahoo.vespa.orchestrator.status.ReadOnlyStatusRegistry;
+import com.yahoo.vespa.orchestrator.status.StatusService;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -18,6 +29,9 @@ import org.mockito.InOrder;
import java.util.Arrays;
import java.util.Iterator;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static com.yahoo.vespa.orchestrator.status.ApplicationInstanceStatus.ALLOWED_TO_BE_DOWN;
import static com.yahoo.vespa.orchestrator.status.ApplicationInstanceStatus.NO_REMARKS;
@@ -31,7 +45,9 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
/**
* Test Orchestrator with a mock backend (the InMemoryStatusService)
@@ -139,7 +155,6 @@ public class OrchestratorImplTest {
assertThat(orchestrator.getApplicationInstanceStatus(app2), is(ALLOWED_TO_BE_DOWN));
}
-
@Test
public void application_suspend_sets_application_nodes_in_maintenance_and_allowed_to_be_down() throws Exception {
// Pre condition
@@ -281,6 +296,63 @@ public class OrchestratorImplTest {
order.verifyNoMoreInteractions();
}
+ @Test
+ public void testGetHost() throws Exception {
+ ClusterControllerClientFactory clusterControllerClientFactory =
+ mock(ClusterControllerClientFactory.class);
+ StatusService statusService = mock(StatusService.class);
+ InstanceLookupService lookupService = mock(InstanceLookupService.class);
+
+ orchestrator = new OrchestratorImpl(
+ clusterControllerClientFactory,
+ statusService,
+ new OrchestratorConfig(new OrchestratorConfig.Builder()),
+ lookupService);
+
+ HostName hostName = new HostName("host.yahoo.com");
+ TenantId tenantId = new TenantId("tenant");
+ ApplicationInstanceId applicationInstanceId =
+ new ApplicationInstanceId("applicationInstanceId");
+ ApplicationInstanceReference reference = new ApplicationInstanceReference(
+ tenantId,
+ applicationInstanceId);
+
+ ApplicationInstance applicationInstance =
+ new ApplicationInstance(
+ tenantId,
+ applicationInstanceId,
+ Stream.of(new ServiceCluster(
+ new ClusterId("clusterId"),
+ new ServiceType("serviceType"),
+ Stream.of(
+ new ServiceInstance(
+ new ConfigId("configId1"),
+ hostName,
+ ServiceStatus.UP),
+ new ServiceInstance(
+ new ConfigId("configId2"),
+ hostName,
+ ServiceStatus.NOT_CHECKED))
+ .collect(Collectors.toSet())))
+ .collect(Collectors.toSet()));
+
+ when(lookupService.findInstanceByHost(hostName))
+ .thenReturn(Optional.of(applicationInstance));
+
+ ReadOnlyStatusRegistry readOnlyStatusRegistry = mock(ReadOnlyStatusRegistry.class);
+ when(statusService.forApplicationInstance(reference))
+ .thenReturn(readOnlyStatusRegistry);
+ when(readOnlyStatusRegistry.getHostStatus(hostName))
+ .thenReturn(HostStatus.ALLOWED_TO_BE_DOWN);
+
+ Host host = orchestrator.getHost(hostName);
+
+ assertEquals(reference, host.getApplicationInstanceReference());
+ assertEquals(hostName, host.getHostName());
+ assertEquals(HostStatus.ALLOWED_TO_BE_DOWN, host.getHostStatus());
+ assertEquals(2, host.getServiceInstances().size());
+ }
+
private boolean isInMaintenance(ApplicationId appId, HostName hostName) throws ApplicationIdNotFoundException {
for (ApplicationInstance app : DummyInstanceLookupService.getApplications()) {
if (app.reference().equals(OrchestratorUtil.toApplicationInstanceReference(appId, new DummyInstanceLookupService()))) {