From 57827bfcbbd38d1e52f4513660a18a44b2edd4a0 Mon Sep 17 00:00:00 2001 From: GihanAyesh Date: Tue, 24 Oct 2023 10:24:51 +0530 Subject: [PATCH] Integration test for revision deployment approval workflow --- .../clients/admin/api/openapi.yaml | 2 + .../admin/api/dto/WorkflowInfoDTO.java | 4 +- .../admin/src/main/resources/admin-api.yaml | 2 + .../clients/publisher/api/openapi.yaml | 118 ++++++++++ .../clients/publisher/docs/APIDTO.md | 1 + .../clients/publisher/docs/APIProductDTO.md | 1 + .../docs/APIRevisionDeploymentDTO.md | 11 + .../clients/publisher/docs/ApiRevisionsApi.md | 73 ++++++ .../publisher/api/v1/ApiRevisionsApi.java | 135 +++++++++++ .../clients/publisher/api/v1/dto/APIDTO.java | 31 ++- .../api/v1/dto/APIRevisionDeploymentDTO.java | 80 ++++++- .../src/main/resources/publisher-api.yaml | 53 +++++ .../test/impl/RestAPIAdminImpl.java | 25 +++ .../WorkflowApprovalExecutorTest.java | 211 ++++++++++++++++++ .../approveWorkflow/workflow-extensions.xml | 2 + 15 files changed, 746 insertions(+), 3 deletions(-) diff --git a/modules/integration/tests-common/clients/admin/api/openapi.yaml b/modules/integration/tests-common/clients/admin/api/openapi.yaml index f2c53f24bf..c763656859 100644 --- a/modules/integration/tests-common/clients/admin/api/openapi.yaml +++ b/modules/integration/tests-common/clients/admin/api/openapi.yaml @@ -5195,6 +5195,7 @@ paths: - AM_APPLICATION_DELETION - AM_API_STATE - AM_API_PRODUCT_STATE + - AM_REVISION_DEPLOYMENT type: string style: form responses: @@ -9442,6 +9443,7 @@ components: - SUBSCRIPTION_DELETION - SUBSCRIPTION_UPDATE - API_PRODUCT_STATE + - REVISION_DEPLOYMENT example: APPLICATION_CREATION type: string workflowStatus: diff --git a/modules/integration/tests-common/clients/admin/src/gen/java/org/wso2/am/integration/clients/admin/api/dto/WorkflowInfoDTO.java b/modules/integration/tests-common/clients/admin/src/gen/java/org/wso2/am/integration/clients/admin/api/dto/WorkflowInfoDTO.java index 67f1712d0b..8fb204d9e9 100644 --- a/modules/integration/tests-common/clients/admin/src/gen/java/org/wso2/am/integration/clients/admin/api/dto/WorkflowInfoDTO.java +++ b/modules/integration/tests-common/clients/admin/src/gen/java/org/wso2/am/integration/clients/admin/api/dto/WorkflowInfoDTO.java @@ -52,7 +52,9 @@ public enum WorkflowTypeEnum { SUBSCRIPTION_UPDATE("SUBSCRIPTION_UPDATE"), - API_PRODUCT_STATE("API_PRODUCT_STATE"); + API_PRODUCT_STATE("API_PRODUCT_STATE"), + + REVISION_DEPLOYMENT("REVISION_DEPLOYMENT"); private String value; diff --git a/modules/integration/tests-common/clients/admin/src/main/resources/admin-api.yaml b/modules/integration/tests-common/clients/admin/src/main/resources/admin-api.yaml index 69131316c6..98f9152052 100644 --- a/modules/integration/tests-common/clients/admin/src/main/resources/admin-api.yaml +++ b/modules/integration/tests-common/clients/admin/src/main/resources/admin-api.yaml @@ -3031,6 +3031,7 @@ paths: - AM_APPLICATION_DELETION - AM_API_STATE - AM_API_PRODUCT_STATE + - AM_REVISION_DEPLOYMENT responses: 200: description: | @@ -5815,6 +5816,7 @@ components: - SUBSCRIPTION_DELETION - SUBSCRIPTION_UPDATE - API_PRODUCT_STATE + - REVISION_DEPLOYMENT workflowStatus: type: string description: | diff --git a/modules/integration/tests-common/clients/publisher/api/openapi.yaml b/modules/integration/tests-common/clients/publisher/api/openapi.yaml index b4ce30723f..46920472c1 100644 --- a/modules/integration/tests-common/clients/publisher/api/openapi.yaml +++ b/modules/integration/tests-common/clients/publisher/api/openapi.yaml @@ -3129,6 +3129,83 @@ paths: source: 'curl -k -X POST -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" "https://127.0.0.1:9443/api/am/publisher/v4/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/restore-revision?revisionId=e0824883-3e86-403a-aec1-22bbc454eb7c"' x-accepts: application/json + /apis/{apiId}/cancel-revision-workflow/{revisionId}/{envName}: + delete: + description: | + This operation can be used to remove pending revision deployment requests that are in pending state + operationId: deleteAPIRevisionDeploymentPendingTask + parameters: + - description: | + **API ID** consisting of the **UUID** of the API. + explode: false + in: path + name: apiId + required: true + schema: + type: string + style: simple + - description: | + Revision ID of an API + explode: false + in: path + name: revisionId + required: true + schema: + type: string + style: simple + - description: | + Environment name of an Revision + explode: false + in: path + name: envName + required: true + schema: + type: string + style: simple + responses: + "200": + content: {} + description: | + OK. + Revision deployment pending task removed successfully. + "404": + content: + application/json: + example: + code: 404 + message: Not Found + description: The specified resource does not exist + moreInfo: "" + error: [] + schema: + $ref: '#/components/schemas/Error' + description: Not Found. The specified resource does not exist. + "412": + content: + application/json: + example: + code: 412 + message: Precondition Failed + description: The request has not been performed because one of the + preconditions is not met + moreInfo: "" + error: [] + schema: + $ref: '#/components/schemas/Error' + description: Precondition Failed. The request has not been performed because + one of the preconditions is not met. + security: + - OAuth2Security: + - apim:api_publish + - apim:api_manage + summary: Delete Pending Revision Deployment Workflow Tasks + tags: + - API Revisions + x-code-samples: + - lang: Curl + source: 'curl -k -X DELETE -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + "https://127.0.0.1:9443/api/am/publisher/v4/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/cancel-revision-workflow/e0824883-3e86-403a-aec1-22bbc454eb7c/Default"' + x-accepts: application/json /apis/import-service: post: description: This operation can be used to create an API from a Service from @@ -15161,6 +15238,16 @@ components: schema: type: string style: simple + envName: + description: | + Environment name of an Revision + explode: false + in: path + name: envName + required: true + schema: + type: string + style: simple revisionId-Q: description: | Revision ID of an API @@ -16020,6 +16107,7 @@ components: createdTime: createdTime id: 01234567-0123-0123-0123-012345678901 wsdlUrl: /apimgt/applicationdata/wsdls/admin--soap1.wsdl + apiKeyHeader: apiKey accessControlRoles: [] audience: PUBLIC visibility: PUBLIC @@ -16333,6 +16421,12 @@ components: example: Authorization pattern: (^[^~!@#;:%^*()+={}|\\<>"',&$\s+]*$) type: string + apiKeyHeader: + description: | + Name of the API key header used for invoking the API. If it is not set, default value `apiKey` will be used. + example: apiKey + pattern: (^[^~!@#;:%^*()+={}|\\<>"',&$\s+]*$) + type: string securityScheme: description: | Types of API security, the current API secured with. It can be either OAuth2 or mutual SSL or both. If @@ -16637,12 +16731,14 @@ components: deployedTime: deployedTime name: default successDeployedTime: successDeployedTime + status: CREATED - revisionUuid: c26b2b9b-4632-4ca4-b6f3-521c8863990c vhost: mg.wso2.com displayOnDevportal: true deployedTime: deployedTime name: default successDeployedTime: successDeployedTime + status: CREATED apiInfo: id: 01234567-0123-0123-0123-012345678901 properties: @@ -16694,12 +16790,14 @@ components: deployedTime: deployedTime name: default successDeployedTime: successDeployedTime + status: CREATED - revisionUuid: c26b2b9b-4632-4ca4-b6f3-521c8863990c vhost: mg.wso2.com displayOnDevportal: true deployedTime: deployedTime name: default successDeployedTime: successDeployedTime + status: CREATED apiInfo: id: 01234567-0123-0123-0123-012345678901 - displayName: REVISION 1 @@ -16713,12 +16811,14 @@ components: deployedTime: deployedTime name: default successDeployedTime: successDeployedTime + status: CREATED - revisionUuid: c26b2b9b-4632-4ca4-b6f3-521c8863990c vhost: mg.wso2.com displayOnDevportal: true deployedTime: deployedTime name: default successDeployedTime: successDeployedTime + status: CREATED apiInfo: id: 01234567-0123-0123-0123-012345678901 properties: @@ -16741,12 +16841,14 @@ components: deployedTime: deployedTime name: default successDeployedTime: successDeployedTime + status: CREATED - revisionUuid: c26b2b9b-4632-4ca4-b6f3-521c8863990c vhost: mg.wso2.com displayOnDevportal: true deployedTime: deployedTime name: default successDeployedTime: successDeployedTime + status: CREATED properties: list: items: @@ -16761,6 +16863,7 @@ components: deployedTime: deployedTime name: default successDeployedTime: successDeployedTime + status: CREATED properties: revisionUuid: example: c26b2b9b-4632-4ca4-b6f3-521c8863990c @@ -16772,6 +16875,14 @@ components: maxLength: 255 minLength: 1 type: string + status: + default: CREATED + enum: + - CREATED + - APPROVED + - REJECTED + example: CREATED + type: string vhost: example: mg.wso2.com maxLength: 255 @@ -16960,6 +17071,7 @@ components: name: name value: value revisionedApiProductId: 01234567-0123-0123-0123-012345678901 + apiKeyHeader: apiKey accessControlRoles: [] lastUpdatedTimestamp: lastUpdatedTimestamp hasThumbnail: false @@ -17142,6 +17254,12 @@ components: in tenant or system level will be used. example: Authorization type: string + apiKeyHeader: + description: | + Name of the API key header used for invoking the API. If it is not set, default value `apiKey` will be used. + example: apiKey + pattern: (^[^~!@#;:%^*()+={}|\\<>"',&$\s+]*$) + type: string securityScheme: description: | Types of API security, the current API secured with. It can be either OAuth2 or mutual SSL or both. If diff --git a/modules/integration/tests-common/clients/publisher/docs/APIDTO.md b/modules/integration/tests-common/clients/publisher/docs/APIDTO.md index 1b635027e6..a3a8119b18 100644 --- a/modules/integration/tests-common/clients/publisher/docs/APIDTO.md +++ b/modules/integration/tests-common/clients/publisher/docs/APIDTO.md @@ -31,6 +31,7 @@ Name | Type | Description | Notes **policies** | **List<String>** | | [optional] **apiThrottlingPolicy** | **String** | The API level throttling policy selected for the particular API | [optional] **authorizationHeader** | **String** | Name of the Authorization header used for invoking the API. If it is not set, Authorization header name specified in tenant or system level will be used. | [optional] +**apiKeyHeader** | **String** | Name of the API key header used for invoking the API. If it is not set, default value `apiKey` will be used. | [optional] **securityScheme** | **List<String>** | Types of API security, the current API secured with. It can be either OAuth2 or mutual SSL or both. If it is not set OAuth2 will be set as the security for the current API. | [optional] **maxTps** | [**APIMaxTpsDTO**](APIMaxTpsDTO.md) | | [optional] **visibility** | [**VisibilityEnum**](#VisibilityEnum) | The visibility level of the API. Accepts one of the following. PUBLIC, PRIVATE, RESTRICTED. | [optional] diff --git a/modules/integration/tests-common/clients/publisher/docs/APIProductDTO.md b/modules/integration/tests-common/clients/publisher/docs/APIProductDTO.md index 91ea7557aa..8007b719d2 100644 --- a/modules/integration/tests-common/clients/publisher/docs/APIProductDTO.md +++ b/modules/integration/tests-common/clients/publisher/docs/APIProductDTO.md @@ -30,6 +30,7 @@ Name | Type | Description | Notes **policies** | **List<String>** | | [optional] **apiThrottlingPolicy** | **String** | The API level throttling policy selected for the particular API Product | [optional] **authorizationHeader** | **String** | Name of the Authorization header used for invoking the API. If it is not set, Authorization header name specified in tenant or system level will be used. | [optional] +**apiKeyHeader** | **String** | Name of the API key header used for invoking the API. If it is not set, default value `apiKey` will be used. | [optional] **securityScheme** | **List<String>** | Types of API security, the current API secured with. It can be either OAuth2 or mutual SSL or both. If it is not set OAuth2 will be set as the security for the current API. | [optional] **subscriptionAvailability** | [**SubscriptionAvailabilityEnum**](#SubscriptionAvailabilityEnum) | The subscription availability. Accepts one of the following. CURRENT_TENANT, ALL_TENANTS or SPECIFIC_TENANTS. | [optional] **subscriptionAvailableTenants** | **List<String>** | | [optional] diff --git a/modules/integration/tests-common/clients/publisher/docs/APIRevisionDeploymentDTO.md b/modules/integration/tests-common/clients/publisher/docs/APIRevisionDeploymentDTO.md index a7a8ac79e4..22e451b137 100644 --- a/modules/integration/tests-common/clients/publisher/docs/APIRevisionDeploymentDTO.md +++ b/modules/integration/tests-common/clients/publisher/docs/APIRevisionDeploymentDTO.md @@ -8,6 +8,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **revisionUuid** | **String** | | [optional] **name** | **String** | | [optional] +**status** | [**StatusEnum**](#StatusEnum) | | [optional] **vhost** | **String** | | [optional] **displayOnDevportal** | **Boolean** | | [optional] **deployedTime** | **String** | | [optional] [readonly] @@ -15,3 +16,13 @@ Name | Type | Description | Notes +## Enum: StatusEnum + +Name | Value +---- | ----- +CREATED | "CREATED" +APPROVED | "APPROVED" +REJECTED | "REJECTED" + + + diff --git a/modules/integration/tests-common/clients/publisher/docs/ApiRevisionsApi.md b/modules/integration/tests-common/clients/publisher/docs/ApiRevisionsApi.md index 0739d75ee4..21c0037e32 100644 --- a/modules/integration/tests-common/clients/publisher/docs/ApiRevisionsApi.md +++ b/modules/integration/tests-common/clients/publisher/docs/ApiRevisionsApi.md @@ -6,6 +6,7 @@ Method | HTTP request | Description ------------- | ------------- | ------------- [**createAPIRevision**](ApiRevisionsApi.md#createAPIRevision) | **POST** /apis/{apiId}/revisions | Create API Revision [**deleteAPIRevision**](ApiRevisionsApi.md#deleteAPIRevision) | **DELETE** /apis/{apiId}/revisions/{revisionId} | Delete Revision +[**deleteAPIRevisionDeploymentPendingTask**](ApiRevisionsApi.md#deleteAPIRevisionDeploymentPendingTask) | **DELETE** /apis/{apiId}/cancel-revision-workflow/{revisionId}/{envName} | Delete Pending Revision Deployment Workflow Tasks [**deployAPIRevision**](ApiRevisionsApi.md#deployAPIRevision) | **POST** /apis/{apiId}/deploy-revision | Deploy Revision [**getAPIRevision**](ApiRevisionsApi.md#getAPIRevision) | **GET** /apis/{apiId}/revisions/{revisionId} | Retrieve Revision [**getAPIRevisionDeployments**](ApiRevisionsApi.md#getAPIRevisionDeployments) | **GET** /apis/{apiId}/deployments | List Deployments @@ -157,6 +158,78 @@ Name | Type | Description | Notes **204** | No Content. Successfully deleted the revision | - | **404** | Not Found. The specified resource does not exist. | - | + +# **deleteAPIRevisionDeploymentPendingTask** +> deleteAPIRevisionDeploymentPendingTask(apiId, revisionId, envName) + +Delete Pending Revision Deployment Workflow Tasks + +This operation can be used to remove pending revision deployment requests that are in pending state + +### Example +```java +// Import classes: +import org.wso2.am.integration.clients.publisher.api.ApiClient; +import org.wso2.am.integration.clients.publisher.api.ApiException; +import org.wso2.am.integration.clients.publisher.api.Configuration; +import org.wso2.am.integration.clients.publisher.api.auth.*; +import org.wso2.am.integration.clients.publisher.api.models.*; +import org.wso2.am.integration.clients.publisher.api.v1.ApiRevisionsApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("https://apis.wso2.com/api/am/publisher/v4"); + + // Configure OAuth2 access token for authorization: OAuth2Security + OAuth OAuth2Security = (OAuth) defaultClient.getAuthentication("OAuth2Security"); + OAuth2Security.setAccessToken("YOUR ACCESS TOKEN"); + + ApiRevisionsApi apiInstance = new ApiRevisionsApi(defaultClient); + String apiId = "apiId_example"; // String | **API ID** consisting of the **UUID** of the API. + String revisionId = "revisionId_example"; // String | Revision ID of an API + String envName = "envName_example"; // String | Environment name of an Revision + try { + apiInstance.deleteAPIRevisionDeploymentPendingTask(apiId, revisionId, envName); + } catch (ApiException e) { + System.err.println("Exception when calling ApiRevisionsApi#deleteAPIRevisionDeploymentPendingTask"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **apiId** | **String**| **API ID** consisting of the **UUID** of the API. | + **revisionId** | **String**| Revision ID of an API | + **envName** | **String**| Environment name of an Revision | + +### Return type + +null (empty response body) + +### Authorization + +[OAuth2Security](../README.md#OAuth2Security) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK. Revision deployment pending task removed successfully. | - | +**404** | Not Found. The specified resource does not exist. | - | +**412** | Precondition Failed. The request has not been performed because one of the preconditions is not met. | - | + # **deployAPIRevision** > List<APIRevisionDeploymentDTO> deployAPIRevision(apiId, revisionId, apIRevisionDeploymentDTO) diff --git a/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/ApiRevisionsApi.java b/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/ApiRevisionsApi.java index 52eeac166b..0c3df0fa03 100644 --- a/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/ApiRevisionsApi.java +++ b/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/ApiRevisionsApi.java @@ -311,6 +311,141 @@ public okhttp3.Call deleteAPIRevisionAsync(String apiId, String revisionId, fina localVarApiClient.executeAsync(localVarCall, localVarReturnType, _callback); return localVarCall; } + /** + * Build call for deleteAPIRevisionDeploymentPendingTask + * @param apiId **API ID** consisting of the **UUID** of the API. (required) + * @param revisionId Revision ID of an API (required) + * @param envName Environment name of an Revision (required) + * @param _callback Callback for upload/download progress + * @return Call to execute + * @throws ApiException If fail to serialize the request body object + * @http.response.details + + + + + +
Status Code Description Response Headers
200 OK. Revision deployment pending task removed successfully. -
404 Not Found. The specified resource does not exist. -
412 Precondition Failed. The request has not been performed because one of the preconditions is not met. -
+ */ + public okhttp3.Call deleteAPIRevisionDeploymentPendingTaskCall(String apiId, String revisionId, String envName, final ApiCallback _callback) throws ApiException { + Object localVarPostBody = null; + + // create path and map variables + String localVarPath = "/apis/{apiId}/cancel-revision-workflow/{revisionId}/{envName}" + .replaceAll("\\{" + "apiId" + "\\}", localVarApiClient.escapeString(apiId.toString())) + .replaceAll("\\{" + "revisionId" + "\\}", localVarApiClient.escapeString(revisionId.toString())) + .replaceAll("\\{" + "envName" + "\\}", localVarApiClient.escapeString(envName.toString())); + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + localVarHeaderParams.put("Content-Type", localVarContentType); + + String[] localVarAuthNames = new String[] { "OAuth2Security" }; + return localVarApiClient.buildCall(localVarPath, "DELETE", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + @SuppressWarnings("rawtypes") + private okhttp3.Call deleteAPIRevisionDeploymentPendingTaskValidateBeforeCall(String apiId, String revisionId, String envName, final ApiCallback _callback) throws ApiException { + + // verify the required parameter 'apiId' is set + if (apiId == null) { + throw new ApiException("Missing the required parameter 'apiId' when calling deleteAPIRevisionDeploymentPendingTask(Async)"); + } + + // verify the required parameter 'revisionId' is set + if (revisionId == null) { + throw new ApiException("Missing the required parameter 'revisionId' when calling deleteAPIRevisionDeploymentPendingTask(Async)"); + } + + // verify the required parameter 'envName' is set + if (envName == null) { + throw new ApiException("Missing the required parameter 'envName' when calling deleteAPIRevisionDeploymentPendingTask(Async)"); + } + + + okhttp3.Call localVarCall = deleteAPIRevisionDeploymentPendingTaskCall(apiId, revisionId, envName, _callback); + return localVarCall; + + } + + /** + * Delete Pending Revision Deployment Workflow Tasks + * This operation can be used to remove pending revision deployment requests that are in pending state + * @param apiId **API ID** consisting of the **UUID** of the API. (required) + * @param revisionId Revision ID of an API (required) + * @param envName Environment name of an Revision (required) + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + * @http.response.details + + + + + +
Status Code Description Response Headers
200 OK. Revision deployment pending task removed successfully. -
404 Not Found. The specified resource does not exist. -
412 Precondition Failed. The request has not been performed because one of the preconditions is not met. -
+ */ + public void deleteAPIRevisionDeploymentPendingTask(String apiId, String revisionId, String envName) throws ApiException { + deleteAPIRevisionDeploymentPendingTaskWithHttpInfo(apiId, revisionId, envName); + } + + /** + * Delete Pending Revision Deployment Workflow Tasks + * This operation can be used to remove pending revision deployment requests that are in pending state + * @param apiId **API ID** consisting of the **UUID** of the API. (required) + * @param revisionId Revision ID of an API (required) + * @param envName Environment name of an Revision (required) + * @return ApiResponse<Void> + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + * @http.response.details + + + + + +
Status Code Description Response Headers
200 OK. Revision deployment pending task removed successfully. -
404 Not Found. The specified resource does not exist. -
412 Precondition Failed. The request has not been performed because one of the preconditions is not met. -
+ */ + public ApiResponse deleteAPIRevisionDeploymentPendingTaskWithHttpInfo(String apiId, String revisionId, String envName) throws ApiException { + okhttp3.Call localVarCall = deleteAPIRevisionDeploymentPendingTaskValidateBeforeCall(apiId, revisionId, envName, null); + return localVarApiClient.execute(localVarCall); + } + + /** + * Delete Pending Revision Deployment Workflow Tasks (asynchronously) + * This operation can be used to remove pending revision deployment requests that are in pending state + * @param apiId **API ID** consisting of the **UUID** of the API. (required) + * @param revisionId Revision ID of an API (required) + * @param envName Environment name of an Revision (required) + * @param _callback The callback to be executed when the API call finishes + * @return The request call + * @throws ApiException If fail to process the API call, e.g. serializing the request body object + * @http.response.details + + + + + +
Status Code Description Response Headers
200 OK. Revision deployment pending task removed successfully. -
404 Not Found. The specified resource does not exist. -
412 Precondition Failed. The request has not been performed because one of the preconditions is not met. -
+ */ + public okhttp3.Call deleteAPIRevisionDeploymentPendingTaskAsync(String apiId, String revisionId, String envName, final ApiCallback _callback) throws ApiException { + + okhttp3.Call localVarCall = deleteAPIRevisionDeploymentPendingTaskValidateBeforeCall(apiId, revisionId, envName, _callback); + localVarApiClient.executeAsync(localVarCall, _callback); + return localVarCall; + } /** * Build call for deployAPIRevision * @param apiId **API ID** consisting of the **UUID** of the API. (required) diff --git a/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIDTO.java b/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIDTO.java index be8c66c016..2ccfa175ca 100644 --- a/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIDTO.java +++ b/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIDTO.java @@ -256,6 +256,10 @@ public AudienceEnum read(final JsonReader jsonReader) throws IOException { @SerializedName(SERIALIZED_NAME_AUTHORIZATION_HEADER) private String authorizationHeader; + public static final String SERIALIZED_NAME_API_KEY_HEADER = "apiKeyHeader"; + @SerializedName(SERIALIZED_NAME_API_KEY_HEADER) + private String apiKeyHeader; + public static final String SERIALIZED_NAME_SECURITY_SCHEME = "securityScheme"; @SerializedName(SERIALIZED_NAME_SECURITY_SCHEME) private List securityScheme = null; @@ -1151,6 +1155,29 @@ public void setAuthorizationHeader(String authorizationHeader) { } + public APIDTO apiKeyHeader(String apiKeyHeader) { + + this.apiKeyHeader = apiKeyHeader; + return this; + } + + /** + * Name of the API key header used for invoking the API. If it is not set, default value `apiKey` will be used. + * @return apiKeyHeader + **/ + @javax.annotation.Nullable + @ApiModelProperty(example = "apiKey", value = "Name of the API key header used for invoking the API. If it is not set, default value `apiKey` will be used. ") + + public String getApiKeyHeader() { + return apiKeyHeader; + } + + + public void setApiKeyHeader(String apiKeyHeader) { + this.apiKeyHeader = apiKeyHeader; + } + + public APIDTO securityScheme(List securityScheme) { this.securityScheme = securityScheme; @@ -1921,6 +1948,7 @@ public boolean equals(Object o) { Objects.equals(this.policies, API.policies) && Objects.equals(this.apiThrottlingPolicy, API.apiThrottlingPolicy) && Objects.equals(this.authorizationHeader, API.authorizationHeader) && + Objects.equals(this.apiKeyHeader, API.apiKeyHeader) && Objects.equals(this.securityScheme, API.securityScheme) && Objects.equals(this.maxTps, API.maxTps) && Objects.equals(this.visibility, API.visibility) && @@ -1957,7 +1985,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(id, name, description, context, version, provider, lifeCycleStatus, wsdlInfo, wsdlUrl, responseCachingEnabled, cacheTimeout, hasThumbnail, isDefaultVersion, isRevision, revisionedApiId, revisionId, enableSchemaValidation, enableSubscriberVerification, type, audience, transport, tags, policies, apiThrottlingPolicy, authorizationHeader, securityScheme, maxTps, visibility, visibleRoles, visibleTenants, mediationPolicies, apiPolicies, subscriptionAvailability, subscriptionAvailableTenants, additionalProperties, additionalPropertiesMap, monetization, accessControl, accessControlRoles, businessInformation, corsConfiguration, websubSubscriptionConfiguration, workflowStatus, createdTime, lastUpdatedTimestamp, lastUpdatedTime, endpointConfig, endpointImplementationType, scopes, operations, threatProtectionPolicies, categories, keyManagers, serviceInfo, advertiseInfo, gatewayVendor, asyncTransportProtocols); + return Objects.hash(id, name, description, context, version, provider, lifeCycleStatus, wsdlInfo, wsdlUrl, responseCachingEnabled, cacheTimeout, hasThumbnail, isDefaultVersion, isRevision, revisionedApiId, revisionId, enableSchemaValidation, enableSubscriberVerification, type, audience, transport, tags, policies, apiThrottlingPolicy, authorizationHeader, apiKeyHeader, securityScheme, maxTps, visibility, visibleRoles, visibleTenants, mediationPolicies, apiPolicies, subscriptionAvailability, subscriptionAvailableTenants, additionalProperties, additionalPropertiesMap, monetization, accessControl, accessControlRoles, businessInformation, corsConfiguration, websubSubscriptionConfiguration, workflowStatus, createdTime, lastUpdatedTimestamp, lastUpdatedTime, endpointConfig, endpointImplementationType, scopes, operations, threatProtectionPolicies, categories, keyManagers, serviceInfo, advertiseInfo, gatewayVendor, asyncTransportProtocols); } @@ -1990,6 +2018,7 @@ public String toString() { sb.append(" policies: ").append(toIndentedString(policies)).append("\n"); sb.append(" apiThrottlingPolicy: ").append(toIndentedString(apiThrottlingPolicy)).append("\n"); sb.append(" authorizationHeader: ").append(toIndentedString(authorizationHeader)).append("\n"); + sb.append(" apiKeyHeader: ").append(toIndentedString(apiKeyHeader)).append("\n"); sb.append(" securityScheme: ").append(toIndentedString(securityScheme)).append("\n"); sb.append(" maxTps: ").append(toIndentedString(maxTps)).append("\n"); sb.append(" visibility: ").append(toIndentedString(visibility)).append("\n"); diff --git a/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIRevisionDeploymentDTO.java b/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIRevisionDeploymentDTO.java index c680743540..48e550bc70 100644 --- a/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIRevisionDeploymentDTO.java +++ b/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIRevisionDeploymentDTO.java @@ -37,6 +37,59 @@ public class APIRevisionDeploymentDTO { @SerializedName(SERIALIZED_NAME_NAME) private String name; + /** +* Gets or Sets status +*/ + @JsonAdapter(StatusEnum.Adapter.class) +public enum StatusEnum { + CREATED("CREATED"), + + APPROVED("APPROVED"), + + REJECTED("REJECTED"); + +private String value; + +StatusEnum(String value) { +this.value = value; +} + +public String getValue() { +return value; +} + +@Override +public String toString() { +return String.valueOf(value); +} + +public static StatusEnum fromValue(String value) { + for (StatusEnum b : StatusEnum.values()) { + if (b.name().equals(value)) { + return b; + } +} + throw new IllegalArgumentException("Unexpected value '" + value + "'"); +} + + public static class Adapter extends TypeAdapter { + @Override + public void write(final JsonWriter jsonWriter, final StatusEnum enumeration) throws IOException { + jsonWriter.value(enumeration.getValue()); + } + + @Override + public StatusEnum read(final JsonReader jsonReader) throws IOException { + String value = jsonReader.nextString(); + return StatusEnum.fromValue(value); + } + } +} + + public static final String SERIALIZED_NAME_STATUS = "status"; + @SerializedName(SERIALIZED_NAME_STATUS) + private StatusEnum status = StatusEnum.CREATED; + public static final String SERIALIZED_NAME_VHOST = "vhost"; @SerializedName(SERIALIZED_NAME_VHOST) private String vhost; @@ -100,6 +153,29 @@ public void setName(String name) { } + public APIRevisionDeploymentDTO status(StatusEnum status) { + + this.status = status; + return this; + } + + /** + * Get status + * @return status + **/ + @javax.annotation.Nullable + @ApiModelProperty(example = "CREATED", value = "") + + public StatusEnum getStatus() { + return status; + } + + + public void setStatus(StatusEnum status) { + this.status = status; + } + + public APIRevisionDeploymentDTO vhost(String vhost) { this.vhost = vhost; @@ -203,6 +279,7 @@ public boolean equals(Object o) { APIRevisionDeploymentDTO apIRevisionDeployment = (APIRevisionDeploymentDTO) o; return Objects.equals(this.revisionUuid, apIRevisionDeployment.revisionUuid) && Objects.equals(this.name, apIRevisionDeployment.name) && + Objects.equals(this.status, apIRevisionDeployment.status) && Objects.equals(this.vhost, apIRevisionDeployment.vhost) && Objects.equals(this.displayOnDevportal, apIRevisionDeployment.displayOnDevportal) && Objects.equals(this.deployedTime, apIRevisionDeployment.deployedTime) && @@ -211,7 +288,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(revisionUuid, name, vhost, displayOnDevportal, deployedTime, successDeployedTime); + return Objects.hash(revisionUuid, name, status, vhost, displayOnDevportal, deployedTime, successDeployedTime); } @@ -221,6 +298,7 @@ public String toString() { sb.append("class APIRevisionDeploymentDTO {\n"); sb.append(" revisionUuid: ").append(toIndentedString(revisionUuid)).append("\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); sb.append(" vhost: ").append(toIndentedString(vhost)).append("\n"); sb.append(" displayOnDevportal: ").append(toIndentedString(displayOnDevportal)).append("\n"); sb.append(" deployedTime: ").append(toIndentedString(deployedTime)).append("\n"); diff --git a/modules/integration/tests-common/clients/publisher/src/main/resources/publisher-api.yaml b/modules/integration/tests-common/clients/publisher/src/main/resources/publisher-api.yaml index de67456fcb..3c71436647 100644 --- a/modules/integration/tests-common/clients/publisher/src/main/resources/publisher-api.yaml +++ b/modules/integration/tests-common/clients/publisher/src/main/resources/publisher-api.yaml @@ -1810,6 +1810,40 @@ paths: source: 'curl -k -X POST -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" "https://127.0.0.1:9443/api/am/publisher/v4/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/restore-revision?revisionId=e0824883-3e86-403a-aec1-22bbc454eb7c"' + /apis/{apiId}/cancel-revision-workflow/{revisionId}/{envName}: + #-------------------------------------------------------- + # Cancel a pending revision deployment workflow task given revision id and environment name + #-------------------------------------------------------- + delete: + tags: + - API Revisions + summary: Delete Pending Revision Deployment Workflow Tasks + description: | + This operation can be used to remove pending revision deployment requests that are in pending state + parameters: + - $ref: '#/components/parameters/apiId' + - $ref: '#/components/parameters/revisionId' + - $ref: '#/components/parameters/envName' + responses: + 200: + description: | + OK. + Revision deployment pending task removed successfully. + content: { } + 404: + $ref: '#/components/responses/NotFound' + 412: + $ref: '#/components/responses/PreconditionFailed' + security: + - OAuth2Security: + - apim:api_publish + - apim:api_manage + x-code-samples: + - lang: Curl + source: 'curl -k -X DELETE -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + "https://127.0.0.1:9443/api/am/publisher/v4/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/cancel-revision-workflow/e0824883-3e86-403a-aec1-22bbc454eb7c/Default"' + operationId: deleteAPIRevisionDeploymentPendingTask + /apis/import-service: post: tags: @@ -9120,6 +9154,14 @@ components: minLength: 1 type: string example: default + status: + type: string + example: CREATED + default: CREATED + enum: + - CREATED + - APPROVED + - REJECTED vhost: maxLength: 255 minLength: 1 @@ -12166,6 +12208,17 @@ components: schema: type: string + # API Revision Environment + # Specified as part of the path expression + envName: + name: envName + in: path + description: | + Environment name of an Revision + required: true + schema: + type: string + # API Revision Identifier # Specified as part of the query string revisionId-Q: diff --git a/modules/integration/tests-common/integration-test-utils/src/main/java/org/wso2/am/integration/test/impl/RestAPIAdminImpl.java b/modules/integration/tests-common/integration-test-utils/src/main/java/org/wso2/am/integration/test/impl/RestAPIAdminImpl.java index 9d4ff98d93..d8999038f6 100644 --- a/modules/integration/tests-common/integration-test-utils/src/main/java/org/wso2/am/integration/test/impl/RestAPIAdminImpl.java +++ b/modules/integration/tests-common/integration-test-utils/src/main/java/org/wso2/am/integration/test/impl/RestAPIAdminImpl.java @@ -741,6 +741,31 @@ public HttpResponse updateWorkflowStatus(String workflowReferenceId) throws ApiE return response; } + /** + * This method is used to reject a workflow + * + * @return API response returned by API call. + * @throws ApiException if an error occurs while rejecting a workflow + */ + public HttpResponse rejectWorkflowStatus(String workflowReferenceId) throws ApiException { + WorkflowDTO workflowdto = null; + HttpResponse response = null; + Gson gson = new Gson(); + + WorkflowDTO body = new WorkflowDTO(); + WorkflowDTO.StatusEnum status = WorkflowDTO.StatusEnum.valueOf(WorkflowDTO.StatusEnum.class, "REJECTED"); + body.setStatus(status); + body.setDescription("Reject workflow request."); + //body.setAttributes(); + try { + workflowdto = workflowsIndividualApi.workflowsUpdateWorkflowStatusPost(workflowReferenceId, body); + response = new HttpResponse(gson.toJson(workflowdto), 200); + } catch (ApiException e) { + return new HttpResponse(gson.toJson(e.getResponseBody()), e.getCode()); + } + return response; + } + /** * This method is used to retrieve tenant Config. * diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/workflow/WorkflowApprovalExecutorTest.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/workflow/WorkflowApprovalExecutorTest.java index 6e9b9b941b..6f61868d71 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/workflow/WorkflowApprovalExecutorTest.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/workflow/WorkflowApprovalExecutorTest.java @@ -44,10 +44,12 @@ import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationDTO; import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationKeyDTO; import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationKeyGenerateRequestDTO; +import org.wso2.am.integration.test.Constants; import org.wso2.am.integration.test.impl.ApiProductTestHelper; import org.wso2.am.integration.test.impl.ApiTestHelper; import org.wso2.am.integration.test.impl.RestAPIAdminImpl; import org.wso2.am.integration.test.impl.RestAPIStoreImpl; +import org.wso2.am.integration.test.utils.APIManagerIntegrationTestException; import org.wso2.am.integration.test.utils.UserManagementUtils; import org.wso2.am.integration.test.utils.base.APIMIntegrationConstants; import org.wso2.am.integration.test.utils.bean.*; @@ -1096,6 +1098,215 @@ public void testCleanUpWorkflowProcess() throws Exception { "Clean up pending task process is failed for Application Key generation"); } + /** + * Test API revision deployment workflow + * Following flows will be tested, + * Deploy revision request will be sent and check whether it is not deployed + * Reject request and check whether it is not deployed + * Deploy request will be sent, admin will approve it and check whether it is deployed + * Undeploy the revision and check whether it is undeployed + * Deploy a revision and send another request and check whether the second request is not deployed + * Reject the second request and check whether it is not deployed + * Deploy the second request and check whether it is deployed and the first deployment is undeployed + * + * @throws Exception if an error occurs when revision deployment workflow test is running + **/ + @Test(groups = { "wso2.am" }, description = "Testing the API Revision Deployment Workflow Process") + public void testAPIRevisionDeploymentWorkflowProcess() throws Exception { + //Add API + String apiName = "WorkflowRevisionDeployment"; + String apiVersion = "1.0.0"; + String apiContext = "workflowrevision"; + String url = getGatewayURLHttp() + "jaxrs_basic/services/customers/customerservice"; + APIRequest apiRequest; + apiRequest = new APIRequest(apiName, apiContext, new URL(url)); + apiRequest.setVersion(apiVersion); + apiRequest.setTiersCollection(APIMIntegrationConstants.API_TIER.UNLIMITED); + apiRequest.setTier(APIMIntegrationConstants.API_TIER.UNLIMITED); + apiRequest.setProvider(USER_SMITH); + HttpResponse apiResponse = restAPIPublisher.addAPI(apiRequest); + apiId = apiResponse.getData(); + assertEquals(apiResponse.getResponseCode(), 201, + "API creation failed in Revision Deployment Workflow Executor"); + + // Create revision and send deploy request + String firstRevisionUUID = createAPIRevisionAndDeployUsingRest(apiId, restAPIPublisher); + + // Get workflow pending requests by admin + String workflowType = "AM_REVISION_DEPLOYMENT"; + org.wso2.am.integration.test.HttpResponse response = restAPIAdmin.getWorkflows(workflowType); + assertEquals(response.getResponseCode(), 200, "Get Workflow Pending requests failed for User Admin"); + + // Get the externalReference of the workflow + JSONObject workflowRespObj = new JSONObject(response.getData()); + String firstExternalWorkflowRef = null; + JSONArray revisionArray = (JSONArray) workflowRespObj.get("list"); + for (int item = 0; item < revisionArray.length(); item++) { + JSONObject revision = (JSONObject) revisionArray.get(item); + JSONObject properties = (JSONObject) revision.get("properties"); + if (properties.has("apiName") && apiName.equals(properties.get("apiName"))) { + firstExternalWorkflowRef = (String) revision.get("referenceId"); + } + } + assertNotNull("First Workflow reference is not available ", firstExternalWorkflowRef); + + // Get workflow pending request by external workflow reference by admin + response = restAPIAdmin.getWorkflowByExternalWorkflowReference(firstExternalWorkflowRef); + assertEquals(response.getResponseCode(), 200, + "Get First Workflow Pending request by external workflow reference failed for User Admin"); + + // Reject workflow and check whether the revision is not deployed + response = restAPIAdmin.rejectWorkflowStatus(firstExternalWorkflowRef); + assertEquals(response.getResponseCode(), 200, "First Workflow request reject failed for user admin"); + HttpResponse apiRevisionsGetResponse = restAPIPublisher.getAPIRevisions(apiId, "deployed:true"); + assertEquals(apiRevisionsGetResponse.getResponseCode(), HTTP_RESPONSE_CODE_OK, + "Unable to retrieve deployed revisions" + apiRevisionsGetResponse.getData()); + JSONObject apiRevisionsGetResponseObj = new JSONObject(apiRevisionsGetResponse.getData()); + assertEquals(apiRevisionsGetResponseObj.getJSONArray("list").length(), 0, "First Revision is deployed"); + + deployAPIRevisionWithWorkflow(apiId, firstRevisionUUID, firstExternalWorkflowRef); + apiRevisionsGetResponse = restAPIPublisher.getAPIRevisions(apiId, "deployed:true"); + assertEquals(apiRevisionsGetResponse.getResponseCode(), HTTP_RESPONSE_CODE_OK, + "Unable to retrieve deployed revisions" + apiRevisionsGetResponse.getData()); + apiRevisionsGetResponseObj = new JSONObject(apiRevisionsGetResponse.getData()); + JSONArray listArray = apiRevisionsGetResponseObj.getJSONArray("list"); + // Iterate through the "list" array + for (int i = 0; i < listArray.length(); i++) { + JSONObject item = listArray.getJSONObject(i); + String status = item.getJSONArray("deploymentInfo").getJSONObject(0).getString("status"); + if ("APPROVED".equals(status)) { + assertEquals(firstRevisionUUID, item.getString("id"), "First Revision is not deployed"); + } + } + + // Undeploy revision and check whether it is undeployed + undeployAPIRevisionWithWorkflow(apiId, firstRevisionUUID, firstExternalWorkflowRef); + apiRevisionsGetResponse = restAPIPublisher.getAPIRevisions(apiId, "deployed:true"); + assertEquals(apiRevisionsGetResponse.getResponseCode(), HTTP_RESPONSE_CODE_OK, + "Unable to retrieve deployed revisions" + apiRevisionsGetResponse.getData()); + apiRevisionsGetResponseObj = new JSONObject(apiRevisionsGetResponse.getData()); + assertEquals(apiRevisionsGetResponseObj.getJSONArray("list").length(), 0, "First Revision is deployed"); + + // Deploy a revision then send another request and check whether the second request is not deployed + deployAPIRevisionWithWorkflow(apiId, firstRevisionUUID, firstExternalWorkflowRef); + // Create Second Revision and send deploy request + String secondRevisionUUID = createAPIRevisionAndDeployUsingRest(apiId, restAPIPublisher); + apiRevisionsGetResponse = restAPIPublisher.getAPIRevisions(apiId, "deployed:true"); + assertEquals(apiRevisionsGetResponse.getResponseCode(), HTTP_RESPONSE_CODE_OK, + "Unable to retrieve deployed revisions" + apiRevisionsGetResponse.getData()); + apiRevisionsGetResponseObj = new JSONObject(apiRevisionsGetResponse.getData()); + listArray = apiRevisionsGetResponseObj.getJSONArray("list"); + // Iterate through the "list" array + for (int i = 0; i < listArray.length(); i++) { + JSONObject item = listArray.getJSONObject(i); + String status = item.getJSONArray("deploymentInfo").getJSONObject(0).getString("status"); + if ("APPROVED".equals(status)) { + assertEquals(firstRevisionUUID, item.getString("id"), "Second Revision is deployed"); + } + } + + //Get workflow pending requests by admin + response = restAPIAdmin.getWorkflows(workflowType); + assertEquals(response.getResponseCode(), 200, "Get Workflow Pending requests failed for User Admin"); + workflowRespObj = new JSONObject(response.getData()); + String secondExternalWorkflowRef = null; + revisionArray = (JSONArray) workflowRespObj.get("list"); + for (int item = 0; item < revisionArray.length(); item++) { + JSONObject revision = (JSONObject) revisionArray.get(item); + JSONObject properties = (JSONObject) revision.get("properties"); + if (properties.has("apiName") && apiName.equals(properties.get("apiName"))) { + secondExternalWorkflowRef = (String) revision.get("referenceId"); + } + } + assertNotNull("Second Workflow reference is not available ", secondExternalWorkflowRef); + apiRevisionsGetResponse = restAPIPublisher.getAPIRevisions(apiId, "deployed:true"); + assertEquals(apiRevisionsGetResponse.getResponseCode(), HTTP_RESPONSE_CODE_OK, + "Unable to retrieve deployed revisions" + apiRevisionsGetResponse.getData()); + + // Reject the second workflow request and check whether the second revision is not deployed + response = restAPIAdmin.rejectWorkflowStatus(secondExternalWorkflowRef); + assertEquals(response.getResponseCode(), 200, "Workflow request update failed for user admin"); + apiRevisionsGetResponse = restAPIPublisher.getAPIRevisions(apiId, "deployed:true"); + assertEquals(apiRevisionsGetResponse.getResponseCode(), HTTP_RESPONSE_CODE_OK, + "Unable to retrieve deployed revisions" + apiRevisionsGetResponse.getData()); + apiRevisionsGetResponseObj = new JSONObject(apiRevisionsGetResponse.getData()); + listArray = apiRevisionsGetResponseObj.getJSONArray("list"); + // Iterate through the "list" array + for (int i = 0; i < listArray.length(); i++) { + JSONObject item = listArray.getJSONObject(i); + String status = item.getJSONArray("deploymentInfo").getJSONObject(0).getString("status"); + if ("APPROVED".equals(status)) { + Assert.assertNotEquals(secondRevisionUUID, item.getString("id"), "Second Revision is deployed"); + } + } + + // Deploy the second revision and check whether the first revision is undeployed + deployAPIRevisionWithWorkflow(apiId, secondRevisionUUID, secondExternalWorkflowRef); + apiRevisionsGetResponse = restAPIPublisher.getAPIRevisions(apiId, "deployed:true"); + assertEquals(apiRevisionsGetResponse.getResponseCode(), HTTP_RESPONSE_CODE_OK, + "Unable to retrieve deployed revisions" + apiRevisionsGetResponse.getData()); + apiRevisionsGetResponseObj = new JSONObject(apiRevisionsGetResponse.getData()); + listArray = apiRevisionsGetResponseObj.getJSONArray("list"); + // Iterate through the "list" array + for (int i = 0; i < listArray.length(); i++) { + JSONObject item = listArray.getJSONObject(i); + String status = item.getJSONArray("deploymentInfo").getJSONObject(0).getString("status"); + if ("APPROVED".equals(status)) { + Assert.assertNotEquals(firstRevisionUUID, item.getString("id"), "First Revision is deployed"); + assertEquals(secondRevisionUUID, item.getString("id"), "Second Revision is not deployed"); + } + } + } + + /** + * Deploy a revision when revision deployment workflow is active + * + * @param apiId API Id + * @param revisionUUID Revision UUID + * @param externalRef External reference + * @throws Exception if an error occurs when deploying a revision + **/ + private void deployAPIRevisionWithWorkflow(String apiId, String revisionUUID, String externalRef) throws Exception { + // Send deploy request, approve and check whether it is deployed + List apiRevisionDeployRequestList = new ArrayList<>(); + APIRevisionDeployUndeployRequest apiRevisionDeployRequest = new APIRevisionDeployUndeployRequest(); + apiRevisionDeployRequest.setName(Constants.GATEWAY_ENVIRONMENT); + apiRevisionDeployRequest.setVhost("localhost"); + apiRevisionDeployRequest.setDisplayOnDevportal(true); + apiRevisionDeployRequestList.add(apiRevisionDeployRequest); + HttpResponse apiRevisionsDeployResponse = restAPIPublisher.deployAPIRevision(apiId, revisionUUID, + apiRevisionDeployRequestList, "API"); + assertEquals(apiRevisionsDeployResponse.getResponseCode(), HTTP_RESPONSE_CODE_CREATED, + "Unable to deploy API Revisions:" + apiRevisionsDeployResponse.getData()); + org.wso2.am.integration.test.HttpResponse response = restAPIAdmin.updateWorkflowStatus(externalRef); + assertEquals(response.getResponseCode(), 200, "First Workflow request update failed for user admin"); + } + + /** + * Undeploy a revision when revision deployment workflow is active + * + * @param apiId API Id + * @param revisionUUID Revision UUID + * @param externalRef External reference + * @throws Exception if an error occurs when undeploying a revision + **/ + private void undeployAPIRevisionWithWorkflow(String apiId, String revisionUUID, String externalRef) + throws Exception { + List apiRevisionDeployRequestList = new ArrayList<>(); + APIRevisionDeployUndeployRequest apiRevisionDeployRequest = new APIRevisionDeployUndeployRequest(); + apiRevisionDeployRequest.setName(Constants.GATEWAY_ENVIRONMENT); + apiRevisionDeployRequest.setVhost("localhost"); + apiRevisionDeployRequest.setDisplayOnDevportal(true); + apiRevisionDeployRequestList.add(apiRevisionDeployRequest); + HttpResponse apiRevisionsDeployResponse = restAPIPublisher.undeployAPIRevision(apiId, revisionUUID, + apiRevisionDeployRequestList); + assertEquals(apiRevisionsDeployResponse.getResponseCode(), HTTP_RESPONSE_CODE_CREATED, + "Unable to deploy API Revisions:" + apiRevisionsDeployResponse.getData()); + org.wso2.am.integration.test.HttpResponse response = restAPIAdmin.updateWorkflowStatus(externalRef); + assertEquals(response.getResponseCode(), 200, "First Workflow request update failed for user admin"); + } + + @AfterClass(alwaysRun = true) public void destroy() throws Exception { restAPIStore.deleteApplication(applicationID); diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/approveWorkflow/workflow-extensions.xml b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/approveWorkflow/workflow-extensions.xml index d164df1782..07f1e9fdd5 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/approveWorkflow/workflow-extensions.xml +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/approveWorkflow/workflow-extensions.xml @@ -1,4 +1,6 @@ + +