diff options
author | Håkon Hallingstad <hakon@oath.com> | 2018-02-26 16:59:57 +0100 |
---|---|---|
committer | Håkon Hallingstad <hakon@oath.com> | 2018-02-26 16:59:57 +0100 |
commit | 1921322a0b816a3a58a566848384dccb72ffd16f (patch) | |
tree | f63181b36468e61358b0285c4827eaa09fb56651 | |
parent | 92258b807a6ec3ce6a6ac1b728a47d437f071c17 (diff) |
Support reporting UP for node admin outside zone app
If the nodeAdminInContainer ConfigserverConfig has been set, with this PR, the
service monitor will always report the node admin container service as UP,
thereby avoiding issues related to standalone node admin seemingly being down
when not running as part of the application.
This postpones checking /status/v1/health for later.
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 |