diff options
Diffstat (limited to 'orchestrator')
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()))) { |