diff options
author | Arne H Juul <arnej@yahooinc.com> | 2022-02-17 18:42:02 +0000 |
---|---|---|
committer | Arne H Juul <arnej@yahooinc.com> | 2022-02-17 18:42:02 +0000 |
commit | 419ca82c28e7ea97ae7f7f1265eca158fae0844c (patch) | |
tree | 55ee9be894ad4f862ffeb12f733048451ff8c063 /configserver | |
parent | c1e701cd70e2531302a6e72d0900772f4296ab2c (diff) | |
parent | 70e50ea1b7d974ffb2e1db805e8e273eeffd6d0e (diff) |
Merge branch 'master' into arnej/rename-summaryfeatures-back-to-original
Diffstat (limited to 'configserver')
47 files changed, 451 insertions, 327 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java index 80194337daa..ccd9f0e7044 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java @@ -88,7 +88,6 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; -import java.net.URI; import java.nio.file.Files; import java.nio.file.attribute.BasicFileAttributes; import java.time.Clock; @@ -111,8 +110,8 @@ import java.util.stream.Collectors; import static com.yahoo.config.model.api.container.ContainerServiceType.CONTAINER; import static com.yahoo.config.model.api.container.ContainerServiceType.LOGSERVER_CONTAINER; -import static com.yahoo.vespa.config.server.application.ConfigConvergenceChecker.ServiceResponse; import static com.yahoo.vespa.config.server.application.ConfigConvergenceChecker.ServiceListResponse; +import static com.yahoo.vespa.config.server.application.ConfigConvergenceChecker.ServiceResponse; import static com.yahoo.vespa.config.server.filedistribution.FileDistributionUtil.fileReferenceExistsOnDisk; import static com.yahoo.vespa.config.server.filedistribution.FileDistributionUtil.getFileReferencesOnDisk; import static com.yahoo.vespa.config.server.tenant.TenantRepository.HOSTED_VESPA_TENANT; @@ -147,6 +146,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye private final Metric metric; private final SecretStoreValidator secretStoreValidator; private final ClusterReindexingStatusClient clusterReindexingStatusClient; + private final FlagSource flagSource; @Inject public ApplicationRepository(TenantRepository tenantRepository, @@ -203,8 +203,10 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye this.metric = Objects.requireNonNull(metric); this.secretStoreValidator = Objects.requireNonNull(secretStoreValidator); this.clusterReindexingStatusClient = clusterReindexingStatusClient; + this.flagSource = flagSource; } + // Should be used by tests only (first constructor in this class makes sure we use injectable components where possible) public static class Builder { private TenantRepository tenantRepository; private Optional<Provisioner> hostProvisioner; @@ -217,6 +219,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye private Metric metric = new NullMetric(); private SecretStoreValidator secretStoreValidator = new SecretStoreValidator(new SecretStoreProvider().get()); private FlagSource flagSource = new InMemoryFlagSource(); + private ConfigConvergenceChecker configConvergenceChecker = new ConfigConvergenceChecker(); public Builder withTenantRepository(TenantRepository tenantRepository) { this.tenantRepository = tenantRepository; @@ -280,11 +283,16 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye return this; } + public Builder withConfigConvergenceChecker(ConfigConvergenceChecker configConvergenceChecker) { + this.configConvergenceChecker = configConvergenceChecker; + return this; + } + public ApplicationRepository build() { return new ApplicationRepository(tenantRepository, hostProvisioner, InfraDeployerProvider.empty().getInfraDeployer(), - new ConfigConvergenceChecker(), + configConvergenceChecker, httpProxy, configserverConfig, orchestrator, @@ -631,7 +639,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye private List<String> sortedUnusedFileReferences(File fileReferencesPath, Set<String> fileReferencesInUse, Duration keepFileReferences) { Set<String> fileReferencesOnDisk = getFileReferencesOnDisk(fileReferencesPath); log.log(Level.FINE, () -> "File references on disk (in " + fileReferencesPath + "): " + fileReferencesOnDisk); - Instant instant = Instant.now().minus(keepFileReferences); + Instant instant = clock.instant().minus(keepFileReferences); return fileReferencesOnDisk .stream() .filter(fileReference -> ! fileReferencesInUse.contains(fileReference)) @@ -747,10 +755,9 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye } public ServiceListResponse servicesToCheckForConfigConvergence(ApplicationId applicationId, - URI uri, Duration timeoutPerService, Optional<Version> vespaVersion) { - return convergeChecker.getServiceConfigGenerations(getApplication(applicationId, vespaVersion), uri, timeoutPerService); + return convergeChecker.checkConvergenceForAllServices(getApplication(applicationId, vespaVersion), timeoutPerService); } public ConfigConvergenceChecker configConvergenceChecker() { return convergeChecker; } @@ -1016,6 +1023,8 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye return applicationId.orElse(null); } + public FlagSource flagSource() { return flagSource; } + private Session validateThatLocalSessionIsNotActive(Tenant tenant, long sessionId) { Session session = getLocalSession(tenant, sessionId); if (Session.Status.ACTIVATE.equals(session.getStatus())) { @@ -1042,6 +1051,12 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye return getTenant(appId).getSessionRepository().getActiveApplicationSet(appId); } + public Application getActiveApplication(ApplicationId applicationId) { + return getActiveApplicationSet(applicationId) + .map(a -> a.getForVersionOrLatest(Optional.empty(), clock.instant())) + .orElseThrow(() -> new RuntimeException("Found no active application for " + applicationId)); + } + private File decompressApplication(InputStream in, String contentType, File tempDir) { try (CompressedApplicationInputStream application = CompressedApplicationInputStream.createFromCompressedStream(in, contentType)) { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerBootstrap.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerBootstrap.java index 57e49ef3e8d..8d51a91bc3a 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerBootstrap.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerBootstrap.java @@ -17,6 +17,7 @@ import com.yahoo.vespa.config.server.version.VersionState; import com.yahoo.vespa.flags.FlagSource; import com.yahoo.yolean.Exceptions; +import java.time.Clock; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; @@ -73,6 +74,7 @@ public class ConfigServerBootstrap extends AbstractComponent implements Runnable private final RedeployingApplicationsFails exitIfRedeployingApplicationsFails; private final ExecutorService rpcServerExecutor; private final ConfigServerMaintenance configServerMaintenance; + private final Clock clock; @SuppressWarnings("unused") // Injected component @Inject @@ -83,21 +85,22 @@ public class ConfigServerBootstrap extends AbstractComponent implements Runnable applicationRepository.configserverConfig().hostedVespa() ? VipStatusMode.VIP_STATUS_FILE : VipStatusMode.VIP_STATUS_PROGRAMMATICALLY, - flagSource, convergence); + flagSource, convergence, Clock.systemUTC()); } // For testing only ConfigServerBootstrap(ApplicationRepository applicationRepository, RpcServer server, VersionState versionState, StateMonitor stateMonitor, VipStatus vipStatus, VipStatusMode vipStatusMode, - FlagSource flagSource, ConfigConvergenceChecker convergence) { + FlagSource flagSource, ConfigConvergenceChecker convergence, Clock clock) { this(applicationRepository, server, versionState, stateMonitor, vipStatus, - FOR_TESTING_NO_BOOTSTRAP_OF_APPS, CONTINUE, vipStatusMode, flagSource, convergence); + FOR_TESTING_NO_BOOTSTRAP_OF_APPS, CONTINUE, vipStatusMode, flagSource, convergence, clock); } private ConfigServerBootstrap(ApplicationRepository applicationRepository, RpcServer server, VersionState versionState, StateMonitor stateMonitor, VipStatus vipStatus, Mode mode, RedeployingApplicationsFails exitIfRedeployingApplicationsFails, - VipStatusMode vipStatusMode, FlagSource flagSource, ConfigConvergenceChecker convergence) { + VipStatusMode vipStatusMode, FlagSource flagSource, ConfigConvergenceChecker convergence, + Clock clock) { this.applicationRepository = applicationRepository; this.server = server; this.versionState = versionState; @@ -107,6 +110,7 @@ public class ConfigServerBootstrap extends AbstractComponent implements Runnable this.maxDurationOfRedeployment = Duration.ofSeconds(configserverConfig.maxDurationOfBootstrap()); this.sleepTimeWhenRedeployingFails = Duration.ofSeconds(configserverConfig.sleepTimeWhenRedeployingFails()); this.exitIfRedeployingApplicationsFails = exitIfRedeployingApplicationsFails; + this.clock = clock; rpcServerExecutor = Executors.newSingleThreadExecutor(new DaemonThreadFactory("config server RPC server")); configServerMaintenance = new ConfigServerMaintenance(configserverConfig, @@ -197,8 +201,8 @@ public class ConfigServerBootstrap extends AbstractComponent implements Runnable private void startRpcServerWithFileDistribution() { rpcServerExecutor.execute(server); - Instant end = Instant.now().plus(Duration.ofSeconds(10)); - while (!server.isRunning() && Instant.now().isBefore(end)) { + Instant end = clock.instant().plus(Duration.ofSeconds(10)); + while (!server.isRunning() && clock.instant().isBefore(end)) { try { Thread.sleep(10); } catch (InterruptedException e) { @@ -220,7 +224,7 @@ public class ConfigServerBootstrap extends AbstractComponent implements Runnable } private void redeployAllApplications() throws InterruptedException { - Instant end = Instant.now().plus(maxDurationOfRedeployment); + Instant end = clock.instant().plus(maxDurationOfRedeployment); List<ApplicationId> applicationsToRedeploy = applicationRepository.listApplications(); Collections.shuffle(applicationsToRedeploy); long failCount = 0; @@ -233,7 +237,7 @@ public class ConfigServerBootstrap extends AbstractComponent implements Runnable log.log(Level.INFO, "Redeployment of " + applicationsToRedeploy + " not finished, will retry in " + sleepTime); Thread.sleep(sleepTime.toMillis()); } - } while ( ! applicationsToRedeploy.isEmpty() && Instant.now().isBefore(end)); + } while ( ! applicationsToRedeploy.isEmpty() && clock.instant().isBefore(end)); if ( ! applicationsToRedeploy.isEmpty()) throw new RuntimeException("Redeploying applications not finished after " + maxDurationOfRedeployment + @@ -296,11 +300,11 @@ public class ConfigServerBootstrap extends AbstractComponent implements Runnable } private void logProgress(LogState logState, int failedDeployments, int finishedDeployments) { - if ( ! Duration.between(logState.lastLogged, Instant.now()).minus(Duration.ofSeconds(10)).isNegative() + if ( ! Duration.between(logState.lastLogged, clock.instant()).minus(Duration.ofSeconds(10)).isNegative() && (logState.failedDeployments != failedDeployments || logState.finishedDeployments != finishedDeployments)) { log.log(Level.INFO, () -> finishedDeployments + " of " + logState.applicationCount + " apps redeployed " + "(" + failedDeployments + " failed)"); - logState.update(Instant.now(), failedDeployments, finishedDeployments); + logState.update(clock.instant(), failedDeployments, finishedDeployments); } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/TimeoutBudget.java b/configserver/src/main/java/com/yahoo/vespa/config/server/TimeoutBudget.java index d3295c023b0..a96f9db855c 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/TimeoutBudget.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/TimeoutBudget.java @@ -1,7 +1,7 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server; -import com.google.common.util.concurrent.UncheckedTimeoutException; +import com.yahoo.concurrent.UncheckedTimeoutException; import java.time.Clock; import java.time.Duration; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigConvergenceChecker.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigConvergenceChecker.java index ad14cf4aab6..a49af0a0e51 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigConvergenceChecker.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigConvergenceChecker.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.Inject; import com.yahoo.component.AbstractComponent; import com.yahoo.concurrent.DaemonThreadFactory; +import com.yahoo.config.model.api.ApplicationClusterInfo; import com.yahoo.config.model.api.HostInfo; import com.yahoo.config.model.api.PortInfo; import com.yahoo.config.model.api.ServiceInfo; @@ -39,14 +40,17 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.stream.Collectors; import static com.yahoo.config.model.api.container.ContainerServiceType.CLUSTERCONTROLLER_CONTAINER; import static com.yahoo.config.model.api.container.ContainerServiceType.CONTAINER; import static com.yahoo.config.model.api.container.ContainerServiceType.LOGSERVER_CONTAINER; +import static com.yahoo.config.model.api.container.ContainerServiceType.METRICS_PROXY_CONTAINER; import static com.yahoo.config.model.api.container.ContainerServiceType.QRSERVER; /** @@ -65,13 +69,14 @@ public class ConfigConvergenceChecker extends AbstractComponent { QRSERVER.serviceName, LOGSERVER_CONTAINER.serviceName, CLUSTERCONTROLLER_CONTAINER.serviceName, + METRICS_PROXY_CONTAINER.serviceName, "searchnode", "storagenode", "distributor" ); - private final Executor responseHandlerExecutor = + private final ExecutorService responseHandlerExecutor = Executors.newSingleThreadExecutor(new DaemonThreadFactory("config-convergence-checker-response-handler-")); private final ObjectMapper jsonMapper = new ObjectMapper(); @@ -80,20 +85,43 @@ public class ConfigConvergenceChecker extends AbstractComponent { /** Fetches the active config generation for all services in the given application. */ public Map<ServiceInfo, Long> getServiceConfigGenerations(Application application, Duration timeoutPerService) { + return getServiceConfigGenerations(application, timeoutPerService, true); + } + + /** + * Fetches the active config generation for all services in the given application. Will not check services + * which defer config changes until restart if checkAll is false. + */ + private Map<ServiceInfo, Long> getServiceConfigGenerations(Application application, Duration timeoutPerService, boolean checkAll) { List<ServiceInfo> servicesToCheck = new ArrayList<>(); application.getModel().getHosts() .forEach(host -> host.getServices().stream() .filter(service -> serviceTypesToCheck.contains(service.getServiceType())) + .filter(serviceInfo -> shouldCheckService(checkAll, application, serviceInfo)) .forEach(service -> getStatePort(service).ifPresent(port -> servicesToCheck.add(service)))); + log.log(Level.FINE, "Services to check for config convergence: " + servicesToCheck); return getServiceGenerations(servicesToCheck, timeoutPerService); } - /** Check all services in given application. Returns the minimum current generation of all services */ - public ServiceListResponse getServiceConfigGenerations(Application application, URI uri, Duration timeoutPerService) { - Map<ServiceInfo, Long> currentGenerations = getServiceConfigGenerations(application, timeoutPerService); + /** Checks all services in given application. Returns the minimum current generation of all services */ + public ServiceListResponse checkConvergenceForAllServices(Application application, Duration timeoutPerService) { + return checkConvergence(application, timeoutPerService, true); + } + + /** + * Checks services except those which defer config changes until restart in the given application. + * Returns the minimum current generation of those services. + */ + public ServiceListResponse checkConvergenceUnlessDeferringChangesUntilRestart(Application application) { + Duration timeoutPerService = Duration.ofSeconds(10); + return checkConvergence(application, timeoutPerService, false); + } + + private ServiceListResponse checkConvergence(Application application, Duration timeoutPerService, boolean checkAll) { + Map<ServiceInfo, Long> currentGenerations = getServiceConfigGenerations(application, timeoutPerService, checkAll); long currentGeneration = currentGenerations.values().stream().mapToLong(Long::longValue).min().orElse(-1); - return new ServiceListResponse(currentGenerations, uri, application.getApplicationGeneration(), currentGeneration); + return new ServiceListResponse(currentGenerations, application.getApplicationGeneration(), currentGeneration); } /** Check service identified by host and port in given application */ @@ -113,6 +141,26 @@ public class ConfigConvergenceChecker extends AbstractComponent { } } + private boolean shouldCheckService(boolean checkServicesWithDeferChangesUntilRestart, Application application, ServiceInfo serviceInfo) { + if (checkServicesWithDeferChangesUntilRestart) return true; + if (isNotContainer(serviceInfo)) return true; + return serviceIsInClusterWhichShouldBeChecked(application, serviceInfo); + } + + private boolean isNotContainer(ServiceInfo serviceInfo) { + return ! List.of(CONTAINER.serviceName, QRSERVER.serviceName, METRICS_PROXY_CONTAINER).contains(serviceInfo.getServiceType()); + } + + // Don't check service in a cluster which uses restartOnDeploy (new config will not be used until service is restarted) + private boolean serviceIsInClusterWhichShouldBeChecked(Application application, ServiceInfo serviceInfo) { + Set<ApplicationClusterInfo> excludeFromChecking = application.getModel().applicationClusterInfo() + .stream() + .filter(ApplicationClusterInfo::getDeferChangesUntilRestart) + .collect(Collectors.toSet()); + + return excludeFromChecking.stream().noneMatch(info -> info.name().equals(serviceInfo.getProperty("clustername").orElse(""))); + } + /** Gets service generation for a list of services (in parallel). */ private Map<ServiceInfo, Long> getServiceGenerations(List<ServiceInfo> services, Duration timeout) { try (CloseableHttpAsyncClient client = createHttpClient()) { @@ -196,6 +244,16 @@ public class ConfigConvergenceChecker extends AbstractComponent { .findFirst(); } + @Override + public void deconstruct() { + responseHandlerExecutor.shutdown(); + try { + responseHandlerExecutor.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + log.log(Level.WARNING, "Unable to shutdown executor", e); + } + } + private static long generationFromContainerState(JsonNode state) { return state.get("config").get("generation").asLong(-1); } @@ -256,23 +314,23 @@ public class ConfigConvergenceChecker extends AbstractComponent { public final boolean converged; public final Optional<String> errorMessage; - public ServiceResponse(Status status, Long wantedGeneration) { - this(status, wantedGeneration, 0L); + public ServiceResponse(Status status, long wantedGeneration) { + this(status, wantedGeneration, 0); } - public ServiceResponse(Status status, Long wantedGeneration, Long currentGeneration) { + public ServiceResponse(Status status, long wantedGeneration, long currentGeneration) { this(status, wantedGeneration, currentGeneration, false); } - public ServiceResponse(Status status, Long wantedGeneration, Long currentGeneration, boolean converged) { + public ServiceResponse(Status status, long wantedGeneration, long currentGeneration, boolean converged) { this(status, wantedGeneration, currentGeneration, converged, Optional.empty()); } - public ServiceResponse(Status status, Long wantedGeneration, String errorMessage) { - this(status, wantedGeneration, 0L, false, Optional.ofNullable(errorMessage)); + public ServiceResponse(Status status, long wantedGeneration, String errorMessage) { + this(status, wantedGeneration, 0, false, Optional.ofNullable(errorMessage)); } - private ServiceResponse(Status status, Long wantedGeneration, Long currentGeneration, boolean converged, Optional<String> errorMessage) { + private ServiceResponse(Status status, long wantedGeneration, long currentGeneration, boolean converged, Optional<String> errorMessage) { this.status = status; this.wantedGeneration = wantedGeneration; this.currentGeneration = currentGeneration; @@ -285,15 +343,15 @@ public class ConfigConvergenceChecker extends AbstractComponent { public static class ServiceListResponse { public final List<Service> services = new ArrayList<>(); - public final URI uri; public final long wantedGeneration; public final long currentGeneration; + public final boolean converged; - public ServiceListResponse(Map<ServiceInfo, Long> services, URI uri, long wantedGeneration, long currentGeneration) { + public ServiceListResponse(Map<ServiceInfo, Long> services, long wantedGeneration, long currentGeneration) { services.forEach((key, value) -> this.services.add(new Service(key, value))); - this.uri = uri; this.wantedGeneration = wantedGeneration; this.currentGeneration = currentGeneration; + this.converged = currentGeneration >= wantedGeneration; } public List<Service> services() { return services; } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigNotConvergedException.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigNotConvergedException.java index f0711e5c238..88cddb93d9d 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigNotConvergedException.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigNotConvergedException.java @@ -5,7 +5,13 @@ package com.yahoo.vespa.config.server.application; * @author Ulf Lilleengen */ public class ConfigNotConvergedException extends RuntimeException { + + public ConfigNotConvergedException(Throwable t) { + super(t); + } + public ConfigNotConvergedException(String message) { super(message); } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java index 98ddf702a7f..937ec2bb0e7 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java @@ -472,7 +472,7 @@ public class TenantApplications implements RequestHandler, HostValidator<Applica // If some are missing, quorum is enough, but wait for all up to 5 seconds before returning if (respondents.size() >= barrierMemberCount()) { if (gotQuorumTime.isBefore(startTime)) - gotQuorumTime = Instant.now(); + gotQuorumTime = clock.instant(); // Give up if more than some time has passed since we got quorum, otherwise continue if (Duration.between(Instant.now(), gotQuorumTime.plus(waitForAll)).isNegative()) { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/DeployHandlerLogger.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/DeployHandlerLogger.java index 71e5489fb2e..d7977477f30 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/DeployHandlerLogger.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/DeployHandlerLogger.java @@ -36,6 +36,7 @@ public class DeployHandlerLogger implements DeployLogger { } @Override + @SuppressWarnings("deprecation") public void log(Level level, String message) { if (level.intValue() <= LogLevel.DEBUG.intValue() && !verbose) return; @@ -46,6 +47,7 @@ public class DeployHandlerLogger implements DeployLogger { } @Override + @SuppressWarnings("deprecation") public void logApplicationPackage(Level level, String message) { if (level.intValue() <= LogLevel.DEBUG.intValue() && !verbose) return; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java index 4b7e39f48a4..e6159cbfa33 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.config.server.deploy; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; +import com.yahoo.concurrent.UncheckedTimeoutException; import com.yahoo.config.FileReference; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.model.api.ServiceInfo; @@ -19,6 +20,9 @@ import com.yahoo.vespa.config.server.ApplicationRepository; import com.yahoo.vespa.config.server.ApplicationRepository.ActionTimer; import com.yahoo.vespa.config.server.ApplicationRepository.Activation; import com.yahoo.vespa.config.server.TimeoutBudget; +import com.yahoo.vespa.config.server.application.Application; +import com.yahoo.vespa.config.server.application.ConfigConvergenceChecker; +import com.yahoo.vespa.config.server.application.ConfigNotConvergedException; import com.yahoo.vespa.config.server.configchange.ConfigChangeActions; import com.yahoo.vespa.config.server.configchange.ReindexActions; import com.yahoo.vespa.config.server.configchange.RestartActions; @@ -35,6 +39,8 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; +import static com.yahoo.vespa.config.server.application.ConfigConvergenceChecker.ServiceListResponse; + /** * The process of deploying an application. * Deployments are created by an {@link ApplicationRepository}. @@ -149,6 +155,9 @@ public class Deployment implements com.yahoo.config.provision.Deployment { RestartActions restartActions = configChangeActions.getRestartActions().useForInternalRestart(internalRedeploy); if ( ! restartActions.isEmpty()) { + + waitForConfigToConverge(applicationId); + Set<String> hostnames = restartActions.getEntries().stream() .flatMap(entry -> entry.getServices().stream()) .map(ServiceInfo::getHostName) @@ -165,6 +174,30 @@ public class Deployment implements com.yahoo.config.provision.Deployment { } } + private void waitForConfigToConverge(ApplicationId applicationId) { + deployLogger.log(Level.INFO, "Wait for all services to use new config generation before restarting"); + while (true) { + try { + params.get().getTimeoutBudget().assertNotTimedOut( + () -> "Timeout exceeded while waiting for config convergence for " + applicationId); + } catch (UncheckedTimeoutException e) { + throw new ConfigNotConvergedException(e); + } + + ConfigConvergenceChecker convergenceChecker = applicationRepository.configConvergenceChecker(); + Application app = applicationRepository.getActiveApplication(applicationId); + ServiceListResponse response = convergenceChecker.checkConvergenceUnlessDeferringChangesUntilRestart(app); + if (response.converged) { + deployLogger.log(Level.INFO, "Services converged on new config generation " + response.currentGeneration); + return; + } else { + deployLogger.log(Level.INFO, "Services did not converge on new config generation " + + response.wantedGeneration + ", current generation: " + response.currentGeneration + ", will retry"); + try { Thread.sleep(10_000); } catch (InterruptedException e) { /* ignore */ } + } + } + } + private void storeReindexing(ApplicationId applicationId, long requiredSession) { applicationRepository.modifyReindexing(applicationId, reindexing -> { if (configChangeActions != null) diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java index 8c1fcf9d9f2..38245f26a18 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java @@ -177,24 +177,20 @@ public class ModelContextImpl implements ModelContext { private final boolean skipMbusReplyThread; private final boolean useAsyncMessageHandlingOnSchedule; private final double feedConcurrency; - private final boolean enableFeedBlockInDistributor; private final List<String> allowedAthenzProxyIdentities; private final int maxActivationInhibitedOutOfSyncGroups; private final ToIntFunction<ClusterSpec.Type> jvmOmitStackTraceInFastThrow; private final int maxConcurrentMergesPerContentNode; private final int maxMergeQueueSize; - private final boolean ignoreMergeQueueLimit; private final double resourceLimitDisk; private final double resourceLimitMemory; private final double minNodeRatioPerGroup; private final int metricsproxyNumThreads; + private final int availableProcessors; private final boolean containerDumpHeapOnShutdownTimeout; private final double containerShutdownTimeout; - private final int distributorMergeBusyWait; - private final boolean distributorEnhancedMaintenanceScheduling; private final int maxUnCommittedMemory; private final boolean forwardIssuesAsErrors; - private final boolean asyncApplyBucketDiff; private final boolean ignoreThreadStackSizes; private final boolean unorderedMergeChaining; private final boolean useV8GeoPositions; @@ -204,6 +200,11 @@ public class ModelContextImpl implements ModelContext { private final List<String> ignoredHttpUserAgents; private final boolean enableServerOcspStapling; private final String persistenceAsyncThrottling; + private final String mergeThrottlingPolicy; + private final double persistenceThrottlingWsDecrementFactor; + private final double persistenceThrottlingWsBackoff; + private final boolean inhibitDefaultMergesWhenGlobalMergesPending; + private final boolean useQrserverServiceName; private final boolean avoidRenamingSummaryFeatures; public FeatureFlags(FlagSource source, ApplicationId appId) { @@ -220,24 +221,20 @@ public class ModelContextImpl implements ModelContext { this.skipMbusReplyThread = flagValue(source, appId, Flags.SKIP_MBUS_REPLY_THREAD); this.useAsyncMessageHandlingOnSchedule = flagValue(source, appId, Flags.USE_ASYNC_MESSAGE_HANDLING_ON_SCHEDULE); this.feedConcurrency = flagValue(source, appId, Flags.FEED_CONCURRENCY); - this.enableFeedBlockInDistributor = flagValue(source, appId, Flags.ENABLE_FEED_BLOCK_IN_DISTRIBUTOR); this.allowedAthenzProxyIdentities = flagValue(source, appId, Flags.ALLOWED_ATHENZ_PROXY_IDENTITIES); this.maxActivationInhibitedOutOfSyncGroups = flagValue(source, appId, Flags.MAX_ACTIVATION_INHIBITED_OUT_OF_SYNC_GROUPS); this.jvmOmitStackTraceInFastThrow = type -> flagValueAsInt(source, appId, type, PermanentFlags.JVM_OMIT_STACK_TRACE_IN_FAST_THROW); this.maxConcurrentMergesPerContentNode = flagValue(source, appId, Flags.MAX_CONCURRENT_MERGES_PER_NODE); this.maxMergeQueueSize = flagValue(source, appId, Flags.MAX_MERGE_QUEUE_SIZE); - this.ignoreMergeQueueLimit = flagValue(source, appId, Flags.IGNORE_MERGE_QUEUE_LIMIT); this.resourceLimitDisk = flagValue(source, appId, PermanentFlags.RESOURCE_LIMIT_DISK); this.resourceLimitMemory = flagValue(source, appId, PermanentFlags.RESOURCE_LIMIT_MEMORY); this.minNodeRatioPerGroup = flagValue(source, appId, Flags.MIN_NODE_RATIO_PER_GROUP); this.metricsproxyNumThreads = flagValue(source, appId, Flags.METRICSPROXY_NUM_THREADS); + this.availableProcessors = flagValue(source, appId, Flags.AVAILABLE_PROCESSORS); this.containerDumpHeapOnShutdownTimeout = flagValue(source, appId, Flags.CONTAINER_DUMP_HEAP_ON_SHUTDOWN_TIMEOUT); this.containerShutdownTimeout = flagValue(source, appId,Flags.CONTAINER_SHUTDOWN_TIMEOUT); - this.distributorMergeBusyWait = flagValue(source, appId, Flags.DISTRIBUTOR_MERGE_BUSY_WAIT); - this.distributorEnhancedMaintenanceScheduling = flagValue(source, appId, Flags.DISTRIBUTOR_ENHANCED_MAINTENANCE_SCHEDULING); - this.maxUnCommittedMemory = flagValue(source, appId, Flags.MAX_UNCOMMITTED_MEMORY);; + this.maxUnCommittedMemory = flagValue(source, appId, Flags.MAX_UNCOMMITTED_MEMORY); this.forwardIssuesAsErrors = flagValue(source, appId, PermanentFlags.FORWARD_ISSUES_AS_ERRORS); - this.asyncApplyBucketDiff = flagValue(source, appId, Flags.ASYNC_APPLY_BUCKET_DIFF); this.ignoreThreadStackSizes = flagValue(source, appId, Flags.IGNORE_THREAD_STACK_SIZES); this.unorderedMergeChaining = flagValue(source, appId, Flags.UNORDERED_MERGE_CHAINING); this.useV8GeoPositions = flagValue(source, appId, Flags.USE_V8_GEO_POSITIONS); @@ -247,6 +244,11 @@ public class ModelContextImpl implements ModelContext { this.ignoredHttpUserAgents = flagValue(source, appId, PermanentFlags.IGNORED_HTTP_USER_AGENTS); this.enableServerOcspStapling = flagValue(source, appId, Flags.ENABLE_SERVER_OCSP_STAPLING); this.persistenceAsyncThrottling = flagValue(source, appId, Flags.PERSISTENCE_ASYNC_THROTTLING); + this.mergeThrottlingPolicy = flagValue(source, appId, Flags.MERGE_THROTTLING_POLICY); + this.persistenceThrottlingWsDecrementFactor = flagValue(source, appId, Flags.PERSISTENCE_THROTTLING_WS_DECREMENT_FACTOR); + this.persistenceThrottlingWsBackoff = flagValue(source, appId, Flags.PERSISTENCE_THROTTLING_WS_BACKOFF); + this.inhibitDefaultMergesWhenGlobalMergesPending = flagValue(source, appId, Flags.INHIBIT_DEFAULT_MERGES_WHEN_GLOBAL_MERGES_PENDING); + this.useQrserverServiceName = flagValue(source, appId, Flags.USE_QRSERVER_SERVICE_NAME); this.avoidRenamingSummaryFeatures = flagValue(source, appId, Flags.AVOID_RENAMING_SUMMARY_FEATURES); } @@ -263,7 +265,6 @@ public class ModelContextImpl implements ModelContext { @Override public boolean skipMbusReplyThread() { return skipMbusReplyThread; } @Override public boolean useAsyncMessageHandlingOnSchedule() { return useAsyncMessageHandlingOnSchedule; } @Override public double feedConcurrency() { return feedConcurrency; } - @Override public boolean enableFeedBlockInDistributor() { return enableFeedBlockInDistributor; } @Override public List<String> allowedAthenzProxyIdentities() { return allowedAthenzProxyIdentities; } @Override public int maxActivationInhibitedOutOfSyncGroups() { return maxActivationInhibitedOutOfSyncGroups; } @Override public String jvmOmitStackTraceInFastThrowOption(ClusterSpec.Type type) { @@ -271,18 +272,15 @@ public class ModelContextImpl implements ModelContext { } @Override public int maxConcurrentMergesPerNode() { return maxConcurrentMergesPerContentNode; } @Override public int maxMergeQueueSize() { return maxMergeQueueSize; } - @Override public boolean ignoreMergeQueueLimit() { return ignoreMergeQueueLimit; } @Override public double resourceLimitDisk() { return resourceLimitDisk; } @Override public double resourceLimitMemory() { return resourceLimitMemory; } @Override public double minNodeRatioPerGroup() { return minNodeRatioPerGroup; } - @Override public int metricsproxyNumThreads() { return metricsproxyNumThreads; } + @Override public int defaultPoolNumThreads() { return metricsproxyNumThreads; } + @Override public int availableProcessors() { return availableProcessors; } @Override public double containerShutdownTimeout() { return containerShutdownTimeout; } @Override public boolean containerDumpHeapOnShutdownTimeout() { return containerDumpHeapOnShutdownTimeout; } - @Override public int distributorMergeBusyWait() { return distributorMergeBusyWait; } - @Override public boolean distributorEnhancedMaintenanceScheduling() { return distributorEnhancedMaintenanceScheduling; } @Override public int maxUnCommittedMemory() { return maxUnCommittedMemory; } @Override public boolean forwardIssuesAsErrors() { return forwardIssuesAsErrors; } - @Override public boolean asyncApplyBucketDiff() { return asyncApplyBucketDiff; } @Override public boolean ignoreThreadStackSizes() { return ignoreThreadStackSizes; } @Override public boolean unorderedMergeChaining() { return unorderedMergeChaining; } @Override public boolean useV8GeoPositions() { return useV8GeoPositions; } @@ -292,6 +290,11 @@ public class ModelContextImpl implements ModelContext { @Override public List<String> ignoredHttpUserAgents() { return ignoredHttpUserAgents; } @Override public boolean enableServerOcspStapling() { return enableServerOcspStapling; } @Override public String persistenceAsyncThrottling() { return persistenceAsyncThrottling; } + @Override public String mergeThrottlingPolicy() { return mergeThrottlingPolicy; } + @Override public double persistenceThrottlingWsDecrementFactor() { return persistenceThrottlingWsDecrementFactor; } + @Override public double persistenceThrottlingWsBackoff() { return persistenceThrottlingWsBackoff; } + @Override public boolean inhibitDefaultMergesWhenGlobalMergesPending() { return inhibitDefaultMergesWhenGlobalMergesPending; } + @Override public boolean useQrserverServiceName() { return useQrserverServiceName; } @Override public boolean avoidRenamingSummaryFeatures() { return avoidRenamingSummaryFeatures; } private static <V> V flagValue(FlagSource source, ApplicationId appId, UnboundFlag<? extends V, ?, ?> flag) { @@ -354,6 +357,7 @@ public class ModelContextImpl implements ModelContext { private final List<X509Certificate> operatorCertificates; private final List<String> tlsCiphersOverride; private final List<String> zoneDnsSuffixes; + private final List<String> environmentVariables; public Properties(ApplicationId applicationId, ConfigserverConfig configserverConfig, @@ -386,13 +390,15 @@ public class ModelContextImpl implements ModelContext { this.tenantSecretStores = tenantSecretStores; this.secretStore = secretStore; this.jvmGCOptionsFlag = PermanentFlags.JVM_GC_OPTIONS.bindTo(flagSource) - .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()); + .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()); this.allowDisableMtls = PermanentFlags.ALLOW_DISABLE_MTLS.bindTo(flagSource) .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()).value(); this.operatorCertificates = operatorCertificates; this.tlsCiphersOverride = PermanentFlags.TLS_CIPHERS_OVERRIDE.bindTo(flagSource) .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()).value(); this.zoneDnsSuffixes = configserverConfig.zoneDnsSuffixes(); + this.environmentVariables = PermanentFlags.ENVIRONMENT_VARIABLES.bindTo(flagSource) + .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()).value(); } @Override public ModelContext.FeatureFlags featureFlags() { return featureFlags; } @@ -474,6 +480,9 @@ public class ModelContextImpl implements ModelContext { .value(); } + @Override + public List<String> environmentVariables() { return environmentVariables; } + } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java index ca822b7a99d..0acf32d79a7 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java @@ -90,15 +90,15 @@ public class ZooKeeperClient { } private void writeSchemas(ApplicationPackage app) throws IOException { - Collection<NamedReader> sds = app.getSchemas(); - if (sds.isEmpty()) return; + Collection<NamedReader> schemas = app.getSchemas(); + if (schemas.isEmpty()) return; Path zkPath = getZooKeeperAppPath(USERAPP_ZK_SUBPATH).append(SCHEMAS_DIR); curator.create(zkPath); // Ensures that ranking expressions and other files are also written - writeDir(app.getFile(ApplicationPackage.SEARCH_DEFINITIONS_DIR), zkPath, false); - writeDir(app.getFile(ApplicationPackage.SCHEMAS_DIR), zkPath, false); - for (NamedReader sd : sds) { + writeDir(app.getFile(ApplicationPackage.SEARCH_DEFINITIONS_DIR), zkPath, true); + writeDir(app.getFile(ApplicationPackage.SCHEMAS_DIR), zkPath, true); + for (NamedReader sd : schemas) { curator.set(zkPath.append(sd.getName()), Utf8.toBytes(com.yahoo.io.IOUtils.readAll(sd.getReader()))); sd.getReader().close(); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/filedistribution/FileServer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/filedistribution/FileServer.java index 8e5eee2104c..a3f9dbfad11 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/filedistribution/FileServer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/filedistribution/FileServer.java @@ -223,6 +223,7 @@ public class FileServer { } private static ConnectionPool createConnectionPool(List<String> configServers, Supervisor supervisor) { + @SuppressWarnings("removal") // TODO Vespa 8: remove ConfigSourceSet configSourceSet = new ConfigSourceSet(configServers); if (configServers.size() == 0) return FileDownloader.emptyConnectionPool(); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpErrorResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpErrorResponse.java index 96e1767b462..c414d8dfa9a 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpErrorResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpErrorResponse.java @@ -2,13 +2,13 @@ package com.yahoo.vespa.config.server.http; import com.yahoo.container.jdisc.HttpResponse; -import java.util.logging.Level; import com.yahoo.slime.Cursor; import com.yahoo.slime.JsonFormat; import com.yahoo.slime.Slime; import java.io.IOException; import java.io.OutputStream; +import java.util.logging.Level; import java.util.logging.Logger; import static com.yahoo.jdisc.Response.Status.BAD_REQUEST; @@ -50,7 +50,8 @@ public class HttpErrorResponse extends HttpResponse { UNKNOWN_VESPA_VERSION, PARENT_HOST_NOT_READY, CERTIFICATE_NOT_READY, - LOAD_BALANCER_NOT_READY + LOAD_BALANCER_NOT_READY, + CONFIG_NOT_CONVERGED } public static HttpErrorResponse notFoundError(String msg) { @@ -101,6 +102,10 @@ public class HttpErrorResponse extends HttpResponse { return new HttpErrorResponse(CONFLICT, ErrorCode.CERTIFICATE_NOT_READY.name(), msg); } + public static HttpErrorResponse configNotConverged(String msg) { + return new HttpErrorResponse(CONFLICT, ErrorCode.CONFIG_NOT_CONVERGED.name(), msg); + } + public static HttpErrorResponse loadBalancerNotReady(String msg) { return new HttpErrorResponse(CONFLICT, ErrorCode.LOAD_BALANCER_NOT_READY.name(), msg); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpHandler.java index 2dad2c060cc..190005771c7 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpHandler.java @@ -9,7 +9,8 @@ import com.yahoo.config.provision.exception.ActivationConflictException; import com.yahoo.config.provision.exception.LoadBalancerServiceException; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; -import com.yahoo.container.jdisc.LoggingRequestHandler; +import com.yahoo.vespa.config.server.application.ConfigNotConvergedException; +import com.yahoo.container.jdisc.ThreadedHttpRequestHandler; import com.yahoo.yolean.Exceptions; import java.io.PrintWriter; @@ -24,7 +25,7 @@ import java.util.logging.Level; * * @author hmusum */ -public class HttpHandler extends LoggingRequestHandler { +public class HttpHandler extends ThreadedHttpRequestHandler { public HttpHandler(HttpHandler.Context ctx) { super(ctx); @@ -68,6 +69,8 @@ public class HttpHandler extends LoggingRequestHandler { return HttpErrorResponse.parentHostNotReady(getMessage(e, request)); } catch (CertificateNotReadyException e) { return HttpErrorResponse.certificateNotReady(getMessage(e, request)); + } catch (ConfigNotConvergedException e) { + return HttpErrorResponse.configNotConverged(getMessage(e, request)); } catch (LoadBalancerServiceException e) { return HttpErrorResponse.loadBalancerNotReady(getMessage(e, request)); } catch (Exception e) { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v1/RoutingStatusApiHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v1/RoutingStatusApiHandler.java index d9cbc7bc533..569ed1525b2 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v1/RoutingStatusApiHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v1/RoutingStatusApiHandler.java @@ -63,6 +63,7 @@ public class RoutingStatusApiHandler extends RestApiRequestHandler<RoutingStatus private static RestApi createRestApiDefinition(RoutingStatusApiHandler self) { return RestApi.builder() + // TODO(mpolden): Remove this route when clients have migrated to v2 .addRoute(RestApi.route("/routing/v1/status") .get(self::listInactiveDeployments)) .addRoute(RestApi.route("/routing/v1/status/zone") @@ -72,9 +73,27 @@ public class RoutingStatusApiHandler extends RestApiRequestHandler<RoutingStatus .addRoute(RestApi.route("/routing/v1/status/{upstreamName}") .get(self::getDeploymentStatus) .put(self::changeDeploymentStatus)) + .addRoute(RestApi.route("/routing/v2/status") + .get(self::getDeploymentStatusV2)) .build(); } + /* Get inactive deployments and zone status */ + private SlimeJsonResponse getDeploymentStatusV2(RestApi.RequestContext context) { + Slime slime = new Slime(); + Cursor root = slime.setObject(); + Cursor inactiveDeploymentsArray = root.setArray("inactiveDeployments"); + curator.getChildren(DEPLOYMENT_STATUS_ROOT).stream() + .filter(upstreamName -> deploymentStatus(upstreamName).status() == RoutingStatus.out) + .sorted() + .forEach(upstreamName -> { + Cursor deploymentObject = inactiveDeploymentsArray.addObject(); + deploymentObject.setString("upstreamName", upstreamName); + }); + root.setBool("zoneActive", zoneStatus() == RoutingStatus.in); + return new SlimeJsonResponse(slime); + } + /** Get upstream of all deployments with status OUT */ private SlimeJsonResponse listInactiveDeployments(RestApi.RequestContext context) { List<String> inactiveDeployments = curator.getChildren(DEPLOYMENT_STATUS_ROOT).stream() diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java index 0131517818d..df4df234ed0 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java @@ -117,10 +117,9 @@ public class ApplicationHandler extends HttpHandler { private HttpResponse listServiceConverge(ApplicationId applicationId, HttpRequest request) { ServiceListResponse response = applicationRepository.servicesToCheckForConfigConvergence(applicationId, - request.getUri(), getTimeoutFromRequest(request), getVespaVersionFromRequest(request)); - return new HttpServiceListResponse(response); + return new HttpServiceListResponse(response, request.getUri()); } private HttpResponse checkServiceConverge(ApplicationId applicationId, String hostAndPort, HttpRequest request) { @@ -370,7 +369,7 @@ public class ApplicationHandler extends HttpHandler { static class HttpServiceListResponse extends JSONResponse { // Pre-condition: servicesToCheck has a state port - public HttpServiceListResponse(ConfigConvergenceChecker.ServiceListResponse response) { + public HttpServiceListResponse(ConfigConvergenceChecker.ServiceListResponse response, URI uri) { super(200); Cursor serviceArray = object.setArray("services"); response.services().forEach((service) -> { @@ -381,13 +380,13 @@ public class ApplicationHandler extends HttpHandler { serviceObject.setString("host", hostName); serviceObject.setLong("port", statePort); serviceObject.setString("type", serviceInfo.getServiceType()); - serviceObject.setString("url", response.uri.toString() + "/" + hostName + ":" + statePort); + serviceObject.setString("url", uri.toString() + "/" + hostName + ":" + statePort); serviceObject.setLong("currentGeneration", service.currentGeneration); }); - object.setString("url", response.uri.toString()); + object.setString("url", uri.toString()); object.setLong("currentGeneration", response.currentGeneration); object.setLong("wantedGeneration", response.wantedGeneration); - object.setBool("converged", response.currentGeneration >= response.wantedGeneration); + object.setBool("converged", response.converged); } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java index a0e8d83fba1..9d8a3d87811 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java @@ -96,6 +96,7 @@ public class ApplicationPackageMaintainer extends ConfigServerMaintainer { File downloadDirectory, Supervisor supervisor) { List<String> otherConfigServersInCluster = getOtherConfigServersInCluster(configserverConfig); + @SuppressWarnings("removal") // TODO Vespa 8: remove ConfigSourceSet configSourceSet = new ConfigSourceSet(otherConfigServersInCluster); ConnectionPool connectionPool = (otherConfigServersInCluster.isEmpty()) diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/model/LbServicesProducer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/model/LbServicesProducer.java index dccabca2858..7677417f1a9 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/model/LbServicesProducer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/model/LbServicesProducer.java @@ -1,7 +1,6 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.model; -import com.google.common.base.Joiner; import com.yahoo.cloud.config.LbServicesConfig; import com.yahoo.config.model.api.ApplicationClusterEndpoint; import com.yahoo.config.model.api.ApplicationClusterInfo; @@ -11,19 +10,14 @@ import com.yahoo.config.model.api.ServiceInfo; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.Zone; -import com.yahoo.vespa.flags.BooleanFlag; -import com.yahoo.vespa.flags.FetchVector; import com.yahoo.vespa.flags.FlagSource; -import com.yahoo.vespa.flags.Flags; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -import java.util.stream.Stream; import static com.yahoo.config.model.api.container.ContainerServiceType.CONTAINER; import static com.yahoo.config.model.api.container.ContainerServiceType.QRSERVER; @@ -37,12 +31,10 @@ public class LbServicesProducer implements LbServicesConfig.Producer { private final Map<TenantName, Set<ApplicationInfo>> models; private final Zone zone; - private final BooleanFlag generateNonMtlsEndpoint; public LbServicesProducer(Map<TenantName, Set<ApplicationInfo>> models, Zone zone, FlagSource flagSource) { this.models = models; this.zone = zone; - generateNonMtlsEndpoint = Flags.GENERATE_NON_MTLS_ENDPOINT.bindTo(flagSource); } @Override @@ -76,13 +68,6 @@ public class LbServicesProducer implements LbServicesConfig.Producer { // TODO: read active rotation from ApplicationClusterInfo ab.activeRotation(getActiveRotation(app)); - ab.usePowerOfTwoChoicesLb(true); - ab.generateNonMtlsEndpoint(generateNonMtlsEndpoint(app)); - - // TODO: Remove when endpoints-config is read by all load balancers - app.getModel().getHosts().stream() - .sorted((a, b) -> a.getHostname().compareTo(b.getHostname())) - .forEach(hostInfo -> ab.hosts(hostInfo.getHostname(), getHostsConfig(hostInfo))); Set<ApplicationClusterInfo> applicationClusterInfos = app.getModel().applicationClusterInfo(); List<LbServicesConfig.Tenants.Applications.Endpoints.Builder> endpointBuilder = applicationClusterInfos.stream() @@ -123,38 +108,4 @@ public class LbServicesProducer implements LbServicesConfig.Producer { return activeRotation; } - private boolean generateNonMtlsEndpoint(ApplicationInfo app) { - return generateNonMtlsEndpoint.with(FetchVector.Dimension.APPLICATION_ID, app.getApplicationId().serializedForm()).value(); - } - - private LbServicesConfig.Tenants.Applications.Hosts.Builder getHostsConfig(HostInfo hostInfo) { - LbServicesConfig.Tenants.Applications.Hosts.Builder hb = new LbServicesConfig.Tenants.Applications.Hosts.Builder(); - hb.hostname(hostInfo.getHostname()); - hostInfo.getServices().forEach(serviceInfo -> hb.services(serviceInfo.getServiceName(), getServiceConfig(serviceInfo))); - return hb; - } - - private LbServicesConfig.Tenants.Applications.Hosts.Services.Builder getServiceConfig(ServiceInfo serviceInfo) { - List<String> endpointAliases = Stream.of(serviceInfo.getProperty("endpointaliases").orElse("").split(",")). - filter(prop -> !"".equals(prop)).collect(Collectors.toList()); - endpointAliases.addAll(Stream.of(serviceInfo.getProperty("rotations").orElse("").split(",")).filter(prop -> !"".equals(prop)).collect(Collectors.toList())); - Collections.sort(endpointAliases); - - LbServicesConfig.Tenants.Applications.Hosts.Services.Builder sb = new LbServicesConfig.Tenants.Applications.Hosts.Services.Builder() - .type(serviceInfo.getServiceType()) - .clustertype(serviceInfo.getProperty("clustertype").orElse("")) - .clustername(serviceInfo.getProperty("clustername").orElse("")) - .configId(serviceInfo.getConfigId()) - .servicealiases(Stream.of(serviceInfo.getProperty("servicealiases").orElse("").split(",")). - filter(prop -> !"".equals(prop)).sorted((a, b) -> a.compareTo(b)).collect(Collectors.toList())) - .endpointaliases(endpointAliases) - .index(Integer.parseInt(serviceInfo.getProperty("index").orElse("999999"))); - serviceInfo.getPorts().forEach(portInfo -> { - LbServicesConfig.Tenants.Applications.Hosts.Services.Ports.Builder pb = new LbServicesConfig.Tenants.Applications.Hosts.Services.Ports.Builder() - .number(portInfo.getPort()) - .tags(Joiner.on(" ").join(portInfo.getTags())); - sb.ports(pb); - }); - return sb; - } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java index e4a0fa81f94..f8ee3e5e0c9 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java @@ -1,10 +1,10 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.session; -import com.google.common.util.concurrent.UncheckedTimeoutException; import com.yahoo.cloud.config.ConfigserverConfig; import com.yahoo.component.Version; import com.yahoo.component.Vtag; +import com.yahoo.concurrent.UncheckedTimeoutException; import com.yahoo.config.FileReference; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.DeployLogger; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java index 42ccdffb2af..ab02594d164 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java @@ -578,7 +578,7 @@ public class SessionRepository { // Skip sessions newly added (we might have a session in the file system, but not in ZooKeeper, // we don't want to touch any of them) if (newSessions.contains(candidate.getSessionId())) { - log.log(Level.INFO, () -> "Skipping session " + candidate.getSessionId() + ", newly created: "); + log.log(Level.FINE, () -> "Skipping expiring newly created session " + candidate.getSessionId()); continue; } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRepository.java index b3c2fa2e300..7d53c383cf5 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRepository.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TenantRepository.java @@ -330,7 +330,7 @@ public class TenantRepository { private Tenant createTenant(TenantName tenantName, Instant created) { if (tenants.containsKey(tenantName)) return getTenant(tenantName); - Instant start = Instant.now(); + Instant start = clock.instant(); log.log(Level.FINE, () -> "Adding tenant '" + tenantName); TenantApplications applicationRepo = new TenantApplications(tenantName, @@ -375,7 +375,7 @@ public class TenantRepository { configDefinitionRepo, zookeeperServerConfig.juteMaxBuffer()); log.log(Level.INFO, "Adding tenant '" + tenantName + "'" + ", created " + created + - ". Bootstrapping in " + Duration.between(start, Instant.now())); + ". Bootstrapping in " + Duration.between(start, clock.instant())); Tenant tenant = new Tenant(tenantName, sessionRepository, applicationRepo, created); createAndWriteTenantMetaData(tenant); tenants.putIfAbsent(tenantName, tenant); diff --git a/configserver/src/main/java/com/yahoo/vespa/serviceview/StateRequestHandler.java b/configserver/src/main/java/com/yahoo/vespa/serviceview/StateRequestHandler.java index d81297a87e9..d3c19bb0ba5 100644 --- a/configserver/src/main/java/com/yahoo/vespa/serviceview/StateRequestHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/serviceview/StateRequestHandler.java @@ -3,7 +3,7 @@ package com.yahoo.vespa.serviceview; import com.google.inject.Inject; import com.yahoo.cloud.config.ConfigserverConfig; -import com.yahoo.container.jdisc.LoggingRequestHandler; +import com.yahoo.container.jdisc.ThreadedHttpRequestHandler; import com.yahoo.restapi.RestApi; import com.yahoo.restapi.RestApiRequestHandler; import com.yahoo.restapi.UriBuilder; @@ -57,7 +57,7 @@ public class StateRequestHandler extends RestApiRequestHandler<StateRequestHandl } @Inject - public StateRequestHandler(LoggingRequestHandler.Context context, + public StateRequestHandler(ThreadedHttpRequestHandler.Context context, ConfigserverConfig configserverConfig) { super(context, StateRequestHandler::createRestApiDefinition); this.restApiPort = configserverConfig.httpport(); diff --git a/configserver/src/main/resources/configserver-app/services.xml b/configserver/src/main/resources/configserver-app/services.xml index 729b50419d7..b3a37c6f669 100644 --- a/configserver/src/main/resources/configserver-app/services.xml +++ b/configserver/src/main/resources/configserver-app/services.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" ?> <!-- Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> <services version="1.0" xmlns:preprocess="properties"> - <container id="configserver" jetty="true" version="1.0"> + <container id="configserver" version="1.0"> <config name="container.jdisc.config.health-monitor"> <initialStatus>initializing</initialStatus> </config> diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java index 7baad75ebc5..284a0aa0a62 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java @@ -42,6 +42,7 @@ import com.yahoo.vespa.config.server.session.Session; import com.yahoo.vespa.config.server.session.SessionRepository; import com.yahoo.vespa.config.server.session.SessionZooKeeperClient; import com.yahoo.vespa.config.server.tenant.Tenant; +import com.yahoo.vespa.config.server.tenant.TenantMetaData; import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.vespa.config.server.tenant.TestTenantRepository; import com.yahoo.vespa.config.util.ConfigUtils; @@ -94,7 +95,6 @@ public class ApplicationRepositoryTest { private final static TenantName tenant1 = TenantName.from("test1"); private final static TenantName tenant2 = TenantName.from("test2"); - private final static TenantName tenant3 = TenantName.from("test3"); private final static ManualClock clock = new ManualClock(Instant.now()); private ApplicationRepository applicationRepository; @@ -103,6 +103,7 @@ public class ApplicationRepositoryTest { private OrchestratorMock orchestrator; private TimeoutBudget timeoutBudget; private Curator curator; + private ConfigserverConfig configserverConfig; @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); @@ -114,24 +115,22 @@ public class ApplicationRepositoryTest { @Before public void setup() throws IOException { curator = new MockCurator(); - ConfigserverConfig configserverConfig = new ConfigserverConfig.Builder() + configserverConfig = new ConfigserverConfig.Builder() .payloadCompressionType(ConfigserverConfig.PayloadCompressionType.Enum.UNCOMPRESSED) .configServerDBDir(temporaryFolder.newFolder().getAbsolutePath()) .configDefinitionsDir(temporaryFolder.newFolder().getAbsolutePath()) .fileReferencesDir(temporaryFolder.newFolder().getAbsolutePath()) .build(); - InMemoryFlagSource flagSource = new InMemoryFlagSource(); tenantRepository = new TestTenantRepository.Builder() .withClock(clock) .withConfigserverConfig(configserverConfig) .withCurator(curator) .withFileDistributionFactory(new MockFileDistributionFactory(configserverConfig)) - .withFlagSource(flagSource) + .withFlagSource(new InMemoryFlagSource()) .build(); tenantRepository.addTenant(TenantRepository.HOSTED_VESPA_TENANT); tenantRepository.addTenant(tenant1); tenantRepository.addTenant(tenant2); - tenantRepository.addTenant(tenant3); orchestrator = new OrchestratorMock(); provisioner = new MockProvisioner(); applicationRepository = new ApplicationRepository.Builder() @@ -146,47 +145,42 @@ public class ApplicationRepositoryTest { } @Test - public void prepareAndActivate() { - PrepareResult result = prepareAndActivate(testApp); - assertTrue(result.configChangeActions().getRefeedActions().isEmpty()); - assertTrue(result.configChangeActions().getReindexActions().isEmpty()); - assertTrue(result.configChangeActions().getRestartActions().isEmpty()); - - Tenant tenant = applicationRepository.getTenant(applicationId()); - Session session = applicationRepository.getActiveLocalSession(tenant, applicationId()); - session.getAllocatedHosts(); - } - - @Test public void prepareAndActivateWithTenantMetaData() { - Instant startTime = clock.instant(); + long startTime = clock.instant().toEpochMilli(); Duration duration = Duration.ofHours(1); clock.advance(duration); - Instant deployTime = clock.instant(); + long deployTime = clock.instant().toEpochMilli(); PrepareResult result = prepareAndActivate(testApp); assertTrue(result.configChangeActions().getRefeedActions().isEmpty()); assertTrue(result.configChangeActions().getReindexActions().isEmpty()); assertTrue(result.configChangeActions().getRestartActions().isEmpty()); - Tenant tenant = applicationRepository.getTenant(applicationId()); + Session session = applicationRepository.getActiveLocalSession(tenant(), applicationId()); + session.getAllocatedHosts(); - assertEquals(startTime.toEpochMilli(), - applicationRepository.getTenantMetaData(tenant).createdTimestamp().toEpochMilli()); - assertEquals(deployTime.toEpochMilli(), - applicationRepository.getTenantMetaData(tenant).lastDeployTimestamp().toEpochMilli()); + assertEquals(startTime, tenantMetaData(tenant()).createdTimestamp().toEpochMilli()); + assertEquals(deployTime, tenantMetaData(tenant()).lastDeployTimestamp().toEpochMilli()); // Creating a new tenant will have metadata with timestamp equal to current time clock.advance(duration); - Instant createTenantTime = clock.instant(); + long createTenantTime = clock.instant().toEpochMilli(); Tenant fooTenant = tenantRepository.addTenant(TenantName.from("foo")); - assertEquals(createTenantTime.toEpochMilli(), - applicationRepository.getTenantMetaData(fooTenant).createdTimestamp().toEpochMilli()); - assertEquals(createTenantTime.toEpochMilli(), - applicationRepository.getTenantMetaData(fooTenant).lastDeployTimestamp().toEpochMilli()); + assertEquals(createTenantTime, tenantMetaData(fooTenant).createdTimestamp().toEpochMilli()); + assertEquals(createTenantTime, tenantMetaData(fooTenant).lastDeployTimestamp().toEpochMilli()); } @Test public void prepareAndActivateWithRestart() { + applicationRepository = new ApplicationRepository.Builder() + .withTenantRepository(tenantRepository) + .withProvisioner(provisioner) + .withConfigserverConfig(configserverConfig) + .withOrchestrator(orchestrator) + .withLogRetriever(new MockLogRetriever()) + .withClock(clock) + .withConfigConvergenceChecker(new MockConfigConvergenceChecker(2)) + .build(); + prepareAndActivate(testAppJdiscOnly); PrepareResult result = prepareAndActivate(testAppJdiscOnlyRestart); assertTrue(result.configChangeActions().getRefeedActions().isEmpty()); @@ -217,24 +211,20 @@ public class ApplicationRepositoryTest { @Test public void redeploy() { - PrepareResult result = deployApp(testApp); + long firstSessionId = deployApp(testApp).sessionId(); - long firstSessionId = result.sessionId(); - - PrepareResult result2 = deployApp(testApp); - long secondSessionId = result2.sessionId(); + long secondSessionId = deployApp(testApp).sessionId(); assertNotEquals(firstSessionId, secondSessionId); - Tenant tenant = applicationRepository.getTenant(applicationId()); - Session session = applicationRepository.getActiveLocalSession(tenant, applicationId()); + Session session = applicationRepository.getActiveLocalSession(tenant(), applicationId()); assertEquals(firstSessionId, session.getMetaData().getPreviousActiveGeneration()); } @Test public void createFromActiveSession() { - PrepareResult result = deployApp(testApp); - long sessionId = applicationRepository.createSessionFromExisting(applicationId(), false, timeoutBudget); - long originalSessionId = result.sessionId(); + long originalSessionId = deployApp(testApp).sessionId(); + + long sessionId = createSessionFromExisting(applicationId(), timeoutBudget); ApplicationMetaData originalApplicationMetaData = getApplicationMetaData(applicationId(), originalSessionId); ApplicationMetaData applicationMetaData = getApplicationMetaData(applicationId(), sessionId); @@ -269,20 +259,24 @@ public class ApplicationRepositoryTest { } @Test - public void deleteUnusedFileReferences() throws IOException, InterruptedException { + public void deleteUnusedFileReferences() throws IOException { File fileReferencesDir = temporaryFolder.newFolder(); Duration keepFileReferencesDuration = Duration.ofSeconds(4); // Add file reference that is not in use and should be deleted (older than 'keepFileReferencesDuration') File filereferenceDirOldest = createFilereferenceOnDisk(new File(fileReferencesDir, "foo")); - //Thread.sleep(Duration.ofSeconds(1).toMillis()); + clock.advance(Duration.ofSeconds(1)); // Add file references that are not in use and could be deleted IntStream.range(0, 3).forEach(i -> { - createFilereferenceOnDisk(new File(fileReferencesDir, "bar" + i)); - try { Thread.sleep(Duration.ofSeconds(1).toMillis()); } catch (InterruptedException e) { /* ignore */ } + try { + createFilereferenceOnDisk(new File(fileReferencesDir, "bar" + i)); + } catch (IOException e) { + fail(e.getMessage()); + } + clock.advance(Duration.ofSeconds(1)); }); - Thread.sleep(keepFileReferencesDuration.toMillis()); + clock.advance(keepFileReferencesDuration); // Add file reference that is not in use, but should not be deleted (newer than 'keepFileReferencesDuration') File filereferenceDirNewest = createFilereferenceOnDisk(new File(fileReferencesDir, "baz")); @@ -309,17 +303,17 @@ public class ApplicationRepositoryTest { assertTrue(filereferenceDirNewest.exists()); } - private File createFilereferenceOnDisk(File filereferenceDir) { + private File createFilereferenceOnDisk(File filereferenceDir) throws IOException { assertTrue(filereferenceDir.mkdir()); - File bar = new File(filereferenceDir, "file"); - IOUtils.writeFile(bar, Utf8.toBytes("test")); + File file = new File(filereferenceDir, "bar"); + IOUtils.writeFile(file, Utf8.toBytes("test")); + Files.setAttribute(filereferenceDir.toPath(), "lastAccessTime", FileTime.from(clock.instant())); return filereferenceDir; } @Test public void delete() { - Tenant tenant = applicationRepository.getTenant(applicationId()); - SessionRepository sessionRepository = tenant.getSessionRepository(); + SessionRepository sessionRepository = tenant().getSessionRepository(); { PrepareResult result = deployApp(testApp); long sessionId = result.sessionId(); @@ -330,7 +324,7 @@ public class ApplicationRepositoryTest { assertNotNull(applicationRepository.getActiveSession(applicationId())); Path sessionNode = sessionRepository.getSessionPath(sessionId); assertTrue(curator.exists(sessionNode)); - TenantFileSystemDirs tenantFileSystemDirs = tenant.getApplicationRepo().getTenantFileSystemDirs(); + TenantFileSystemDirs tenantFileSystemDirs = tenant().getApplicationRepo().getTenantFileSystemDirs(); File sessionFile = new File(tenantFileSystemDirs.sessionsPath(), String.valueOf(sessionId)); assertTrue(sessionFile.exists()); @@ -339,7 +333,7 @@ public class ApplicationRepositoryTest { assertNull(applicationRepository.getActiveSession(applicationId())); assertEquals(Optional.empty(), sessionRepository.getRemoteSession(sessionId).applicationSet()); assertTrue(provisioner.removed()); - assertEquals(tenant.getName(), provisioner.lastApplicationId().tenant()); + assertEquals(tenant().getName(), provisioner.lastApplicationId().tenant()); assertEquals(applicationId(), provisioner.lastApplicationId()); assertTrue(curator.exists(sessionNode)); assertEquals(Session.Status.DELETE.name(), Utf8.toString(curator.getData(sessionNode.append("sessionState")).get())); @@ -367,10 +361,9 @@ public class ApplicationRepositoryTest { assertTrue(applicationRepository.delete(applicationId())); } - // If delete fails, a retry should work if the failure is transient and zookeeper state should be constistent + // If delete fails, a retry should work if the failure is transient and zookeeper state should be consistent { - PrepareResult result = deployApp(testApp); - long sessionId = result.sessionId(); + long sessionId = deployApp(testApp).sessionId(); assertNotNull(sessionRepository.getRemoteSession(sessionId)); assertNotNull(applicationRepository.getActiveSession(applicationId())); assertEquals(sessionId, applicationRepository.getActiveSession(applicationId()).getSessionId()); @@ -488,8 +481,7 @@ public class ApplicationRepositoryTest { // ... but it should be deleted if some time has passed clock.advance(Duration.ofSeconds(60)); - tester.applicationRepository().deleteExpiredLocalSessions(); - assertEquals(1, sessionRepository.getLocalSessions().size()); + deleteExpiredLocalSessionsAndAssertNumberOfSessions(1, tester, sessionRepository); // Set older created timestamp for session dir for local session without any data in zookeeper, should be deleted setCreatedTime(dir, Instant.now().minus(Duration.ofDays(31))); @@ -564,10 +556,10 @@ public class ApplicationRepositoryTest { long firstSession = result.sessionId(); TimeoutBudget timeoutBudget = new TimeoutBudget(clock, Duration.ofSeconds(10)); - long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, testAppJdiscOnly); + long sessionId = createSession(applicationId(), timeoutBudget, testAppJdiscOnly); exceptionRule.expect(IllegalArgumentException.class); exceptionRule.expectMessage("tenant:test1 Session 3 is not prepared"); - applicationRepository.activate(applicationRepository.getTenant(applicationId()), sessionId, timeoutBudget, false); + activate(applicationId(), sessionId, timeoutBudget); Session activeSession = applicationRepository.getActiveSession(applicationId()); assertEquals(firstSession, activeSession.getSessionId()); @@ -577,14 +569,13 @@ public class ApplicationRepositoryTest { @Test public void testActivationTimesOut() { // Needed so we can test that the original active session is still active after a failed activation - PrepareResult result = deployApp(testAppJdiscOnly); - long firstSession = result.sessionId(); + long firstSession = deployApp(testAppJdiscOnly).sessionId(); - long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, testAppJdiscOnly); + long sessionId = createSession(applicationId(), timeoutBudget, testAppJdiscOnly); applicationRepository.prepare(sessionId, prepareParams()); exceptionRule.expect(RuntimeException.class); exceptionRule.expectMessage("Timeout exceeded when trying to activate 'test1.testapp'"); - applicationRepository.activate(applicationRepository.getTenant(applicationId()), sessionId, new TimeoutBudget(clock, Duration.ofSeconds(0)), false); + activate(applicationId(), sessionId, new TimeoutBudget(clock, Duration.ofSeconds(0))); Session activeSession = applicationRepository.getActiveSession(applicationId()); assertEquals(firstSession, activeSession.getSessionId()); @@ -595,18 +586,16 @@ public class ApplicationRepositoryTest { public void testActivationOfSessionCreatedFromNoLongerActiveSessionFails() { TimeoutBudget timeoutBudget = new TimeoutBudget(clock, Duration.ofSeconds(10)); - PrepareResult result1 = deployApp(testAppJdiscOnly); - result1.sessionId(); + deployApp(testAppJdiscOnly); - long sessionId2 = applicationRepository.createSessionFromExisting(applicationId(), false, timeoutBudget); + long sessionId2 = createSessionFromExisting(applicationId(), timeoutBudget); // Deploy and activate another session - PrepareResult result2 = deployApp(testAppJdiscOnly); - result2.sessionId(); + deployApp(testAppJdiscOnly); applicationRepository.prepare(sessionId2, prepareParams()); exceptionRule.expect(ActivationConflictException.class); exceptionRule.expectMessage("app:test1.testapp.default Cannot activate session 3 because the currently active session (4) has changed since session 3 was created (was 2 at creation time)"); - applicationRepository.activate(applicationRepository.getTenant(applicationId()), sessionId2, timeoutBudget, false); + activate(applicationId(), sessionId2, timeoutBudget); } @Test @@ -620,7 +609,7 @@ public class ApplicationRepositoryTest { exceptionRule.expect(IllegalArgumentException.class); exceptionRule.expectMessage("app:test1.testapp.default Session 2 is already active"); - applicationRepository.activate(applicationRepository.getTenant(applicationId()), sessionId, timeoutBudget, false); + activate(applicationId(), sessionId, timeoutBudget); } @Test @@ -641,9 +630,8 @@ public class ApplicationRepositoryTest { .vespaVersion(vespaVersion) .build()); - RequestHandler requestHandler = getRequestHandler(applicationId()); - SimpletypesConfig config = resolve(SimpletypesConfig.class, requestHandler, applicationId(), vespaVersion); - assertEquals(1337 , config.intval()); + SimpletypesConfig config = resolve(applicationId(), vespaVersion); + assertEquals(1337, config.intval()); } @Test @@ -664,18 +652,17 @@ public class ApplicationRepositoryTest { .vespaVersion(vespaVersion) .build()); - RequestHandler requestHandler = getRequestHandler(applicationId()); - SimpletypesConfig config = resolve(SimpletypesConfig.class, requestHandler, applicationId(), vespaVersion); + SimpletypesConfig config = resolve(applicationId(), vespaVersion); assertEquals(1337, config.intval()); - RequestHandler requestHandler2 = getRequestHandler(appId2); - SimpletypesConfig config2 = resolve(SimpletypesConfig.class, requestHandler2, appId2, vespaVersion); + SimpletypesConfig config2 = resolve(appId2, vespaVersion); assertEquals(1330, config2.intval()); + RequestHandler requestHandler = getRequestHandler(applicationId()); assertTrue(requestHandler.hasApplication(applicationId(), Optional.of(vespaVersion))); assertNull(requestHandler.resolveApplicationId("doesnotexist")); assertEquals(new ApplicationId.Builder().tenant(tenant1).applicationName("testapp").build(), - requestHandler.resolveApplicationId("mytesthost")); // Host set in application package. + requestHandler.resolveApplicationId("mytesthost")); // Host set in application package. } @Test @@ -686,12 +673,11 @@ public class ApplicationRepositoryTest { .vespaVersion(vespaVersion) .build()); - RequestHandler requestHandler = getRequestHandler(applicationId()); - SimpletypesConfig config = resolve(SimpletypesConfig.class, requestHandler, applicationId(), vespaVersion); + SimpletypesConfig config = resolve(applicationId(), vespaVersion); assertEquals(1337, config.intval()); // TODO: Revisit this test, I cannot see that we create a model for version 3.2.1 - config = resolve(SimpletypesConfig.class, requestHandler, applicationId(), new Version(3, 2, 1)); + config = resolve(applicationId(), new Version(3, 2, 1)); assertEquals(1337, config.intval()); } @@ -703,15 +689,14 @@ public class ApplicationRepositoryTest { .vespaVersion(vespaVersion) .build()); - RequestHandler requestHandler = getRequestHandler(applicationId()); - SimpletypesConfig config = resolve(SimpletypesConfig.class, requestHandler, applicationId(), vespaVersion); - assertEquals(1337 , config.intval()); + SimpletypesConfig config = resolve(applicationId(), vespaVersion); + assertEquals(1337, config.intval()); applicationRepository.delete(applicationId()); exceptionRule.expect(com.yahoo.vespa.config.server.NotFoundException.class); exceptionRule.expectMessage("No such application id: test1.testapp"); - resolve(SimpletypesConfig.class, requestHandler, applicationId(), vespaVersion); + resolve(applicationId(), vespaVersion); } private PrepareResult prepareAndActivate(File application) { @@ -730,14 +715,14 @@ public class ApplicationRepositoryTest { return new PrepareParams.Builder().applicationId(applicationId()).build(); } - private ApplicationId applicationId() { - return applicationId(tenant1); - } + private ApplicationId applicationId() { return applicationId(tenant1); } private ApplicationId applicationId(TenantName tenantName) { return ApplicationId.from(tenantName, ApplicationName.from("testapp"), InstanceName.defaultName()); } + private Tenant tenant() { return applicationRepository.getTenant(applicationId()); } + private ApplicationMetaData getApplicationMetaData(ApplicationId applicationId, long sessionId) { Tenant tenant = tenantRepository.getTenant(applicationId.tenant()); return applicationRepository.getMetadataFromLocalSession(tenant, sessionId); @@ -786,12 +771,11 @@ public class ApplicationRepositoryTest { } - private <T extends ConfigInstance> T resolve(Class<T> clazz, - RequestHandler applications, - ApplicationId appId, - Version vespaVersion) { + private SimpletypesConfig resolve(ApplicationId applicationId, Version vespaVersion) { String configId = ""; - ConfigResponse response = getConfigResponse(clazz, applications, appId, vespaVersion, configId); + RequestHandler requestHandler = getRequestHandler(applicationId); + Class<SimpletypesConfig> clazz = SimpletypesConfig.class; + ConfigResponse response = getConfigResponse(clazz, requestHandler, applicationId, vespaVersion, configId); return ConfigPayload.fromUtf8Array(response.getPayload()).toInstance(clazz, configId); } @@ -841,4 +825,20 @@ public class ApplicationRepositoryTest { assertEquals(expectedNumberOfSessions, sessionRepository.getLocalSessions().size()); } + private void activate(ApplicationId applicationId, long sessionId, TimeoutBudget timeoutBudget) { + applicationRepository.activate(applicationRepository.getTenant(applicationId), sessionId, timeoutBudget, false); + } + + private TenantMetaData tenantMetaData(Tenant tenant) { + return applicationRepository.getTenantMetaData(tenant); + } + + private long createSession(ApplicationId applicationId, TimeoutBudget timeoutBudget, File app) { + return applicationRepository.createSession(applicationId, timeoutBudget, app); + } + + private long createSessionFromExisting(ApplicationId applicationId, TimeoutBudget timeoutBudget) { + return applicationRepository.createSessionFromExisting(applicationId, false, timeoutBudget); + } + } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java index babc7b79b65..67613d5a806 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java @@ -18,6 +18,7 @@ import com.yahoo.container.handler.VipStatus; import com.yahoo.container.jdisc.state.StateMonitor; import com.yahoo.docproc.jdisc.metric.NullMetric; import com.yahoo.path.Path; +import com.yahoo.test.ManualClock; import com.yahoo.text.Utf8; import com.yahoo.vespa.config.server.application.ConfigConvergenceChecker; import com.yahoo.vespa.config.server.deploy.DeployTester; @@ -42,6 +43,7 @@ import java.util.Optional; import java.util.function.BooleanSupplier; import java.util.stream.Collectors; +import static com.yahoo.vespa.config.server.ConfigServerBootstrap.VipStatusMode; import static com.yahoo.vespa.config.server.ConfigServerBootstrap.VipStatusMode.VIP_STATUS_FILE; import static com.yahoo.vespa.config.server.ConfigServerBootstrap.VipStatusMode.VIP_STATUS_PROGRAMMATICALLY; import static com.yahoo.vespa.config.server.deploy.DeployTester.createHostedModelFactory; @@ -56,6 +58,7 @@ import static org.junit.Assert.assertTrue; public class ConfigServerBootstrapTest { private final MockCurator curator = new MockCurator(); + private final ManualClock clock = new ManualClock(); @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); @@ -177,7 +180,7 @@ public class ConfigServerBootstrapTest { waitUntil(() -> bootstrap.vipStatus().isInRotation(), "failed waiting for server to be in rotation"); } - private ConfigServerBootstrap createBootstrap(DeployTester tester, RpcServer rpcServer, ConfigServerBootstrap.VipStatusMode vipStatusProgrammatically) throws IOException { + private ConfigServerBootstrap createBootstrap(DeployTester tester, RpcServer rpcServer, VipStatusMode vipStatusMode) throws IOException { VersionState versionState = createVersionState(); assertTrue(versionState.isUpgraded()); @@ -188,9 +191,10 @@ public class ConfigServerBootstrapTest { versionState, stateMonitor, vipStatus, - vipStatusProgrammatically, + vipStatusMode, new InMemoryFlagSource(), - new ConfigConvergenceChecker()); + new ConfigConvergenceChecker(), + clock); } private void waitUntil(BooleanSupplier booleanSupplier, String messageIfWaitingFails) throws InterruptedException { @@ -223,7 +227,7 @@ public class ConfigServerBootstrapTest { .fileReferencesDir(temporaryFolder.newFolder("filedistribution").getAbsolutePath()) .hostedVespa(hosted) .multitenant(hosted) - .maxDurationOfBootstrap(2) /* seconds */ + .maxDurationOfBootstrap(0) /* seconds, 0 => it will not retry deployment if bootstrap fails */ .sleepTimeWhenRedeployingFails(0)); /* seconds */ } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/MockConfigConvergenceChecker.java b/configserver/src/test/java/com/yahoo/vespa/config/server/MockConfigConvergenceChecker.java new file mode 100644 index 00000000000..b4892caa05f --- /dev/null +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/MockConfigConvergenceChecker.java @@ -0,0 +1,38 @@ +package com.yahoo.vespa.config.server; + +import com.yahoo.config.model.api.ServiceInfo; +import com.yahoo.vespa.config.server.application.Application; +import com.yahoo.vespa.config.server.application.ConfigConvergenceChecker; + +import java.time.Duration; +import java.util.Map; + +public class MockConfigConvergenceChecker extends ConfigConvergenceChecker { + + private final long wantedGeneration; + + public MockConfigConvergenceChecker(long wantedGeneration) { + this.wantedGeneration = wantedGeneration; + } + + @Override + public Map<ServiceInfo, Long> getServiceConfigGenerations(Application application, Duration timeoutPerService) { + return Map.of(); + } + + @Override + public ServiceListResponse checkConvergenceForAllServices(Application application, Duration timeoutPerService) { + return new ServiceListResponse(Map.of(), wantedGeneration, wantedGeneration); + } + + @Override + public ServiceResponse getServiceConfigGeneration(Application application, String hostAndPortToCheck, Duration timeout) { + return new ServiceResponse(ServiceResponse.Status.ok, wantedGeneration); + } + + @Override + public ServiceListResponse checkConvergenceUnlessDeferringChangesUntilRestart(Application application) { + return new ServiceListResponse(Map.of(), wantedGeneration, wantedGeneration); + } + +} diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelControllerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelControllerTest.java index 2c738e2d519..57060e10282 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelControllerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/SuperModelControllerTest.java @@ -13,9 +13,9 @@ import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.Zone; -import com.yahoo.vespa.config.PayloadChecksums; import com.yahoo.jrt.Request; import com.yahoo.vespa.config.ConfigKey; +import com.yahoo.vespa.config.PayloadChecksums; import com.yahoo.vespa.config.protocol.CompressionType; import com.yahoo.vespa.config.protocol.DefContent; import com.yahoo.vespa.config.protocol.JRTServerConfigRequestV3; @@ -35,10 +35,9 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; -import static com.yahoo.config.model.api.container.ContainerServiceType.QRSERVER; import static com.yahoo.vespa.config.protocol.JRTClientConfigRequestV3.createWithParams; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNotNull; /** * @author Ulf Lilleengen @@ -67,10 +66,9 @@ public class SuperModelControllerTest { assertEquals(1, lbc.tenants().size()); assertEquals(1, lbc.tenants("a").applications().size()); Applications app = lbc.tenants("a").applications("foo:prod:default:default"); - assertTrue(app.hosts().size() > 0); + assertNotNull(app); } - @Test(expected = UnknownConfigDefinitionException.class) public void test_unknown_config_definition() { PayloadChecksums payloadChecksums = PayloadChecksums.empty(); @@ -107,31 +105,12 @@ public class SuperModelControllerTest { assertEquals(2, lbc.tenants().size()); assertEquals(2, lbc.tenants("t1").applications().size()); assertEquals(1, lbc.tenants("t2").applications().size()); - assertEquals(1, lbc.tenants("t2").applications("minetooadvancedapp:prod:default:default").hosts().size()); - assertQrServer(lbc.tenants("t2").applications("minetooadvancedapp:prod:default:default")); } private ApplicationId applicationId(String applicationName, TenantName tenantName) { return ApplicationId.from(tenantName, ApplicationName.from(applicationName), InstanceName.defaultName()); } - private void assertQrServer(Applications app) { - String host = app.hosts().keySet().iterator().next(); - Applications.Hosts hosts = app.hosts(host); - assertEquals(host, hosts.hostname()); - for (Map.Entry<String, Applications.Hosts.Services> e : app.hosts(host).services().entrySet()) { - if (QRSERVER.serviceName.equals(e.getKey())) { - Applications.Hosts.Services s = e.getValue(); - assertEquals("qrserver", s.type()); - assertEquals(4, s.ports().size()); - assertEquals(8000, s.ports().get(0).number()); - assertEquals(0, s.index()); - return; - } - } - org.junit.Assert.fail("No container service in config"); - } - private DeployState createDeployState(File applicationPackage, ApplicationId applicationId) { return new DeployState.Builder() .applicationPackage(FilesApplicationPackage.fromFile(applicationPackage)) diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/ConfigConvergenceCheckerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/ConfigConvergenceCheckerTest.java index 6afb9ef086d..6016ce991d0 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/ConfigConvergenceCheckerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/ConfigConvergenceCheckerTest.java @@ -28,6 +28,7 @@ import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options import static com.yahoo.vespa.config.server.application.ConfigConvergenceChecker.ServiceListResponse; import static com.yahoo.vespa.config.server.application.ConfigConvergenceChecker.ServiceResponse; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** @@ -88,12 +89,12 @@ public class ConfigConvergenceCheckerTest { @Test public void service_list_convergence() { { - URI requestUrl = testServer().resolve("/serviceconverge"); wireMock.stubFor(get(urlEqualTo("/state/v1/config")).willReturn(okJson("{\"config\":{\"generation\":3}}"))); - ServiceListResponse response = checker.getServiceConfigGenerations(application, requestUrl, clientTimeout); + ServiceListResponse response = checker.checkConvergenceForAllServices(application, clientTimeout); assertEquals(3, response.wantedGeneration); assertEquals(3, response.currentGeneration); + assertTrue(response.converged); List<ServiceListResponse.Service> services = response.services; assertEquals(1, services.size()); assertService(this.service, services.get(0), 3); @@ -113,9 +114,10 @@ public class ConfigConvergenceCheckerTest { URI requestUrl = testServer().resolve("/serviceconverge"); - ServiceListResponse response = checker.getServiceConfigGenerations(application, requestUrl, clientTimeout); + ServiceListResponse response = checker.checkConvergenceForAllServices(application, clientTimeout); assertEquals(4, response.wantedGeneration); assertEquals(3, response.currentGeneration); + assertFalse(response.converged); List<ServiceListResponse.Service> services = response.services; assertEquals(2, services.size()); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployHandlerLoggerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployHandlerLoggerTest.java index 582b7f2c071..ea1f6a845b0 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployHandlerLoggerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployHandlerLoggerTest.java @@ -39,6 +39,7 @@ public class DeployHandlerLoggerTest { assertTrue(Pattern.matches(expectedPattern, baos.toString())); } + @SuppressWarnings("deprecation") private void logMessages(DeployLogger logger) { logger.log(LogLevel.DEBUG, "foobar"); logger.log(LogLevel.SPAM, "foobar"); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java index f16b1102f2a..7f223fbce6f 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java @@ -24,6 +24,7 @@ import com.yahoo.config.provision.Zone; import com.yahoo.vespa.config.server.ApplicationRepository; import com.yahoo.vespa.config.server.MockProvisioner; import com.yahoo.vespa.config.server.TimeoutBudget; +import com.yahoo.vespa.config.server.application.ConfigConvergenceChecker; import com.yahoo.vespa.config.server.application.OrchestratorMock; import com.yahoo.vespa.config.server.filedistribution.MockFileDistributionFactory; import com.yahoo.vespa.config.server.http.v2.PrepareResult; @@ -37,9 +38,10 @@ import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.vespa.config.server.tenant.TestTenantRepository; import com.yahoo.vespa.curator.Curator; import com.yahoo.vespa.curator.mock.MockCurator; +import com.yahoo.vespa.flags.FlagSource; +import com.yahoo.vespa.flags.InMemoryFlagSource; import com.yahoo.vespa.model.VespaModel; import com.yahoo.vespa.model.VespaModelFactory; -import com.yahoo.vespa.orchestrator.Orchestrator; import java.io.File; import java.nio.file.Files; @@ -253,7 +255,8 @@ public class DeployTester { private Curator curator = new MockCurator(); private Metrics metrics; private List<ModelFactory> modelFactories; - private Orchestrator orchestrator; + private ConfigConvergenceChecker configConvergenceChecker = new ConfigConvergenceChecker(); + private FlagSource flagSource = new InMemoryFlagSource(); public DeployTester build() { Clock clock = Optional.ofNullable(this.clock).orElseGet(Clock::systemUTC); @@ -285,9 +288,11 @@ public class DeployTester { ApplicationRepository applicationRepository = new ApplicationRepository.Builder() .withTenantRepository(tenantRepository) .withConfigserverConfig(configserverConfig) - .withOrchestrator(Optional.ofNullable(orchestrator).orElseGet(OrchestratorMock::new)) + .withOrchestrator(new OrchestratorMock()) .withClock(clock) .withProvisioner(provisioner) + .withConfigConvergenceChecker(configConvergenceChecker) + .withFlagSource(flagSource) .build(); return new DeployTester(clock, tenantRepository, applicationRepository); @@ -336,10 +341,16 @@ public class DeployTester { return this; } - public Builder orchestrator(Orchestrator orchestrator) { - this.orchestrator = orchestrator; + public Builder configConvergenceChecker(ConfigConvergenceChecker configConvergenceChecker) { + this.configConvergenceChecker = configConvergenceChecker; return this; } + + public Builder flagSource(FlagSource flagSource) { + this.flagSource = flagSource; + return this; + } + } } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java index 33e18843738..a6d7cf02bc7 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java @@ -22,6 +22,7 @@ import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.Zone; import com.yahoo.test.ManualClock; +import com.yahoo.vespa.config.server.MockConfigConvergenceChecker; import com.yahoo.vespa.config.server.application.ApplicationReindexing; import com.yahoo.vespa.config.server.http.InternalServerException; import com.yahoo.vespa.config.server.http.InvalidApplicationException; @@ -432,7 +433,14 @@ public class HostedDeployTest { "reindex please", services, "music"), new VespaRestartAction(ClusterSpec.Id.from("test"), "change", services))); - DeployTester tester = createTester(hosts, modelFactories, prodZone, clock); + DeployTester tester = new DeployTester.Builder() + .modelFactories(modelFactories) + .configserverConfig(createConfigserverConfig(prodZone)) + .clock(clock) + .zone(prodZone) + .hostProvisioner(new InMemoryProvisioner(new Hosts(hosts), true, false)) + .configConvergenceChecker(new MockConfigConvergenceChecker(2)) + .build(); PrepareResult prepareResult = tester.deployApp("src/test/apps/hosted/", "6.1.0"); assertEquals(7, tester.getAllocatedHostsOf(tester.applicationId()).getHosts().size()); @@ -480,7 +488,9 @@ public class HostedDeployTest { .configserverConfig(createConfigserverConfig(prodZone)) .clock(clock) .zone(prodZone) - .hostProvisioner(new InMemoryProvisioner(new Hosts(hosts), true, false)).build(); + .hostProvisioner(new InMemoryProvisioner(new Hosts(hosts), true, false)) + .configConvergenceChecker(new MockConfigConvergenceChecker(2)) + .build(); } private static class ConfigChangeActionsModelFactory extends TestModelFactory { diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpGetConfigHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpGetConfigHandlerTest.java index 8816e695e64..279f3a237e8 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpGetConfigHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpGetConfigHandlerTest.java @@ -63,7 +63,7 @@ public class HttpGetConfigHandlerTest { .withOrchestrator(new OrchestratorMock()) .withConfigserverConfig(configserverConfig) .build(); - handler = new HttpGetConfigHandler(HttpGetConfigHandler.testOnlyContext(), tenantRepository); + handler = new HttpGetConfigHandler(HttpGetConfigHandler.testContext(), tenantRepository); applicationRepository.deploy(testApp, prepareParams()); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpHandlerTest.java index 8f092ec9d54..40671294b4c 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpHandlerTest.java @@ -45,7 +45,7 @@ public class HttpHandlerTest { private static class HttpTestHandler extends HttpHandler { private final RuntimeException exception; HttpTestHandler(RuntimeException exception) { - super(HttpHandler.testOnlyContext()); + super(HttpHandler.testContext()); this.exception = exception; } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpListConfigsHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpListConfigsHandlerTest.java index 45c74f0d49f..520b4d0edc5 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpListConfigsHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/HttpListConfigsHandlerTest.java @@ -70,7 +70,7 @@ public class HttpListConfigsHandlerTest { .build(); applicationRepository.deploy(testApp, prepareParams()); - HttpListConfigsHandler.Context ctx = HttpListConfigsHandler.testOnlyContext(); + HttpListConfigsHandler.Context ctx = HttpListConfigsHandler.testContext(); handler = new HttpListConfigsHandler(ctx, tenantRepository); namedHandler = new HttpListNamedConfigsHandler(ctx, tenantRepository); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/status/StatusHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/status/StatusHandlerTest.java index 18fa307a9d3..ed739d73860 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/status/StatusHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/status/StatusHandlerTest.java @@ -29,7 +29,7 @@ public class StatusHandlerTest { public void require_that_handler_works() throws IOException { ModelFactoryRegistry modelFactoryRegistry = new ModelFactoryRegistry(List.of(new VespaModelFactory(new NullConfigModelRegistry()))); ConfigserverConfig configserverConfig = new ConfigserverConfig.Builder().build(); - StatusHandler handler = new StatusHandler(StatusHandler.testOnlyContext(), modelFactoryRegistry, configserverConfig); + StatusHandler handler = new StatusHandler(StatusHandler.testContext(), modelFactoryRegistry, configserverConfig); HttpResponse response = handler.handle(HttpRequest.createTestRequest("/status", GET)); JsonNode jsonNode = mapper.readTree(SessionHandlerTest.getRenderedString(response)); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v1/RoutingStatusApiHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v1/RoutingStatusApiHandlerTest.java index e2b45d33cbc..f389829a160 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v1/RoutingStatusApiHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v1/RoutingStatusApiHandlerTest.java @@ -62,6 +62,22 @@ public class RoutingStatusApiHandlerTest { } @Test + public void get_deployment_status_v2() { + String response = responseAsString(executeRequest(Method.GET, "/routing/v2/status/", null)); + assertEquals("{\"inactiveDeployments\":[],\"zoneActive\":true}", response); + + // Set deployment out + executeRequest(Method.PUT, "/routing/v1/status/" + upstreamName + "?application=" + instance.serializedForm(), statusOut()); + response = responseAsString(executeRequest(Method.GET, "/routing/v2/status/", null)); + assertEquals("{\"inactiveDeployments\":[{\"upstreamName\":\"test-upstream-name\"}],\"zoneActive\":true}", response); + + // Set zone out + executeRequest(Method.PUT, "/routing/v1/status/zone", null); + response = responseAsString(executeRequest(Method.GET, "/routing/v2/status/", null)); + assertEquals("{\"inactiveDeployments\":[{\"upstreamName\":\"test-upstream-name\"}],\"zoneActive\":false}", response); + } + + @Test public void set_deployment_status() { String response = responseAsString(executeRequest(Method.PUT, "/routing/v1/status/" + upstreamName + "?application=" + instance.serializedForm(), statusOut())); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentHandlerTest.java index 322a2b924bd..1d891c0547c 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentHandlerTest.java @@ -69,7 +69,7 @@ public class ApplicationContentHandlerTest extends ContentHandlerTestBase { .build(); applicationRepository.deploy(testApp, prepareParams(appId1)); - handler = new ApplicationHandler(ApplicationHandler.testOnlyContext(), + handler = new ApplicationHandler(ApplicationHandler.testContext(), Zone.defaultZone(), applicationRepository); pathPrefix = createPath(appId1, Zone.defaultZone()); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java index 04483e0191d..005dd715dd4 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java @@ -556,8 +556,8 @@ public class ApplicationHandlerTest { { // Known service HttpResponse response = createResponse(new ServiceResponse(ServiceResponse.Status.ok, - 3L, - 3L, + 3, + 3, true), hostAndPort, uri); @@ -601,9 +601,9 @@ public class ApplicationHandlerTest { { HttpServiceListResponse response = new HttpServiceListResponse(new ServiceListResponse(Map.of(createServiceInfo(hostname, port), 3L), - requestUrl, 3L, - 3L)); + 3L), + requestUrl); assertResponse("{\n" + " \"services\": [\n" + " {\n" + @@ -635,9 +635,9 @@ public class ApplicationHandlerTest { HttpServiceListResponse response = new HttpServiceListResponse(new ServiceListResponse(serviceInfos, - requestUrl, 4L, - 3L)); + 3L), + requestUrl); assertResponse("{\n" + " \"services\": [\n" + " {\n" + @@ -756,7 +756,7 @@ public class ApplicationHandlerTest { "/environment/" + zone.environment().value() + "/region/" + zone.region().value() + "/instance/" + applicationId.instance().value() + "\"]"; - ListApplicationsHandler listApplicationsHandler = new ListApplicationsHandler(ListApplicationsHandler.testOnlyContext(), + ListApplicationsHandler listApplicationsHandler = new ListApplicationsHandler(ListApplicationsHandler.testContext(), tenantRepository, Zone.defaultZone()); ListApplicationsHandlerTest.assertResponse(listApplicationsHandler, @@ -808,7 +808,7 @@ public class ApplicationHandlerTest { } private ApplicationHandler createApplicationHandler(ApplicationRepository applicationRepository) { - return new ApplicationHandler(ApplicationHandler.testOnlyContext(), Zone.defaultZone(), applicationRepository); + return new ApplicationHandler(ApplicationHandler.testContext(), Zone.defaultZone(), applicationRepository); } private PrepareParams prepareParams(ApplicationId applicationId) { diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java index 6bbbc451094..fbc5e87c329 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HostHandlerTest.java @@ -62,7 +62,7 @@ public class HostHandlerTest { .withOrchestrator(new OrchestratorMock()) .withConfigserverConfig(configserverConfig) .build(); - handler = new HostHandler(HostHandler.testOnlyContext(), applicationRepository); + handler = new HostHandler(HostHandler.testContext(), applicationRepository); } @Test diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandlerTest.java index 3d207f9f64a..9aae64cb884 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandlerTest.java @@ -72,7 +72,7 @@ public class HttpGetConfigHandlerTest { .withOrchestrator(new OrchestratorMock()) .withConfigserverConfig(configserverConfig) .build(); - handler = new HttpGetConfigHandler(HttpGetConfigHandler.testOnlyContext(), tenantRepository); + handler = new HttpGetConfigHandler(HttpGetConfigHandler.testContext(), tenantRepository); applicationRepository.deploy(testApp, prepareParams()); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandlerTest.java index 141f8a52f13..2ee1064f614 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandlerTest.java @@ -76,10 +76,10 @@ public class HttpListConfigsHandlerTest { .withConfigserverConfig(configserverConfig) .build(); applicationRepository.deploy(testApp, prepareParams()); - handler = new HttpListConfigsHandler(HttpListConfigsHandler.testOnlyContext(), + handler = new HttpListConfigsHandler(HttpListConfigsHandler.testContext(), tenantRepository, Zone.defaultZone()); - namedHandler = new HttpListNamedConfigsHandler(HttpListConfigsHandler.testOnlyContext(), + namedHandler = new HttpListNamedConfigsHandler(HttpListConfigsHandler.testContext(), tenantRepository, Zone.defaultZone()); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandlerTest.java index e2ad65786a4..76790e6264d 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandlerTest.java @@ -55,7 +55,7 @@ public class ListApplicationsHandlerTest { tenantRepository.addTenant(foobar); applicationRepo = tenantRepository.getTenant(mytenant).getApplicationRepo(); applicationRepo2 = tenantRepository.getTenant(foobar).getApplicationRepo(); - handler = new ListApplicationsHandler(ListApplicationsHandler.testOnlyContext(), + handler = new ListApplicationsHandler(ListApplicationsHandler.testContext(), tenantRepository, new Zone(Environment.dev, RegionName.from("us-east"))); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java index c6f84c2d6ae..ecb8d7603f6 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java @@ -164,7 +164,7 @@ public class SessionActiveHandlerTest { } private SessionActiveHandler createHandler() { - return new SessionActiveHandler(SessionActiveHandler.testOnlyContext(), + return new SessionActiveHandler(SessionActiveHandler.testContext(), applicationRepository, Zone.defaultZone()); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandlerTest.java index f13ec6cd5c8..ec96be0d0c8 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandlerTest.java @@ -183,7 +183,7 @@ public class SessionContentHandlerTest extends ContentHandlerTestBase { private SessionContentHandler createHandler() { return new SessionContentHandler( - SessionContentHandler.testOnlyContext(), + SessionContentHandler.testContext(), new ApplicationRepository.Builder() .withTenantRepository(tenantRepository) .withProvisioner(new MockProvisioner()) diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java index 4cb69ce5d20..702dd2792da 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java @@ -195,7 +195,7 @@ public class SessionCreateHandlerTest extends SessionHandlerTest { } private SessionCreateHandler createHandler() { - return new SessionCreateHandler(SessionCreateHandler.testOnlyContext(), + return new SessionCreateHandler(SessionCreateHandler.testContext(), applicationRepository, configserverConfig); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java index 3c762b7c2e5..3d2e108a75e 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java @@ -1,8 +1,8 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.http.v2; -import com.google.common.util.concurrent.UncheckedTimeoutException; import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.concurrent.UncheckedTimeoutException; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationLockException; import com.yahoo.config.provision.ApplicationName; @@ -247,7 +247,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest { public void test_out_of_capacity_response() throws IOException { long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, app); String exceptionMessage = "Out of capacity"; - FailingSessionPrepareHandler handler = new FailingSessionPrepareHandler(SessionPrepareHandler.testOnlyContext(), + FailingSessionPrepareHandler handler = new FailingSessionPrepareHandler(SessionPrepareHandler.testContext(), applicationRepository, configserverConfig, new OutOfCapacityException(exceptionMessage)); @@ -262,7 +262,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest { public void test_that_nullpointerexception_gives_internal_server_error() throws IOException { long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, app); String exceptionMessage = "nullpointer thrown in test handler"; - FailingSessionPrepareHandler handler = new FailingSessionPrepareHandler(SessionPrepareHandler.testOnlyContext(), + FailingSessionPrepareHandler handler = new FailingSessionPrepareHandler(SessionPrepareHandler.testContext(), applicationRepository, configserverConfig, new NullPointerException(exceptionMessage)); @@ -277,7 +277,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest { public void test_application_lock_failure() throws IOException { String exceptionMessage = "Timed out after waiting PT1M to acquire lock '/provision/v1/locks/foo/bar/default'"; long sessionId = applicationRepository.createSession(applicationId(), timeoutBudget, app); - FailingSessionPrepareHandler handler = new FailingSessionPrepareHandler(SessionPrepareHandler.testOnlyContext(), + FailingSessionPrepareHandler handler = new FailingSessionPrepareHandler(SessionPrepareHandler.testContext(), applicationRepository, configserverConfig, new ApplicationLockException(new UncheckedTimeoutException(exceptionMessage))); @@ -314,7 +314,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest { } private SessionHandler createHandler() { - return new SessionPrepareHandler(SessionPrepareHandler.testOnlyContext(), applicationRepository, configserverConfig); + return new SessionPrepareHandler(SessionPrepareHandler.testContext(), applicationRepository, configserverConfig); } private HttpResponse request(HttpRequest.Method put, long l) { diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java index 402e2576591..ee35ca572e1 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java @@ -19,7 +19,6 @@ import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.Zone; import com.yahoo.vespa.config.ConfigPayload; -import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.InMemoryFlagSource; import com.yahoo.vespa.model.VespaModel; import org.junit.Test; @@ -43,7 +42,6 @@ import static com.yahoo.cloud.config.LbServicesConfig.Tenants.Applications.Endpo import static com.yahoo.cloud.config.LbServicesConfig.Tenants.Applications.Endpoints.Scope.Enum.application; import static com.yahoo.cloud.config.LbServicesConfig.Tenants.Applications.Endpoints.Scope.Enum.global; import static com.yahoo.cloud.config.LbServicesConfig.Tenants.Applications.Endpoints.Scope.Enum.zone; -import static com.yahoo.config.model.api.container.ContainerServiceType.QRSERVER; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @@ -56,8 +54,6 @@ import static org.junit.Assume.assumeFalse; @RunWith(Parameterized.class) public class LbServicesProducerTest { - private static final String rotation1 = "rotation-1"; - private static final String rotation2 = "rotation-2"; private static final Set<ContainerEndpoint> endpoints = Set.of( new ContainerEndpoint("mydisc", ApplicationClusterEndpoint.Scope.global, List.of("rotation-1", "rotation-2")), new ContainerEndpoint("mydisc", ApplicationClusterEndpoint.Scope.application, List.of("app-endpoint")) @@ -91,20 +87,6 @@ public class LbServicesProducerTest { } @Test - public void testConfigAliases() { - Map<TenantName, Set<ApplicationInfo>> testModel = createTestModel(new DeployState.Builder()); - LbServicesConfig conf = getLbServicesConfig(Zone.defaultZone(), testModel); - LbServicesConfig.Tenants.Applications.Hosts.Services services = - conf.tenants("foo").applications("foo:prod:default:default").hosts("foo.foo.yahoo.com").services(QRSERVER.serviceName); - assertEquals(1, services.servicealiases().size()); - assertEquals(2, services.endpointaliases().size()); - - assertEquals("service1", services.servicealiases(0)); - assertEquals("foo1.bar1.com", services.endpointaliases(0)); - assertEquals("foo2.bar2.com", services.endpointaliases(1)); - } - - @Test public void testConfigActiveRotation() { { RegionName regionName = RegionName.from("us-east-1"); @@ -119,18 +101,6 @@ public class LbServicesProducerTest { } } - @Test - public void generate_non_mtls_endpoints_from_feature_flag() { - RegionName regionName = RegionName.from("us-east-1"); - - LbServicesConfig conf = createModelAndGetLbServicesConfig(regionName); - assertTrue(conf.tenants("foo").applications("foo:prod:" + regionName.value() + ":default").generateNonMtlsEndpoint()); - - flagSource.withBooleanFlag(Flags.GENERATE_NON_MTLS_ENDPOINT.id(), false); - conf = createModelAndGetLbServicesConfig(regionName); - assertFalse(conf.tenants("foo").applications("foo:prod:" + regionName.value() + ":default").generateNonMtlsEndpoint()); - } - private LbServicesConfig createModelAndGetLbServicesConfig(RegionName regionName) { Zone zone = new Zone(Environment.prod, regionName); Map<TenantName, Set<ApplicationInfo>> testModel = createTestModel(new DeployState.Builder().zone(zone)); @@ -153,20 +123,12 @@ public class LbServicesProducerTest { .properties(new TestProperties().setHostedVespa(true))); RegionName regionName = RegionName.from("us-east-1"); LbServicesConfig config = getLbServicesConfig(new Zone(Environment.prod, regionName), testModel); - LbServicesConfig.Tenants.Applications.Hosts.Services services = config - .tenants("foo") - .applications("foo:prod:" + regionName.value() + ":default") - .hosts("foo.foo.yahoo.com") - .services(QRSERVER.serviceName); - - assertTrue(services.servicealiases().contains("service1")); - assertTrue("Missing endpoints in list: " + services.endpointaliases(), services.endpointaliases().containsAll(List.of("foo1.bar1.com", "foo2.bar2.com", rotation1, rotation2))); List<Endpoints> endpointList = config.tenants("foo").applications("foo:prod:" + regionName.value() + ":default").endpoints(); - // Expect 4 zone endpoints (2 suffixes), 2 global endpoints and 1 application endpoint - assertEquals(7, endpointList.size()); + // Expect 2 zone endpoints (2 suffixes), 2 global endpoints and 1 application endpoint + assertEquals(5, endpointList.size()); List<Endpoints> zoneEndpoints = endpointList.stream().filter(e -> e.scope() == zone).collect(Collectors.toList()); - assertEquals(4, zoneEndpoints.size()); + assertEquals(2, zoneEndpoints.size()); assertTrue(zoneEndpoints.stream() .filter(e -> e.routingMethod() == sharedLayer4) .map(Endpoints::dnsName).collect(Collectors.toList()) @@ -186,16 +148,11 @@ public class LbServicesProducerTest { assertContainsEndpoint(applicationEndpoints, "app-endpoint", "mydisc", application, sharedLayer4, 1, List.of("foo.foo.yahoo.com")); } - @Test public void testRoutingConfigForTesterApplication() { assumeFalse(useGlobalServiceId); Map<TenantName, Set<ApplicationInfo>> testModel = createTestModel(new DeployState.Builder()); - LbServicesConfig conf = getLbServicesConfig(Zone.defaultZone(), testModel); - LbServicesConfig.Tenants.Applications.Hosts.Services services = conf.tenants("foo").applications("foo:prod:default:default").hosts("foo.foo.yahoo.com").services(QRSERVER.serviceName); - assertEquals(1, services.servicealiases().size()); - assertEquals(2, services.endpointaliases().size()); // No config for tester application assertNull(getLbServicesConfig(Zone.defaultZone(), testModel) @@ -231,7 +188,7 @@ public class LbServicesProducerTest { TenantName baz = TenantName.from("baz"); tMap.put(foo, createTestApplications(foo, deployStateBuilder)); tMap.put(bar, createTestApplications(bar, deployStateBuilder)); - tMap.put(bar, createTestApplications(baz, deployStateBuilder)); + tMap.put(baz, createTestApplications(baz, deployStateBuilder)); return tMap; } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java index 854abee91f5..30d3dcffc30 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java @@ -116,7 +116,7 @@ public class MultiTenantRpcAuthorizerTest { new ConfigKey<>(LbServicesConfig.CONFIG_DEF_NAME, "*", LbServicesConfig.CONFIG_DEF_NAMESPACE), HOSTNAME); - exceptionRule.expectMessage("Node with type 'tenant' is not allowed to access global config [name=lb-services,namespace=cloud.config,configId=*]"); + exceptionRule.expectMessage("Node with type 'tenant' is not allowed to access global config [name=cloud.config.lb-services,configId=*]"); exceptionRule.expectCause(instanceOf(AuthorizationException.class)); authorizer.authorizeConfigRequest(configRequest) |