diff options
13 files changed, 316 insertions, 23 deletions
diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceCluster.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceCluster.java index d18ced478f1..e53058f40e3 100644 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceCluster.java +++ b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceCluster.java @@ -1,9 +1,11 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.applicationmodel; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; +import java.util.Optional; import java.util.Set; /** @@ -16,6 +18,7 @@ public class ServiceCluster { private final ClusterId clusterId; private final ServiceType serviceType; private final Set<ServiceInstance> serviceInstances; + private Optional<ApplicationInstance> applicationInstance = Optional.empty(); public ServiceCluster(ClusterId clusterId, ServiceType serviceType, Set<ServiceInstance> serviceInstances) { this.clusterId = clusterId; @@ -38,12 +41,25 @@ public class ServiceCluster { return serviceInstances; } + @JsonIgnore + public void setApplicationInstance(ApplicationInstance applicationInstance) { + this.applicationInstance = Optional.of(applicationInstance); + } + + @JsonIgnore + public ApplicationInstance getApplicationInstance() { + return applicationInstance.get(); + } + @Override public String toString() { return "ServiceCluster{" + "clusterId=" + clusterId + ", serviceType=" + serviceType + ", serviceInstances=" + serviceInstances + + (applicationInstance.isPresent() ? + ", applicationInstance=" + applicationInstance.get() : + "") + '}'; } @@ -54,12 +70,12 @@ public class ServiceCluster { ServiceCluster that = (ServiceCluster) o; return Objects.equals(clusterId, that.clusterId) && Objects.equals(serviceType, that.serviceType) && - Objects.equals(serviceInstances, that.serviceInstances); + Objects.equals(serviceInstances, that.serviceInstances) && + Objects.equals(applicationInstance, that.applicationInstance); } @Override public int hashCode() { - return Objects.hash(clusterId, serviceType, serviceInstances); + return Objects.hash(clusterId, serviceType, serviceInstances, applicationInstance); } - } diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceInstance.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceInstance.java index 2b31bb11ff7..4c802218b22 100644 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceInstance.java +++ b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceInstance.java @@ -1,9 +1,11 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.applicationmodel; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; +import java.util.Optional; /** * @author bjorncs @@ -13,6 +15,7 @@ public class ServiceInstance { private final ConfigId configId; private final HostName hostName; private final ServiceStatus serviceStatus; + private Optional<ServiceCluster> serviceCluster = Optional.empty(); public ServiceInstance(ConfigId configId, HostName hostName, ServiceStatus serviceStatus) { this.configId = configId; @@ -35,12 +38,23 @@ public class ServiceInstance { return serviceStatus; } + @JsonIgnore + public void setServiceCluster(ServiceCluster serviceCluster) { + this.serviceCluster = Optional.of(serviceCluster); + } + + @JsonIgnore + public ServiceCluster getServiceCluster() { + return serviceCluster.get(); + } + @Override public String toString() { return "ServiceInstance{" + "configId=" + configId + ", hostName=" + hostName + ", serviceStatus=" + serviceStatus + + (serviceCluster.isPresent() ? ", serviceCluster=" + serviceCluster.get() : "") + '}'; } @@ -51,12 +65,12 @@ public class ServiceInstance { ServiceInstance that = (ServiceInstance) o; return Objects.equals(configId, that.configId) && Objects.equals(hostName, that.hostName) && - Objects.equals(serviceStatus, that.serviceStatus); + serviceStatus == that.serviceStatus && + Objects.equals(serviceCluster, that.serviceCluster); } @Override public int hashCode() { - return Objects.hash(configId, hostName, serviceStatus); + return Objects.hash(configId, hostName, serviceStatus, serviceCluster); } - } 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 index 19882f0a508..46d72974718 100644 --- 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 @@ -7,6 +7,7 @@ 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.Host; import com.yahoo.vespa.orchestrator.HostNameNotFoundException; import com.yahoo.vespa.orchestrator.OrchestrationException; import com.yahoo.vespa.orchestrator.Orchestrator; @@ -29,6 +30,11 @@ public class OrchestratorMock implements Orchestrator { Set<ApplicationId> suspendedApplications = new HashSet<>(); @Override + public Host getHost(HostName hostName) throws HostNameNotFoundException { + return null; + } + + @Override public HostStatus getNodeStatus(HostName hostName) throws HostNameNotFoundException { return null; } diff --git a/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/HostApi.java b/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/HostApi.java index 1c4d138acef..7f576f6c4e3 100644 --- a/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/HostApi.java +++ b/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/HostApi.java @@ -14,7 +14,9 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriInfo; /** * Definition of Orchestrator's REST API for hosts. @@ -38,7 +40,8 @@ public interface HostApi { @GET @Path("/{hostname}") @Produces(MediaType.APPLICATION_JSON) - GetHostResponse getHost(@PathParam("hostname") String hostNameString); + GetHostResponse getHost(@Context UriInfo uriInfo, + @PathParam("hostname") String hostNameString); /** * Tweak internal Orchestrator state for host. diff --git a/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/GetHostResponse.java b/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/GetHostResponse.java index 99489b345d4..38801c4c817 100644 --- a/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/GetHostResponse.java +++ b/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/GetHostResponse.java @@ -2,27 +2,48 @@ package com.yahoo.vespa.orchestrator.restapi.wire; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; import java.util.Objects; /* * @author andreer */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) public class GetHostResponse { public static final String FIELD_NAME_HOSTNAME = "hostname"; public static final String FIELD_NAME_STATE = "state"; + public static final String FIELD_NAME_APPLICATION_URL = "applicationUrl"; + public static final String FIELD_NAME_SERVICES = "services"; private final String hostname; private final String state; + private final String applicationUrl; + private final List<HostService> services; + + // Deprecated - kept for backwards compatibility until clients have migrated away + public GetHostResponse(String hostname, String state) { + this.hostname = hostname; + this.state = state; + this.applicationUrl = null; + this.services = null; + } @JsonCreator public GetHostResponse( - @JsonProperty(FIELD_NAME_HOSTNAME) final String hostname, - @JsonProperty(FIELD_NAME_STATE) final String state) { + @JsonProperty(FIELD_NAME_HOSTNAME) String hostname, + @JsonProperty(FIELD_NAME_STATE) String state, + @JsonProperty(FIELD_NAME_APPLICATION_URL) String applicationUrl, + @JsonProperty(FIELD_NAME_SERVICES) List<HostService> services) { this.hostname = hostname; this.state = state; + this.applicationUrl = applicationUrl; + this.services = services; } @JsonProperty(FIELD_NAME_HOSTNAME) @@ -35,21 +56,29 @@ public class GetHostResponse { return state; } - @Override - public boolean equals(final Object o) { - if (!(o instanceof GetHostResponse)) { - return false; - } + @JsonProperty(FIELD_NAME_APPLICATION_URL) + public String applicationUrl() { + return applicationUrl; + } - final GetHostResponse other = (GetHostResponse) o; - if (!Objects.equals(this.hostname, other.hostname)) return false; - if (!Objects.equals(this.state, other.state)) return false; + @JsonProperty(FIELD_NAME_SERVICES) + public List<HostService> services() { + return services; + } - return true; + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GetHostResponse that = (GetHostResponse) o; + return Objects.equals(hostname, that.hostname) && + Objects.equals(state, that.state) && + Objects.equals(applicationUrl, that.applicationUrl) && + Objects.equals(services, that.services); } @Override public int hashCode() { - return Objects.hash(hostname, state); + return Objects.hash(hostname, state, applicationUrl, services); } } diff --git a/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/HostService.java b/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/HostService.java new file mode 100644 index 00000000000..70cc9187dd1 --- /dev/null +++ b/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/HostService.java @@ -0,0 +1,52 @@ +// 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.restapi.wire; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class HostService { + @JsonProperty("clusterId") + public final String clusterId; + + @JsonProperty("serviceType") + public final String serviceType; + + @JsonProperty("configId") + public final String configId; + + @JsonProperty("serviceStatus") + public final String serviceStatus; + + @JsonCreator + public HostService(@JsonProperty("clusterId") String clusterId, + @JsonProperty("serviceType") String serviceType, + @JsonProperty("configId") String configId, + @JsonProperty("serviceStatus") String serviceStatus) { + this.clusterId = clusterId; + this.serviceType = serviceType; + this.configId = configId; + this.serviceStatus = serviceStatus; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + HostService that = (HostService) o; + return Objects.equals(clusterId, that.clusterId) && + Objects.equals(serviceType, that.serviceType) && + Objects.equals(configId, that.configId) && + Objects.equals(serviceStatus, that.serviceStatus); + } + + @Override + public int hashCode() { + return Objects.hash(clusterId, serviceType, configId, serviceStatus); + } +} 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()))) { diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ConfigServerApplication.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ConfigServerApplication.java index 1a48ba870fb..7a76c072076 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ConfigServerApplication.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ConfigServerApplication.java @@ -48,6 +48,12 @@ public class ConfigServerApplication { APPLICATION_INSTANCE_ID, serviceClusters); + // Fill back-references + serviceCluster.setApplicationInstance(applicationInstance); + for (ServiceInstance serviceInstance : serviceCluster.serviceInstances()) { + serviceInstance.setServiceCluster(serviceCluster); + } + return applicationInstance; } } diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ModelGenerator.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ModelGenerator.java index d9f019ade63..9716846dea4 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ModelGenerator.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ModelGenerator.java @@ -101,6 +101,14 @@ public class ModelGenerator { toApplicationInstanceId(applicationInfo, zone), serviceClusters); + // Fill back-references + for (ServiceCluster serviceCluster : applicationInstance.serviceClusters()) { + serviceCluster.setApplicationInstance(applicationInstance); + for (ServiceInstance serviceInstance : serviceCluster.serviceInstances()) { + serviceInstance.setServiceCluster(serviceCluster); + } + } + return applicationInstance; } |