summaryrefslogtreecommitdiffstats
path: root/configserver
diff options
context:
space:
mode:
authorMorten Tokle <mortent@verizonmedia.com>2021-05-19 22:38:55 +0200
committerMorten Tokle <mortent@verizonmedia.com>2021-05-20 09:49:02 +0200
commit0a8b5307acfdd5063412b41a1d7aa4297223ce4e (patch)
treef1ea43aaff290c452846fb145fd0ee81b62d5ee9 /configserver
parentfc0711f7870b55ea77d18d87ec3e70b75e0de2e0 (diff)
Support http multipart on prepareandactivate
Diffstat (limited to 'configserver')
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionHandler.java6
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationApiHandler.java44
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandler.java12
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java68
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializer.java3
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java113
6 files changed, 232 insertions, 14 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionHandler.java
index fcac023eec3..540a6545383 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionHandler.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/SessionHandler.java
@@ -61,7 +61,11 @@ public class SessionHandler extends HttpHandler {
}
public static TimeoutBudget getTimeoutBudget(HttpRequest request, Duration defaultTimeout) {
- return new TimeoutBudget(Clock.systemUTC(), getRequestTimeout(request, defaultTimeout));
+ return getTimeoutBudget(getRequestTimeout(request, defaultTimeout));
+ }
+
+ public static TimeoutBudget getTimeoutBudget(Duration requestTimeout) {
+ return new TimeoutBudget(Clock.systemUTC(), requestTimeout);
}
/**
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationApiHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationApiHandler.java
index 9ea96b97af3..91c926d8a5c 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationApiHandler.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationApiHandler.java
@@ -8,14 +8,25 @@ import com.yahoo.config.provision.Zone;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.container.jdisc.HttpResponse;
import com.yahoo.jdisc.application.BindingMatch;
+import com.yahoo.jdisc.http.HttpHeaders;
import com.yahoo.vespa.config.server.ApplicationRepository;
import com.yahoo.vespa.config.server.application.CompressedApplicationInputStream;
+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 com.yahoo.vespa.config.server.session.PrepareParams;
import com.yahoo.vespa.config.server.tenant.TenantRepository;
+import org.eclipse.jetty.http.MultiPartFormInputStream;
+import javax.servlet.http.Part;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.time.Duration;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.logging.Level;
+import java.util.stream.Collectors;
import static com.yahoo.vespa.config.server.application.CompressedApplicationInputStream.createFromCompressedStream;
import static com.yahoo.vespa.config.server.http.Utils.checkThatTenantExists;
@@ -32,6 +43,9 @@ public class ApplicationApiHandler extends SessionHandler {
public final static String APPLICATION_X_GZIP = "application/x-gzip";
public final static String APPLICATION_ZIP = "application/zip";
+ public final static String MULTIPART_FORM_DATA = "multipart/form-data";
+ public final static String MULTIPART_PARAMS = "prepareParams";
+ public final static String MULTIPART_APPLICATION_PACKAGE = "applicationPackage";
public final static String contentTypeHeader = "Content-Type";
private final TenantRepository tenantRepository;
private final Duration zookeeperBarrierTimeout;
@@ -50,10 +64,34 @@ public class ApplicationApiHandler extends SessionHandler {
@Override
protected HttpResponse handlePOST(HttpRequest request) {
- validateDataAndHeader(request);
+ validateDataAndHeader(request, List.of(APPLICATION_X_GZIP, APPLICATION_ZIP, MULTIPART_FORM_DATA));
TenantName tenantName = validateTenant(request);
- PrepareParams prepareParams = PrepareParams.fromHttpRequest(request, tenantName, zookeeperBarrierTimeout);
- CompressedApplicationInputStream compressedStream = createFromCompressedStream(request.getData(), request.getHeader(contentTypeHeader));
+
+ PrepareParams prepareParams;
+ CompressedApplicationInputStream compressedStream;
+ boolean multipartRequest = Optional.ofNullable(request.getHeader(HttpHeaders.Names.CONTENT_TYPE))
+ .map(val -> val.equalsIgnoreCase(MULTIPART_FORM_DATA))
+ .orElse(false);
+ if(multipartRequest) {
+ try {
+ MultiPartFormInputStream multiPartFormInputStream = new MultiPartFormInputStream(request.getData(), request.getHeader(CONTENT_TYPE), /* config */null, /* contextTmpDir */null);
+ Map<String, Part> parts = multiPartFormInputStream.getParts().stream()
+ .collect(Collectors.toMap(Part::getName, p -> p));
+
+ byte[] params = parts.get(MULTIPART_PARAMS).getInputStream().readAllBytes();
+ log.log(Level.FINE, "Deploy parameters: [{}]", new String(params, StandardCharsets.UTF_8));
+ prepareParams = PrepareParams.fromJson(parts.get(MULTIPART_PARAMS).getInputStream().readAllBytes(), tenantName, zookeeperBarrierTimeout);
+ Part appPackagePart = parts.get(MULTIPART_APPLICATION_PACKAGE);
+ compressedStream = createFromCompressedStream(appPackagePart.getInputStream(), appPackagePart.getContentType());
+ } catch (IOException e) {
+ log.log(Level.WARNING, "Unable to parse multipart in deploy", e);
+ throw new BadRequestException("Request contains invalid data");
+ }
+ } else {
+ prepareParams = PrepareParams.fromHttpRequest(request, tenantName, zookeeperBarrierTimeout);
+ compressedStream = createFromCompressedStream(request.getData(), request.getHeader(contentTypeHeader));
+ }
+
PrepareResult result = applicationRepository.deploy(compressedStream, prepareParams);
return new SessionPrepareAndActivateResponse(result, request, prepareParams.getApplicationId(), zone);
}
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 732bad80e00..a3e82c51dfa 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
@@ -19,6 +19,8 @@ import com.yahoo.vespa.config.server.http.Utils;
import java.net.URI;
import java.time.Duration;
+import java.util.List;
+import java.util.stream.Collectors;
/**
* A handler that is able to create a session from an application package,
@@ -55,7 +57,7 @@ public class SessionCreateHandler extends SessionHandler {
logger = DeployHandlerLogger.forApplication(applicationId, verbose);
sessionId = applicationRepository.createSessionFromExisting(applicationId, false, timeoutBudget);
} else {
- validateDataAndHeader(request);
+ validateDataAndHeader(request, List.of(ApplicationApiHandler.APPLICATION_ZIP, ApplicationApiHandler.APPLICATION_X_GZIP));
logger = DeployHandlerLogger.forTenant(tenantName, verbose);
// TODO: Avoid using application id here at all
ApplicationId applicationId = ApplicationId.from(tenantName, ApplicationName.defaultName(), InstanceName.defaultName());
@@ -84,16 +86,16 @@ public class SessionCreateHandler extends SessionHandler {
.instanceName(match.group(6)).build();
}
- static void validateDataAndHeader(HttpRequest request) {
+ static void validateDataAndHeader(HttpRequest request, List<String> supportedContentTypes) {
if (request.getData() == null) {
throw new BadRequestException("Request contains no data");
}
String header = request.getHeader(ApplicationApiHandler.contentTypeHeader);
if (header == null) {
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");
+ } else if (!supportedContentTypes.contains(header)) {
+ throw new BadRequestException("Request contains invalid " + ApplicationApiHandler.contentTypeHeader + " header, only '["
+ + String.join(", ", supportedContentTypes) + "' are supported");
}
}
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java
index 5a3e0311db9..c9f4b8164eb 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java
@@ -11,6 +11,8 @@ import com.yahoo.config.provision.AthenzDomain;
import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.TenantName;
import com.yahoo.container.jdisc.HttpRequest;
+import com.yahoo.slime.Inspector;
+import com.yahoo.slime.Slime;
import com.yahoo.slime.SlimeUtils;
import com.yahoo.vespa.config.server.TimeoutBudget;
import com.yahoo.config.model.api.TenantSecretStore;
@@ -21,9 +23,11 @@ import com.yahoo.vespa.config.server.tenant.TenantSecretStoreSerializer;
import java.time.Clock;
import java.time.Duration;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
+import java.util.function.Function;
/**
* Parameters for preparing an application. Immutable.
@@ -163,6 +167,16 @@ public final class PrepareParams {
return this;
}
+ public Builder containerEndpointList(List<ContainerEndpoint> endpoints) {
+ this.containerEndpoints = endpoints;
+ return this;
+ }
+
+ public Builder endpointCertificateMetadata(EndpointCertificateMetadata endpointCertificateMetadata) {
+ this.endpointCertificateMetadata = Optional.ofNullable(endpointCertificateMetadata);
+ return this;
+ }
+
public Builder endpointCertificateMetadata(String serialized) {
this.endpointCertificateMetadata = (serialized == null)
? Optional.empty()
@@ -197,6 +211,11 @@ public final class PrepareParams {
return this;
}
+ public Builder quota(Quota quota) {
+ this.quota = Optional.ofNullable(quota);
+ return this;
+ }
+
public Builder quota(String serialized) {
this.quota = (serialized == null)
? Optional.empty()
@@ -253,6 +272,53 @@ public final class PrepareParams {
.build();
}
+ public static PrepareParams fromJson(byte[] json, TenantName tenant, Duration barrierTimeout) {
+ Slime slime = SlimeUtils.jsonToSlime(json);
+ Inspector params = slime.get();
+
+ return new Builder().ignoreValidationErrors(params.field(IGNORE_VALIDATION_PARAM_NAME).asBool())
+ .dryRun(params.field(DRY_RUN_PARAM_NAME).asBool())
+ .verbose(params.field(VERBOSE_PARAM_NAME).asBool())
+ .timeoutBudget(SessionHandler.getTimeoutBudget(getTimeout(params, barrierTimeout)))
+ .applicationId(createApplicationId(params, tenant))
+ .vespaVersion(params.field(VESPA_VERSION_PARAM_NAME).asString())
+ .containerEndpointList(deserialize(params.field(CONTAINER_ENDPOINTS_PARAM_NAME), ContainerEndpointSerializer::endpointListFromSlime, Collections.emptyList()))
+ .endpointCertificateMetadata(deserialize(params.field(ENDPOINT_CERTIFICATE_METADATA_PARAM_NAME), EndpointCertificateMetadataSerializer::fromSlime))
+ .dockerImageRepository(SlimeUtils.optionalString(params.field(DOCKER_IMAGE_REPOSITORY)).orElse(null))
+ .athenzDomain(SlimeUtils.optionalString(params.field(ATHENZ_DOMAIN)).orElse(null))
+ .applicationRoles(ApplicationRoles.fromString(SlimeUtils.optionalString(params.field(APPLICATION_HOST_ROLE)).orElse(null), SlimeUtils.optionalString(params.field(APPLICATION_CONTAINER_ROLE)).orElse(null)))
+ .quota(deserialize(params.field(QUOTA_PARAM_NAME), Quota::fromSlime))
+ .tenantSecretStores(SlimeUtils.optionalString(params.field(TENANT_SECRET_STORES_PARAM_NAME)).orElse(null))
+ .force(params.field(FORCE_PARAM_NAME).asBool())
+ .waitForResourcesInPrepare(params.field(WAIT_FOR_RESOURCES_IN_PREPARE).asBool())
+ .build();
+ }
+
+ private static <T> T deserialize(Inspector field, Function<Inspector, T> mapper) {
+ return deserialize(field, mapper, null);
+ }
+ private static <T> T deserialize(Inspector field, Function<Inspector, T> mapper, T defaultValue) {
+ return field.valid()
+ ? mapper.apply(field)
+ : defaultValue;
+ }
+
+ private static Duration getTimeout(Inspector params, Duration defaultTimeout) {
+ if(params.field("timeout").valid()) {
+ return Duration.ofSeconds(params.field("timeout").asLong());
+ } else {
+ return defaultTimeout;
+ }
+ }
+
+ private static ApplicationId createApplicationId(Inspector params, TenantName tenant) {
+ return new ApplicationId.Builder()
+ .tenant(tenant)
+ .applicationName(SlimeUtils.optionalString(params.field(APPLICATION_NAME_PARAM_NAME)).orElse("default"))
+ .instanceName(SlimeUtils.optionalString(params.field(INSTANCE_PARAM_NAME)).orElse("default"))
+ .build();
+ }
+
private static ApplicationId createApplicationId(HttpRequest request, TenantName tenant) {
return new ApplicationId.Builder()
.tenant(tenant)
@@ -268,7 +334,7 @@ public final class PrepareParams {
private static Optional<String> getProperty(HttpRequest request, String propertyName) {
return Optional.ofNullable(request.getProperty(propertyName));
}
-
+
public String getApplicationName() {
return applicationId.application().value();
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializer.java
index 6ec0ba693f5..15fe04932dd 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializer.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializer.java
@@ -54,6 +54,9 @@ public class ContainerEndpointSerializer {
public static List<ContainerEndpoint> endpointListFromSlime(Slime slime) {
final var inspector = slime.get();
+ return endpointListFromSlime(inspector);
+ }
+ public static List<ContainerEndpoint> endpointListFromSlime(Inspector inspector) {
final var endpoints = new ArrayList<ContainerEndpoint>();
inspector.traverse((ArrayTraverser) (idx, endpointInspector) -> {
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java
index 941f2726b0e..04984f85a64 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java
@@ -3,16 +3,32 @@ package com.yahoo.vespa.config.server.session;
import com.yahoo.config.model.api.ApplicationRoles;
import com.yahoo.config.model.api.ContainerEndpoint;
+import com.yahoo.config.model.api.EndpointCertificateMetadata;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.TenantName;
import com.yahoo.container.jdisc.HttpRequest;
+import com.yahoo.slime.ArrayInserter;
+import com.yahoo.slime.Cursor;
+import com.yahoo.slime.Injector;
+import com.yahoo.slime.Inspector;
+import com.yahoo.slime.ObjectInserter;
+import com.yahoo.slime.ObjectSymbolInserter;
+import com.yahoo.slime.Slime;
+import com.yahoo.slime.SlimeInserter;
+import com.yahoo.slime.SlimeUtils;
+import com.yahoo.vespa.config.server.tenant.ContainerEndpointSerializer;
+import com.yahoo.vespa.config.server.tenant.EndpointCertificateMetadataSerializer;
import org.junit.Test;
+import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
+import java.util.stream.Collectors;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
@@ -26,13 +42,22 @@ import static org.junit.Assert.assertTrue;
public class PrepareParamsTest {
private static final String vespaVersion = "6.37.49";
- private static final String request = "http://foo:19071/application/v2/tenant/foo/application/bar?" +
+ private static final String baseRequest = "http://foo:19071/application/v2/tenant/foo/application/bar";
+ private static final String request = baseRequest + "?" +
PrepareParams.DRY_RUN_PARAM_NAME + "=true&" +
PrepareParams.VERBOSE_PARAM_NAME+ "=true&" +
PrepareParams.IGNORE_VALIDATION_PARAM_NAME + "=false&" +
PrepareParams.APPLICATION_NAME_PARAM_NAME + "=baz&" +
PrepareParams.VESPA_VERSION_PARAM_NAME + "=" + vespaVersion;
+ private static final String json = "{\n" +
+ "\"" + PrepareParams.DRY_RUN_PARAM_NAME + "\": true,\n" +
+ "\"" + PrepareParams.VERBOSE_PARAM_NAME+ "\": true,\n" +
+ "\"" + PrepareParams.IGNORE_VALIDATION_PARAM_NAME + "\": false,\n" +
+ "\"" + PrepareParams.APPLICATION_NAME_PARAM_NAME + "\":\"baz\",\n" +
+ "\"" + PrepareParams.VESPA_VERSION_PARAM_NAME + "\":\"" + vespaVersion + "\"\n" +
+ "}";
+
@Test
public void testCorrectParsing() {
PrepareParams prepareParams = createParams("http://foo:19071/application/v2/", TenantName.defaultName());
@@ -47,7 +72,7 @@ public class PrepareParamsTest {
}
@Test
- public void testCorrectParsingWithContainerEndpoints() {
+ public void testCorrectParsingWithContainerEndpoints() throws IOException {
var endpoints = List.of(new ContainerEndpoint("qrs1",
List.of("c1.example.com",
"c2.example.com")),
@@ -69,10 +94,16 @@ public class PrepareParamsTest {
var prepareParams = createParams(request + "&" + PrepareParams.CONTAINER_ENDPOINTS_PARAM_NAME +
"=" + encoded, TenantName.from("foo"));
assertEquals(endpoints, prepareParams.containerEndpoints());
+
+ // Verify using json object
+ var slime = SlimeUtils.jsonToSlime(json);
+ new Injector().inject(ContainerEndpointSerializer.endpointListToSlime(endpoints).get(), new ObjectInserter(slime.get(), PrepareParams.CONTAINER_ENDPOINTS_PARAM_NAME));
+ PrepareParams prepareParamsJson = PrepareParams.fromJson(SlimeUtils.toJsonBytes(slime), TenantName.from("foo"), Duration.ofSeconds(60));
+ assertPrepareParamsEqual(prepareParams, prepareParamsJson);
}
@Test
- public void testCorrectParsingWithApplicationRoles() {
+ public void testCorrectParsingWithApplicationRoles() throws IOException {
String req = request + "&" +
PrepareParams.APPLICATION_HOST_ROLE + "=hostRole&" +
PrepareParams.APPLICATION_CONTAINER_ROLE + "=containerRole";
@@ -82,15 +113,89 @@ public class PrepareParamsTest {
assertTrue(applicationRoles.isPresent());
assertEquals("hostRole", applicationRoles.get().applicationHostRole());
assertEquals("containerRole", applicationRoles.get().applicationContainerRole());
+
+ // Verify using json object
+ var slime = SlimeUtils.jsonToSlime(json);
+ var cursor = slime.get();
+ cursor.setString(PrepareParams.APPLICATION_HOST_ROLE, "hostRole");
+ cursor.setString(PrepareParams.APPLICATION_CONTAINER_ROLE, "containerRole");
+
+ PrepareParams prepareParamsJson = PrepareParams.fromJson(SlimeUtils.toJsonBytes(slime), TenantName.from("foo"), Duration.ofSeconds(60));
+ assertPrepareParamsEqual(prepareParams, prepareParamsJson);
}
@Test
- public void testQuotaParsing() {
+ public void testQuotaParsing() throws IOException {
var quotaParam = "{\"clusterSize\": 23, \"budget\": 23232323}";
var quotaEncoded = URLEncoder.encode(quotaParam, StandardCharsets.UTF_8);
var prepareParams = createParams(request + "&" + PrepareParams.QUOTA_PARAM_NAME + "=" + quotaEncoded, TenantName.from("foo"));
assertEquals(23, (int) prepareParams.quota().get().maxClusterSize().get());
assertEquals(23232323, (int) prepareParams.quota().get().budget().get());
+
+ // Verify using json object
+ var slime = SlimeUtils.jsonToSlime(json);
+ new Injector().inject(SlimeUtils.jsonToSlime(quotaParam).get(), new ObjectInserter(slime.get(), PrepareParams.QUOTA_PARAM_NAME));
+ PrepareParams prepareParamsJson = PrepareParams.fromJson(SlimeUtils.toJsonBytes(slime), TenantName.from("foo"), Duration.ofSeconds(60));
+ assertPrepareParamsEqual(prepareParams, prepareParamsJson);
+ }
+
+ @Test
+ public void testEndpointCertificateParsing() throws IOException {
+ var certMeta = new EndpointCertificateMetadata("key", "cert", 3);
+ var slime = new Slime();
+ EndpointCertificateMetadataSerializer.toSlime(certMeta, slime.setObject());
+ String encoded = URLEncoder.encode(new String(SlimeUtils.toJsonBytes(slime), StandardCharsets.UTF_8), StandardCharsets.UTF_8);
+ var prepareParams = createParams(request + "&" + PrepareParams.ENDPOINT_CERTIFICATE_METADATA_PARAM_NAME + "=" + encoded, TenantName.from("foo"));
+ assertTrue(prepareParams.endpointCertificateMetadata().isPresent());
+ assertEquals("key", prepareParams.endpointCertificateMetadata().get().keyName());
+ assertEquals("cert", prepareParams.endpointCertificateMetadata().get().certName());
+ assertEquals(3, prepareParams.endpointCertificateMetadata().get().version());
+
+ // Verify using json object
+ var root = SlimeUtils.jsonToSlime(json);
+ new Injector().inject(slime.get(), new ObjectInserter(root.get(), PrepareParams.ENDPOINT_CERTIFICATE_METADATA_PARAM_NAME));
+ PrepareParams prepareParamsJson = PrepareParams.fromJson(SlimeUtils.toJsonBytes(root), TenantName.from("foo"), Duration.ofSeconds(60));
+ assertPrepareParamsEqual(prepareParams, prepareParamsJson);
+ }
+
+ @Test
+ public void compareEmptyUrlparamsVsJson() {
+ TenantName tenantName = TenantName.from("foo");
+ Duration barrierTimeout = Duration.ofSeconds(60);
+ HttpRequest httpRequest = HttpRequest.createTestRequest(baseRequest, com.yahoo.jdisc.http.HttpRequest.Method.POST);
+ PrepareParams urlPrepareParams = PrepareParams.fromHttpRequest(httpRequest, tenantName, barrierTimeout);
+ PrepareParams jsonPrepareParams = PrepareParams.fromJson(new byte[0], tenantName, barrierTimeout);
+
+ assertPrepareParamsEqual(urlPrepareParams, jsonPrepareParams);
+ }
+
+ @Test
+ public void compareStandardUrlparamsVsJson() {
+ TenantName tenantName = TenantName.from("foo");
+ Duration barrierTimeout = Duration.ofSeconds(60);
+ HttpRequest httpRequest = HttpRequest.createTestRequest(request, com.yahoo.jdisc.http.HttpRequest.Method.POST);
+ PrepareParams urlPrepareParams = PrepareParams.fromHttpRequest(httpRequest, tenantName, barrierTimeout);
+ PrepareParams jsonPrepareParams = PrepareParams.fromJson(json.getBytes(StandardCharsets.UTF_8), tenantName, barrierTimeout);
+ assertPrepareParamsEqual(urlPrepareParams, jsonPrepareParams);
+ }
+
+ private void assertPrepareParamsEqual(PrepareParams urlParams, PrepareParams jsonParams) {
+ assertEquals(urlParams.ignoreValidationErrors(), jsonParams.ignoreValidationErrors());
+ assertEquals(urlParams.isDryRun(), jsonParams.isDryRun());
+ assertEquals(urlParams.isVerbose(), jsonParams.isVerbose());
+ assertEquals(urlParams.isBootstrap(), jsonParams.isBootstrap());
+ assertEquals(urlParams.force(), jsonParams.force());
+ assertEquals(urlParams.waitForResourcesInPrepare(), jsonParams.waitForResourcesInPrepare());
+ assertEquals(urlParams.getApplicationId(), jsonParams.getApplicationId());
+ assertEquals(urlParams.getTimeoutBudget().timeout(), jsonParams.getTimeoutBudget().timeout());
+ assertEquals(urlParams.vespaVersion(), jsonParams.vespaVersion());
+ assertEquals(urlParams.containerEndpoints(), jsonParams.containerEndpoints());
+ assertEquals(urlParams.endpointCertificateMetadata(), jsonParams.endpointCertificateMetadata());
+ assertEquals(urlParams.dockerImageRepository(), jsonParams.dockerImageRepository());
+ assertEquals(urlParams.athenzDomain(), jsonParams.athenzDomain());
+ assertEquals(urlParams.applicationRoles(), jsonParams.applicationRoles());
+ assertEquals(urlParams.quota(), jsonParams.quota());
+ assertEquals(urlParams.tenantSecretStores(), jsonParams.tenantSecretStores());
}
// Create PrepareParams from a request (based on uri and tenant name)