summaryrefslogtreecommitdiffstats
path: root/configserver
diff options
context:
space:
mode:
authorHarald Musum <musum@oath.com>2018-02-05 14:33:31 +0100
committerHarald Musum <musum@oath.com>2018-02-05 14:33:31 +0100
commit9da3356c15e5c4f9f148716a1d773a35435df5ae (patch)
tree44fd2d5b7046bb703cfd5ea00f414be80038aacd /configserver
parentc7cbe1364113698465758840e51b3acf0390903c (diff)
Support POST with app for prepareandactivate
Start move to ApplicationApiHandler
Diffstat (limited to 'configserver')
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java36
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStream.java6
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandler.java50
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareAndActivateHandler.java68
-rw-r--r--configserver/src/main/resources/configserver-app/services.xml2
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java18
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionFactoryTest.java4
8 files changed, 71 insertions, 116 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 967cb06a13a..96b9651a55f 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
@@ -1,6 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server;
+import com.google.common.io.Files;
import com.google.inject.Inject;
import com.yahoo.cloud.config.ConfigserverConfig;
import com.yahoo.component.Version;
@@ -15,6 +16,7 @@ import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.Provisioner;
import com.yahoo.config.provision.TenantName;
import com.yahoo.container.jdisc.HttpResponse;
+import com.yahoo.io.IOUtils;
import com.yahoo.log.LogLevel;
import com.yahoo.path.Path;
import com.yahoo.slime.Slime;
@@ -31,6 +33,7 @@ import com.yahoo.vespa.config.server.configchange.RefeedActions;
import com.yahoo.vespa.config.server.configchange.RestartActions;
import com.yahoo.vespa.config.server.deploy.DeployHandlerLogger;
import com.yahoo.vespa.config.server.deploy.Deployment;
+import com.yahoo.vespa.config.server.http.CompressedApplicationInputStream;
import com.yahoo.vespa.config.server.http.SimpleHttpFetcher;
import com.yahoo.vespa.config.server.http.v2.PrepareResult;
import com.yahoo.vespa.config.server.provision.HostProvisionerProvider;
@@ -46,6 +49,8 @@ import com.yahoo.vespa.config.server.tenant.Tenant;
import com.yahoo.vespa.config.server.tenant.Tenants;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
import java.net.URI;
import java.time.Clock;
import java.time.Duration;
@@ -360,6 +365,23 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
return result;
}
+ public PrepareResult createSessionAndPrepareAndActivate(Tenant tenant, InputStream in, String contentType, TimeoutBudget timeoutBudget,
+ String name, PrepareParams prepareParams,
+ boolean ignoreLockFailure, boolean ignoreSessionStaleFailure,
+ Instant now) {
+ long sessionId = createSession(tenant, timeoutBudget, in, contentType, name);
+ return prepareAndActivate(tenant, sessionId, prepareParams, ignoreLockFailure, ignoreSessionStaleFailure, now);
+ }
+
+ private File decompressApplication(InputStream in, String contentType, File tempDir) {
+ try (CompressedApplicationInputStream application =
+ CompressedApplicationInputStream.createFromCompressedStream(in, contentType)) {
+ return application.decompress(tempDir);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Unable to decompress data in body", e);
+ }
+ }
+
private List<ApplicationId> listApplicationIds(Tenant tenant) {
TenantApplications applicationRepo = tenant.getApplicationRepo();
return applicationRepo.listApplications();
@@ -375,6 +397,13 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
return session.getSessionId();
}
+ public long createSession(Tenant tenant, TimeoutBudget timeoutBudget, InputStream in, String contentType, String applicationName) {
+ File tempDir = Files.createTempDir();
+ long sessionId = createSession(tenant, timeoutBudget, decompressApplication(in, contentType, tempDir), applicationName);
+ cleanupApplicationDirectory(tempDir, logger);
+ return sessionId;
+ }
+
public long createSession(Tenant tenant, TimeoutBudget timeoutBudget, File applicationDirectory, String applicationName) {
LocalSessionRepo localSessionRepo = tenant.getLocalSessionRepo();
SessionFactory sessionFactory = tenant.getSessionFactory();
@@ -391,6 +420,13 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
deploymentExecutor.awaitTermination(365, TimeUnit.DAYS); // Timeout should never happen
}
+ private static void cleanupApplicationDirectory(File tempDir, DeployLogger logger) {
+ logger.log(LogLevel.DEBUG, "Deleting tmp dir '" + tempDir + "'");
+ if (!IOUtils.recursiveDeleteDir(tempDir)) {
+ logger.log(LogLevel.WARNING, "Not able to delete tmp dir '" + tempDir + "'");
+ }
+ }
+
private void redeployApplication(ApplicationId applicationId, Deployer deployer, ExecutorService deploymentExecutor) {
log.log(LogLevel.DEBUG, () -> "Redeploying " + applicationId);
deployer.deployFromLocalActive(applicationId)
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStream.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStream.java
index 7cbd5b8a15a..548d2f0a43c 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStream.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStream.java
@@ -4,7 +4,7 @@ package com.yahoo.vespa.config.server.http;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import com.yahoo.log.LogLevel;
-import com.yahoo.vespa.config.server.http.v2.SessionCreateHandler;
+import com.yahoo.vespa.config.server.http.v2.ApplicationApiHandler;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
@@ -48,10 +48,10 @@ public class CompressedApplicationInputStream implements AutoCloseable {
private static ArchiveInputStream getArchiveInputStream(InputStream is, String contentTypeHeader) throws IOException {
ArchiveInputStream ais;
switch (contentTypeHeader) {
- case SessionCreateHandler.APPLICATION_X_GZIP:
+ case ApplicationApiHandler.APPLICATION_X_GZIP:
ais = new TarArchiveInputStream(new GZIPInputStream(is));
break;
- case SessionCreateHandler.APPLICATION_ZIP:
+ case ApplicationApiHandler.APPLICATION_ZIP:
ais = new ZipArchiveInputStream(is);
break;
default:
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandler.java
index b0c251f477c..eb81ce15b3a 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandler.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandler.java
@@ -1,7 +1,6 @@
// Copyright 2017 Yahoo Holdings. 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.io.Files;
import com.google.inject.Inject;
import com.yahoo.cloud.config.ConfigserverConfig;
import com.yahoo.config.application.api.DeployLogger;
@@ -9,15 +8,11 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.TenantName;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.container.logging.AccessLog;
-import com.yahoo.io.IOUtils;
import com.yahoo.jdisc.application.UriPattern;
import com.yahoo.log.LogLevel;
import com.yahoo.slime.Slime;
import com.yahoo.vespa.config.server.ApplicationRepository;
import com.yahoo.vespa.config.server.deploy.DeployHandlerLogger;
-import com.yahoo.vespa.config.server.http.CompressedApplicationInputStream;
-import com.yahoo.vespa.config.server.http.InternalServerException;
import com.yahoo.vespa.config.server.tenant.Tenant;
import com.yahoo.vespa.config.server.tenant.Tenants;
import com.yahoo.vespa.config.server.TimeoutBudget;
@@ -25,11 +20,8 @@ import com.yahoo.vespa.config.server.http.BadRequestException;
import com.yahoo.vespa.config.server.http.SessionHandler;
import com.yahoo.vespa.config.server.http.Utils;
-import java.io.File;
-import java.io.IOException;
import java.net.URI;
import java.time.Duration;
-import java.util.concurrent.Executor;
/**
* A handler that is able to create a session from an application package,
@@ -37,12 +29,9 @@ import java.util.concurrent.Executor;
* Handles /application/v2/ requests
*
* @author hmusum
- * @since 5.1
*/
public class SessionCreateHandler extends SessionHandler {
- public final static String APPLICATION_X_GZIP = "application/x-gzip";
- public final static String APPLICATION_ZIP = "application/zip";
- public final static String contentTypeHeader = "Content-Type";
+
private static final String fromPattern = "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*";
private final Tenants tenants;
@@ -72,11 +61,8 @@ public class SessionCreateHandler extends SessionHandler {
sessionId = applicationRepository.createSessionFromExisting(tenant, logger, timeoutBudget, applicationId);
} else {
validateDataAndHeader(request);
- File tempDir = Files.createTempDir();
- File applicationDirectory = decompressApplication(request, tempDir);
String name = getNameProperty(request, logger);
- sessionId = applicationRepository.createSession(tenant, timeoutBudget, applicationDirectory, name);
- cleanupApplicationDirectory(tempDir, logger);
+ sessionId = applicationRepository.createSession(tenant, timeoutBudget, request.getData(), request.getHeader(ApplicationApiHandler.contentTypeHeader), name);
}
return createResponse(request, tenantName, deployLog, sessionId);
}
@@ -100,12 +86,12 @@ public class SessionCreateHandler extends SessionHandler {
.instanceName(match.group(6)).build();
}
- private DeployHandlerLogger createLogger(HttpRequest request, Slime deployLog, TenantName tenant) {
+ static DeployHandlerLogger createLogger(HttpRequest request, Slime deployLog, TenantName tenant) {
return SessionHandler.createLogger(deployLog, request,
new ApplicationId.Builder().tenant(tenant).applicationName("-").build());
}
- private String getNameProperty(HttpRequest request, DeployLogger logger) {
+ static String getNameProperty(HttpRequest request, DeployLogger logger) {
String name = request.getProperty("name");
// TODO: Do we need validation of this parameter?
if (name == null) {
@@ -115,32 +101,16 @@ public class SessionCreateHandler extends SessionHandler {
return name;
}
- private File decompressApplication(HttpRequest request, File tempDir) {
- try (CompressedApplicationInputStream application = CompressedApplicationInputStream.createFromCompressedStream(request.getData(), request
- .getHeader(contentTypeHeader))) {
- return application.decompress(tempDir);
- } catch (IOException e) {
- throw new InternalServerException("Unable to decompress data in body", e);
- }
- }
-
- private void cleanupApplicationDirectory(File tempDir, DeployLogger logger) {
- logger.log(LogLevel.DEBUG, "Deleting tmp dir '" + tempDir + "'");
- if (!IOUtils.recursiveDeleteDir(tempDir)) {
- logger.log(LogLevel.WARNING, "Not able to delete tmp dir '" + tempDir + "'");
- }
- }
-
- private static void validateDataAndHeader(HttpRequest request) {
+ static void validateDataAndHeader(HttpRequest request) {
if (request.getData() == null) {
throw new BadRequestException("Request contains no data");
}
- String header = request.getHeader(contentTypeHeader);
+ String header = request.getHeader(ApplicationApiHandler.contentTypeHeader);
if (header == null) {
- throw new BadRequestException("Request contains no " + contentTypeHeader + " header");
- } else if (!(header.equals(APPLICATION_X_GZIP) || header.equals(APPLICATION_ZIP))) {
- throw new BadRequestException("Request contains invalid " + contentTypeHeader + " header, only '" +
- APPLICATION_X_GZIP + "' and '" + APPLICATION_ZIP + "' are supported");
+ throw new BadRequestException("Request contains no " + ApplicationApiHandler.contentTypeHeader + " header");
+ } else if (!(header.equals(ApplicationApiHandler.APPLICATION_X_GZIP) || header.equals(ApplicationApiHandler.APPLICATION_ZIP))) {
+ throw new BadRequestException("Request contains invalid " + ApplicationApiHandler.contentTypeHeader + " header, only '" +
+ ApplicationApiHandler.APPLICATION_X_GZIP + "' and '" + ApplicationApiHandler.APPLICATION_ZIP + "' are supported");
}
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareAndActivateHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareAndActivateHandler.java
deleted file mode 100644
index dc88a6ddddc..00000000000
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareAndActivateHandler.java
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2018 Yahoo Holdings. 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.inject.Inject;
-import com.yahoo.cloud.config.ConfigserverConfig;
-import com.yahoo.config.provision.TenantName;
-import com.yahoo.config.provision.Zone;
-import com.yahoo.container.jdisc.HttpRequest;
-import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.vespa.config.server.ApplicationRepository;
-import com.yahoo.vespa.config.server.http.SessionHandler;
-import com.yahoo.vespa.config.server.http.Utils;
-import com.yahoo.vespa.config.server.session.PrepareParams;
-import com.yahoo.vespa.config.server.tenant.Tenant;
-import com.yahoo.vespa.config.server.tenant.Tenants;
-
-import java.time.Duration;
-import java.time.Instant;
-
-/**
- * A handler that prepares and activates a session/application given by a session id in the request.
- *
- * @author hmusum
- */
-public class SessionPrepareAndActivateHandler extends SessionHandler {
-
- private final Tenants tenants;
- private final Duration zookeeperBarrierTimeout;
- private final Zone zone;
-
- @Inject
- public SessionPrepareAndActivateHandler(Context ctx,
- ApplicationRepository applicationRepository,
- Tenants tenants,
- ConfigserverConfig configserverConfig,
- Zone zone) {
- super(ctx, applicationRepository);
- this.tenants = tenants;
- this.zookeeperBarrierTimeout = Duration.ofSeconds(configserverConfig.zookeeper().barrierTimeout());
- this.zone = zone;
- }
-
- @Override
- protected HttpResponse handlePUT(HttpRequest request) {
- Tenant tenant = getExistingTenant(request);
- TenantName tenantName = tenant.getName();
- long sessionId = getSessionIdV2(request);
- PrepareParams prepareParams = PrepareParams.fromHttpRequest(request, tenantName, zookeeperBarrierTimeout);
-
- PrepareResult result = applicationRepository.prepareAndActivate(tenant, sessionId, prepareParams,
- shouldIgnoreLockFailure(request),
- shouldIgnoreSessionStaleFailure(request),
- Instant.now());
- return new SessionPrepareAndActivateResponse(result, tenantName, request, prepareParams.getApplicationId(), zone);
- }
-
- @Override
- public Duration getTimeout() {
- return zookeeperBarrierTimeout.plus(Duration.ofSeconds(10));
- }
-
- private Tenant getExistingTenant(HttpRequest request) {
- TenantName tenantName = Utils.getTenantNameFromSessionRequest(request);
- Utils.checkThatTenantExists(tenants, tenantName);
- return tenants.getTenant(tenantName);
- }
-
-}
diff --git a/configserver/src/main/resources/configserver-app/services.xml b/configserver/src/main/resources/configserver-app/services.xml
index bf38eedc97f..b3f0a58ea90 100644
--- a/configserver/src/main/resources/configserver-app/services.xml
+++ b/configserver/src/main/resources/configserver-app/services.xml
@@ -106,7 +106,7 @@
<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.SessionPrepareAndActivateHandler' bundle='configserver'>
+ <handler id='com.yahoo.vespa.config.server.http.v2.ApplicationApiHandler' bundle='configserver'>
<binding>http://*/application/v2/tenant/*/session/*/prepareandactivate</binding>
<binding>https://*/application/v2/tenant/*/session/*/prepareandactivate</binding>
</handler>
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 52c711e3157..ecc3a8a0a54 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
@@ -4,7 +4,9 @@ package com.yahoo.vespa.config.server;
import com.yahoo.config.model.application.provider.FilesApplicationPackage;
import com.yahoo.config.provision.Provisioner;
import com.yahoo.config.provision.TenantName;
+import com.yahoo.vespa.config.server.http.CompressedApplicationInputStreamTest;
import com.yahoo.vespa.config.server.http.SessionHandlerTest;
+import com.yahoo.vespa.config.server.http.v2.ApplicationApiHandler;
import com.yahoo.vespa.config.server.http.v2.PrepareResult;
import com.yahoo.vespa.config.server.session.PrepareParams;
import com.yahoo.vespa.config.server.tenant.Tenant;
@@ -15,6 +17,7 @@ import org.junit.Before;
import org.junit.Test;
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.time.Clock;
import java.time.Duration;
@@ -65,12 +68,27 @@ public class ApplicationRepositoryTest {
assertFalse(result.configChangeActions().getRestartActions().isEmpty());
}
+ @Test
+ public void createAndPrepareAndActivate() throws IOException {
+ PrepareResult result = createAndPrepareAndActivateApp();
+ assertTrue(result.configChangeActions().getRefeedActions().isEmpty());
+ assertTrue(result.configChangeActions().getRestartActions().isEmpty());
+ }
+
private PrepareResult prepareAndActivateApp(File application) throws IOException {
FilesApplicationPackage appDir = FilesApplicationPackage.fromFile(application);
long sessionId = applicationRepository.createSession(tenant, timeoutBudget, appDir.getAppDir(), "testapp");
return applicationRepository.prepareAndActivate(tenant, sessionId, prepareParams(), false, false, Instant.now());
}
+ private PrepareResult createAndPrepareAndActivateApp() throws IOException {
+ File file = CompressedApplicationInputStreamTest.createTarFile();
+ return applicationRepository.createSessionAndPrepareAndActivate(tenant, new FileInputStream(file),
+ ApplicationApiHandler.APPLICATION_X_GZIP,
+ timeoutBudget, "testapp", prepareParams(),
+ false, false, Instant.now());
+ }
+
private PrepareParams prepareParams() {
return new PrepareParams.Builder().build();
}
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 fc9264a6ef5..d5d76ebe549 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
@@ -7,7 +7,6 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.TenantName;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.container.logging.AccessLog;
import com.yahoo.vespa.config.server.ApplicationRepository;
import com.yahoo.vespa.config.server.application.MemoryTenantApplications;
import com.yahoo.vespa.config.server.application.TenantApplications;
@@ -61,7 +60,7 @@ public class SessionCreateHandlerTest extends SessionHandlerTest {
private TenantApplications applicationRepo;
static {
- postHeaders.put(SessionCreateHandler.contentTypeHeader, SessionCreateHandler.APPLICATION_X_GZIP);
+ postHeaders.put(ApplicationApiHandler.contentTypeHeader, ApplicationApiHandler.APPLICATION_X_GZIP);
}
@Before
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionFactoryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionFactoryTest.java
index 4ce34c11a22..7434bf411dd 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionFactoryTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionFactoryTest.java
@@ -10,7 +10,7 @@ import com.yahoo.vespa.config.server.*;
import com.yahoo.vespa.config.server.http.CompressedApplicationInputStream;
import com.yahoo.vespa.config.server.http.CompressedApplicationInputStreamTest;
-import com.yahoo.vespa.config.server.http.v2.SessionCreateHandler;
+import com.yahoo.vespa.config.server.http.v2.ApplicationApiHandler;
import com.yahoo.vespa.config.server.tenant.TestWithTenant;
import org.json.JSONException;
import org.json.JSONObject;
@@ -77,7 +77,7 @@ public class SessionFactoryTest extends TestWithTenant {
private LocalSession getLocalSession(String appName) throws IOException {
CompressedApplicationInputStream app = CompressedApplicationInputStream.createFromCompressedStream(
- new FileInputStream(CompressedApplicationInputStreamTest.createTarFile()), SessionCreateHandler.APPLICATION_X_GZIP);
+ new FileInputStream(CompressedApplicationInputStreamTest.createTarFile()), ApplicationApiHandler.APPLICATION_X_GZIP);
return factory.createSession(app.decompress(Files.createTempDir()), appName, TimeoutBudgetTest.day());
}
}