aboutsummaryrefslogtreecommitdiffstats
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
parent9606e88b7ca082f36eb38b0e197a0513f76ef6eb (diff)
Provide more info in host Orchestrator REST API
-rw-r--r--application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceCluster.java22
-rw-r--r--application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceInstance.java20
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/OrchestratorMock.java6
-rw-r--r--orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/HostApi.java5
-rw-r--r--orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/GetHostResponse.java53
-rw-r--r--orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/HostService.java52
-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
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ConfigServerApplication.java6
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ModelGenerator.java8
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;
}