summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/IdentityDocumentGenerator.java5
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/SystemStateBroadcaster.java1
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java51
-rw-r--r--configserver/src/main/resources/configserver-app/services.xml4
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java6
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java30
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListTenantsTest.java6
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantHandlerTest.java2
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantsTestCase.java36
-rw-r--r--container-di/src/main/scala/com/yahoo/container/di/Container.scala3
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/ErrorResponse.java8
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java24
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/Authorizer.java24
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/DeployAuthorizer.java81
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java2
-rw-r--r--eval/src/vespa/eval/eval/interpreted_function.cpp38
-rw-r--r--eval/src/vespa/eval/eval/simple_tensor.cpp10
-rw-r--r--eval/src/vespa/eval/eval/simple_tensor.h1
-rw-r--r--eval/src/vespa/eval/eval/tensor.h1
-rw-r--r--eval/src/vespa/eval/eval/value.cpp6
-rw-r--r--eval/src/vespa/eval/eval/value.h1
-rw-r--r--eval/src/vespa/eval/tensor/tensor.h1
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceModel.java6
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ConfigServerApplication.java (renamed from service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ConfigServerApplication.java)2
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ModelGenerator.java (renamed from service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ModelGenerator.java)4
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ServiceMonitorImpl.java (renamed from service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceMonitorImpl.java)6
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitor.java (renamed from service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitor.java)2
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImpl.java (renamed from service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerImpl.java)3
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImpl.java (renamed from service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SuperModelListenerImpl.java)5
-rw-r--r--service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ConfigServerApplicationTest.java (renamed from service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ConfigServerApplicationTest.java)2
-rw-r--r--service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ExampleModel.java (renamed from service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ExampleModel.java)2
-rw-r--r--service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ExampleModelTest.java (renamed from service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ExampleModelTest.java)2
-rw-r--r--service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ModelGeneratorTest.java (renamed from service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ModelGeneratorTest.java)3
-rw-r--r--service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImplImplTest.java (renamed from service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerImplImplTest.java)2
-rw-r--r--service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorTest.java (renamed from service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SlobrokMonitorTest.java)2
-rw-r--r--service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImplTest.java (renamed from service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SuperModelListenerImplTest.java)4
37 files changed, 198 insertions, 190 deletions
diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/IdentityDocumentGenerator.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/IdentityDocumentGenerator.java
index 644fc929884..efb2179ff6b 100644
--- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/IdentityDocumentGenerator.java
+++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/impl/IdentityDocumentGenerator.java
@@ -1,7 +1,6 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl;
-import com.yahoo.athenz.auth.util.Crypto;
import com.yahoo.config.provision.Zone;
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.config.AthenzProviderServiceConfig;
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.impl.model.IdentityDocument;
@@ -27,6 +26,7 @@ public class IdentityDocumentGenerator {
private final String dnsSuffix;
private final String providerService;
private final String ztsUrl;
+ private final String providerDomain;
public IdentityDocumentGenerator(AthenzProviderServiceConfig config, NodeRepository nodeRepository, Zone zone, KeyProvider keyProvider) {
this.nodeRepository = nodeRepository;
@@ -35,6 +35,7 @@ public class IdentityDocumentGenerator {
this.dnsSuffix = config.certDnsSuffix();
this.providerService = config.serviceName();
this.ztsUrl = config.ztsUrl();
+ this.providerDomain = config.domain();
}
public String generateSignedIdentityDocument(String hostname) {
@@ -59,7 +60,7 @@ public class IdentityDocumentGenerator {
SignedIdentityDocument.DEFAULT_KEY_VERSION,
identityDocument.providerUniqueId.asString(),
dnsSuffix,
- providerService,
+ providerDomain + "." + providerService,
ztsUrl,
SignedIdentityDocument.DEFAILT_DOCUMENT_VERSION
);
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/SystemStateBroadcaster.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/SystemStateBroadcaster.java
index 5c035a0d5a7..024c5d21607 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/SystemStateBroadcaster.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/SystemStateBroadcaster.java
@@ -134,6 +134,7 @@ public class SystemStateBroadcaster {
if (systemState == null) return false;
if (!systemState.isOfficial()) {
+ log.log(LogLevel.INFO, String.format("Publishing cluster state version %d", systemState.getVersion()));
systemState.setOfficial(true);
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java
index b02d17a9372..46d007126c0 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java
@@ -37,7 +37,7 @@ public class TenantHandler extends HttpHandler {
protected HttpResponse handlePUT(HttpRequest request) {
TenantName tenantName = getAndValidateTenantFromRequest(request);
try {
- tenants.writeTenantPath(tenantName);
+ tenants.addTenant(tenantName);
} catch (Exception e) {
throw new InternalServerException(Exceptions.toMessageString(e));
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java
index 3ad920bbff2..cf05440a1d2 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Tenants.java
@@ -28,7 +28,6 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -42,7 +41,7 @@ import java.util.logging.Logger;
* implemented support for it).
*
* This instance is called from two different threads, the http handler threads and the zookeeper watcher threads.
- * To create or delete a tenant, the handler calls {@link Tenants#writeTenantPath} and {@link Tenants#deleteTenant} methods.
+ * To create or delete a tenant, the handler calls {@link Tenants#addTenant} and {@link Tenants#deleteTenant} methods.
* This will delete shared state from zookeeper, and return, so it does not mean a tenant is immediately deleted.
*
* Once a tenant is deleted from zookeeper, the zookeeper watcher thread will get notified on all configservers, and
@@ -73,14 +72,13 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen
/**
- * New instance from the tenants in the given component registry's ZooKeeper. Will set watch when reading them.
+ * New instance from the tenants in the given component registry's ZooKeeper data.
*
* @param globalComponentRegistry a {@link com.yahoo.vespa.config.server.GlobalComponentRegistry}
* @throws Exception is creating the Tenants instance fails
*/
@Inject
public Tenants(GlobalComponentRegistry globalComponentRegistry, Metrics metrics) throws Exception {
- // Note: unit tests may want to use the constructor below to avoid setting watch by calling readTenants().
this.globalComponentRegistry = globalComponentRegistry;
this.curator = globalComponentRegistry.getCurator();
metricUpdater = metrics.getOrCreateMetricUpdater(Collections.emptyMap());
@@ -94,12 +92,12 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen
this.directoryCache = curator.createDirectoryCache(tenantsPath.getAbsolute(), false, false, pathChildrenExecutor);
directoryCache.start();
directoryCache.addListener(this);
- tenantsChanged(readTenants());
+ createTenants();
notifyTenantsLoaded();
}
/**
- * New instance containing the given tenants. This will not watch in ZooKeeper.
+ * New instance containing the given tenants. This will not create Zookeeper watches. For testing only
* @param globalComponentRegistry a {@link com.yahoo.vespa.config.server.GlobalComponentRegistry} instance
* @param metrics a {@link com.yahoo.vespa.config.server.monitoring.Metrics} instance
* @param tenants a collection of {@link Tenant}s
@@ -131,9 +129,9 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen
return sessionTenants;
}
- public synchronized void addTenant(Tenant tenant) {
- tenants.put(tenant.getName(), tenant);
- metricUpdater.setTenants(tenants.size());
+ public synchronized void addTenant(TenantName tenantName) throws Exception {
+ writeTenantPath(tenantName);
+ createTenant(tenantName);
}
/**
@@ -141,7 +139,7 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen
*
* @return a set of tenant names
*/
- private Set<TenantName> readTenants() {
+ private Set<TenantName> readTenantsFromZooKeeper() {
Set<TenantName> tenants = new LinkedHashSet<>();
for (String tenant : curator.getChildren(tenantsPath)) {
tenants.add(TenantName.from(tenant));
@@ -149,10 +147,11 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen
return tenants;
}
- synchronized void tenantsChanged(Set<TenantName> newTenants) throws Exception {
- log.log(LogLevel.DEBUG, "Tenants changed: " + newTenants);
- checkForRemovedTenants(newTenants);
- checkForAddedTenants(newTenants);
+ synchronized void createTenants() throws Exception {
+ Set<TenantName> allTenants = readTenantsFromZooKeeper();
+ log.log(LogLevel.DEBUG, "Create tenants, tenants found in zookeeper: " + allTenants);
+ checkForRemovedTenants(allTenants);
+ checkForAddedTenants(allTenants);
metricUpdater.setTenants(tenants.size());
}
@@ -170,24 +169,26 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen
private void checkForAddedTenants(Set<TenantName> newTenants) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(globalComponentRegistry.getConfigserverConfig().numParallelTenantLoaders());
- Map<TenantName, Tenant> addedTenants = new ConcurrentHashMap<>();
for (TenantName tenantName : newTenants) {
// Note: the http handler will check if the tenant exists, and throw accordingly
if (!tenants.containsKey(tenantName)) {
executor.execute(() -> {
- try {
- Tenant tenant = TenantBuilder.create(globalComponentRegistry, tenantName, getTenantPath(tenantName)).build();
- notifyNewTenant(tenant);
- addedTenants.put(tenantName, tenant);
- } catch (Exception e) {
- log.log(LogLevel.WARNING, "Error loading tenant '" + tenantName + "', skipping.", e);
- }
+ createTenant(tenantName);
});
}
}
executor.shutdown();
executor.awaitTermination(365, TimeUnit.DAYS); // Timeout should never happen
- tenants.putAll(addedTenants);
+ }
+
+ private void createTenant(TenantName tenantName) {
+ try {
+ Tenant tenant = TenantBuilder.create(globalComponentRegistry, tenantName, getTenantPath(tenantName)).build();
+ notifyNewTenant(tenant);
+ tenants.put(tenantName, tenant);
+ } catch (Exception e) {
+ log.log(LogLevel.WARNING, "Error loading tenant '" + tenantName + "', skipping.", e);
+ }
}
/**
@@ -239,7 +240,7 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen
* @param name name of the tenant
* @return this Tenants
*/
- public synchronized Tenants writeTenantPath(TenantName name) {
+ synchronized Tenants writeTenantPath(TenantName name) {
Path tenantPath = getTenantPath(name);
curator.createAtomically(tenantPath, tenantPath.append(Tenant.SESSIONS), tenantPath.append(Tenant.APPLICATIONS));
return this;
@@ -316,7 +317,7 @@ public class Tenants implements ConnectionStateListener, PathChildrenCacheListen
switch (event.getType()) {
case CHILD_ADDED:
case CHILD_REMOVED:
- tenantsChanged(readTenants());
+ createTenants();
break;
}
}
diff --git a/configserver/src/main/resources/configserver-app/services.xml b/configserver/src/main/resources/configserver-app/services.xml
index cd2aa6033db..602b4793f6e 100644
--- a/configserver/src/main/resources/configserver-app/services.xml
+++ b/configserver/src/main/resources/configserver-app/services.xml
@@ -43,8 +43,8 @@
<preprocess:include file='config-models.xml' required='false' />
<preprocess:include file='node-repository.xml' required='false' />
<preprocess:include file='hosted-vespa/routing-status.xml' required='false' />
- <component id="com.yahoo.vespa.service.monitor.SlobrokMonitorManagerImpl" bundle="orchestrator" />
- <component id="com.yahoo.vespa.service.monitor.ServiceMonitorImpl" bundle="orchestrator" />
+ <component id="com.yahoo.vespa.service.monitor.internal.SlobrokMonitorManagerImpl" bundle="orchestrator" />
+ <component id="com.yahoo.vespa.service.monitor.internal.ServiceMonitorImpl" bundle="orchestrator" />
<component id="com.yahoo.vespa.orchestrator.ServiceMonitorInstanceLookupService" bundle="orchestrator" />
<component id="com.yahoo.vespa.orchestrator.status.ZookeeperStatusService" bundle="orchestrator" />
<component id="com.yahoo.vespa.orchestrator.controller.RetryingClusterControllerClientFactory" bundle="orchestrator" />
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java
index 88d7177a51e..e0d65055f21 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java
@@ -47,9 +47,9 @@ public class ConfigServerBootstrapTest extends TestWithTenant {
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@Before
- public void setup() {
- tenants.writeTenantPath(tenant1);
- tenants.writeTenantPath(tenant2);
+ public void setup() throws Exception {
+ tenants.addTenant(tenant1);
+ tenants.addTenant(tenant2);
applicationRepository = new ApplicationRepository(tenants,
new SessionHandlerTest.MockProvisioner(),
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java
index afe51adee20..892c821950e 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java
@@ -24,8 +24,6 @@ import com.yahoo.vespa.config.server.TestComponentRegistry;
import com.yahoo.vespa.config.server.application.ApplicationConvergenceChecker;
import com.yahoo.vespa.config.server.application.HttpProxy;
import com.yahoo.vespa.config.server.application.LogServerLogGrabber;
-import com.yahoo.vespa.config.server.application.TenantApplications;
-import com.yahoo.vespa.config.server.application.ZKTenantApplications;
import com.yahoo.vespa.config.server.http.HandlerTest;
import com.yahoo.vespa.config.server.http.HttpErrorResponse;
import com.yahoo.vespa.config.server.http.StaticResponse;
@@ -40,7 +38,6 @@ import com.yahoo.vespa.config.server.session.RemoteSession;
import com.yahoo.vespa.config.server.session.SessionContext;
import com.yahoo.vespa.config.server.session.SessionZooKeeperClient;
import com.yahoo.vespa.config.server.tenant.Tenant;
-import com.yahoo.vespa.config.server.tenant.TenantBuilder;
import com.yahoo.vespa.config.server.tenant.Tenants;
import com.yahoo.vespa.curator.mock.MockCurator;
import com.yahoo.vespa.model.VespaModelFactory;
@@ -279,7 +276,7 @@ public class ApplicationHandlerTest {
tenant.getRemoteSessionRepo().addSession(new RemoteSession(tenant.getName(), sessionId, componentRegistry, new MockSessionZKClient(app), clock));
}
- static Tenants addApplication(ApplicationId applicationId, long sessionId) throws Exception {
+ private static Tenants addApplication(ApplicationId applicationId, long sessionId) throws Exception {
// This method is a good illustration of the spaghetti wiring resulting from no design
// TODO: When this setup looks sane we have refactored sufficiently that there is a design
@@ -289,18 +286,15 @@ public class ApplicationHandlerTest {
Path sessionPath = tenantPath.append(Tenant.SESSIONS).append(String.valueOf(sessionId));
MockCurator curator = new MockCurator();
- GlobalComponentRegistry globalComponents = new TestComponentRegistry.Builder().curator(curator).build();
+ GlobalComponentRegistry componentRegistry = new TestComponentRegistry.Builder()
+ .curator(curator)
+ .modelFactoryRegistry(new ModelFactoryRegistry(
+ Collections.singletonList(new VespaModelFactory(new NullConfigModelRegistry()))))
+ .build();
- Tenants tenants = new Tenants(globalComponents, Metrics.createTestMetrics()); // Creates the application path element in zk
- tenants.writeTenantPath(tenantName);
- TenantApplications tenantApplications = ZKTenantApplications.create(curator,
- tenantPath.append(Tenant.APPLICATIONS),
- new MockReloadHandler(), // TODO: Use the real one
- tenantName);
- Tenant tenant = TenantBuilder.create(globalComponents, applicationId.tenant(), tenantPath)
- .withApplicationRepo(tenantApplications)
- .build();
- tenants.addTenant(tenant);
+ Tenants tenants = new Tenants(componentRegistry, Metrics.createTestMetrics()); // Creates the application path element in zk
+ tenants.addTenant(tenantName);
+ Tenant tenant = tenants.getTenant(tenantName);
tenant.getApplicationRepo().createPutApplicationTransaction(applicationId, sessionId).commit();
ApplicationPackage app = FilesApplicationPackage.fromFile(testApp);
@@ -317,11 +311,7 @@ public class ApplicationHandlerTest {
tenant.getRemoteSessionRepo().addSession(
new RemoteSession(tenantName, sessionId,
- new TestComponentRegistry.Builder()
- .curator(curator)
- .modelFactoryRegistry(new ModelFactoryRegistry(
- Collections.singletonList(new VespaModelFactory(new NullConfigModelRegistry()))))
- .build(),
+ componentRegistry,
sessionClient,
Clock.systemUTC()));
return tenants;
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListTenantsTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListTenantsTest.java
index 189314577e4..aa27dd0783c 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListTenantsTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListTenantsTest.java
@@ -19,9 +19,9 @@ public class ListTenantsTest extends TenantTest {
@Test
public void testListTenants() throws Exception {
- tenants.writeTenantPath(a);
- tenants.writeTenantPath(b);
- tenants.writeTenantPath(c);
+ tenants.addTenant(a);
+ tenants.addTenant(b);
+ tenants.addTenant(c);
ListTenantsHandler listTenantsHandler = new ListTenantsHandler(testExecutor(), null, tenants);
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantHandlerTest.java
index cf79770ad20..ca545611e7f 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/TenantHandlerTest.java
@@ -54,7 +54,7 @@ public class TenantHandlerTest extends TenantTest {
@Test
public void testGetExisting() throws Exception {
- tenants.writeTenantPath(a);
+ tenants.addTenant(a);
TenantGetResponse response = (TenantGetResponse) handler.handleGET(
HttpRequest.createTestRequest("http://deploy.example.yahoo.com:80/application/v2/tenant/a", Method.GET));
assertResponseEquals(response, "{\"message\":\"Tenant 'a' exists.\"}");
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantsTestCase.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantsTestCase.java
index a77b7615e6d..ce16ac14f60 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantsTestCase.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantsTestCase.java
@@ -3,8 +3,6 @@ package com.yahoo.vespa.config.server.tenant;
import com.yahoo.config.model.test.MockApplicationPackage;
import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.ApplicationName;
-import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.Version;
import com.yahoo.vespa.config.server.application.ApplicationSet;
@@ -12,7 +10,6 @@ import com.yahoo.vespa.config.server.ServerCache;
import com.yahoo.vespa.config.server.TestComponentRegistry;
import com.yahoo.vespa.config.server.TestWithCurator;
import com.yahoo.vespa.config.server.application.Application;
-import com.yahoo.vespa.config.server.deploy.MockDeployer;
import com.yahoo.vespa.config.server.monitoring.MetricUpdater;
import com.yahoo.vespa.config.server.monitoring.Metrics;
import com.yahoo.vespa.model.VespaModel;
@@ -52,8 +49,8 @@ public class TenantsTestCase extends TestWithCurator {
tenantListener.tenantsLoaded = false;
tenants = new Tenants(globalComponentRegistry, Metrics.createTestMetrics());
assertTrue(tenantListener.tenantsLoaded);
- tenants.writeTenantPath(tenant1);
- tenants.writeTenantPath(tenant2);
+ tenants.addTenant(tenant1);
+ tenants.addTenant(tenant2);
}
@After
@@ -79,7 +76,7 @@ public class TenantsTestCase extends TestWithCurator {
@Test
public void testTenantListenersNotified() throws Exception {
- tenants.writeTenantPath(tenant3);
+ tenants.addTenant(tenant3);
assertThat("tenant3 not the last created tenant. Tenants: " + tenants.getAllTenantNames() + ", /config/v2/tenants: " + readZKChildren("/config/v2/tenants"), tenantListener.tenantCreatedName, is(tenant3));
tenants.deleteTenant(tenant2);
assertFalse(tenants.getAllTenantNames().contains(tenant2));
@@ -91,7 +88,7 @@ public class TenantsTestCase extends TestWithCurator {
Set<TenantName> allTenants = tenants.getAllTenantNames();
assertTrue(allTenants.contains(tenant1));
assertTrue(allTenants.contains(tenant2));
- tenants.writeTenantPath(tenant3);
+ tenants.addTenant(tenant3);
allTenants = tenants.getAllTenantNames();
assertTrue(allTenants.contains(tenant1));
assertTrue(allTenants.contains(tenant2));
@@ -100,7 +97,7 @@ public class TenantsTestCase extends TestWithCurator {
@Test
public void testPutAdd() throws Exception {
- tenants.writeTenantPath(tenant3);
+ tenants.addTenant(tenant3);
assertNotNull(globalComponentRegistry.getCurator().framework().checkExists().forPath(tenants.tenantZkPath(tenant3)));
}
@@ -115,29 +112,28 @@ public class TenantsTestCase extends TestWithCurator {
public void testTenantsChanged() throws Exception {
tenants.close(); // close the Tenants instance created in setupSession, we do not want to use one with a PatchChildrenCache listener
tenants = new Tenants(globalComponentRegistry, Metrics.createTestMetrics(), new ArrayList<>());
- Set<TenantName> newTenants = new LinkedHashSet<>();
TenantName defaultTenant = TenantName.defaultName();
- newTenants.add(tenant2);
- newTenants.add(defaultTenant);
- tenants.tenantsChanged(newTenants);
+ tenants.writeTenantPath(tenant2);
+ tenants.writeTenantPath(defaultTenant);
+ tenants.createTenants();
Set<TenantName> allTenants = tenants.getAllTenantNames();
assertTrue(allTenants.contains(tenant2));
assertEquals("default", defaultTenant.value());
assertTrue(allTenants.contains(defaultTenant));
- assertFalse(allTenants.contains(tenant1));
- newTenants.clear();
- tenants.tenantsChanged(newTenants);
+ tenants.deleteTenant(tenant1);
+ tenants.deleteTenant(tenant2);
+ tenants.deleteTenant(defaultTenant);
+ tenants.createTenants();
allTenants = tenants.getAllTenantNames();
assertFalse(allTenants.contains(tenant1));
assertFalse(allTenants.contains(tenant2));
assertFalse(allTenants.contains(defaultTenant));
- newTenants.clear();
TenantName foo = TenantName.from("foo");
TenantName bar = TenantName.from("bar");
- newTenants.add(tenant2);
- newTenants.add(foo);
- newTenants.add(bar);
- tenants.tenantsChanged(newTenants);
+ tenants.writeTenantPath(tenant2);
+ tenants.writeTenantPath(foo);
+ tenants.writeTenantPath(bar);
+ tenants.createTenants();
allTenants = tenants.getAllTenantNames();
assertTrue(allTenants.contains(tenant2));
assertTrue(allTenants.contains(foo));
diff --git a/container-di/src/main/scala/com/yahoo/container/di/Container.scala b/container-di/src/main/scala/com/yahoo/container/di/Container.scala
index c82625bae3b..c6812c52242 100644
--- a/container-di/src/main/scala/com/yahoo/container/di/Container.scala
+++ b/container-di/src/main/scala/com/yahoo/container/di/Container.scala
@@ -183,6 +183,9 @@ class Container(
val graph = new ComponentGraph(generation)
val componentsConfig = getConfig(componentsConfigKey, configsIncludingBootstrapConfigs)
+ if (componentsConfig == null)
+ throw new ConfigurationRuntimeException(
+ "The set of all configs does not include a valid 'components' config. Config set: " + configsIncludingBootstrapConfigs.keySet)
addNodes(componentsConfig, graph)
injectNodes(componentsConfig, graph)
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/ErrorResponse.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/ErrorResponse.java
index a9643e21c00..4af833baa98 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/ErrorResponse.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/ErrorResponse.java
@@ -11,6 +11,7 @@ import static com.yahoo.jdisc.Response.Status.FORBIDDEN;
import static com.yahoo.jdisc.Response.Status.INTERNAL_SERVER_ERROR;
import static com.yahoo.jdisc.Response.Status.METHOD_NOT_ALLOWED;
import static com.yahoo.jdisc.Response.Status.NOT_FOUND;
+import static com.yahoo.jdisc.Response.Status.UNAUTHORIZED;
/**
* A HTTP JSON response containing an error code and a message
@@ -24,7 +25,8 @@ public class ErrorResponse extends SlimeJsonResponse {
BAD_REQUEST,
FORBIDDEN,
METHOD_NOT_ALLOWED,
- INTERNAL_SERVER_ERROR
+ INTERNAL_SERVER_ERROR,
+ UNAUTHORIZED
}
public ErrorResponse(int statusCode, String errorType, String message) {
@@ -55,6 +57,10 @@ public class ErrorResponse extends SlimeJsonResponse {
return new ErrorResponse(FORBIDDEN, errorCodes.FORBIDDEN.name(), message);
}
+ public static ErrorResponse unauthorized(String message) {
+ return new ErrorResponse(UNAUTHORIZED, errorCodes.UNAUTHORIZED.name(), message);
+ }
+
public static ErrorResponse methodNotAllowed(String message) {
return new ErrorResponse(METHOD_NOT_ALLOWED, errorCodes.METHOD_NOT_ALLOWED.name(), message);
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index a6d9f4c5d33..a259e221a1e 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -67,7 +67,6 @@ import com.yahoo.vespa.hosted.controller.application.DeploymentMetrics;
import com.yahoo.vespa.hosted.controller.application.JobStatus;
import com.yahoo.vespa.hosted.controller.application.SourceRevision;
import com.yahoo.vespa.hosted.controller.athenz.AthenzClientFactory;
-import com.yahoo.vespa.hosted.controller.athenz.AthenzPrincipal;
import com.yahoo.vespa.hosted.controller.athenz.NToken;
import com.yahoo.vespa.hosted.controller.athenz.ZmsException;
import com.yahoo.vespa.hosted.controller.restapi.ErrorResponse;
@@ -82,6 +81,7 @@ import com.yahoo.yolean.Exceptions;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.ForbiddenException;
+import javax.ws.rs.NotAuthorizedException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
@@ -140,6 +140,9 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
catch (ForbiddenException e) {
return ErrorResponse.forbidden(Exceptions.toMessageString(e));
}
+ catch (NotAuthorizedException e) {
+ return ErrorResponse.unauthorized(Exceptions.toMessageString(e));
+ }
catch (NotExistsException e) {
return ErrorResponse.notFoundError(Exceptions.toMessageString(e));
}
@@ -780,25 +783,8 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
DeployAuthorizer deployAuthorizer = new DeployAuthorizer(controller.zoneRegistry(), athenzClientFactory);
Tenant tenant = controller.tenants().tenant(new TenantId(tenantName)).orElseThrow(() -> new NotExistsException(new TenantId(tenantName)));
Principal principal = authorizer.getPrincipal(request);
- if (principal instanceof AthenzPrincipal) {
- deployAuthorizer.throwIfUnauthorizedForDeploy(principal,
- Environment.from(environment),
- tenant,
- applicationId);
- } else { // In case of host-based principal
- // TODO What about other user type principals like Bouncer?
- log.log(LogLevel.WARNING,
- "Using deprecated DeployAuthorizer.throwIfUnauthorizedForDeploy. Principal=" + principal);
- UserId userId = new UserId(principal.getName());
- deployAuthorizer.throwIfUnauthorizedForDeploy(
- Environment.from(environment),
- userId,
- tenant,
- applicationId,
- optional("screwdriverBuildJob", deployOptions).map(ScrewdriverId::new));
- }
+ deployAuthorizer.throwIfUnauthorizedForDeploy(principal, Environment.from(environment), tenant, applicationId);
-
// TODO: get rid of the json object
DeployOptions deployOptionsJsonClass = new DeployOptions(screwdriverBuildJobFromSlime(deployOptions.field("screwdriverBuildJob")),
optional("vespaVersion", deployOptions).map(Version::new),
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/Authorizer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/Authorizer.java
index 93dc2541385..0c808e30c2a 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/Authorizer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/Authorizer.java
@@ -1,7 +1,6 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.restapi.application;
-import com.google.common.collect.ImmutableSet;
import com.yahoo.config.provision.Environment;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.vespa.hosted.controller.Controller;
@@ -12,19 +11,16 @@ import com.yahoo.vespa.hosted.controller.api.identifiers.UserGroup;
import com.yahoo.vespa.hosted.controller.api.identifiers.UserId;
import com.yahoo.vespa.hosted.controller.api.integration.entity.EntityService;
import com.yahoo.vespa.hosted.controller.athenz.AthenzClientFactory;
-import com.yahoo.vespa.hosted.controller.athenz.AthenzPrincipal;
import com.yahoo.vespa.hosted.controller.athenz.AthenzUtils;
import com.yahoo.vespa.hosted.controller.athenz.NToken;
import com.yahoo.vespa.hosted.controller.common.ContextAttributes;
import com.yahoo.vespa.hosted.controller.restapi.filter.NTokenRequestFilter;
-import com.yahoo.vespa.hosted.controller.restapi.filter.UnauthenticatedUserPrincipal;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.SecurityContext;
import java.security.Principal;
import java.util.Optional;
-import java.util.Set;
import java.util.logging.Logger;
@@ -41,11 +37,6 @@ public class Authorizer {
// Must be kept in sync with bouncer filter configuration.
private static final String VESPA_HOSTED_ADMIN_ROLE = "10707.A";
- private static final Set<UserId> SCREWDRIVER_USERS = ImmutableSet.of(new UserId("screwdrv"),
- new UserId("screwdriver"),
- new UserId("sdrvtest"),
- new UserId("screwdriver-test"));
-
private final Controller controller;
private final AthenzClientFactory athenzClientFactory;
private final EntityService entityService;
@@ -92,17 +83,8 @@ public class Authorizer {
}
public boolean isSuperUser(HttpRequest request) {
- // TODO Check membership of admin role in Vespa's Athenz domain
- return isMemberOfVespaBouncerGroup(request) || isScrewdriverPrincipal(getPrincipal(request));
- }
-
- public static boolean isScrewdriverPrincipal(Principal principal) {
- if (principal instanceof UnauthenticatedUserPrincipal) // Host-based authentication
- return SCREWDRIVER_USERS.contains(new UserId(principal.getName()));
- else if (principal instanceof AthenzPrincipal)
- return ((AthenzPrincipal)principal).getDomain().equals(AthenzUtils.SCREWDRIVER_DOMAIN);
- else
- return false;
+ // TODO Replace check with membership of a dedicated 'hosted Vespa super-user' role in Vespa's Athenz domain
+ return isMemberOfVespaBouncerGroup(request);
}
private static ForbiddenException loggedForbiddenException(String message, Object... args) {
@@ -149,6 +131,8 @@ public class Authorizer {
return method.equals(HttpMethod.GET) || method.equals(HttpMethod.HEAD) || method.equals(HttpMethod.OPTIONS);
}
+ @Deprecated
+ // TODO Remove this method. Stop using Bouncer for authorization and use Athenz instead
private boolean isMemberOfVespaBouncerGroup(HttpRequest request) {
Optional<SecurityContext> securityContext = securityContextOf(request);
if ( ! securityContext.isPresent() ) throw Authorizer.loggedForbiddenException("User is not authenticated");
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/DeployAuthorizer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/DeployAuthorizer.java
index 7cf19629774..71126259417 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/DeployAuthorizer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/DeployAuthorizer.java
@@ -5,23 +5,19 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Environment;
import com.yahoo.vespa.hosted.controller.api.Tenant;
import com.yahoo.vespa.hosted.controller.api.identifiers.AthenzDomain;
-import com.yahoo.vespa.hosted.controller.api.identifiers.ScrewdriverId;
-import com.yahoo.vespa.hosted.controller.api.identifiers.UserId;
import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry;
import com.yahoo.vespa.hosted.controller.athenz.ApplicationAction;
import com.yahoo.vespa.hosted.controller.athenz.AthenzClientFactory;
import com.yahoo.vespa.hosted.controller.athenz.AthenzPrincipal;
import com.yahoo.vespa.hosted.controller.athenz.AthenzUtils;
import com.yahoo.vespa.hosted.controller.athenz.ZmsException;
-import com.yahoo.vespa.hosted.controller.restapi.filter.UnauthenticatedUserPrincipal;
import javax.ws.rs.ForbiddenException;
+import javax.ws.rs.NotAuthorizedException;
import java.security.Principal;
-import java.util.Optional;
import java.util.logging.Logger;
import static com.yahoo.vespa.hosted.controller.restapi.application.Authorizer.environmentRequiresAuthorization;
-import static com.yahoo.vespa.hosted.controller.restapi.application.Authorizer.isScrewdriverPrincipal;
/**
* @author bjorncs
@@ -43,36 +39,40 @@ public class DeployAuthorizer {
Environment environment,
Tenant tenant,
ApplicationId applicationId) {
- if (athenzCredentialsRequired(environment, tenant, applicationId, principal))
- checkAthenzCredentials(principal, tenant, applicationId);
- }
-
- // TODO: inline when deployment via ssh is removed
- private boolean athenzCredentialsRequired(Environment environment, Tenant tenant, ApplicationId applicationId, Principal principal) {
- if (!environmentRequiresAuthorization(environment)) return false;
-
- if (! isScrewdriverPrincipal(principal))
- throw loggedForbiddenException(
- "Principal '%s' is not a screwdriver principal, and does not have deploy access to application '%s'",
- principal.getName(), applicationId.toShortString());
+ if (!environmentRequiresAuthorization(environment)) {
+ return;
+ }
- return tenant.isAthensTenant();
- }
+ if (principal == null) {
+ throw loggedUnauthorizedException("Principal not authenticated!");
+ }
+ if (!(principal instanceof AthenzPrincipal)) {
+ throw loggedUnauthorizedException(
+ "Principal '%s' of type '%s' is not an Athenz principal, which is required for production deployments.",
+ principal.getName(), principal.getClass().getSimpleName());
+ }
- // TODO: inline when deployment via ssh is removed
- private void checkAthenzCredentials(Principal principal, Tenant tenant, ApplicationId applicationId) {
- AthenzDomain domain = tenant.getAthensDomain().get();
- if (! (principal instanceof AthenzPrincipal))
- throw loggedForbiddenException("Principal '%s' is not authenticated.", principal.getName());
+ AthenzPrincipal athenzPrincipal = (AthenzPrincipal) principal;
+ AthenzDomain principalDomain = athenzPrincipal.getDomain();
- AthenzPrincipal athensPrincipal = (AthenzPrincipal)principal;
- if ( ! hasDeployAccessToAthenzApplication(athensPrincipal, domain, applicationId))
+ if (!principalDomain.equals(AthenzUtils.SCREWDRIVER_DOMAIN)) {
throw loggedForbiddenException(
- "Screwdriver principal '%1$s' does not have deploy access to '%2$s'. " +
- "Either the application has not been created at " + zoneRegistry.getDashboardUri() + " or " +
- "'%1$s' is not added to the application's deployer role in Athens domain '%3$s'.",
- athensPrincipal, applicationId, tenant.getAthensDomain().get());
+ "Principal '%s' is not a Screwdriver principal. Excepted principal with Athenz domain '%s', got '%s'.",
+ principal.getName(), AthenzUtils.SCREWDRIVER_DOMAIN.id(), principalDomain.id());
+ }
+
+ // NOTE: no fine-grained deploy authorization for non-Athenz tenants
+ if (tenant.isAthensTenant()) {
+ AthenzDomain tenantDomain = tenant.getAthensDomain().get();
+ if (!hasDeployAccessToAthenzApplication(athenzPrincipal, tenantDomain, applicationId)) {
+ throw loggedForbiddenException(
+ "Screwdriver principal '%1$s' does not have deploy access to '%2$s'. " +
+ "Either the application has not been created at " + zoneRegistry.getDashboardUri() + " or " +
+ "'%1$s' is not added to the application's deployer role in Athenz domain '%3$s'.",
+ athenzPrincipal.toYRN(), applicationId, tenantDomain.id());
+ }
+ }
}
private static ForbiddenException loggedForbiddenException(String message, Object... args) {
@@ -81,23 +81,10 @@ public class DeployAuthorizer {
return new ForbiddenException(formattedMessage);
}
- /**
- * @deprecated Only usable for ssh. Use the method that takes Principal instead of UserId and screwdriverId.
- */
- @Deprecated
- public void throwIfUnauthorizedForDeploy(Environment environment,
- UserId userId,
- Tenant tenant,
- ApplicationId applicationId,
- Optional<ScrewdriverId> optionalScrewdriverId) {
- Principal principal = new UnauthenticatedUserPrincipal(userId.id());
-
- if (athenzCredentialsRequired(environment, tenant, applicationId, principal)) {
- ScrewdriverId screwdriverId = optionalScrewdriverId.orElseThrow(
- () -> loggedForbiddenException("Screwdriver id must be provided when deploying from Screwdriver."));
- principal = AthenzUtils.createPrincipal(screwdriverId);
- checkAthenzCredentials(principal, tenant, applicationId);
- }
+ private static NotAuthorizedException loggedUnauthorizedException(String message, Object... args) {
+ String formattedMessage = String.format(message, args);
+ log.info(formattedMessage);
+ return new NotAuthorizedException(formattedMessage);
}
private boolean hasDeployAccessToAthenzApplication(AthenzPrincipal principal, AthenzDomain domain, ApplicationId applicationId) {
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
index b36a88ca1d4..eeeed08c2b8 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
@@ -577,7 +577,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
entity,
Request.Method.POST,
athenzUserDomain, "mytenant"),
- "{\"error-code\":\"FORBIDDEN\",\"message\":\"Principal 'mytenant' is not a screwdriver principal, and does not have deploy access to application 'tenant1.application1'\"}",
+ "{\"error-code\":\"FORBIDDEN\",\"message\":\"Principal 'mytenant' is not a Screwdriver principal. Excepted principal with Athenz domain 'cd.screwdriver.project', got 'domain1'.\"}",
403);
// Deleting an application for an Athens domain the user is not admin for is disallowed
diff --git a/eval/src/vespa/eval/eval/interpreted_function.cpp b/eval/src/vespa/eval/eval/interpreted_function.cpp
index 09cc2d57e80..82aa71893e1 100644
--- a/eval/src/vespa/eval/eval/interpreted_function.cpp
+++ b/eval/src/vespa/eval/eval/interpreted_function.cpp
@@ -98,6 +98,24 @@ void op_not_member(State &state, uint64_t) {
//-----------------------------------------------------------------------------
+void op_double_map(State &state, uint64_t param) {
+ state.replace(1, state.stash.create<DoubleValue>(to_map_fun(param)(state.peek(0).as_double())));
+}
+
+void op_double_mul(State &state, uint64_t) {
+ state.replace(2, state.stash.create<DoubleValue>(state.peek(1).as_double() * state.peek(0).as_double()));
+}
+
+void op_double_add(State &state, uint64_t) {
+ state.replace(2, state.stash.create<DoubleValue>(state.peek(1).as_double() + state.peek(0).as_double()));
+}
+
+void op_double_join(State &state, uint64_t param) {
+ state.replace(2, state.stash.create<DoubleValue>(to_join_fun(param)(state.peek(1).as_double(), state.peek(0).as_double())));
+}
+
+//-----------------------------------------------------------------------------
+
void op_tensor_map(State &state, uint64_t param) {
state.replace(1, state.engine.map(state.peek(0), to_map_fun(param), state.stash));
}
@@ -217,13 +235,25 @@ struct ProgramBuilder : public NodeVisitor, public NodeTraverser {
}
void make_map_op(const Node &node, map_fun_t function) {
- (void) node;
- program.emplace_back(op_tensor_map, to_param(function));
+ if (types.get_type(node).is_double()) {
+ program.emplace_back(op_double_map, to_param(function));
+ } else {
+ program.emplace_back(op_tensor_map, to_param(function));
+ }
}
void make_join_op(const Node &node, join_fun_t function) {
- (void) node;
- program.emplace_back(op_tensor_join, to_param(function));
+ if (types.get_type(node).is_double()) {
+ if (function == operation::Mul::f) {
+ program.emplace_back(op_double_mul);
+ } else if (function == operation::Add::f) {
+ program.emplace_back(op_double_add);
+ } else {
+ program.emplace_back(op_double_join, to_param(function));
+ }
+ } else {
+ program.emplace_back(op_tensor_join, to_param(function));
+ }
}
//-------------------------------------------------------------------------
diff --git a/eval/src/vespa/eval/eval/simple_tensor.cpp b/eval/src/vespa/eval/eval/simple_tensor.cpp
index 37d2e8747ef..75c170d48ba 100644
--- a/eval/src/vespa/eval/eval/simple_tensor.cpp
+++ b/eval/src/vespa/eval/eval/simple_tensor.cpp
@@ -542,6 +542,16 @@ SimpleTensor::SimpleTensor(const ValueType &type_in, Cells cells_in)
[](const auto &a, const auto &b){ return (a.address < b.address); });
}
+double
+SimpleTensor::as_double() const
+{
+ double sum = 0.0;
+ for (auto &cell: _cells) {
+ sum += cell.value;
+ }
+ return sum;
+}
+
std::unique_ptr<SimpleTensor>
SimpleTensor::map(map_fun_t function) const
{
diff --git a/eval/src/vespa/eval/eval/simple_tensor.h b/eval/src/vespa/eval/eval/simple_tensor.h
index 3de80483fb3..ec154ff969a 100644
--- a/eval/src/vespa/eval/eval/simple_tensor.h
+++ b/eval/src/vespa/eval/eval/simple_tensor.h
@@ -81,6 +81,7 @@ public:
SimpleTensor();
explicit SimpleTensor(double value);
SimpleTensor(const ValueType &type_in, Cells cells_in);
+ double as_double() const final override;
const ValueType &type() const { return _type; }
const Cells &cells() const { return _cells; }
std::unique_ptr<SimpleTensor> map(map_fun_t function) const;
diff --git a/eval/src/vespa/eval/eval/tensor.h b/eval/src/vespa/eval/eval/tensor.h
index ed17a47f775..57cd9abe1f5 100644
--- a/eval/src/vespa/eval/eval/tensor.h
+++ b/eval/src/vespa/eval/eval/tensor.h
@@ -30,6 +30,7 @@ public:
Tensor(Tensor &&) = delete;
Tensor &operator=(const Tensor &) = delete;
Tensor &operator=(Tensor &&) = delete;
+ virtual double as_double() const = 0;
const TensorEngine &engine() const { return _engine; }
virtual ~Tensor() {}
};
diff --git a/eval/src/vespa/eval/eval/value.cpp b/eval/src/vespa/eval/eval/value.cpp
index 2a0a80b8547..0118d95e5cb 100644
--- a/eval/src/vespa/eval/eval/value.cpp
+++ b/eval/src/vespa/eval/eval/value.cpp
@@ -8,6 +8,12 @@ namespace eval {
ErrorValue ErrorValue::instance;
+double
+TensorValue::as_double() const
+{
+ return _tensor->as_double();
+}
+
bool
TensorValue::equal(const Value &rhs) const
{
diff --git a/eval/src/vespa/eval/eval/value.h b/eval/src/vespa/eval/eval/value.h
index 42dddeef188..0d727db6b91 100644
--- a/eval/src/vespa/eval/eval/value.h
+++ b/eval/src/vespa/eval/eval/value.h
@@ -64,6 +64,7 @@ public:
TensorValue(const Tensor &value) : _tensor(&value), _stored() {}
TensorValue(std::unique_ptr<Tensor> value) : _tensor(value.get()), _stored(std::move(value)) {}
bool is_tensor() const override { return true; }
+ double as_double() const override;
const Tensor *as_tensor() const override { return _tensor; }
bool equal(const Value &rhs) const override;
ValueType type() const override;
diff --git a/eval/src/vespa/eval/tensor/tensor.h b/eval/src/vespa/eval/tensor/tensor.h
index 1f4d599ac18..3b3d7ce4a70 100644
--- a/eval/src/vespa/eval/tensor/tensor.h
+++ b/eval/src/vespa/eval/tensor/tensor.h
@@ -32,6 +32,7 @@ struct Tensor : public eval::Tensor
virtual ~Tensor() {}
virtual const eval::ValueType &getType() const = 0;
virtual double sum() const = 0;
+ virtual double as_double() const final override { return sum(); }
virtual Tensor::UP add(const Tensor &arg) const = 0;
virtual Tensor::UP subtract(const Tensor &arg) const = 0;
virtual Tensor::UP multiply(const Tensor &arg) const = 0;
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 46102a366d2..2432abcc2d4 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<ApplicationInstanceReference, ApplicationInstance> applications;
- ServiceModel(Map<ApplicationInstanceReference, ApplicationInstance> applications) {
+ public ServiceModel(Map<ApplicationInstanceReference, ApplicationInstance> applications) {
this.applications = Collections.unmodifiableMap(applications);
}
- Map<ApplicationInstanceReference, ApplicationInstance> getAllApplicationInstances() {
+ public Map<ApplicationInstanceReference, ApplicationInstance> getAllApplicationInstances() {
return applications;
}
- Optional<ApplicationInstance> getApplicationInstance(ApplicationInstanceReference reference) {
+ public Optional<ApplicationInstance> getApplicationInstance(ApplicationInstanceReference reference) {
return Optional.ofNullable(applications.get(reference));
}
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/internal/ConfigServerApplication.java
index 7a76c072076..ea86de2b442 100644
--- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ConfigServerApplication.java
+++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ConfigServerApplication.java
@@ -1,5 +1,5 @@
// 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;
+package com.yahoo.vespa.service.monitor.internal;
import com.yahoo.vespa.applicationmodel.ApplicationInstance;
import com.yahoo.vespa.applicationmodel.ApplicationInstanceId;
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/internal/ModelGenerator.java
index 9716846dea4..961d5701901 100644
--- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ModelGenerator.java
+++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ModelGenerator.java
@@ -1,5 +1,5 @@
// 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;
+package com.yahoo.vespa.service.monitor.internal;
import com.yahoo.config.model.api.ApplicationInfo;
import com.yahoo.config.model.api.HostInfo;
@@ -19,6 +19,8 @@ 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;
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/internal/ServiceMonitorImpl.java
index 5d2a9f296b4..282a0797912 100644
--- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceMonitorImpl.java
+++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/ServiceMonitorImpl.java
@@ -1,5 +1,5 @@
// 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;
+package com.yahoo.vespa.service.monitor.internal;
import com.google.inject.Inject;
import com.yahoo.cloud.config.ConfigserverConfig;
@@ -9,8 +9,8 @@ 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 com.yahoo.vespa.service.monitor.ServiceModel;
+import com.yahoo.vespa.service.monitor.ServiceMonitor;
import java.util.Collections;
import java.util.List;
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/internal/SlobrokMonitor.java
index 4da7b7c0e68..e0195e11759 100644
--- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitor.java
+++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitor.java
@@ -1,5 +1,5 @@
// 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;
+package com.yahoo.vespa.service.monitor.internal;
import com.yahoo.config.model.api.ApplicationInfo;
import com.yahoo.config.model.api.HostInfo;
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/internal/SlobrokMonitorManagerImpl.java
index becd7cf7ef6..801f4b05079 100644
--- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerImpl.java
+++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImpl.java
@@ -1,5 +1,5 @@
// 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;
+package com.yahoo.vespa.service.monitor.internal;
import com.google.inject.Inject;
import com.yahoo.config.model.api.ApplicationInfo;
@@ -11,6 +11,7 @@ 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;
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/internal/SuperModelListenerImpl.java
index 506a2f7d649..b44d73125bd 100644
--- a/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/SuperModelListenerImpl.java
+++ b/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImpl.java
@@ -1,5 +1,5 @@
// 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;
+package com.yahoo.vespa.service.monitor.internal;
import com.yahoo.config.model.api.ApplicationInfo;
import com.yahoo.config.model.api.SuperModel;
@@ -7,8 +7,7 @@ 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 com.yahoo.vespa.service.monitor.ServiceModel;
import java.util.List;
import java.util.function.Supplier;
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/internal/ConfigServerApplicationTest.java
index 8eebdbb611b..d00dca99116 100644
--- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ConfigServerApplicationTest.java
+++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ConfigServerApplicationTest.java
@@ -1,5 +1,5 @@
// 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;
+package com.yahoo.vespa.service.monitor.internal;
import com.yahoo.vespa.applicationmodel.ApplicationInstance;
import com.yahoo.vespa.applicationmodel.ServiceStatus;
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/internal/ExampleModel.java
index df9391a5ec9..fca1512e3ea 100644
--- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ExampleModel.java
+++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ExampleModel.java
@@ -1,5 +1,5 @@
// 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;
+package com.yahoo.vespa.service.monitor.internal;
import com.yahoo.config.model.api.ApplicationInfo;
import com.yahoo.config.model.api.HostInfo;
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/internal/ExampleModelTest.java
index bcd4eae1b4e..64ba2ba5097 100644
--- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ExampleModelTest.java
+++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ExampleModelTest.java
@@ -1,6 +1,6 @@
// 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;
+package com.yahoo.vespa.service.monitor.internal;
import com.yahoo.config.model.api.ApplicationInfo;
import com.yahoo.config.model.api.HostInfo;
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/internal/ModelGeneratorTest.java
index 1d8e2ad4ceb..cf07c39950c 100644
--- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/ModelGeneratorTest.java
+++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/ModelGeneratorTest.java
@@ -1,5 +1,5 @@
// 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;
+package com.yahoo.vespa.service.monitor.internal;
import com.yahoo.config.model.api.SuperModel;
import com.yahoo.config.provision.Environment;
@@ -10,6 +10,7 @@ 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;
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/internal/SlobrokMonitorManagerImplImplTest.java
index d21088ccbf4..79f927f6161 100644
--- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SlobrokMonitorManagerImplImplTest.java
+++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorManagerImplImplTest.java
@@ -1,5 +1,5 @@
// 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;
+package com.yahoo.vespa.service.monitor.internal;
import com.yahoo.config.model.api.ApplicationInfo;
import com.yahoo.config.model.api.SuperModel;
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/internal/SlobrokMonitorTest.java
index 2cbe48c7be5..075647e9c16 100644
--- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SlobrokMonitorTest.java
+++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SlobrokMonitorTest.java
@@ -1,5 +1,5 @@
// 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;
+package com.yahoo.vespa.service.monitor.internal;
import com.yahoo.config.model.api.ApplicationInfo;
import com.yahoo.jrt.slobrok.api.Mirror;
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/internal/SuperModelListenerImplTest.java
index e2aaf1c9838..6233f39b9cf 100644
--- a/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/SuperModelListenerImplTest.java
+++ b/service-monitor/src/test/java/com/yahoo/vespa/service/monitor/internal/SuperModelListenerImplTest.java
@@ -1,11 +1,11 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.service.monitor;
+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.internal.ServiceMonitorMetrics;
+import com.yahoo.vespa.service.monitor.ServiceModel;
import org.junit.Test;
import java.util.ArrayList;