From bd80f45ea8d1932abdfe80a6a914e2cfa0aba7b7 Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Thu, 7 Dec 2023 14:15:16 +0530 Subject: [PATCH] Fix to save advance configs under x-wso2 production and sandbox endpoints. Fixes https://github.com/wso2/api-manager/issues/2280 --- .../impl/definitions/OASParserUtil.java | 59 +++++++--- .../common/mappings/PublisherCommonUtils.java | 106 +++++++++++++++++- 2 files changed, 146 insertions(+), 19 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/definitions/OASParserUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/definitions/OASParserUtil.java index f828e8db2ab0..b75039b4b617 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/definitions/OASParserUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/definitions/OASParserUtil.java @@ -1241,7 +1241,8 @@ public static URITemplate setScopesToTemplate(URITemplate template, List * @param isProduction is production endpoints * @return JsonNode */ - public static JsonNode generateOASConfigForEndpoints(API api, boolean isProduction) { + public static JsonNode generateOASConfigForEndpoints(API api, boolean isProduction) + throws APIManagementException { if (api.getEndpointConfig() == null || api.getEndpointConfig().trim().isEmpty()) { return null; } @@ -1297,7 +1298,8 @@ private static void populateEndpointSecurity(API api, ObjectNode endpointResult) * @param endpointConfig endpoint configuration json string * @param isProd endpoint type */ - private static ObjectNode populateFailoverConfig(JSONObject endpointConfig, boolean isProd) { + private static ObjectNode populateFailoverConfig(JSONObject endpointConfig, boolean isProd) + throws APIManagementException { JSONArray endpointsURLs = null; JSONObject primaryEndpoints = null; if (isProd) { @@ -1332,7 +1334,7 @@ private static ObjectNode populateFailoverConfig(JSONObject endpointConfig, bool ObjectNode endpointResult = objectMapper.createObjectNode(); endpointResult.set(APIConstants.ENDPOINT_URLS, endpointsArray); endpointResult.put(APIConstants.X_WSO2_ENDPOINT_TYPE, APIConstants.ENDPOINT_TYPE_FAILOVER); - return endpointResult; + return updateEndpointResult(primaryEndpoints, endpointResult); } /** @@ -1341,7 +1343,8 @@ private static ObjectNode populateFailoverConfig(JSONObject endpointConfig, bool * @param endpointConfig endpoint configuration json string * @param isProd endpoint type */ - private static ObjectNode populateLoadBalanceConfig(JSONObject endpointConfig, boolean isProd) { + private static ObjectNode populateLoadBalanceConfig(JSONObject endpointConfig, boolean isProd) + throws APIManagementException { JSONArray primaryProdEndpoints = new JSONArray(); if (isProd) { if (endpointConfig.has(APIConstants.ENDPOINT_PRODUCTION_ENDPOINTS) && endpointConfig @@ -1368,6 +1371,15 @@ private static ObjectNode populateLoadBalanceConfig(JSONObject endpointConfig, b ObjectNode endpointResult = objectMapper.createObjectNode(); endpointResult.set(APIConstants.ENDPOINT_URLS, endpointsArray); endpointResult.put(APIConstants.X_WSO2_ENDPOINT_TYPE, APIConstants.ENDPOINT_TYPE_LOADBALANCE); + + if (primaryProdEndpoints != null) { + for (int i = 0; i < primaryProdEndpoints.length(); i++) { + if (primaryProdEndpoints.getJSONObject(i).has(APIConstants.ADVANCE_ENDPOINT_CONFIG)) { + return updateEndpointResult(primaryProdEndpoints.getJSONObject(i), endpointResult); + } + } + } + return endpointResult; } @@ -1378,7 +1390,8 @@ private static ObjectNode populateLoadBalanceConfig(JSONObject endpointConfig, b * @param isProd endpoint type * @param type endpoint type */ - private static ObjectNode setPrimaryConfig(JSONObject endpointConfig, boolean isProd, String type) { + private static ObjectNode setPrimaryConfig(JSONObject endpointConfig, boolean isProd, String type) + throws APIManagementException { JSONObject primaryEndpoints = new JSONObject(); if (isProd) { if (endpointConfig.has(APIConstants.ENDPOINT_PRODUCTION_ENDPOINTS)) { @@ -1395,22 +1408,34 @@ private static ObjectNode setPrimaryConfig(JSONObject endpointConfig, boolean is ObjectNode endpointResult = objectMapper.createObjectNode(); endpointResult.set(APIConstants.ENDPOINT_URLS, endpointsArray); endpointResult.put(APIConstants.X_WSO2_ENDPOINT_TYPE, type); - if (primaryEndpoints.has(APIConstants.ADVANCE_ENDPOINT_CONFIG) - && primaryEndpoints.get(APIConstants.ADVANCE_ENDPOINT_CONFIG) != JSONObject.NULL) { - JSONObject advanceEndpointConfig = primaryEndpoints.getJSONObject(APIConstants.ADVANCE_ENDPOINT_CONFIG); - ObjectNode advanceEndpointsObject = objectMapper.createObjectNode(); - if (advanceEndpointConfig.has(APIConstants.TIMEOUT_IN_MILLIS) - && advanceEndpointConfig.get(APIConstants.TIMEOUT_IN_MILLIS) != JSONObject.NULL) { - advanceEndpointsObject.put(APIConstants.TIMEOUT_IN_MILLIS, - advanceEndpointConfig.getInt(APIConstants.TIMEOUT_IN_MILLIS)); - endpointResult.set(APIConstants.ADVANCE_ENDPOINT_CONFIG, advanceEndpointsObject); - } - } - return endpointResult; + return updateEndpointResult(primaryEndpoints, endpointResult); } return null; } + /** + * Add advance configuration to the endpointResult object + * + * @param primaryEndpoints production and sandbox endpoint configuration Json object + * @param endpointResult endpoint result ObjectNode + */ + private static ObjectNode updateEndpointResult(JSONObject primaryEndpoints, ObjectNode endpointResult) + throws APIManagementException { + if (primaryEndpoints.has(APIConstants.ADVANCE_ENDPOINT_CONFIG)) { + try { + endpointResult.put(APIConstants.ADVANCE_ENDPOINT_CONFIG, objectMapper + .readTree(primaryEndpoints.get(APIConstants.ADVANCE_ENDPOINT_CONFIG).toString())); + } catch (JsonProcessingException e) { + throw new APIManagementException( + "Error while setting the advance endpoint configs ", e); + } + } else { + //When user removes existing advancedConfigurations section.Returns null if key was not an existing + endpointResult.remove(APIConstants.ADVANCE_ENDPOINT_CONFIG); + } + return endpointResult; + } + /** * remove publisher/MG related extension from OAS * diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java index a33cd065bb03..8d86ea9fa643 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java @@ -18,6 +18,8 @@ package org.wso2.carbon.apimgt.rest.api.publisher.v1.common.mappings; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import graphql.language.FieldDefinition; import graphql.language.ObjectTypeDefinition; @@ -29,11 +31,12 @@ import graphql.schema.idl.errors.SchemaProblem; import graphql.schema.validation.SchemaValidationError; import graphql.schema.validation.SchemaValidator; +import io.swagger.v3.parser.ObjectMapperFactory; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.json.JSONArray; +import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; @@ -1063,7 +1066,7 @@ private static void extractURLsFromEndpointConfig(org.json.JSONObject endpointCo if (endpointObj != null) { endpoints.add(endpointConfigObj.getJSONObject(endpointType).getString(APIConstants.API_DATA_URL)); } else { - JSONArray endpointArray = endpointConfigObj.getJSONArray(endpointType); + org.json.JSONArray endpointArray = endpointConfigObj.getJSONArray(endpointType); for (int i = 0; i < endpointArray.length(); i++) { endpoints.add((String) endpointArray.getJSONObject(i).get(APIConstants.API_DATA_URL)); } @@ -1467,6 +1470,105 @@ private static void prepareForUpdateSwagger(String apiId, APIDefinitionValidatio existingAPI.setUriTemplates(uriTemplates); existingAPI.setScopes(scopes); + try { + ObjectMapper mapper = ObjectMapperFactory.createJson(); + JsonNode newProductionEndpointJson = mapper.readTree(apiDefinition) + .get(APIConstants.X_WSO2_PRODUCTION_ENDPOINTS); + JsonNode newSandboxEndpointJson = mapper.readTree(apiDefinition) + .get(APIConstants.X_WSO2_SANDBOX_ENDPOINTS); + String existingEndpointConfigString = existingAPI.getEndpointConfig(); + + if (StringUtils.isNotEmpty(existingEndpointConfigString)) { //check if endpoints are configured + JSONObject existingEndpointConfigJson = (JSONObject) new JSONParser() + .parse(existingEndpointConfigString); + if (newProductionEndpointJson != null) { + if (existingEndpointConfigJson.get(APIConstants.ENDPOINT_PRODUCTION_ENDPOINTS) != null) { + //put as a value under the ENDPOINT_PRODUCTION_ENDPOINTS key + //if loadbalance endpoints, get relevant jsonobject from array + if (existingEndpointConfigJson.get(APIConstants.API_ENDPOINT_CONFIG_PROTOCOL_TYPE) + .equals(APIConstants.ENDPOINT_TYPE_LOADBALANCE)) { + JSONArray productionConfigsJson = (JSONArray) existingEndpointConfigJson + .get(APIConstants.ENDPOINT_PRODUCTION_ENDPOINTS); + for (int i = 0; i < productionConfigsJson.size(); i++) { + if (!(((JSONObject) productionConfigsJson.get(i)).containsKey(APIConstants + .API_ENDPOINT_CONFIG_PROTOCOL_TYPE))) { + if (newProductionEndpointJson.has(APIConstants + .ADVANCE_ENDPOINT_CONFIG)) { + JsonNode advanceConfig = newProductionEndpointJson + .get(APIConstants.ADVANCE_ENDPOINT_CONFIG); + ((JSONObject) productionConfigsJson.get(i)) + .put(APIConstants.ADVANCE_ENDPOINT_CONFIG, advanceConfig); + } else { + ((JSONObject) productionConfigsJson.get(i)) + .remove(APIConstants.ADVANCE_ENDPOINT_CONFIG); + } + break; + } + } + existingEndpointConfigJson.put(APIConstants.ENDPOINT_PRODUCTION_ENDPOINTS, + productionConfigsJson); + } else { + JSONObject productionConfigsJson = (JSONObject) existingEndpointConfigJson + .get(APIConstants.ENDPOINT_PRODUCTION_ENDPOINTS); + if (newProductionEndpointJson.has(APIConstants.ADVANCE_ENDPOINT_CONFIG)) { + JsonNode advanceConfig = newProductionEndpointJson + .get(APIConstants.ADVANCE_ENDPOINT_CONFIG); + productionConfigsJson.put(APIConstants.ADVANCE_ENDPOINT_CONFIG, advanceConfig); + } else { + productionConfigsJson.remove(APIConstants.ADVANCE_ENDPOINT_CONFIG); + } + existingEndpointConfigJson.put(APIConstants.ENDPOINT_PRODUCTION_ENDPOINTS, + productionConfigsJson); + } + } + } + if (newSandboxEndpointJson != null) { + if (existingEndpointConfigJson.get(APIConstants.ENDPOINT_SANDBOX_ENDPOINTS) != null) { + //put as a value under the ENDPOINT_SANDBOX_ENDPOINTS key + //if loadbalance endpoints, get relevant jsonobject from array + if (existingEndpointConfigJson.get(APIConstants.API_ENDPOINT_CONFIG_PROTOCOL_TYPE) + .equals(APIConstants.ENDPOINT_TYPE_LOADBALANCE)) { + JSONArray sandboxConfigsJson = (JSONArray) existingEndpointConfigJson + .get(APIConstants.ENDPOINT_SANDBOX_ENDPOINTS); + for (int i = 0; i < sandboxConfigsJson.size(); i++) { + if (!(((JSONObject) sandboxConfigsJson.get(i)).containsKey(APIConstants + .API_ENDPOINT_CONFIG_PROTOCOL_TYPE))) { + if (newSandboxEndpointJson.has(APIConstants + .ADVANCE_ENDPOINT_CONFIG)) { + JsonNode advanceConfig = newSandboxEndpointJson + .get(APIConstants.ADVANCE_ENDPOINT_CONFIG); + ((JSONObject) sandboxConfigsJson.get(i)) + .put(APIConstants.ADVANCE_ENDPOINT_CONFIG, advanceConfig); + } else { + ((JSONObject) sandboxConfigsJson.get(i)) + .remove(APIConstants.ADVANCE_ENDPOINT_CONFIG); + } + break; + } + } + existingEndpointConfigJson.put(APIConstants.ENDPOINT_SANDBOX_ENDPOINTS, + sandboxConfigsJson); + } else { + JSONObject sandboxConfigsJson = (JSONObject) existingEndpointConfigJson + .get(APIConstants.ENDPOINT_SANDBOX_ENDPOINTS); + if (newSandboxEndpointJson.has(APIConstants.ADVANCE_ENDPOINT_CONFIG)) { + JsonNode advanceConfig = newSandboxEndpointJson + .get(APIConstants.ADVANCE_ENDPOINT_CONFIG); + sandboxConfigsJson.put(APIConstants.ADVANCE_ENDPOINT_CONFIG, advanceConfig); + } else { + sandboxConfigsJson.remove(APIConstants.ADVANCE_ENDPOINT_CONFIG); + } + existingEndpointConfigJson.put(APIConstants.ENDPOINT_SANDBOX_ENDPOINTS, + sandboxConfigsJson); + } + } + } + existingAPI.setEndpointConfig(existingEndpointConfigJson.toString()); + } + } catch (ParseException | JsonProcessingException e) { + throw new APIManagementException("Error when parsing endpoint configurations ", e); + } + PublisherCommonUtils.validateScopes(existingAPI); SwaggerData swaggerData = new SwaggerData(existingAPI);