All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.cloud.mt.subscription.ProvisioningService Maven / Gradle / Ivy

There is a newer version: 3.3.1
Show newest version
/******************************************************************************
 * © 2020 SAP SE or an SAP affiliate company. All rights reserved.            *
 ******************************************************************************/
package com.sap.cloud.mt.subscription;

import com.sap.cloud.mt.subscription.exceptions.InternalError;
import com.sap.cloud.mt.subscription.exceptions.NotFound;
import com.sap.cloud.mt.subscription.json.DeletePayload;
import com.sap.cloud.mt.subscription.json.SubscriptionPayload;
import com.sap.cloud.mt.tools.api.ServiceCall;
import com.sap.cloud.mt.tools.api.ServiceEndpoint;
import com.sap.cloud.mt.tools.api.ServiceResponse;
import com.sap.cloud.mt.tools.exception.InternalException;
import com.sap.cloud.mt.tools.exception.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static com.sap.cloud.mt.subscription.MtxTools.extractJobId;
import static com.sap.cloud.mt.tools.api.CodeTools.code;
import static org.apache.http.HttpStatus.SC_ACCEPTED;
import static org.apache.http.HttpStatus.SC_BAD_GATEWAY;
import static org.apache.http.HttpStatus.SC_GATEWAY_TIMEOUT;
import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
import static org.apache.http.HttpStatus.SC_NOT_FOUND;
import static org.apache.http.HttpStatus.SC_NO_CONTENT;
import static org.apache.http.HttpStatus.SC_OK;
import static org.apache.http.HttpStatus.SC_SERVICE_UNAVAILABLE;

public class ProvisioningService {
    public static final String MTX_PROVISIONING_SERVICE_DESTINATION = "com.sap.cds.mtxSidecar";
    private static final Logger logger = LoggerFactory.getLogger(ProvisioningService.class);
    private static final String PROVISIONING_ENDPOINT = "/-/cds/saas-provisioning/tenant/";
    private static final String UPGRADE_ENDPOINT = "/-/cds/saas-provisioning/upgrade";
    private static final String JOB_STATUS_ENDPOINT = "/-/cds/jobs/";
    private static final String UNEXPECTED_RETURN_CODE = "Unexpected return code ";
    private static final String PREFER = "prefer";
    private static final String RESPOND_ASYNC = "respond-async";
    private final Set retryCodes = new HashSet<>();
    private final ServiceEndpoint statusEndpoint;
    private final ServiceEndpoint subscribeEndpoint;
    private final ServiceEndpoint unsubscribeEndpoint;
    private final ServiceEndpoint upgradeEndpoint;
    private final ServiceSpecification serviceSpecification;

    public ProvisioningService(ServiceSpecification serviceSpecification) throws InternalError {
        this.serviceSpecification = serviceSpecification;
        retryCodes.add(SC_BAD_GATEWAY);
        retryCodes.add(SC_GATEWAY_TIMEOUT);
        retryCodes.add(SC_INTERNAL_SERVER_ERROR);
        retryCodes.add(SC_SERVICE_UNAVAILABLE);
        try {
            statusEndpoint = ServiceEndpoint.create()
                    .destinationName(MTX_PROVISIONING_SERVICE_DESTINATION)
                    .path(JOB_STATUS_ENDPOINT)
                    .returnCodeChecker(c -> {
                        if (c == SC_NOT_FOUND) {
                            return new NotFound("Job id not known");
                        }
                        if (c != SC_OK) {
                            return new InternalError(UNEXPECTED_RETURN_CODE + c);
                        }
                        return null;
                    }).retry().forReturnCodes(retryCodes)
                    .config(serviceSpecification.getResilienceConfig())
                    .end();
            subscribeEndpoint = ServiceEndpoint.create()
                    .destinationName(MTX_PROVISIONING_SERVICE_DESTINATION)
                    .path(PROVISIONING_ENDPOINT)
                    .returnCodeChecker(c -> {
                        if (code(c).notIn(SC_ACCEPTED, SC_OK)) {
                            return new InternalError(UNEXPECTED_RETURN_CODE + c);
                        }
                        return null;
                    }).retry().forReturnCodes(retryCodes)
                    .config(serviceSpecification.getResilienceConfig())
                    .end();
            unsubscribeEndpoint = ServiceEndpoint.create()
                    .destinationName(MTX_PROVISIONING_SERVICE_DESTINATION)
                    .path(PROVISIONING_ENDPOINT)
                    .returnCodeChecker(c -> {
                        if (code(c).notIn(SC_ACCEPTED, SC_OK, SC_NO_CONTENT)) {
                            return new InternalError(UNEXPECTED_RETURN_CODE + c);
                        }
                        return null;
                    }).retry().forReturnCodes(retryCodes)
                    .config(serviceSpecification.getResilienceConfig())
                    .end();
            upgradeEndpoint = ServiceEndpoint.create()
                    .destinationName(MTX_PROVISIONING_SERVICE_DESTINATION)
                    .path(UPGRADE_ENDPOINT)
                    .returnCodeChecker(c -> {
                        if (code(c).notIn(SC_ACCEPTED, SC_OK, SC_NO_CONTENT)) {
                            return new InternalError(UNEXPECTED_RETURN_CODE + c);
                        }
                        return null;
                    }).retry().forReturnCodes(retryCodes)
                    .config(serviceSpecification.getResilienceConfig())
                    .end();
        } catch (InternalException e) {
            throw new InternalError(e);
        }
    }

