diff options
37 files changed, 187 insertions, 172 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java index 46acdb44746..d5e42276c1a 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.model.admin.clustercontroller; import com.yahoo.cloud.config.ZookeeperServerConfig; import com.yahoo.component.ComponentSpecification; +import com.yahoo.config.model.api.container.ContainerServiceType; import com.yahoo.config.model.producer.AbstractConfigProducer; import com.yahoo.container.BundlesConfig; import com.yahoo.container.bundle.BundleInstantiationSpecification; @@ -10,10 +11,8 @@ import com.yahoo.log.LogLevel; import com.yahoo.osgi.provider.model.ComponentModel; import com.yahoo.search.config.QrStartConfig; import com.yahoo.vespa.config.content.FleetcontrollerConfig; -import static com.yahoo.vespa.defaults.Defaults.getDefaults; import com.yahoo.vespa.model.application.validation.RestartConfigs; import com.yahoo.vespa.model.container.Container; -import com.yahoo.config.model.api.container.ContainerServiceType; import com.yahoo.vespa.model.container.component.AccessLogComponent; import com.yahoo.vespa.model.container.component.Component; import com.yahoo.vespa.model.container.component.Handler; @@ -21,6 +20,8 @@ import com.yahoo.vespa.model.container.component.Handler; import java.util.Set; import java.util.TreeSet; +import static com.yahoo.vespa.defaults.Defaults.getDefaults; + /** * Container implementation for cluster-controllers */ @@ -87,8 +88,7 @@ public class ClusterControllerContainer extends Container implements } private void addHandler(Handler h, String binding) { - h.addServerBindings("http://*/" + binding, - "https://*/" + binding); + h.addServerBindings("http://*/" + binding); super.addHandler(h); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java index a370e0dc38b..446169c0ed2 100755 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java @@ -212,9 +212,7 @@ public abstract class ContainerCluster<CONTAINER extends Container> Handler<AbstractConfigProducer<?>> stateHandler = new Handler<>( new ComponentModel(STATE_HANDLER_CLASS, null, null, null)); stateHandler.addServerBindings("http://*" + StateHandler.STATE_API_ROOT, - "https://*" + StateHandler.STATE_API_ROOT, - "http://*" + StateHandler.STATE_API_ROOT + "/*", - "https://*" + StateHandler.STATE_API_ROOT + "/*"); + "http://*" + StateHandler.STATE_API_ROOT + "/*"); addComponent(stateHandler); } @@ -242,13 +240,13 @@ public abstract class ContainerCluster<CONTAINER extends Container> Handler<AbstractConfigProducer<?>> statusHandler = new Handler<>( new ComponentModel(BundleInstantiationSpecification.getInternalHandlerSpecificationFromStrings( APPLICATION_STATUS_HANDLER_CLASS, null), null)); - statusHandler.addServerBindings("http://*/ApplicationStatus", "https://*/ApplicationStatus"); + statusHandler.addServerBindings("http://*/ApplicationStatus"); addComponent(statusHandler); } public void addVipHandler() { Handler<?> vipHandler = Handler.fromClassName(FileStatusHandlerComponent.CLASS); - vipHandler.addServerBindings("http://*/status.html", "https://*/status.html"); + vipHandler.addServerBindings("http://*/status.html"); addComponent(vipHandler); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerModelEvaluation.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerModelEvaluation.java index b7c8460a9a5..6b4f8d486ec 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerModelEvaluation.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerModelEvaluation.java @@ -49,9 +49,7 @@ public class ContainerModelEvaluation implements RankProfilesConfig.Producer, Ra public static Handler<?> getHandler() { Handler<?> handler = new Handler<>(new ComponentModel(REST_HANDLER_NAME, null, BUNDLE_NAME)); handler.addServerBindings("http://*/" + REST_BINDING, - "https://*/" + REST_BINDING, - "http://*/" + REST_BINDING + "/*", - "https://*/" + REST_BINDING + "/*"); + "http://*/" + REST_BINDING + "/*"); return handler; } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/AccessControl.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/AccessControl.java index 4220a6571a0..071411845ad 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/AccessControl.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/AccessControl.java @@ -153,6 +153,6 @@ public final class AccessControl { } private static Stream<String> servletBindings(Servlet servlet) { - return Stream.of("http://*/", "https://*/").map(protocol -> protocol + servlet.bindingPath); + return Stream.of("http://*/").map(protocol -> protocol + servlet.bindingPath); } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/processing/ProcessingChains.java b/config-model/src/main/java/com/yahoo/vespa/model/container/processing/ProcessingChains.java index 32f0f373a92..4fd79a4f335 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/processing/ProcessingChains.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/processing/ProcessingChains.java @@ -4,10 +4,6 @@ package com.yahoo.vespa.model.container.processing; import com.yahoo.config.model.producer.AbstractConfigProducer; import com.yahoo.vespa.model.container.component.chain.Chains; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - /** * Root config producer for processing * @@ -15,7 +11,7 @@ import java.util.List; */ public class ProcessingChains extends Chains<ProcessingChain> { - public static final String[] defaultBindings = new String[] {"http://*/processing/*", "https://*/processing/*"}; + public static final String[] defaultBindings = new String[] {"http://*/processing/*"}; public ProcessingChains(AbstractConfigProducer parent, String subId) { diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java index 6663dc0bbc0..7e80c6be221 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java @@ -271,7 +271,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { Optional<String> statusFile = Optional.ofNullable(System.getenv(HOSTED_VESPA_STATUS_FILE_SETTING)); cluster.addComponent( new FileStatusHandlerComponent(name + "-status-handler", statusFile.orElse(HOSTED_VESPA_STATUS_FILE), - "http://*/" + name, "https://*/" + name)); + "http://*/" + name)); } else { cluster.addVipHandler(); } @@ -712,7 +712,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { ProcessingHandler<SearchChains> searchHandler = new ProcessingHandler<>( cluster.getSearch().getChains(), "com.yahoo.search.handler.SearchHandler"); - String[] defaultBindings = {"http://*/search/*", "https://*/search/*"}; + String[] defaultBindings = {"http://*/search/*"}; for (String binding: serverBindings(searchElement, defaultBindings)) { searchHandler.addServerBindings(binding); } @@ -722,7 +722,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { private void addGUIHandler(ApplicationContainerCluster cluster) { Handler<?> guiHandler = new GUIHandler(); - guiHandler.addServerBindings("http://"+GUIHandler.BINDING, "https://"+GUIHandler.BINDING); + guiHandler.addServerBindings("http://"+GUIHandler.BINDING); cluster.addComponent(guiHandler); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/DocumentApiOptionsBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/DocumentApiOptionsBuilder.java index a44f5440a9f..10e24a609f7 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/DocumentApiOptionsBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/DocumentApiOptionsBuilder.java @@ -18,7 +18,7 @@ import java.util.logging.Logger; public class DocumentApiOptionsBuilder { private static final Logger log = Logger.getLogger(DocumentApiOptionsBuilder.class.getName()); - private static final String[] DEFAULT_BINDINGS = {"http://*/", "https://*/"}; + private static final String[] DEFAULT_BINDINGS = {"http://*/"}; public static ContainerDocumentApi.Options build(Element spec) { return new ContainerDocumentApi.Options( diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/AccessControlTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/AccessControlTest.java index fd1ea2ae7ab..f5df3df0070 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/AccessControlTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/AccessControlTest.java @@ -196,8 +196,8 @@ public class AccessControlTest extends ContainerModelBuilderTestBase { @Test public void servlet_can_be_excluded_by_excluding_one_of_its_bindings() throws Exception { final String servletPath = "servlet/path"; - final String notExcludedBinding = "https://*/" + servletPath; - final String excludedBinding = "http://*/" + servletPath; + final String notExcludedBinding = "http://*:8081/" + servletPath; + final String excludedBinding = "http://*:8080/" + servletPath; Element clusterElem = DomBuilderTest.parse( "<jdisc version='1.0'>", httpWithExcludedBinding(excludedBinding), @@ -217,8 +217,8 @@ public class AccessControlTest extends ContainerModelBuilderTestBase { @Test public void rest_api_can_be_excluded_by_excluding_one_of_its_bindings() throws Exception { final String restApiPath = "api/v0"; - final String notExcludedBinding = "http://*/" + restApiPath + Jersey2Servlet.BINDING_SUFFIX;; - final String excludedBinding = "https://*/" + restApiPath + Jersey2Servlet.BINDING_SUFFIX;; + final String notExcludedBinding = "http://*:8081/" + restApiPath + Jersey2Servlet.BINDING_SUFFIX;; + final String excludedBinding = "http://*:8080/" + restApiPath + Jersey2Servlet.BINDING_SUFFIX;; Element clusterElem = DomBuilderTest.parse( "<jdisc version='1.0'>", httpWithExcludedBinding(excludedBinding), diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java index 428286c4794..5b92934678d 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java @@ -16,7 +16,6 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.hasItem; import static org.junit.Assert.assertThat; @@ -64,7 +63,7 @@ public class ContainerDocumentApiBuilderTest extends ContainerModelBuilderTestBa Element elem = DomBuilderTest.parse( "<jdisc id='cluster1' version='1.0'>", " <document-api>", - " <binding>https://*/document-api/</binding>", + " <binding>http://*/document-api/</binding>", " <binding>missing-trailing-slash</binding>", " </document-api>", nodesXml, @@ -77,8 +76,8 @@ public class ContainerDocumentApiBuilderTest extends ContainerModelBuilderTestBa private void verifyCustomBindings(String id, String bindingSuffix) { Handler<?> handler = getHandlers("cluster1").get(id); - assertThat(handler.getServerBindings(), hasItem("https://*/document-api/" + bindingSuffix)); - assertThat(handler.getServerBindings(), hasItem("https://*/document-api/" + bindingSuffix + "/")); + assertThat(handler.getServerBindings(), hasItem("http://*/document-api/" + bindingSuffix)); + assertThat(handler.getServerBindings(), hasItem("http://*/document-api/" + bindingSuffix + "/")); assertThat(handler.getServerBindings(), hasItem("missing-trailing-slash/" + bindingSuffix)); assertThat(handler.getServerBindings(), hasItem("missing-trailing-slash/" + bindingSuffix + "/")); @@ -102,9 +101,7 @@ public class ContainerDocumentApiBuilderTest extends ContainerModelBuilderTestBa assertThat(handlerMap.get("com.yahoo.vespa.http.server.FeedHandler"), not(nullValue())); assertThat(handlerMap.get("com.yahoo.vespa.http.server.FeedHandler").getServerBindings().contains("http://*/" + ContainerCluster.RESERVED_URI_PREFIX + "/feedapi"), is(true)); - assertThat(handlerMap.get("com.yahoo.vespa.http.server.FeedHandler").getServerBindings().contains("https://*/" + ContainerCluster.RESERVED_URI_PREFIX + "/feedapi"), is(true)); assertThat(handlerMap.get("com.yahoo.vespa.http.server.FeedHandler").getServerBindings().contains("http://*/" + ContainerCluster.RESERVED_URI_PREFIX + "/feedapi/"), is(true)); - assertThat(handlerMap.get("com.yahoo.vespa.http.server.FeedHandler").getServerBindings().contains("https://*/" + ContainerCluster.RESERVED_URI_PREFIX + "/feedapi/"), is(true)); - assertThat(handlerMap.get("com.yahoo.vespa.http.server.FeedHandler").getServerBindings().size(), equalTo(4)); + assertThat(handlerMap.get("com.yahoo.vespa.http.server.FeedHandler").getServerBindings().size(), equalTo(2)); } } diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java index 26820672f2c..31077df7f7c 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java @@ -35,7 +35,6 @@ import com.yahoo.vespa.model.container.Container; import com.yahoo.vespa.model.container.ContainerCluster; import com.yahoo.vespa.model.container.SecretStore; import com.yahoo.vespa.model.container.component.Component; -import com.yahoo.vespa.model.container.component.HttpFilter; import com.yahoo.vespa.model.content.utils.ContentClusterUtils; import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithFilePkg; import org.junit.Test; @@ -266,11 +265,11 @@ public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase { JdiscBindingsConfig.Handlers applicationStatusHandler = config.handlers(ApplicationStatusHandler.class.getName()); assertThat(applicationStatusHandler.serverBindings(), - contains("http://*/ApplicationStatus", "https://*/ApplicationStatus")); + contains("http://*/ApplicationStatus")); JdiscBindingsConfig.Handlers fileRequestHandler = config.handlers(VipStatusHandler.class.getName()); assertThat(fileRequestHandler.serverBindings(), - contains("http://*/status.html", "https://*/status.html")); + contains("http://*/status.html")); } @Test diff --git a/config-model/src/test/schema-test-files/services.xml b/config-model/src/test/schema-test-files/services.xml index 40a2b31b3fc..d5a02949cf3 100644 --- a/config-model/src/test/schema-test-files/services.xml +++ b/config-model/src/test/schema-test-files/services.xml @@ -75,7 +75,6 @@ <access-control domain="my.athens-domain" read="true"> <exclude> <binding>http//*/foo/*</binding> - <binding>https://*/foo/*</binding> </exclude> <application>my-app</application> <vespa-domain>vespa.vespa.cd</vespa-domain> @@ -134,7 +133,6 @@ <document-api> <binding>http://*/document-api/</binding> - <binding>https://*/document-api/</binding> <abortondocumenterror>false</abortondocumenterror> <retryenabled>false</retryenabled> <timeout>5.55</timeout> diff --git a/config-model/src/test/schema-test-files/standalone-container.xml b/config-model/src/test/schema-test-files/standalone-container.xml index e36218fa084..0656f293001 100644 --- a/config-model/src/test/schema-test-files/standalone-container.xml +++ b/config-model/src/test/schema-test-files/standalone-container.xml @@ -70,7 +70,6 @@ <document-api> <binding>http://*/document-api/</binding> - <binding>https://*/document-api/</binding> <abortondocumenterror>false</abortondocumenterror> <retryenabled>false</retryenabled> <timeout>5.55</timeout> 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 c4b1d0f7c86..53d20379989 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 @@ -301,12 +301,12 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye if (tenant == null) return false; TenantApplications tenantApplications = tenant.getApplicationRepo(); - if (!tenantApplications.listApplications().contains(applicationId)) return false; + if (!tenantApplications.activeApplications().contains(applicationId)) return false; // Deleting an application is done by deleting the remote session and waiting // until the config server where the deployment happened picks it up and deletes // the local session - long sessionId = tenantApplications.getSessionIdForApplication(applicationId); + long sessionId = tenantApplications.requireActiveSessionOf(applicationId); RemoteSession remoteSession = getRemoteSession(tenant, sessionId); remoteSession.createDeleteTransaction().commit(); @@ -324,7 +324,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye transaction.add(new Rotations(tenant.getCurator(), tenant.getPath()).delete(applicationId)); // TODO: Not unit tested // (When rotations are updated in zk, we need to redeploy the zone app, on the right config server // this is done asynchronously in application maintenance by the node repository) - transaction.add(tenantApplications.deleteApplication(applicationId)); + transaction.add(tenantApplications.createDeleteTransaction(applicationId)); hostProvisioner.ifPresent(provisioner -> provisioner.remove(transaction, applicationId)); transaction.onCommitted(() -> log.log(LogLevel.INFO, "Deleted " + applicationId)); @@ -425,7 +425,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye Set<ApplicationId> listApplications() { return tenantRepository.getAllTenants().stream() - .flatMap(tenant -> tenant.getApplicationRepo().listApplications().stream()) + .flatMap(tenant -> tenant.getApplicationRepo().activeApplications().stream()) .collect(Collectors.toSet()); } @@ -483,7 +483,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye if (applicationRepo == null) throw new IllegalArgumentException("Application repo for tenant '" + tenant.getName() + "' not found"); - return applicationRepo.getSessionIdForApplication(applicationId); + return applicationRepo.requireActiveSessionOf(applicationId); } public void validateThatRemoteSessionIsNotActive(Tenant tenant, long sessionId) { @@ -565,7 +565,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye } private List<ApplicationId> activeApplications(TenantName tenantName) { - return tenantRepository.getTenant(tenantName).getApplicationRepo().listApplications(); + return tenantRepository.getTenant(tenantName).getApplicationRepo().activeApplications(); } // ---------------- Misc operations ---------------------------------------------------------------- @@ -616,7 +616,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye Optional<ApplicationSet> currentActiveApplicationSet = Optional.empty(); TenantApplications applicationRepo = tenant.getApplicationRepo(); try { - long currentActiveSessionId = applicationRepo.getSessionIdForApplication(appId); + long currentActiveSessionId = applicationRepo.requireActiveSessionOf(appId); RemoteSession currentActiveSession = getRemoteSession(tenant, currentActiveSessionId); if (currentActiveSession != null) { currentActiveApplicationSet = Optional.ofNullable(currentActiveSession.ensureApplicationLoaded()); @@ -646,7 +646,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye private List<ApplicationId> listApplicationIds(Tenant tenant) { TenantApplications applicationRepo = tenant.getApplicationRepo(); - return applicationRepo.listApplications(); + return applicationRepo.activeApplications(); } private void cleanupTempDirectory(File tempDir) { @@ -658,13 +658,13 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye private LocalSession getExistingSession(Tenant tenant, ApplicationId applicationId) { TenantApplications applicationRepo = tenant.getApplicationRepo(); - return getLocalSession(tenant, applicationRepo.getSessionIdForApplication(applicationId)); + return getLocalSession(tenant, applicationRepo.requireActiveSessionOf(applicationId)); } private LocalSession getActiveSession(Tenant tenant, ApplicationId applicationId) { TenantApplications applicationRepo = tenant.getApplicationRepo(); - if (applicationRepo.listApplications().contains(applicationId)) { - return tenant.getLocalSessionRepo().getSession(applicationRepo.getSessionIdForApplication(applicationId)); + if (applicationRepo.activeApplications().contains(applicationId)) { + return tenant.getLocalSessionRepo().getSession(applicationRepo.requireActiveSessionOf(applicationId)); } return null; } 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 3705a0ec145..656030bb8d2 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 @@ -17,18 +17,19 @@ import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; import java.util.List; +import java.util.OptionalLong; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.logging.Logger; import java.util.stream.Collectors; -import java.util.stream.Stream; /** * The applications of a tenant, backed by ZooKeeper. * - * Each application is stored as a single node under /config/v2/tenants/<tenant>/applications/<applications>, - * named the same as the application id and containing the id of the session storing the content of the application. + * Each application is stored under /config/v2/tenants/<tenant>/applications/<applications>, + * the root contains the currently active session, if any, and sub-paths /preparing contains the session id + * of whatever session may be activated next, if any, and /lock is used for synchronizing writes to all these paths. * * @author Ulf Lilleengen */ @@ -69,16 +70,18 @@ public class TenantApplications { * * @return a list of {@link ApplicationId}s that are active. */ - public List<ApplicationId> listApplications() { + public List<ApplicationId> activeApplications() { return curator.getChildren(applicationsPath).stream() - .flatMap(this::parseApplication) + .filter(this::isValid) + .map(ApplicationId::fromSerializedForm) + .filter(id -> activeSessionOf(id).isPresent()) .collect(Collectors.toUnmodifiableList()); } - // TODO jvenstad: Remove after it has run once everywhere. - private Stream<ApplicationId> parseApplication(String appNode) { + private boolean isValid(String appNode) { // TODO jvenstad: Remove after it has run once everywhere. try { - return Stream.of(ApplicationId.fromSerializedForm(appNode)); + ApplicationId.fromSerializedForm(appNode); + return true; } catch (IllegalArgumentException __) { log.log(LogLevel.INFO, TenantRepository.logPre(tenant) + "Unable to parse application id from '" + appNode + "'; deleting it as it shouldn't be here."); @@ -88,18 +91,25 @@ public class TenantApplications { catch (Exception e) { log.log(LogLevel.WARNING, TenantRepository.logPre(tenant) + "Failed to clean up stray node '" + appNode + "'!", e); } - return Stream.empty(); + return false; } } + /** Returns the id of the currently active session for the given application, if any. Throws on unknown applications. */ + public OptionalLong activeSessionOf(ApplicationId id) { + String data = curator.getData(applicationPath(id)).map(Utf8::toString) + .orElseThrow(() -> new IllegalArgumentException("Unknown application '" + id + "'.")); + return data.isEmpty() ? OptionalLong.empty() : OptionalLong.of(Long.parseLong(data)); + } + /** * Returns a transaction which writes the given session id as the currently active for the given application. * * @param applicationId An {@link ApplicationId} that represents an active application. * @param sessionId Id of the session containing the application package for this id. */ - public Transaction createPutApplicationTransaction(ApplicationId applicationId, long sessionId) { - if (listApplications().contains(applicationId)) { + public Transaction createPutTransaction(ApplicationId applicationId, long sessionId) { + if (curator.exists(applicationPath(applicationId))) { return new CuratorTransaction(curator).add(CuratorOperations.setData(applicationPath(applicationId).getAbsolute(), Utf8.toAsciiBytes(sessionId))); } else { return new CuratorTransaction(curator).add(CuratorOperations.create(applicationPath(applicationId).getAbsolute(), Utf8.toAsciiBytes(sessionId))); @@ -107,25 +117,21 @@ public class TenantApplications { } /** - * Return the stored session id for a given application. + * Return the active session id for a given application. * * @param applicationId an {@link ApplicationId} * @return session id of given application id. * @throws IllegalArgumentException if the application does not exist */ - public long getSessionIdForApplication(ApplicationId applicationId) { - String path = applicationPath(applicationId).getAbsolute(); - try { - return Long.parseLong(Utf8.toString(curator.framework().getData().forPath(path))); - } catch (Exception e) { - throw new IllegalArgumentException(TenantRepository.logPre(applicationId) + "Unable to read the session id from '" + path + "'", e); - } + public long requireActiveSessionOf(ApplicationId applicationId) { + return activeSessionOf(applicationId) + .orElseThrow(() -> new IllegalArgumentException("Application '" + applicationId + "' has no active session.")); } /** * Returns a transaction which deletes this application. */ - public CuratorTransaction deleteApplication(ApplicationId applicationId) { + public CuratorTransaction createDeleteTransaction(ApplicationId applicationId) { return CuratorTransaction.from(CuratorOperations.delete(applicationPath(applicationId).getAbsolute()), curator); } @@ -133,7 +139,7 @@ public class TenantApplications { * Removes all applications not known to this from the config server state. */ public void removeUnusedApplications() { - reloadHandler.removeApplicationsExcept(Set.copyOf(listApplications())); + reloadHandler.removeApplicationsExcept(Set.copyOf(activeApplications())); } /** diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandler.java index 6345532d4ff..cdf995b80bb 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsHandler.java @@ -56,7 +56,7 @@ public class ListApplicationsHandler extends HttpHandler { Utils.checkThatTenantExists(tenantRepository, tenantName); Tenant tenant = tenantRepository.getTenant(tenantName); TenantApplications applicationRepo = tenant.getApplicationRepo(); - return applicationRepo.listApplications(); + return applicationRepo.activeApplications(); } private static String createUrlStringFromId(String urlBase, ApplicationId id, Zone zone) { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java index 0cdf5ebfe95..af8956803ab 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java @@ -95,7 +95,7 @@ public class LocalSession extends Session implements Comparable<LocalSession> { zooKeeperClient.createActiveWaiter(); superModelGenerationCounter.increment(); // TODO jvenstad: I hope this counter isn't used for serious things, as it's updated way ahead of activation. Transaction transaction = createSetStatusTransaction(Status.ACTIVATE); - transaction.add(applicationRepo.createPutApplicationTransaction(zooKeeperClient.readApplicationId(), getSessionId()).operations()); + transaction.add(applicationRepo.createPutTransaction(zooKeeperClient.readApplicationId(), getSessionId()).operations()); return transaction; } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionRepo.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionRepo.java index 15182813a22..ccd5684b9ff 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionRepo.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSessionRepo.java @@ -190,9 +190,9 @@ public class RemoteSessionRepo extends SessionRepo<RemoteSession> { } private void loadSessionIfActive(RemoteSession session) { - for (ApplicationId applicationId : applicationRepo.listApplications()) { + for (ApplicationId applicationId : applicationRepo.activeApplications()) { try { - if (applicationRepo.getSessionIdForApplication(applicationId) == session.getSessionId()) { + if (applicationRepo.requireActiveSessionOf(applicationId) == session.getSessionId()) { log.log(LogLevel.DEBUG, "Found active application for session " + session.getSessionId() + " , loading it"); loadActiveSession(session); break; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java index 90eeb89dc8e..d8ba5890545 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java @@ -188,9 +188,9 @@ public class SessionFactoryImpl implements SessionFactory, LocalSessionLoader { } private long getActiveSessionId(ApplicationId applicationId) { - List<ApplicationId> applicationIds = applicationRepo.listApplications(); + List<ApplicationId> applicationIds = applicationRepo.activeApplications(); if (applicationIds.contains(applicationId)) { - return applicationRepo.getSessionIdForApplication(applicationId); + return applicationRepo.requireActiveSessionOf(applicationId); } return nonExistingActiveSession; } diff --git a/configserver/src/main/resources/configserver-app/services.xml b/configserver/src/main/resources/configserver-app/services.xml index b2c426e707b..5aca82409a9 100644 --- a/configserver/src/main/resources/configserver-app/services.xml +++ b/configserver/src/main/resources/configserver-app/services.xml @@ -76,115 +76,77 @@ <handler id='com.yahoo.vespa.config.server.http.HttpGetConfigHandler' bundle='configserver'> <binding>http://*/config/v1/*/*</binding> - <binding>https://*/config/v1/*/*</binding> <binding>http://*/config/v1/*</binding> - <binding>https://*/config/v1/*</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.HttpListConfigsHandler' bundle='configserver'> <binding>http://*/config/v1/</binding> - <binding>https://*/config/v1/</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.HttpListNamedConfigsHandler' bundle='configserver'> <binding>http://*/config/v1/*/</binding> - <binding>https://*/config/v1/*/</binding> <binding>http://*/config/v1/*/*/</binding> - <binding>https://*/config/v1/*/*/</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.status.StatusHandler' bundle='configserver'> <binding>http://*/status</binding> - <binding>https://*/status</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.flags.FlagsHandler' bundle='configserver'> <binding>http://*/flags/v1</binding> - <binding>https://*/flags/v1</binding> <binding>http://*/flags/v1/*</binding> - <binding>https://*/flags/v1/*</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.v2.TenantHandler' bundle='configserver'> <binding>http://*/application/v2/tenant/</binding> - <binding>https://*/application/v2/tenant/</binding> <binding>http://*/application/v2/tenant/*</binding> - <binding>https://*/application/v2/tenant/*</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.v2.SessionCreateHandler' bundle='configserver'> <binding>http://*/application/v2/tenant/*/session</binding> - <binding>https://*/application/v2/tenant/*/session</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.v2.SessionPrepareHandler' bundle='configserver'> <binding>http://*/application/v2/tenant/*/session/*/prepared</binding> - <binding>https://*/application/v2/tenant/*/session/*/prepared</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.v2.SessionActiveHandler' bundle='configserver'> <binding>http://*/application/v2/tenant/*/session/*/active</binding> - <binding>https://*/application/v2/tenant/*/session/*/active</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.v2.ApplicationApiHandler' bundle='configserver'> <binding>http://*/application/v2/tenant/*/prepareandactivate</binding> - <binding>https://*/application/v2/tenant/*/prepareandactivate</binding> <binding>http://*/application/v2/tenant/*/session/*/prepareandactivate</binding> - <binding>https://*/application/v2/tenant/*/session/*/prepareandactivate</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.v2.SessionContentHandler' bundle='configserver'> <binding>http://*/application/v2/tenant/*/session/*/content/*</binding> - <binding>https://*/application/v2/tenant/*/session/*/content/*</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.v2.ListApplicationsHandler' bundle='configserver'> <binding>http://*/application/v2/tenant/*/application/</binding> - <binding>https://*/application/v2/tenant/*/application/</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.v2.ApplicationHandler' bundle='configserver'> <!-- WARNING: THIS LIST *MUST* MATCH THE ONE IN ApplicationHandler::getBindingMatch --> <binding>http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/content/*</binding> - <binding>https://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/content/*</binding> <binding>http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/filedistributionstatus</binding> - <binding>https://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/filedistributionstatus</binding> <binding>http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/suspended</binding> <binding>http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/restart</binding> - <binding>https://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/restart</binding> <binding>http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/converge</binding> - <binding>https://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/converge</binding> <binding>http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/serviceconverge</binding> - <binding>https://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/serviceconverge</binding> <binding>http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/serviceconverge/*</binding> - <binding>https://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/serviceconverge/*</binding> <binding>http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/clustercontroller/*/status/*</binding> - <binding>https://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/clustercontroller/*/status/*</binding> <binding>http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*</binding> - <binding>https://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*</binding> <binding>http://*/application/v2/tenant/*/application/*</binding> - <binding>https://*/application/v2/tenant/*/application/*</binding> <binding>http://*/application/v2/tenant/*/application/*/logs</binding> - <binding>https://*/application/v2/tenant/*/application/*/logs</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.v2.HttpGetConfigHandler' bundle='configserver'> <binding>http://*/config/v2/tenant/*/application/*/*</binding> - <binding>https://*/config/v2/tenant/*/application/*/*</binding> <binding>http://*/config/v2/tenant/*/application/*/*/*</binding> - <binding>https://*/config/v2/tenant/*/application/*/*/*</binding> <binding>http://*/config/v2/tenant/*/application/*/environment/*/region/*/instance/*/*</binding> - <binding>https://*/config/v2/tenant/*/application/*/environment/*/region/*/instance/*/*</binding> <binding>http://*/config/v2/tenant/*/application/*/environment/*/region/*/instance/*/*/*</binding> - <binding>https://*/config/v2/tenant/*/application/*/environment/*/region/*/instance/*/*/*</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.v2.HttpListConfigsHandler' bundle='configserver'> <binding>http://*/config/v2/tenant/*/application/*/</binding> - <binding>https://*/config/v2/tenant/*/application/*/</binding> <binding>http://*/config/v2/tenant/*/application/*/environment/*/region/*/instance/*/</binding> - <binding>https://*/config/v2/tenant/*/application/*/environment/*/region/*/instance/*/</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.v2.HttpListNamedConfigsHandler' bundle='configserver'> <binding>http://*/config/v2/tenant/*/application/*/*/</binding> - <binding>https://*/config/v2/tenant/*/application/*/*/</binding> <binding>http://*/config/v2/tenant/*/application/*/*/*/</binding> - <binding>https://*/config/v2/tenant/*/application/*/*/*/</binding> <binding>http://*/config/v2/tenant/*/application/*/environment/*/region/*/instance/*/*/</binding> - <binding>https://*/config/v2/tenant/*/application/*/environment/*/region/*/instance/*/*/</binding> <binding>http://*/config/v2/tenant/*/application/*/environment/*/region/*/instance/*/*/*/</binding> - <binding>https://*/config/v2/tenant/*/application/*/environment/*/region/*/instance/*/*/*/</binding> </handler> <handler id='com.yahoo.vespa.config.server.http.v2.HostHandler' bundle='configserver'> <binding>http://*/application/v2/host/*</binding> - <binding>https://*/application/v2/host/*</binding> </handler> <http> 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 5d356ddf88e..e0fa760b35d 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 @@ -315,7 +315,7 @@ public class ApplicationRepositoryTest { assertTrue(deployment2.isPresent()); deployment2.get().activate(); // session 3 - long activeSessionId = tester.tenant().getApplicationRepo().getSessionIdForApplication(tester.applicationId()); + long activeSessionId = tester.tenant().getApplicationRepo().requireActiveSessionOf(tester.applicationId()); clock.advance(Duration.ofSeconds(10)); Optional<com.yahoo.config.provision.Deployment> deployment3 = tester.redeployFromLocalActive(); @@ -325,7 +325,7 @@ public class ApplicationRepositoryTest { LocalSession deployment3session = ((com.yahoo.vespa.config.server.deploy.Deployment) deployment3.get()).session(); assertNotEquals(activeSessionId, deployment3session); // No change to active session id - assertEquals(activeSessionId, tester.tenant().getApplicationRepo().getSessionIdForApplication(tester.applicationId())); + assertEquals(activeSessionId, tester.tenant().getApplicationRepo().requireActiveSessionOf(tester.applicationId())); assertEquals(3, tester.tenant().getLocalSessionRepo().listSessions().size()); clock.advance(Duration.ofHours(1)); // longer than session lifetime diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java index a708e4d8ace..01a7d5e0239 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java @@ -39,12 +39,12 @@ public class TenantApplicationsTest { writeApplicationData(createApplicationId("foo"), 3L); writeApplicationData(createApplicationId("bar"), 4L); TenantApplications repo = createZKAppRepo(); - List<ApplicationId> applications = repo.listApplications(); + List<ApplicationId> applications = repo.activeApplications(); assertThat(applications.size(), is(2)); assertThat(applications.get(0).application().value(), is("foo")); assertThat(applications.get(1).application().value(), is("bar")); - assertThat(repo.getSessionIdForApplication(applications.get(0)), is(3L)); - assertThat(repo.getSessionIdForApplication(applications.get(1)), is(4L)); + assertThat(repo.requireActiveSessionOf(applications.get(0)), is(3L)); + assertThat(repo.requireActiveSessionOf(applications.get(1)), is(4L)); } @Test @@ -52,7 +52,7 @@ public class TenantApplicationsTest { writeApplicationData(createApplicationId("foo"), 3L); writeApplicationData("invalid", 3L); TenantApplications repo = createZKAppRepo(); - List<ApplicationId> applications = repo.listApplications(); + List<ApplicationId> applications = repo.activeApplications(); assertThat(applications.size(), is(1)); assertThat(applications.get(0).application().value(), is("foo")); } @@ -60,7 +60,7 @@ public class TenantApplicationsTest { @Test(expected = IllegalArgumentException.class) public void require_that_requesting_session_for_unknown_application_throws_exception() throws Exception { TenantApplications repo = createZKAppRepo(); - repo.getSessionIdForApplication(createApplicationId("nonexistent")); + repo.requireActiveSessionOf(createApplicationId("nonexistent")); } @Test(expected = IllegalArgumentException.class) @@ -70,18 +70,18 @@ public class TenantApplicationsTest { curatorFramework.create().creatingParentsIfNeeded() .forPath(TenantRepository.getApplicationsPath(tenantName).append(baz.serializedForm()).getAbsolute()); TenantApplications repo = createZKAppRepo(); - repo.getSessionIdForApplication(baz); + repo.requireActiveSessionOf(baz); } @Test public void require_that_application_ids_can_be_written() throws Exception { TenantApplications repo = createZKAppRepo(); ApplicationId myapp = createApplicationId("myapp"); - repo.createPutApplicationTransaction(myapp, 3l).commit(); + repo.createPutTransaction(myapp, 3l).commit(); String path = TenantRepository.getApplicationsPath(tenantName).append(myapp.serializedForm()).getAbsolute(); assertTrue(curatorFramework.checkExists().forPath(path) != null); assertThat(Utf8.toString(curatorFramework.getData().forPath(path)), is("3")); - repo.createPutApplicationTransaction(myapp, 5l).commit(); + repo.createPutTransaction(myapp, 5l).commit(); assertTrue(curatorFramework.checkExists().forPath(path) != null); assertThat(Utf8.toString(curatorFramework.getData().forPath(path)), is("5")); } @@ -91,13 +91,13 @@ public class TenantApplicationsTest { TenantApplications repo = createZKAppRepo(); ApplicationId id1 = createApplicationId("myapp"); ApplicationId id2 = createApplicationId("myapp2"); - repo.createPutApplicationTransaction(id1, 1).commit(); - repo.createPutApplicationTransaction(id2, 1).commit(); - assertThat(repo.listApplications().size(), is(2)); - repo.deleteApplication(id1).commit(); - assertThat(repo.listApplications().size(), is(1)); - repo.deleteApplication(id2).commit(); - assertThat(repo.listApplications().size(), is(0)); + repo.createPutTransaction(id1, 1).commit(); + repo.createPutTransaction(id2, 1).commit(); + assertThat(repo.activeApplications().size(), is(2)); + repo.createDeleteTransaction(id1).commit(); + assertThat(repo.activeApplications().size(), is(1)); + repo.createDeleteTransaction(id2).commit(); + assertThat(repo.activeApplications().size(), is(0)); } @Test @@ -108,7 +108,7 @@ public class TenantApplicationsTest { MockReloadHandler reloadHandler = new MockReloadHandler(); TenantApplications repo = createZKAppRepo(reloadHandler); assertNull(reloadHandler.lastRemoved); - repo.deleteApplication(foo).commit(); + repo.createDeleteTransaction(foo).commit(); long endTime = System.currentTimeMillis() + 60_000; while (System.currentTimeMillis() < endTime && reloadHandler.lastRemoved == null) { Thread.sleep(100); 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 7ffb9552cf8..6b67dcc4e9a 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 @@ -183,7 +183,7 @@ public class DeployTester { public AllocatedHosts getAllocatedHostsOf(ApplicationId applicationId) { Tenant tenant = tenant(); LocalSession session = tenant.getLocalSessionRepo().getSession(tenant.getApplicationRepo() - .getSessionIdForApplication(applicationId)); + .requireActiveSessionOf(applicationId)); return session.getAllocatedHosts(); } 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 b0bb3bf244f..3d34a4eeaf5 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 @@ -56,12 +56,12 @@ public class ApplicationContentHandlerTest extends ContentHandlerTestBase { session2 = new MockSession(2l, FilesApplicationPackage.fromFile(new File("src/test/apps/content"))); Tenant tenant1 = tenantRepository.getTenant(tenantName1); tenant1.getLocalSessionRepo().addSession(session2); - tenant1.getApplicationRepo().createPutApplicationTransaction(idTenant1, 2l).commit(); + tenant1.getApplicationRepo().createPutTransaction(idTenant1, 2l).commit(); MockSession session3 = new MockSession(3l, FilesApplicationPackage.fromFile(new File("src/test/apps/content2"))); Tenant tenant2 = tenantRepository.getTenant(tenantName2); tenant2.getLocalSessionRepo().addSession(session3); - tenant2.getApplicationRepo().createPutApplicationTransaction(idTenant2, 3l).commit(); + tenant2.getApplicationRepo().createPutTransaction(idTenant2, 3l).commit(); handler = new ApplicationHandler(ApplicationHandler.testOnlyContext(), 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 d3dcbcc2252..fa560ceae4d 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 @@ -223,13 +223,13 @@ public class ApplicationHandlerTest { } private void deleteAndAssertOKResponseMocked(ApplicationId applicationId, boolean fullAppIdInUrl) throws IOException { - long sessionId = tenantRepository.getTenant(applicationId.tenant()).getApplicationRepo().getSessionIdForApplication(applicationId); + long sessionId = tenantRepository.getTenant(applicationId.tenant()).getApplicationRepo().requireActiveSessionOf(applicationId); deleteAndAssertResponse(applicationId, Zone.defaultZone(), Response.Status.OK, null, fullAppIdInUrl); assertNull(tenantRepository.getTenant(applicationId.tenant()).getLocalSessionRepo().getSession(sessionId)); } private void deleteAndAssertOKResponse(Tenant tenant, ApplicationId applicationId) throws IOException { - long sessionId = tenant.getApplicationRepo().getSessionIdForApplication(applicationId); + long sessionId = tenant.getApplicationRepo().requireActiveSessionOf(applicationId); deleteAndAssertResponse(applicationId, Zone.defaultZone(), Response.Status.OK, null, true); assertNull(tenant.getLocalSessionRepo().getSession(sessionId)); } 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 2d3dcc592f7..fb75e91dfd6 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 @@ -46,7 +46,7 @@ public class HostHandlerTest { private HostHandler hostHandler; static void addMockApplication(Tenant tenant, ApplicationId applicationId, long sessionId) { - tenant.getApplicationRepo().createPutApplicationTransaction(applicationId, sessionId).commit(); + tenant.getApplicationRepo().createPutTransaction(applicationId, sessionId).commit(); ApplicationPackage app = FilesApplicationPackage.fromFile(testApp); tenant.getLocalSessionRepo().addSession(new SessionHandlerTest.MockSession(sessionId, app, applicationId)); TestComponentRegistry componentRegistry = new TestComponentRegistry.Builder() 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 f57e7f09b39..b34f7a0c487 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 @@ -51,12 +51,12 @@ public class ListApplicationsHandlerTest { final String url = "http://myhost:14000/application/v2/tenant/mytenant/application/"; assertResponse(url, Response.Status.OK, "[]"); - applicationRepo.createPutApplicationTransaction( + applicationRepo.createPutTransaction( new ApplicationId.Builder().tenant("tenant").applicationName("foo").instanceName("quux").build(), 1).commit(); assertResponse(url, Response.Status.OK, "[\"" + url + "foo/environment/dev/region/us-east/instance/quux\"]"); - applicationRepo.createPutApplicationTransaction( + applicationRepo.createPutTransaction( new ApplicationId.Builder().tenant("tenant").applicationName("bali").instanceName("quux").build(), 1).commit(); assertResponse(url, Response.Status.OK, @@ -82,10 +82,10 @@ public class ListApplicationsHandlerTest { @Test public void require_that_listing_works_with_multiple_tenants() throws Exception { - applicationRepo.createPutApplicationTransaction(new ApplicationId.Builder() + applicationRepo.createPutTransaction(new ApplicationId.Builder() .tenant("tenant") .applicationName("foo").instanceName("quux").build(), 1).commit(); - applicationRepo2.createPutApplicationTransaction(new ApplicationId.Builder() + applicationRepo2.createPutTransaction(new ApplicationId.Builder() .tenant("tenant") .applicationName("quux").instanceName("foo").build(), 1).commit(); String url = "http://myhost:14000/application/v2/tenant/mytenant/application/"; 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 927ac26b77d..bc509fcd802 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 @@ -194,7 +194,7 @@ public class SessionCreateHandlerTest extends SessionHandlerTest { .applicationName("foo") .instanceName("quux") .build(); - applicationRepo.createPutApplicationTransaction(fooId, 2).commit(); + applicationRepo.createPutTransaction(fooId, 2).commit(); assertFromParameter("3", "http://myhost:40555/application/v2/tenant/" + tenant + "/application/foo/environment/test/region/baz/instance/quux"); localSessionRepo.addSession(new SessionHandlerTest.MockSession(5l, FilesApplicationPackage.fromFile(testApp))); ApplicationId bioId = new ApplicationId.Builder() @@ -202,7 +202,7 @@ public class SessionCreateHandlerTest extends SessionHandlerTest { .applicationName("foobio") .instanceName("quux") .build(); - applicationRepo.createPutApplicationTransaction(bioId, 5).commit(); + applicationRepo.createPutTransaction(bioId, 5).commit(); assertFromParameter("6", "http://myhost:40555/application/v2/tenant/" + tenant + "/application/foobio/environment/staging/region/baz/instance/quux"); } diff --git a/http-utils/OWNERS b/http-utils/OWNERS new file mode 100644 index 00000000000..569bf1cc3a1 --- /dev/null +++ b/http-utils/OWNERS @@ -0,0 +1 @@ +bjorncs diff --git a/http-utils/README.md b/http-utils/README.md new file mode 100644 index 00000000000..8bbe2cd7d05 --- /dev/null +++ b/http-utils/README.md @@ -0,0 +1 @@ +# Http utilities for Java
\ No newline at end of file diff --git a/http-utils/pom.xml b/http-utils/pom.xml new file mode 100644 index 00000000000..aea402aef87 --- /dev/null +++ b/http-utils/pom.xml @@ -0,0 +1,52 @@ +<?xml version="1.0"?> +<!-- Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.yahoo.vespa</groupId> + <artifactId>parent</artifactId> + <version>7-SNAPSHOT</version> + <relativePath>../parent/pom.xml</relativePath> + </parent> + <artifactId>http-utils</artifactId> + <packaging>jar</packaging> + <version>7-SNAPSHOT</version> + <dependencies> + <!-- provided --> + <dependency> + <groupId>com.yahoo.vespa</groupId> + <artifactId>security-utils</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + + <!-- compile scope --> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpcore</artifactId> + <scope>compile</scope> + </dependency> + + <!-- test scope --> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/security-utils/src/main/java/com/yahoo/security/tls/https/VespaHttpClientBuilder.java b/http-utils/src/main/java/ai/vespa/util/http/VespaHttpClientBuilder.java index 9fa51fc36cb..5e7a9441fc8 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/https/VespaHttpClientBuilder.java +++ b/http-utils/src/main/java/ai/vespa/util/http/VespaHttpClientBuilder.java @@ -1,5 +1,5 @@ // Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.security.tls.https; +package ai.vespa.util.http; import com.yahoo.security.tls.MixedMode; import com.yahoo.security.tls.TlsContext; @@ -8,10 +8,15 @@ import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.utils.URIBuilder; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.HttpClientConnectionManager; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; import org.apache.http.protocol.HttpContext; import javax.net.ssl.SSLParameters; @@ -34,19 +39,33 @@ public class VespaHttpClientBuilder { private static final Logger log = Logger.getLogger(VespaHttpClientBuilder.class.getName()); public interface ConnectionManagerFactory { - HttpClientConnectionManager create(SSLConnectionSocketFactory sslSocketFactory); + HttpClientConnectionManager create(Registry<ConnectionSocketFactory> socketFactoryRegistry); } private VespaHttpClientBuilder() {} + /** + * Create a client builder with default connection manager. + */ public static HttpClientBuilder create() { return createBuilder(null); } + /** + * Create a client builder with a user specified connection manager. + */ public static HttpClientBuilder create(ConnectionManagerFactory connectionManagerFactory) { return createBuilder(connectionManagerFactory); } + /** + * Creates a client builder with a {@link BasicHttpClientConnectionManager} configured. + * This connection manager uses a single connection for all requests. See Javadoc for details. + */ + public static HttpClientBuilder createWithBasicConnectionManager() { + return createBuilder(BasicHttpClientConnectionManager::new); + } + private static HttpClientBuilder createBuilder(ConnectionManagerFactory connectionManagerFactory) { var builder = HttpClientBuilder.create(); addSslSocketFactory(builder, connectionManagerFactory); @@ -60,7 +79,7 @@ public class VespaHttpClientBuilder { log.log(Level.FINE, "Adding ssl socket factory to client"); SSLConnectionSocketFactory socketFactory = createSslSocketFactory(tlsContext); if (connectionManagerFactory != null) { - builder.setConnectionManager(connectionManagerFactory.create(socketFactory)); + builder.setConnectionManager(connectionManagerFactory.create(createRegistry(socketFactory))); } else { builder.setSSLSocketFactory(socketFactory); } @@ -80,6 +99,13 @@ public class VespaHttpClientBuilder { return new SSLConnectionSocketFactory(tlsContext.context(), parameters.getProtocols(), parameters.getCipherSuites(), new NoopHostnameVerifier()); } + private static Registry<ConnectionSocketFactory> createRegistry(SSLConnectionSocketFactory sslSocketFactory) { + return RegistryBuilder.<ConnectionSocketFactory>create() + .register("https", sslSocketFactory) + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .build(); + } + static class HttpToHttpsRewritingRequestInterceptor implements HttpRequestInterceptor { @Override public void process(HttpRequest request, HttpContext context) { diff --git a/security-utils/src/test/java/com/yahoo/security/tls/https/VespaHttpClientBuilderTest.java b/http-utils/src/test/java/ai/vespa/util/http/VespaHttpClientBuilderTest.java index 10b8458359c..7ffd0e459b0 100644 --- a/security-utils/src/test/java/com/yahoo/security/tls/https/VespaHttpClientBuilderTest.java +++ b/http-utils/src/test/java/ai/vespa/util/http/VespaHttpClientBuilderTest.java @@ -1,7 +1,7 @@ // Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.security.tls.https; +package ai.vespa.util.http; -import com.yahoo.security.tls.https.VespaHttpClientBuilder.HttpToHttpsRewritingRequestInterceptor; +import ai.vespa.util.http.VespaHttpClientBuilder.HttpToHttpsRewritingRequestInterceptor; import org.apache.http.client.methods.HttpGet; import org.apache.http.protocol.BasicHttpContext; import org.junit.Test; diff --git a/jdisc_core/src/main/java/com/yahoo/jdisc/application/BindingRepository.java b/jdisc_core/src/main/java/com/yahoo/jdisc/application/BindingRepository.java index b6591ef4825..574be20e910 100644 --- a/jdisc_core/src/main/java/com/yahoo/jdisc/application/BindingRepository.java +++ b/jdisc_core/src/main/java/com/yahoo/jdisc/application/BindingRepository.java @@ -33,6 +33,9 @@ public class BindingRepository<T> implements Iterable<Map.Entry<UriPattern, T>> * @throws IllegalArgumentException If the URI pattern string could not be parsed. */ public void bind(String uriPattern, T target) { + if (uriPattern.startsWith("https://")) { + log.warning(() -> "Bindings with 'https' scheme are deprecated. Use 'http' to match both 'http' and 'https' in URIs."); + } put(new UriPattern(uriPattern), target); } diff --git a/jrt/pom.xml b/jrt/pom.xml index e9383654e30..5208c0417cc 100644 --- a/jrt/pom.xml +++ b/jrt/pom.xml @@ -34,16 +34,6 @@ <artifactId>security-utils</artifactId> <version>${project.version}</version> <scope>compile</scope> - <exclusions> - <exclusion> <!-- not needed --> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpclient</artifactId> - </exclusion> - <exclusion> <!-- not needed --> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpcore</artifactId> - </exclusion> - </exclusions> </dependency> <dependency> <!-- required due to bug in maven dependency resolving - bouncycastle is compile scope in security-utils, yet it is not part of test scope here --> <groupId>org.bouncycastle</groupId> diff --git a/node-repository/src/main/config/node-repository.xml b/node-repository/src/main/config/node-repository.xml index f46a2d9d2e3..2bc3ae5cfeb 100644 --- a/node-repository/src/main/config/node-repository.xml +++ b/node-repository/src/main/config/node-repository.xml @@ -8,12 +8,10 @@ <handler id="com.yahoo.vespa.hosted.provision.restapi.v2.NodesApiHandler" bundle="node-repository"> <binding>http://*/nodes/v2/*</binding> - <binding>https://*/nodes/v2/*</binding> </handler> <handler id="com.yahoo.vespa.hosted.provision.restapi.v2.LoadBalancersApiHandler" bundle="node-repository"> <binding>http://*/loadbalancers/v1/*</binding> - <binding>https://*/loadbalancers/v1/*</binding> </handler> <preprocess:include file="node-flavors.xml" required="false" /> @@ -79,6 +79,7 @@ <module>filedistribution</module> <module>flags</module> <module>fsa</module> + <module>http-utils</module> <module>indexinglanguage</module> <module>jaxrs_client_utils</module> <module>jaxrs_utils</module> diff --git a/security-utils/pom.xml b/security-utils/pom.xml index f7704762250..10dec598915 100644 --- a/security-utils/pom.xml +++ b/security-utils/pom.xml @@ -31,16 +31,6 @@ <artifactId>jackson-databind</artifactId> <scope>compile</scope> </dependency> - <dependency> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpclient</artifactId> - <scope>compile</scope> - </dependency> - <dependency> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpcore</artifactId> - <scope>compile</scope> - </dependency> <!-- test scope --> <dependency> |