From f61980c5d253dbc00474374153f86674c98e0549 Mon Sep 17 00:00:00 2001 From: Jon Marius Venstad Date: Fri, 27 Oct 2017 20:22:14 +0200 Subject: Revert "Do not export service monitor internals" --- service-monitor/pom.xml | 6 - .../service/monitor/ConfigServerApplication.java | 59 ++++++++ .../vespa/service/monitor/ModelGenerator.java | 147 ++++++++++++++++++ .../yahoo/vespa/service/monitor/ServiceModel.java | 6 +- .../vespa/service/monitor/ServiceMonitorImpl.java | 69 +++++++++ .../service/monitor/ServiceMonitorProvider.java | 36 ----- .../vespa/service/monitor/SlobrokMonitor.java | 81 ++++++++++ .../service/monitor/SlobrokMonitorManagerImpl.java | 132 +++++++++++++++++ .../monitor/SlobrokMonitorManagerProvider.java | 23 --- .../service/monitor/SuperModelListenerImpl.java | 89 +++++++++++ .../monitor/internal/ConfigServerApplication.java | 59 -------- .../service/monitor/internal/ModelGenerator.java | 149 ------------------- .../monitor/internal/ServiceMonitorImpl.java | 67 --------- .../service/monitor/internal/SlobrokMonitor.java | 81 ---------- .../internal/SlobrokMonitorManagerImpl.java | 131 ---------------- .../monitor/internal/SuperModelListenerImpl.java | 88 ----------- .../monitor/ConfigServerApplicationTest.java | 61 ++++++++ .../yahoo/vespa/service/monitor/ExampleModel.java | 164 +++++++++++++++++++++ .../vespa/service/monitor/ExampleModelTest.java | 93 ++++++++++++ .../vespa/service/monitor/ModelGeneratorTest.java | 139 +++++++++++++++++ .../monitor/SlobrokMonitorManagerImplImplTest.java | 93 ++++++++++++ .../vespa/service/monitor/SlobrokMonitorTest.java | 36 +++++ .../monitor/SuperModelListenerImplTest.java | 52 +++++++ .../internal/ConfigServerApplicationTest.java | 61 -------- .../service/monitor/internal/ExampleModel.java | 164 --------------------- .../service/monitor/internal/ExampleModelTest.java | 93 ------------ .../monitor/internal/ModelGeneratorTest.java | 140 ------------------ .../SlobrokMonitorManagerImplImplTest.java | 93 ------------ .../monitor/internal/SlobrokMonitorTest.java | 36 ----- .../internal/SuperModelListenerImplTest.java | 52 ------- 30 files changed, 1218 insertions(+), 1282 deletions(-) create mode 100644 service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ConfigServerApplication.java create mode 100644 service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ModelGenerator.java create mode 100644 service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceMonitorImpl.java delete mode 100644 service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceMonitorProvider.java create mode 100644 service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitor.java create mode 100644 service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerImpl.java delete mode 100644 service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerProvider.java create mode 100644 service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SuperModelListenerImpl.java delete mode 100644 service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ConfigServerApplication.java delete mode 100644 service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ModelGenerator.java delete mode 100644 service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ServiceMonitorImpl.java delete mode 100644 service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitor.java delete mode 100644 service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImpl.java delete mode 100644 service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImpl.java create mode 100644 service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ConfigServerApplicationTest.java create mode 100644 service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ExampleModel.java create mode 100644 service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ExampleModelTest.java create mode 100644 service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ModelGeneratorTest.java create mode 100644 service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerImplImplTest.java create mode 100644 service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SlobrokMonitorTest.java create mode 100644 service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SuperModelListenerImplTest.java delete mode 100644 service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ConfigServerApplicationTest.java delete mode 100644 service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ExampleModel.java delete mode 100644 service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ExampleModelTest.java delete mode 100644 service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ModelGeneratorTest.java delete mode 100644 service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImplImplTest.java delete mode 100644 service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorTest.java delete mode 100644 service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImplTest.java (limited to 'service-monitor') diff --git a/service-monitor/pom.xml b/service-monitor/pom.xml index 4240a4980ff..c63bdf35574 100644 --- a/service-monitor/pom.xml +++ b/service-monitor/pom.xml @@ -21,12 +21,6 @@ ${project.version} provided - - com.yahoo.vespa - container-di - ${project.version} - provided - com.yahoo.vespa jdisc_core 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 new file mode 100644 index 00000000000..7a76c072076 --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ConfigServerApplication.java @@ -0,0 +1,59 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor; + +import com.yahoo.vespa.applicationmodel.ApplicationInstance; +import com.yahoo.vespa.applicationmodel.ApplicationInstanceId; +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 java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * A service/application model of the config server with health status. + */ +public class ConfigServerApplication { + public static final ClusterId CLUSTER_ID = new ClusterId("zone-config-servers"); + public static final ServiceType SERVICE_TYPE = new ServiceType("configserver"); + public static final TenantId TENANT_ID = new TenantId("hosted-vespa"); + public static final ApplicationInstanceId APPLICATION_INSTANCE_ID = new ApplicationInstanceId("zone-config-servers"); + public static final String CONFIG_ID_PREFIX = "configid."; + + ApplicationInstance toApplicationInstance(List hostnames) { + Set serviceInstances = hostnames.stream() + .map(hostname -> new ServiceInstance( + new ConfigId(CONFIG_ID_PREFIX + hostname), + new HostName(hostname), + ServiceStatus.NOT_CHECKED)) + .collect(Collectors.toSet()); + + ServiceCluster serviceCluster = new ServiceCluster( + CLUSTER_ID, + SERVICE_TYPE, + serviceInstances); + + Set serviceClusters = + Stream.of(serviceCluster).collect(Collectors.toSet()); + + ApplicationInstance applicationInstance = new ApplicationInstance( + TENANT_ID, + 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 new file mode 100644 index 00000000000..9716846dea4 --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ModelGenerator.java @@ -0,0 +1,147 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor; + +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.SuperModel; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.Zone; +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.ServiceClusterKey; +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 java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Util to convert SuperModel to ServiceModel and application model classes + */ +public class ModelGenerator { + public static final String CLUSTER_ID_PROPERTY_NAME = "clustername"; + + /** + * Create service model based primarily on super model. + * + * If the configServerhosts is non-empty, a config server application is added. + */ + ServiceModel toServiceModel( + SuperModel superModel, + Zone zone, + List configServerHosts, + SlobrokMonitorManager slobrokMonitorManager) { + Map applicationInstances = new HashMap<>(); + + for (ApplicationInfo applicationInfo : superModel.getAllApplicationInfos()) { + + ApplicationInstance applicationInstance = toApplicationInstance( + applicationInfo, + zone, + slobrokMonitorManager); + applicationInstances.put(applicationInstance.reference(), applicationInstance); + } + + // The config server is part of the service model (but not super model) + if (!configServerHosts.isEmpty()) { + ConfigServerApplication configServerApplication = new ConfigServerApplication(); + ApplicationInstance configServerApplicationInstance = + configServerApplication.toApplicationInstance(configServerHosts); + applicationInstances.put(configServerApplicationInstance.reference(), configServerApplicationInstance); + } + + return new ServiceModel(applicationInstances); + } + + ApplicationInstance toApplicationInstance( + ApplicationInfo applicationInfo, + Zone zone, + SlobrokMonitorManager slobrokMonitorManager) { + Map> groupedServiceInstances = new HashMap<>(); + + for (HostInfo host : applicationInfo.getModel().getHosts()) { + HostName hostName = new HostName(host.getHostname()); + for (ServiceInfo serviceInfo : host.getServices()) { + ServiceClusterKey serviceClusterKey = toServiceClusterKey(serviceInfo); + ServiceInstance serviceInstance = + toServiceInstance( + applicationInfo.getApplicationId(), + serviceInfo, + hostName, + slobrokMonitorManager); + + if (!groupedServiceInstances.containsKey(serviceClusterKey)) { + groupedServiceInstances.put(serviceClusterKey, new HashSet<>()); + } + groupedServiceInstances.get(serviceClusterKey).add(serviceInstance); + } + } + + Set serviceClusters = groupedServiceInstances.entrySet().stream() + .map(entry -> new ServiceCluster( + entry.getKey().clusterId(), + entry.getKey().serviceType(), + entry.getValue())) + .collect(Collectors.toSet()); + + ApplicationInstance applicationInstance = new ApplicationInstance( + new TenantId(applicationInfo.getApplicationId().tenant().toString()), + 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; + } + + ServiceClusterKey toServiceClusterKey(ServiceInfo serviceInfo) { + ClusterId clusterId = new ClusterId(serviceInfo.getProperty(CLUSTER_ID_PROPERTY_NAME).orElse("")); + ServiceType serviceType = toServiceType(serviceInfo); + return new ServiceClusterKey(clusterId, serviceType); + } + + ServiceInstance toServiceInstance( + ApplicationId applicationId, + ServiceInfo serviceInfo, + HostName hostName, + SlobrokMonitorManager slobrokMonitorManager) { + ConfigId configId = new ConfigId(serviceInfo.getConfigId()); + + ServiceStatus status = slobrokMonitorManager.getStatus( + applicationId, + toServiceType(serviceInfo), + configId); + + return new ServiceInstance(configId, hostName, status); + } + + ApplicationInstanceId toApplicationInstanceId(ApplicationInfo applicationInfo, Zone zone) { + return new ApplicationInstanceId(String.format("%s:%s:%s:%s", + applicationInfo.getApplicationId().application().value(), + zone.environment().value(), + zone.region().value(), + applicationInfo.getApplicationId().instance().value())); + } + + ServiceType toServiceType(ServiceInfo serviceInfo) { + return new ServiceType(serviceInfo.getServiceType()); + } +} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceModel.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceModel.java index 2432abcc2d4..46102a366d2 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceModel.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceModel.java @@ -21,15 +21,15 @@ import java.util.stream.Collectors; public class ServiceModel { private final Map applications; - public ServiceModel(Map applications) { + ServiceModel(Map applications) { this.applications = Collections.unmodifiableMap(applications); } - public Map getAllApplicationInstances() { + Map getAllApplicationInstances() { return applications; } - public Optional getApplicationInstance(ApplicationInstanceReference reference) { + Optional getApplicationInstance(ApplicationInstanceReference reference) { return Optional.ofNullable(applications.get(reference)); } diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceMonitorImpl.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceMonitorImpl.java new file mode 100644 index 00000000000..5d2a9f296b4 --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceMonitorImpl.java @@ -0,0 +1,69 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor; + +import com.google.inject.Inject; +import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.config.model.api.SuperModelProvider; +import com.yahoo.config.provision.Zone; +import com.yahoo.jdisc.Metric; +import com.yahoo.jdisc.Timer; +import com.yahoo.vespa.applicationmodel.ApplicationInstance; +import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference; +import com.yahoo.vespa.service.monitor.internal.ServiceModelCache; +import com.yahoo.vespa.service.monitor.internal.ServiceMonitorMetrics; + +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 configServerHosts; + private final ServiceModelCache serviceModelCache; + + @Inject + public ServiceMonitorImpl(SuperModelProvider superModelProvider, + ConfigserverConfig configserverConfig, + SlobrokMonitorManagerImpl slobrokMonitorManager, + Metric metric, + Timer timer) { + this.zone = superModelProvider.getZone(); + this.configServerHosts = toConfigServerList(configserverConfig); + ServiceMonitorMetrics metrics = new ServiceMonitorMetrics(metric, timer); + + SuperModelListenerImpl superModelListener = new SuperModelListenerImpl( + slobrokMonitorManager, + metrics, + new ModelGenerator(), + zone, + configServerHosts); + superModelListener.start(superModelProvider); + serviceModelCache = new ServiceModelCache( + () -> superModelListener.get(), + timer); + } + + private List toConfigServerList(ConfigserverConfig configserverConfig) { + if (configserverConfig.multitenant()) { + return configserverConfig.zookeeperserver().stream() + .map(server -> server.hostname()) + .collect(Collectors.toList()); + } + + return Collections.emptyList(); + } + + @Override + public Map getAllApplicationInstances() { + return serviceModelCache.get().getAllApplicationInstances(); + } + + @Override + public ServiceModel getServiceModelSnapshot() { + return serviceModelCache.get(); + } +} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceMonitorProvider.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceMonitorProvider.java deleted file mode 100644 index b1af48f885d..00000000000 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceMonitorProvider.java +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.service.monitor; - -import com.google.inject.Inject; -import com.yahoo.cloud.config.ConfigserverConfig; -import com.yahoo.config.model.api.SuperModelProvider; -import com.yahoo.container.di.componentgraph.Provider; -import com.yahoo.jdisc.Metric; -import com.yahoo.jdisc.Timer; -import com.yahoo.vespa.service.monitor.internal.ServiceMonitorImpl; -import com.yahoo.vespa.service.monitor.internal.SlobrokMonitorManagerImpl; - -public class ServiceMonitorProvider implements Provider { - private final ServiceMonitorImpl serviceMonitor; - - @Inject - public ServiceMonitorProvider(SuperModelProvider superModelProvider, - ConfigserverConfig configserverConfig, - SlobrokMonitorManagerImpl slobrokMonitorManager, - Metric metric, - Timer timer) { - serviceMonitor = new ServiceMonitorImpl( - superModelProvider, - configserverConfig, - slobrokMonitorManager, - metric, - timer); - } - @Override - public ServiceMonitor get() { - return serviceMonitor; - } - - @Override - public void deconstruct() {} -} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitor.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitor.java new file mode 100644 index 00000000000..4da7b7c0e68 --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitor.java @@ -0,0 +1,81 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor; + +import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.model.api.HostInfo; +import com.yahoo.config.model.api.PortInfo; +import com.yahoo.config.model.api.ServiceInfo; +import com.yahoo.jrt.Spec; +import com.yahoo.jrt.Supervisor; +import com.yahoo.jrt.Transport; +import com.yahoo.jrt.slobrok.api.Mirror; +import com.yahoo.jrt.slobrok.api.SlobrokList; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +/** + * Class to manage Slobrok + */ +public class SlobrokMonitor implements AutoCloseable { + public static final String SLOBROK_SERVICE_TYPE = "slobrok"; + public static final String SLOBROK_RPC_PORT_TAG = "rpc"; + + private final SlobrokList slobrokList; + private final Mirror mirror; + + SlobrokMonitor() { + this(new SlobrokList()); + } + + // Package-private for testing. + SlobrokMonitor(SlobrokList slobrokList, Mirror mirror) { + this.slobrokList = slobrokList; + this.mirror = mirror; + } + + private SlobrokMonitor(SlobrokList slobrokList) { + this(slobrokList, new Mirror(new Supervisor(new Transport()), slobrokList)); + } + + void updateSlobrokList(ApplicationInfo application) { + List slobrokSpecs = getSlobrokSpecs(application); + slobrokList.setup(slobrokSpecs.toArray(new String[0])); + } + + List getSlobrokSpecs(ApplicationInfo applicationInfo) { + List slobrokSpecs = new ArrayList<>(); + + for (HostInfo host : applicationInfo.getModel().getHosts()) { + for (ServiceInfo service : host.getServices()) { + if (!Objects.equals(service.getServiceType(), SLOBROK_SERVICE_TYPE)) { + continue; + } + + for (PortInfo port : service.getPorts()) { + if (port.getTags().contains(SLOBROK_RPC_PORT_TAG)) { + Spec spec = new Spec(host.getHostname(), port.getPort()); + slobrokSpecs.add(spec.toString()); + } + } + } + } + + return slobrokSpecs; + } + + List lookup(String pattern) { + return Arrays.asList(mirror.lookup(pattern)); + } + + @Override + public void close() { + mirror.shutdown(); + } + + boolean registeredInSlobrok(String slobrokServiceName) { + return mirror.lookup(slobrokServiceName).length > 0; + } +} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerImpl.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerImpl.java new file mode 100644 index 00000000000..becd7cf7ef6 --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerImpl.java @@ -0,0 +1,132 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor; + +import com.google.inject.Inject; +import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.model.api.SuperModel; +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.ConfigId; +import com.yahoo.vespa.applicationmodel.ServiceStatus; +import com.yahoo.vespa.applicationmodel.ServiceType; + +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.function.Supplier; +import java.util.logging.Logger; + +public class SlobrokMonitorManagerImpl implements SuperModelListener, SlobrokMonitorManager { + private static final Logger logger = + Logger.getLogger(SlobrokMonitorManagerImpl.class.getName()); + + private final Supplier slobrokMonitorFactory; + + private final Object monitor = new Object(); + private final HashMap slobrokMonitors = new HashMap<>(); + + @Inject + public SlobrokMonitorManagerImpl() { + this(() -> new SlobrokMonitor()); + } + + SlobrokMonitorManagerImpl(Supplier slobrokMonitorFactory) { + this.slobrokMonitorFactory = slobrokMonitorFactory; + } + + @Override + public void applicationActivated(SuperModel superModel, ApplicationInfo application) { + synchronized (monitor) { + SlobrokMonitor slobrokMonitor = slobrokMonitors.computeIfAbsent( + application.getApplicationId(), + id -> slobrokMonitorFactory.get()); + slobrokMonitor.updateSlobrokList(application); + } + } + + @Override + public void applicationRemoved(SuperModel superModel, ApplicationId id) { + synchronized (monitor) { + SlobrokMonitor slobrokMonitor = slobrokMonitors.remove(id); + if (slobrokMonitor == null) { + logger.log(LogLevel.WARNING, "Removed application " + id + + ", but it was never registered"); + } else { + slobrokMonitor.close(); + } + } + } + + @Override + public List lookup(ApplicationId id, String pattern) { + synchronized (monitor) { + SlobrokMonitor slobrokMonitor = slobrokMonitors.get(id); + if (slobrokMonitor == null) { + throw new IllegalArgumentException("Slobrok manager has no knowledge of application " + id); + } else { + return slobrokMonitor.lookup(pattern); + } + } + } + + @Override + public ServiceStatus getStatus(ApplicationId applicationId, + ServiceType serviceType, + ConfigId configId) { + Optional slobrokServiceName = findSlobrokServiceName(serviceType, configId); + if (slobrokServiceName.isPresent()) { + synchronized (monitor) { + SlobrokMonitor slobrokMonitor = slobrokMonitors.get(applicationId); + if (slobrokMonitor != null && + slobrokMonitor.registeredInSlobrok(slobrokServiceName.get())) { + return ServiceStatus.UP; + } else { + return ServiceStatus.DOWN; + } + } + } else { + return ServiceStatus.NOT_CHECKED; + } + } + + /** + * Get the Slobrok service name of the service, or empty if the service + * is not registered with Slobrok. + */ + Optional findSlobrokServiceName(ServiceType serviceType, ConfigId configId) { + switch (serviceType.s()) { + case "adminserver": + case "config-sentinel": + case "configproxy": + case "configserver": + case "filedistributorservice": + case "logd": + case "logserver": + case "metricsproxy": + case "slobrok": + case "transactionlogserver": + return Optional.empty(); + + case "topleveldispatch": + return Optional.of(configId.s()); + + case "qrserver": + case "container": + case "docprocservice": + case "container-clustercontroller": + return Optional.of("vespa/service/" + configId.s()); + + case "searchnode": //TODO: handle only as storagenode instead of both as searchnode/storagenode + return Optional.of(configId.s() + "/realtimecontroller"); + case "distributor": + case "storagenode": + return Optional.of("storage/cluster." + configId.s()); + default: + logger.log(LogLevel.DEBUG, "Unknown service type " + serviceType.s() + + " with config id " + configId.s()); + return Optional.empty(); + } + } +} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerProvider.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerProvider.java deleted file mode 100644 index ca523ca5fdf..00000000000 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerProvider.java +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.service.monitor; - -import com.google.inject.Inject; -import com.yahoo.container.di.componentgraph.Provider; -import com.yahoo.vespa.service.monitor.internal.SlobrokMonitorManagerImpl; - -public class SlobrokMonitorManagerProvider implements Provider { - private final SlobrokMonitorManager slobrokMonitorManager; - - @Inject - public SlobrokMonitorManagerProvider() { - slobrokMonitorManager = new SlobrokMonitorManagerImpl(); - } - - @Override - public SlobrokMonitorManager get() { - return slobrokMonitorManager; - } - - @Override - public void deconstruct() {} -} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SuperModelListenerImpl.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SuperModelListenerImpl.java new file mode 100644 index 00000000000..506a2f7d649 --- /dev/null +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SuperModelListenerImpl.java @@ -0,0 +1,89 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor; + +import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.model.api.SuperModel; +import com.yahoo.config.model.api.SuperModelListener; +import com.yahoo.config.model.api.SuperModelProvider; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.Zone; +import com.yahoo.vespa.service.monitor.internal.LatencyMeasurement; +import com.yahoo.vespa.service.monitor.internal.ServiceMonitorMetrics; + +import java.util.List; +import java.util.function.Supplier; +import java.util.logging.Logger; + +public class SuperModelListenerImpl implements SuperModelListener, Supplier { + private static final Logger logger = Logger.getLogger(SuperModelListenerImpl.class.getName()); + + private final ServiceMonitorMetrics metrics; + private final ModelGenerator modelGenerator; + private final Zone zone; + private final List configServerHosts; + + // superModel and slobrokMonitorManager are always updated together + // and atomically using this monitor. + private final Object monitor = new Object(); + private final SlobrokMonitorManagerImpl slobrokMonitorManager; + private SuperModel superModel; + + SuperModelListenerImpl(SlobrokMonitorManagerImpl slobrokMonitorManager, + ServiceMonitorMetrics metrics, + ModelGenerator modelGenerator, + Zone zone, + List configServerHosts) { + this.slobrokMonitorManager = slobrokMonitorManager; + this.metrics = metrics; + this.modelGenerator = modelGenerator; + this.zone = zone; + this.configServerHosts = configServerHosts; + } + + void start(SuperModelProvider superModelProvider) { + synchronized (monitor) { + // This snapshot() call needs to be within the synchronized block, + // since applicationActivated()/applicationRemoved() may be called + // asynchronously even before snapshot() returns. + SuperModel snapshot = superModelProvider.snapshot(this); + + snapshot.getAllApplicationInfos().stream().forEach(application -> + applicationActivated(snapshot, application)); + } + } + + @Override + public void applicationActivated(SuperModel superModel, ApplicationInfo application) { + synchronized (monitor) { + this.superModel = superModel; + slobrokMonitorManager.applicationActivated(superModel, application); + } + } + + @Override + public void applicationRemoved(SuperModel superModel, ApplicationId id) { + synchronized (monitor) { + this.superModel = superModel; + slobrokMonitorManager.applicationRemoved(superModel, id); + } + } + + @Override + public ServiceModel get() { + try (LatencyMeasurement measurement = metrics.startServiceModelSnapshotLatencyMeasurement()) { + // Reference 'measurement' in a dummy statement, otherwise the compiler + // complains about "auto-closeable resource is never referenced in body of + // corresponding try statement". Why hasn't javac fixed this!? + dummy(measurement); + + // WARNING: The slobrok monitor manager may be out-of-sync with super model (no locking) + return modelGenerator.toServiceModel( + superModel, + zone, + configServerHosts, + slobrokMonitorManager); + } + } + + private void dummy(LatencyMeasurement measurement) {} +} \ No newline at end of file diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ConfigServerApplication.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ConfigServerApplication.java deleted file mode 100644 index ea86de2b442..00000000000 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ConfigServerApplication.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2017 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.vespa.applicationmodel.ApplicationInstance; -import com.yahoo.vespa.applicationmodel.ApplicationInstanceId; -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 java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * A service/application model of the config server with health status. - */ -public class ConfigServerApplication { - public static final ClusterId CLUSTER_ID = new ClusterId("zone-config-servers"); - public static final ServiceType SERVICE_TYPE = new ServiceType("configserver"); - public static final TenantId TENANT_ID = new TenantId("hosted-vespa"); - public static final ApplicationInstanceId APPLICATION_INSTANCE_ID = new ApplicationInstanceId("zone-config-servers"); - public static final String CONFIG_ID_PREFIX = "configid."; - - ApplicationInstance toApplicationInstance(List hostnames) { - Set serviceInstances = hostnames.stream() - .map(hostname -> new ServiceInstance( - new ConfigId(CONFIG_ID_PREFIX + hostname), - new HostName(hostname), - ServiceStatus.NOT_CHECKED)) - .collect(Collectors.toSet()); - - ServiceCluster serviceCluster = new ServiceCluster( - CLUSTER_ID, - SERVICE_TYPE, - serviceInstances); - - Set serviceClusters = - Stream.of(serviceCluster).collect(Collectors.toSet()); - - ApplicationInstance applicationInstance = new ApplicationInstance( - TENANT_ID, - 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/internal/ModelGenerator.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ModelGenerator.java deleted file mode 100644 index 961d5701901..00000000000 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ModelGenerator.java +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2017 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.HostInfo; -import com.yahoo.config.model.api.ServiceInfo; -import com.yahoo.config.model.api.SuperModel; -import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.Zone; -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.ServiceClusterKey; -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.service.monitor.ServiceModel; -import com.yahoo.vespa.service.monitor.SlobrokMonitorManager; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Util to convert SuperModel to ServiceModel and application model classes - */ -public class ModelGenerator { - public static final String CLUSTER_ID_PROPERTY_NAME = "clustername"; - - /** - * Create service model based primarily on super model. - * - * If the configServerhosts is non-empty, a config server application is added. - */ - ServiceModel toServiceModel( - SuperModel superModel, - Zone zone, - List configServerHosts, - SlobrokMonitorManager slobrokMonitorManager) { - Map applicationInstances = new HashMap<>(); - - for (ApplicationInfo applicationInfo : superModel.getAllApplicationInfos()) { - - ApplicationInstance applicationInstance = toApplicationInstance( - applicationInfo, - zone, - slobrokMonitorManager); - applicationInstances.put(applicationInstance.reference(), applicationInstance); - } - - // The config server is part of the service model (but not super model) - if (!configServerHosts.isEmpty()) { - ConfigServerApplication configServerApplication = new ConfigServerApplication(); - ApplicationInstance configServerApplicationInstance = - configServerApplication.toApplicationInstance(configServerHosts); - applicationInstances.put(configServerApplicationInstance.reference(), configServerApplicationInstance); - } - - return new ServiceModel(applicationInstances); - } - - ApplicationInstance toApplicationInstance( - ApplicationInfo applicationInfo, - Zone zone, - SlobrokMonitorManager slobrokMonitorManager) { - Map> groupedServiceInstances = new HashMap<>(); - - for (HostInfo host : applicationInfo.getModel().getHosts()) { - HostName hostName = new HostName(host.getHostname()); - for (ServiceInfo serviceInfo : host.getServices()) { - ServiceClusterKey serviceClusterKey = toServiceClusterKey(serviceInfo); - ServiceInstance serviceInstance = - toServiceInstance( - applicationInfo.getApplicationId(), - serviceInfo, - hostName, - slobrokMonitorManager); - - if (!groupedServiceInstances.containsKey(serviceClusterKey)) { - groupedServiceInstances.put(serviceClusterKey, new HashSet<>()); - } - groupedServiceInstances.get(serviceClusterKey).add(serviceInstance); - } - } - - Set serviceClusters = groupedServiceInstances.entrySet().stream() - .map(entry -> new ServiceCluster( - entry.getKey().clusterId(), - entry.getKey().serviceType(), - entry.getValue())) - .collect(Collectors.toSet()); - - ApplicationInstance applicationInstance = new ApplicationInstance( - new TenantId(applicationInfo.getApplicationId().tenant().toString()), - 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; - } - - ServiceClusterKey toServiceClusterKey(ServiceInfo serviceInfo) { - ClusterId clusterId = new ClusterId(serviceInfo.getProperty(CLUSTER_ID_PROPERTY_NAME).orElse("")); - ServiceType serviceType = toServiceType(serviceInfo); - return new ServiceClusterKey(clusterId, serviceType); - } - - ServiceInstance toServiceInstance( - ApplicationId applicationId, - ServiceInfo serviceInfo, - HostName hostName, - SlobrokMonitorManager slobrokMonitorManager) { - ConfigId configId = new ConfigId(serviceInfo.getConfigId()); - - ServiceStatus status = slobrokMonitorManager.getStatus( - applicationId, - toServiceType(serviceInfo), - configId); - - return new ServiceInstance(configId, hostName, status); - } - - ApplicationInstanceId toApplicationInstanceId(ApplicationInfo applicationInfo, Zone zone) { - return new ApplicationInstanceId(String.format("%s:%s:%s:%s", - applicationInfo.getApplicationId().application().value(), - zone.environment().value(), - zone.region().value(), - applicationInfo.getApplicationId().instance().value())); - } - - ServiceType toServiceType(ServiceInfo serviceInfo) { - return new ServiceType(serviceInfo.getServiceType()); - } -} 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 deleted file mode 100644 index 0470d37af85..00000000000 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ServiceMonitorImpl.java +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2017 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.SuperModelProvider; -import com.yahoo.config.provision.Zone; -import com.yahoo.jdisc.Metric; -import com.yahoo.jdisc.Timer; -import com.yahoo.vespa.applicationmodel.ApplicationInstance; -import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference; -import com.yahoo.vespa.service.monitor.ServiceModel; -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 configServerHosts; - private final ServiceModelCache serviceModelCache; - - public ServiceMonitorImpl(SuperModelProvider superModelProvider, - ConfigserverConfig configserverConfig, - SlobrokMonitorManagerImpl slobrokMonitorManager, - Metric metric, - Timer timer) { - this.zone = superModelProvider.getZone(); - this.configServerHosts = toConfigServerList(configserverConfig); - ServiceMonitorMetrics metrics = new ServiceMonitorMetrics(metric, timer); - - SuperModelListenerImpl superModelListener = new SuperModelListenerImpl( - slobrokMonitorManager, - metrics, - new ModelGenerator(), - zone, - configServerHosts); - superModelListener.start(superModelProvider); - serviceModelCache = new ServiceModelCache( - () -> superModelListener.get(), - timer); - } - - private List toConfigServerList(ConfigserverConfig configserverConfig) { - if (configserverConfig.multitenant()) { - return configserverConfig.zookeeperserver().stream() - .map(server -> server.hostname()) - .collect(Collectors.toList()); - } - - return Collections.emptyList(); - } - - @Override - public Map getAllApplicationInstances() { - return serviceModelCache.get().getAllApplicationInstances(); - } - - @Override - public ServiceModel getServiceModelSnapshot() { - return serviceModelCache.get(); - } -} diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitor.java b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitor.java deleted file mode 100644 index e0195e11759..00000000000 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitor.java +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2017 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.HostInfo; -import com.yahoo.config.model.api.PortInfo; -import com.yahoo.config.model.api.ServiceInfo; -import com.yahoo.jrt.Spec; -import com.yahoo.jrt.Supervisor; -import com.yahoo.jrt.Transport; -import com.yahoo.jrt.slobrok.api.Mirror; -import com.yahoo.jrt.slobrok.api.SlobrokList; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -/** - * Class to manage Slobrok - */ -public class SlobrokMonitor implements AutoCloseable { - public static final String SLOBROK_SERVICE_TYPE = "slobrok"; - public static final String SLOBROK_RPC_PORT_TAG = "rpc"; - - private final SlobrokList slobrokList; - private final Mirror mirror; - - SlobrokMonitor() { - this(new SlobrokList()); - } - - // Package-private for testing. - SlobrokMonitor(SlobrokList slobrokList, Mirror mirror) { - this.slobrokList = slobrokList; - this.mirror = mirror; - } - - private SlobrokMonitor(SlobrokList slobrokList) { - this(slobrokList, new Mirror(new Supervisor(new Transport()), slobrokList)); - } - - void updateSlobrokList(ApplicationInfo application) { - List slobrokSpecs = getSlobrokSpecs(application); - slobrokList.setup(slobrokSpecs.toArray(new String[0])); - } - - List getSlobrokSpecs(ApplicationInfo applicationInfo) { - List slobrokSpecs = new ArrayList<>(); - - for (HostInfo host : applicationInfo.getModel().getHosts()) { - for (ServiceInfo service : host.getServices()) { - if (!Objects.equals(service.getServiceType(), SLOBROK_SERVICE_TYPE)) { - continue; - } - - for (PortInfo port : service.getPorts()) { - if (port.getTags().contains(SLOBROK_RPC_PORT_TAG)) { - Spec spec = new Spec(host.getHostname(), port.getPort()); - slobrokSpecs.add(spec.toString()); - } - } - } - } - - return slobrokSpecs; - } - - List lookup(String pattern) { - return Arrays.asList(mirror.lookup(pattern)); - } - - @Override - public void close() { - mirror.shutdown(); - } - - boolean registeredInSlobrok(String slobrokServiceName) { - return mirror.lookup(slobrokServiceName).length > 0; - } -} 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 deleted file mode 100644 index f816111f2ee..00000000000 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImpl.java +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2017 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.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.ConfigId; -import com.yahoo.vespa.applicationmodel.ServiceStatus; -import com.yahoo.vespa.applicationmodel.ServiceType; -import com.yahoo.vespa.service.monitor.SlobrokMonitorManager; - -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.function.Supplier; -import java.util.logging.Logger; - -public class SlobrokMonitorManagerImpl implements SuperModelListener, SlobrokMonitorManager { - private static final Logger logger = - Logger.getLogger(SlobrokMonitorManagerImpl.class.getName()); - - private final Supplier slobrokMonitorFactory; - - private final Object monitor = new Object(); - private final HashMap slobrokMonitors = new HashMap<>(); - - public SlobrokMonitorManagerImpl() { - this(SlobrokMonitor::new); - } - - SlobrokMonitorManagerImpl(Supplier slobrokMonitorFactory) { - this.slobrokMonitorFactory = slobrokMonitorFactory; - } - - @Override - public void applicationActivated(SuperModel superModel, ApplicationInfo application) { - synchronized (monitor) { - SlobrokMonitor slobrokMonitor = slobrokMonitors.computeIfAbsent( - application.getApplicationId(), - id -> slobrokMonitorFactory.get()); - slobrokMonitor.updateSlobrokList(application); - } - } - - @Override - public void applicationRemoved(SuperModel superModel, ApplicationId id) { - synchronized (monitor) { - SlobrokMonitor slobrokMonitor = slobrokMonitors.remove(id); - if (slobrokMonitor == null) { - logger.log(LogLevel.WARNING, "Removed application " + id + - ", but it was never registered"); - } else { - slobrokMonitor.close(); - } - } - } - - @Override - public List lookup(ApplicationId id, String pattern) { - synchronized (monitor) { - SlobrokMonitor slobrokMonitor = slobrokMonitors.get(id); - if (slobrokMonitor == null) { - throw new IllegalArgumentException("Slobrok manager has no knowledge of application " + id); - } else { - return slobrokMonitor.lookup(pattern); - } - } - } - - @Override - public ServiceStatus getStatus(ApplicationId applicationId, - ServiceType serviceType, - ConfigId configId) { - Optional slobrokServiceName = findSlobrokServiceName(serviceType, configId); - if (slobrokServiceName.isPresent()) { - synchronized (monitor) { - SlobrokMonitor slobrokMonitor = slobrokMonitors.get(applicationId); - if (slobrokMonitor != null && - slobrokMonitor.registeredInSlobrok(slobrokServiceName.get())) { - return ServiceStatus.UP; - } else { - return ServiceStatus.DOWN; - } - } - } else { - return ServiceStatus.NOT_CHECKED; - } - } - - /** - * Get the Slobrok service name of the service, or empty if the service - * is not registered with Slobrok. - */ - Optional findSlobrokServiceName(ServiceType serviceType, ConfigId configId) { - switch (serviceType.s()) { - case "adminserver": - case "config-sentinel": - case "configproxy": - case "configserver": - case "filedistributorservice": - case "logd": - case "logserver": - case "metricsproxy": - case "slobrok": - case "transactionlogserver": - return Optional.empty(); - - case "topleveldispatch": - return Optional.of(configId.s()); - - case "qrserver": - case "container": - case "docprocservice": - case "container-clustercontroller": - return Optional.of("vespa/service/" + configId.s()); - - case "searchnode": //TODO: handle only as storagenode instead of both as searchnode/storagenode - return Optional.of(configId.s() + "/realtimecontroller"); - case "distributor": - case "storagenode": - return Optional.of("storage/cluster." + configId.s()); - default: - logger.log(LogLevel.DEBUG, "Unknown service type " + serviceType.s() + - " with config id " + configId.s()); - return Optional.empty(); - } - } -} 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 deleted file mode 100644 index b44d73125bd..00000000000 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImpl.java +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2017 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.model.api.SuperModelListener; -import com.yahoo.config.model.api.SuperModelProvider; -import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.Zone; -import com.yahoo.vespa.service.monitor.ServiceModel; - -import java.util.List; -import java.util.function.Supplier; -import java.util.logging.Logger; - -public class SuperModelListenerImpl implements SuperModelListener, Supplier { - private static final Logger logger = Logger.getLogger(SuperModelListenerImpl.class.getName()); - - private final ServiceMonitorMetrics metrics; - private final ModelGenerator modelGenerator; - private final Zone zone; - private final List configServerHosts; - - // superModel and slobrokMonitorManager are always updated together - // and atomically using this monitor. - private final Object monitor = new Object(); - private final SlobrokMonitorManagerImpl slobrokMonitorManager; - private SuperModel superModel; - - SuperModelListenerImpl(SlobrokMonitorManagerImpl slobrokMonitorManager, - ServiceMonitorMetrics metrics, - ModelGenerator modelGenerator, - Zone zone, - List configServerHosts) { - this.slobrokMonitorManager = slobrokMonitorManager; - this.metrics = metrics; - this.modelGenerator = modelGenerator; - this.zone = zone; - this.configServerHosts = configServerHosts; - } - - void start(SuperModelProvider superModelProvider) { - synchronized (monitor) { - // This snapshot() call needs to be within the synchronized block, - // since applicationActivated()/applicationRemoved() may be called - // asynchronously even before snapshot() returns. - SuperModel snapshot = superModelProvider.snapshot(this); - - snapshot.getAllApplicationInfos().stream().forEach(application -> - applicationActivated(snapshot, application)); - } - } - - @Override - public void applicationActivated(SuperModel superModel, ApplicationInfo application) { - synchronized (monitor) { - this.superModel = superModel; - slobrokMonitorManager.applicationActivated(superModel, application); - } - } - - @Override - public void applicationRemoved(SuperModel superModel, ApplicationId id) { - synchronized (monitor) { - this.superModel = superModel; - slobrokMonitorManager.applicationRemoved(superModel, id); - } - } - - @Override - public ServiceModel get() { - try (LatencyMeasurement measurement = metrics.startServiceModelSnapshotLatencyMeasurement()) { - // Reference 'measurement' in a dummy statement, otherwise the compiler - // complains about "auto-closeable resource is never referenced in body of - // corresponding try statement". Why hasn't javac fixed this!? - dummy(measurement); - - // WARNING: The slobrok monitor manager may be out-of-sync with super model (no locking) - return modelGenerator.toServiceModel( - superModel, - zone, - configServerHosts, - slobrokMonitorManager); - } - } - - private void dummy(LatencyMeasurement measurement) {} -} \ No newline at end of file diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ConfigServerApplicationTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ConfigServerApplicationTest.java new file mode 100644 index 00000000000..8eebdbb611b --- /dev/null +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ConfigServerApplicationTest.java @@ -0,0 +1,61 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor; + +import com.yahoo.vespa.applicationmodel.ApplicationInstance; +import com.yahoo.vespa.applicationmodel.ServiceStatus; +import org.junit.Test; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class ConfigServerApplicationTest { + private static final String configServer1 = "cfg1.yahoo.com"; + private static final String configServer2 = "cfg2.yahoo.com"; + private static final String configServer3 = "cfg3.yahoo.com"; + private static final List configServerList = Stream.of( + configServer1, + configServer2, + configServer3).collect(Collectors.toList()); + + @Test + public void toApplicationInstance() throws Exception { + ConfigServerApplication application = new ConfigServerApplication(); + ApplicationInstance applicationInstance = + application.toApplicationInstance(configServerList); + + assertEquals( + ConfigServerApplication.APPLICATION_INSTANCE_ID, + applicationInstance.applicationInstanceId()); + assertEquals( + ConfigServerApplication.TENANT_ID, + applicationInstance.tenantId()); + + assertEquals( + ConfigServerApplication.TENANT_ID.toString() + + ":" + ConfigServerApplication.APPLICATION_INSTANCE_ID, + applicationInstance.reference().toString()); + + assertEquals( + ConfigServerApplication.CLUSTER_ID, + applicationInstance.serviceClusters().iterator().next().clusterId()); + + assertEquals( + ServiceStatus.NOT_CHECKED, + applicationInstance + .serviceClusters().iterator().next() + .serviceInstances().iterator().next() + .serviceStatus()); + + assertTrue(configServerList.contains( + applicationInstance + .serviceClusters().iterator().next() + .serviceInstances().iterator().next() + .hostName() + .toString())); + } + +} \ No newline at end of file diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ExampleModel.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ExampleModel.java new file mode 100644 index 00000000000..df9391a5ec9 --- /dev/null +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ExampleModel.java @@ -0,0 +1,164 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor; + +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.PortInfo; +import com.yahoo.config.model.api.ServiceInfo; +import com.yahoo.config.model.api.SuperModel; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.InstanceName; +import com.yahoo.config.provision.TenantName; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ExampleModel { + + static final String CLUSTER_ID = "cluster-id"; + static final String SERVICE_NAME = "service-name"; + static final String SERVICE_TYPE = SlobrokMonitor.SLOBROK_SERVICE_TYPE; + static final String CONFIG_ID = "configid/1"; + static final String TENANT = "tenant"; + static final String APPLICATION_NAME = "application"; + public static final String INSTANCE_NAME = "default"; + + static SuperModel createExampleSuperModelWithOneRpcPort(String hostname, int rpcPort) { + List hosts = Stream.of(hostname).collect(Collectors.toList()); + + ApplicationInfo applicationInfo = ExampleModel + .createApplication(TENANT, APPLICATION_NAME) + .addServiceCluster(CLUSTER_ID, SERVICE_NAME, SERVICE_TYPE, hosts) + .addPort(rpcPort, "footag", SlobrokMonitor.SLOBROK_RPC_PORT_TAG) + .addPort(rpcPort + 1, "bartag") + .then() + .build(); + + Map> applicationInfos = new HashMap<>(); + applicationInfos.put(applicationInfo.getApplicationId().tenant(), new HashMap<>()); + applicationInfos.get(applicationInfo.getApplicationId().tenant()) + .put(applicationInfo.getApplicationId(), applicationInfo); + return new SuperModel(applicationInfos); + } + + static ApplicationBuilder createApplication(String tenant, + String applicationName) { + return new ApplicationBuilder(tenant, applicationName); + } + + + static class ApplicationBuilder { + private final String tenant; + private final String applicationName; + private final List clusters = new ArrayList<>(); + + ApplicationBuilder(String tenant, String applicationName) { + this.tenant = tenant; + this.applicationName = applicationName; + } + + ClusterBuilder addServiceCluster( + String clusterId, + String serviceName, + String serviceType, + List hosts) { + return new ClusterBuilder( + this, + clusterId, + serviceName, + serviceType, + hosts); + } + + ApplicationInfo build() { + List allHosts = clusters.stream() + .flatMap(clusterBuilder -> clusterBuilder.hosts.stream()) + .distinct() + .collect(Collectors.toList()); + + List hostInfos = new ArrayList<>(); + for (String hostname : allHosts) { + List serviceInfos = new ArrayList<>(); + for (ClusterBuilder cluster : clusters) { + buildServiceInfo(hostname, cluster).ifPresent(serviceInfos::add); + } + + HostInfo hostInfo = new HostInfo(hostname, serviceInfos); + hostInfos.add(hostInfo); + } + + ApplicationId id = ApplicationId.from( + tenant, + applicationName, + InstanceName.defaultName().toString()); + + Model model = mock(Model.class); + when(model.getHosts()).thenReturn(hostInfos); + + return new ApplicationInfo(id, 1, model); + } + + private Optional buildServiceInfo( + String hostname, + ClusterBuilder cluster) { + int hostIndex = cluster.hosts.indexOf(hostname); + if (hostIndex < 0) { + return Optional.empty(); + } + + Map properties = new HashMap<>(); + properties.put(ModelGenerator.CLUSTER_ID_PROPERTY_NAME, cluster.clusterId); + return Optional.of(new ServiceInfo( + cluster.serviceName, + cluster.serviceType, + cluster.portInfos, + properties, + "configid/" + (hostIndex + 1), + hostname)); + } + } + + static class ClusterBuilder { + private final ApplicationBuilder applicationBuilder; + private final String clusterId; + private final String serviceName; + private final String serviceType; + private final List hosts; + private final List portInfos = new ArrayList<>(); + + ClusterBuilder(ApplicationBuilder applicationBuilder, + String clusterId, + String serviceName, + String serviceType, + List hosts) { + this.applicationBuilder = applicationBuilder; + this.clusterId = clusterId; + this.serviceName = serviceName; + this.serviceType = serviceType; + this.hosts = hosts; + } + + /** + * A bit unrealistic, but the port is the same on all hosts. + */ + ClusterBuilder addPort(int port, String... tags) { + portInfos.add(new PortInfo(port, Arrays.asList(tags))); + return this; + } + + ApplicationBuilder then() { + applicationBuilder.clusters.add(this); + return applicationBuilder; + } + } +} diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ExampleModelTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ExampleModelTest.java new file mode 100644 index 00000000000..bcd4eae1b4e --- /dev/null +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ExampleModelTest.java @@ -0,0 +1,93 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +package com.yahoo.vespa.service.monitor; + +import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.model.api.HostInfo; +import com.yahoo.config.model.api.ServiceInfo; +import org.junit.Test; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; + +public class ExampleModelTest { + @Test + public void testEmptyApplication() { + ApplicationInfo application = ExampleModel + .createApplication( + "tenant", + "app") + .build(); + + assertEquals("tenant.app", application.getApplicationId().toString()); + assertEquals(1, application.getGeneration()); + assertEquals(0, application.getModel().getHosts().size()); + } + + @Test + public void test() { + List contentNodes = Stream.of("host1", "host2").collect(Collectors.toList()); + List containerNodes = Stream.of("host3", "host4").collect(Collectors.toList()); + + ApplicationInfo application = ExampleModel + .createApplication( + "tenant", + "app") + .addServiceCluster( + "product-controllers", + "container-clustercontroller.1", + "container-clustercontroller", + contentNodes) + .then() + .addServiceCluster( + "product", + "searchnode.1", + "searchnode", + contentNodes) + .then() + .addServiceCluster( + "admin", + "slobrok.1", + "slobrok", + containerNodes) + .then() + .addServiceCluster( + "default", + "container.1", + "container", + containerNodes) + .then() + .build(); + + assertEquals("tenant.app", application.getApplicationId().toString()); + + Collection hostInfos = application.getModel().getHosts(); + assertEquals(containerNodes.size() + contentNodes.size(), hostInfos.size()); + + HostInfo host1 = hostInfos.stream() + .filter(hostInfo -> hostInfo.getHostname().equals("host1")) + .findAny() + .orElseThrow(() -> new RuntimeException()); + ServiceInfo controller1 = host1.getServices().stream() + .filter(i -> i.getServiceType().equals("container-clustercontroller")) + .findAny() + .orElseThrow(() -> new RuntimeException()); + + assertEquals("container-clustercontroller", controller1.getServiceType()); + assertEquals("configid/1", controller1.getConfigId()); + + HostInfo host4 = hostInfos.stream() + .filter(hostInfo -> hostInfo.getHostname().equals("host4")) + .findAny() + .orElseThrow(() -> new RuntimeException()); + ServiceInfo slobrok2 = host4.getServices().stream() + .filter(i -> i.getServiceType().equals("slobrok")) + .findAny() + .orElseThrow(() -> new RuntimeException()); + assertEquals("configid/2", slobrok2.getConfigId()); + } +} diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ModelGeneratorTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ModelGeneratorTest.java new file mode 100644 index 00000000000..1d8e2ad4ceb --- /dev/null +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ModelGeneratorTest.java @@ -0,0 +1,139 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor; + +import com.yahoo.config.model.api.SuperModel; +import com.yahoo.config.provision.Environment; +import com.yahoo.config.provision.RegionName; +import com.yahoo.config.provision.Zone; +import com.yahoo.vespa.applicationmodel.ApplicationInstance; +import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference; +import com.yahoo.vespa.applicationmodel.ServiceCluster; +import com.yahoo.vespa.applicationmodel.ServiceInstance; +import com.yahoo.vespa.applicationmodel.ServiceStatus; +import org.junit.Test; + +import java.util.Collections; +import java.util.Iterator; +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.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ModelGeneratorTest { + private final String ENVIRONMENT = "prod"; + private final String REGION = "us-west-1"; + private final String HOSTNAME = "hostname"; + private final int PORT = 2; + + @Test + public void toApplicationModelWithConfigServerApplication() throws Exception { + SuperModel superModel = + ExampleModel.createExampleSuperModelWithOneRpcPort(HOSTNAME, PORT); + ModelGenerator modelGenerator = new ModelGenerator(); + + Zone zone = new Zone(Environment.from(ENVIRONMENT), RegionName.from(REGION)); + + List configServerHosts = Stream.of("cfg1", "cfg2", "cfg3") + .collect(Collectors.toList()); + + SlobrokMonitorManagerImpl slobrokMonitorManager = mock(SlobrokMonitorManagerImpl.class); + when(slobrokMonitorManager.getStatus(any(), any(), any())) + .thenReturn(ServiceStatus.UP); + + ServiceModel serviceModel = + modelGenerator.toServiceModel( + superModel, + zone, + configServerHosts, + slobrokMonitorManager); + + Map applicationInstances = + serviceModel.getAllApplicationInstances(); + + assertEquals(2, applicationInstances.size()); + + Iterator> iterator = + applicationInstances.entrySet().iterator(); + + ApplicationInstance applicationInstance1 = iterator.next().getValue(); + ApplicationInstance applicationInstance2 = iterator.next().getValue(); + + if (applicationInstance1.applicationInstanceId().equals( + ConfigServerApplication.APPLICATION_INSTANCE_ID)) { + verifyConfigServerApplication(applicationInstance1); + verifyOtherApplication(applicationInstance2); + } else { + verifyConfigServerApplication(applicationInstance2); + verifyOtherApplication(applicationInstance1); + } + } + + @Test + public void toApplicationModel() throws Exception { + SuperModel superModel = + ExampleModel.createExampleSuperModelWithOneRpcPort(HOSTNAME, PORT); + ModelGenerator modelGenerator = new ModelGenerator(); + + Zone zone = new Zone(Environment.from(ENVIRONMENT), RegionName.from(REGION)); + + List configServerHosts = Collections.emptyList(); + + SlobrokMonitorManagerImpl slobrokMonitorManager = mock(SlobrokMonitorManagerImpl.class); + when(slobrokMonitorManager.getStatus(any(), any(), any())) + .thenReturn(ServiceStatus.UP); + + ServiceModel serviceModel = + modelGenerator.toServiceModel( + superModel, + zone, + configServerHosts, + slobrokMonitorManager); + + Map applicationInstances = + serviceModel.getAllApplicationInstances(); + + assertEquals(1, applicationInstances.size()); + verifyOtherApplication(applicationInstances.values().iterator().next()); + } + + private void verifyOtherApplication(ApplicationInstance applicationInstance) { + assertEquals(String.format("%s:%s:%s:%s:%s", + ExampleModel.TENANT, + ExampleModel.APPLICATION_NAME, + ENVIRONMENT, + REGION, + ExampleModel.INSTANCE_NAME), + applicationInstance.reference().toString()); + + assertEquals(ExampleModel.TENANT, applicationInstance.tenantId().toString()); + Set serviceClusters = + applicationInstance.serviceClusters(); + assertEquals(1, serviceClusters.size()); + ServiceCluster serviceCluster = serviceClusters.iterator().next(); + assertEquals(ExampleModel.CLUSTER_ID, serviceCluster.clusterId().toString()); + assertEquals(ExampleModel.SERVICE_TYPE, serviceCluster.serviceType().toString()); + Set serviceInstances = + serviceCluster.serviceInstances(); + assertEquals(1, serviceClusters.size()); + ServiceInstance serviceInstance = serviceInstances.iterator().next(); + assertEquals(HOSTNAME, serviceInstance.hostName().toString()); + assertEquals(ExampleModel.CONFIG_ID, serviceInstance.configId().toString()); + assertEquals(ServiceStatus.UP, serviceInstance.serviceStatus()); + } + + private void verifyConfigServerApplication( + ApplicationInstance applicationInstance) { + assertEquals(ConfigServerApplication.APPLICATION_INSTANCE_ID, + applicationInstance.applicationInstanceId()); + } + +} diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerImplImplTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerImplImplTest.java new file mode 100644 index 00000000000..d21088ccbf4 --- /dev/null +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerImplImplTest.java @@ -0,0 +1,93 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor; + +import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.model.api.SuperModel; +import com.yahoo.vespa.applicationmodel.ConfigId; +import com.yahoo.vespa.applicationmodel.ServiceStatus; +import com.yahoo.vespa.applicationmodel.ServiceType; +import org.junit.Before; +import org.junit.Test; + +import java.util.Optional; +import java.util.function.Supplier; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class SlobrokMonitorManagerImplImplTest { + // IntelliJ complains if parametrized type is specified, Maven complains if not specified. + @SuppressWarnings("unchecked") + private final Supplier slobrokMonitorFactory = mock(Supplier.class); + + private final SlobrokMonitorManagerImpl slobrokMonitorManager = + new SlobrokMonitorManagerImpl(slobrokMonitorFactory); + private final SlobrokMonitor slobrokMonitor = mock(SlobrokMonitor.class); + private final SuperModel superModel = mock(SuperModel.class); + private final ApplicationInfo application = mock(ApplicationInfo.class); + + @Before + public void setup() { + when(slobrokMonitorFactory.get()).thenReturn(slobrokMonitor); + } + + @Test + public void testActivationOfApplication() { + slobrokMonitorManager.applicationActivated(superModel, application); + verify(slobrokMonitorFactory, times(1)).get(); + } + + @Test + public void testGetStatus_ApplicationNotInSlobrok() { + when(slobrokMonitor.registeredInSlobrok("config.id")).thenReturn(true); + assertEquals(ServiceStatus.DOWN, getStatus("topleveldispatch")); + } + + @Test + public void testGetStatus_ApplicationInSlobrok() { + slobrokMonitorManager.applicationActivated(superModel, application); + when(slobrokMonitor.registeredInSlobrok("config.id")).thenReturn(true); + assertEquals(ServiceStatus.UP, getStatus("topleveldispatch")); + } + + @Test + public void testGetStatus_ServiceNotInSlobrok() { + slobrokMonitorManager.applicationActivated(superModel, application); + when(slobrokMonitor.registeredInSlobrok("config.id")).thenReturn(false); + assertEquals(ServiceStatus.DOWN, getStatus("topleveldispatch")); + } + + @Test + public void testGetStatus_NotChecked() { + assertEquals(ServiceStatus.NOT_CHECKED, getStatus("slobrok")); + verify(slobrokMonitor, times(0)).registeredInSlobrok(any()); + } + + private ServiceStatus getStatus(String serviceType) { + return slobrokMonitorManager.getStatus( + application.getApplicationId(), + new ServiceType(serviceType), + new ConfigId("config.id")); + } + + @Test + public void testLookup() { + assertEquals( + Optional.of("config.id"), + findSlobrokServiceName("topleveldispatch", "config.id")); + + assertEquals( + Optional.empty(), + findSlobrokServiceName("adminserver", "config.id")); + } + + private Optional findSlobrokServiceName(String serviceType, String configId) { + return slobrokMonitorManager.findSlobrokServiceName( + new ServiceType(serviceType), + new ConfigId(configId)); + } +} diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SlobrokMonitorTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SlobrokMonitorTest.java new file mode 100644 index 00000000000..2cbe48c7be5 --- /dev/null +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SlobrokMonitorTest.java @@ -0,0 +1,36 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.service.monitor; + +import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.jrt.slobrok.api.Mirror; +import com.yahoo.jrt.slobrok.api.SlobrokList; +import org.junit.Test; + +import static org.mockito.Mockito.mock; + +public class SlobrokMonitorTest { + private final SlobrokList slobrokList = mock(SlobrokList.class); + private final Mirror mirror = mock(Mirror.class); + private SlobrokMonitor slobrokMonitor = new SlobrokMonitor(slobrokList, mirror); + + @Test + public void testUpdateSlobrokList() { + ApplicationInfo applicationInfo = ExampleModel.createApplication( + "tenant", + "application-name") + .build(); + } + + @Test + public void testUpdateSlobrokList2() { + /* + final String hostname = "hostname"; + final int port = 1; + + SuperModel superModel = ExampleModel.createExampleSuperModelWithOneRpcPort(hostname, port); + slobrokMonitor.updateSlobrokList(superModel.getApplicationInfo()); + + String[] expectedSpecs = new String[] {"tcp/" + hostname + ":" + port}; + verify(slobrokList).setup(expectedSpecs); */ + } +} diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SuperModelListenerImplTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SuperModelListenerImplTest.java new file mode 100644 index 00000000000..e2aaf1c9838 --- /dev/null +++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SuperModelListenerImplTest.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.service.monitor; + +import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.model.api.SuperModel; +import com.yahoo.config.model.api.SuperModelProvider; +import com.yahoo.config.provision.Zone; +import com.yahoo.vespa.service.monitor.internal.ServiceMonitorMetrics; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class SuperModelListenerImplTest { + @Test + public void sanityCheck() { + SlobrokMonitorManagerImpl slobrokMonitorManager = mock(SlobrokMonitorManagerImpl.class); + ServiceMonitorMetrics metrics = mock(ServiceMonitorMetrics.class); + ModelGenerator modelGenerator = mock(ModelGenerator.class); + Zone zone = mock(Zone.class); + List configServers = new ArrayList<>(); + SuperModelListenerImpl listener = new SuperModelListenerImpl( + slobrokMonitorManager, + metrics, + modelGenerator, + zone, + configServers); + + SuperModelProvider superModelProvider = mock(SuperModelProvider.class); + SuperModel superModel = mock(SuperModel.class); + when(superModelProvider.snapshot(listener)).thenReturn(superModel); + + ApplicationInfo application1 = mock(ApplicationInfo.class); + ApplicationInfo application2 = mock(ApplicationInfo.class); + List applications = Stream.of(application1, application2) + .collect(Collectors.toList()); + when(superModel.getAllApplicationInfos()).thenReturn(applications); + + listener.start(superModelProvider); + verify(slobrokMonitorManager).applicationActivated(superModel, application1); + verify(slobrokMonitorManager).applicationActivated(superModel, application2); + + ServiceModel serviceModel = listener.get(); + verify(modelGenerator).toServiceModel(superModel, zone, configServers, slobrokMonitorManager); + } +} \ No newline at end of file diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ConfigServerApplicationTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ConfigServerApplicationTest.java deleted file mode 100644 index d00dca99116..00000000000 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ConfigServerApplicationTest.java +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2017 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.vespa.applicationmodel.ApplicationInstance; -import com.yahoo.vespa.applicationmodel.ServiceStatus; -import org.junit.Test; - -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class ConfigServerApplicationTest { - private static final String configServer1 = "cfg1.yahoo.com"; - private static final String configServer2 = "cfg2.yahoo.com"; - private static final String configServer3 = "cfg3.yahoo.com"; - private static final List configServerList = Stream.of( - configServer1, - configServer2, - configServer3).collect(Collectors.toList()); - - @Test - public void toApplicationInstance() throws Exception { - ConfigServerApplication application = new ConfigServerApplication(); - ApplicationInstance applicationInstance = - application.toApplicationInstance(configServerList); - - assertEquals( - ConfigServerApplication.APPLICATION_INSTANCE_ID, - applicationInstance.applicationInstanceId()); - assertEquals( - ConfigServerApplication.TENANT_ID, - applicationInstance.tenantId()); - - assertEquals( - ConfigServerApplication.TENANT_ID.toString() + - ":" + ConfigServerApplication.APPLICATION_INSTANCE_ID, - applicationInstance.reference().toString()); - - assertEquals( - ConfigServerApplication.CLUSTER_ID, - applicationInstance.serviceClusters().iterator().next().clusterId()); - - assertEquals( - ServiceStatus.NOT_CHECKED, - applicationInstance - .serviceClusters().iterator().next() - .serviceInstances().iterator().next() - .serviceStatus()); - - assertTrue(configServerList.contains( - applicationInstance - .serviceClusters().iterator().next() - .serviceInstances().iterator().next() - .hostName() - .toString())); - } - -} \ No newline at end of file diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ExampleModel.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ExampleModel.java deleted file mode 100644 index fca1512e3ea..00000000000 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ExampleModel.java +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2017 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.HostInfo; -import com.yahoo.config.model.api.Model; -import com.yahoo.config.model.api.PortInfo; -import com.yahoo.config.model.api.ServiceInfo; -import com.yahoo.config.model.api.SuperModel; -import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.InstanceName; -import com.yahoo.config.provision.TenantName; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class ExampleModel { - - static final String CLUSTER_ID = "cluster-id"; - static final String SERVICE_NAME = "service-name"; - static final String SERVICE_TYPE = SlobrokMonitor.SLOBROK_SERVICE_TYPE; - static final String CONFIG_ID = "configid/1"; - static final String TENANT = "tenant"; - static final String APPLICATION_NAME = "application"; - public static final String INSTANCE_NAME = "default"; - - static SuperModel createExampleSuperModelWithOneRpcPort(String hostname, int rpcPort) { - List hosts = Stream.of(hostname).collect(Collectors.toList()); - - ApplicationInfo applicationInfo = ExampleModel - .createApplication(TENANT, APPLICATION_NAME) - .addServiceCluster(CLUSTER_ID, SERVICE_NAME, SERVICE_TYPE, hosts) - .addPort(rpcPort, "footag", SlobrokMonitor.SLOBROK_RPC_PORT_TAG) - .addPort(rpcPort + 1, "bartag") - .then() - .build(); - - Map> applicationInfos = new HashMap<>(); - applicationInfos.put(applicationInfo.getApplicationId().tenant(), new HashMap<>()); - applicationInfos.get(applicationInfo.getApplicationId().tenant()) - .put(applicationInfo.getApplicationId(), applicationInfo); - return new SuperModel(applicationInfos); - } - - static ApplicationBuilder createApplication(String tenant, - String applicationName) { - return new ApplicationBuilder(tenant, applicationName); - } - - - static class ApplicationBuilder { - private final String tenant; - private final String applicationName; - private final List clusters = new ArrayList<>(); - - ApplicationBuilder(String tenant, String applicationName) { - this.tenant = tenant; - this.applicationName = applicationName; - } - - ClusterBuilder addServiceCluster( - String clusterId, - String serviceName, - String serviceType, - List hosts) { - return new ClusterBuilder( - this, - clusterId, - serviceName, - serviceType, - hosts); - } - - ApplicationInfo build() { - List allHosts = clusters.stream() - .flatMap(clusterBuilder -> clusterBuilder.hosts.stream()) - .distinct() - .collect(Collectors.toList()); - - List hostInfos = new ArrayList<>(); - for (String hostname : allHosts) { - List serviceInfos = new ArrayList<>(); - for (ClusterBuilder cluster : clusters) { - buildServiceInfo(hostname, cluster).ifPresent(serviceInfos::add); - } - - HostInfo hostInfo = new HostInfo(hostname, serviceInfos); - hostInfos.add(hostInfo); - } - - ApplicationId id = ApplicationId.from( - tenant, - applicationName, - InstanceName.defaultName().toString()); - - Model model = mock(Model.class); - when(model.getHosts()).thenReturn(hostInfos); - - return new ApplicationInfo(id, 1, model); - } - - private Optional buildServiceInfo( - String hostname, - ClusterBuilder cluster) { - int hostIndex = cluster.hosts.indexOf(hostname); - if (hostIndex < 0) { - return Optional.empty(); - } - - Map properties = new HashMap<>(); - properties.put(ModelGenerator.CLUSTER_ID_PROPERTY_NAME, cluster.clusterId); - return Optional.of(new ServiceInfo( - cluster.serviceName, - cluster.serviceType, - cluster.portInfos, - properties, - "configid/" + (hostIndex + 1), - hostname)); - } - } - - static class ClusterBuilder { - private final ApplicationBuilder applicationBuilder; - private final String clusterId; - private final String serviceName; - private final String serviceType; - private final List hosts; - private final List portInfos = new ArrayList<>(); - - ClusterBuilder(ApplicationBuilder applicationBuilder, - String clusterId, - String serviceName, - String serviceType, - List hosts) { - this.applicationBuilder = applicationBuilder; - this.clusterId = clusterId; - this.serviceName = serviceName; - this.serviceType = serviceType; - this.hosts = hosts; - } - - /** - * A bit unrealistic, but the port is the same on all hosts. - */ - ClusterBuilder addPort(int port, String... tags) { - portInfos.add(new PortInfo(port, Arrays.asList(tags))); - return this; - } - - ApplicationBuilder then() { - applicationBuilder.clusters.add(this); - return applicationBuilder; - } - } -} diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ExampleModelTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ExampleModelTest.java deleted file mode 100644 index 64ba2ba5097..00000000000 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ExampleModelTest.java +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2017 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.HostInfo; -import com.yahoo.config.model.api.ServiceInfo; -import org.junit.Test; - -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.junit.Assert.assertEquals; - -public class ExampleModelTest { - @Test - public void testEmptyApplication() { - ApplicationInfo application = ExampleModel - .createApplication( - "tenant", - "app") - .build(); - - assertEquals("tenant.app", application.getApplicationId().toString()); - assertEquals(1, application.getGeneration()); - assertEquals(0, application.getModel().getHosts().size()); - } - - @Test - public void test() { - List contentNodes = Stream.of("host1", "host2").collect(Collectors.toList()); - List containerNodes = Stream.of("host3", "host4").collect(Collectors.toList()); - - ApplicationInfo application = ExampleModel - .createApplication( - "tenant", - "app") - .addServiceCluster( - "product-controllers", - "container-clustercontroller.1", - "container-clustercontroller", - contentNodes) - .then() - .addServiceCluster( - "product", - "searchnode.1", - "searchnode", - contentNodes) - .then() - .addServiceCluster( - "admin", - "slobrok.1", - "slobrok", - containerNodes) - .then() - .addServiceCluster( - "default", - "container.1", - "container", - containerNodes) - .then() - .build(); - - assertEquals("tenant.app", application.getApplicationId().toString()); - - Collection hostInfos = application.getModel().getHosts(); - assertEquals(containerNodes.size() + contentNodes.size(), hostInfos.size()); - - HostInfo host1 = hostInfos.stream() - .filter(hostInfo -> hostInfo.getHostname().equals("host1")) - .findAny() - .orElseThrow(() -> new RuntimeException()); - ServiceInfo controller1 = host1.getServices().stream() - .filter(i -> i.getServiceType().equals("container-clustercontroller")) - .findAny() - .orElseThrow(() -> new RuntimeException()); - - assertEquals("container-clustercontroller", controller1.getServiceType()); - assertEquals("configid/1", controller1.getConfigId()); - - HostInfo host4 = hostInfos.stream() - .filter(hostInfo -> hostInfo.getHostname().equals("host4")) - .findAny() - .orElseThrow(() -> new RuntimeException()); - ServiceInfo slobrok2 = host4.getServices().stream() - .filter(i -> i.getServiceType().equals("slobrok")) - .findAny() - .orElseThrow(() -> new RuntimeException()); - assertEquals("configid/2", slobrok2.getConfigId()); - } -} 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 deleted file mode 100644 index cf07c39950c..00000000000 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ModelGeneratorTest.java +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2017 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.SuperModel; -import com.yahoo.config.provision.Environment; -import com.yahoo.config.provision.RegionName; -import com.yahoo.config.provision.Zone; -import com.yahoo.vespa.applicationmodel.ApplicationInstance; -import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference; -import com.yahoo.vespa.applicationmodel.ServiceCluster; -import com.yahoo.vespa.applicationmodel.ServiceInstance; -import com.yahoo.vespa.applicationmodel.ServiceStatus; -import com.yahoo.vespa.service.monitor.ServiceModel; -import org.junit.Test; - -import java.util.Collections; -import java.util.Iterator; -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.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class ModelGeneratorTest { - private final String ENVIRONMENT = "prod"; - private final String REGION = "us-west-1"; - private final String HOSTNAME = "hostname"; - private final int PORT = 2; - - @Test - public void toApplicationModelWithConfigServerApplication() throws Exception { - SuperModel superModel = - ExampleModel.createExampleSuperModelWithOneRpcPort(HOSTNAME, PORT); - ModelGenerator modelGenerator = new ModelGenerator(); - - Zone zone = new Zone(Environment.from(ENVIRONMENT), RegionName.from(REGION)); - - List configServerHosts = Stream.of("cfg1", "cfg2", "cfg3") - .collect(Collectors.toList()); - - SlobrokMonitorManagerImpl slobrokMonitorManager = mock(SlobrokMonitorManagerImpl.class); - when(slobrokMonitorManager.getStatus(any(), any(), any())) - .thenReturn(ServiceStatus.UP); - - ServiceModel serviceModel = - modelGenerator.toServiceModel( - superModel, - zone, - configServerHosts, - slobrokMonitorManager); - - Map applicationInstances = - serviceModel.getAllApplicationInstances(); - - assertEquals(2, applicationInstances.size()); - - Iterator> iterator = - applicationInstances.entrySet().iterator(); - - ApplicationInstance applicationInstance1 = iterator.next().getValue(); - ApplicationInstance applicationInstance2 = iterator.next().getValue(); - - if (applicationInstance1.applicationInstanceId().equals( - ConfigServerApplication.APPLICATION_INSTANCE_ID)) { - verifyConfigServerApplication(applicationInstance1); - verifyOtherApplication(applicationInstance2); - } else { - verifyConfigServerApplication(applicationInstance2); - verifyOtherApplication(applicationInstance1); - } - } - - @Test - public void toApplicationModel() throws Exception { - SuperModel superModel = - ExampleModel.createExampleSuperModelWithOneRpcPort(HOSTNAME, PORT); - ModelGenerator modelGenerator = new ModelGenerator(); - - Zone zone = new Zone(Environment.from(ENVIRONMENT), RegionName.from(REGION)); - - List configServerHosts = Collections.emptyList(); - - SlobrokMonitorManagerImpl slobrokMonitorManager = mock(SlobrokMonitorManagerImpl.class); - when(slobrokMonitorManager.getStatus(any(), any(), any())) - .thenReturn(ServiceStatus.UP); - - ServiceModel serviceModel = - modelGenerator.toServiceModel( - superModel, - zone, - configServerHosts, - slobrokMonitorManager); - - Map applicationInstances = - serviceModel.getAllApplicationInstances(); - - assertEquals(1, applicationInstances.size()); - verifyOtherApplication(applicationInstances.values().iterator().next()); - } - - private void verifyOtherApplication(ApplicationInstance applicationInstance) { - assertEquals(String.format("%s:%s:%s:%s:%s", - ExampleModel.TENANT, - ExampleModel.APPLICATION_NAME, - ENVIRONMENT, - REGION, - ExampleModel.INSTANCE_NAME), - applicationInstance.reference().toString()); - - assertEquals(ExampleModel.TENANT, applicationInstance.tenantId().toString()); - Set serviceClusters = - applicationInstance.serviceClusters(); - assertEquals(1, serviceClusters.size()); - ServiceCluster serviceCluster = serviceClusters.iterator().next(); - assertEquals(ExampleModel.CLUSTER_ID, serviceCluster.clusterId().toString()); - assertEquals(ExampleModel.SERVICE_TYPE, serviceCluster.serviceType().toString()); - Set serviceInstances = - serviceCluster.serviceInstances(); - assertEquals(1, serviceClusters.size()); - ServiceInstance serviceInstance = serviceInstances.iterator().next(); - assertEquals(HOSTNAME, serviceInstance.hostName().toString()); - assertEquals(ExampleModel.CONFIG_ID, serviceInstance.configId().toString()); - assertEquals(ServiceStatus.UP, serviceInstance.serviceStatus()); - } - - private void verifyConfigServerApplication( - ApplicationInstance applicationInstance) { - assertEquals(ConfigServerApplication.APPLICATION_INSTANCE_ID, - applicationInstance.applicationInstanceId()); - } - -} 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/SlobrokMonitorManagerImplImplTest.java deleted file mode 100644 index 79f927f6161..00000000000 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImplImplTest.java +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2017 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.vespa.applicationmodel.ConfigId; -import com.yahoo.vespa.applicationmodel.ServiceStatus; -import com.yahoo.vespa.applicationmodel.ServiceType; -import org.junit.Before; -import org.junit.Test; - -import java.util.Optional; -import java.util.function.Supplier; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class SlobrokMonitorManagerImplImplTest { - // IntelliJ complains if parametrized type is specified, Maven complains if not specified. - @SuppressWarnings("unchecked") - private final Supplier slobrokMonitorFactory = mock(Supplier.class); - - private final SlobrokMonitorManagerImpl slobrokMonitorManager = - new SlobrokMonitorManagerImpl(slobrokMonitorFactory); - private final SlobrokMonitor slobrokMonitor = mock(SlobrokMonitor.class); - private final SuperModel superModel = mock(SuperModel.class); - private final ApplicationInfo application = mock(ApplicationInfo.class); - - @Before - public void setup() { - when(slobrokMonitorFactory.get()).thenReturn(slobrokMonitor); - } - - @Test - public void testActivationOfApplication() { - slobrokMonitorManager.applicationActivated(superModel, application); - verify(slobrokMonitorFactory, times(1)).get(); - } - - @Test - public void testGetStatus_ApplicationNotInSlobrok() { - when(slobrokMonitor.registeredInSlobrok("config.id")).thenReturn(true); - assertEquals(ServiceStatus.DOWN, getStatus("topleveldispatch")); - } - - @Test - public void testGetStatus_ApplicationInSlobrok() { - slobrokMonitorManager.applicationActivated(superModel, application); - when(slobrokMonitor.registeredInSlobrok("config.id")).thenReturn(true); - assertEquals(ServiceStatus.UP, getStatus("topleveldispatch")); - } - - @Test - public void testGetStatus_ServiceNotInSlobrok() { - slobrokMonitorManager.applicationActivated(superModel, application); - when(slobrokMonitor.registeredInSlobrok("config.id")).thenReturn(false); - assertEquals(ServiceStatus.DOWN, getStatus("topleveldispatch")); - } - - @Test - public void testGetStatus_NotChecked() { - assertEquals(ServiceStatus.NOT_CHECKED, getStatus("slobrok")); - verify(slobrokMonitor, times(0)).registeredInSlobrok(any()); - } - - private ServiceStatus getStatus(String serviceType) { - return slobrokMonitorManager.getStatus( - application.getApplicationId(), - new ServiceType(serviceType), - new ConfigId("config.id")); - } - - @Test - public void testLookup() { - assertEquals( - Optional.of("config.id"), - findSlobrokServiceName("topleveldispatch", "config.id")); - - assertEquals( - Optional.empty(), - findSlobrokServiceName("adminserver", "config.id")); - } - - private Optional findSlobrokServiceName(String serviceType, String configId) { - return slobrokMonitorManager.findSlobrokServiceName( - new ServiceType(serviceType), - new ConfigId(configId)); - } -} diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorTest.java deleted file mode 100644 index 075647e9c16..00000000000 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorTest.java +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017 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.jrt.slobrok.api.Mirror; -import com.yahoo.jrt.slobrok.api.SlobrokList; -import org.junit.Test; - -import static org.mockito.Mockito.mock; - -public class SlobrokMonitorTest { - private final SlobrokList slobrokList = mock(SlobrokList.class); - private final Mirror mirror = mock(Mirror.class); - private SlobrokMonitor slobrokMonitor = new SlobrokMonitor(slobrokList, mirror); - - @Test - public void testUpdateSlobrokList() { - ApplicationInfo applicationInfo = ExampleModel.createApplication( - "tenant", - "application-name") - .build(); - } - - @Test - public void testUpdateSlobrokList2() { - /* - final String hostname = "hostname"; - final int port = 1; - - SuperModel superModel = ExampleModel.createExampleSuperModelWithOneRpcPort(hostname, port); - slobrokMonitor.updateSlobrokList(superModel.getApplicationInfo()); - - String[] expectedSpecs = new String[] {"tcp/" + hostname + ":" + port}; - verify(slobrokList).setup(expectedSpecs); */ - } -} diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImplTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImplTest.java deleted file mode 100644 index 6233f39b9cf..00000000000 --- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImplTest.java +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2017 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.model.api.SuperModelProvider; -import com.yahoo.config.provision.Zone; -import com.yahoo.vespa.service.monitor.ServiceModel; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class SuperModelListenerImplTest { - @Test - public void sanityCheck() { - SlobrokMonitorManagerImpl slobrokMonitorManager = mock(SlobrokMonitorManagerImpl.class); - ServiceMonitorMetrics metrics = mock(ServiceMonitorMetrics.class); - ModelGenerator modelGenerator = mock(ModelGenerator.class); - Zone zone = mock(Zone.class); - List configServers = new ArrayList<>(); - SuperModelListenerImpl listener = new SuperModelListenerImpl( - slobrokMonitorManager, - metrics, - modelGenerator, - zone, - configServers); - - SuperModelProvider superModelProvider = mock(SuperModelProvider.class); - SuperModel superModel = mock(SuperModel.class); - when(superModelProvider.snapshot(listener)).thenReturn(superModel); - - ApplicationInfo application1 = mock(ApplicationInfo.class); - ApplicationInfo application2 = mock(ApplicationInfo.class); - List applications = Stream.of(application1, application2) - .collect(Collectors.toList()); - when(superModel.getAllApplicationInfos()).thenReturn(applications); - - listener.start(superModelProvider); - verify(slobrokMonitorManager).applicationActivated(superModel, application1); - verify(slobrokMonitorManager).applicationActivated(superModel, application2); - - ServiceModel serviceModel = listener.get(); - verify(modelGenerator).toServiceModel(superModel, zone, configServers, slobrokMonitorManager); - } -} \ No newline at end of file -- cgit v1.2.3