diff options
author | Jon Bratseth <bratseth@gmail.com> | 2020-10-09 14:37:58 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@gmail.com> | 2020-10-09 14:37:58 +0200 |
commit | 4e6f7776fee9461dc8c7e4364b774c04916f99d4 (patch) | |
tree | 93dbb0188599ecb24286c6222a2a27d0a47aa1b0 /config-model | |
parent | 2e3515a187d0b3aae7ae1afd2708f011b9b8bf22 (diff) |
Signal deference of config change application until restart
When a restart needs to be done, processes should not apply
new config until restarted. This signals to clusters in the config model
when this obtains, but this is a no-op for now.
Diffstat (limited to 'config-model')
36 files changed, 475 insertions, 372 deletions
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/derived/validation/Validator.java b/config-model/src/main/java/com/yahoo/searchdefinition/derived/validation/Validator.java index e3bbf78ec21..6189276707b 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/derived/validation/Validator.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/derived/validation/Validator.java @@ -8,6 +8,7 @@ import com.yahoo.searchdefinition.derived.DerivedConfiguration; * @author mathiasm */ public abstract class Validator { + protected DerivedConfiguration config; protected Search search; diff --git a/config-model/src/main/java/com/yahoo/vespa/model/AbstractService.java b/config-model/src/main/java/com/yahoo/vespa/model/AbstractService.java index 5ef01f986c0..e75a9f2b125 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/AbstractService.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/AbstractService.java @@ -56,7 +56,7 @@ public abstract class AbstractService extends AbstractConfigProducer<AbstractCon private String preload = Defaults.getDefaults().underVespaHome("lib64/vespa/malloc/libvespamalloc.so"); // If larger or equal to 0 it mean that explicit mmaps shall not be included in coredump. - private long mmapNoCoreLimit = -1l; + private long mmapNoCoreLimit = -1L; // If this is true it will dump core when OOM private boolean coreOnOOM = false; @@ -77,7 +77,7 @@ public abstract class AbstractService extends AbstractConfigProducer<AbstractCon * more key/value pairs to the service-list dump. * Supported key datatypes are String, and values may be String or Integer. */ - private Map<String, Object> serviceProperties = new LinkedHashMap<>(); + private final Map<String, Object> serviceProperties = new LinkedHashMap<>(); /** The affinity properties of this service. */ private Optional<Affinity> affinity = Optional.empty(); @@ -176,15 +176,6 @@ public abstract class AbstractService extends AbstractConfigProducer<AbstractCon } else { // User defined from spec wantedPort = userWantedPort; -/* if ((wantedPort >= Host.BASE_PORT) && - (wantedPort <= (Host.BASE_PORT + Host.MAX_PORTS))) { - throw new RuntimeException - ("Attribute 'basePort=" + wantedPort + - "' is not allowed to be inside Vespa's reserved port range " - + Host.BASE_PORT + "-" - + (Host.BASE_PORT + Host.MAX_PORTS) + "."); - } -*/ } return wantedPort; } @@ -210,20 +201,18 @@ public abstract class AbstractService extends AbstractConfigProducer<AbstractCon * Computes and returns the i'th port for this service, based on * this Service's baseport. * - * @param i The offset from 'basePort' of the port to return + * @param i the offset from 'basePort' of the port to return * @return the i'th port relative to the base port. * @throws IllegalStateException if i is out of range. */ public int getRelativePort(int i) { if (ports.size() < 1) { - throw new IllegalStateException - ("Requested port with offset " + i + " for service that " + - "has not reserved any ports: " + this); + throw new IllegalStateException("Requested port with offset " + i + " for service that " + + "has not reserved any ports: " + this); } if (i >= ports.size()) { - throw new IllegalStateException - ("Requested port with offset " + i + " for service that " + - "only has reserved " + ports.size() + " ports: " + this); + throw new IllegalStateException("Requested port with offset " + i + " for service that " + + "only has reserved " + ports.size() + " ports: " + this); } return ports.get(i); } @@ -269,20 +258,10 @@ public abstract class AbstractService extends AbstractConfigProducer<AbstractCon return myClass.getName().substring(1 + myPackage.getName().length()); } - /** - * @return the physical host on which this service runs. - */ - public Host getHost() { - if (hostResource != null) { - return hostResource.getHost(); - } else { - return null; - } - } + @Override + public HostResource getHost() { return hostResource; } - /** - * @return The hostname on which this service runs. - */ + @Override public String getHostName() { return hostResource.getHostname(); } @@ -306,7 +285,6 @@ public abstract class AbstractService extends AbstractConfigProducer<AbstractCon protected int getIndex(HostResource host) { int i = 0; for (Service s : host.getServices()) { - //if (s.getClass().equals(getClass()) && (s != this)) { if (s.getServiceType().equals(getServiceType()) && (s != this)) { i++; } @@ -448,7 +426,7 @@ public abstract class AbstractService extends AbstractConfigProducer<AbstractCon } /** - * WARNING: should only be called before initService(), otherwise call at own risk! + * WARNING: should only be called before initService() */ public void setBasePort(int wantedPort) { this.basePort = wantedPort; @@ -465,27 +443,27 @@ public abstract class AbstractService extends AbstractConfigProducer<AbstractCon /** * Add the given file to the application's file distributor. * - * @param relativePath path to the file, relative to the app package. + * @param relativePath path to the file, relative to the app package * @return the file reference hash */ public FileReference sendFile(String relativePath) { - return getRoot().getFileDistributor().sendFileToHost(relativePath, getHost()); + Host host = null; + if (getHost() != null) // false when running application tests without hosts + host = getHost().getHost(); + return getRoot().getFileDistributor().sendFileToHost(relativePath, host); } public FileReference sendUri(String uri) { - return getRoot().getFileDistributor().sendUriToHost(uri, getHost()); + return getRoot().getFileDistributor().sendUriToHost(uri, getHost().getHost()); } - /** - * - * The service HTTP port for health status - * @return portnumber - */ + /** The service HTTP port for health status */ public int getHealthPort() { return -1;} /** * Overridden by subclasses. List of default dimensions to be added to this services metrics - * @return The default dimensions for this service + * + * @return the default dimensions for this service */ public HashMap<String, String> getDefaultMetricDimensions(){ return new LinkedHashMap<>(); } @@ -510,4 +488,5 @@ public abstract class AbstractService extends AbstractConfigProducer<AbstractCon public String toString() { return getServiceName() + " on " + (getHost() == null ? "no host" : getHost().toString()); } + } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java b/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java index 1c73000cc24..27fb0f444ef 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java @@ -47,7 +47,7 @@ public class HostResource implements Comparable<HostResource> { } /** - * Return the currently bounded {@link com.yahoo.vespa.model.Host}. + * Return the currently bound {@link com.yahoo.vespa.model.Host}. * * @return the {@link com.yahoo.vespa.model.Host} if bound, null if not. */ diff --git a/config-model/src/main/java/com/yahoo/vespa/model/Service.java b/config-model/src/main/java/com/yahoo/vespa/model/Service.java index 25128c5ab14..b102ccebee0 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/Service.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/Service.java @@ -29,16 +29,11 @@ public interface Service extends ConfigProducer, NetworkPortRequestor { */ Optional<String> getPreShutdownCommand(); - /** - * Returns a PortsMeta object, giving access to more information - * about the different ports of this service. - */ + /** Returns a PortsMeta object, giving access to more information about the different ports of this service. */ PortsMeta getPortsMeta(); - /** - * @return the physical host on which this service runs. - */ - Host getHost(); + /** Returns the physical host resource on which this service runs. */ + HostResource getHost(); /** * Get meta information about service. @@ -46,21 +41,18 @@ public interface Service extends ConfigProducer, NetworkPortRequestor { */ ServiceInfo getServiceInfo(); - /** - * @return The hostname on which this service runs. - */ + /** Returns the hostname on which this service runs. */ String getHostName(); /** Optional JVM execution options for this service */ String getJvmOptions(); /** - * Computes and returns the i'th port for this service, based on - * this Service's baseport. + * Computes and returns the i'th port for this service, based on this Service's baseport. * - * @param i The offset from 'basePort' of the port to return - * @return the i'th port relative to the base port. - * @throws IllegalStateException if i is out of range. + * @param i the offset from 'basePort' of the port to return + * @return the i'th port relative to the base port + * @throws IllegalStateException if i is out of range */ int getRelativePort(int i); @@ -70,23 +62,16 @@ public interface Service extends ConfigProducer, NetworkPortRequestor { * * @param key a key used for lookup in the service properties * @param defStr default String value returned if no value for key found - * @return the associated String value for the given key, or + * @return the associated String value for the given key */ String getServicePropertyString(String key, String defStr); int getHealthPort(); - /** - * - * @return HashMap of default dimensions for metrics. - */ + /** Returns a HashMap of default dimensions for metrics. */ HashMap<String,String> getDefaultMetricDimensions(); - /** - * Return the Affinity of this service if it has. - * - * @return The {@link com.yahoo.vespa.model.Affinity} for this service. - */ + /** Returns the Affinity of this service if it has. */ Optional<Affinity> getAffinity(); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsNodesConfigGenerator.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsNodesConfigGenerator.java index 21fa05ceeab..bdd04dc1692 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsNodesConfigGenerator.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsNodesConfigGenerator.java @@ -22,7 +22,7 @@ public class MetricsNodesConfigGenerator { private static MetricsNodesConfig.Node.Builder toNodeBuilder(MetricsProxyContainer container) { var builder = new MetricsNodesConfig.Node.Builder() - .role(container.getHost().getConfigId()) + .role(container.getHost().getHost().getConfigId()) .hostname(container.getHostName()) .metricsPort(MetricsProxyContainer.BASEPORT) .metricsPath(MetricsV1Handler.VALUES_PATH); diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainer.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainer.java index fccacc3210d..cc9f13f60f5 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainer.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainer.java @@ -132,7 +132,7 @@ public class MetricsProxyContainer extends Container implements } private String getNodeRole() { - String hostConfigId = getHost().getConfigId(); + String hostConfigId = getHost().getHost().getConfigId(); if (! isHostedVespa) return hostConfigId; return getHostResource().spec().membership() .map(ClusterMembership::stringValue) diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java index 9480690c395..fc5d4317d2f 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java @@ -7,6 +7,7 @@ import com.yahoo.config.model.api.ConfigChangeAction; import com.yahoo.config.model.api.Model; import com.yahoo.config.model.api.ValidationParameters; import com.yahoo.config.model.deploy.DeployState; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.vespa.model.VespaModel; import com.yahoo.vespa.model.application.validation.change.ChangeValidator; import com.yahoo.vespa.model.application.validation.change.ClusterSizeReductionValidator; @@ -28,6 +29,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; import static java.util.stream.Collectors.toList; @@ -70,9 +73,11 @@ public class Validation { validateFirstTimeDeployment(model, deployState); } else { Optional<Model> currentActiveModel = deployState.getPreviousModel(); - if (currentActiveModel.isPresent() && (currentActiveModel.get() instanceof VespaModel)) + if (currentActiveModel.isPresent() && (currentActiveModel.get() instanceof VespaModel)) { result = validateChanges((VespaModel) currentActiveModel.get(), model, deployState.validationOverrides(), deployState.getDeployLogger(), deployState.now()); + deferConfigChangesForClustersToBeRestarted(result, model); + } } return result; } @@ -103,4 +108,20 @@ public class Validation { new AccessControlOnFirstDeploymentValidator().validate(model, deployState); } + private static void deferConfigChangesForClustersToBeRestarted(List<ConfigChangeAction> actions, VespaModel model) { + Set<ClusterSpec.Id> clustersToBeRestarted = actions.stream() + .filter(action -> action.getType() == ConfigChangeAction.Type.RESTART) + .map(action -> action.clusterId()) + .collect(Collectors.toSet()); + for (var clusterToRestart : clustersToBeRestarted) { + var containerCluster = model.getContainerClusters().get(clusterToRestart.value()); + if (containerCluster != null) + containerCluster.deferChangesUntilRestart(); + + var contentCluster = model.getContentClusters().get(clusterToRestart.value()); + if (contentCluster != null) + contentCluster.deferChangesUntilRestart(); + } + } + } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ConfigValueChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ConfigValueChangeValidator.java index d94cd57357d..a11628bb0ea 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ConfigValueChangeValidator.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ConfigValueChangeValidator.java @@ -7,6 +7,7 @@ import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.application.api.ValidationOverrides; import com.yahoo.config.model.api.ConfigChangeAction; import com.yahoo.config.model.producer.AbstractConfigProducerRoot; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.vespa.model.Service; import com.yahoo.vespa.model.VespaModel; import com.yahoo.vespa.model.application.validation.RestartConfigs; @@ -44,32 +45,32 @@ public class ConfigValueChangeValidator implements ChangeValidator { return findConfigChangesFromModels(currentModel, nextModel).collect(Collectors.toList()); } - public Stream<ConfigChangeAction> findConfigChangesFromModels( - AbstractConfigProducerRoot currentModel, - AbstractConfigProducerRoot nextModel) { + public Stream<ConfigChangeAction> findConfigChangesFromModels(AbstractConfigProducerRoot currentModel, + AbstractConfigProducerRoot nextModel) { return nextModel.getDescendantServices().stream() .map(service -> findConfigChangeActionForService(service, currentModel, nextModel)) .filter(Optional::isPresent) .map(Optional::get); } - private Optional<ConfigChangeAction> findConfigChangeActionForService( - Service service, - AbstractConfigProducerRoot currentModel, - AbstractConfigProducerRoot nextModel) { + private Optional<ConfigChangeAction> findConfigChangeActionForService(Service service, + AbstractConfigProducerRoot currentModel, + AbstractConfigProducerRoot nextModel) { List<ChangesRequiringRestart> changes = findConfigChangesForService(service, currentModel, nextModel) .collect(Collectors.toList()); if (changes.isEmpty()) { return Optional.empty(); } String description = createDescriptionOfConfigChanges(changes.stream()); - return Optional.of(new VespaRestartAction(description, service.getServiceInfo())); + ClusterSpec.Id id = service.getHost().spec().membership().isPresent() ? + service.getHost().spec().membership().get().cluster().id() : + ClusterSpec.Id.from(service.getConfigId()); + return Optional.of(new VespaRestartAction(id, description, service.getServiceInfo())); } - private Stream<ChangesRequiringRestart> findConfigChangesForService( - Service service, - AbstractConfigProducerRoot currentModel, - AbstractConfigProducerRoot nextModel) { + private Stream<ChangesRequiringRestart> findConfigChangesForService(Service service, + AbstractConfigProducerRoot currentModel, + AbstractConfigProducerRoot nextModel) { Class<? extends Service> serviceClass = service.getClass(); if (!currentModel.getService(service.getConfigId()).isPresent()) { // Service does not exist in the current model. diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContainerRestartValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContainerRestartValidator.java index 3176ad9f912..17e4f031f3e 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContainerRestartValidator.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContainerRestartValidator.java @@ -2,18 +2,24 @@ package com.yahoo.vespa.model.application.validation.change; import com.yahoo.config.model.api.ConfigChangeAction; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.container.QrConfig; import com.yahoo.vespa.model.VespaModel; import com.yahoo.config.application.api.ValidationOverrides; +import com.yahoo.vespa.model.container.ApplicationContainer; +import com.yahoo.vespa.model.container.ApplicationContainerCluster; import com.yahoo.vespa.model.container.Container; +import com.yahoo.vespa.model.container.ContainerCluster; import java.time.Instant; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import static java.util.stream.Collectors.toList; /** - * Returns a restart action for each container that has turned on {@link QrConfig#restartOnDeploy}. + * Returns a restart action for each container that has turned on {@link QrConfig#restartOnDeploy()}. * * @author bjorncs */ @@ -22,16 +28,19 @@ public class ContainerRestartValidator implements ChangeValidator { @Override public List<ConfigChangeAction> validate(VespaModel currentModel, VespaModel nextModel, ValidationOverrides ignored, Instant now) { - return nextModel.getContainerClusters().values().stream() - .flatMap(cluster -> cluster.getContainers().stream()) - .filter(container -> isExistingContainer(container, currentModel)) - .filter(container -> shouldContainerRestartOnDeploy(container, nextModel)) - .map(ContainerRestartValidator::createConfigChangeAction) - .collect(toList()); + List<ConfigChangeAction> actions = new ArrayList<>(); + for (ContainerCluster<ApplicationContainer> cluster : nextModel.getContainerClusters().values()) { + actions.addAll(cluster.getContainers().stream() + .filter(container -> isExistingContainer(container, currentModel)) + .filter(container -> shouldContainerRestartOnDeploy(container, nextModel)) + .map(container -> createConfigChangeAction(cluster.id(), container)) + .collect(Collectors.toList())); + } + return actions; } - private static ConfigChangeAction createConfigChangeAction(Container container) { - return new VespaRestartAction(createMessage(container), container.getServiceInfo(), true); + private static ConfigChangeAction createConfigChangeAction(ClusterSpec.Id id, Container container) { + return new VespaRestartAction(id, createMessage(container), container.getServiceInfo(), true); } private static String createMessage(Container container) { diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidator.java index 4ed28331467..b321d5f3fd7 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidator.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidator.java @@ -20,7 +20,6 @@ import java.util.stream.Collectors; * Validates the changes between all current and next indexed search clusters in a vespa model. * * @author geirst - * @since 2014-11-18 */ public class IndexedSearchClusterChangeValidator implements ChangeValidator { @@ -40,9 +39,7 @@ public class IndexedSearchClusterChangeValidator implements ChangeValidator { ContentCluster nextCluster, ValidationOverrides overrides, Instant now) { - List<ConfigChangeAction> result = new ArrayList<>(); - result.addAll(validateDocumentDatabases(currentCluster, nextCluster, overrides, now)); - return result; + return validateDocumentDatabases(currentCluster, nextCluster, overrides, now); } private static List<ConfigChangeAction> validateDocumentDatabases(ContentCluster currentCluster, @@ -72,7 +69,7 @@ public class IndexedSearchClusterChangeValidator implements ChangeValidator { NewDocumentType currentDocType = currentCluster.getDocumentDefinitions().get(docTypeName); NewDocumentType nextDocType = nextCluster.getDocumentDefinitions().get(docTypeName); List<VespaConfigChangeAction> result = - new DocumentDatabaseChangeValidator(currentDb, currentDocType, nextDb, nextDocType).validate(overrides, now); + new DocumentDatabaseChangeValidator(currentCluster.id(), currentDb, currentDocType, nextDb, nextDocType).validate(overrides, now); return modifyActions(result, getSearchNodeServices(nextCluster.getSearch().getIndexed()), docTypeName); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexingModeChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexingModeChangeValidator.java index 908809b4b44..08b4b37968c 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexingModeChangeValidator.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/IndexingModeChangeValidator.java @@ -42,7 +42,8 @@ public class IndexingModeChangeValidator implements ChangeValidator { if (currentClusterIsIndexed == nextClusterIsIndexed) return Optional.empty(); - return Optional.of(VespaRefeedAction.of(ValidationId.indexModeChange.value(), + return Optional.of(VespaRefeedAction.of(currentCluster.id(), + ValidationId.indexModeChange.value(), overrides, "Cluster '" + currentCluster.getName() + "' changed indexing mode from '" + indexingMode(currentClusterIsIndexed) + "' to '" + indexingMode(nextClusterIsIndexed) + "'", diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/NodeResourceChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/NodeResourceChangeValidator.java index 5d56a27321a..0add9f243fe 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/NodeResourceChangeValidator.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/NodeResourceChangeValidator.java @@ -63,7 +63,8 @@ public class NodeResourceChangeValidator implements ChangeValidator { private List<ConfigChangeAction> createRestartActionsFor(ApplicationContainerCluster cluster) { return cluster.getContainers().stream() - .map(container -> new VespaRestartAction("Node resource change", + .map(container -> new VespaRestartAction(cluster.id(), + "Node resource change", container.getServiceInfo(), false)) .collect(Collectors.toList()); @@ -71,7 +72,8 @@ public class NodeResourceChangeValidator implements ChangeValidator { private List<ConfigChangeAction> createRestartActionsFor(ContentCluster cluster) { return cluster.getSearch().getSearchNodes().stream() - .map(node -> new VespaRestartAction("Node resource change", + .map(node -> new VespaRestartAction(cluster.id(), + "Node resource change", node.getServiceInfo(), false)) .collect(Collectors.toList()); diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/StartupCommandChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/StartupCommandChangeValidator.java index 840ab69ba08..54ce869eba1 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/StartupCommandChangeValidator.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/StartupCommandChangeValidator.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.model.application.validation.change; import com.yahoo.config.model.api.ConfigChangeAction; import com.yahoo.config.model.producer.AbstractConfigProducerRoot; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.vespa.model.Service; import com.yahoo.vespa.model.VespaModel; import com.yahoo.config.application.api.ValidationOverrides; @@ -28,11 +29,11 @@ public class StartupCommandChangeValidator implements ChangeValidator { return findServicesWithChangedStartupCommmand(currentModel, nextModel).collect(Collectors.toList()); } - public Stream<ConfigChangeAction> findServicesWithChangedStartupCommmand( - AbstractConfigProducerRoot currentModel, AbstractConfigProducerRoot nextModel) { + public Stream<ConfigChangeAction> findServicesWithChangedStartupCommmand(AbstractConfigProducerRoot currentModel, + AbstractConfigProducerRoot nextModel) { return nextModel.getDescendantServices().stream() .map(nextService -> currentModel.getService(nextService.getConfigId()) - .flatMap(currentService -> compareStartupCommand(currentService, nextService))) + .flatMap(currentService -> compareStartupCommand(currentService, nextService))) .filter(Optional::isPresent) .map(Optional::get); } @@ -41,13 +42,13 @@ public class StartupCommandChangeValidator implements ChangeValidator { String currentCommand = currentService.getStartupCommand(); String nextCommand = nextService.getStartupCommand(); - // Objects.equals is null-aware - if (Objects.equals(currentCommand, nextCommand)) { - return Optional.empty(); - } + if (Objects.equals(currentCommand, nextCommand)) return Optional.empty(); + String message = String.format("Startup command for '%s' has changed.\nNew command: %s.\nOld command: %s.", currentService.getServiceName(), nextCommand, currentCommand); - return Optional.of(new VespaRestartAction(message, currentService.getServiceInfo())); + return Optional.of(new VespaRestartAction(ClusterSpec.Id.from(currentService.getConfigId()), + message, + currentService.getServiceInfo())); } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/StreamingSearchClusterChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/StreamingSearchClusterChangeValidator.java index a96275010bf..d85d9bd2db5 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/StreamingSearchClusterChangeValidator.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/StreamingSearchClusterChangeValidator.java @@ -4,6 +4,7 @@ package com.yahoo.vespa.model.application.validation.change; import com.yahoo.config.application.api.ValidationOverrides; import com.yahoo.config.model.api.ConfigChangeAction; import com.yahoo.config.model.api.ServiceInfo; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.documentmodel.NewDocumentType; import com.yahoo.searchdefinition.derived.AttributeFields; import com.yahoo.searchdefinition.document.Attribute; @@ -59,45 +60,51 @@ public class StreamingSearchClusterChangeValidator implements ChangeValidator { Instant now) { List<VespaConfigChangeAction> result = new ArrayList<>(); - result.addAll(validateDocumentTypeChanges(getDocumentType(currentCluster, currentStreamingCluster), - getDocumentType(nextCluster, nextStreamingCluster), overrides, now)); - result.addAll(validateAttributeFastAccessAdded(currentStreamingCluster.getSdConfig().getAttributeFields(), - nextStreamingCluster.getSdConfig().getAttributeFields())); - result.addAll(validateAttributeFastAccessRemoved(currentStreamingCluster.getSdConfig().getAttributeFields(), - nextStreamingCluster.getSdConfig().getAttributeFields())); + result.addAll(validateDocumentTypeChanges(currentCluster.id(), + getDocumentType(currentCluster, currentStreamingCluster), + getDocumentType(nextCluster, nextStreamingCluster), overrides, now)); + result.addAll(validateAttributeFastAccessAdded(currentCluster.id(), + currentStreamingCluster.getSdConfig().getAttributeFields(), + nextStreamingCluster.getSdConfig().getAttributeFields())); + result.addAll(validateAttributeFastAccessRemoved(currentCluster.id(), + currentStreamingCluster.getSdConfig().getAttributeFields(), + nextStreamingCluster.getSdConfig().getAttributeFields())); return modifyActions(result, getSearchNodeServices(nextCluster), nextStreamingCluster.getDocTypeName()); } - private static List<VespaConfigChangeAction> validateDocumentTypeChanges(NewDocumentType currentDocType, + private static List<VespaConfigChangeAction> validateDocumentTypeChanges(ClusterSpec.Id id, + NewDocumentType currentDocType, NewDocumentType nextDocType, ValidationOverrides overrides, Instant now) { - return new DocumentTypeChangeValidator(currentDocType, nextDocType).validate(overrides, now); + return new DocumentTypeChangeValidator(id, currentDocType, nextDocType).validate(overrides, now); } private static NewDocumentType getDocumentType(ContentCluster cluster, StreamingSearchCluster streamingCluster) { return cluster.getDocumentDefinitions().get(streamingCluster.getDocTypeName()); } - private static List<VespaConfigChangeAction> validateAttributeFastAccessAdded(AttributeFields currentAttributes, + private static List<VespaConfigChangeAction> validateAttributeFastAccessAdded(ClusterSpec.Id id, + AttributeFields currentAttributes, AttributeFields nextAttributes) { - return validateAttributeFastAccessChanged(nextAttributes, currentAttributes, "add"); + return validateAttributeFastAccessChanged(id, nextAttributes, currentAttributes, "add"); } - private static List<VespaConfigChangeAction> validateAttributeFastAccessRemoved(AttributeFields currentAttributes, + private static List<VespaConfigChangeAction> validateAttributeFastAccessRemoved(ClusterSpec.Id id, + AttributeFields currentAttributes, AttributeFields nextAttributes) { - return validateAttributeFastAccessChanged(currentAttributes, nextAttributes, "remove"); + return validateAttributeFastAccessChanged(id, currentAttributes, nextAttributes, "remove"); } - private static List<VespaConfigChangeAction> validateAttributeFastAccessChanged(AttributeFields lhsAttributes, + private static List<VespaConfigChangeAction> validateAttributeFastAccessChanged(ClusterSpec.Id id, + AttributeFields lhsAttributes, AttributeFields rhsAttributes, String change) { return lhsAttributes.attributes().stream() .filter(attr -> attr.isFastAccess() && !hasFastAccessAttribute(attr.getName(), rhsAttributes)) - .map(attr -> new VespaRestartAction(new ChangeMessageBuilder(attr.getName()) - .addChange(change + " fast-access attribute").build())) + .map(attr -> new VespaRestartAction(id, new ChangeMessageBuilder(attr.getName()).addChange(change + " fast-access attribute").build())) .collect(Collectors.toList()); } @@ -117,7 +124,7 @@ public class StreamingSearchClusterChangeValidator implements ChangeValidator { String docTypeName) { return result.stream() .map(action -> action.modifyAction("Document type '" + docTypeName + "': " + action.getMessage(), - services, docTypeName)) + services, docTypeName)) .collect(Collectors.toList()); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaConfigChangeAction.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaConfigChangeAction.java index ea57b88ff4e..96c1a6a7b09 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaConfigChangeAction.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaConfigChangeAction.java @@ -3,8 +3,10 @@ package com.yahoo.vespa.model.application.validation.change; import com.yahoo.config.model.api.ConfigChangeAction; import com.yahoo.config.model.api.ServiceInfo; +import com.yahoo.config.provision.ClusterSpec; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; /** @@ -12,14 +14,15 @@ import java.util.stream.Collectors; * between the current active vespa model and the next vespa model to prepare. * * @author geirst - * @since 2014-11-18 */ public abstract class VespaConfigChangeAction implements ConfigChangeAction { + private final ClusterSpec.Id id; private final String message; private final List<ServiceInfo> services; - protected VespaConfigChangeAction(String message, List<ServiceInfo> services) { + protected VespaConfigChangeAction(ClusterSpec.Id id, String message, List<ServiceInfo> services) { + this.id = id; this.message = message; this.services = services; } @@ -27,6 +30,9 @@ public abstract class VespaConfigChangeAction implements ConfigChangeAction { public abstract VespaConfigChangeAction modifyAction(String newMessage, List<ServiceInfo> newServices, String documentType); @Override + public ClusterSpec.Id clusterId() { return id; } + + @Override public String getMessage() { return message; } @@ -63,4 +69,5 @@ public abstract class VespaConfigChangeAction implements ConfigChangeAction { result = 31 * result + services.hashCode(); return result; } + } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaRefeedAction.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaRefeedAction.java index be43c6eddfb..b61cd7af151 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaRefeedAction.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaRefeedAction.java @@ -4,6 +4,7 @@ package com.yahoo.vespa.model.application.validation.change; import com.yahoo.config.model.api.ConfigChangeRefeedAction; import com.yahoo.config.model.api.ServiceInfo; import com.yahoo.config.application.api.ValidationOverrides; +import com.yahoo.config.provision.ClusterSpec; import java.time.Instant; import java.util.List; @@ -13,7 +14,6 @@ import java.util.List; * * @author geirst * @author bratseth - * @since 5.43 */ public class VespaRefeedAction extends VespaConfigChangeAction implements ConfigChangeRefeedAction { @@ -27,8 +27,8 @@ public class VespaRefeedAction extends VespaConfigChangeAction implements Config private final String documentType; private final boolean allowed; - private VespaRefeedAction(String name, String message, List<ServiceInfo> services, String documentType, boolean allowed) { - super(message, services); + private VespaRefeedAction(ClusterSpec.Id id, String name, String message, List<ServiceInfo> services, String documentType, boolean allowed) { + super(id, message, services); this.name = name; this.documentType = documentType; this.allowed = allowed; @@ -36,19 +36,19 @@ public class VespaRefeedAction extends VespaConfigChangeAction implements Config /** Creates a refeed action with some missing information */ // TODO: We should require document type or model its absence properly - public static VespaRefeedAction of(String name, ValidationOverrides overrides, String message, Instant now) { - return new VespaRefeedAction(name, message, List.of(), "", overrides.allows(name, now)); + public static VespaRefeedAction of(ClusterSpec.Id id, String name, ValidationOverrides overrides, String message, Instant now) { + return new VespaRefeedAction(id, name, message, List.of(), "", overrides.allows(name, now)); } /** Creates a refeed action */ - public static VespaRefeedAction of(String name, ValidationOverrides overrides, String message, + public static VespaRefeedAction of(ClusterSpec.Id id, String name, ValidationOverrides overrides, String message, List<ServiceInfo> services, String documentType, Instant now) { - return new VespaRefeedAction(name, message, services, documentType, overrides.allows(name, now)); + return new VespaRefeedAction(id, name, message, services, documentType, overrides.allows(name, now)); } @Override public VespaConfigChangeAction modifyAction(String newMessage, List<ServiceInfo> newServices, String documentType) { - return new VespaRefeedAction(name, newMessage, newServices, documentType, allowed); + return new VespaRefeedAction(clusterId(), name, newMessage, newServices, documentType, allowed); } @Override diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaRestartAction.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaRestartAction.java index 3ea18cac1d6..ca3a408b2e0 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaRestartAction.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/VespaRestartAction.java @@ -3,8 +3,10 @@ package com.yahoo.vespa.model.application.validation.change; import com.yahoo.config.model.api.ConfigChangeRestartAction; import com.yahoo.config.model.api.ServiceInfo; +import com.yahoo.config.provision.ClusterSpec; import java.util.List; +import java.util.Optional; /** * Represents an action to restart services in order to handle a config change. @@ -15,27 +17,27 @@ public class VespaRestartAction extends VespaConfigChangeAction implements Confi private final boolean ignoreForInternalRedeploy; - public VespaRestartAction(String message) { - this(message, List.of()); + public VespaRestartAction(ClusterSpec.Id id, String message) { + this(id, message, List.of()); } - public VespaRestartAction(String message, ServiceInfo service) { - this(message, List.of(service)); + public VespaRestartAction(ClusterSpec.Id id, String message, ServiceInfo service) { + this(id, message, List.of(service)); } - public VespaRestartAction(String message, ServiceInfo services, boolean ignoreForInternalRedeploy) { - super(message, List.of(services)); + public VespaRestartAction(ClusterSpec.Id id, String message, ServiceInfo services, boolean ignoreForInternalRedeploy) { + super(id, message, List.of(services)); this.ignoreForInternalRedeploy = ignoreForInternalRedeploy; } - public VespaRestartAction(String message, List<ServiceInfo> services) { - super(message, services); + public VespaRestartAction(ClusterSpec.Id id, String message, List<ServiceInfo> services) { + super(id, message, services); this.ignoreForInternalRedeploy = false; } @Override public VespaConfigChangeAction modifyAction(String newMessage, List<ServiceInfo> newServices, String documentType) { - return new VespaRestartAction(newMessage, newServices); + return new VespaRestartAction(clusterId(), newMessage, newServices); } @Override diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidator.java index 5d790c74f18..a10aac30298 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidator.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidator.java @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.application.validation.change.search; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.documentmodel.NewDocumentType; import com.yahoo.searchdefinition.derived.AttributeFields; import com.yahoo.searchdefinition.derived.IndexSchema; @@ -26,6 +27,7 @@ import java.util.stream.Collectors; */ public class AttributeChangeValidator { + private final ClusterSpec.Id id; private final AttributeFields currentFields; private final IndexSchema currentIndexSchema; private final NewDocumentType currentDocType; @@ -33,12 +35,14 @@ public class AttributeChangeValidator { private final IndexSchema nextIndexSchema; private final NewDocumentType nextDocType; - public AttributeChangeValidator(AttributeFields currentFields, + public AttributeChangeValidator(ClusterSpec.Id id, + AttributeFields currentFields, IndexSchema currentIndexSchema, NewDocumentType currentDocType, AttributeFields nextFields, IndexSchema nextIndexSchema, NewDocumentType nextDocType) { + this.id = id; this.currentFields = currentFields; this.currentIndexSchema = currentIndexSchema; this.currentDocType = currentDocType; @@ -60,9 +64,8 @@ public class AttributeChangeValidator { return nextFields.attributes().stream(). map(attr -> attr.getName()). filter(attrName -> !currentFields.containsAttribute(attrName) && - currentDocType.containsField(attrName)). - map(attrName -> new VespaRestartAction(new ChangeMessageBuilder(attrName). - addChange("add attribute aspect").build())). + currentDocType.containsField(attrName)). + map(attrName -> new VespaRestartAction(id, new ChangeMessageBuilder(attrName).addChange("add attribute aspect").build())). collect(Collectors.toList()); } @@ -70,10 +73,9 @@ public class AttributeChangeValidator { return currentFields.attributes().stream(). map(attr -> attr.getName()). filter(attrName -> !nextFields.containsAttribute(attrName) && - nextDocType.containsField(attrName) && - !isIndexField(attrName)). - map(attrName -> new VespaRestartAction(new ChangeMessageBuilder(attrName). - addChange("remove attribute aspect").build())). + nextDocType.containsField(attrName) && + !isIndexField(attrName)). + map(attrName -> new VespaRestartAction(id, new ChangeMessageBuilder(attrName).addChange("remove attribute aspect").build())). collect(Collectors.toList()); } @@ -90,60 +92,63 @@ public class AttributeChangeValidator { for (Attribute nextAttr : nextFields.attributes()) { Attribute currAttr = currentFields.getAttribute(nextAttr.getName()); if (currAttr != null) { - validateAttributeSetting(currAttr, nextAttr, Attribute::isFastSearch, "fast-search", result); - validateAttributeSetting(currAttr, nextAttr, Attribute::isFastAccess, "fast-access", result); - validateAttributeSetting(currAttr, nextAttr, Attribute::isHuge, "huge", result); - validateAttributeSetting(currAttr, nextAttr, Attribute::densePostingListThreshold, "dense-posting-list-threshold", result); - validateAttributeSetting(currAttr, nextAttr, Attribute::isEnabledOnlyBitVector, "rank: filter", result); - validateAttributeSetting(currAttr, nextAttr, AttributeChangeValidator::hasHnswIndex, "indexing: index", result); - validateAttributeSetting(currAttr, nextAttr, Attribute::distanceMetric, "distance-metric", result); + validateAttributeSetting(id, currAttr, nextAttr, Attribute::isFastSearch, "fast-search", result); + validateAttributeSetting(id, currAttr, nextAttr, Attribute::isFastAccess, "fast-access", result); + validateAttributeSetting(id, currAttr, nextAttr, Attribute::isHuge, "huge", result); + validateAttributeSetting(id, currAttr, nextAttr, Attribute::densePostingListThreshold, "dense-posting-list-threshold", result); + validateAttributeSetting(id, currAttr, nextAttr, Attribute::isEnabledOnlyBitVector, "rank: filter", result); + validateAttributeSetting(id, currAttr, nextAttr, AttributeChangeValidator::hasHnswIndex, "indexing: index", result); + validateAttributeSetting(id, currAttr, nextAttr, Attribute::distanceMetric, "distance-metric", result); if (hasHnswIndex(currAttr) && hasHnswIndex(nextAttr)) { - validateAttributeHnswIndexSetting(currAttr, nextAttr, HnswIndexParams::maxLinksPerNode, "max-links-per-node", result); - validateAttributeHnswIndexSetting(currAttr, nextAttr, HnswIndexParams::neighborsToExploreAtInsert, "neighbors-to-explore-at-insert", result); + validateAttributeHnswIndexSetting(id, currAttr, nextAttr, HnswIndexParams::maxLinksPerNode, "max-links-per-node", result); + validateAttributeHnswIndexSetting(id, currAttr, nextAttr, HnswIndexParams::neighborsToExploreAtInsert, "neighbors-to-explore-at-insert", result); } } } return result; } - private static void validateAttributeSetting(Attribute currentAttr, Attribute nextAttr, + private static void validateAttributeSetting(ClusterSpec.Id id, + Attribute currentAttr, Attribute nextAttr, Predicate<Attribute> predicate, String setting, List<VespaConfigChangeAction> result) { - final boolean nextValue = predicate.test(nextAttr); + boolean nextValue = predicate.test(nextAttr); if (predicate.test(currentAttr) != nextValue) { String change = nextValue ? "add" : "remove"; - result.add(new VespaRestartAction(new ChangeMessageBuilder(nextAttr.getName()). - addChange(change + " attribute '" + setting + "'").build())); + result.add(new VespaRestartAction(id, new ChangeMessageBuilder(nextAttr.getName()).addChange(change + " attribute '" + setting + "'").build())); } } - private static <T> void validateAttributeSetting(Attribute currentAttr, Attribute nextAttr, + private static <T> void validateAttributeSetting(ClusterSpec.Id id, + Attribute currentAttr, Attribute nextAttr, Function<Attribute, T> settingValueProvider, String setting, List<VespaConfigChangeAction> result) { T currentValue = settingValueProvider.apply(currentAttr); T nextValue = settingValueProvider.apply(nextAttr); if ( ! Objects.equals(currentValue, nextValue)) { String message = String.format("change property '%s' from '%s' to '%s'", setting, currentValue, nextValue); - result.add(new VespaRestartAction(new ChangeMessageBuilder(nextAttr.getName()).addChange(message).build())); + result.add(new VespaRestartAction(id, new ChangeMessageBuilder(nextAttr.getName()).addChange(message).build())); } } - private static <T> void validateAttributeHnswIndexSetting(Attribute currentAttr, Attribute nextAttr, - Function<HnswIndexParams, T> settingValueProvider, String setting, + private static <T> void validateAttributeHnswIndexSetting(ClusterSpec.Id id, + Attribute currentAttr, Attribute nextAttr, + Function<HnswIndexParams, T> settingValueProvider, + String setting, List<VespaConfigChangeAction> result) { T currentValue = settingValueProvider.apply(currentAttr.hnswIndexParams().get()); T nextValue = settingValueProvider.apply(nextAttr.hnswIndexParams().get()); if (!Objects.equals(currentValue, nextValue)) { String message = String.format("change hnsw index property '%s' from '%s' to '%s'", setting, currentValue, nextValue); - result.add(new VespaRestartAction(new ChangeMessageBuilder(nextAttr.getName()).addChange(message).build())); + result.add(new VespaRestartAction(id, new ChangeMessageBuilder(nextAttr.getName()).addChange(message).build())); } } - private List<VespaConfigChangeAction> validateTensorTypes(final ValidationOverrides overrides, Instant now) { - final List<VespaConfigChangeAction> result = new ArrayList<>(); + private List<VespaConfigChangeAction> validateTensorTypes(ValidationOverrides overrides, Instant now) { + List<VespaConfigChangeAction> result = new ArrayList<>(); - for (final Attribute nextAttr : nextFields.attributes()) { - final Attribute currentAttr = currentFields.getAttribute(nextAttr.getName()); + for (Attribute nextAttr : nextFields.attributes()) { + Attribute currentAttr = currentFields.getAttribute(nextAttr.getName()); if (currentAttr != null && currentAttr.tensorType().isPresent()) { // If the tensor attribute is not present on the new attribute, it means that the data type of the attribute @@ -154,7 +159,7 @@ public class AttributeChangeValidator { // Tensor attribute has changed type if (!nextAttr.tensorType().get().equals(currentAttr.tensorType().get())) { - result.add(createTensorTypeChangedRefeedAction(currentAttr, nextAttr, overrides, now)); + result.add(createTensorTypeChangedRefeedAction(id, currentAttr, nextAttr, overrides, now)); } } } @@ -162,15 +167,13 @@ public class AttributeChangeValidator { return result; } - private static VespaRefeedAction createTensorTypeChangedRefeedAction(Attribute currentAttr, Attribute nextAttr, ValidationOverrides overrides, Instant now) { - return VespaRefeedAction.of( - "tensor-type-change", - overrides, - new ChangeMessageBuilder(nextAttr.getName()) - .addChange( - "tensor type", - currentAttr.tensorType().get().toString(), - nextAttr.tensorType().get().toString()).build(), now); + private static VespaRefeedAction createTensorTypeChangedRefeedAction(ClusterSpec.Id id, Attribute currentAttr, Attribute nextAttr, ValidationOverrides overrides, Instant now) { + return VespaRefeedAction.of(id, + "tensor-type-change", + overrides, + new ChangeMessageBuilder(nextAttr.getName()).addChange("tensor type", + currentAttr.tensorType().get().toString(), + nextAttr.tensorType().get().toString()).build(), now); } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidator.java index deae0a89c56..68a97f33dfd 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidator.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidator.java @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.application.validation.change.search; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.documentmodel.NewDocumentType; import com.yahoo.config.application.api.ValidationOverrides; import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction; @@ -14,19 +15,21 @@ import java.util.List; * Validates the changes between a current and next document database that is part of an indexed search cluster. * * @author geirst - * @since 2014-11-18 */ public class DocumentDatabaseChangeValidator { - private DocumentDatabase currentDatabase; - private NewDocumentType currentDocType; - private DocumentDatabase nextDatabase; - private NewDocumentType nextDocType; + private final ClusterSpec.Id id; + private final DocumentDatabase currentDatabase; + private final NewDocumentType currentDocType; + private final DocumentDatabase nextDatabase; + private final NewDocumentType nextDocType; - public DocumentDatabaseChangeValidator(DocumentDatabase currentDatabase, + public DocumentDatabaseChangeValidator(ClusterSpec.Id id, + DocumentDatabase currentDatabase, NewDocumentType currentDocType, DocumentDatabase nextDatabase, NewDocumentType nextDocType) { + this.id = id; this.currentDatabase = currentDatabase; this.currentDocType = currentDocType; this.nextDatabase = nextDatabase; @@ -43,25 +46,33 @@ public class DocumentDatabaseChangeValidator { } private List<VespaConfigChangeAction> validateAttributeChanges(ValidationOverrides overrides, Instant now) { - return new AttributeChangeValidator( - currentDatabase.getDerivedConfiguration().getAttributeFields(), - currentDatabase.getDerivedConfiguration().getIndexSchema(), currentDocType, - nextDatabase.getDerivedConfiguration().getAttributeFields(), - nextDatabase.getDerivedConfiguration().getIndexSchema(), nextDocType).validate(overrides, now); + return new AttributeChangeValidator(id, + currentDatabase.getDerivedConfiguration().getAttributeFields(), + currentDatabase.getDerivedConfiguration().getIndexSchema(), currentDocType, + nextDatabase.getDerivedConfiguration().getAttributeFields(), + nextDatabase.getDerivedConfiguration().getIndexSchema(), nextDocType) + .validate(overrides, now); } private List<VespaConfigChangeAction> validateStructFieldAttributeChanges(ValidationOverrides overrides, Instant now) { - return new StructFieldAttributeChangeValidator(currentDocType, currentDatabase.getDerivedConfiguration().getAttributeFields(), - nextDocType, nextDatabase.getDerivedConfiguration().getAttributeFields()).validate(overrides, now); + return new StructFieldAttributeChangeValidator(id, + currentDocType, + currentDatabase.getDerivedConfiguration().getAttributeFields(), + nextDocType, + nextDatabase.getDerivedConfiguration().getAttributeFields()) + .validate(overrides, now); } private List<VespaConfigChangeAction> validateIndexingScriptChanges(ValidationOverrides overrides, Instant now) { - return new IndexingScriptChangeValidator(currentDatabase.getDerivedConfiguration().getSearch(), - nextDatabase.getDerivedConfiguration().getSearch()).validate(overrides, now); + return new IndexingScriptChangeValidator(id, + currentDatabase.getDerivedConfiguration().getSearch(), + nextDatabase.getDerivedConfiguration().getSearch()) + .validate(overrides, now); } private List<VespaConfigChangeAction> validateDocumentTypeChanges(ValidationOverrides overrides, Instant now) { - return new DocumentTypeChangeValidator(currentDocType, nextDocType).validate(overrides, now); + return new DocumentTypeChangeValidator(id, currentDocType, nextDocType) + .validate(overrides, now); } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidator.java index 4fd5e82e93f..b66145a10c5 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidator.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidator.java @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.application.validation.change.search; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.document.StructDataType; import com.yahoo.documentmodel.NewDocumentType; import com.yahoo.document.Field; @@ -16,12 +17,12 @@ import java.util.stream.Collectors; * Validates the changes between a current and next document type used in a document database. * * @author toregge - * @since 2014-11-25 */ public class DocumentTypeChangeValidator { - private NewDocumentType currentDocType; - private NewDocumentType nextDocType; + private final ClusterSpec.Id id; + private final NewDocumentType currentDocType; + private final NewDocumentType nextDocType; private static abstract class FieldChange { @@ -127,8 +128,10 @@ public class DocumentTypeChangeValidator { } } - public DocumentTypeChangeValidator(NewDocumentType currentDocType, + public DocumentTypeChangeValidator(ClusterSpec.Id id, + NewDocumentType currentDocType, NewDocumentType nextDocType) { + this.id = id; this.currentDocType = currentDocType; this.nextDocType = nextDocType; } @@ -137,7 +140,8 @@ public class DocumentTypeChangeValidator { return currentDocType.getAllFields().stream(). map(field -> createFieldChange(field, nextDocType)). filter(fieldChange -> fieldChange.valid() && fieldChange.changedType()). - map(fieldChange -> VespaRefeedAction.of("field-type-change", + map(fieldChange -> VespaRefeedAction.of(id, + "field-type-change", overrides, new ChangeMessageBuilder(fieldChange.fieldName()). addChange("data type", fieldChange.currentTypeName(), diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidator.java index b03141fa5d9..4761d1613b8 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidator.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidator.java @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.application.validation.change.search; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.searchdefinition.Search; import com.yahoo.searchdefinition.document.ImmutableSDField; import com.yahoo.vespa.indexinglanguage.ExpressionConverter; @@ -21,14 +22,15 @@ import java.util.Optional; * Validates the indexing script changes in all fields in the current and next search model. * * @author geirst - * @since 2014-12-08 */ public class IndexingScriptChangeValidator { + private final ClusterSpec.Id id; private final Search currentSearch; private final Search nextSearch; - public IndexingScriptChangeValidator(Search currentSearch, Search nextSearch) { + public IndexingScriptChangeValidator(ClusterSpec.Id id, Search currentSearch, Search nextSearch) { + this.id = id; this.currentSearch = currentSearch; this.nextSearch = nextSearch; } @@ -53,7 +55,7 @@ public class IndexingScriptChangeValidator { ChangeMessageBuilder messageBuilder = new ChangeMessageBuilder(nextField.getName()); new IndexingScriptChangeMessageBuilder(currentSearch, currentField, nextSearch, nextField).populate(messageBuilder); messageBuilder.addChange("indexing script", currentScript.toString(), nextScript.toString()); - return Optional.of(VespaRefeedAction.of(ValidationId.indexingChange.value(), overrides, messageBuilder.build(), now)); + return Optional.of(VespaRefeedAction.of(id, ValidationId.indexingChange.value(), overrides, messageBuilder.build(), now)); } return Optional.empty(); } @@ -68,8 +70,7 @@ public class IndexingScriptChangeValidator { } private static ScriptExpression removeOutputExpressions(ScriptExpression script) { - ScriptExpression retval = (ScriptExpression) new OutputExpressionRemover().convert(script); - return retval; + return (ScriptExpression) new OutputExpressionRemover().convert(script); } private static class OutputExpressionRemover extends ExpressionConverter { diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/StructFieldAttributeChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/StructFieldAttributeChangeValidator.java index e3f9610d0a4..e8b2d593de6 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/StructFieldAttributeChangeValidator.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/search/StructFieldAttributeChangeValidator.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.model.application.validation.change.search; import com.yahoo.config.application.api.ValidationOverrides; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.document.ArrayDataType; import com.yahoo.document.DataType; import com.yahoo.document.Field; @@ -33,15 +34,18 @@ import java.util.stream.Collectors; */ public class StructFieldAttributeChangeValidator { + private final ClusterSpec.Id id; private final NewDocumentType currentDocType; private final AttributeFields currentAttributes; private final NewDocumentType nextDocType; private final AttributeFields nextAttributes; - public StructFieldAttributeChangeValidator(NewDocumentType currentDocType, + public StructFieldAttributeChangeValidator(ClusterSpec.Id id, + NewDocumentType currentDocType, AttributeFields currentAttributes, NewDocumentType nextDocType, AttributeFields nextAttributes) { + this.id = id; this.currentDocType = currentDocType; this.currentAttributes = currentAttributes; this.nextDocType = nextDocType; @@ -64,10 +68,8 @@ public class StructFieldAttributeChangeValidator { private List<VespaConfigChangeAction> validateAddAttributeAspect(Context current, Context next, ValidationOverrides overrides, Instant now) { return next.structFieldAttributes.stream() .filter(nextAttr -> current.hasFieldForStructFieldAttribute(nextAttr) && - !current.hasStructFieldAttribute(nextAttr)) - .map(nextAttr -> new VespaRestartAction( - new ChangeMessageBuilder(nextAttr.getName()) - .addChange("add attribute aspect").build())) + !current.hasStructFieldAttribute(nextAttr)) + .map(nextAttr -> new VespaRestartAction(id, new ChangeMessageBuilder(nextAttr.getName()).addChange("add attribute aspect").build())) .collect(Collectors.toList()); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainerCluster.java index 11e74fa6136..93717f0f532 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainerCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainerCluster.java @@ -8,6 +8,7 @@ import com.yahoo.config.FileReference; import com.yahoo.config.application.api.ComponentInfo; import com.yahoo.config.model.deploy.DeployState; import com.yahoo.config.model.producer.AbstractConfigProducer; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.container.bundle.BundleInstantiationSpecification; import com.yahoo.container.di.config.ApplicationBundlesConfig; import com.yahoo.container.handler.metrics.MetricsProxyApiConfig; @@ -81,8 +82,8 @@ public final class ApplicationContainerCluster extends ContainerCluster<Applicat private Integer memoryPercentage = null; - public ApplicationContainerCluster(AbstractConfigProducer<?> parent, String subId, String name, DeployState deployState) { - super(parent, subId, name, deployState); + public ApplicationContainerCluster(AbstractConfigProducer<?> parent, String configSubId, String clusterId, DeployState deployState) { + super(parent, configSubId, clusterId, deployState); this.tlsClientAuthority = deployState.tlsClientAuthority(); restApiGroup = new ConfigProducerGroup<>(this, "rest-api"); servletGroup = new ConfigProducerGroup<>(this, "servlet"); diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java b/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java index c6de198c06a..9433768f4de 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java @@ -321,7 +321,7 @@ public abstract class Container extends AbstractService implements FileDistributionConfigProducer fileDistribution = getRoot().getFileDistributionConfigProducer(); if (fileDistribution != null) { - builder.configid(fileDistribution.getConfigProducer(getHost()).getConfigId()); + builder.configid(fileDistribution.getConfigProducer(getHost().getHost()).getConfigId()); } return builder; } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java index 6b47584908f..2d7d49f03ed 100755 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java @@ -11,6 +11,7 @@ import com.yahoo.config.docproc.SchemamappingConfig; import com.yahoo.config.model.ApplicationConfigProducerRoot; import com.yahoo.config.model.deploy.DeployState; import com.yahoo.config.model.producer.AbstractConfigProducer; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Zone; import com.yahoo.container.ComponentsConfig; import com.yahoo.container.QrSearchersConfig; @@ -157,9 +158,9 @@ public abstract class ContainerCluster<CONTAINER extends Container> private String jvmGCOptions = null; private String environmentVars = null; - public ContainerCluster(AbstractConfigProducer<?> parent, String subId, String name, DeployState deployState) { - super(parent, subId); - this.name = name; + public ContainerCluster(AbstractConfigProducer<?> parent, String configSubId, String clusterId, DeployState deployState) { + super(parent, configSubId); + this.name = clusterId; this.isHostedVespa = stateIsHosted(deployState); this.zone = (deployState != null) ? deployState.zone() : Zone.defaultZone(); @@ -183,6 +184,8 @@ public abstract class ContainerCluster<CONTAINER extends Container> addJaxProviders(); } + public ClusterSpec.Id id() { return ClusterSpec.Id.from(getName()); } + public void setZone(Zone zone) { this.zone = zone; } @@ -614,4 +617,12 @@ public abstract class ContainerCluster<CONTAINER extends Container> protected abstract boolean messageBusEnabled(); + /** + * Mark that the config emitted by this cluster currently should be applied by clients already running with + * a previous generation of it only by restarting the consuming processes. + */ + public void deferChangesUntilRestart() { + + } + } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java index 9923cb2fece..1a994cd4636 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java @@ -91,7 +91,7 @@ public class ContentCluster extends AbstractConfigProducer implements private Redundancy redundancy; private ClusterControllerConfig clusterControllerConfig; private PersistenceEngine.PersistenceFactory persistenceFactory; - private final String clusterName; + private final String clusterId; private Integer maxNodesPerMerge; private final Zone zone; @@ -138,7 +138,7 @@ public class ContentCluster extends AbstractConfigProducer implements c.storageNodes = new StorageCluster.Builder().build(deployState, c, w3cContentElement); c.distributorNodes = new DistributorCluster.Builder(c).build(deployState, c, w3cContentElement); c.rootGroup = new StorageGroup.Builder(contentElement, context).buildRootGroup(deployState, redundancyBuilder, c); - validateThatGroupSiblingsAreUnique(c.clusterName, c.rootGroup); + validateThatGroupSiblingsAreUnique(c.clusterId, c.rootGroup); c.search.handleRedundancy(c.redundancy); setupSearchCluster(c.search, contentElement, deployState.getDeployLogger()); @@ -163,7 +163,7 @@ public class ContentCluster extends AbstractConfigProducer implements if (context.getParentProducer().getRoot() == null) return c; - addClusterControllers(containers, context, c.rootGroup, contentElement, c.clusterName, c); + addClusterControllers(containers, context, c.rootGroup, contentElement, c.clusterId, c); return c; } @@ -492,19 +492,21 @@ public class ContentCluster extends AbstractConfigProducer implements } - private ContentCluster(AbstractConfigProducer parent, String clusterName, + private ContentCluster(AbstractConfigProducer parent, String clusterId, Map<String, NewDocumentType> documentDefinitions, Set<NewDocumentType> globallyDistributedDocuments, String routingSelection, Zone zone, boolean isHosted) { - super(parent, clusterName); + super(parent, clusterId); this.isHosted = isHosted; - this.clusterName = clusterName; + this.clusterId = clusterId; this.documentDefinitions = documentDefinitions; this.globallyDistributedDocuments = globallyDistributedDocuments; this.documentSelection = routingSelection; this.zone = zone; } + public ClusterSpec.Id id() { return ClusterSpec.Id.from(clusterId); } + public void prepare(DeployState deployState) { search.prepare(); @@ -525,7 +527,7 @@ public class ContentCluster extends AbstractConfigProducer implements return clusterId != null ? clusterId : "content"; } - public String getName() { return clusterName; } + public String getName() { return clusterId; } public String getRoutingSelector() { return documentSelection; } @@ -740,4 +742,13 @@ public class ContentCluster extends AbstractConfigProducer implements builder.documenttype(docTypeBuilder); } } + + /** + * Mark that the config emitted by this cluster currently should be applied by clients already running with + * a previous generation of it only by restarting the consuming processes. + */ + public void deferChangesUntilRestart() { + + } + } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/search/SearchNode.java b/config-model/src/main/java/com/yahoo/vespa/model/search/SearchNode.java index b44040f843d..534bab4677c 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/search/SearchNode.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/search/SearchNode.java @@ -259,7 +259,7 @@ public class SearchNode extends AbstractService implements public void getConfig(FiledistributorrpcConfig.Builder builder) { FileDistributionConfigProducer fileDistribution = getRoot().getFileDistributionConfigProducer(); if (fileDistribution != null) { - FileDistributionConfigProvider configProducer = fileDistribution.getConfigProducer(getHost()); + FileDistributionConfigProvider configProducer = fileDistribution.getConfigProducer(getHost().getHost()); configProducer.getConfig(builder); } } diff --git a/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java b/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java index 1be58564d1b..26d8a9b0eca 100644 --- a/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java +++ b/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java @@ -444,12 +444,14 @@ public class ModelProvisioningTest { // Check container cluster assertEquals(1, model.getContainerClusters().size()); - Set<com.yahoo.vespa.model.Host> containerHosts = model.getContainerClusters().get("foo").getContainers().stream().map(Container::getHost).collect(Collectors.toSet()); + Set<HostResource> containerHosts = model.getContainerClusters().get("foo").getContainers().stream() + .map(Container::getHost) + .collect(Collectors.toSet()); assertEquals(10, containerHosts.size()); // Check admin clusters Admin admin = model.getAdmin(); - Set<com.yahoo.vespa.model.Host> slobrokHosts = admin.getSlobroks().stream().map(Slobrok::getHost).collect(Collectors.toSet()); + Set<HostResource> slobrokHosts = admin.getSlobroks().stream().map(Slobrok::getHost).collect(Collectors.toSet()); assertEquals(3, slobrokHosts.size()); assertTrue("Slobroks are assigned from container nodes", containerHosts.containsAll(slobrokHosts)); assertTrue("Logserver is assigned from container nodes", containerHosts.contains(admin.getLogserver().getHost())); diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ConfigChangeTestUtils.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ConfigChangeTestUtils.java index 65ac6c7625e..4fd2609eb67 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ConfigChangeTestUtils.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ConfigChangeTestUtils.java @@ -4,8 +4,10 @@ package com.yahoo.vespa.model.application.validation.change; import com.yahoo.config.model.api.ConfigChangeAction; import com.yahoo.config.model.api.ServiceInfo; import com.yahoo.config.application.api.ValidationOverrides; +import com.yahoo.config.provision.ClusterSpec; import java.time.Instant; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -14,25 +16,25 @@ import static org.junit.Assert.assertThat; public class ConfigChangeTestUtils { - public static VespaConfigChangeAction newRestartAction(String message) { - return new VespaRestartAction(message); + public static VespaConfigChangeAction newRestartAction(ClusterSpec.Id id, String message) { + return new VespaRestartAction(id, message); } - public static VespaConfigChangeAction newRestartAction(String message, List<ServiceInfo> services) { - return new VespaRestartAction(message, services); + public static VespaConfigChangeAction newRestartAction(ClusterSpec.Id id, String message, List<ServiceInfo> services) { + return new VespaRestartAction(id, message, services); } - public static VespaConfigChangeAction newRefeedAction(String name, String message) { - return VespaRefeedAction.of(name, ValidationOverrides.empty, message, Instant.now()); + public static VespaConfigChangeAction newRefeedAction(ClusterSpec.Id id, String name, String message) { + return VespaRefeedAction.of(id, name, ValidationOverrides.empty, message, Instant.now()); } - public static VespaConfigChangeAction newRefeedAction(String name, ValidationOverrides overrides, String message, Instant now) { - return VespaRefeedAction.of(name, overrides, message, now); + public static VespaConfigChangeAction newRefeedAction(ClusterSpec.Id id, String name, ValidationOverrides overrides, String message, Instant now) { + return VespaRefeedAction.of(id, name, overrides, message, now); } - public static VespaConfigChangeAction newRefeedAction(String name, ValidationOverrides overrides, String message, + public static VespaConfigChangeAction newRefeedAction(ClusterSpec.Id id, String name, ValidationOverrides overrides, String message, List<ServiceInfo> services, String documentType, Instant now) { - return VespaRefeedAction.of(name, overrides, message, services, documentType, now); + return VespaRefeedAction.of(id, name, overrides, message, services, documentType, now); } public static List<ConfigChangeAction> normalizeServicesInActions(List<ConfigChangeAction> result) { @@ -53,9 +55,11 @@ public class ConfigChangeTestUtils { } public static void assertEqualActions(List<ConfigChangeAction> exp, List<ConfigChangeAction> act) { - exp.sort((lhs, rhs) -> lhs.getMessage().compareTo(rhs.getMessage())); - act.sort((lhs, rhs) -> lhs.getMessage().compareTo(rhs.getMessage())); - assertThat(act, equalTo(exp)); + var mutableExp = new ArrayList<>(exp); + var mutableAct = new ArrayList<>(act); + mutableExp.sort((lhs, rhs) -> lhs.getMessage().compareTo(rhs.getMessage())); + mutableAct.sort((lhs, rhs) -> lhs.getMessage().compareTo(rhs.getMessage())); + assertThat(mutableAct, equalTo(mutableExp)); } } diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidatorTest.java index 80127ac6854..8d365f24c7f 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidatorTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/IndexedSearchClusterChangeValidatorTest.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.model.application.validation.change; import com.yahoo.config.model.api.ConfigChangeAction; import com.yahoo.config.model.api.ServiceInfo; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.vespa.model.VespaModel; import com.yahoo.config.application.api.ValidationOverrides; import com.yahoo.vespa.model.content.utils.ApplicationPackageBuilder; @@ -11,15 +12,13 @@ import com.yahoo.vespa.model.content.utils.SchemaBuilder; import org.junit.Test; import java.time.Instant; -import java.util.Arrays; import java.util.List; import static com.yahoo.vespa.model.application.validation.change.ConfigChangeTestUtils.assertEqualActions; import static com.yahoo.vespa.model.application.validation.change.ConfigChangeTestUtils.newRefeedAction; import static com.yahoo.vespa.model.application.validation.change.ConfigChangeTestUtils.newRestartAction; import static com.yahoo.vespa.model.application.validation.change.ConfigChangeTestUtils.normalizeServicesInActions; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; public class IndexedSearchClusterChangeValidatorTest { @@ -40,9 +39,9 @@ public class IndexedSearchClusterChangeValidatorTest { public static VespaModel newOneDocModel(String sdContent) { return new ApplicationPackageBuilder(). - addCluster(new ContentClusterBuilder().name("foo").docTypes("d1")). - addSchemas(new SchemaBuilder(). - name("d1").content(sdContent).build()).buildCreator().create(); + addCluster(new ContentClusterBuilder().name("foo").docTypes("d1")) + .addSchemas(new SchemaBuilder().name("d1").content(sdContent).build()) + .buildCreator().create(); } public static Fixture newTwoDocFixture(String currentSd, String nextSd) { @@ -51,11 +50,9 @@ public class IndexedSearchClusterChangeValidatorTest { public static VespaModel newTwoDocModel(String d1Content, String d2Content) { return new ApplicationPackageBuilder(). - addCluster(new ContentClusterBuilder().name("foo").docTypes("d1", "d2")). - addSchemas(new SchemaBuilder(). - name("d1").content(d1Content).build()). - addSchemas(new SchemaBuilder(). - name("d2").content(d2Content).build()). + addCluster(new ContentClusterBuilder().name("foo").docTypes("d1", "d2")) + .addSchemas(new SchemaBuilder().name("d1").content(d1Content).build()) + .addSchemas(new SchemaBuilder().name("d2").content(d2Content).build()). buildCreator().create(); } @@ -66,25 +63,23 @@ public class IndexedSearchClusterChangeValidatorTest { public static VespaModel newTwoClusterModel(String d1Content, String d2Content) { return new ApplicationPackageBuilder(). addCluster(new ContentClusterBuilder().name("foo").docTypes("d1")). - addCluster(new ContentClusterBuilder().name("bar").docTypes("d2")). - addSchemas(new SchemaBuilder(). - name("d1").content(d1Content).build()). - addSchemas(new SchemaBuilder(). - name("d2").content(d2Content).build()). + addCluster(new ContentClusterBuilder().name("bar").docTypes("d2")) + .addSchemas(new SchemaBuilder().name("d1").content(d1Content).build()) + .addSchemas(new SchemaBuilder().name("d2").content(d2Content).build()). buildCreator().create(); } private List<ConfigChangeAction> validate() { return normalizeServicesInActions(validator.validate(currentModel, nextModel, - ValidationOverrides.empty, Instant.now())); + ValidationOverrides.empty, Instant.now())); } public void assertValidation() { - assertThat(validate().size(), is(0)); + assertTrue(validate().isEmpty()); } public void assertValidation(ConfigChangeAction exp) { - assertValidation(Arrays.asList(exp)); + assertValidation(List.of(exp)); } public void assertValidation(List<ConfigChangeAction> exp) { @@ -97,31 +92,34 @@ public class IndexedSearchClusterChangeValidatorTest { static String ATTRIBUTE_CHANGE_MSG = "Field 'f1' changed: add attribute aspect"; static String INT_FIELD = "field f1 type int { indexing: summary }"; static String FIELD_TYPE_CHANGE_MSG = "Field 'f1' changed: data type: 'string' -> 'int'"; - private static List<ServiceInfo> FOO_SERVICE = Arrays.asList( + private static final List<ServiceInfo> FOO_SERVICE = List.of( new ServiceInfo("searchnode", "null", null, null, "foo/search/cluster.foo/0", "null")); - private static List<ServiceInfo> BAR_SERVICE = Arrays.asList( + private static final List<ServiceInfo> BAR_SERVICE = List.of( new ServiceInfo("searchnode2", "null", null, null, "bar/search/cluster.bar/0", "null")); @Test public void requireThatDocumentDatabaseChangeIsDiscovered() { Fixture.newOneDocFixture(STRING_FIELD, ATTRIBUTE_FIELD). - assertValidation(newRestartAction("Document type 'd1': " + ATTRIBUTE_CHANGE_MSG, FOO_SERVICE)); + assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Document type 'd1': " + ATTRIBUTE_CHANGE_MSG, FOO_SERVICE)); } @Test public void requireThatChangeInSeveralDocumentDatabasesAreDiscovered() { Fixture.newTwoDocFixture(STRING_FIELD, ATTRIBUTE_FIELD). - assertValidation(Arrays.asList(newRestartAction("Document type 'd1': " - + ATTRIBUTE_CHANGE_MSG, FOO_SERVICE), - newRestartAction("Document type 'd2': " + ATTRIBUTE_CHANGE_MSG, FOO_SERVICE))); + assertValidation(List.of(newRestartAction(ClusterSpec.Id.from("test"), + "Document type 'd1': " + ATTRIBUTE_CHANGE_MSG, FOO_SERVICE), + newRestartAction(ClusterSpec.Id.from("test"), + "Document type 'd2': " + ATTRIBUTE_CHANGE_MSG, FOO_SERVICE))); } @Test public void requireThatChangeInSeveralContentClustersAreDiscovered() { Fixture.newTwoClusterFixture(STRING_FIELD, ATTRIBUTE_FIELD). - assertValidation(Arrays.asList(newRestartAction("Document type 'd1': " - + ATTRIBUTE_CHANGE_MSG, FOO_SERVICE), - newRestartAction("Document type 'd2': " + ATTRIBUTE_CHANGE_MSG, BAR_SERVICE))); + assertValidation(List.of(newRestartAction(ClusterSpec.Id.from("test"), + "Document type 'd1': " + ATTRIBUTE_CHANGE_MSG, FOO_SERVICE), + newRestartAction(ClusterSpec.Id.from("test"), + "Document type 'd2': " + ATTRIBUTE_CHANGE_MSG, BAR_SERVICE))); } @Test @@ -147,9 +145,10 @@ public class IndexedSearchClusterChangeValidatorTest { @Test public void requireThatChangingFieldTypeIsDiscovered() { Fixture f = Fixture.newOneDocFixture(STRING_FIELD, INT_FIELD); - f.assertValidation(Arrays.asList(newRefeedAction("field-type-change", - ValidationOverrides.empty, - "Document type 'd1': " + FIELD_TYPE_CHANGE_MSG, FOO_SERVICE, "d1", Instant.now()))); + f.assertValidation(List.of(newRefeedAction(ClusterSpec.Id.from("test"), + "field-type-change", + ValidationOverrides.empty, + "Document type 'd1': " + FIELD_TYPE_CHANGE_MSG, FOO_SERVICE, "d1", Instant.now()))); } } diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/StreamingSearchClusterChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/StreamingSearchClusterChangeValidatorTest.java index 8edbc964bfb..f5ef50ee3a4 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/StreamingSearchClusterChangeValidatorTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/StreamingSearchClusterChangeValidatorTest.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.model.application.validation.change; import com.yahoo.config.model.api.ConfigChangeAction; import com.yahoo.config.model.api.ServiceInfo; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.vespa.model.VespaModel; import com.yahoo.config.application.api.ValidationOverrides; import com.yahoo.vespa.model.content.utils.ApplicationPackageBuilder; @@ -162,18 +163,23 @@ public class StreamingSearchClusterChangeValidatorTest { } private static VespaConfigChangeAction createFieldTypeChangeRefeedAction(String docType, List<ServiceInfo> service) { - return ConfigChangeTestUtils.newRefeedAction("field-type-change", - ValidationOverrides.empty, + return ConfigChangeTestUtils.newRefeedAction(ClusterSpec.Id.from("test"), + "field-type-change", + ValidationOverrides.empty, "Document type '" + docType + "': Field 'f1' changed: data type: 'string' -> 'int'", - service, docType, Instant.now()); + service, docType, Instant.now()); } private static VespaConfigChangeAction createAddFastAccessRestartAction() { - return ConfigChangeTestUtils.newRestartAction("Document type 'd1': Field 'f1' changed: add fast-access attribute", FOO_SERVICE); + return ConfigChangeTestUtils.newRestartAction(ClusterSpec.Id.from("test"), + "Document type 'd1': Field 'f1' changed: add fast-access attribute", + FOO_SERVICE); } private static VespaConfigChangeAction createRemoveFastAccessRestartAction() { - return ConfigChangeTestUtils.newRestartAction("Document type 'd1': Field 'f1' changed: remove fast-access attribute", FOO_SERVICE); + return ConfigChangeTestUtils.newRestartAction(ClusterSpec.Id.from("test"), + "Document type 'd1': Field 'f1' changed: remove fast-access attribute", + FOO_SERVICE); } } diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidatorTest.java index e00b34d4a79..168ee797fbf 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidatorTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidatorTest.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.model.application.validation.change.search; import com.yahoo.config.application.api.ValidationOverrides; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction; import org.junit.Test; @@ -18,12 +19,13 @@ public class AttributeChangeValidatorTest { public Fixture(String currentSd, String nextSd) throws Exception { super(currentSd, nextSd); - validator = new AttributeChangeValidator(currentDb().getDerivedConfiguration().getAttributeFields(), - currentDb().getDerivedConfiguration().getIndexSchema(), - currentDocType(), - nextDb().getDerivedConfiguration().getAttributeFields(), - nextDb().getDerivedConfiguration().getIndexSchema(), - nextDocType()); + validator = new AttributeChangeValidator(ClusterSpec.Id.from("test"), + currentDb().getDerivedConfiguration().getAttributeFields(), + currentDb().getDerivedConfiguration().getIndexSchema(), + currentDocType(), + nextDb().getDerivedConfiguration().getAttributeFields(), + nextDb().getDerivedConfiguration().getIndexSchema(), + nextDocType()); } @Override @@ -37,16 +39,16 @@ public class AttributeChangeValidatorTest { public void adding_attribute_aspect_require_restart() throws Exception { Fixture f = new Fixture("field f1 type string { indexing: summary }", "field f1 type string { indexing: attribute | summary }"); - f.assertValidation(newRestartAction( - "Field 'f1' changed: add attribute aspect")); + f.assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: add attribute aspect")); } @Test public void removing_attribute_aspect_require_restart() throws Exception { Fixture f = new Fixture("field f1 type string { indexing: attribute | summary }", "field f1 type string { indexing: summary }"); - f.assertValidation(newRestartAction( - "Field 'f1' changed: remove attribute aspect")); + f.assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: remove attribute aspect")); } @Test @@ -65,24 +67,24 @@ public class AttributeChangeValidatorTest { public void changing_fast_search_require_restart() throws Exception { new Fixture("field f1 type string { indexing: attribute }", "field f1 type string { indexing: attribute \n attribute: fast-search }"). - assertValidation(newRestartAction( - "Field 'f1' changed: add attribute 'fast-search'")); + assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: add attribute 'fast-search'")); } @Test public void changing_fast_access_require_restart() throws Exception { new Fixture("field f1 type string { indexing: attribute \n attribute: fast-access }", "field f1 type string { indexing: attribute }"). - assertValidation(newRestartAction( - "Field 'f1' changed: remove attribute 'fast-access'")); + assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: remove attribute 'fast-access'")); } @Test public void changing_huge_require_restart() throws Exception { new Fixture("field f1 type string { indexing: attribute }", "field f1 type string { indexing: attribute \n attribute: huge }"). - assertValidation(newRestartAction( - "Field 'f1' changed: add attribute 'huge'")); + assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: add attribute 'huge'")); } @Test @@ -90,8 +92,8 @@ public class AttributeChangeValidatorTest { new Fixture( "field f1 type predicate { indexing: attribute \n index { arity: 8 \n dense-posting-list-threshold: 0.2 } }", "field f1 type predicate { indexing: attribute \n index { arity: 8 \n dense-posting-list-threshold: 0.4 } }"). - assertValidation(newRestartAction( - "Field 'f1' changed: change property 'dense-posting-list-threshold' from '0.2' to '0.4'")); + assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: change property 'dense-posting-list-threshold' from '0.2' to '0.4'")); } @Test @@ -113,18 +115,18 @@ public class AttributeChangeValidatorTest { new Fixture( "field f1 type tensor(x[2]) { indexing: attribute }", "field f1 type tensor(x[3]) { indexing: attribute }") - .assertValidation(newRefeedAction( - "tensor-type-change", - ValidationOverrides.empty, - "Field 'f1' changed: tensor type: 'tensor(x[2])' -> 'tensor(x[3])'", Instant.now())); + .assertValidation(newRefeedAction(ClusterSpec.Id.from("test"), + "tensor-type-change", + ValidationOverrides.empty, + "Field 'f1' changed: tensor type: 'tensor(x[2])' -> 'tensor(x[3])'", Instant.now())); new Fixture( "field f1 type tensor(x[5]) { indexing: attribute }", "field f1 type tensor(x[3]) { indexing: attribute }") - .assertValidation(newRefeedAction( - "tensor-type-change", - ValidationOverrides.empty, - "Field 'f1' changed: tensor type: 'tensor(x[5])' -> 'tensor(x[3])'", Instant.now())); + .assertValidation(newRefeedAction(ClusterSpec.Id.from("test"), + "tensor-type-change", + ValidationOverrides.empty, + "Field 'f1' changed: tensor type: 'tensor(x[5])' -> 'tensor(x[3])'", Instant.now())); } @Test @@ -139,32 +141,32 @@ public class AttributeChangeValidatorTest { public void adding_rank_filter_requires_restart() throws Exception { new Fixture("field f1 type string { indexing: attribute }", "field f1 type string { indexing: attribute \n rank: filter }"). - assertValidation(newRestartAction( - "Field 'f1' changed: add attribute 'rank: filter'")); + assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: add attribute 'rank: filter'")); } @Test public void removing_rank_filter_requires_restart() throws Exception { new Fixture("field f1 type string { indexing: attribute \n rank: filter }", "field f1 type string { indexing: attribute }"). - assertValidation(newRestartAction( - "Field 'f1' changed: remove attribute 'rank: filter'")); + assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: remove attribute 'rank: filter'")); } @Test public void adding_hnsw_index_requires_restart() throws Exception { new Fixture("field f1 type tensor(x[2]) { indexing: attribute }", "field f1 type tensor(x[2]) { indexing: attribute | index \n index { hnsw } }"). - assertValidation(newRestartAction( - "Field 'f1' changed: add attribute 'indexing: index'")); + assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: add attribute 'indexing: index'")); } @Test public void removing_hnsw_index_requres_restart() throws Exception { new Fixture("field f1 type tensor(x[2]) { indexing: attribute | index \n index { hnsw } }", "field f1 type tensor(x[2]) { indexing: attribute }"). - assertValidation(newRestartAction( - "Field 'f1' changed: remove attribute 'indexing: index'")); + assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: remove attribute 'indexing: index'")); } @Test @@ -172,8 +174,9 @@ public class AttributeChangeValidatorTest { new Fixture("field f1 type tensor(x[2]) { indexing: attribute }", "field f1 type tensor(x[2]) { indexing: attribute \n attribute { " + "distance-metric: geodegrees \n } }"). - assertValidation(newRestartAction("Field 'f1' changed: change property " + - "'distance-metric' from 'EUCLIDEAN' to 'GEODEGREES'")); + assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: change property " + + "'distance-metric' from 'EUCLIDEAN' to 'GEODEGREES'")); } @Test @@ -181,8 +184,9 @@ public class AttributeChangeValidatorTest { new Fixture("field f1 type tensor(x[2]) { indexing: attribute | index \n index { hnsw } }", "field f1 type tensor(x[2]) { indexing: attribute | index \n attribute { " + "distance-metric: geodegrees \n } }"). - assertValidation(newRestartAction("Field 'f1' changed: change property " + - "'distance-metric' from 'EUCLIDEAN' to 'GEODEGREES'")); + assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: change property " + + "'distance-metric' from 'EUCLIDEAN' to 'GEODEGREES'")); } @Test @@ -190,8 +194,9 @@ public class AttributeChangeValidatorTest { new Fixture("field f1 type tensor(x[2]) { indexing: attribute | index \n index { hnsw } }", "field f1 type tensor(x[2]) { indexing: attribute | index \n index { " + "hnsw { max-links-per-node: 4 } } }"). - assertValidation(newRestartAction("Field 'f1' changed: change hnsw index property " + - "'max-links-per-node' from '16' to '4'")); + assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: change hnsw index property " + + "'max-links-per-node' from '16' to '4'")); } @Test @@ -199,7 +204,8 @@ public class AttributeChangeValidatorTest { new Fixture("field f1 type tensor(x[2]) { indexing: attribute | index \n index { hnsw } }", "field f1 type tensor(x[2]) { indexing: attribute | index \n index { " + "hnsw { neighbors-to-explore-at-insert: 100 } } }"). - assertValidation(newRestartAction("Field 'f1' changed: change hnsw index property " + - "'neighbors-to-explore-at-insert' from '200' to '100'")); + assertValidation(newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: change hnsw index property " + + "'neighbors-to-explore-at-insert' from '200' to '100'")); } } diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidatorTest.java index c24b5250a5d..60b17142340 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidatorTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidatorTest.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.model.application.validation.change.search; import com.yahoo.config.application.api.ValidationOverrides; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction; import org.junit.Test; @@ -19,7 +20,11 @@ public class DocumentDatabaseChangeValidatorTest { public Fixture(String currentSd, String nextSd) throws Exception { super(currentSd, nextSd); - validator = new DocumentDatabaseChangeValidator(currentDb(), currentDocType(), nextDb(), nextDocType()); + validator = new DocumentDatabaseChangeValidator(ClusterSpec.Id.from("test"), + currentDb(), + currentDocType(), + nextDb(), + nextDocType()); } @Override @@ -42,13 +47,17 @@ public class DocumentDatabaseChangeValidatorTest { "field f3 type string { indexing: summary } " + "field f4 type array<s> { struct-field s1 { indexing: attribute } }"); f.assertValidation(Arrays.asList( - newRestartAction("Field 'f1' changed: add attribute aspect"), - newRestartAction("Field 'f4.s1' changed: add attribute aspect"), - newRefeedAction("indexing-change", + newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f1' changed: add attribute aspect"), + newRestartAction(ClusterSpec.Id.from("test"), + "Field 'f4.s1' changed: add attribute aspect"), + newRefeedAction(ClusterSpec.Id.from("test"), + "indexing-change", ValidationOverrides.empty, "Field 'f2' changed: add index aspect, indexing script: '{ input f2 | summary f2; }' -> " + "'{ input f2 | tokenize normalize stem:\"BEST\" | index f2 | summary f2; }'", Instant.now()), - newRefeedAction("field-type-change", + newRefeedAction(ClusterSpec.Id.from("test"), + "field-type-change", ValidationOverrides.empty, "Field 'f3' changed: data type: 'int' -> 'string'", Instant.now()))); } @@ -56,7 +65,7 @@ public class DocumentDatabaseChangeValidatorTest { @Test public void requireThatRemovingAttributeAspectFromIndexFieldIsOk() throws Exception { Fixture f = new Fixture("field f1 type string { indexing: index | attribute }", - "field f1 type string { indexing: index }"); + "field f1 type string { indexing: index }"); f.assertValidation(); } diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidatorTest.java index 4bba66f0fb3..190c2c8c645 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidatorTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentTypeChangeValidatorTest.java @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.application.validation.change.search; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.document.DocumentType; import com.yahoo.document.Field; import com.yahoo.document.ReferenceDataType; @@ -34,7 +35,9 @@ public class DocumentTypeChangeValidatorTest { public Fixture(String currentSd, String nextSd) throws Exception { super(currentSd, nextSd); - validator = new DocumentTypeChangeValidator(currentDocType(), nextDocType()); + validator = new DocumentTypeChangeValidator(ClusterSpec.Id.from("test"), + currentDocType(), + nextDocType()); } @Override @@ -62,7 +65,8 @@ public class DocumentTypeChangeValidatorTest { public void requireThatDataTypeChangeIsNotOK() throws Exception { Fixture f = new Fixture("field f1 type string { indexing: summary }", "field f1 type int { indexing: summary }"); - f.assertValidation(newRefeedAction("field-type-change", + f.assertValidation(newRefeedAction(ClusterSpec.Id.from("test"), + "field-type-change", ValidationOverrides.empty, "Field 'f1' changed: data type: 'string' -> 'int'", Instant.now())); @@ -72,7 +76,8 @@ public class DocumentTypeChangeValidatorTest { public void requireThatAddingCollectionTypeIsNotOK() throws Exception { Fixture f = new Fixture("field f1 type string { indexing: summary }", "field f1 type array<string> { indexing: summary }"); - f.assertValidation(newRefeedAction("field-type-change", + f.assertValidation(newRefeedAction(ClusterSpec.Id.from("test"), + "field-type-change", ValidationOverrides.empty, "Field 'f1' changed: data type: 'string' -> 'Array<string>'", Instant.now())); } @@ -89,7 +94,8 @@ public class DocumentTypeChangeValidatorTest { public void requireThatNestedDataTypeChangeIsNotOK() throws Exception { Fixture f = new Fixture("field f1 type array<string> { indexing: summary }", "field f1 type array<int> { indexing: summary }"); - f.assertValidation(newRefeedAction("field-type-change", + f.assertValidation(newRefeedAction(ClusterSpec.Id.from("test"), + "field-type-change", ValidationOverrides.empty, "Field 'f1' changed: data type: 'Array<string>' -> 'Array<int>'", Instant.now())); } @@ -98,7 +104,8 @@ public class DocumentTypeChangeValidatorTest { public void requireThatChangedCollectionTypeIsNotOK() throws Exception { Fixture f = new Fixture("field f1 type array<string> { indexing: summary }", "field f1 type weightedset<string> { indexing: summary }"); - f.assertValidation(newRefeedAction("field-type-change", + f.assertValidation(newRefeedAction(ClusterSpec.Id.from("test"), + "field-type-change", ValidationOverrides.empty, "Field 'f1' changed: data type: 'Array<string>' -> 'WeightedSet<string>'", Instant.now())); } @@ -107,10 +114,12 @@ public class DocumentTypeChangeValidatorTest { public void requireThatMultipleDataTypeChangesIsNotOK() throws Exception { Fixture f = new Fixture("field f1 type string { indexing: summary } field f2 type int { indexing: summary }" , "field f2 type string { indexing: summary } field f1 type int { indexing: summary }"); - f.assertValidation(Arrays.asList(newRefeedAction("field-type-change", + f.assertValidation(Arrays.asList(newRefeedAction(ClusterSpec.Id.from("test"), + "field-type-change", ValidationOverrides.empty, "Field 'f1' changed: data type: 'string' -> 'int'", Instant.now()), - newRefeedAction("field-type-change", + newRefeedAction(ClusterSpec.Id.from("test"), + "field-type-change", ValidationOverrides.empty, "Field 'f2' changed: data type: 'int' -> 'string'", Instant.now()))); } @@ -147,7 +156,8 @@ public class DocumentTypeChangeValidatorTest { public void requireThatDataTypeChangeInStructFieldIsNotOK() throws Exception { Fixture f = new Fixture("struct s1 { field f1 type string {} } field f2 type s1 { indexing: summary }", "struct s1 { field f1 type int {} } field f2 type s1 { indexing: summary }"); - f.assertValidation(newRefeedAction("field-type-change", + f.assertValidation(newRefeedAction(ClusterSpec.Id.from("test"), + "field-type-change", ValidationOverrides.empty, "Field 'f2' changed: data type: 's1:{f1:string}' -> 's1:{f1:int}'", Instant.now())); } @@ -156,7 +166,8 @@ public class DocumentTypeChangeValidatorTest { public void requireThatNestedDataTypeChangeInStructFieldIsNotOK() throws Exception { Fixture f = new Fixture("struct s1 { field f1 type array<string> {} } field f2 type s1 { indexing: summary }", "struct s1 { field f1 type array<int> {} } field f2 type s1 { indexing: summary }"); - f.assertValidation(newRefeedAction("field-type-change", + f.assertValidation(newRefeedAction(ClusterSpec.Id.from("test"), + "field-type-change", ValidationOverrides.empty, "Field 'f2' changed: data type: 's1:{f1:Array<string>}' -> 's1:{f1:Array<int>}'", Instant.now())); } @@ -165,7 +176,8 @@ public class DocumentTypeChangeValidatorTest { public void requireThatDataTypeChangeInNestedStructFieldIsNotOK() throws Exception { Fixture f = new Fixture("struct s1 { field f1 type string {} } struct s2 { field f2 type s1 {} } field f3 type s2 { indexing: summary }", "struct s1 { field f1 type int {} } struct s2 { field f2 type s1 {} } field f3 type s2 { indexing: summary }"); - f.assertValidation(newRefeedAction("field-type-change", + f.assertValidation(newRefeedAction(ClusterSpec.Id.from("test"), + "field-type-change", ValidationOverrides.empty, "Field 'f3' changed: data type: 's2:{s1:{f1:string}}' -> 's2:{s1:{f1:int}}'", Instant.now())); } @@ -174,16 +186,17 @@ public class DocumentTypeChangeValidatorTest { public void requireThatMultipleDataTypeChangesInStructFieldIsNotOK() throws Exception { Fixture f = new Fixture("struct s1 { field f1 type string {} field f2 type int {} } field f3 type s1 { indexing: summary }", "struct s1 { field f1 type int {} field f2 type string {} } field f3 type s1 { indexing: summary }"); - f.assertValidation(newRefeedAction("field-type-change", + f.assertValidation(newRefeedAction(ClusterSpec.Id.from("test"), + "field-type-change", ValidationOverrides.empty, "Field 'f3' changed: data type: 's1:{f1:string,f2:int}' -> 's1:{f1:int,f2:string}'", Instant.now())); } @Test public void requireThatChangingTargetTypeOfReferenceFieldIsNotOK() { - DocumentTypeChangeValidator validator = new DocumentTypeChangeValidator( - createDocumentTypeWithReferenceField("oldDoc"), - createDocumentTypeWithReferenceField("newDoc")); + var validator = new DocumentTypeChangeValidator(ClusterSpec.Id.from("test"), + createDocumentTypeWithReferenceField("oldDoc"), + createDocumentTypeWithReferenceField("newDoc")); List<VespaConfigChangeAction> result = validator.validate(ValidationOverrides.empty, Instant.now()); assertEquals(1, result.size()); VespaConfigChangeAction action = result.get(0); diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidatorTest.java index 7a5b235737a..8ffd02a4381 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidatorTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidatorTest.java @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.application.validation.change.search; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.vespa.indexinglanguage.expressions.ScriptExpression; import com.yahoo.config.application.api.ValidationOverrides; import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction; @@ -20,8 +21,9 @@ public class IndexingScriptChangeValidatorTest { public Fixture(String currentSd, String nextSd) throws Exception { super(currentSd, nextSd); - validator = new IndexingScriptChangeValidator(currentDb().getDerivedConfiguration().getSearch(), - nextDb().getDerivedConfiguration().getSearch()); + validator = new IndexingScriptChangeValidator(ClusterSpec.Id.from("test"), + currentDb().getDerivedConfiguration().getSearch(), + nextDb().getDerivedConfiguration().getSearch()); } @Override @@ -31,6 +33,7 @@ public class IndexingScriptChangeValidatorTest { } private static class ScriptFixture { + private final ScriptExpression currentScript; private final ScriptExpression nextScript; @@ -44,15 +47,16 @@ public class IndexingScriptChangeValidatorTest { } } - private static String FIELD = "field f1 type string"; - private static String FIELD_F2 = "field f2 type string"; + private static final String FIELD = "field f1 type string"; + private static final String FIELD_F2 = "field f2 type string"; private static VespaConfigChangeAction expectedAction(String changedMsg, String fromScript, String toScript) { return expectedAction("f1", changedMsg, fromScript, toScript); } private static VespaConfigChangeAction expectedAction(String field, String changedMsg, String fromScript, String toScript) { - return VespaRefeedAction.of("indexing-change", + return VespaRefeedAction.of(ClusterSpec.Id.from("test"), + "indexing-change", ValidationOverrides.empty, "Field '" + field + "' changed: " + (changedMsg.isEmpty() ? "" : changedMsg + ", ") + diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/StructFieldAttributeChangeValidatorTestCase.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/StructFieldAttributeChangeValidatorTestCase.java index 2d68284c9a5..04efffab438 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/StructFieldAttributeChangeValidatorTestCase.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/StructFieldAttributeChangeValidatorTestCase.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.model.application.validation.change.search; import com.yahoo.config.application.api.ValidationOverrides; +import com.yahoo.config.provision.ClusterSpec; import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction; import org.junit.Test; @@ -17,16 +18,18 @@ import static com.yahoo.vespa.model.application.validation.change.ConfigChangeTe public class StructFieldAttributeChangeValidatorTestCase { private static class Fixture extends ContentClusterFixture { - private StructFieldAttributeChangeValidator structFieldAttributeValidator; - private DocumentTypeChangeValidator docTypeValidator; + + private final StructFieldAttributeChangeValidator structFieldAttributeValidator; + private final DocumentTypeChangeValidator docTypeValidator; public Fixture(String currentSd, String nextSd) throws Exception { super(currentSd, nextSd); - structFieldAttributeValidator = new StructFieldAttributeChangeValidator(currentDocType(), - currentDb().getDerivedConfiguration().getAttributeFields(), - nextDocType(), - nextDb().getDerivedConfiguration().getAttributeFields()); - docTypeValidator = new DocumentTypeChangeValidator(currentDocType(), nextDocType()); + structFieldAttributeValidator = new StructFieldAttributeChangeValidator(ClusterSpec.Id.from("test"), + currentDocType(), + currentDb().getDerivedConfiguration().getAttributeFields(), + nextDocType(), + nextDb().getDerivedConfiguration().getAttributeFields()); + docTypeValidator = new DocumentTypeChangeValidator(ClusterSpec.Id.from("test"), currentDocType(), nextDocType()); } @Override @@ -49,34 +52,34 @@ public class StructFieldAttributeChangeValidatorTestCase { @Test public void adding_attribute_aspect_to_struct_field_requires_restart() throws Exception { validate(arrayOfStruct(oneFieldStruct(), ""), - arrayOfStruct(oneFieldStruct(), structAttribute("s1")), - newRestartAction("Field 'f1.s1' changed: add attribute aspect")); + arrayOfStruct(oneFieldStruct(), structAttribute("s1")), + newRestartAction(ClusterSpec.Id.from("test"), "Field 'f1.s1' changed: add attribute aspect")); validate(mapOfStruct(oneFieldStruct(), ""), - mapOfStruct(oneFieldStruct(), structAttribute("key")), - newRestartAction("Field 'f1.key' changed: add attribute aspect")); + mapOfStruct(oneFieldStruct(), structAttribute("key")), + newRestartAction(ClusterSpec.Id.from("test"), "Field 'f1.key' changed: add attribute aspect")); validate(mapOfStruct(oneFieldStruct(), ""), - mapOfStruct(oneFieldStruct(), structAttribute("value.s1")), - newRestartAction("Field 'f1.value.s1' changed: add attribute aspect")); + mapOfStruct(oneFieldStruct(), structAttribute("value.s1")), + newRestartAction(ClusterSpec.Id.from("test"), "Field 'f1.value.s1' changed: add attribute aspect")); validate(mapOfPrimitive(""), mapOfPrimitive(structAttribute("key")), - newRestartAction("Field 'f1.key' changed: add attribute aspect")); + newRestartAction(ClusterSpec.Id.from("test"), "Field 'f1.key' changed: add attribute aspect")); validate(mapOfPrimitive(""), mapOfPrimitive(structAttribute("value")), - newRestartAction("Field 'f1.value' changed: add attribute aspect")); + newRestartAction(ClusterSpec.Id.from("test"), "Field 'f1.value' changed: add attribute aspect")); } @Test public void removing_attribute_aspect_from_struct_field_is_ok() throws Exception { validate(arrayOfStruct(oneFieldStruct(), structAttribute("s1")), - arrayOfStruct(oneFieldStruct(), "")); + arrayOfStruct(oneFieldStruct(), "")); validate(mapOfStruct(oneFieldStruct(), structAttribute("key")), - mapOfStruct(oneFieldStruct(), "")); + mapOfStruct(oneFieldStruct(), "")); validate(mapOfStruct(oneFieldStruct(), structAttribute("value.s1")), - mapOfStruct(oneFieldStruct(), "")); + mapOfStruct(oneFieldStruct(), "")); validate(mapOfPrimitive(structAttribute("key")), mapOfPrimitive("")); @@ -89,34 +92,34 @@ public class StructFieldAttributeChangeValidatorTestCase { arrayOfStruct(twoFieldStruct(), structAttribute("s2"))); validate(mapOfStruct(oneFieldStruct(), ""), - mapOfStruct(twoFieldStruct(), structAttribute("value.s2"))); + mapOfStruct(twoFieldStruct(), structAttribute("value.s2"))); } @Test public void removing_struct_field_with_attribute_aspect_is_ok() throws Exception { validate(arrayOfStruct(twoFieldStruct(), structAttribute("s2")), - arrayOfStruct(oneFieldStruct(), "")); + arrayOfStruct(oneFieldStruct(), "")); validate(mapOfStruct(twoFieldStruct(), structAttribute("value.s2")), - mapOfStruct(oneFieldStruct(), "")); + mapOfStruct(oneFieldStruct(), "")); } @Test public void adding_struct_field_without_attribute_aspect_is_ok() throws Exception { validate(arrayOfStruct(oneFieldStruct(), ""), - arrayOfStruct(twoFieldStruct(), "")); + arrayOfStruct(twoFieldStruct(), "")); validate(mapOfStruct(oneFieldStruct(), ""), - mapOfStruct(twoFieldStruct(), "")); + mapOfStruct(twoFieldStruct(), "")); } @Test public void removing_struct_field_without_attribute_aspect_is_ok() throws Exception { validate(arrayOfStruct(twoFieldStruct(), ""), - arrayOfStruct(oneFieldStruct(), "")); + arrayOfStruct(oneFieldStruct(), "")); validate(mapOfStruct(twoFieldStruct(), ""), - mapOfStruct(oneFieldStruct(), "")); + mapOfStruct(oneFieldStruct(), "")); } private static String oneFieldStruct() { |