aboutsummaryrefslogtreecommitdiffstats
path: root/configserver/src/main/java/com/yahoo
diff options
context:
space:
mode:
Diffstat (limited to 'configserver/src/main/java/com/yahoo')
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java20
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigConvergenceChecker.java116
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java100
3 files changed, 169 insertions, 67 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 02ca4ce14c4..80194337daa 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
@@ -111,6 +111,8 @@ import java.util.stream.Collectors;
import static com.yahoo.config.model.api.container.ContainerServiceType.CONTAINER;
import static com.yahoo.config.model.api.container.ContainerServiceType.LOGSERVER_CONTAINER;
+import static com.yahoo.vespa.config.server.application.ConfigConvergenceChecker.ServiceResponse;
+import static com.yahoo.vespa.config.server.application.ConfigConvergenceChecker.ServiceListResponse;
import static com.yahoo.vespa.config.server.filedistribution.FileDistributionUtil.fileReferenceExistsOnDisk;
import static com.yahoo.vespa.config.server.filedistribution.FileDistributionUtil.getFileReferencesOnDisk;
import static com.yahoo.vespa.config.server.tenant.TenantRepository.HOSTED_VESPA_TENANT;
@@ -737,16 +739,22 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
// ---------------- Convergence ----------------------------------------------------------------
- public HttpResponse checkServiceForConfigConvergence(ApplicationId applicationId, String hostAndPort, URI uri,
- Duration timeout, Optional<Version> vespaVersion) {
- return convergeChecker.getServiceConfigGenerationResponse(getApplication(applicationId, vespaVersion), hostAndPort, uri, timeout);
+ public ServiceResponse checkServiceForConfigConvergence(ApplicationId applicationId,
+ String hostAndPort,
+ Duration timeout,
+ Optional<Version> vespaVersion) {
+ return convergeChecker.getServiceConfigGeneration(getApplication(applicationId, vespaVersion), hostAndPort, timeout);
}
- public HttpResponse servicesToCheckForConfigConvergence(ApplicationId applicationId, URI uri,
- Duration timeoutPerService, Optional<Version> vespaVersion) {
- return convergeChecker.getServiceConfigGenerationsResponse(getApplication(applicationId, vespaVersion), uri, timeoutPerService);
+ public ServiceListResponse servicesToCheckForConfigConvergence(ApplicationId applicationId,
+ URI uri,
+ Duration timeoutPerService,
+ Optional<Version> vespaVersion) {
+ return convergeChecker.getServiceConfigGenerations(getApplication(applicationId, vespaVersion), uri, timeoutPerService);
}
+ public ConfigConvergenceChecker configConvergenceChecker() { return convergeChecker; }
+
// ---------------- Logs ----------------------------------------------------------------
public HttpResponse getLogs(ApplicationId applicationId, Optional<String> hostname, String apiParams) {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigConvergenceChecker.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigConvergenceChecker.java
index 24744a1b3b2..ad14cf4aab6 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigConvergenceChecker.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ConfigConvergenceChecker.java
@@ -10,8 +10,6 @@ import com.yahoo.concurrent.DaemonThreadFactory;
import com.yahoo.config.model.api.HostInfo;
import com.yahoo.config.model.api.PortInfo;
import com.yahoo.config.model.api.ServiceInfo;
-import com.yahoo.slime.Cursor;
-import com.yahoo.vespa.config.server.http.JSONResponse;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
@@ -92,27 +90,26 @@ public class ConfigConvergenceChecker extends AbstractComponent {
}
/** Check all services in given application. Returns the minimum current generation of all services */
- public JSONResponse getServiceConfigGenerationsResponse(Application application, URI requestUrl, Duration timeoutPerService) {
+ public ServiceListResponse getServiceConfigGenerations(Application application, URI uri, Duration timeoutPerService) {
Map<ServiceInfo, Long> currentGenerations = getServiceConfigGenerations(application, timeoutPerService);
long currentGeneration = currentGenerations.values().stream().mapToLong(Long::longValue).min().orElse(-1);
- return new ServiceListResponse(200, currentGenerations, requestUrl, application.getApplicationGeneration(),
- currentGeneration);
+ return new ServiceListResponse(currentGenerations, uri, application.getApplicationGeneration(), currentGeneration);
}
/** Check service identified by host and port in given application */
- public JSONResponse getServiceConfigGenerationResponse(Application application, String hostAndPortToCheck, URI requestUrl, Duration timeout) {
+ public ServiceResponse getServiceConfigGeneration(Application application, String hostAndPortToCheck, Duration timeout) {
Long wantedGeneration = application.getApplicationGeneration();
try (CloseableHttpAsyncClient client = createHttpClient()) {
client.start();
if ( ! hostInApplication(application, hostAndPortToCheck))
- return ServiceResponse.createHostNotFoundInAppResponse(requestUrl, hostAndPortToCheck, wantedGeneration);
+ return new ServiceResponse(ServiceResponse.Status.hostNotFound, wantedGeneration);
long currentGeneration = getServiceGeneration(client, URI.create("http://" + hostAndPortToCheck), timeout).get();
boolean converged = currentGeneration >= wantedGeneration;
- return ServiceResponse.createOkResponse(requestUrl, hostAndPortToCheck, wantedGeneration, currentGeneration, converged);
+ return new ServiceResponse(ServiceResponse.Status.ok, wantedGeneration, currentGeneration, converged);
} catch (InterruptedException | ExecutionException | CancellationException e) { // e.g. if we cannot connect to the service to find generation
- return ServiceResponse.createNotFoundResponse(requestUrl, hostAndPortToCheck, wantedGeneration, e.getMessage());
+ return new ServiceResponse(ServiceResponse.Status.notFound, wantedGeneration, e.getMessage());
} catch (Exception e) {
- return ServiceResponse.createErrorResponse(requestUrl, hostAndPortToCheck, wantedGeneration, e.getMessage());
+ return new ServiceResponse(ServiceResponse.Status.error, wantedGeneration, e.getMessage());
}
}
@@ -192,7 +189,7 @@ public class ConfigConvergenceChecker extends AbstractComponent {
return false;
}
- private static Optional<Integer> getStatePort(ServiceInfo service) {
+ public static Optional<Integer> getStatePort(ServiceInfo service) {
return service.getPorts().stream()
.filter(port -> port.getTags().contains("state"))
.map(PortInfo::getPort)
@@ -249,63 +246,70 @@ public class ConfigConvergenceChecker extends AbstractComponent {
.build();
}
- private static class ServiceListResponse extends JSONResponse {
-
- // Pre-condition: servicesToCheck has a state port
- private ServiceListResponse(int status, Map<ServiceInfo, Long> servicesToCheck, URI uri, long wantedGeneration,
- long currentGeneration) {
- super(status);
- Cursor serviceArray = object.setArray("services");
- servicesToCheck.forEach((service, generation) -> {
- Cursor serviceObject = serviceArray.addObject();
- String hostName = service.getHostName();
- int statePort = getStatePort(service).get();
- serviceObject.setString("host", hostName);
- serviceObject.setLong("port", statePort);
- serviceObject.setString("type", service.getServiceType());
- serviceObject.setString("url", uri.toString() + "/" + hostName + ":" + statePort);
- serviceObject.setLong("currentGeneration", generation);
- });
- object.setString("url", uri.toString());
- object.setLong("currentGeneration", currentGeneration);
- object.setLong("wantedGeneration", wantedGeneration);
- object.setBool("converged", currentGeneration >= wantedGeneration);
+ public static class ServiceResponse {
+
+ public enum Status { ok, notFound, hostNotFound, error }
+
+ public final Status status;
+ public final Long wantedGeneration;
+ public final Long currentGeneration;
+ public final boolean converged;
+ public final Optional<String> errorMessage;
+
+ public ServiceResponse(Status status, Long wantedGeneration) {
+ this(status, wantedGeneration, 0L);
}
- }
- private static class ServiceResponse extends JSONResponse {
+ public ServiceResponse(Status status, Long wantedGeneration, Long currentGeneration) {
+ this(status, wantedGeneration, currentGeneration, false);
+ }
- private ServiceResponse(int status, URI uri, String hostname, Long wantedGeneration) {
- super(status);
- object.setString("url", uri.toString());
- object.setString("host", hostname);
- object.setLong("wantedGeneration", wantedGeneration);
+ public ServiceResponse(Status status, Long wantedGeneration, Long currentGeneration, boolean converged) {
+ this(status, wantedGeneration, currentGeneration, converged, Optional.empty());
}
- static ServiceResponse createOkResponse(URI uri, String hostname, Long wantedGeneration, Long currentGeneration, boolean converged) {
- ServiceResponse serviceResponse = new ServiceResponse(200, uri, hostname, wantedGeneration);
- serviceResponse.object.setBool("converged", converged);
- serviceResponse.object.setLong("currentGeneration", currentGeneration);
- return serviceResponse;
+ public ServiceResponse(Status status, Long wantedGeneration, String errorMessage) {
+ this(status, wantedGeneration, 0L, false, Optional.ofNullable(errorMessage));
}
- static ServiceResponse createHostNotFoundInAppResponse(URI uri, String hostname, Long wantedGeneration) {
- ServiceResponse serviceResponse = new ServiceResponse(410, uri, hostname, wantedGeneration);
- serviceResponse.object.setString("problem", "Host:port (service) no longer part of application, refetch list of services.");
- return serviceResponse;
+ private ServiceResponse(Status status, Long wantedGeneration, Long currentGeneration, boolean converged, Optional<String> errorMessage) {
+ this.status = status;
+ this.wantedGeneration = wantedGeneration;
+ this.currentGeneration = currentGeneration;
+ this.converged = converged;
+ this.errorMessage = errorMessage;
}
- static ServiceResponse createErrorResponse(URI uri, String hostname, Long wantedGeneration, String error) {
- ServiceResponse serviceResponse = new ServiceResponse(500, uri, hostname, wantedGeneration);
- serviceResponse.object.setString("error", error);
- return serviceResponse;
+ }
+
+ public static class ServiceListResponse {
+
+ public final List<Service> services = new ArrayList<>();
+ public final URI uri;
+ public final long wantedGeneration;
+ public final long currentGeneration;
+
+ public ServiceListResponse(Map<ServiceInfo, Long> services, URI uri, long wantedGeneration, long currentGeneration) {
+ services.forEach((key, value) -> this.services.add(new Service(key, value)));
+ this.uri = uri;
+ this.wantedGeneration = wantedGeneration;
+ this.currentGeneration = currentGeneration;
}
- static ServiceResponse createNotFoundResponse(URI uri, String hostname, Long wantedGeneration, String error) {
- ServiceResponse serviceResponse = new ServiceResponse(404, uri, hostname, wantedGeneration);
- serviceResponse.object.setString("error", error);
- return serviceResponse;
+ public List<Service> services() { return services; }
+
+ public static class Service {
+
+ public final ServiceInfo serviceInfo;
+ public final Long currentGeneration;
+
+ public Service(ServiceInfo serviceInfo, Long currentGeneration) {
+ this.serviceInfo = serviceInfo;
+ this.currentGeneration = currentGeneration;
+ }
+
}
+
}
}
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 4dda141491c..0131517818d 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
@@ -5,6 +5,7 @@ import com.google.inject.Inject;
import com.yahoo.component.Version;
import com.yahoo.config.application.api.ApplicationFile;
import com.yahoo.config.model.api.Model;
+import com.yahoo.config.model.api.ServiceInfo;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.InstanceName;
@@ -16,13 +17,15 @@ import com.yahoo.jdisc.Response;
import com.yahoo.restapi.ErrorResponse;
import com.yahoo.restapi.MessageResponse;
import com.yahoo.restapi.Path;
+import com.yahoo.slime.Cursor;
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.ConfigConvergenceChecker;
import com.yahoo.vespa.config.server.http.ContentHandler;
import com.yahoo.vespa.config.server.http.ContentRequest;
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;
@@ -33,6 +36,7 @@ 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.URI;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
@@ -43,8 +47,11 @@ import java.util.StringJoiner;
import java.util.TreeMap;
import java.util.TreeSet;
+import static com.yahoo.vespa.config.server.application.ConfigConvergenceChecker.ServiceListResponse;
+import static com.yahoo.vespa.config.server.application.ConfigConvergenceChecker.ServiceResponse;
import static com.yahoo.yolean.Exceptions.uncheck;
+
/**
* Operations on applications (delete, wait for config convergence, restart, application content etc.)
*
@@ -108,13 +115,21 @@ public class ApplicationHandler extends HttpHandler {
}
private HttpResponse listServiceConverge(ApplicationId applicationId, HttpRequest request) {
- return applicationRepository.servicesToCheckForConfigConvergence(applicationId, request.getUri(),
- getTimeoutFromRequest(request), getVespaVersionFromRequest(request));
+ ServiceListResponse response =
+ applicationRepository.servicesToCheckForConfigConvergence(applicationId,
+ request.getUri(),
+ getTimeoutFromRequest(request),
+ getVespaVersionFromRequest(request));
+ return new HttpServiceListResponse(response);
}
private HttpResponse checkServiceConverge(ApplicationId applicationId, String hostAndPort, HttpRequest request) {
- return applicationRepository.checkServiceForConfigConvergence(applicationId, hostAndPort, request.getUri(),
- getTimeoutFromRequest(request), getVespaVersionFromRequest(request));
+ ServiceResponse response =
+ applicationRepository.checkServiceForConfigConvergence(applicationId,
+ hostAndPort,
+ getTimeoutFromRequest(request),
+ getVespaVersionFromRequest(request));
+ return HttpServiceResponse.createResponse(response, hostAndPort, request.getUri());
}
private HttpResponse serviceStatusPage(ApplicationId applicationId, String service, String hostname, String pathSuffix) {
@@ -301,4 +316,79 @@ public class ApplicationHandler extends HttpHandler {
.map(Version::fromString);
}
+ static class HttpServiceResponse extends JSONResponse {
+
+ public static HttpServiceResponse createResponse(ConfigConvergenceChecker.ServiceResponse serviceResponse, String hostAndPort, URI uri) {
+ switch (serviceResponse.status) {
+ case ok:
+ return createOkResponse(uri, hostAndPort, serviceResponse.wantedGeneration, serviceResponse.currentGeneration, serviceResponse.converged);
+ case hostNotFound:
+ return createHostNotFoundInAppResponse(uri, hostAndPort, serviceResponse.wantedGeneration);
+ case notFound:
+ return createNotFoundResponse(uri, hostAndPort, serviceResponse.wantedGeneration, serviceResponse.errorMessage.orElse(""));
+ case error:
+ return createErrorResponse(uri, hostAndPort, serviceResponse.wantedGeneration, serviceResponse.errorMessage.orElse(""));
+ default:
+ throw new IllegalArgumentException("Unknown status " + serviceResponse.status);
+ }
+ }
+
+ private HttpServiceResponse(int status, URI uri, String hostname, Long wantedGeneration) {
+ super(status);
+ object.setString("url", uri.toString());
+ object.setString("host", hostname);
+ object.setLong("wantedGeneration", wantedGeneration);
+ }
+
+ private static HttpServiceResponse createOkResponse(URI uri, String hostname, Long wantedGeneration, Long currentGeneration, boolean converged) {
+ HttpServiceResponse serviceResponse = new HttpServiceResponse(200, uri, hostname, wantedGeneration);
+ serviceResponse.object.setBool("converged", converged);
+ serviceResponse.object.setLong("currentGeneration", currentGeneration);
+ return serviceResponse;
+ }
+
+ private static HttpServiceResponse createHostNotFoundInAppResponse(URI uri, String hostname, Long wantedGeneration) {
+ HttpServiceResponse serviceResponse = new HttpServiceResponse(410, uri, hostname, wantedGeneration);
+ serviceResponse.object.setString("problem", "Host:port (service) no longer part of application, refetch list of services.");
+ return serviceResponse;
+ }
+
+ private static HttpServiceResponse createErrorResponse(URI uri, String hostname, Long wantedGeneration, String error) {
+ HttpServiceResponse serviceResponse = new HttpServiceResponse(500, uri, hostname, wantedGeneration);
+ serviceResponse.object.setString("error", error);
+ return serviceResponse;
+ }
+
+ private static HttpServiceResponse createNotFoundResponse(URI uri, String hostname, Long wantedGeneration, String error) {
+ HttpServiceResponse serviceResponse = new HttpServiceResponse(404, uri, hostname, wantedGeneration);
+ serviceResponse.object.setString("error", error);
+ return serviceResponse;
+ }
+
+ }
+
+ static class HttpServiceListResponse extends JSONResponse {
+
+ // Pre-condition: servicesToCheck has a state port
+ public HttpServiceListResponse(ConfigConvergenceChecker.ServiceListResponse response) {
+ super(200);
+ Cursor serviceArray = object.setArray("services");
+ response.services().forEach((service) -> {
+ ServiceInfo serviceInfo = service.serviceInfo;
+ Cursor serviceObject = serviceArray.addObject();
+ String hostName = serviceInfo.getHostName();
+ int statePort = ConfigConvergenceChecker.getStatePort(serviceInfo).get();
+ serviceObject.setString("host", hostName);
+ serviceObject.setLong("port", statePort);
+ serviceObject.setString("type", serviceInfo.getServiceType());
+ serviceObject.setString("url", response.uri.toString() + "/" + hostName + ":" + statePort);
+ serviceObject.setLong("currentGeneration", service.currentGeneration);
+ });
+ object.setString("url", response.uri.toString());
+ object.setLong("currentGeneration", response.currentGeneration);
+ object.setLong("wantedGeneration", response.wantedGeneration);
+ object.setBool("converged", response.currentGeneration >= response.wantedGeneration);
+ }
+ }
+
}