diff options
Diffstat (limited to 'configserver/src/main/java/com/yahoo')
37 files changed, 314 insertions, 424 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 2d5940ebba2..6249e3bfff8 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 @@ -56,9 +56,9 @@ import com.yahoo.vespa.config.server.http.LogRetriever; import com.yahoo.vespa.config.server.http.SecretStoreValidator; import com.yahoo.vespa.config.server.http.SimpleHttpFetcher; import com.yahoo.vespa.config.server.http.TesterClient; -import com.yahoo.vespa.config.server.http.v2.DeploymentMetricsResponse; +import com.yahoo.vespa.config.server.http.v2.response.DeploymentMetricsResponse; import com.yahoo.vespa.config.server.http.v2.PrepareResult; -import com.yahoo.vespa.config.server.http.v2.ProtonMetricsResponse; +import com.yahoo.vespa.config.server.http.v2.response.ProtonMetricsResponse; import com.yahoo.vespa.config.server.metrics.DeploymentMetricsRetriever; import com.yahoo.vespa.config.server.metrics.ProtonMetricsRetriever; import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpConfigRequest.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpConfigRequest.java index ff70ce1e1b2..cdbd7378151 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpConfigRequest.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpConfigRequest.java @@ -18,8 +18,8 @@ import com.yahoo.vespa.config.protocol.DefContent; import com.yahoo.vespa.config.protocol.VespaVersion; import com.yahoo.vespa.config.server.RequestHandler; import com.yahoo.config.provision.ApplicationId; -import com.yahoo.vespa.config.server.http.v2.HttpConfigRequests; -import com.yahoo.vespa.config.server.http.v2.TenantRequest; +import com.yahoo.vespa.config.server.http.v2.request.HttpConfigRequests; +import com.yahoo.vespa.config.server.http.v2.request.TenantRequest; import com.yahoo.vespa.config.util.ConfigUtils; /** 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 dfbce72d4ba..7e8940d28b3 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 @@ -14,9 +14,9 @@ import com.yahoo.vespa.config.server.application.CompressedApplicationInputStrea 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.http.v2.response.SessionPrepareAndActivateResponse; import com.yahoo.vespa.config.server.session.PrepareParams; import com.yahoo.vespa.config.server.tenant.TenantRepository; -import com.yahoo.vespa.model.content.Content; import org.apache.hc.core5.http.ContentType; import org.eclipse.jetty.http.MultiPartFormInputStream; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java index 3634a6825a3..e56fb0b1bcc 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java @@ -6,47 +6,42 @@ import com.yahoo.component.Version; import com.yahoo.config.application.api.ApplicationFile; import com.yahoo.config.model.api.Model; import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.HostFilter; -import com.yahoo.config.provision.TenantName; +import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.Zone; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.io.IOUtils; import com.yahoo.jdisc.Response; -import com.yahoo.jdisc.application.BindingMatch; -import com.yahoo.jdisc.application.UriPattern; -import com.yahoo.slime.Cursor; +import com.yahoo.restapi.ErrorResponse; +import com.yahoo.restapi.MessageResponse; +import com.yahoo.restapi.Path; import com.yahoo.slime.SlimeUtils; import com.yahoo.text.StringUtilities; import com.yahoo.vespa.config.server.ApplicationRepository; -import com.yahoo.vespa.config.server.application.ApplicationReindexing; -import com.yahoo.vespa.config.server.application.ClusterReindexing; import com.yahoo.vespa.config.server.http.ContentHandler; import com.yahoo.vespa.config.server.http.ContentRequest; -import com.yahoo.vespa.config.server.http.HttpErrorResponse; import com.yahoo.vespa.config.server.http.HttpHandler; -import com.yahoo.vespa.config.server.http.JSONResponse; import com.yahoo.vespa.config.server.http.NotFoundException; +import com.yahoo.vespa.config.server.http.v2.request.ApplicationContentRequest; +import com.yahoo.vespa.config.server.http.v2.response.ApplicationSuspendedResponse; +import com.yahoo.vespa.config.server.http.v2.response.DeleteApplicationResponse; +import com.yahoo.vespa.config.server.http.v2.response.GetApplicationResponse; +import com.yahoo.vespa.config.server.http.v2.response.QuotaUsageResponse; +import com.yahoo.vespa.config.server.http.v2.response.ReindexingResponse; import com.yahoo.vespa.config.server.tenant.Tenant; import java.io.IOException; -import java.net.URLDecoder; import java.time.Duration; import java.time.Instant; -import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.StringJoiner; import java.util.TreeMap; import java.util.TreeSet; -import java.util.stream.Stream; import static com.yahoo.yolean.Exceptions.uncheck; -import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.stream.Collectors.toList; /** * Operations on applications (delete, wait for config convergence, restart, application content etc.) @@ -55,28 +50,6 @@ import static java.util.stream.Collectors.toList; */ public class ApplicationHandler extends HttpHandler { - private static final List<UriPattern> URI_PATTERNS = Stream.of( - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/content/*", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/filedistributionstatus", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/restart", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/reindex", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/reindexing", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/suspended", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/serviceconverge", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/serviceconverge/*", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/clustercontroller/*/status/*", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/metrics/*", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/metrics/*", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/logs", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/validate-secret-store", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/tester/*/*", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/tester/*", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*/quota", - "http://*/application/v2/tenant/*/application/*/environment/*/region/*/instance/*", - "http://*/application/v2/tenant/*/application/*") - .map(UriPattern::new) - .collect(toList()); - private final Zone zone; private final ApplicationRepository applicationRepository; @@ -90,152 +63,135 @@ public class ApplicationHandler extends HttpHandler { } @Override - public HttpResponse handleDELETE(HttpRequest request) { - ApplicationId applicationId = getApplicationIdFromRequest(request); - - if (isReindexingRequest(request)) { - applicationRepository.modifyReindexing(applicationId, reindexing -> reindexing.enabled(false)); - return createMessageResponse("Reindexing disabled"); - } + public HttpResponse handleGET(HttpRequest request) { + Path path = new Path(request.getUri()); + + if (path.matches("/application/v2/tenant/{tenant}/application/{application}")) return getApplicationResponse(ApplicationId.from(path.get("tenant"), path.get("application"), InstanceName.defaultName().value())); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}")) return getApplicationResponse(applicationId(path)); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/clustercontroller/{hostname}/status/{*}")) return clusterControllerStatusPage(applicationId(path), path.get("hostname"), path.getRest()); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/content/{*}")) return content(applicationId(path), path.getRest(), request); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/filedistributionstatus")) return filedistributionStatus(applicationId(path), request); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/logs")) return logs(applicationId(path), request); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/metrics/deployment")) return deploymentMetrics(applicationId(path)); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/metrics/proton")) return protonMetrics(applicationId(path)); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/reindexing")) return getReindexingStatus(applicationId(path)); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/serviceconverge")) return listServiceConverge(applicationId(path), request); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/serviceconverge/{hostAndPort}")) return checkServiceConverge(applicationId(path), path.get("hostAndPort"), request); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/suspended")) return isSuspended(applicationId(path)); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/tester/{command}")) return testerRequest(applicationId(path), path.get("command"), request); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/quota")) return quotaUsage(applicationId(path)); + return ErrorResponse.notFoundError("Nothing at " + path); + } - if (applicationRepository.delete(applicationId)) - return new DeleteApplicationResponse(Response.Status.OK, applicationId); + @Override + public HttpResponse handlePOST(HttpRequest request) { + Path path = new Path(request.getUri()); - return HttpErrorResponse.notFoundError("Unable to delete " + applicationId.toFullString() + ": Not found"); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/reindex")) return triggerReindexing(applicationId(path), request); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/reindexing")) return enableReindexing(applicationId(path)); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/restart")) return restart(applicationId(path), request); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/tester/run/{suite}")) return testerStartTests(applicationId(path), path.get("suite"), request); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/validate-secret-store")) return validateSecretStore(applicationId(path), request); + return ErrorResponse.notFoundError("Nothing at " + path); } @Override - public HttpResponse handleGET(HttpRequest request) { - ApplicationId applicationId = getApplicationIdFromRequest(request); - Duration timeout = HttpHandler.getRequestTimeout(request, Duration.ofSeconds(5)); - - if (isServiceConvergeRequest(request)) { - // Expects both hostname and port in the request (hostname:port) - String hostAndPort = getHostNameFromRequest(request); - return applicationRepository.checkServiceForConfigConvergence(applicationId, hostAndPort, request.getUri(), - timeout, getVespaVersionFromRequest(request)); - } + public HttpResponse handleDELETE(HttpRequest request) { + Path path = new Path(request.getUri()); - if (isClusterControllerStatusRequest(request)) { - String hostName = getHostNameFromRequest(request); - String pathSuffix = URLDecoder.decode(getPathSuffix(request), UTF_8); - return applicationRepository.clusterControllerStatusPage(applicationId, hostName, pathSuffix); - } + if (path.matches("/application/v2/tenant/{tenant}/application/{application}")) return deleteApplication(ApplicationId.from(path.get("tenant"), path.get("application"), InstanceName.defaultName().value())); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}")) return deleteApplication(applicationId(path)); + if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/reindexing")) return disableReindexing(applicationId(path)); + return ErrorResponse.notFoundError("Nothing at " + path); + } - if (isReindexingRequest(request)) { - return getReindexingStatus(applicationId); - } + private HttpResponse listServiceConverge(ApplicationId applicationId, HttpRequest request) { + return applicationRepository.servicesToCheckForConfigConvergence(applicationId, request.getUri(), + getTimeoutFromRequest(request), getVespaVersionFromRequest(request)); + } - if (isContentRequest(request)) { - long sessionId = applicationRepository.getSessionIdForApplication(applicationId); - String contentPath = getBindingMatch(request).group(7); - ApplicationFile applicationFile = - applicationRepository.getApplicationFileFromSession(applicationId.tenant(), - sessionId, - contentPath, - ContentRequest.getApplicationFileMode(request.getMethod())); - ApplicationContentRequest contentRequest = new ApplicationContentRequest(request, - sessionId, - applicationId, - zone, - contentPath, - applicationFile); - return new ContentHandler().get(contentRequest); - } + private HttpResponse checkServiceConverge(ApplicationId applicationId, String hostAndPort, HttpRequest request) { + return applicationRepository.checkServiceForConfigConvergence(applicationId, hostAndPort, request.getUri(), + getTimeoutFromRequest(request), getVespaVersionFromRequest(request)); + } - if (isServiceConvergeListRequest(request)) { - return applicationRepository.servicesToCheckForConfigConvergence(applicationId, request.getUri(), timeout, - getVespaVersionFromRequest(request)); - } + private HttpResponse clusterControllerStatusPage(ApplicationId applicationId, String hostname, String pathSuffix) { + return applicationRepository.clusterControllerStatusPage(applicationId, hostname, pathSuffix); + } - if (isFiledistributionStatusRequest(request)) { - return applicationRepository.filedistributionStatus(applicationId, timeout); - } + private HttpResponse content(ApplicationId applicationId, String contentPath, HttpRequest request) { + long sessionId = applicationRepository.getSessionIdForApplication(applicationId); + ApplicationFile applicationFile = + applicationRepository.getApplicationFileFromSession(applicationId.tenant(), + sessionId, + contentPath, + ContentRequest.getApplicationFileMode(request.getMethod())); + ApplicationContentRequest contentRequest = new ApplicationContentRequest(request, + sessionId, + applicationId, + zone, + contentPath, + applicationFile); + return new ContentHandler().get(contentRequest); + } - if (isLogRequest(request)) { - Optional<String> hostname = Optional.ofNullable(request.getProperty("hostname")); - String apiParams = Optional.ofNullable(request.getUri().getQuery()).map(q -> "?" + q).orElse(""); - return applicationRepository.getLogs(applicationId, hostname, apiParams); - } + private HttpResponse filedistributionStatus(ApplicationId applicationId, HttpRequest request) { + return applicationRepository.filedistributionStatus(applicationId, getTimeoutFromRequest(request)); + } - if (isProtonMetricsRequest(request)) { - return applicationRepository.getProtonMetrics(applicationId); - } + private HttpResponse logs(ApplicationId applicationId, HttpRequest request) { + Optional<String> hostname = Optional.ofNullable(request.getProperty("hostname")); + String apiParams = Optional.ofNullable(request.getUri().getQuery()).map(q -> "?" + q).orElse(""); + return applicationRepository.getLogs(applicationId, hostname, apiParams); + } - if (isDeploymentMetricsRequest(request)) { - return applicationRepository.getDeploymentMetrics(applicationId); - } + private HttpResponse protonMetrics(ApplicationId applicationId) { + return applicationRepository.getProtonMetrics(applicationId); + } - if (isIsSuspendedRequest(request)) { - return new ApplicationSuspendedResponse(applicationRepository.isSuspended(applicationId)); - } + private HttpResponse deploymentMetrics(ApplicationId applicationId) { + return applicationRepository.getDeploymentMetrics(applicationId); + } - if (isTesterRequest(request)) { - String testerCommand = getTesterCommandFromRequest(request); - switch (testerCommand) { - case "status": - return applicationRepository.getTesterStatus(applicationId); - case "log": - Long after = Long.valueOf(request.getProperty("after")); - return applicationRepository.getTesterLog(applicationId, after); - case "ready": - return applicationRepository.isTesterReady(applicationId); - case "report": - return applicationRepository.getTestReport(applicationId); - default: - throw new IllegalArgumentException("Unknown tester command in request " + request.getUri().toString()); - } - } + private HttpResponse isSuspended(ApplicationId applicationId) { + return new ApplicationSuspendedResponse(applicationRepository.isSuspended(applicationId)); + } - if (isQuotaUsageRequest(request)) { - var quotaUsageRate = applicationRepository.getQuotaUsageRate(applicationId); - return new QuotaUsageResponse(quotaUsageRate); + private HttpResponse testerRequest(ApplicationId applicationId, String command, HttpRequest request) { + switch (command) { + case "status": + return applicationRepository.getTesterStatus(applicationId); + case "log": + Long after = Long.valueOf(request.getProperty("after")); + return applicationRepository.getTesterLog(applicationId, after); + case "ready": + return applicationRepository.isTesterReady(applicationId); + case "report": + return applicationRepository.getTestReport(applicationId); + default: + throw new IllegalArgumentException("Unknown tester command in request " + request.getUri().toString()); } + } - return getApplicationResponse(applicationId); + private HttpResponse quotaUsage(ApplicationId applicationId) { + double quotaUsageRate = applicationRepository.getQuotaUsageRate(applicationId); + return new QuotaUsageResponse(quotaUsageRate); } - GetApplicationResponse getApplicationResponse(ApplicationId applicationId) { + private HttpResponse getApplicationResponse(ApplicationId applicationId) { return new GetApplicationResponse(Response.Status.OK, - applicationRepository.getApplicationGeneration(applicationId), - applicationRepository.getAllVersions(applicationId), - applicationRepository.getApplicationPackageReference(applicationId)); + applicationRepository.getApplicationGeneration(applicationId), + applicationRepository.getAllVersions(applicationId), + applicationRepository.getApplicationPackageReference(applicationId)); } - @Override - public HttpResponse handlePOST(HttpRequest request) { - ApplicationId applicationId = getApplicationIdFromRequest(request); - - if (isRestartRequest(request)) - return restart(request, applicationId); - - if (isTesterStartTestsRequest(request)) { - byte[] data; - try { - data = IOUtils.readBytes(request.getData(), 1024 * 1000); - } catch (IOException e) { - throw new IllegalArgumentException("Could not read data in request " + request); - } - return applicationRepository.startTests(applicationId, getSuiteFromRequest(request), data); - } - - if (isReindexRequest(request)) { - return triggerReindexing(request, applicationId); - } - - if (isReindexingRequest(request)) { - applicationRepository.modifyReindexing(applicationId, reindexing -> reindexing.enabled(true)); - return createMessageResponse("Reindexing enabled"); - } - - if (isValidateSecretStoreRequest(request)) { - var slime = uncheck(() -> SlimeUtils.jsonToSlime(request.getData().readAllBytes())); - return applicationRepository.validateSecretStore(applicationId, zone.system(), slime); - } - - throw new NotFoundException("Illegal POST request '" + request.getUri() + "'"); + public HttpResponse deleteApplication(ApplicationId applicationId) { + if (applicationRepository.delete(applicationId)) + return new DeleteApplicationResponse(applicationId); + return ErrorResponse.notFoundError("Unable to delete " + applicationId.toFullString() + ": Not found"); } + private Model getActiveModelOrThrow(ApplicationId id) { return applicationRepository.getActiveApplicationSet(id) .orElseThrow(() -> new NotFoundException("Application '" + id + "' not found")) @@ -243,7 +199,7 @@ public class ApplicationHandler extends HttpHandler { .getModel(); } - private HttpResponse triggerReindexing(HttpRequest request, ApplicationId applicationId) { + private HttpResponse triggerReindexing(ApplicationId applicationId, HttpRequest request) { Model model = getActiveModelOrThrow(applicationId); Map<String, Set<String>> documentTypes = model.documentTypesByCluster(); Map<String, Set<String>> indexedDocumentTypes = model.indexedDocumentTypesByCluster(); @@ -274,7 +230,7 @@ public class ApplicationHandler extends HttpHandler { return reindexing; }); - return createMessageResponse(reindexed.entrySet().stream() + return new MessageResponse(reindexed.entrySet().stream() .filter(cluster -> ! cluster.getValue().isEmpty()) .map(cluster -> "[" + String.join(", ", cluster.getValue()) + "] in '" + cluster.getKey() + "'") .reduce(new StringJoiner(", ", "Reindexing document types ", " of application " + applicationId) @@ -284,6 +240,16 @@ public class ApplicationHandler extends HttpHandler { .toString()); } + public HttpResponse disableReindexing(ApplicationId applicationId) { + applicationRepository.modifyReindexing(applicationId, reindexing -> reindexing.enabled(false)); + return new MessageResponse("Reindexing disabled"); + } + + private HttpResponse enableReindexing(ApplicationId applicationId) { + applicationRepository.modifyReindexing(applicationId, reindexing -> reindexing.enabled(true)); + return new MessageResponse("Reindexing enabled"); + } + private HttpResponse getReindexingStatus(ApplicationId applicationId) { Tenant tenant = applicationRepository.getTenant(applicationId); if (tenant == null) @@ -294,239 +260,42 @@ public class ApplicationHandler extends HttpHandler { applicationRepository.getClusterReindexingStatus(applicationId)); } - private HttpResponse restart(HttpRequest request, ApplicationId applicationId) { - if (getBindingMatch(request).groupCount() != 7) - throw new NotFoundException("Illegal POST restart request '" + request.getUri() + - "': Must have 6 arguments but had " + (getBindingMatch(request).groupCount() - 1)); - applicationRepository.restart(applicationId, hostFilterFrom(request)); - return new JSONResponse(Response.Status.OK); // return empty - } - - private HostFilter hostFilterFrom(HttpRequest request) { - return HostFilter.from(request.getProperty("hostname"), - request.getProperty("flavor"), - request.getProperty("clusterType"), - request.getProperty("clusterId")); - } - - private static BindingMatch<?> getBindingMatch(HttpRequest request) { - return URI_PATTERNS.stream() - .map(pattern -> { - UriPattern.Match match = pattern.match(request.getUri()); - if (match == null) return null; - return new BindingMatch<>(match, new Object(), pattern); - }) - .filter(Objects::nonNull) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Illegal url for config request: " + request.getUri())); - } - - private static boolean isRestartRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 7 && - request.getUri().getPath().endsWith("/restart"); - } - - private static boolean isReindexRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 7 && - request.getUri().getPath().endsWith("/reindex"); - } - - private static boolean isReindexingRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 7 && - request.getUri().getPath().endsWith("/reindexing"); - } - - private static boolean isIsSuspendedRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 7 && - request.getUri().getPath().endsWith("/suspended"); - } - - private static boolean isProtonMetricsRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 8 && - request.getUri().getPath().endsWith("/metrics/proton"); - } - - private static boolean isDeploymentMetricsRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 8 && - request.getUri().getPath().endsWith("/metrics/deployment"); - } - - private static boolean isLogRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 7 && - request.getUri().getPath().endsWith("/logs"); - } - - private static boolean isValidateSecretStoreRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 7 && - request.getUri().getPath().endsWith("/validate-secret-store"); - } - - private static boolean isServiceConvergeListRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 7 && - request.getUri().getPath().endsWith("/serviceconverge"); - } - - private static boolean isServiceConvergeRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 8 && - request.getUri().getPath().contains("/serviceconverge/"); - } - - private static boolean isClusterControllerStatusRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 9 && - request.getUri().getPath().contains("/clustercontroller/"); - } - - private static boolean isContentRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() > 7 && - request.getUri().getPath().contains("/content/"); - } - - private static boolean isFiledistributionStatusRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 7 && - request.getUri().getPath().contains("/filedistributionstatus"); - } - - private static boolean isTesterRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 8 && - request.getUri().getPath().contains("/tester"); - } - - private static boolean isTesterStartTestsRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 9 && - request.getUri().getPath().contains("/tester/run/"); - } - - private static boolean isQuotaUsageRequest(HttpRequest request) { - return getBindingMatch(request).groupCount() == 7 && - request.getUri().getPath().endsWith("/quota"); - } - - private static String getHostNameFromRequest(HttpRequest req) { - BindingMatch<?> bm = getBindingMatch(req); - return bm.group(7); - } - - private static String getTesterCommandFromRequest(HttpRequest req) { - BindingMatch<?> bm = getBindingMatch(req); - return bm.group(7); - } - - private static String getSuiteFromRequest(HttpRequest req) { - BindingMatch<?> bm = getBindingMatch(req); - return bm.group(8); - } - - private static String getPathSuffix(HttpRequest req) { - BindingMatch<?> bm = getBindingMatch(req); - return bm.group(8); - } - - private static ApplicationId getApplicationIdFromRequest(HttpRequest req) { - // Two bindings for this: with full app id or only application name - BindingMatch<?> bm = getBindingMatch(req); - if (bm.groupCount() > 4) return createFromRequestFullAppId(bm); - return createFromRequestSimpleAppId(bm); - } - - // The URL pattern with only tenant and application given - private static ApplicationId createFromRequestSimpleAppId(BindingMatch<?> bm) { - TenantName tenant = TenantName.from(bm.group(2)); - ApplicationName application = ApplicationName.from(bm.group(3)); - return new ApplicationId.Builder().tenant(tenant).applicationName(application).build(); - } - - // The URL pattern with full app id given - private static ApplicationId createFromRequestFullAppId(BindingMatch<?> bm) { - String tenant = bm.group(2); - String application = bm.group(3); - String instance = bm.group(6); - return new ApplicationId.Builder() - .tenant(tenant) - .applicationName(application).instanceName(instance) - .build(); - } - - private static Optional<Version> getVespaVersionFromRequest(HttpRequest request) { - String vespaVersion = request.getProperty("vespaVersion"); - return (vespaVersion == null || vespaVersion.isEmpty()) - ? Optional.empty() - : Optional.of(Version.fromString(vespaVersion)); + private HttpResponse restart(ApplicationId applicationId, HttpRequest request) { + HostFilter filter = HostFilter.from(request.getProperty("hostname"), + request.getProperty("flavor"), + request.getProperty("clusterType"), + request.getProperty("clusterId")); + applicationRepository.restart(applicationId, filter); + return new MessageResponse("Success"); } - private static class DeleteApplicationResponse extends JSONResponse { - DeleteApplicationResponse(int status, ApplicationId applicationId) { - super(status); - object.setString("message", "Application '" + applicationId + "' deleted"); + private HttpResponse testerStartTests(ApplicationId applicationId, String suite, HttpRequest request) { + byte[] data; + try { + data = IOUtils.readBytes(request.getData(), 1024 * 1000); + } catch (IOException e) { + throw new IllegalArgumentException("Could not read data in request " + request); } + return applicationRepository.startTests(applicationId, suite, data); } - private static class GetApplicationResponse extends JSONResponse { - GetApplicationResponse(int status, long generation, List<Version> modelVersions, Optional<String> applicationPackageReference) { - super(status); - object.setLong("generation", generation); - object.setString("applicationPackageFileReference", applicationPackageReference.orElse("")); - Cursor modelVersionArray = object.setArray("modelVersions"); - modelVersions.forEach(version -> modelVersionArray.addString(version.toFullString())); - } + private HttpResponse validateSecretStore(ApplicationId applicationId, HttpRequest request) { + var slime = uncheck(() -> SlimeUtils.jsonToSlime(request.getData().readAllBytes())); + return applicationRepository.validateSecretStore(applicationId, zone.system(), slime); } - private static class ApplicationSuspendedResponse extends JSONResponse { - ApplicationSuspendedResponse(boolean suspended) { - super(Response.Status.OK); - object.setBool("suspended", suspended); - } + private static ApplicationId applicationId(Path path) { + return ApplicationId.from(path.get("tenant"), path.get("application"), path.get("instance")); } - private static class QuotaUsageResponse extends JSONResponse { - QuotaUsageResponse(double usageRate) { - super(Response.Status.OK); - object.setDouble("rate", usageRate); - } + private static Duration getTimeoutFromRequest(HttpRequest request) { + return HttpHandler.getRequestTimeout(request, Duration.ofSeconds(5)); } - static class ReindexingResponse extends JSONResponse { - ReindexingResponse(Map<String, Set<String>> documentTypes, ApplicationReindexing reindexing, - Map<String, ClusterReindexing> clusters) { - super(Response.Status.OK); - object.setBool("enabled", reindexing.enabled()); - Cursor clustersObject = object.setObject("clusters"); - documentTypes.forEach((cluster, types) -> { - Cursor clusterObject = clustersObject.setObject(cluster); - Cursor pendingObject = clusterObject.setObject("pending"); - Cursor readyObject = clusterObject.setObject("ready"); - - for (String type : types) { - Cursor statusObject = readyObject.setObject(type); - if (reindexing.clusters().containsKey(cluster)) { - if (reindexing.clusters().get(cluster).pending().containsKey(type)) - pendingObject.setLong(type, reindexing.clusters().get(cluster).pending().get(type)); - - if (reindexing.clusters().get(cluster).ready().containsKey(type)) - setStatus(statusObject, reindexing.clusters().get(cluster).ready().get(type)); - } - if (clusters.containsKey(cluster)) - if (clusters.get(cluster).documentTypeStatus().containsKey(type)) - setStatus(statusObject, clusters.get(cluster).documentTypeStatus().get(type)); - } - }); - } - - private static void setStatus(Cursor object, ApplicationReindexing.Status readyStatus) { - object.setLong("readyMillis", readyStatus.ready().toEpochMilli()); - } - - private static void setStatus(Cursor object, ClusterReindexing.Status status) { - object.setLong("startedMillis", status.startedAt().toEpochMilli()); - status.endedAt().ifPresent(endedAt -> object.setLong("endedMillis", endedAt.toEpochMilli())); - status.state().map(ClusterReindexing.State::asString).ifPresent(state -> object.setString("state", state)); - status.message().ifPresent(message -> object.setString("message", message)); - status.progress().ifPresent(progress -> object.setDouble("progress", progress)); - } - - } - - private static JSONResponse createMessageResponse(String message) { - return new JSONResponse(Response.Status.OK) { { object.setString("message", message); } }; + private static Optional<Version> getVespaVersionFromRequest(HttpRequest request) { + return Optional.ofNullable(request.getProperty("vespaVersion")) + .filter(s -> !s.isEmpty()) + .map(Version::fromString); } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HostHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HostHandler.java index 1ea41b85983..0a69c7ed904 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HostHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HostHandler.java @@ -12,6 +12,7 @@ import com.yahoo.vespa.config.server.ApplicationRepository; import com.yahoo.vespa.config.server.http.HttpErrorResponse; import com.yahoo.vespa.config.server.http.HttpHandler; import com.yahoo.vespa.config.server.http.JSONResponse; +import com.yahoo.vespa.config.server.http.v2.request.HttpConfigRequests; /** * Handler for getting tenant and application for a given hostname. diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandler.java index 1787431e841..76a39bbcadb 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpGetConfigHandler.java @@ -7,6 +7,7 @@ import com.yahoo.container.jdisc.HttpResponse; import java.util.logging.Level; import com.yahoo.vespa.config.protocol.ConfigResponse; import com.yahoo.vespa.config.server.RequestHandler; +import com.yahoo.vespa.config.server.http.v2.request.HttpConfigRequests; import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.vespa.config.server.http.HttpConfigRequest; import com.yahoo.vespa.config.server.http.HttpConfigResponse; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandler.java index 71be471193a..3210f5eb8e5 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsHandler.java @@ -15,6 +15,8 @@ import com.yahoo.slime.JsonFormat; import com.yahoo.slime.Slime; import com.yahoo.vespa.config.ConfigKey; import com.yahoo.vespa.config.server.RequestHandler; +import com.yahoo.vespa.config.server.http.v2.request.HttpConfigRequests; +import com.yahoo.vespa.config.server.http.v2.request.HttpListConfigsRequest; import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.config.provision.ApplicationId; import com.yahoo.vespa.config.server.http.HttpConfigResponse; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListNamedConfigsHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListNamedConfigsHandler.java index bbc2efe9c36..425aa1c2bd2 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListNamedConfigsHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListNamedConfigsHandler.java @@ -10,6 +10,8 @@ import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.vespa.config.ConfigKey; import com.yahoo.vespa.config.server.RequestHandler; +import com.yahoo.vespa.config.server.http.v2.request.HttpConfigRequests; +import com.yahoo.vespa.config.server.http.v2.request.HttpListConfigsRequest; import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.config.provision.ApplicationId; import com.yahoo.vespa.config.server.http.HttpConfigRequest; 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 b06d5c31ac6..20688f4f2f1 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 @@ -10,6 +10,7 @@ import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.jdisc.Response; import com.yahoo.vespa.config.server.application.TenantApplications; +import com.yahoo.vespa.config.server.http.v2.response.ListApplicationsResponse; import com.yahoo.vespa.config.server.tenant.Tenant; import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.config.provision.ApplicationId; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandler.java index 4e75234620f..f97e272b132 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandler.java @@ -14,6 +14,7 @@ import com.yahoo.jdisc.Request; import com.yahoo.jdisc.handler.ResponseHandler; import java.util.logging.Level; import com.yahoo.vespa.config.server.ApplicationRepository; +import com.yahoo.vespa.config.server.http.v2.response.SessionActiveResponse; import com.yahoo.vespa.config.server.tenant.Tenant; import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.vespa.config.server.TimeoutBudget; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandler.java index 9f526bbdce8..4664fdf3557 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionContentHandler.java @@ -11,6 +11,7 @@ import com.yahoo.vespa.config.server.http.ContentRequest; import com.yahoo.vespa.config.server.http.ContentHandler; import com.yahoo.vespa.config.server.http.SessionHandler; import com.yahoo.vespa.config.server.http.Utils; +import com.yahoo.vespa.config.server.http.v2.request.SessionContentRequestV2; /** * A handler that will return content or content status for files or directories 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 61f099fb8ea..ea7d11d9802 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 @@ -9,7 +9,6 @@ import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.TenantName; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; -import com.yahoo.jdisc.HeaderFields; import com.yahoo.jdisc.application.UriPattern; import com.yahoo.vespa.config.server.ApplicationRepository; import com.yahoo.vespa.config.server.deploy.DeployHandlerLogger; @@ -17,13 +16,12 @@ import com.yahoo.vespa.config.server.TimeoutBudget; 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.model.content.Content; +import com.yahoo.vespa.config.server.http.v2.response.SessionCreateResponse; import org.apache.hc.core5.http.ContentType; 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, diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandler.java index 6fa2075807f..0d6d5ed943a 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandler.java @@ -7,6 +7,7 @@ import com.yahoo.config.provision.TenantName; 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.v2.response.SessionPrepareResponse; import com.yahoo.vespa.config.server.session.PrepareParams; import com.yahoo.vespa.config.server.tenant.Tenant; import com.yahoo.vespa.config.server.tenant.TenantRepository; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java index bb94f8d442a..a9961762f8b 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java @@ -10,6 +10,10 @@ import com.yahoo.restapi.RestApi; import com.yahoo.restapi.RestApiException; import com.yahoo.restapi.RestApiRequestHandler; import com.yahoo.vespa.config.server.ApplicationRepository; +import com.yahoo.vespa.config.server.http.v2.response.ListTenantsResponse; +import com.yahoo.vespa.config.server.http.v2.response.TenantCreateResponse; +import com.yahoo.vespa.config.server.http.v2.response.TenantDeleteResponse; +import com.yahoo.vespa.config.server.http.v2.response.TenantGetResponse; import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.yolean.Exceptions; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentRequest.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/request/ApplicationContentRequest.java index af3ab0b1b83..b7ec6272c3a 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationContentRequest.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/request/ApplicationContentRequest.java @@ -1,5 +1,5 @@ // 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; +package com.yahoo.vespa.config.server.http.v2.request; import com.yahoo.config.application.api.ApplicationFile; import com.yahoo.config.provision.ApplicationId; @@ -18,12 +18,12 @@ public class ApplicationContentRequest extends ContentRequest { private final ApplicationId applicationId; private final Zone zone; - ApplicationContentRequest(HttpRequest request, - long sessionId, - ApplicationId applicationId, - Zone zone, - String contentPath, - ApplicationFile applicationFile) { + public ApplicationContentRequest(HttpRequest request, + long sessionId, + ApplicationId applicationId, + Zone zone, + String contentPath, + ApplicationFile applicationFile) { super(request, sessionId, contentPath, applicationFile); this.applicationId = applicationId; this.zone = zone; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpConfigRequests.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/request/HttpConfigRequests.java index 8b482997044..d190ccaec12 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpConfigRequests.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/request/HttpConfigRequests.java @@ -1,5 +1,5 @@ // 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; +package com.yahoo.vespa.config.server.http.v2.request; import java.net.URI; @@ -45,7 +45,7 @@ public class HttpConfigRequests { } - static RequestHandler getRequestHandler(TenantRepository tenantRepository, TenantRequest request) { + public static RequestHandler getRequestHandler(TenantRepository tenantRepository, TenantRequest request) { Tenant tenant = tenantRepository.getTenant(request.getApplicationId().tenant()); if (tenant==null) throw new NotFoundException("No such tenant: "+request.getApplicationId().tenant()); return tenant.getRequestHandler(); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsRequest.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/request/HttpListConfigsRequest.java index 208b682df9a..cd9c44db85b 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/HttpListConfigsRequest.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/request/HttpListConfigsRequest.java @@ -1,5 +1,5 @@ // 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; +package com.yahoo.vespa.config.server.http.v2.request; import com.yahoo.collections.Tuple2; import com.yahoo.config.provision.ApplicationName; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionContentRequestV2.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/request/SessionContentRequestV2.java index c5a9d36f493..4f34b2fb332 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionContentRequestV2.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/request/SessionContentRequestV2.java @@ -1,5 +1,5 @@ // 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; +package com.yahoo.vespa.config.server.http.v2.request; import com.yahoo.config.application.api.ApplicationFile; import com.yahoo.config.provision.TenantName; @@ -20,7 +20,7 @@ public class SessionContentRequestV2 extends ContentRequest { private final TenantName tenantName; private final long sessionId; - SessionContentRequestV2(HttpRequest request, + public SessionContentRequestV2(HttpRequest request, long sessionId, TenantName tenantName, String path, @@ -35,7 +35,7 @@ public class SessionContentRequestV2 extends ContentRequest { return "/application/v2/tenant/" + tenantName.value() + "/session/" + sessionId; } - static String getContentPath(HttpRequest request) { + public static String getContentPath(HttpRequest request) { BindingMatch<?> bm = Utils.getBindingMatch(request, uriPattern); return bm.group(4); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantRequest.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/request/TenantRequest.java index 0fae091aa78..84071ca2a98 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantRequest.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/request/TenantRequest.java @@ -1,5 +1,5 @@ // 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; +package com.yahoo.vespa.config.server.http.v2.request; import com.yahoo.config.provision.ApplicationId; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ApplicationSuspendedResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ApplicationSuspendedResponse.java new file mode 100644 index 00000000000..c2449d9a31d --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ApplicationSuspendedResponse.java @@ -0,0 +1,12 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.config.server.http.v2.response; + +import com.yahoo.jdisc.Response; +import com.yahoo.vespa.config.server.http.JSONResponse; + +public class ApplicationSuspendedResponse extends JSONResponse { + public ApplicationSuspendedResponse(boolean suspended) { + super(Response.Status.OK); + object.setBool("suspended", suspended); + } +} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/DeleteApplicationResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/DeleteApplicationResponse.java new file mode 100644 index 00000000000..375a6d5e57f --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/DeleteApplicationResponse.java @@ -0,0 +1,11 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.config.server.http.v2.response; + +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.restapi.MessageResponse; + +public class DeleteApplicationResponse extends MessageResponse { + public DeleteApplicationResponse(ApplicationId applicationId) { + super("Application '" + applicationId + "' deleted"); + } +} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/DeploymentMetricsResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/DeploymentMetricsResponse.java index cdfdce91500..253e37f2b0a 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/DeploymentMetricsResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/DeploymentMetricsResponse.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.vespa.config.server.http.v2; +package com.yahoo.vespa.config.server.http.v2.response; import com.yahoo.config.provision.ApplicationId; import com.yahoo.restapi.SlimeJsonResponse; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/GetApplicationResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/GetApplicationResponse.java new file mode 100644 index 00000000000..dc124891540 --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/GetApplicationResponse.java @@ -0,0 +1,19 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.config.server.http.v2.response; + +import com.yahoo.component.Version; +import com.yahoo.slime.Cursor; +import com.yahoo.vespa.config.server.http.JSONResponse; + +import java.util.List; +import java.util.Optional; + +public class GetApplicationResponse extends JSONResponse { + public GetApplicationResponse(int status, long generation, List<Version> modelVersions, Optional<String> applicationPackageReference) { + super(status); + object.setLong("generation", generation); + object.setString("applicationPackageFileReference", applicationPackageReference.orElse("")); + Cursor modelVersionArray = object.setArray("modelVersions"); + modelVersions.forEach(version -> modelVersionArray.addString(version.toFullString())); + } +} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ListApplicationsResponse.java index a4527305abb..6b1f7031d81 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListApplicationsResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ListApplicationsResponse.java @@ -1,5 +1,5 @@ // 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; +package com.yahoo.vespa.config.server.http.v2.response; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.slime.Cursor; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListTenantsResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ListTenantsResponse.java index 3789939429c..ec1b3c83604 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ListTenantsResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ListTenantsResponse.java @@ -1,11 +1,12 @@ // 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; +package com.yahoo.vespa.config.server.http.v2.response; -import com.google.common.collect.ImmutableSet; import com.yahoo.config.provision.TenantName; import com.yahoo.restapi.SlimeJsonResponse; import com.yahoo.slime.Cursor; +import java.util.Set; + /** * Tenant list response * @@ -13,7 +14,7 @@ import com.yahoo.slime.Cursor; */ public class ListTenantsResponse extends SlimeJsonResponse { - ListTenantsResponse(ImmutableSet<TenantName> tenants) { + public ListTenantsResponse(Set<TenantName> tenants) { Cursor tenantArray = slime.setObject().setArray("tenants"); tenants.forEach(tenantName -> tenantArray.addString(tenantName.value())); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ProtonMetricsResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ProtonMetricsResponse.java index 99b95f9244c..25e770c7211 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ProtonMetricsResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ProtonMetricsResponse.java @@ -1,5 +1,5 @@ // Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server.http.v2; +package com.yahoo.vespa.config.server.http.v2.response; import com.yahoo.config.provision.ApplicationId; import com.yahoo.restapi.SlimeJsonResponse; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/QuotaUsageResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/QuotaUsageResponse.java new file mode 100644 index 00000000000..e30f0f45098 --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/QuotaUsageResponse.java @@ -0,0 +1,12 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.config.server.http.v2.response; + +import com.yahoo.jdisc.Response; +import com.yahoo.vespa.config.server.http.JSONResponse; + +public class QuotaUsageResponse extends JSONResponse { + public QuotaUsageResponse(double usageRate) { + super(Response.Status.OK); + object.setDouble("rate", usageRate); + } +} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ReindexingResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ReindexingResponse.java new file mode 100644 index 00000000000..e73d4a9cb56 --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ReindexingResponse.java @@ -0,0 +1,52 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.config.server.http.v2.response; + +import com.yahoo.jdisc.Response; +import com.yahoo.slime.Cursor; +import com.yahoo.vespa.config.server.application.ApplicationReindexing; +import com.yahoo.vespa.config.server.application.ClusterReindexing; +import com.yahoo.vespa.config.server.http.JSONResponse; + +import java.util.Map; +import java.util.Set; + +public class ReindexingResponse extends JSONResponse { + public ReindexingResponse(Map<String, Set<String>> documentTypes, ApplicationReindexing reindexing, + Map<String, ClusterReindexing> clusters) { + super(Response.Status.OK); + object.setBool("enabled", reindexing.enabled()); + Cursor clustersObject = object.setObject("clusters"); + documentTypes.forEach((cluster, types) -> { + Cursor clusterObject = clustersObject.setObject(cluster); + Cursor pendingObject = clusterObject.setObject("pending"); + Cursor readyObject = clusterObject.setObject("ready"); + + for (String type : types) { + Cursor statusObject = readyObject.setObject(type); + if (reindexing.clusters().containsKey(cluster)) { + if (reindexing.clusters().get(cluster).pending().containsKey(type)) + pendingObject.setLong(type, reindexing.clusters().get(cluster).pending().get(type)); + + if (reindexing.clusters().get(cluster).ready().containsKey(type)) + setStatus(statusObject, reindexing.clusters().get(cluster).ready().get(type)); + } + if (clusters.containsKey(cluster)) + if (clusters.get(cluster).documentTypeStatus().containsKey(type)) + setStatus(statusObject, clusters.get(cluster).documentTypeStatus().get(type)); + } + }); + } + + private static void setStatus(Cursor object, ApplicationReindexing.Status readyStatus) { + object.setLong("readyMillis", readyStatus.ready().toEpochMilli()); + } + + private static void setStatus(Cursor object, ClusterReindexing.Status status) { + object.setLong("startedMillis", status.startedAt().toEpochMilli()); + status.endedAt().ifPresent(endedAt -> object.setLong("endedMillis", endedAt.toEpochMilli())); + status.state().map(ClusterReindexing.State::asString).ifPresent(state -> object.setString("state", state)); + status.message().ifPresent(message -> object.setString("message", message)); + status.progress().ifPresent(progress -> object.setDouble("progress", progress)); + } + +} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/SessionActiveResponse.java index 9c0fbdf2613..f14f9cc6575 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionActiveResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/SessionActiveResponse.java @@ -1,5 +1,5 @@ // 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; +package com.yahoo.vespa.config.server.http.v2.response; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.Zone; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/SessionCreateResponse.java index faf02a1ea4f..047962ea16b 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionCreateResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/SessionCreateResponse.java @@ -1,5 +1,5 @@ // 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; +package com.yahoo.vespa.config.server.http.v2.response; import com.yahoo.config.provision.TenantName; import com.yahoo.restapi.SlimeJsonResponse; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareAndActivateResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/SessionPrepareAndActivateResponse.java index 7bace4749a8..d219ff64b4e 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareAndActivateResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/SessionPrepareAndActivateResponse.java @@ -1,5 +1,5 @@ // 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; +package com.yahoo.vespa.config.server.http.v2.response; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; @@ -8,15 +8,16 @@ import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.restapi.SlimeJsonResponse; import com.yahoo.slime.Cursor; import com.yahoo.vespa.config.server.configchange.ConfigChangeActionsSlimeConverter; +import com.yahoo.vespa.config.server.http.v2.PrepareResult; /** * Creates a response for SessionPrepareHandler. * * @author hmusum */ -class SessionPrepareAndActivateResponse extends SlimeJsonResponse { +public class SessionPrepareAndActivateResponse extends SlimeJsonResponse { - SessionPrepareAndActivateResponse(PrepareResult result, HttpRequest request, ApplicationId applicationId, Zone zone) { + public SessionPrepareAndActivateResponse(PrepareResult result, HttpRequest request, ApplicationId applicationId, Zone zone) { super(result.deployLogger().slime()); TenantName tenantName = applicationId.tenant(); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/SessionPrepareResponse.java index a97cd37d3b4..5f50a5236fb 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/SessionPrepareResponse.java @@ -1,5 +1,5 @@ // 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; +package com.yahoo.vespa.config.server.http.v2.response; import com.yahoo.config.provision.TenantName; import com.yahoo.container.jdisc.HttpRequest; @@ -9,19 +9,20 @@ import com.yahoo.slime.Slime; import com.yahoo.slime.Type; import com.yahoo.vespa.config.server.configchange.ConfigChangeActions; import com.yahoo.vespa.config.server.configchange.ConfigChangeActionsSlimeConverter; +import com.yahoo.vespa.config.server.http.v2.PrepareResult; /** * Creates a response for SessionPrepareHandler. * * @author hmusum */ -class SessionPrepareResponse extends SlimeJsonResponse { +public class SessionPrepareResponse extends SlimeJsonResponse { - SessionPrepareResponse(TenantName tenantName, HttpRequest request, long sessionId) { + public SessionPrepareResponse(TenantName tenantName, HttpRequest request, long sessionId) { this(new Slime(), tenantName, request, sessionId, new ConfigChangeActions()); } - SessionPrepareResponse(PrepareResult result, TenantName tenantName, HttpRequest request) { + public SessionPrepareResponse(PrepareResult result, TenantName tenantName, HttpRequest request) { this(result.deployLogger().slime(), tenantName, request, result.sessionId(), result.configChangeActions()); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantCreateResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/TenantCreateResponse.java index 6ff2b30075d..395a52df9f2 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantCreateResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/TenantCreateResponse.java @@ -1,5 +1,5 @@ // 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; +package com.yahoo.vespa.config.server.http.v2.response; import com.yahoo.config.provision.TenantName; import com.yahoo.restapi.MessageResponse; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantDeleteResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/TenantDeleteResponse.java index d21584c8cdc..fbfb4d581c6 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantDeleteResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/TenantDeleteResponse.java @@ -1,5 +1,5 @@ // 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; +package com.yahoo.vespa.config.server.http.v2.response; import com.yahoo.config.provision.TenantName; import com.yahoo.restapi.MessageResponse; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantGetResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/TenantGetResponse.java index b918cab7828..3a50a68cb21 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantGetResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/TenantGetResponse.java @@ -1,5 +1,5 @@ // 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; +package com.yahoo.vespa.config.server.http.v2.response; import com.yahoo.config.provision.TenantName; import com.yahoo.restapi.MessageResponse; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/DeploymentMetricsRetriever.java b/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/DeploymentMetricsRetriever.java index 7fc2c47c06c..2681952cae9 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/DeploymentMetricsRetriever.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/DeploymentMetricsRetriever.java @@ -4,7 +4,7 @@ package com.yahoo.vespa.config.server.metrics; import com.yahoo.config.model.api.HostInfo; import com.yahoo.config.model.api.ServiceInfo; import com.yahoo.vespa.config.server.application.Application; -import com.yahoo.vespa.config.server.http.v2.DeploymentMetricsResponse; +import com.yahoo.vespa.config.server.http.v2.response.DeploymentMetricsResponse; import java.net.URI; import java.util.Collection; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/ProtonMetricsRetriever.java b/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/ProtonMetricsRetriever.java index 5078fba8b38..4c111687c41 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/ProtonMetricsRetriever.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/ProtonMetricsRetriever.java @@ -4,7 +4,7 @@ package com.yahoo.vespa.config.server.metrics; import com.yahoo.config.model.api.HostInfo; import com.yahoo.config.model.api.ServiceInfo; import com.yahoo.vespa.config.server.application.Application; -import com.yahoo.vespa.config.server.http.v2.ProtonMetricsResponse; +import com.yahoo.vespa.config.server.http.v2.response.ProtonMetricsResponse; import java.net.URI; import java.util.Collection; import java.util.function.Predicate; |