diff options
2 files changed, 85 insertions, 0 deletions
diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/model/ApplicationInstanceGenerator.java b/service-monitor/src/main/java/com/yahoo/vespa/service/model/ApplicationInstanceGenerator.java index 0a4e8e75adf..e535aff8b46 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/model/ApplicationInstanceGenerator.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/model/ApplicationInstanceGenerator.java @@ -4,6 +4,7 @@ package com.yahoo.vespa.service.model; import com.yahoo.config.model.api.ApplicationInfo; import com.yahoo.config.model.api.HostInfo; import com.yahoo.config.model.api.ServiceInfo; +import com.yahoo.config.model.api.container.ContainerServiceType; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Zone; import com.yahoo.vespa.applicationmodel.ApplicationInstance; @@ -18,6 +19,7 @@ import com.yahoo.vespa.applicationmodel.ServiceStatusInfo; import com.yahoo.vespa.applicationmodel.ServiceType; import com.yahoo.vespa.applicationmodel.TenantId; import com.yahoo.vespa.service.duper.ConfigServerApplication; +import com.yahoo.vespa.service.duper.ZoneApplication; import com.yahoo.vespa.service.monitor.ServiceId; import com.yahoo.vespa.service.monitor.ServiceStatusProvider; @@ -53,8 +55,21 @@ public class ApplicationInstanceGenerator { for (HostInfo host : applicationInfo.getModel().getHosts()) { HostName hostName = new HostName(host.getHostname()); + + boolean isTenantHost = + applicationInfo.getApplicationId().equals(ZoneApplication.getApplicationId()) && + host.getServices().stream().anyMatch(serviceInfo -> + ZoneApplication.isNodeAdminServiceInfo(applicationInfo.getApplicationId(), serviceInfo)); + for (ServiceInfo serviceInfo : host.getServices()) { ServiceClusterKey serviceClusterKey = toServiceClusterKey(serviceInfo); + + if (isTenantHost && !ZoneApplication.isNodeAdminServiceInfo(applicationInfo.getApplicationId(), serviceInfo)) { + // A tenant host only runs the host-admin service, even though the model contains a bunch of + // standard services like config-sentinel and metrics proxy. + continue; + } + ServiceInstance serviceInstance = toServiceInstance( applicationInfo.getApplicationId(), diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/model/ApplicationInstanceGeneratorTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/model/ApplicationInstanceGeneratorTest.java index 7eba54977cc..e182c9d6468 100644 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/model/ApplicationInstanceGeneratorTest.java +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/model/ApplicationInstanceGeneratorTest.java @@ -2,20 +2,32 @@ package com.yahoo.vespa.service.model; import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.model.api.HostInfo; +import com.yahoo.config.model.api.Model; +import com.yahoo.config.model.api.ServiceInfo; +import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.HostName; +import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.Zone; import com.yahoo.vespa.applicationmodel.ApplicationInstance; +import com.yahoo.vespa.applicationmodel.ClusterId; +import com.yahoo.vespa.applicationmodel.ServiceCluster; import com.yahoo.vespa.applicationmodel.ServiceStatus; import com.yahoo.vespa.applicationmodel.ServiceStatusInfo; import com.yahoo.vespa.service.duper.ConfigServerApplication; +import com.yahoo.vespa.service.duper.ZoneApplication; import com.yahoo.vespa.service.monitor.ServiceStatusProvider; import org.junit.Test; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; @@ -73,4 +85,62 @@ public class ApplicationInstanceGeneratorTest { .toString())); } + @Test + public void verifyOnlyNodeAdminServiceIsLeft() { + when(statusProvider.getStatus(any(), any(), any(), any())).thenReturn(new ServiceStatusInfo(ServiceStatus.NOT_CHECKED)); + + String host1 = "host1"; + String host2 = "host2"; + + List<ServiceInfo> serviceInfos1 = List.of( + makeServiceInfo("metrics", "metricsproxy-container", host1) + ); + + List<ServiceInfo> serviceInfos2 = List.of( + makeServiceInfo("metrics", "metricsproxy-container", host2), + makeServiceInfo(ZoneApplication.getNodeAdminClusterId().s(), + ZoneApplication.getNodeAdminServiceType().s(), host2) + ); + + List<HostInfo> hostInfos = List.of( + new HostInfo(host1, serviceInfos1), + new HostInfo(host2, serviceInfos2) + ); + + Model model = mock(Model.class); + when(model.getHosts()).thenReturn(hostInfos); + + ApplicationInfo applicationInfo = new ApplicationInfo(ZoneApplication.getApplicationId(), 0, model); + + Zone zone = mock(Zone.class); + when(zone.environment()).thenReturn(Environment.prod); + when(zone.region()).thenReturn(RegionName.from("us-east-1")); + + ApplicationInstanceGenerator generator = new ApplicationInstanceGenerator(applicationInfo, zone); + ApplicationInstance applicationInstance = generator.makeApplicationInstance(statusProvider); + + Map<ClusterId, List<ServiceCluster>> serviceClusters = + applicationInstance.serviceClusters().stream().collect(Collectors.groupingBy(ServiceCluster::clusterId)); + assertEquals(2, serviceClusters.size()); + List<ServiceCluster> nodeAdminClusters = serviceClusters.get(ZoneApplication.getNodeAdminClusterId()); + assertNotNull(nodeAdminClusters); + assertEquals(1, nodeAdminClusters.size()); + ServiceCluster nodeAdminCluster = nodeAdminClusters.iterator().next(); + assertEquals(1, nodeAdminCluster.serviceInstances().size()); + assertEquals(host2, nodeAdminCluster.serviceInstances().iterator().next().hostName().s()); + + List<ServiceCluster> metricsClusters = serviceClusters.get(new ClusterId("metrics")); + assertNotNull(metricsClusters); + assertEquals(1, metricsClusters.size()); + ServiceCluster metricsCluster = metricsClusters.iterator().next(); + + // The metrics service on the node admin host is ignored + assertEquals(1, metricsCluster.serviceInstances().size()); + assertEquals(host1, metricsCluster.serviceInstances().iterator().next().hostName().s()); + } + + private ServiceInfo makeServiceInfo(String clusterId, String serviceType, String hostname) { + var properties = Map.of(ApplicationInstanceGenerator.CLUSTER_ID_PROPERTY_NAME, clusterId); + return new ServiceInfo("servicename", serviceType, List.of(), properties, "configid", hostname); + } }
\ No newline at end of file |