com.yahoo.config.model.ApplicationConfigProducerRoot Maven / Gradle / Ivy
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.config.model;
import com.yahoo.cloud.config.ApplicationIdConfig;
import com.yahoo.cloud.config.ClusterListConfig;
import com.yahoo.cloud.config.ModelConfig;
import com.yahoo.cloud.config.ModelConfig.Hosts;
import com.yahoo.cloud.config.ModelConfig.Hosts.Services;
import com.yahoo.cloud.config.ModelConfig.Hosts.Services.Ports;
import com.yahoo.cloud.config.SlobroksConfig;
import com.yahoo.cloud.config.ZookeepersConfig;
import com.yahoo.cloud.config.log.LogdConfig;
import com.yahoo.component.Version;
import com.yahoo.config.model.api.ModelContext;
import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.config.model.producer.AnyConfigProducer;
import com.yahoo.config.model.producer.TreeConfigProducer;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.document.config.DocumenttypesConfig;
import com.yahoo.document.config.DocumentmanagerConfig;
import com.yahoo.documentapi.messagebus.protocol.DocumentrouteselectorpolicyConfig;
import com.yahoo.documentapi.messagebus.protocol.DocumentProtocolPoliciesConfig;
import com.yahoo.messagebus.MessagebusConfig;
import com.yahoo.vespa.config.content.AllClustersBucketSpacesConfig;
import com.yahoo.vespa.config.content.DistributionConfig;
import com.yahoo.vespa.configmodel.producers.DocumentManager;
import com.yahoo.vespa.configmodel.producers.DocumentTypes;
import com.yahoo.vespa.documentmodel.DocumentModel;
import com.yahoo.vespa.model.ConfigProducer;
import com.yahoo.vespa.model.HostResource;
import com.yahoo.vespa.model.HostSystem;
import com.yahoo.vespa.model.PortsMeta;
import com.yahoo.vespa.model.Service;
import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.admin.Admin;
import com.yahoo.vespa.model.content.cluster.ContentCluster;
import com.yahoo.vespa.model.routing.Routing;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* This is the parent of all ConfigProducers in the system resulting from configuring an application.
*
* @author gjoranv
*/
public class ApplicationConfigProducerRoot extends TreeConfigProducer implements CommonConfigsProducer {
private final DocumentModel documentModel;
private Routing routing = null;
// The ConfigProducers contained in this Vespa. (configId->producer)
Map id2producer = new LinkedHashMap<>();
private Admin admin = null;
private HostSystem hostSystem = null;
private final Version vespaVersion;
private final ApplicationId applicationId;
/**
* Creates and initializes a new Vespa from the service config file
* in the given application directory.
*
* @param parent the parent, usually VespaModel
* @param name the name, used as configId
* @param documentModel DocumentModel to serve global document config from.
*/
public ApplicationConfigProducerRoot(TreeConfigProducer parent,
String name, DocumentModel documentModel, Version vespaVersion, ApplicationId applicationId) {
super(parent, name);
this.documentModel = documentModel;
this.vespaVersion = vespaVersion;
this.applicationId = applicationId;
}
private boolean useV8GeoPositions = false;
public void useFeatureFlags(ModelContext.FeatureFlags featureFlags) {
this.useV8GeoPositions = featureFlags.useV8GeoPositions();
}
/**
* @return an unmodifiable copy of the set of configIds in this VespaModel.
*/
public Set getConfigIds() {
return Collections.unmodifiableSet(id2producer.keySet());
}
/**
* Returns the ConfigProducer with the given id, or null if no such
* configId exists.
*
* @param configId The configId, e.g. "search.0/tld.0"
* @return ConfigProducer with the given configId
*/
public ConfigProducer getConfigProducer(String configId) {
return id2producer.get(configId);
}
/**
* Adds the descendant (at any depth level), so it can be looked up
* on configId in the Map.
*
* @param descendant The configProducer descendant to add
*/
// TODO: Make protected if this moves to the same package as TreeConfigProducer
public void addDescendant(AnyConfigProducer descendant) {
id2producer.put(descendant.getConfigId(), descendant);
}
/**
* Prepares the model for start. The {@link VespaModel} calls
* this methods after it has loaded this and all plugins have been loaded and
* their initialize() methods have been called.
*
* @param plugins All initialized plugins of the vespa model.
*/
public void prepare(ConfigModelRepo plugins) {
if (routing != null) {
routing.deriveCommonSettings(plugins);
}
}
public void setupAdmin(Admin admin) {
this.admin = admin;
}
// TODO: Do this as another config model depending on the other models
public void setupRouting(DeployState deployState, VespaModel vespaModel, ConfigModelRepo configModels) {
if (admin != null) {
Routing routing = configModels.getRouting();
if (routing == null) {
routing = new Routing(ConfigModelContext.create(deployState, vespaModel, configModels, this, "routing"));
configModels.add(routing);
}
this.routing = routing;
}
}
@Override
public void getConfig(DocumentmanagerConfig.Builder builder) {
new DocumentManager()
.useV8GeoPositions(this.useV8GeoPositions)
.produce(documentModel, builder);
}
@Override
public void getConfig(DocumenttypesConfig.Builder builder) {
new DocumentTypes()
.useV8GeoPositions(this.useV8GeoPositions)
.produce(documentModel, builder);
}
@Override
public void getConfig(DocumentrouteselectorpolicyConfig.Builder builder) {
if (routing != null) {
routing.getConfig(builder);
}
}
@Override
public void getConfig(DocumentProtocolPoliciesConfig.Builder builder) {
if (routing != null) {
routing.getConfig(builder);
}
}
@Override
public void getConfig(MessagebusConfig.Builder builder) {
if (routing != null) {
routing.getConfig(builder);
}
}
@Override
public void getConfig(LogdConfig.Builder builder) {
if (admin != null) {
admin.getConfig(builder);
}
}
@Override
public void getConfig(SlobroksConfig.Builder builder) {
if (admin != null) {
admin.getConfig(builder);
}
}
@Override
public void getConfig(ZookeepersConfig.Builder builder) {
if (admin != null) {
admin.getConfig(builder);
}
}
@Override
public void getConfig(ClusterListConfig.Builder builder) {
VespaModel model = (VespaModel) getRoot();
for (ContentCluster cluster : model.getContentClusters().values()) {
ClusterListConfig.Storage.Builder storage = new ClusterListConfig.Storage.Builder();
storage.name(cluster.getName());
storage.configid(cluster.getConfigId());
builder.storage(storage);
}
}
@Override
public void getConfig(DistributionConfig.Builder builder) {
for (ContentCluster cluster : ((VespaModel) getRoot()).getContentClusters().values()) {
cluster.getConfig(builder);
}
}
@Override
public void getConfig(AllClustersBucketSpacesConfig.Builder builder) {
VespaModel model = (VespaModel) getRoot();
for (ContentCluster cluster : model.getContentClusters().values()) {
builder.cluster(cluster.getName(), cluster.clusterBucketSpaceConfigBuilder());
}
}
@Override
public void getConfig(ModelConfig.Builder builder) {
builder.vespaVersion(vespaVersion.toFullString());
for (HostResource modelHost : hostSystem().getHosts()) {
builder.hosts(new Hosts.Builder()
.name(modelHost.getHostname())
.services(getServices(modelHost))
);
}
}
public record StatePortInfo(String hostName, int portNumber, Service service)
{}
public List getStatePorts() {
List result = new ArrayList<>();
for (HostResource modelHost : hostSystem().getHosts()) {
String hostName = modelHost.getHostname();
for (Service modelService : modelHost.getServices()) {
PortsMeta portsMeta = modelService.getPortsMeta();
for (int i = 0; i < portsMeta.getNumPorts(); i++) {
int portNumber = modelService.getRelativePort(i);
boolean hasState = false;
boolean isHttp = false;
for (String tag : portsMeta.getTagsAt(i)) {
if (tag.equals("state")) hasState = true;
if (tag.equals("http")) isHttp = true;
}
if (hasState && isHttp) {
result.add(new StatePortInfo(hostName, portNumber, modelService));
}
}
}
}
return result;
}
private List getServices(HostResource modelHost) {
List ret = new ArrayList<>();
for (Service modelService : modelHost.getServices()) {
ret.add(new Services.Builder()
.name(modelService.getServiceName())
.type(modelService.getServiceType())
.configid(modelService.getConfigId())
.clustertype(modelService.getServicePropertyString("clustertype", ""))
.clustername(modelService.getServicePropertyString("clustername", ""))
.index(Integer.parseInt(modelService.getServicePropertyString("index", "999999")))
.ports(getPorts(modelService))
);
}
return ret;
}
private List getPorts(Service modelService) {
List ret = new ArrayList<>();
PortsMeta portsMeta = modelService.getPortsMeta();
for (int i = 0; i < portsMeta.getNumPorts(); i++) {
ret.add(new Ports.Builder()
.number(modelService.getRelativePort(i))
.tags(getPortTags(portsMeta, i))
);
}
return ret;
}
public static String getPortTags(PortsMeta portsMeta, int portNumber) {
StringBuilder sb = new StringBuilder();
boolean firstTag = true;
for (String s : portsMeta.getTagsAt(portNumber)) {
if (!firstTag) {
sb.append(" ");
} else {
firstTag = false;
}
sb.append(s);
}
return sb.toString();
}
public void setHostSystem(HostSystem hostSystem) {
this.hostSystem = hostSystem;
}
@Override
public HostSystem hostSystem() {
return hostSystem;
}
public Admin getAdmin() {
return admin;
}
@Override
public void getConfig(ApplicationIdConfig.Builder builder) {
builder.tenant(applicationId.tenant().value());
builder.application(applicationId.application().value());
builder.instance(applicationId.instance().value());
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy