Search in sources :

Example 21 with RestException

use of org.apache.pulsar.common.util.RestException in project pulsar by apache.

the class ComponentImpl method listFunctions.

@Override
public List<String> listFunctions(final String tenant, final String namespace, final String clientRole, final AuthenticationDataSource clientAuthenticationDataHttps) {
    if (!isWorkerServiceAvailable()) {
        throwUnavailableException();
    }
    try {
        if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
            log.warn("{}/{} Client [{}] is not authorized to list {}", tenant, namespace, clientRole, ComponentTypeUtils.toString(componentType));
            throw new RestException(Status.UNAUTHORIZED, "Client is not authorized to perform operation");
        }
    } catch (PulsarAdminException e) {
        log.error("{}/{} Failed to authorize [{}]", tenant, namespace, e);
        throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());
    }
    // validate parameters
    try {
        validateListFunctionRequestParams(tenant, namespace);
    } catch (IllegalArgumentException e) {
        log.error("Invalid list {} request @ /{}/{}", ComponentTypeUtils.toString(componentType), tenant, namespace, e);
        throw new RestException(Status.BAD_REQUEST, e.getMessage());
    }
    FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();
    Collection<FunctionMetaData> functionStateList = functionMetaDataManager.listFunctions(tenant, namespace);
    List<String> retVals = new LinkedList<>();
    for (FunctionMetaData functionMetaData : functionStateList) {
        if (InstanceUtils.calculateSubjectType(functionMetaData.getFunctionDetails()).equals(componentType)) {
            retVals.add(functionMetaData.getFunctionDetails().getName());
        }
    }
    return retVals;
}
Also used : FunctionMetaData(org.apache.pulsar.functions.proto.Function.FunctionMetaData) FunctionMetaDataManager(org.apache.pulsar.functions.worker.FunctionMetaDataManager) RestException(org.apache.pulsar.common.util.RestException) PulsarAdminException(org.apache.pulsar.client.admin.PulsarAdminException) LinkedList(java.util.LinkedList)

Example 22 with RestException

use of org.apache.pulsar.common.util.RestException in project pulsar by apache.

the class FunctionsImpl method updateFunction.

@Override
public void updateFunction(final String tenant, final String namespace, final String functionName, final InputStream uploadedInputStream, final FormDataContentDisposition fileDetail, final String functionPkgUrl, final FunctionConfig functionConfig, final String clientRole, AuthenticationDataSource clientAuthenticationDataHttps, UpdateOptionsImpl updateOptions) {
    if (!isWorkerServiceAvailable()) {
        throwUnavailableException();
    }
    if (tenant == null) {
        throw new RestException(Response.Status.BAD_REQUEST, "Tenant is not provided");
    }
    if (namespace == null) {
        throw new RestException(Response.Status.BAD_REQUEST, "Namespace is not provided");
    }
    if (functionName == null) {
        throw new RestException(Response.Status.BAD_REQUEST, "Function name is not provided");
    }
    if (functionConfig == null) {
        throw new RestException(Response.Status.BAD_REQUEST, "Function config is not provided");
    }
    try {
        if (!isAuthorizedRole(tenant, namespace, clientRole, clientAuthenticationDataHttps)) {
            log.error("{}/{}/{} Client [{}] is not authorized to update {}", tenant, namespace, functionName, clientRole, ComponentTypeUtils.toString(componentType));
            throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
        }
    } catch (PulsarAdminException e) {
        log.error("{}/{}/{} Failed to authorize [{}]", tenant, namespace, functionName, e);
        throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
    }
    FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();
    if (!functionMetaDataManager.containsFunction(tenant, namespace, functionName)) {
        throw new RestException(Response.Status.BAD_REQUEST, String.format("%s %s doesn't exist", ComponentTypeUtils.toString(componentType), functionName));
    }
    Function.FunctionMetaData existingComponent = functionMetaDataManager.getFunctionMetaData(tenant, namespace, functionName);
    if (!InstanceUtils.calculateSubjectType(existingComponent.getFunctionDetails()).equals(componentType)) {
        log.error("{}/{}/{} is not a {}", tenant, namespace, functionName, ComponentTypeUtils.toString(componentType));
        throw new RestException(Response.Status.NOT_FOUND, String.format("%s %s doesn't exist", ComponentTypeUtils.toString(componentType), functionName));
    }
    FunctionConfig existingFunctionConfig = FunctionConfigUtils.convertFromDetails(existingComponent.getFunctionDetails());
    // The rest end points take precedence over whatever is there in function config
    functionConfig.setTenant(tenant);
    functionConfig.setNamespace(namespace);
    functionConfig.setName(functionName);
    FunctionConfig mergedConfig;
    try {
        mergedConfig = FunctionConfigUtils.validateUpdate(existingFunctionConfig, functionConfig);
    } catch (Exception e) {
        throw new RestException(Response.Status.BAD_REQUEST, e.getMessage());
    }
    if (existingFunctionConfig.equals(mergedConfig) && isBlank(functionPkgUrl) && uploadedInputStream == null) {
        log.error("{}/{}/{} Update contains no changes", tenant, namespace, functionName);
        throw new RestException(Response.Status.BAD_REQUEST, "Update contains no change");
    }
    Function.FunctionDetails functionDetails = null;
    File componentPackageFile = null;
    try {
        // validate parameters
        try {
            if (isNotBlank(functionPkgUrl)) {
                if (Utils.hasPackageTypePrefix(functionPkgUrl)) {
                    componentPackageFile = downloadPackageFile(functionName);
                } else {
                    try {
                        componentPackageFile = FunctionCommon.extractFileFromPkgURL(functionPkgUrl);
                    } catch (Exception e) {
                        throw new IllegalArgumentException(String.format("Encountered error \"%s\" " + "when getting %s package from %s", e.getMessage(), ComponentTypeUtils.toString(componentType), functionPkgUrl));
                    }
                }
                functionDetails = validateUpdateRequestParams(tenant, namespace, functionName, mergedConfig, componentPackageFile);
            } else if (existingComponent.getPackageLocation().getPackagePath().startsWith(Utils.FILE) || existingComponent.getPackageLocation().getPackagePath().startsWith(Utils.HTTP)) {
                try {
                    componentPackageFile = FunctionCommon.extractFileFromPkgURL(existingComponent.getPackageLocation().getPackagePath());
                } catch (Exception e) {
                    throw new IllegalArgumentException(String.format("Encountered error \"%s\" " + "when getting %s package from %s", e.getMessage(), ComponentTypeUtils.toString(componentType), functionPkgUrl));
                }
                functionDetails = validateUpdateRequestParams(tenant, namespace, functionName, mergedConfig, componentPackageFile);
            } else if (uploadedInputStream != null) {
                componentPackageFile = WorkerUtils.dumpToTmpFile(uploadedInputStream);
                functionDetails = validateUpdateRequestParams(tenant, namespace, functionName, mergedConfig, componentPackageFile);
            } else if (existingComponent.getPackageLocation().getPackagePath().startsWith(Utils.BUILTIN)) {
                functionDetails = validateUpdateRequestParams(tenant, namespace, functionName, mergedConfig, componentPackageFile);
                if (!isFunctionCodeBuiltin(functionDetails) && (componentPackageFile == null || fileDetail == null)) {
                    throw new IllegalArgumentException(ComponentTypeUtils.toString(componentType) + " Package is not provided");
                }
            } else {
                componentPackageFile = FunctionCommon.createPkgTempFile();
                componentPackageFile.deleteOnExit();
                WorkerUtils.downloadFromBookkeeper(worker().getDlogNamespace(), componentPackageFile, existingComponent.getPackageLocation().getPackagePath());
                functionDetails = validateUpdateRequestParams(tenant, namespace, functionName, mergedConfig, componentPackageFile);
            }
        } catch (Exception e) {
            log.error("Invalid update {} request @ /{}/{}/{}", ComponentTypeUtils.toString(componentType), tenant, namespace, functionName, e);
            throw new RestException(Response.Status.BAD_REQUEST, e.getMessage());
        }
        try {
            worker().getFunctionRuntimeManager().getRuntimeFactory().doAdmissionChecks(functionDetails);
        } catch (Exception e) {
            log.error("Updated {} {}/{}/{} cannot be submitted to runtime factory", ComponentTypeUtils.toString(componentType), tenant, namespace, functionName);
            throw new RestException(Response.Status.BAD_REQUEST, String.format("%s %s cannot be admitted:- %s", ComponentTypeUtils.toString(componentType), functionName, e.getMessage()));
        }
        // merge from existing metadata
        Function.FunctionMetaData.Builder functionMetaDataBuilder = Function.FunctionMetaData.newBuilder().mergeFrom(existingComponent).setFunctionDetails(functionDetails);
        // update auth data if need
        if (worker().getWorkerConfig().isAuthenticationEnabled()) {
            Function.FunctionDetails finalFunctionDetails = functionDetails;
            worker().getFunctionRuntimeManager().getRuntimeFactory().getAuthProvider().ifPresent(functionAuthProvider -> {
                if (clientAuthenticationDataHttps != null && updateOptions != null && updateOptions.isUpdateAuthData()) {
                    // get existing auth data if it exists
                    Optional<FunctionAuthData> existingFunctionAuthData = Optional.empty();
                    if (functionMetaDataBuilder.hasFunctionAuthSpec()) {
                        existingFunctionAuthData = Optional.ofNullable(getFunctionAuthData(Optional.ofNullable(functionMetaDataBuilder.getFunctionAuthSpec())));
                    }
                    try {
                        Optional<FunctionAuthData> newFunctionAuthData = functionAuthProvider.updateAuthData(finalFunctionDetails, existingFunctionAuthData, clientAuthenticationDataHttps);
                        if (newFunctionAuthData.isPresent()) {
                            functionMetaDataBuilder.setFunctionAuthSpec(Function.FunctionAuthenticationSpec.newBuilder().setData(ByteString.copyFrom(newFunctionAuthData.get().getData())).build());
                        } else {
                            functionMetaDataBuilder.clearFunctionAuthSpec();
                        }
                    } catch (Exception e) {
                        log.error("Error updating authentication data for {} {}/{}/{}", ComponentTypeUtils.toString(componentType), tenant, namespace, functionName, e);
                        throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, String.format("Error caching authentication data for %s %s:- %s", ComponentTypeUtils.toString(componentType), functionName, e.getMessage()));
                    }
                }
            });
        }
        Function.PackageLocationMetaData.Builder packageLocationMetaDataBuilder;
        if (isNotBlank(functionPkgUrl) || uploadedInputStream != null) {
            try {
                packageLocationMetaDataBuilder = getFunctionPackageLocation(functionMetaDataBuilder.build(), functionPkgUrl, fileDetail, componentPackageFile);
            } catch (Exception e) {
                log.error("Failed process {} {}/{}/{} package: ", ComponentTypeUtils.toString(componentType), tenant, namespace, functionName, e);
                throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
            }
        } else {
            packageLocationMetaDataBuilder = Function.PackageLocationMetaData.newBuilder().mergeFrom(existingComponent.getPackageLocation());
        }
        functionMetaDataBuilder.setPackageLocation(packageLocationMetaDataBuilder);
        updateRequest(existingComponent, functionMetaDataBuilder.build());
    } finally {
        if (componentPackageFile != null && componentPackageFile.exists()) {
            if ((functionPkgUrl != null && !functionPkgUrl.startsWith(Utils.FILE)) || uploadedInputStream != null) {
                componentPackageFile.delete();
            }
        }
    }
}
Also used : FunctionConfig(org.apache.pulsar.common.functions.FunctionConfig) RestException(org.apache.pulsar.common.util.RestException) RestUtils.throwUnavailableException(org.apache.pulsar.functions.worker.rest.RestUtils.throwUnavailableException) RestException(org.apache.pulsar.common.util.RestException) PulsarAdminException(org.apache.pulsar.client.admin.PulsarAdminException) IOException(java.io.IOException) WebApplicationException(javax.ws.rs.WebApplicationException) Function(org.apache.pulsar.functions.proto.Function) FunctionMetaDataManager(org.apache.pulsar.functions.worker.FunctionMetaDataManager) FunctionAuthData(org.apache.pulsar.functions.auth.FunctionAuthData) FunctionAuthUtils.getFunctionAuthData(org.apache.pulsar.functions.auth.FunctionAuthUtils.getFunctionAuthData) PulsarAdminException(org.apache.pulsar.client.admin.PulsarAdminException) File(java.io.File)

Example 23 with RestException

use of org.apache.pulsar.common.util.RestException in project pulsar by apache.

the class FunctionsImpl method getFunctionInstanceStatus.

/**
 * Get status of a function instance.  If this worker is not running the function instance,
 * @param tenant the tenant the function belongs to
 * @param namespace the namespace the function belongs to
 * @param componentName the function name
 * @param instanceId the function instance id
 * @return the function status
 */
@Override
public FunctionStatus.FunctionInstanceStatus.FunctionInstanceStatusData getFunctionInstanceStatus(final String tenant, final String namespace, final String componentName, final String instanceId, final URI uri, final String clientRole, final AuthenticationDataSource clientAuthenticationDataHttps) {
    // validate parameters
    componentInstanceStatusRequestValidate(tenant, namespace, componentName, Integer.parseInt(instanceId), clientRole, clientAuthenticationDataHttps);
    FunctionStatus.FunctionInstanceStatus.FunctionInstanceStatusData functionInstanceStatusData;
    try {
        functionInstanceStatusData = new GetFunctionStatus().getComponentInstanceStatus(tenant, namespace, componentName, Integer.parseInt(instanceId), uri);
    } catch (WebApplicationException we) {
        throw we;
    } catch (Exception e) {
        log.error("{}/{}/{} Got Exception Getting Status", tenant, namespace, componentName, e);
        throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
    }
    return functionInstanceStatusData;
}
Also used : WebApplicationException(javax.ws.rs.WebApplicationException) RestException(org.apache.pulsar.common.util.RestException) RestUtils.throwUnavailableException(org.apache.pulsar.functions.worker.rest.RestUtils.throwUnavailableException) RestException(org.apache.pulsar.common.util.RestException) PulsarAdminException(org.apache.pulsar.client.admin.PulsarAdminException) IOException(java.io.IOException) WebApplicationException(javax.ws.rs.WebApplicationException)

Example 24 with RestException

use of org.apache.pulsar.common.util.RestException in project pulsar by apache.

the class FunctionsImpl method updateFunctionOnWorkerLeader.

@Override
public void updateFunctionOnWorkerLeader(final String tenant, final String namespace, final String functionName, final InputStream uploadedInputStream, final boolean delete, URI uri, final String clientRole, AuthenticationDataSource authenticationData) {
    if (!isWorkerServiceAvailable()) {
        throwUnavailableException();
    }
    if (worker().getWorkerConfig().isAuthorizationEnabled()) {
        if (!isSuperUser(clientRole, authenticationData)) {
            log.error("{}/{}/{} Client [{}] is not superuser to update on worker leader {}", tenant, namespace, functionName, clientRole, ComponentTypeUtils.toString(componentType));
            throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
        }
    }
    if (tenant == null) {
        throw new RestException(Response.Status.BAD_REQUEST, "Tenant is not provided");
    }
    if (namespace == null) {
        throw new RestException(Response.Status.BAD_REQUEST, "Namespace is not provided");
    }
    if (functionName == null) {
        throw new RestException(Response.Status.BAD_REQUEST, "Function name is not provided");
    }
    Function.FunctionMetaData functionMetaData;
    try {
        functionMetaData = Function.FunctionMetaData.parseFrom(uploadedInputStream);
    } catch (IOException e) {
        throw new RestException(Response.Status.BAD_REQUEST, "Corrupt Function MetaData");
    }
    // Redirect if we are not the leader
    if (!worker().getLeaderService().isLeader()) {
        WorkerInfo workerInfo = worker().getMembershipManager().getLeader();
        if (workerInfo.getWorkerId().equals(worker().getWorkerConfig().getWorkerId())) {
            throw new RestException(Response.Status.SERVICE_UNAVAILABLE, "Leader not yet ready. Please retry again");
        }
        URI redirect = UriBuilder.fromUri(uri).host(workerInfo.getWorkerHostname()).port(workerInfo.getPort()).build();
        throw new WebApplicationException(Response.temporaryRedirect(redirect).build());
    }
    // Its possible that we are not the leader anymore. That will be taken care of by FunctionMetaDataManager
    FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();
    try {
        functionMetaDataManager.updateFunctionOnLeader(functionMetaData, delete);
    } catch (IllegalStateException e) {
        throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
    } catch (IllegalArgumentException e) {
        throw new RestException(Response.Status.BAD_REQUEST, e.getMessage());
    }
}
Also used : Function(org.apache.pulsar.functions.proto.Function) WebApplicationException(javax.ws.rs.WebApplicationException) FunctionMetaDataManager(org.apache.pulsar.functions.worker.FunctionMetaDataManager) RestException(org.apache.pulsar.common.util.RestException) WorkerInfo(org.apache.pulsar.common.functions.WorkerInfo) IOException(java.io.IOException) URI(java.net.URI)

