diff options
17 files changed, 320 insertions, 62 deletions
diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ClusterId.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ClusterId.java index da5ea7f975d..7648432dc11 100644 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ClusterId.java +++ b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ClusterId.java @@ -9,6 +9,10 @@ import java.util.Objects; * @author bjorncs */ public class ClusterId { + // Common cluster IDs + public static final ClusterId ADMIN = new ClusterId("admin"); + public static final ClusterId NODE_ADMIN = new ClusterId("node-admin"); + public static final ClusterId ROUTING = new ClusterId("routing"); private final String id; diff --git a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceType.java b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceType.java index 784ff9d1e38..0054264d42f 100644 --- a/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceType.java +++ b/application-model/src/main/java/com/yahoo/vespa/applicationmodel/ServiceType.java @@ -9,6 +9,9 @@ import java.util.Objects; * @author bjorncs */ public class ServiceType { + // Common service types. + public static final ServiceType CONTAINER = new ServiceType("container"); + public static final ServiceType SLOBROK = new ServiceType("slobrok"); private final String id; diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/InstanceResource.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/InstanceResource.java index c16256df73d..7f0227df4c5 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/InstanceResource.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/InstanceResource.java @@ -6,6 +6,7 @@ import com.yahoo.container.jaxrs.annotation.Component; import com.yahoo.jrt.slobrok.api.Mirror; import com.yahoo.vespa.applicationmodel.ApplicationInstance; 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.ServiceStatus; @@ -15,7 +16,7 @@ import com.yahoo.vespa.orchestrator.OrchestratorUtil; import com.yahoo.vespa.orchestrator.restapi.wire.SlobrokEntryResponse; import com.yahoo.vespa.orchestrator.status.HostStatus; import com.yahoo.vespa.orchestrator.status.StatusService; -import com.yahoo.vespa.service.monitor.SlobrokMonitorManager; +import com.yahoo.vespa.service.monitor.SlobrokApi; import javax.inject.Inject; import javax.ws.rs.GET; @@ -48,16 +49,16 @@ public class InstanceResource { public static final String DEFAULT_SLOBROK_PATTERN = "**"; private final StatusService statusService; - private final SlobrokMonitorManager slobrokMonitorManager; + private final SlobrokApi slobrokApi; private final InstanceLookupService instanceLookupService; @Inject public InstanceResource(@Component InstanceLookupService instanceLookupService, @Component StatusService statusService, - @Component SlobrokMonitorManager slobrokMonitorManager) { + @Component SlobrokApi slobrokApi) { this.instanceLookupService = instanceLookupService; this.statusService = statusService; - this.slobrokMonitorManager = slobrokMonitorManager; + this.slobrokApi = slobrokApi; } @GET @@ -96,7 +97,7 @@ public class InstanceResource { pattern = DEFAULT_SLOBROK_PATTERN; } - List<Mirror.Entry> entries = slobrokMonitorManager.lookup(applicationId, pattern); + List<Mirror.Entry> entries = slobrokApi.lookup(applicationId, pattern); return entries.stream() .map(entry -> new SlobrokEntryResponse(entry.getName(), entry.getSpec())) .collect(Collectors.toList()); @@ -107,11 +108,16 @@ public class InstanceResource { @Produces(MediaType.APPLICATION_JSON) public ServiceStatus getServiceStatus( @PathParam("instanceId") String instanceId, + @QueryParam("clusterId") String clusterIdString, @QueryParam("serviceType") String serviceTypeString, @QueryParam("configId") String configIdString) { ApplicationInstanceReference reference = parseInstanceId(instanceId); ApplicationId applicationId = OrchestratorUtil.toApplicationId(reference); + if (clusterIdString == null) { + throwBadRequest("Missing clusterId query parameter"); + } + if (serviceTypeString == null) { throwBadRequest("Missing serviceType query parameter"); } @@ -120,10 +126,11 @@ public class InstanceResource { throwBadRequest("Missing configId query parameter"); } + ClusterId clusterId = new ClusterId(clusterIdString); ServiceType serviceType = new ServiceType(serviceTypeString); ConfigId configId = new ConfigId(configIdString); - return slobrokMonitorManager.getStatus(applicationId, serviceType, configId); + return slobrokApi.getStatus(applicationId, clusterId, serviceType, configId); } static ApplicationInstanceReference parseInstanceId(String instanceIdString) { diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/InstanceResourceTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/InstanceResourceTest.java index 42b5b70ab55..d7255327ba6 100644 --- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/InstanceResourceTest.java +++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/InstanceResourceTest.java @@ -4,11 +4,12 @@ package com.yahoo.vespa.orchestrator.resources; import com.fasterxml.jackson.databind.ObjectMapper; import com.yahoo.config.provision.ApplicationId; import com.yahoo.jrt.slobrok.api.Mirror; +import com.yahoo.vespa.applicationmodel.ClusterId; import com.yahoo.vespa.applicationmodel.ConfigId; import com.yahoo.vespa.applicationmodel.ServiceStatus; import com.yahoo.vespa.applicationmodel.ServiceType; import com.yahoo.vespa.orchestrator.restapi.wire.SlobrokEntryResponse; -import com.yahoo.vespa.service.monitor.SlobrokMonitorManager; +import com.yahoo.vespa.service.monitor.SlobrokApi; import org.junit.Test; import javax.ws.rs.WebApplicationException; @@ -27,12 +28,13 @@ public class InstanceResourceTest { private static final List<Mirror.Entry> ENTRIES = Arrays.asList( new Mirror.Entry("name1", "spec1"), new Mirror.Entry("name2", "spec2")); + private static final ClusterId CLUSTER_ID = new ClusterId("cluster-id"); - private final SlobrokMonitorManager slobrokMonitorManager = mock(SlobrokMonitorManager.class); + private final SlobrokApi slobrokApi = mock(SlobrokApi.class); private final InstanceResource resource = new InstanceResource( null, null, - slobrokMonitorManager); + slobrokApi); @Test public void testGetSlobrokEntries() throws Exception { @@ -49,31 +51,32 @@ public class InstanceResourceTest { ServiceType serviceType = new ServiceType("serviceType"); ConfigId configId = new ConfigId("configId"); ServiceStatus serviceStatus = ServiceStatus.UP; - when(slobrokMonitorManager.getStatus(APPLICATION_ID, serviceType, configId)) + when(slobrokApi.getStatus(APPLICATION_ID, CLUSTER_ID, serviceType, configId)) .thenReturn(serviceStatus); ServiceStatus actualServiceStatus = resource.getServiceStatus( APPLICATION_INSTANCE_REFERENCE, + CLUSTER_ID.s(), serviceType.s(), configId.s()); - verify(slobrokMonitorManager).getStatus(APPLICATION_ID, serviceType, configId); + verify(slobrokApi).getStatus(APPLICATION_ID, CLUSTER_ID, serviceType, configId); assertEquals(serviceStatus, actualServiceStatus); } @Test(expected = WebApplicationException.class) public void testBadRequest() { - resource.getServiceStatus(APPLICATION_INSTANCE_REFERENCE, null, null); + resource.getServiceStatus(APPLICATION_INSTANCE_REFERENCE, CLUSTER_ID.s(), null, null); } private void testGetSlobrokEntriesWith(String pattern, String expectedLookupPattern) throws Exception{ - when(slobrokMonitorManager.lookup(APPLICATION_ID, expectedLookupPattern)) + when(slobrokApi.lookup(APPLICATION_ID, expectedLookupPattern)) .thenReturn(ENTRIES); List<SlobrokEntryResponse> response = resource.getSlobrokEntries( APPLICATION_INSTANCE_REFERENCE, pattern); - verify(slobrokMonitorManager).lookup(APPLICATION_ID, expectedLookupPattern); + verify(slobrokApi).lookup(APPLICATION_ID, expectedLookupPattern); ObjectMapper mapper = new ObjectMapper(); String actualJson = mapper.writeValueAsString(response); diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceStatusProvider.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceStatusProvider.java new file mode 100644 index 00000000000..35003313775 --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceStatusProvider.java @@ -0,0 +1,19 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor;// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.vespa.applicationmodel.ClusterId; +import com.yahoo.vespa.applicationmodel.ConfigId; +import com.yahoo.vespa.applicationmodel.ServiceStatus; +import com.yahoo.vespa.applicationmodel.ServiceType; + +/** + * @author hakon + */ +public interface ServiceStatusProvider { + /** Get the {@link ServiceStatus} of a particular service. */ + ServiceStatus getStatus(ApplicationId applicationId, + ClusterId clusterId, + ServiceType serviceType, + ConfigId configId); +} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManager.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokApi.java index 9cffa1192be..dff605b888d 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManager.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokApi.java @@ -3,23 +3,13 @@ package com.yahoo.vespa.service.monitor; import com.yahoo.config.provision.ApplicationId; import com.yahoo.jrt.slobrok.api.Mirror; -import com.yahoo.vespa.applicationmodel.ConfigId; -import com.yahoo.vespa.applicationmodel.ServiceStatus; -import com.yahoo.vespa.applicationmodel.ServiceType; import java.util.List; -public interface SlobrokMonitorManager { +public interface SlobrokApi extends ServiceStatusProvider { /** * Get all Slobrok entries that has a name matching pattern as described in * Mirror::lookup. */ List<Mirror.Entry> lookup(ApplicationId application, String pattern); - - /** - * Query the ServiceMonitorStatus of a particular service. - */ - ServiceStatus getStatus(ApplicationId applicationId, - ServiceType serviceType, - ConfigId configId); } diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/HealthMonitorManager.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/HealthMonitorManager.java new file mode 100644 index 00000000000..160a49594b8 --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/HealthMonitorManager.java @@ -0,0 +1,37 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor.internal; + +import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.model.api.SuperModel; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.vespa.applicationmodel.ClusterId; +import com.yahoo.vespa.applicationmodel.ConfigId; +import com.yahoo.vespa.applicationmodel.ServiceStatus; +import com.yahoo.vespa.applicationmodel.ServiceType; + +/** + * @author hakon + */ +public class HealthMonitorManager implements MonitorManager { + HealthMonitorManager() {} + + @Override + public void applicationActivated(SuperModel superModel, ApplicationInfo application) { + } + + @Override + public void applicationRemoved(SuperModel superModel, ApplicationId id) { + } + + @Override + public ServiceStatus getStatus(ApplicationId applicationId, ClusterId clusterId, ServiceType serviceType, ConfigId configId) { + // TODO: Do proper health check + if (ZoneApplication.isNodeAdminService(applicationId, clusterId, serviceType)) { + return ServiceStatus.UP; + } + + throw new IllegalArgumentException("Health monitoring not implemented for application " + + applicationId.toShortString() + ", cluster " + clusterId.s() + ", serviceType " + + serviceType); + } +} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ModelGenerator.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ModelGenerator.java index 961d5701901..ca70b18439b 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ModelGenerator.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ModelGenerator.java @@ -20,7 +20,7 @@ import com.yahoo.vespa.applicationmodel.ServiceStatus; import com.yahoo.vespa.applicationmodel.ServiceType; import com.yahoo.vespa.applicationmodel.TenantId; import com.yahoo.vespa.service.monitor.ServiceModel; -import com.yahoo.vespa.service.monitor.SlobrokMonitorManager; +import com.yahoo.vespa.service.monitor.ServiceStatusProvider; import java.util.HashMap; import java.util.HashSet; @@ -44,7 +44,7 @@ public class ModelGenerator { SuperModel superModel, Zone zone, List<String> configServerHosts, - SlobrokMonitorManager slobrokMonitorManager) { + ServiceStatusProvider serviceStatusProvider) { Map<ApplicationInstanceReference, ApplicationInstance> applicationInstances = new HashMap<>(); for (ApplicationInfo applicationInfo : superModel.getAllApplicationInfos()) { @@ -52,7 +52,7 @@ public class ModelGenerator { ApplicationInstance applicationInstance = toApplicationInstance( applicationInfo, zone, - slobrokMonitorManager); + serviceStatusProvider); applicationInstances.put(applicationInstance.reference(), applicationInstance); } @@ -70,7 +70,7 @@ public class ModelGenerator { ApplicationInstance toApplicationInstance( ApplicationInfo applicationInfo, Zone zone, - SlobrokMonitorManager slobrokMonitorManager) { + ServiceStatusProvider serviceStatusProvider) { Map<ServiceClusterKey, Set<ServiceInstance>> groupedServiceInstances = new HashMap<>(); for (HostInfo host : applicationInfo.getModel().getHosts()) { @@ -80,9 +80,10 @@ public class ModelGenerator { ServiceInstance serviceInstance = toServiceInstance( applicationInfo.getApplicationId(), + serviceClusterKey.clusterId(), serviceInfo, hostName, - slobrokMonitorManager); + serviceStatusProvider); if (!groupedServiceInstances.containsKey(serviceClusterKey)) { groupedServiceInstances.put(serviceClusterKey, new HashSet<>()); @@ -114,28 +115,33 @@ public class ModelGenerator { return applicationInstance; } - ServiceClusterKey toServiceClusterKey(ServiceInfo serviceInfo) { - ClusterId clusterId = new ClusterId(serviceInfo.getProperty(CLUSTER_ID_PROPERTY_NAME).orElse("")); + static ClusterId getClusterId(ServiceInfo serviceInfo) { + return new ClusterId(serviceInfo.getProperty(CLUSTER_ID_PROPERTY_NAME).orElse("")); + } + + private ServiceClusterKey toServiceClusterKey(ServiceInfo serviceInfo) { + ClusterId clusterId = getClusterId(serviceInfo); ServiceType serviceType = toServiceType(serviceInfo); return new ServiceClusterKey(clusterId, serviceType); } - ServiceInstance toServiceInstance( + private ServiceInstance toServiceInstance( ApplicationId applicationId, + ClusterId clusterId, ServiceInfo serviceInfo, HostName hostName, - SlobrokMonitorManager slobrokMonitorManager) { + ServiceStatusProvider serviceStatusProvider) { ConfigId configId = new ConfigId(serviceInfo.getConfigId()); - ServiceStatus status = slobrokMonitorManager.getStatus( + ServiceStatus status = serviceStatusProvider.getStatus( applicationId, - toServiceType(serviceInfo), - configId); + clusterId, + toServiceType(serviceInfo), configId); return new ServiceInstance(configId, hostName, status); } - ApplicationInstanceId toApplicationInstanceId(ApplicationInfo applicationInfo, Zone zone) { + private ApplicationInstanceId toApplicationInstanceId(ApplicationInfo applicationInfo, Zone zone) { return new ApplicationInstanceId(String.format("%s:%s:%s:%s", applicationInfo.getApplicationId().application().value(), zone.environment().value(), @@ -143,7 +149,7 @@ public class ModelGenerator { applicationInfo.getApplicationId().instance().value())); } - ServiceType toServiceType(ServiceInfo serviceInfo) { + private ServiceType toServiceType(ServiceInfo serviceInfo) { return new ServiceType(serviceInfo.getServiceType()); } } diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/MonitorManager.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/MonitorManager.java new file mode 100644 index 00000000000..49863672c43 --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/MonitorManager.java @@ -0,0 +1,11 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor.internal;// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +import com.yahoo.config.model.api.SuperModelListener; +import com.yahoo.vespa.service.monitor.ServiceStatusProvider; + +/** + * @author hakon + */ +public interface MonitorManager extends SuperModelListener, ServiceStatusProvider { +} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ServiceMonitorImpl.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ServiceMonitorImpl.java index 282a0797912..b2b6538fe6c 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ServiceMonitorImpl.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ServiceMonitorImpl.java @@ -15,42 +15,41 @@ import com.yahoo.vespa.service.monitor.ServiceMonitor; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.logging.Logger; import java.util.stream.Collectors; public class ServiceMonitorImpl implements ServiceMonitor { - private static final Logger logger = Logger.getLogger(ServiceMonitorImpl.class.getName()); - - private final Zone zone; - private final List<String> configServerHosts; private final ServiceModelCache serviceModelCache; @Inject public ServiceMonitorImpl(SuperModelProvider superModelProvider, ConfigserverConfig configserverConfig, SlobrokMonitorManagerImpl slobrokMonitorManager, + HealthMonitorManager healthMonitorManager, Metric metric, Timer timer) { - this.zone = superModelProvider.getZone(); - this.configServerHosts = toConfigServerList(configserverConfig); + Zone zone = superModelProvider.getZone(); + List<String> configServerHosts = toConfigServerList(configserverConfig); ServiceMonitorMetrics metrics = new ServiceMonitorMetrics(metric, timer); - SuperModelListenerImpl superModelListener = new SuperModelListenerImpl( + UnionMonitorManager monitorManager = new UnionMonitorManager( slobrokMonitorManager, + healthMonitorManager, + configserverConfig); + + SuperModelListenerImpl superModelListener = new SuperModelListenerImpl( + monitorManager, metrics, new ModelGenerator(), zone, configServerHosts); superModelListener.start(superModelProvider); - serviceModelCache = new ServiceModelCache( - () -> superModelListener.get(), - timer); + serviceModelCache = new ServiceModelCache(superModelListener, timer); } private List<String> toConfigServerList(ConfigserverConfig configserverConfig) { if (configserverConfig.multitenant()) { return configserverConfig.zookeeperserver().stream() - .map(server -> server.hostname()) + .map(ConfigserverConfig.Zookeeperserver::hostname) .collect(Collectors.toList()); } diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImpl.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImpl.java index 801f4b05079..b96364bf95e 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImpl.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImpl.java @@ -8,10 +8,11 @@ import com.yahoo.config.model.api.SuperModelListener; import com.yahoo.config.provision.ApplicationId; import com.yahoo.jrt.slobrok.api.Mirror; import com.yahoo.log.LogLevel; +import com.yahoo.vespa.applicationmodel.ClusterId; import com.yahoo.vespa.applicationmodel.ConfigId; import com.yahoo.vespa.applicationmodel.ServiceStatus; import com.yahoo.vespa.applicationmodel.ServiceType; -import com.yahoo.vespa.service.monitor.SlobrokMonitorManager; +import com.yahoo.vespa.service.monitor.SlobrokApi; import java.util.HashMap; import java.util.List; @@ -19,7 +20,7 @@ import java.util.Optional; import java.util.function.Supplier; import java.util.logging.Logger; -public class SlobrokMonitorManagerImpl implements SuperModelListener, SlobrokMonitorManager { +public class SlobrokMonitorManagerImpl implements SuperModelListener, SlobrokApi, MonitorManager { private static final Logger logger = Logger.getLogger(SlobrokMonitorManagerImpl.class.getName()); @@ -30,7 +31,7 @@ public class SlobrokMonitorManagerImpl implements SuperModelListener, SlobrokMon @Inject public SlobrokMonitorManagerImpl() { - this(() -> new SlobrokMonitor()); + this(SlobrokMonitor::new); } SlobrokMonitorManagerImpl(Supplier<SlobrokMonitor> slobrokMonitorFactory) { @@ -74,7 +75,7 @@ public class SlobrokMonitorManagerImpl implements SuperModelListener, SlobrokMon @Override public ServiceStatus getStatus(ApplicationId applicationId, - ServiceType serviceType, + ClusterId clusterId, ServiceType serviceType, ConfigId configId) { Optional<String> slobrokServiceName = findSlobrokServiceName(serviceType, configId); if (slobrokServiceName.isPresent()) { diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImpl.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImpl.java index 82d55cd05d7..5e309d3c18d 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImpl.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImpl.java @@ -24,10 +24,10 @@ public class SuperModelListenerImpl implements SuperModelListener, Supplier<Serv // superModel and slobrokMonitorManager are always updated together // and atomically using this monitor. private final Object monitor = new Object(); - private final SlobrokMonitorManagerImpl slobrokMonitorManager; + private final MonitorManager slobrokMonitorManager; private SuperModel superModel; - SuperModelListenerImpl(SlobrokMonitorManagerImpl slobrokMonitorManager, + SuperModelListenerImpl(MonitorManager slobrokMonitorManager, ServiceMonitorMetrics metrics, ModelGenerator modelGenerator, Zone zone, diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/UnionMonitorManager.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/UnionMonitorManager.java new file mode 100644 index 00000000000..0bb4dea5a94 --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/UnionMonitorManager.java @@ -0,0 +1,57 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor.internal; + +import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.model.api.SuperModel; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.vespa.applicationmodel.ClusterId; +import com.yahoo.vespa.applicationmodel.ConfigId; +import com.yahoo.vespa.applicationmodel.ServiceStatus; +import com.yahoo.vespa.applicationmodel.ServiceType; + +/** + * @author hakon + */ +public class UnionMonitorManager implements MonitorManager { + private final SlobrokMonitorManagerImpl slobrokMonitorManager; + private final HealthMonitorManager healthMonitorManager; + private final ConfigserverConfig configserverConfig; + + UnionMonitorManager(SlobrokMonitorManagerImpl slobrokMonitorManager, + HealthMonitorManager healthMonitorManager, + ConfigserverConfig configserverConfig) { + this.slobrokMonitorManager = slobrokMonitorManager; + this.healthMonitorManager = healthMonitorManager; + this.configserverConfig = configserverConfig; + } + + @Override + public ServiceStatus getStatus(ApplicationId applicationId, + ClusterId clusterId, + ServiceType serviceType, + ConfigId configId) { + MonitorManager monitorManager = useHealth(applicationId, clusterId, serviceType) ? + healthMonitorManager : + slobrokMonitorManager; + + return monitorManager.getStatus(applicationId, clusterId, serviceType, configId); + } + + @Override + public void applicationActivated(SuperModel superModel, ApplicationInfo application) { + slobrokMonitorManager.applicationActivated(superModel, application); + healthMonitorManager.applicationActivated(superModel, application); + } + + @Override + public void applicationRemoved(SuperModel superModel, ApplicationId id) { + slobrokMonitorManager.applicationRemoved(superModel, id); + healthMonitorManager.applicationRemoved(superModel, id); + } + + private boolean useHealth(ApplicationId applicationId, ClusterId clusterId, ServiceType serviceType) { + return !configserverConfig.nodeAdminInContainer() && + ZoneApplication.isNodeAdminService(applicationId, clusterId, serviceType); + } +} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ZoneApplication.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ZoneApplication.java new file mode 100644 index 00000000000..f7097e867df --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ZoneApplication.java @@ -0,0 +1,26 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor.internal; + +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.vespa.applicationmodel.ClusterId; +import com.yahoo.vespa.applicationmodel.ServiceType; + +import java.util.Objects; + +/** + * @author hakon + */ +public class ZoneApplication { + private ZoneApplication() {} + + static final ApplicationId ZONE_APPLICATION_ID = + ApplicationId.from("hosted-vespa", "routing", "default"); + + static boolean isNodeAdminService(ApplicationId applicationId, + ClusterId clusterId, + ServiceType serviceType) { + return Objects.equals(applicationId, ZONE_APPLICATION_ID) && + Objects.equals(serviceType, ServiceType.CONTAINER) && + Objects.equals(clusterId, ClusterId.NODE_ADMIN); + } +} diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ModelGeneratorTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ModelGeneratorTest.java index cf07c39950c..1348c04a7e5 100644 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ModelGeneratorTest.java +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ModelGeneratorTest.java @@ -44,7 +44,7 @@ public class ModelGeneratorTest { .collect(Collectors.toList()); SlobrokMonitorManagerImpl slobrokMonitorManager = mock(SlobrokMonitorManagerImpl.class); - when(slobrokMonitorManager.getStatus(any(), any(), any())) + when(slobrokMonitorManager.getStatus(any(), any(), any(), any())) .thenReturn(ServiceStatus.UP); ServiceModel serviceModel = @@ -88,7 +88,7 @@ public class ModelGeneratorTest { List<String> configServerHosts = Collections.emptyList(); SlobrokMonitorManagerImpl slobrokMonitorManager = mock(SlobrokMonitorManagerImpl.class); - when(slobrokMonitorManager.getStatus(any(), any(), any())) + when(slobrokMonitorManager.getStatus(any(), any(), any(), any())) .thenReturn(ServiceStatus.UP); ServiceModel serviceModel = diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImplImplTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImplTest.java index 79f927f6161..ab50b3192e3 100644 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImplImplTest.java +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImplTest.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.service.monitor.internal; import com.yahoo.config.model.api.ApplicationInfo; import com.yahoo.config.model.api.SuperModel; +import com.yahoo.vespa.applicationmodel.ClusterId; import com.yahoo.vespa.applicationmodel.ConfigId; import com.yahoo.vespa.applicationmodel.ServiceStatus; import com.yahoo.vespa.applicationmodel.ServiceType; @@ -19,7 +20,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -public class SlobrokMonitorManagerImplImplTest { +public class SlobrokMonitorManagerImplTest { // IntelliJ complains if parametrized type is specified, Maven complains if not specified. @SuppressWarnings("unchecked") private final Supplier<SlobrokMonitor> slobrokMonitorFactory = mock(Supplier.class); @@ -29,6 +30,7 @@ public class SlobrokMonitorManagerImplImplTest { private final SlobrokMonitor slobrokMonitor = mock(SlobrokMonitor.class); private final SuperModel superModel = mock(SuperModel.class); private final ApplicationInfo application = mock(ApplicationInfo.class); + private final ClusterId clusterId = new ClusterId("cluster-id"); @Before public void setup() { @@ -70,8 +72,8 @@ public class SlobrokMonitorManagerImplImplTest { private ServiceStatus getStatus(String serviceType) { return slobrokMonitorManager.getStatus( application.getApplicationId(), - new ServiceType(serviceType), - new ConfigId("config.id")); + clusterId, + new ServiceType(serviceType), new ConfigId("config.id")); } @Test diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/UnionMonitorManagerTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/UnionMonitorManagerTest.java new file mode 100644 index 00000000000..2597ebe65d3 --- /dev/null +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/UnionMonitorManagerTest.java @@ -0,0 +1,93 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor.internal; + +import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.vespa.applicationmodel.ClusterId; +import com.yahoo.vespa.applicationmodel.ConfigId; +import com.yahoo.vespa.applicationmodel.ServiceType; +import org.junit.Test; + +import static com.yahoo.vespa.applicationmodel.ClusterId.NODE_ADMIN; +import static com.yahoo.vespa.applicationmodel.ServiceType.CONTAINER; +import static com.yahoo.vespa.service.monitor.internal.ZoneApplication.ZONE_APPLICATION_ID; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class UnionMonitorManagerTest { + @Test + public void nodeAdminInContainer() { + testWith( + true, + ZONE_APPLICATION_ID, + NODE_ADMIN, + CONTAINER, + 1, + 0); + } + + @Test + public void nodeAdminOutsideContainer() { + boolean inContainer = false; + + // When nodeAdminInContainer is set, then only the node admin cluster should use health + testWith( + inContainer, + ZONE_APPLICATION_ID, + NODE_ADMIN, + CONTAINER, + 0, + 1); + + testWith( + inContainer, + ApplicationId.fromSerializedForm("a:b:default"), + NODE_ADMIN, + CONTAINER, + 1, + 0); + + testWith( + inContainer, + ZONE_APPLICATION_ID, + new ClusterId("foo"), + CONTAINER, + 1, + 0); + + testWith( + inContainer, + ZONE_APPLICATION_ID, + NODE_ADMIN, + new ServiceType("foo"), + 1, + 0); + } + + private void testWith(boolean nodeAdminInContainer, + ApplicationId applicationId, + ClusterId clusterId, + ServiceType serviceType, + int expectedSlobrokCalls, + int expectedHealthCalls) { + SlobrokMonitorManagerImpl slobrokMonitorManager = mock(SlobrokMonitorManagerImpl.class); + HealthMonitorManager healthMonitorManager = mock(HealthMonitorManager.class); + + ConfigserverConfig.Builder builder = new ConfigserverConfig.Builder(); + builder.nodeAdminInContainer(nodeAdminInContainer); + ConfigserverConfig config = new ConfigserverConfig(builder); + + + UnionMonitorManager manager = new UnionMonitorManager( + slobrokMonitorManager, + healthMonitorManager, + config); + + manager.getStatus(applicationId, clusterId, serviceType, new ConfigId("config-id")); + + verify(slobrokMonitorManager, times(expectedSlobrokCalls)).getStatus(any(), any(), any(), any()); + verify(healthMonitorManager, times(expectedHealthCalls)).getStatus(any(), any(), any(), any()); + } +}
\ No newline at end of file |