Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revision deployment approval workflow #12169

Merged
merged 36 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
2b62ad7
publisher yaml changes
GihanAyesh Oct 6, 2023
68c4547
add revision executor
GihanAyesh Oct 6, 2023
3a3f49e
add constants
GihanAyesh Oct 6, 2023
a0e5692
admin yaml changes
GihanAyesh Oct 6, 2023
f740eaf
add functions to interface
GihanAyesh Oct 6, 2023
6bcd392
add status
GihanAyesh Oct 6, 2023
bbb3989
logic changes for workflow
GihanAyesh Oct 6, 2023
75279b0
new workflow dto
GihanAyesh Oct 6, 2023
1e14268
approval and simple executors
GihanAyesh Oct 6, 2023
9b2ec5b
auto generated code
GihanAyesh Oct 6, 2023
44d570d
check for revision deployment
GihanAyesh Oct 6, 2023
cb33ad8
admin changes
GihanAyesh Oct 6, 2023
473de80
publisher changes
GihanAyesh Oct 6, 2023
33e5eb6
auto gen content
GihanAyesh Oct 6, 2023
f05b4f7
add status to h2
GihanAyesh Oct 6, 2023
8280f6e
Refactoring code
GihanAyesh Oct 9, 2023
0e1efd0
ability to have a pending and an approved workflow
GihanAyesh Oct 12, 2023
93d8806
refactor files
GihanAyesh Oct 12, 2023
7616a57
add api revision
GihanAyesh Oct 12, 2023
0c988b8
comment changes
GihanAyesh Oct 12, 2023
231c47a
minor fix
GihanAyesh Oct 12, 2023
59ee8d3
bug fix and reformatting
GihanAyesh Oct 13, 2023
fa3c535
Merge branch 'wso2:master' into master
GihanAyesh Oct 18, 2023
c4a6119
change getAPIRevisionDeployments
GihanAyesh Oct 18, 2023
75c268f
displayOnDevportal fix
GihanAyesh Oct 18, 2023
154911f
revision status for other databases
GihanAyesh Oct 18, 2023
fc7885b
Unit tests for revision deployment new functions
GihanAyesh Oct 24, 2023
357bf2a
set autocommit to false and reformatting
GihanAyesh Nov 6, 2023
6a77f97
change complete logic
GihanAyesh Nov 9, 2023
932d40d
remove complete call
GihanAyesh Nov 15, 2023
6b6005d
Merge branch 'wso2:master' into master
GihanAyesh Nov 20, 2023
e279821
Merge branch 'wso2:master' into master
GihanAyesh Dec 1, 2023
96b8beb
Merge branch 'wso2:master' into master
GihanAyesh Dec 6, 2023
020dc14
Test fixes
GihanAyesh Dec 12, 2023
504ee62
Set simple executor as default
GihanAyesh Dec 14, 2023
7c7a2e4
minor fix
GihanAyesh Dec 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1694,4 +1694,26 @@ boolean isValidContext(String providerName, String apiName, String contextTempla
*/
boolean validateAppliedPolicyWithSpecification(OperationPolicySpecification policySpecification, OperationPolicy
appliedPolicy, String apiType) throws APIManagementException;

/**
* Resume API revision deployment process
*
* @param apiId API Id using for the revision deployment
* @param organization organization identifier
* @param revisionUUID revision UUID
* @param revisionId revision number
* @param environment environment the deployment is happening
*/
void resumeDeployedAPIRevision(String apiId, String organization, String revisionUUID, String revisionId,
String environment);

/***
* Cleanup pending or rejected revision workflows
*
* @param apiId Id of the API
* @param externalRef external Id of the revision
* @throws APIManagementException if an exception occurs while cleaning up revision deployment
*/
void cleanupAPIRevisionDeploymentWorkflows(String apiId, String externalRef) throws APIManagementException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

package org.wso2.carbon.apimgt.api.model;

import org.wso2.carbon.apimgt.api.WorkflowStatus;

import java.io.Serializable;

public class APIRevisionDeployment implements Serializable {
Expand All @@ -26,6 +28,7 @@ public class APIRevisionDeployment implements Serializable {
private String revisionUUID;
private String deployment;
private String vhost;
private WorkflowStatus status;
private boolean isDisplayOnDevportal;
private String deployedTime;
private String successDeployedTime;
Expand Down Expand Up @@ -85,4 +88,12 @@ public String getSuccessDeployedTime() {
public void setSuccessDeployedTime(String successDeployedTime) {
this.successDeployedTime = successDeployedTime;
}

public WorkflowStatus getStatus() {
return status;
}

public void setStatus(WorkflowStatus status) {
this.status = status;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1239,6 +1239,14 @@ public static class ApplicationStatus {
public static final String DELETE_PENDING = "DELETE_PENDING";
}

public static class APIRevisionStatus {

public static final String API_REVISION_CREATED = "CREATED";
public static final String API_REVISION_APPROVED = "APPROVED";
public static final String API_REVISION_REJECTED = "REJECTED";
public static final String API_REVISION_DELETE_PENDING = "DELETE_PENDING";
}

public static class AppRegistrationStatus {

public static final String REGISTRATION_CREATED = "CREATED";
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -5658,6 +5658,55 @@ public WorkflowDTO retrieveWorkflowFromInternalReference(String workflowReferenc
return workflowDTO;
}

/**
* Returns a workflow object for a given internal workflow reference and the workflow type.
*
* @param workflowReference Internal workflow reference
* @param workflowType Workflow type
* @return List<WorkflowDTO> List of workflow objects
* @throws APIManagementException if failed to retrieve workflow details
*/
public List<WorkflowDTO> retrieveAllWorkflowFromInternalReference(String workflowReference, String workflowType)
throws APIManagementException {

List<WorkflowDTO> workflowDTOList = new ArrayList<>();

try (Connection connection = APIMgtDBUtil.getConnection();
PreparedStatement statement = connection
.prepareStatement(SQLConstants.GET_ALL_WORKFLOW_ENTRY_FROM_INTERNAL_REF_SQL)) {
statement.setString(1, workflowReference);
statement.setString(2, workflowType);
try (ResultSet rs = statement.executeQuery()) {
while (rs.next()) {
WorkflowDTO workflowDTO = WorkflowExecutorFactory.getInstance()
.createWorkflowDTO(rs.getString("WF_TYPE"));
workflowDTO.setStatus(WorkflowStatus.valueOf(rs.getString("WF_STATUS")));
workflowDTO.setExternalWorkflowReference(rs.getString("WF_EXTERNAL_REFERENCE"));
workflowDTO.setCreatedTime(rs.getTimestamp("WF_CREATED_TIME").getTime());
workflowDTO.setWorkflowReference(rs.getString("WF_REFERENCE"));
workflowDTO.setTenantDomain(rs.getString("TENANT_DOMAIN"));
workflowDTO.setTenantId(rs.getInt("TENANT_ID"));
workflowDTO.setWorkflowDescription(rs.getString("WF_STATUS_DESC"));
workflowDTOList.add(workflowDTO);
InputStream metadataBlob = rs.getBinaryStream("WF_METADATA");

if (metadataBlob != null) {
String metadata = APIMgtDBUtil.getStringFromInputStream(metadataBlob);
Gson metadataGson = new Gson();
JSONObject metadataJson = metadataGson.fromJson(metadata, JSONObject.class);
workflowDTO.setMetadata(metadataJson);
} else {
JSONObject metadataJson = new JSONObject();
workflowDTO.setMetadata(metadataJson);
}
}
}
} catch (SQLException e) {
handleException("Error while retrieving workflow details for " + workflowReference, e);
}
return workflowDTOList;
}

private void setPublishedDefVersion(APIIdentifier apiId, Connection connection, String value)
throws APIManagementException {

Expand Down Expand Up @@ -16741,6 +16790,36 @@ public void addDeployedAPIRevision(String apiRevisionId, List<DeployedAPIRevisio
}
}

/**
* Update the status of the Revision deployment process
*
* @param revisionUUID UUID of the Revision
* @param status Status of the Revision deployment
* @param environment Environment of the Revision deployment
* @throws APIManagementException if an error occurs when updating the status of the Revision deployment
*/
public void updateAPIRevisionDeploymentStatus(String revisionUUID, String status, String environment)
throws APIManagementException {

try (Connection connection = APIMgtDBUtil.getConnection()) {
GihanAyesh marked this conversation as resolved.
Show resolved Hide resolved
try (PreparedStatement statement = connection
.prepareStatement(SQLConstants.APIRevisionSqlConstants.UPDATE_API_REVISION_STATUS_SQL)) {
statement.setString(1, status);
statement.setString(2, revisionUUID);
statement.setString(3, environment);
statement.executeUpdate();
connection.commit();
} catch (SQLException e) {
connection.rollback();
handleException("Failed to update API Revision deployment mapping details for revision: " +
revisionUUID, e);
}
}catch (SQLException e) {
GihanAyesh marked this conversation as resolved.
Show resolved Hide resolved
handleException("Could not open database connection", e);
}

}

/**
* Get APIRevisionDeployment details by providing deployment name and revision uuid
*
Expand Down Expand Up @@ -16807,6 +16886,38 @@ public List<APIRevisionDeployment> getAPIRevisionDeploymentByRevisionUUID(String
return apiRevisionDeploymentList;
}

/**
* Get APIRevisionDeployment details
*
* @param apiUUID API UUID
* @param workflowStatus Workflow status
* @return List<APIRevisionDeployment> APIRevisionDeployment list
* @throws APIManagementException if an error occurs while retrieving revision deployment mapping details
*/
public List<APIRevisionDeployment> getAPIRevisionDeploymentsByWorkflowStatusAndApiUUID(String apiUUID,
String workflowStatus) throws APIManagementException {

List<APIRevisionDeployment> apiRevisionDeploymentList = new ArrayList<>();
try (Connection connection = APIMgtDBUtil.getConnection();
PreparedStatement statement = connection.prepareStatement(
SQLConstants.APIRevisionSqlConstants.GET_API_REVISION_DEPLOYMENT_MAPPINGS_BY_REVISION_STATUS_AND_API_UUID)) {
statement.setString(1, workflowStatus);
statement.setString(2, apiUUID);
try (ResultSet rs = statement.executeQuery()) {
while (rs.next()) {
APIRevisionDeployment apiRevisionDeployment = new APIRevisionDeployment();
String environmentName = rs.getString("NAME");
apiRevisionDeployment.setDeployment(environmentName);
apiRevisionDeployment.setRevisionUUID(rs.getString("REVISION_UUID"));
apiRevisionDeploymentList.add(apiRevisionDeployment);
}
}
} catch (SQLException e) {
handleException("Failed to get API Revision deployment mapping details", e);
}
return apiRevisionDeploymentList;
}

/**
* Get APIRevisionDeployment details by providing API uuid
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3695,24 +3695,30 @@ public static class APIRevisionSqlConstants {
= "SELECT * FROM AM_DEPLOYMENT_REVISION_MAPPING WHERE NAME = ? AND REVISION_UUID = ? ";
public static final String GET_API_REVISION_DEPLOYMENT_MAPPING_BY_REVISION_UUID
= "SELECT * FROM AM_DEPLOYMENT_REVISION_MAPPING WHERE REVISION_UUID = ?";
public static final String GET_API_REVISION_DEPLOYMENT_MAPPINGS_BY_REVISION_STATUS_AND_API_UUID =
"SELECT ADR.NAME, ADR.REVISION_UUID FROM AM_DEPLOYMENT_REVISION_MAPPING AS ADR JOIN "
+ "AM_REVISION AS AM ON ADR.REVISION_UUID = AM.REVISION_UUID WHERE "
+ "ADR.REVISION_STATUS = ? AND AM.API_UUID = ?";
public static final String UPDATE_API_REVISION_STATUS_SQL =
" UPDATE AM_DEPLOYMENT_REVISION_MAPPING SET REVISION_STATUS = ? WHERE REVISION_UUID = ? AND NAME = ?";
static final String GET_API_REVISION_DEPLOYMENTS
= "(SELECT NAME, VHOST, REVISION_UUID, DEPLOYED_TIME, 0 AS DISPLAY_ON_DEVPORTAL, NULL AS DEPLOY_TIME " +
"FROM AM_DEPLOYED_REVISION DR " +
= "(SELECT NAME, VHOST, REVISION_UUID, DEPLOYED_TIME, 0 AS DISPLAY_ON_DEVPORTAL, NULL AS DEPLOY_TIME, "
+ "NULL AS REVISION_STATUS FROM AM_DEPLOYED_REVISION DR " +
"UNION " +
"SELECT NAME, VHOST, REVISION_UUID, NULL AS DEPLOYED_TIME, DISPLAY_ON_DEVPORTAL, " +
"DEPLOYED_TIME AS DEPLOY_TIME " +
"DEPLOYED_TIME AS DEPLOY_TIME, REVISION_STATUS " +
"FROM AM_DEPLOYMENT_REVISION_MAPPING DRM) ";
public static final String GET_API_REVISION_DEPLOYMENTS_BY_API_UUID
= "SELECT * FROM " + GET_API_REVISION_DEPLOYMENTS + "AD " +
"WHERE AD.REVISION_UUID " +
"IN " +
"(SELECT REVISION_UUID FROM AM_REVISION WHERE API_UUID = ?)";
static final String GET_API_REVISION_DEPLOYMENTS_POSTGRES
= "(SELECT NAME, VHOST, REVISION_UUID, DEPLOYED_TIME, false AS DISPLAY_ON_DEVPORTAL, NULL AS DEPLOY_TIME " +
"FROM AM_DEPLOYED_REVISION DR " +
= "(SELECT NAME, VHOST, REVISION_UUID, DEPLOYED_TIME, false AS DISPLAY_ON_DEVPORTAL, " +
"NULL AS DEPLOY_TIME, NULL AS REVISION_STATUS FROM AM_DEPLOYED_REVISION DR " +
"UNION " +
"SELECT NAME, VHOST, REVISION_UUID, NULL AS DEPLOYED_TIME, DISPLAY_ON_DEVPORTAL, " +
"DEPLOYED_TIME AS DEPLOY_TIME " +
"DEPLOYED_TIME AS DEPLOY_TIME, REVISION_STATUS " +
"FROM AM_DEPLOYMENT_REVISION_MAPPING DRM) ";
public static final String GET_API_REVISION_DEPLOYMENTS_BY_API_UUID_POSTGRES
= "SELECT * FROM " + GET_API_REVISION_DEPLOYMENTS_POSTGRES + "AD " +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.apimgt.impl.dto;

import org.wso2.carbon.apimgt.api.model.APIRevision;

/**
* APIRevision DTO class for workflow
*/
public class APIRevisionWorkflowDTO extends WorkflowDTO {
private APIRevision revision;
private String userName;
private String environment;
private String revisionId;
private String apiName;
private String apiProvider;
private String apiVersion;

public APIRevision getAPIRevision() {
return revision;
}

public void setAPIRevision(APIRevision revision) {
this.revision = revision;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getEnvironment() {
return environment;
}

public void setEnvironment(String environment) {
this.environment = environment;
}

public String getRevisionId() {
return revisionId;
}

public void setRevisionId(String revisionId) {
this.revisionId = revisionId;
}

public String getApiProvider() {
return apiProvider;
}

public void setApiProvider(String apiProvider) {
this.apiProvider = apiProvider;
}

public String getApiName() {
return apiName;
}

public void setApiName(String apiName) {
this.apiName = apiName;
}

public String getApiVersion() {
return apiVersion;
}

public void setApiVersion(String apiVersion) {
this.apiVersion = apiVersion;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.api.APIManagerDatabaseException;
import org.wso2.carbon.apimgt.api.WorkflowStatus;
import org.wso2.carbon.apimgt.api.model.APIRevisionDeployment;
import org.wso2.carbon.apimgt.impl.APIManagerConfiguration;
import org.wso2.carbon.apimgt.impl.internal.ServiceReferenceHolder;
Expand Down Expand Up @@ -245,11 +246,30 @@ public static List<APIRevisionDeployment> mergeRevisionDeploymentDTOs(ResultSet
String revisionUuid = rs.getString("REVISION_UUID");
String uniqueKey = (environmentName != null ? environmentName : "") +
(vhost != null ? vhost : "") + (revisionUuid != null ? revisionUuid : "");
String revisionStatus = rs.getString("REVISION_STATUS");
WorkflowStatus status = null;
if (revisionStatus != null) {
switch (revisionStatus) {
case "CREATED":
status = WorkflowStatus.CREATED;
break;
case "APPROVED":
status = WorkflowStatus.APPROVED;
break;
case "REJECTED":
status = WorkflowStatus.REJECTED;
break;
default:
// Handle the case where revisionStatus is not one of the expected values
break;
}
}
if (!uniqueSet.containsKey(uniqueKey)) {
apiRevisionDeployment = new APIRevisionDeployment();
apiRevisionDeployment.setDeployment(environmentName);
apiRevisionDeployment.setVhost(vhost);
apiRevisionDeployment.setRevisionUUID(revisionUuid);
apiRevisionDeployment.setStatus(status);
apiRevisionDeployment.setDisplayOnDevportal(rs.getBoolean("DISPLAY_ON_DEVPORTAL"));
apiRevisionDeployment.setDeployedTime(rs.getString("DEPLOY_TIME"));
apiRevisionDeployment.setSuccessDeployedTime(rs.getString("DEPLOYED_TIME"));
Expand Down
Loading