diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java index e9306c64df34..8a9d56935cfe 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java @@ -749,6 +749,7 @@ private Permissions() { public static final String API_WEBSUB_GATEWAY_ENDPOINT = "GatewayWebSubEndpoint"; public static final String API_GATEWAY_TYPE = "GatewayType"; public static final String API_GATEWAY_TYPE_SYNAPSE = "Synapse"; + public static final String API_GATEWAY_TYPE_ENVOY = "Envoy"; public static final String API_GATEWAY_TYPE_REGULAR = "Regular"; public static final String API_GATEWAY_TYPE_APK = "APK"; public static final String API_GATEWAY_VIRTUAL_HOSTS = "VirtualHosts"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml index 0183499f3c00..e831c37dd589 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml @@ -4013,6 +4013,12 @@ paths: schema: type: boolean default: false + - name: gatewayEnvironment + in: query + description: | + Gateway environment of the exported APIs + schema: + type: string responses: 200: description: | @@ -8167,7 +8173,7 @@ paths: x-code-samples: - lang: Curl source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" - -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F policyDefinitionFile=@setHeader.j2 + -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F synapsePolicyDefinitionFile=@setHeader.j2 "https://127.0.0.1:9443/api/am/publisher/v4/apis/96077508-fd01-4fae-bc64-5de0e2baf43c/operation-policies"' @@ -8411,7 +8417,7 @@ paths: x-code-samples: - lang: Curl source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" - -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F policyDefinitionFile=@setHeader.j2 + -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F synapsePolicyDefinitionFile=@setHeader.j2 "https://127.0.0.1:9443/api/am/publisher/v4/operation-policies"' /operation-policies/export: diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApi.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApi.java index 1b1b92debca2..3a350905eaf8 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApi.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApi.java @@ -615,8 +615,8 @@ public Response editCommentOfAPI(@ApiParam(value = "Comment Id ",required=true) @ApiResponse(code = 200, message = "OK. Export Successful. ", response = File.class), @ApiResponse(code = 404, message = "Not Found. The specified resource does not exist.", response = ErrorDTO.class), @ApiResponse(code = 500, message = "Internal Server Error.", response = ErrorDTO.class) }) - public Response exportAPI( @ApiParam(value = "UUID of the API") @QueryParam("apiId") String apiId, @ApiParam(value = "API Name ") @QueryParam("name") String name, @ApiParam(value = "Version of the API ") @QueryParam("version") String version, @ApiParam(value = "Revision number of the API artifact ") @QueryParam("revisionNumber") String revisionNumber, @ApiParam(value = "Provider name of the API ") @QueryParam("providerName") String providerName, @ApiParam(value = "Format of output documents. Can be YAML or JSON. ", allowableValues="JSON, YAML") @QueryParam("format") String format, @ApiParam(value = "Preserve API Status during export ") @QueryParam("preserveStatus") Boolean preserveStatus, @ApiParam(value = "Export the latest revision of the API ", defaultValue="false") @DefaultValue("false") @QueryParam("latestRevision") Boolean latestRevision) throws APIManagementException{ - return delegate.exportAPI(apiId, name, version, revisionNumber, providerName, format, preserveStatus, latestRevision, securityContext); + public Response exportAPI( @ApiParam(value = "UUID of the API") @QueryParam("apiId") String apiId, @ApiParam(value = "API Name ") @QueryParam("name") String name, @ApiParam(value = "Version of the API ") @QueryParam("version") String version, @ApiParam(value = "Revision number of the API artifact ") @QueryParam("revisionNumber") String revisionNumber, @ApiParam(value = "Provider name of the API ") @QueryParam("providerName") String providerName, @ApiParam(value = "Format of output documents. Can be YAML or JSON. ", allowableValues="JSON, YAML") @QueryParam("format") String format, @ApiParam(value = "Preserve API Status during export ") @QueryParam("preserveStatus") Boolean preserveStatus, @ApiParam(value = "Export the latest revision of the API ", defaultValue="false") @DefaultValue("false") @QueryParam("latestRevision") Boolean latestRevision, @ApiParam(value = "Gateway environment of the exported APIs ") @QueryParam("gatewayEnvironment") String gatewayEnvironment) throws APIManagementException{ + return delegate.exportAPI(apiId, name, version, revisionNumber, providerName, format, preserveStatus, latestRevision, gatewayEnvironment, securityContext); } @POST diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApiService.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApiService.java index 109eed40030d..49182e6d6144 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApiService.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApiService.java @@ -90,7 +90,7 @@ public interface ApisApiService { public Response deleteComment(String commentId, String apiId, String ifMatch, MessageContext messageContext) throws APIManagementException; public Response deployAPIRevision(String apiId, String revisionId, List apIRevisionDeploymentDTO, MessageContext messageContext) throws APIManagementException; public Response editCommentOfAPI(String commentId, String apiId, PatchRequestBodyDTO patchRequestBodyDTO, MessageContext messageContext) throws APIManagementException; - public Response exportAPI(String apiId, String name, String version, String revisionNumber, String providerName, String format, Boolean preserveStatus, Boolean latestRevision, MessageContext messageContext) throws APIManagementException; + public Response exportAPI(String apiId, String name, String version, String revisionNumber, String providerName, String format, Boolean preserveStatus, Boolean latestRevision, String gatewayEnvironment, MessageContext messageContext) throws APIManagementException; public Response generateInternalAPIKey(String apiId, MessageContext messageContext) throws APIManagementException; public Response generateMockScripts(String apiId, String ifNoneMatch, MessageContext messageContext) throws APIManagementException; public Response getAPI(String apiId, String xWSO2Tenant, String ifNoneMatch, MessageContext messageContext) throws APIManagementException; diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java index f54d509c1006..5f58b7f26d74 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java @@ -31,7 +31,6 @@ import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition; import org.apache.cxf.phase.PhaseInterceptorChain; -import org.apache.http.HttpStatus; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; @@ -52,13 +51,14 @@ import org.wso2.carbon.apimgt.impl.certificatemgt.ResponseCode; import org.wso2.carbon.apimgt.impl.dao.ApiMgtDAO; import org.wso2.carbon.apimgt.impl.definitions.*; +import org.wso2.carbon.apimgt.impl.dto.RuntimeArtifactDto; import org.wso2.carbon.apimgt.impl.dto.WorkflowDTO; +import org.wso2.carbon.apimgt.impl.gatewayartifactsynchronizer.RuntimeArtifactGeneratorUtil; import org.wso2.carbon.apimgt.impl.importexport.APIImportExportException; import org.wso2.carbon.apimgt.impl.importexport.ExportFormat; import org.wso2.carbon.apimgt.impl.importexport.ImportExportAPI; import org.wso2.carbon.apimgt.impl.importexport.utils.APIImportExportUtil; import org.wso2.carbon.apimgt.impl.importexport.utils.CommonUtil; -import org.wso2.carbon.apimgt.impl.internal.ServiceReferenceHolder; import org.wso2.carbon.apimgt.impl.restapi.CommonUtils; import org.wso2.carbon.apimgt.impl.restapi.publisher.ApisApiServiceImplUtils; import org.wso2.carbon.apimgt.impl.restapi.publisher.OperationPoliciesApiServiceImplUtils; @@ -79,11 +79,14 @@ import org.wso2.carbon.apimgt.rest.api.util.utils.RestApiUtil; import org.wso2.carbon.core.util.CryptoException; import org.wso2.carbon.core.util.CryptoUtil; +import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; import java.io.*; import java.net.*; +import java.nio.file.Files; import java.util.*; import static org.wso2.carbon.apimgt.api.ExceptionCodes.API_VERSION_ALREADY_EXISTS; @@ -3364,36 +3367,71 @@ public Response createNewAPIVersion(String newVersion, String apiId, Boolean def * WSDL and sequences are exported. This service generates a zipped archive which contains all the above mentioned * resources for a given API. * - * @param apiId UUID of an API - * @param name Name of the API that needs to be exported - * @param version Version of the API that needs to be exported - * @param providerName Provider name of the API that needs to be exported - * @param format Format of output documents. Can be YAML or JSON - * @param preserveStatus Preserve API status on export + * @param apiId UUID of an API + * @param name Name of the API that needs to be exported + * @param version Version of the API that needs to be exported + * @param providerName Provider name of the API that needs to be exported + * @param format Format of output documents. Can be YAML or JSON + * @param preserveStatus Preserve API status on export + * @param gatewayEnvironment * @return */ @Override public Response exportAPI(String apiId, String name, String version, String revisionNum, String providerName, String format, Boolean preserveStatus, - Boolean exportLatestRevision, MessageContext messageContext) + Boolean exportLatestRevision, String gatewayEnvironment, + MessageContext messageContext) throws APIManagementException { - //If not specified status is preserved by default - preserveStatus = preserveStatus == null || preserveStatus; + if (StringUtils.isEmpty(gatewayEnvironment)) { + //If not specified status is preserved by default + preserveStatus = preserveStatus == null || preserveStatus; - // Default export format is YAML - ExportFormat exportFormat = StringUtils.isNotEmpty(format) ? - ExportFormat.valueOf(format.toUpperCase()) : - ExportFormat.YAML; - try { + // Default export format is YAML + ExportFormat exportFormat = StringUtils.isNotEmpty(format) ? + ExportFormat.valueOf(format.toUpperCase()) : + ExportFormat.YAML; + try { + String organization = RestApiUtil.getValidatedOrganization(messageContext); + ImportExportAPI importExportAPI = APIImportExportUtil.getImportExportAPI(); + File file = importExportAPI + .exportAPI(apiId, name, version, revisionNum, providerName, preserveStatus, exportFormat, + Boolean.TRUE, Boolean.FALSE, exportLatestRevision, StringUtils.EMPTY, organization); + return Response.ok(file).header(RestApiConstants.HEADER_CONTENT_DISPOSITION, + "attachment; filename=\"" + file.getName() + "\"").build(); + } catch (APIImportExportException e) { + throw new APIManagementException("Error while exporting " + RestApiConstants.RESOURCE_API, e); + } + } else { String organization = RestApiUtil.getValidatedOrganization(messageContext); - ImportExportAPI importExportAPI = APIImportExportUtil.getImportExportAPI(); - File file = importExportAPI - .exportAPI(apiId, name, version, revisionNum, providerName, preserveStatus, exportFormat, - Boolean.TRUE, Boolean.FALSE, exportLatestRevision, StringUtils.EMPTY, organization); - return Response.ok(file).header(RestApiConstants.HEADER_CONTENT_DISPOSITION, - "attachment; filename=\"" + file.getName() + "\"").build(); - } catch (APIImportExportException e) { - throw new APIManagementException("Error while exporting " + RestApiConstants.RESOURCE_API, e); + if (StringUtils.isEmpty(apiId) && (StringUtils.isNotEmpty(name) && StringUtils.isNotEmpty(version))) { + APIIdentifier apiIdentifier = new APIIdentifier(providerName, name, version); + apiId = APIUtil.getUUIDFromIdentifier(apiIdentifier, organization); + } + RuntimeArtifactDto runtimeArtifactDto; + if (StringUtils.isNotEmpty(organization) && MultitenantConstants.SUPER_TENANT_DOMAIN_NAME + .equalsIgnoreCase(organization)) { + runtimeArtifactDto = RuntimeArtifactGeneratorUtil.generateAllRuntimeArtifact(apiId, gatewayEnvironment, + APIConstants.API_GATEWAY_TYPE_ENVOY); + } else { + runtimeArtifactDto = RuntimeArtifactGeneratorUtil.generateRuntimeArtifact(apiId, gatewayEnvironment, + APIConstants.API_GATEWAY_TYPE_ENVOY, organization); + } + if (runtimeArtifactDto != null) { + if (runtimeArtifactDto.isFile()) { + File artifact = (File) runtimeArtifactDto.getArtifact(); + StreamingOutput streamingOutput = (outputStream) -> { + try { + Files.copy(artifact.toPath(), outputStream); + } finally { + Files.delete(artifact.toPath()); + } + }; + return Response.ok(streamingOutput).header(RestApiConstants.HEADER_CONTENT_DISPOSITION, + "attachment; filename=apis.zip").header(RestApiConstants.HEADER_CONTENT_TYPE, + APIConstants.APPLICATION_ZIP).build(); + } + } + throw new APIManagementException("No API Artifacts", ExceptionCodes.NO_API_ARTIFACT_FOUND); } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml index ace0086ff9e7..e831c37dd589 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml @@ -4013,6 +4013,12 @@ paths: schema: type: boolean default: false + - name: gatewayEnvironment + in: query + description: | + Gateway environment of the exported APIs + schema: + type: string responses: 200: description: | diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/resources/publisher-api.yaml index f34d23ddbc67..4dccd027a630 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/resources/publisher-api.yaml @@ -3999,6 +3999,12 @@ paths: schema: type: boolean default: false + - name: gatewayEnvironment + in: query + description: | + Gateway environment of the exported APIs + schema: + type: string responses: 200: description: |