    public Map determineJobStatus(String jobId) throws InternalError, NotFound {
        ServiceCall getStatus = null;
        try {
            getStatus = statusEndpoint.createServiceCall()
                    .http()
                    .get()
                    .withoutPayload()
                    .pathParameter(String.format("pollJob(ID='%s')", jobId))
                    .noQuery()
                    .enhancer(serviceSpecification.getRequestEnhancer())
                    .end();
            logger.debug("Call mtx determine status service with jobId {}", jobId);
            ServiceResponse response = getStatus.execute(Map.class); //NOSONAR
            return response.getPayload().orElse(new HashMap());
        } catch (InternalException e) {
            throw new InternalError(e);
        } catch (ServiceException e) {
            if (e.getCause() instanceof InternalError) {
                throw (InternalError) e.getCause();
            }
            if (e.getCause() instanceof NotFound) {
                throw (NotFound) e.getCause();
            }
            throw new InternalError(e);
        }
    }

    public String subscribe(String tenantId, SubscriptionPayload subscriptionPayload, ServiceCreateOptions serviceCreateOptions)
            throws InternalError {
        var sidecarPayload = Tools.getProvisioningServicePayload(subscriptionPayload, serviceCreateOptions);
        try {
            ServiceCall subscribe = subscribeEndpoint.createServiceCall()
                    .http()
                    .put()
                    .payload(sidecarPayload)
                    .pathParameter(tenantId)
                    .noQuery()
                    .enhancer(serviceSpecification.getRequestEnhancer())
                    .insertHeaderFields(getHeaderFieldsForAsyncCall(true))
                    .end();
            logger.debug("Call mtx provisioning service method subscribe for tenant {}", tenantId);
            ServiceResponse response = subscribe.execute(String.class);
            return extractJobId(response);
        } catch (InternalException e) {
            throw new InternalError(e);
        } catch (ServiceException e) {
            if (e.getCause() instanceof InternalError) {
                throw (InternalError) e.getCause();
            }
            throw new InternalError(e);
        }
    }

    public String unsubscribe(String tenantId, DeletePayload deletePayload) throws InternalError {
        var sidecarPayload = deletePayload != null ? deletePayload.getMap() : new HashMap<>();
        try {
            ServiceCall unsubscribe = unsubscribeEndpoint.createServiceCall()
                    .http()
                    .delete()
                    .payload(sidecarPayload)
                    .pathParameter(tenantId)
                    .noQuery()
                    .enhancer(serviceSpecification.getRequestEnhancer())
                    .insertHeaderFields(getHeaderFieldsForAsyncCall(true))
                    .end();
            logger.debug("Call mtx provisioning service method unsubscribe for tenant {}", tenantId);
            ServiceResponse response = unsubscribe.execute(String.class);
            return extractJobId(response);
        } catch (InternalException e) {
            throw new InternalError(e);
        } catch (ServiceException e) {
            if (e.getCause() instanceof InternalError) {
                throw (InternalError) e.getCause();
            }
            throw new InternalError(e);
        }
    }

    public Map upgrade(Set tenantIds, boolean asynchronously) throws InternalError {
        Map upgradePayload = new HashMap<>();
        if (tenantIds != null && !tenantIds.isEmpty()) {
            upgradePayload.put("tenants", tenantIds);
        }
        try {
            ServiceCall upgrade = upgradeEndpoint.createServiceCall()
                    .http()
                    .post()
                    .payload(upgradePayload)
                    .noPathParameter()
                    .noQuery()
                    .enhancer(serviceSpecification.getRequestEnhancer())
                    .insertHeaderFields(getHeaderFieldsForAsyncCall(asynchronously))
                    .end();
            logger.debug("Call mtx provisioning service method upgrade all for tenants {}", tenantIds);
            ServiceResponse response = upgrade.execute(Map.class);//NOSONAR
            return response.getPayload().orElse(new HashMap());
        } catch (InternalException e) {
            throw new InternalError(e);
        } catch (ServiceException e) {
            if (e.getCause() instanceof InternalError) {
                throw (InternalError) e.getCause();
            }
            throw new InternalError(e);
        }
    }

    private Map getHeaderFieldsForAsyncCall(boolean asynchronous) {
        Map headerFields = new HashMap<>();
        if (asynchronous) {
            headerFields.put(PREFER, RESPOND_ASYNC);
        }
        return headerFields;
    }

    public ServiceSpecification getServiceSpecification() {
        return serviceSpecification;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy