// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.content; import com.yahoo.cloud.config.ClusterListConfig; import com.yahoo.config.model.deploy.DeployState; import com.yahoo.documentmodel.NewDocumentType; import com.yahoo.messagebus.routing.RoutingTableSpec; import com.yahoo.vespa.config.content.core.StorServerConfig; import com.yahoo.vespa.config.search.core.ProtonConfig; import com.yahoo.vespa.model.VespaModel; import com.yahoo.vespa.model.container.ApplicationContainerCluster; import com.yahoo.vespa.model.content.cluster.ContentCluster; import com.yahoo.vespa.model.routing.DocumentProtocol; import com.yahoo.vespa.model.routing.Routing; import com.yahoo.vespa.model.search.IndexedSearchCluster; import com.yahoo.vespa.model.test.utils.ApplicationPackageUtils; import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithMockPkg; import org.junit.jupiter.api.Test; import java.util.List; import static org.junit.jupiter.api.Assertions.*; /** * Test for using the content model to create indexed search clusters. */ public class IndexedTest extends ContentBaseTest { private String createVespaServices(String pre, List sdNames, String post, String mode) { StringBuilder retval = new StringBuilder(); retval.append(pre); for (String sdName : sdNames) { retval.append(""); } retval.append(post); return retval.toString(); } private String createProtonIndexedVespaServices(List sdNames) { String pre = "" + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " 1" + " " + " " + " 34" + " " + " " + " "; String post = " " + " " + " " + " " + "" + ""; return createVespaServices(pre, sdNames, post, "index"); } private String createProtonStreamingVespaServices(List sdNames) { String pre = "" + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " 1\n" + " " + " " + " " + " "; String post = " " + " " + " " + " " + "" + ""; return createVespaServices(pre, sdNames, post, "streaming"); } private VespaModel getIndexedVespaModel() { return getIndexedVespaModelCreator().create(); } private VespaModelCreatorWithMockPkg getIndexedVespaModelCreator() { List sds = ApplicationPackageUtils.generateSchemas("type1", "type2", "type3"); return new VespaModelCreatorWithMockPkg(getHosts(), createProtonIndexedVespaServices(List.of("type1", "type2", "type3")), sds); } private VespaModel getStreamingVespaModel() { List sds = ApplicationPackageUtils.generateSchemas("type1"); return new VespaModelCreatorWithMockPkg(getHosts(), createProtonStreamingVespaServices(List.of("type1")), sds).create(); } @Test void requireMultipleDocumentTypes() { VespaModelCreatorWithMockPkg creator = getIndexedVespaModelCreator(); VespaModel model = creator.create(); DeployState deployState = creator.deployState; IndexedSearchCluster cluster = model.getContentClusters().get("test").getSearch().getIndexed(); assertEquals(3, cluster.getDocumentDbs().size()); NewDocumentType type1 = deployState.getDocumentModel().getDocumentManager().getDocumentType("type1"); NewDocumentType type2 = deployState.getDocumentModel().getDocumentManager().getDocumentType("type2"); NewDocumentType type3 = deployState.getDocumentModel().getDocumentManager().getDocumentType("type3"); assertNotNull(type1); assertNotNull(type2); assertNotNull(type3); } @Test void requireIndexedOnlyServices() { VespaModel model = getIndexedVespaModel(); // TODO // HostResource h = model.getHostSystem().getHosts().get(0); // String [] expectedServices = {"logserver", "configserver", "adminserver", "slobrok", // "logd", "configproxy","config-sentinel", // "container", "fleetcontroller", // "storagenode", "searchnode", "distributor", "transactionlogserver"}; // DomContentBuilderTest.assertServices(h, expectedServices); Routing routing = model.getRouting(); assertNotNull(routing); assertEquals("[]", routing.getErrors().toString()); assertEquals(1, routing.getProtocols().size()); DocumentProtocol protocol = (DocumentProtocol) routing.getProtocols().get(0); RoutingTableSpec spec = protocol.getRoutingTableSpec(); assertEquals(2, spec.getNumHops()); assertEquals("container/chain.indexing", spec.getHop(0).getName()); assertEquals("indexing", spec.getHop(1).getName()); assertRoute(spec.getRoute(0), "default", "indexing"); assertRoute(spec.getRoute(1), "default-get", "[Content:cluster=test]"); assertRoute(spec.getRoute(2), "storage/cluster.test", "route:test"); assertRoute(spec.getRoute(3), "test", "[MessageType:test]"); assertRoute(spec.getRoute(4), "test-direct", "[Content:cluster=test]"); assertRoute(spec.getRoute(5), "test-index", "container/chain.indexing", "[Content:cluster=test]"); } @Test void requireProtonStreamingOnly() { VespaModel model = getStreamingVespaModel(); // TODO // HostResource h = model.getHostSystem().getHosts().get(0); // String [] expectedServices = {"logserver", "configserver", "adminserver", "slobrok", // "logd", "configproxy","config-sentinel", // "container", "storagenode", "searchnode", "distributor", // "transactionlogserver"}; // DomContentBuilderTest.assertServices(h, expectedServices); ContentCluster s = model.getContentClusters().get("test"); StorServerConfig.Builder builder = new StorServerConfig.Builder(); s.getStorageCluster().getConfig(builder); s.getStorageCluster().getChildren().get("3").getConfig(builder); } @Test void requireCorrectClusterList() { VespaModel model = getStreamingVespaModel(); ContentCluster s = model.getContentClusters().get("test"); assertNotNull(s); ClusterListConfig config = model.getConfig(ClusterListConfig.class, VespaModel.ROOT_CONFIGID); assertEquals(1, config.storage().size()); assertEquals("test", config.storage(0).name()); assertEquals("test", config.storage(0).configid()); } @Test void testContentSummaryStore() { String services = "" + "" + "\n" + " 1\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " 1\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " 2048\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " "; List sds = ApplicationPackageUtils.generateSchemas("docstorebench"); VespaModel model = new VespaModelCreatorWithMockPkg(getHosts(), services, sds).create(); ProtonConfig.Builder pb = new ProtonConfig.Builder(); model.getConfig(pb, "docstore/search/cluster.docstore/0"); } @Test void testMixedIndexAndStoreOnly() { String services = "" + " " + " " + " 1" + " " + " " + " " + " " + " " + " " + " " + " " + ""; List sds = ApplicationPackageUtils.generateSchemas("index_me", "store_me"); VespaModel model = new VespaModelCreatorWithMockPkg(getHosts(), services, sds).create(); ProtonConfig.Builder pb = new ProtonConfig.Builder(); model.getConfig(pb, "docstore/search/cluster.docstore/0"); ProtonConfig protonConfig = new ProtonConfig(pb); assertEquals(2, protonConfig.documentdb().size()); assertEquals("index_me", protonConfig.documentdb(0).inputdoctypename()); assertEquals("docstore/search/cluster.docstore/index_me", protonConfig.documentdb(0).configid()); assertEquals("store_me", protonConfig.documentdb(1).inputdoctypename()); assertEquals("docstore/search", protonConfig.documentdb(1).configid()); } @Test void requireThatIndexingDocprocGetsConfigIdBasedOnDistributionKey() { VespaModel model = getIndexedVespaModel(); ApplicationContainerCluster cluster = model.getContainerClusters().get("container"); assertEquals("container/container.0", cluster.getContainers().get(0).getConfigId()); } }