Example 25 with RestException

use of org.apache.pulsar.common.util.RestException in project pulsar by apache.

the class FunctionsImplV2 method updateFunction.

@Override
public Response updateFunction(String tenant, String namespace, String functionName, InputStream uploadedInputStream, FormDataContentDisposition fileDetail, String functionPkgUrl, String functionDetailsJson, String clientRole) {
    Function.FunctionDetails.Builder functionDetailsBuilder = Function.FunctionDetails.newBuilder();
    try {
        FunctionCommon.mergeJson(functionDetailsJson, functionDetailsBuilder);
    } catch (IOException e) {
        throw new RestException(Response.Status.BAD_REQUEST, e.getMessage());
    }
    FunctionConfig functionConfig = FunctionConfigUtils.convertFromDetails(functionDetailsBuilder.build());
    delegate.updateFunction(tenant, namespace, functionName, uploadedInputStream, fileDetail, functionPkgUrl, functionConfig, clientRole, null, null);
    return Response.ok().build();
}
Also used : FunctionConfig(org.apache.pulsar.common.functions.FunctionConfig) RestException(org.apache.pulsar.common.util.RestException) IOException(java.io.IOException)

Aggregations

RestException (org.apache.pulsar.common.util.RestException)178 IOException (java.io.IOException)101 PulsarAdminException (org.apache.pulsar.client.admin.PulsarAdminException)101 WebApplicationException (javax.ws.rs.WebApplicationException)66 FunctionMetaDataManager (org.apache.pulsar.functions.worker.FunctionMetaDataManager)65 RestUtils.throwUnavailableException (org.apache.pulsar.functions.worker.rest.RestUtils.throwUnavailableException)54 Test (org.testng.annotations.Test)45 File (java.io.File)41 FunctionMetaData (org.apache.pulsar.functions.proto.Function.FunctionMetaData)36 Function (org.apache.pulsar.functions.proto.Function)33 Namespace (org.apache.distributedlog.api.namespace.Namespace)21 SchemaSerializationException (org.apache.pulsar.client.api.SchemaSerializationException)21 ExecutionException (java.util.concurrent.ExecutionException)18 NamespaceNotFoundException (org.apache.bookkeeper.clients.exceptions.NamespaceNotFoundException)18 StreamNotFoundException (org.apache.bookkeeper.clients.exceptions.StreamNotFoundException)18 FunctionAuthData (org.apache.pulsar.functions.auth.FunctionAuthData)18 FunctionAuthUtils.getFunctionAuthData (org.apache.pulsar.functions.auth.FunctionAuthUtils.getFunctionAuthData)18 FunctionRuntimeManager (org.apache.pulsar.functions.worker.FunctionRuntimeManager)15 URI (java.net.URI)14 FunctionConfig (org.apache.pulsar.common.functions.FunctionConfig)12