diff options
-rw-r--r-- | src/main/java/org/onap/clamp/clds/model/properties/Holmes.java | 16 | ||||
-rw-r--r-- | src/main/java/org/onap/clamp/loop/LoopOperation.java | 251 | ||||
-rw-r--r-- | src/main/resources/application-noaaf.properties | 5 | ||||
-rw-r--r-- | src/main/resources/application.properties | 5 | ||||
-rw-r--r-- | src/main/resources/clds/camel/rest/clamp-api-v2.xml | 103 | ||||
-rw-r--r-- | src/main/resources/clds/camel/routes/flexible-flow.xml | 215 | ||||
-rw-r--r-- | src/test/java/org/onap/clamp/loop/LoopOperationTestItCase.java | 250 | ||||
-rw-r--r-- | src/test/resources/application.properties | 5 | ||||
-rwxr-xr-x | src/test/resources/http-cache/third_party_proxy.py | 12 |
9 files changed, 768 insertions, 94 deletions
diff --git a/src/main/java/org/onap/clamp/clds/model/properties/Holmes.java b/src/main/java/org/onap/clamp/clds/model/properties/Holmes.java index a93b09cfa..a56c57d19 100644 --- a/src/main/java/org/onap/clamp/clds/model/properties/Holmes.java +++ b/src/main/java/org/onap/clamp/clds/model/properties/Holmes.java @@ -26,11 +26,11 @@ package org.onap.clamp.clds.model.properties; import com.google.gson.JsonObject; + import org.onap.clamp.clds.util.JsonUtils; /** - * Parse Holmes bpmn parameters json properties. - * Example json: + * Parse Holmes bpmn parameters json properties. Example json: * [{"name":"correlationalLogic","value":"vcwx"},{"name":"configPolicyName","value":"cccc"}] */ public class Holmes extends AbstractModelElement { @@ -43,14 +43,18 @@ public class Holmes extends AbstractModelElement { /** * Default constructor for Holmes Element. * - * @param modelBpmn The model bpmn - * @param modelJson The model json + * @param modelBpmn + * The model bpmn + * @param modelJson + * The model json */ public Holmes(ModelBpmn modelBpmn, JsonObject modelJson) { super(TYPE_HOLMES, modelBpmn, modelJson); - correlationLogic = JsonUtils.getStringValueByName(modelElementJsonNode, "correlationalLogic"); - configPolicyName = JsonUtils.getStringValueByName(modelElementJsonNode, "configPolicyName"); + if (modelElementJsonNode != null) { + correlationLogic = JsonUtils.getStringValueByName(modelElementJsonNode, "correlationalLogic"); + configPolicyName = JsonUtils.getStringValueByName(modelElementJsonNode, "configPolicyName"); + } } public static final String getType() { diff --git a/src/main/java/org/onap/clamp/loop/LoopOperation.java b/src/main/java/org/onap/clamp/loop/LoopOperation.java index 3f4c52939..c3eb08be7 100644 --- a/src/main/java/org/onap/clamp/loop/LoopOperation.java +++ b/src/main/java/org/onap/clamp/loop/LoopOperation.java @@ -31,23 +31,21 @@ import com.google.gson.JsonNull; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; +import java.io.IOException; import java.lang.reflect.Array; import java.util.Collection; -import java.util.Date; +import java.util.Iterator; import java.util.Map; - -import javax.servlet.http.HttpServletRequest; +import java.util.Set; import org.apache.camel.Exchange; -import org.onap.clamp.clds.client.DcaeDispatcherServices; +import org.apache.camel.Message; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; import org.onap.clamp.clds.config.ClampProperties; -import org.onap.clamp.clds.util.LoggingUtils; -import org.onap.clamp.clds.util.ONAPLogConstants; -import org.onap.clamp.exception.OperationException; -import org.onap.clamp.util.HttpConnectionManager; -import org.slf4j.event.Level; +import org.onap.clamp.policy.operational.OperationalPolicy; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.yaml.snakeyaml.Yaml; @@ -59,117 +57,198 @@ public class LoopOperation { protected static final EELFLogger logger = EELFManager.getInstance().getLogger(LoopOperation.class); protected static final EELFLogger auditLogger = EELFManager.getInstance().getMetricsLogger(); - private final DcaeDispatcherServices dcaeDispatcherServices; + private static final String DCAE_LINK_FIELD = "links"; + private static final String DCAE_STATUS_FIELD = "status"; + private static final String DCAE_DEPLOYMENT_TEMPLATE = "dcae.deployment.template"; + private static final String DCAE_SERVICETYPE_ID = "serviceTypeId"; + private static final String DCAE_INPUTS = "inputs"; + private static final String DCAE_DEPLOYMENT_PREFIX = "closedLoop_"; + private static final String DCAE_DEPLOYMENT_SUFIX = "_deploymentId"; private final LoopService loopService; - private LoggingUtils util = new LoggingUtils(logger); + private final ClampProperties refProp; - @Autowired - private HttpServletRequest request; + public enum TempLoopState { + NOT_SUBMITTED, SUBMITTED, DEPLOYED, NOT_DEPLOYED, PROCESSING, IN_ERROR; + } + /** + * The constructor. + * @param loopService The loop service + * @param refProp The clamp properties + */ @Autowired - public LoopOperation(LoopService loopService, DcaeDispatcherServices dcaeDispatcherServices, - ClampProperties refProp, HttpConnectionManager httpConnectionManager) { + public LoopOperation(LoopService loopService, ClampProperties refProp) { this.loopService = loopService; - this.dcaeDispatcherServices = dcaeDispatcherServices; + this.refProp = refProp; } - + /** - * Deploy the closed loop. + * Get the payload used to send the deploy closed loop request. * - * @param loopName - * the loop name - * @return the updated loop - * @throws OperationException - * Exception during the operation + * @param loop The loop + * @return The payload used to send deploy closed loop request + * @throws IOException IOException */ - public Loop deployLoop(Exchange camelExchange, String loopName) throws OperationException { - util.entering(request, "CldsService: Deploy model"); - Date startTime = new Date(); - Loop loop = loopService.getLoop(loopName); - - if (loop == null) { - String msg = "Deploy loop exception: Not able to find closed loop:" + loopName; - util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.toString(), msg, Level.INFO, - ONAPLogConstants.ResponseStatus.ERROR); - throw new OperationException(msg); - } + public String getDeployPayload(Loop loop) throws IOException { + Yaml yaml = new Yaml(); + Map<String, Object> yamlMap = yaml.load(loop.getBlueprint()); + JsonObject bluePrint = wrapSnakeObject(yamlMap).getAsJsonObject(); + + String serviceTypeId = loop.getDcaeBlueprintId(); - // verify the current closed loop state - if (loop.getLastComputedState() != LoopState.SUBMITTED) { - String msg = "Deploy loop exception: This closed loop is in state:" + loop.getLastComputedState() - + ". It could be deployed only when it is in SUBMITTED state."; - util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, ONAPLogConstants.ResponseStatus.ERROR); - throw new OperationException(msg); + JsonObject rootObject = refProp.getJsonTemplate(DCAE_DEPLOYMENT_TEMPLATE).getAsJsonObject(); + rootObject.addProperty(DCAE_SERVICETYPE_ID, serviceTypeId); + if (bluePrint != null) { + rootObject.add(DCAE_INPUTS, bluePrint); } + String apiBodyString = rootObject.toString(); + logger.info("Dcae api Body String - " + apiBodyString); + return apiBodyString; + } + + /** + * Get the deployment id. + * + * @param loop The loop + * @return The deployment id + * @throws IOException IOException + */ + public String getDeploymentId(Loop loop) { // Set the deploymentId if not present yet String deploymentId = ""; // If model is already deployed then pass same deployment id if (loop.getDcaeDeploymentId() != null && !loop.getDcaeDeploymentId().isEmpty()) { deploymentId = loop.getDcaeDeploymentId(); } else { - loop.setDcaeDeploymentId(deploymentId = "closedLoop_" + loopName + "_deploymentId"); + deploymentId = DCAE_DEPLOYMENT_PREFIX + loop.getName() + DCAE_DEPLOYMENT_SUFIX; } + return deploymentId; + } - Yaml yaml = new Yaml(); - Map<String, Object> yamlMap = yaml.load(loop.getBlueprint()); - JsonObject bluePrint = wrapSnakeObject(yamlMap).getAsJsonObject(); + /** + * Update the loop info. + * + * @param camelExchange The camel exchange + * @param loop The loop + * @param deploymentId The deployment id + * @throws ParseException The parse exception + */ + public void updateLoopInfo(Exchange camelExchange, Loop loop, String deploymentId) throws ParseException { + Message in = camelExchange.getIn(); + String msg = in.getBody(String.class); - loop.setDcaeDeploymentStatusUrl( - dcaeDispatcherServices.createNewDeployment(deploymentId, loop.getDcaeBlueprintId(), bluePrint)); - loop.setLastComputedState(LoopState.DEPLOYED); - // save the updated loop + JSONParser parser = new JSONParser(); + Object obj0 = parser.parse(msg); + JSONObject jsonObj = (JSONObject) obj0; + + JSONObject linksObj = (JSONObject) jsonObj.get(DCAE_LINK_FIELD); + String statusUrl = (String) linksObj.get(DCAE_STATUS_FIELD); + + // use http4 instead of http, because camel http4 component is used to do the http call + String newStatusUrl = statusUrl.replaceAll("http:", "http4:"); + + loop.setDcaeDeploymentId(deploymentId); + loop.setDcaeDeploymentStatusUrl(newStatusUrl); loopService.saveOrUpdateLoop(loop); + } - // audit log - LoggingUtils.setTimeContext(startTime, new Date()); - auditLogger.info("Deploy model completed"); - util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED); - return loop; + /** + * Get the Closed Loop status based on the reply from Policy. + * + * @param statusCode The status code + * @return The state based on policy response + * @throws ParseException The parse exception + */ + public String analysePolicyResponse(int statusCode) { + if (statusCode == 200) { + return TempLoopState.SUBMITTED.toString(); + } else if (statusCode == 404) { + return TempLoopState.NOT_SUBMITTED.toString(); + } + return TempLoopState.IN_ERROR.toString(); } /** - * Un deploy closed loop. + * Get the name of the first Operational policy. * - * @param loopName - * the loop name - * @return the updated loop + * @param loop The closed loop + * @return The name of the first operational policy */ - public Loop unDeployLoop(String loopName) throws OperationException { - util.entering(request, "LoopOperation: Undeploy the closed loop"); - Date startTime = new Date(); - Loop loop = loopService.getLoop(loopName); - - if (loop == null) { - String msg = "Undeploy loop exception: Not able to find closed loop:" + loopName; - util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.toString(), msg, Level.INFO, - ONAPLogConstants.ResponseStatus.ERROR); - throw new OperationException(msg); + public String getOperationalPolicyName(Loop loop) { + Set<OperationalPolicy> opSet = (Set<OperationalPolicy>)loop.getOperationalPolicies(); + Iterator<OperationalPolicy> iterator = opSet.iterator(); + while (iterator.hasNext()) { + OperationalPolicy policy = iterator.next(); + return policy.getName(); } + return null; + } - // verify the current closed loop state - if (loop.getLastComputedState() != LoopState.DEPLOYED) { - String msg = "Unploy loop exception: This closed loop is in state:" + loop.getLastComputedState() - + ". It could be undeployed only when it is in DEPLOYED state."; - util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, ONAPLogConstants.ResponseStatus.ERROR); - throw new OperationException(msg); + /** + * Get the Closed Loop status based on the reply from DCAE. + * + * @param camelExchange The camel exchange + * @return The state based on DCAE response + * @throws ParseException The parse exception + */ + public String analyseDcaeResponse(Exchange camelExchange, Integer statusCode) throws ParseException { + if (statusCode == null) { + return TempLoopState.NOT_DEPLOYED.toString(); } + if (statusCode == 200) { + Message in = camelExchange.getIn(); + String msg = in.getBody(String.class); - loop.setDcaeDeploymentStatusUrl( - dcaeDispatcherServices.deleteExistingDeployment(loop.getDcaeDeploymentId(), loop.getDcaeBlueprintId())); + JSONParser parser = new JSONParser(); + Object obj0 = parser.parse(msg); + JSONObject jsonObj = (JSONObject) obj0; - // clean the deployment ID - loop.setDcaeDeploymentId(null); - loop.setLastComputedState(LoopState.SUBMITTED); + String opType = (String) jsonObj.get("operationType"); + String status = (String) jsonObj.get("status"); - // save the updated loop - loopService.saveOrUpdateLoop(loop); + // status = processing/successded/failed + if (status.equals("succeeded")) { + if (opType.equals("install")) { + return TempLoopState.DEPLOYED.toString(); + } else if (opType.equals("uninstall")) { + return TempLoopState.NOT_DEPLOYED.toString(); + } + } else if (status.equals("processing")) { + return TempLoopState.PROCESSING.toString(); + } + } else if (statusCode == 404) { + return TempLoopState.NOT_DEPLOYED.toString(); + } + return TempLoopState.IN_ERROR.toString(); + } - // audit log - LoggingUtils.setTimeContext(startTime, new Date()); - auditLogger.info("Undeploy model completed"); - util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED); - return loop; + /** + * Update the status of the closed loop based on the response from Policy and DCAE. + * + * @param loop The closed loop + * @param policyState The state get from Policy + * @param dcaeState The state get from DCAE + * @throws ParseException The parse exception + */ + public LoopState updateLoopStatus(Loop loop, TempLoopState policyState, TempLoopState dcaeState) { + LoopState clState = LoopState.IN_ERROR; + if (policyState == TempLoopState.SUBMITTED) { + if (dcaeState == TempLoopState.DEPLOYED) { + clState = LoopState.DEPLOYED; + } else if (dcaeState == TempLoopState.PROCESSING) { + clState = LoopState.WAITING; + } else if (dcaeState == TempLoopState.NOT_DEPLOYED) { + clState = LoopState.SUBMITTED; + } + } else if (policyState == TempLoopState.NOT_SUBMITTED) { + if (dcaeState == TempLoopState.NOT_DEPLOYED) { + clState = LoopState.DESIGN; + } + } + loop.setLastComputedState(clState); + loopService.saveOrUpdateLoop(loop); + return clState; } private JsonElement wrapSnakeObject(Object obj) { diff --git a/src/main/resources/application-noaaf.properties b/src/main/resources/application-noaaf.properties index de3f7c07a..52f79bef4 100644 --- a/src/main/resources/application-noaaf.properties +++ b/src/main/resources/application-noaaf.properties @@ -210,6 +210,11 @@ clamp.config.dcae.dispatcher.url=http://dcae.api.simpledemo.onap.org:8188 clamp.config.dcae.dispatcher.retry.interval=20000 clamp.config.dcae.dispatcher.retry.limit=30 +#DCAE Deployment Url Properties +clamp.config.dcae.deployment.url=http4://dcae.api.simpledemo.onap.org:8188 +clamp.config.dcae.deployment.userName=test +clamp.config.dcae.deployment.password=test + #Define user permission related parameters, the permission type can be changed but MUST be redefined in clds-users.properties in that case ! clamp.config.security.permission.type.cl=org.onap.clamp.clds.cl clamp.config.security.permission.type.cl.manage=org.onap.clamp.clds.cl.manage diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f59b8ac64..534dc4818 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -228,6 +228,11 @@ clamp.config.dcae.dispatcher.url=http://dcae.api.simpledemo.onap.org:8188 clamp.config.dcae.dispatcher.retry.interval=20000 clamp.config.dcae.dispatcher.retry.limit=30 +#DCAE Deployment Url Properties +clamp.config.dcae.deployment.url=http4://dcae.api.simpledemo.onap.org:8188 +clamp.config.dcae.deployment.userName=test +clamp.config.dcae.deployment.password=test + #Define user permission related parameters, the permission type can be changed but MUST be redefined in clds-users.properties in that case ! clamp.config.security.permission.type.cl=org.onap.clamp.clds.cl clamp.config.security.permission.type.cl.manage=org.onap.clamp.clds.cl.manage diff --git a/src/main/resources/clds/camel/rest/clamp-api-v2.xml b/src/main/resources/clds/camel/rest/clamp-api-v2.xml index 4c1cd8126..4d3c6b389 100644 --- a/src/main/resources/clds/camel/rest/clamp-api-v2.xml +++ b/src/main/resources/clds/camel/rest/clamp-api-v2.xml @@ -206,7 +206,30 @@ <to uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> <to - uri="bean:org.onap.clamp.operation.LoopOperation?method=deployLoop(*,${header.loopName})" /> + uri="direct:load-loop" /> + <to + uri="direct:get-status-from-policy" /> + <to + uri="direct:get-status-from-dcae" /> + <log + loggingLevel="INFO" + message="policy status0000: ${exchangeProperty[policyStatus]}"></log> + <choice> + <when> + <simple> ${exchangeProperty[policyStatus]} == 'SUBMITTED' and + ${exchangeProperty[dcaeStatus]} == 'NOT_DEPLOYED' + </simple> + <to + uri="direct:deploy-closedloop" /> + </when> + <otherwise> + <log + loggingLevel="INFO" + message="Closed Loop is in state ${exchangeProperty[policyStatus]}, it can only be deployed when in state SUBMIT" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Closed Loop is in state ${exchangeProperty[policyStatus]}, it can only be deployed when in state SUBMIT','ERROR',${exchangeProperty[loopObject]})" /> + </otherwise> + </choice> <to uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> <doCatch> @@ -216,6 +239,11 @@ </handled> <to uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log + loggingLevel="ERROR" + message="Deploy request failed for loop: ${header.loopName}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Deploy request failed','ERROR',${exchangeProperty[loopObject]})" /> </doCatch> </doTry> </route> @@ -234,7 +262,24 @@ <to uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> <to - uri="bean:org.onap.clamp.operation.LoopOperation?method=unDeployLoop(${header.loopName})" /> + uri="direct:load-loop" /> + <to + uri="direct:get-status-from-dcae" /> + <choice> + <when> + <simple> ${exchangeProperty[dcaeStatus]} == 'DEPLOYED' + </simple> + <to + uri="direct:undeploy-closedloop" /> + </when> + <otherwise> + <log + loggingLevel="INFO" + message="Closed Loop is in state ${exchangeProperty[dcaeStatus]}, it can only be undeployed when in state DEPLOYED" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Closed Loop is in state ${exchangeProperty[dcaeStatus]}, it can only be deployed when in state DEPLOYED','ERROR',${exchangeProperty[loopObject]})" /> + </otherwise> + </choice> <to uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> <doCatch> @@ -244,6 +289,11 @@ </handled> <to uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log + loggingLevel="ERROR" + message="Undeploy request failed for loop: $${header.loopName}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Undeploy request failed','ERROR',${exchangeProperty[loopObject]})" /> </doCatch> </doTry> </route> @@ -526,5 +576,54 @@ </doTry> </route> </put> + <get + uri="/v2/loop/getstatus/{loopName}" + outType="org.onap.clamp.loop.Loop" + produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="loopName"/> + <doTry> + <log + loggingLevel="INFO" + message="Get current status for loop: ${header.loopName}" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Get the closed loop status')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','read')" /> + <to uri="direct:load-loop" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Receive GET STATUS request','INFO',${exchangeProperty[loopObject]})" /> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + <to uri="direct:get-status-from-policy" /> + <to uri="direct:get-status-from-dcae" /> + <to + uri="bean:org.onap.clamp.loop.LoopOperation?method=updateLoopStatus(${exchangeProperty[loopObject]},${exchangeProperty[policyStatus]}, ${exchangeProperty[dcaeStatus]})" /> + <log + loggingLevel="INFO" + message="Get Status request successfully executed. The new state is: ${body}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Get Status request successfully executed','INFO',${exchangeProperty[loopObject]})" /> + <to + uri="bean:org.onap.clamp.loop.LoopController?method=getLoop(${header.loopName})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>false</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log + loggingLevel="ERROR" + message="Get Status request failed for loop: ${header.loopName}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Get Status request failed','ERROR',${exchangeProperty[loopObject]})" /> + </doCatch> + </doTry> + </route> + </get> </rest> </rests> diff --git a/src/main/resources/clds/camel/routes/flexible-flow.xml b/src/main/resources/clds/camel/routes/flexible-flow.xml index 1ae6e3d96..8cf1cdfd8 100644 --- a/src/main/resources/clds/camel/routes/flexible-flow.xml +++ b/src/main/resources/clds/camel/routes/flexible-flow.xml @@ -489,7 +489,222 @@ </doFinally> </doTry> </route> + <route id="deploy-closedloop"> + <from uri="direct:deploy-closedloop" /> + <doTry> + <log + loggingLevel="INFO" + message="Deploy the closed loop: ${exchangeProperty[loopObject].getName()}" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Deploy closed loop')" /> + <simple>${exchangeProperty[loopObject].getOperationalPolicies()} + </simple> + <setProperty propertyName="operationalPolicy"> + <simple>${body}</simple> + </setProperty> + <setBody> + <method ref="org.onap.clamp.loop.LoopOperation" + method="getDeployPayload(${exchangeProperty[loopObject]})" /> + </setBody> + <setProperty propertyName="deploymentId"> + <method ref="org.onap.clamp.loop.LoopOperation" + method="getDeploymentId(${exchangeProperty[loopObject]})" /> + </setProperty> + <setHeader headerName="CamelHttpMethod"> + <constant>PUT</constant> + </setHeader> + <setHeader headerName="Content-Type"> + <constant>application/json</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log + loggingLevel="INFO" + message="Endpoint to deploy closed loop: {{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[deploymentId]}"></log> + <toD + uri="{{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[deploymentId]}?bridgeEndpoint=true&mapHttpMessageHeaders=false&throwExceptionOnFailure=${exchangeProperty[RaiseHttpExceptionFlag]}&httpClient.connectTimeout=10000&authUsername={{clamp.config.dcae.deployment.userName}}&authPassword={{clamp.config.dcae.deployment.password}}" /> + <to + uri="bean:org.onap.clamp.loop.LoopOperation?method=updateLoopInfo(*,${exchangeProperty[loopObject]},${exchangeProperty[deploymentId]})" /> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()" /> + <setProperty propertyName="logMessage"> + <simple>Deploy closed loop status</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response" /> + </doFinally> + </doTry> + </route> + <route id="undeploy-closedloop"> + <from uri="direct:undeploy-closedloop" /> + <doTry> + <log + loggingLevel="INFO" + message="UNdeploy the closed loop: ${exchangeProperty[loopObject].getName()} : ${exchangeProperty[loopObject].getDcaeDeploymentId()}" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Undeploy closed loop')" /> + + <setBody> + <simple>{\"serviceTypeId\": \"${exchangeProperty[loopObject].getDcaeBlueprintId()}\"} + </simple> + </setBody> + <setHeader headerName="CamelHttpMethod"> + <constant>DELETE</constant> + </setHeader> + <setHeader headerName="Content-Type"> + <constant>application/json</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log + loggingLevel="INFO" + message="Endpoint to undeploy closed loop: {{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[loopObject].getDcaeDeploymentId()}"></log> + <toD + uri="{{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[loopObject].getDcaeDeploymentId()}?bridgeEndpoint=true&mapHttpMessageHeaders=false&throwExceptionOnFailure=${exchangeProperty[RaiseHttpExceptionFlag]}&httpClient.connectTimeout=10000&authUsername={{clamp.config.dcae.deployment.userName}}&authPassword={{clamp.config.dcae.deployment.password}}" /> + <to + uri="bean:org.onap.clamp.loop.LoopOperation?method=updateLoopInfo(*,${exchangeProperty[loopObject]},null)" /> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()" /> + <setProperty propertyName="logMessage"> + <simple>Undeploy closed loop status</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response" /> + </doFinally> + </doTry> + </route> + <route id="get-status-from-policy"> + <from uri="direct:get-status-from-policy" /> + <doTry> + <log + loggingLevel="INFO" + message="Query Closed Loop status from policy DPD: ${exchangeProperty[loopObject].getName()}" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Query operational policies to PDP group')" /> + <setProperty propertyName="operationalPolicyName"> + <method ref="org.onap.clamp.loop.LoopOperation" + method="getOperationalPolicyName(${exchangeProperty[loopObject]})" /> + </setProperty> + <setHeader headerName="CamelHttpMethod"> + <constant>GET</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log + loggingLevel="INFO" + message="Endpoint to query from Policy DPD: {{clamp.config.policy.pap.url}}/policy/api/v1/policytypes/onap.policies.controlloop.operational/versions/1.0.0/policies/${exchangeProperty[operationalPolicyName]}/versions/deployed"></log> + <toD + uri="{{clamp.config.policy.pap.url}}/policy/api/v1/policytypes/onap.policies.controlloop.operational/versions/1.0.0/policies/${exchangeProperty[operationalPolicyName]}/versions/deployed?bridgeEndpoint=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&httpClient.connectTimeout=10000&authMethod=Basic&authUsername={{clamp.config.policy.pap.userName}}&authPassword={{clamp.config.policy.pap.password}}" /> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()" /> + <setProperty propertyName="logMessage"> + <simple>Query closed loop from Policy status</simple> + </setProperty> + <setProperty propertyName="policyStatus"> + <method ref="org.onap.clamp.loop.LoopOperation" + method="analysePolicyResponse(${header.CamelHttpResponseCode})" /> + </setProperty> + <to uri="direct:dump-loop-log-http-response" /> + </doFinally> + </doTry> + </route> + <route id="get-status-from-dcae"> + <from uri="direct:get-status-from-dcae" /> + <log + loggingLevel="INFO" + message="Query Closed Loop status from DCAE ${exchangeProperty[loopObject].getName()}" /> + <choice> + <when> + <simple>${exchangeProperty[loopObject].getDcaeDeploymentStatusUrl()} == null + </simple> + <setProperty propertyName="dcaeStatus"> + <method ref="org.onap.clamp.loop.LoopOperation" + method="analyseDcaeResponse(*,null)" /> + </setProperty> + <log + loggingLevel="INFO" + message="dcae status: ${exchangeProperty[dcaeStatus]}"></log> + </when> + <otherwise> + <doTry> + <log + loggingLevel="INFO" + message="Query Closed Loop status from Dcae" /> + <setHeader headerName="CamelHttpMethod"> + <constant>GET</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log + loggingLevel="INFO" + message="Endpoint to query Closed Loop status: ${exchangeProperty[loopObject].getDcaeDeploymentStatusUrl()}"></log> + <toD + uri="${exchangeProperty[loopObject].getDcaeDeploymentStatusUrl()}?bridgeEndpoint=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&httpClient.connectTimeout=10000&authMethod=Basic&authUsername={{clamp.config.dcae.deployment.userName}}&authPassword={{clamp.config.dcae.deployment.password}}" /> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()" /> + <setProperty propertyName="logMessage"> + <simple>Query closed loop from DCAE status</simple> + </setProperty> + <setProperty propertyName="dcaeStatus"> + <method ref="org.onap.clamp.loop.LoopOperation" + method="analyseDcaeResponse(*,${header.CamelHttpResponseCode})" /> + </setProperty> + <log + loggingLevel="INFO" + message="dcae status: ${exchangeProperty[dcaeStatus]}"></log> + <to uri="direct:dump-loop-log-http-response" /> + </doFinally> + </doTry> + </otherwise> + </choice> + </route> <route id="reset-raise-http-exception-flag"> <from uri="direct:reset-raise-http-exception-flag" /> <setProperty propertyName="raiseHttpExceptionFlag"> diff --git a/src/test/java/org/onap/clamp/loop/LoopOperationTestItCase.java b/src/test/java/org/onap/clamp/loop/LoopOperationTestItCase.java new file mode 100644 index 000000000..e71b4982d --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/LoopOperationTestItCase.java @@ -0,0 +1,250 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.loop; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; + +import java.io.IOException; +import java.util.HashSet; + +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.json.simple.parser.ParseException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.onap.clamp.clds.Application; +import org.onap.clamp.clds.config.ClampProperties; +import org.onap.clamp.loop.LoopOperation.TempLoopState; +import org.onap.clamp.policy.microservice.MicroServicePolicy; +import org.onap.clamp.policy.operational.OperationalPolicy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class LoopOperationTestItCase { + + private Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().create(); + @Autowired + LoopService loopService; + + @Autowired + ClampProperties property; + + private Loop createTestLoop() { + String yaml = "imports:\n" + + " - \"http://www.getcloudify.org/spec/cloudify/3.4/types.yaml\"\n" + + "node_templates:\n" + + " docker_service_host:\n" + + " type: dcae.nodes.SelectedDockerHost"; + + Loop loopTest = new Loop("ControlLoopTest", yaml, "<xml></xml>"); + loopTest.setGlobalPropertiesJson(new Gson().fromJson("{\"testname\":\"testvalue\"}", JsonObject.class)); + loopTest.setLastComputedState(LoopState.DESIGN); + loopTest.setDcaeDeploymentId("123456789"); + loopTest.setDcaeDeploymentStatusUrl("http4://localhost:8085"); + loopTest.setDcaeBlueprintId("UUID-blueprint"); + + MicroServicePolicy microServicePolicy = new MicroServicePolicy("configPolicyTest", "", + "tosca_definitions_version: tosca_simple_yaml_1_0_0", true, + gson.fromJson("{\"configtype\":\"json\"}", JsonObject.class), new HashSet<>()); + microServicePolicy.setProperties(new Gson().fromJson("{\"param1\":\"value1\"}", JsonObject.class)); + + loopTest.addMicroServicePolicy(microServicePolicy); + return loopTest; + } + + + @Test + public void testAnalysePolicyResponse() { + LoopOperation loopOp = new LoopOperation(loopService, property); + String status1 = loopOp.analysePolicyResponse(200); + String status2 = loopOp.analysePolicyResponse(404); + String status3 = loopOp.analysePolicyResponse(500); + String status4 = loopOp.analysePolicyResponse(503); + + // then + assertThat(status1).isEqualTo("SUBMITTED"); + assertThat(status2).isEqualTo("NOT_SUBMITTED"); + assertThat(status3).isEqualTo("IN_ERROR"); + assertThat(status4).isEqualTo("IN_ERROR"); + } + + @Test + public void testGetOperationalPolicyName() { + LoopOperation loopOp = new LoopOperation(loopService, property); + Loop loop = this.createTestLoop(); + String opName1 = loopOp.getOperationalPolicyName(loop); + assertThat(opName1).isNull(); + + OperationalPolicy opPolicy1 = new OperationalPolicy("OperationalPolicyTest1", null, + gson.fromJson("{\"type\":\"Operational\"}", JsonObject.class)); + loop.addOperationalPolicy(opPolicy1); + String opName2 = loopOp.getOperationalPolicyName(loop); + assertThat(opName2).isEqualTo("OperationalPolicyTest1"); + } + + @Test + public void testAnalyseDcaeResponse() throws ParseException { + LoopOperation loopOp = new LoopOperation(loopService, property); + String dcaeStatus1 = loopOp.analyseDcaeResponse(null, null); + assertThat(dcaeStatus1).isEqualTo("NOT_DEPLOYED"); + + String dcaeStatus2 = loopOp.analyseDcaeResponse(null, 500); + assertThat(dcaeStatus2).isEqualTo("IN_ERROR"); + + String dcaeStatus3 = loopOp.analyseDcaeResponse(null, 404); + assertThat(dcaeStatus3).isEqualTo("NOT_DEPLOYED"); + + Exchange camelExchange = Mockito.mock(Exchange.class); + Message mockMessage = Mockito.mock(Message.class); + Mockito.when(camelExchange.getIn()).thenReturn(mockMessage); + Mockito.when(mockMessage.getBody(String.class)) + .thenReturn("{\"operationType\":\"install\",\"status\":\"succeeded\"}"); + String dcaeStatus4 = loopOp.analyseDcaeResponse(camelExchange, 200); + assertThat(dcaeStatus4).isEqualTo("DEPLOYED"); + + Mockito.when(mockMessage.getBody(String.class)) + .thenReturn("{\"operationType\":\"install\",\"status\":\"processing\"}"); + String dcaeStatus5 = loopOp.analyseDcaeResponse(camelExchange, 200); + assertThat(dcaeStatus5).isEqualTo("PROCESSING"); + + Mockito.when(mockMessage.getBody(String.class)) + .thenReturn("{\"operationType\":\"install\",\"status\":\"failed\"}"); + String dcaeStatus6 = loopOp.analyseDcaeResponse(camelExchange, 200); + assertThat(dcaeStatus6).isEqualTo("IN_ERROR"); + + Mockito.when(mockMessage.getBody(String.class)) + .thenReturn("{\"operationType\":\"uninstall\",\"status\":\"succeeded\"}"); + String dcaeStatus7 = loopOp.analyseDcaeResponse(camelExchange, 200); + assertThat(dcaeStatus7).isEqualTo("NOT_DEPLOYED"); + + Mockito.when(mockMessage.getBody(String.class)) + .thenReturn("{\"operationType\":\"uninstall\",\"status\":\"processing\"}"); + String dcaeStatus8 = loopOp.analyseDcaeResponse(camelExchange, 200); + assertThat(dcaeStatus8).isEqualTo("PROCESSING"); + + Mockito.when(mockMessage.getBody(String.class)) + .thenReturn("{\"operationType\":\"uninstall\",\"status\":\"failed\"}"); + String dcaeStatus9 = loopOp.analyseDcaeResponse(camelExchange, 200); + assertThat(dcaeStatus9).isEqualTo("IN_ERROR"); + } + + @Test + public void testUpdateLoopStatus() { + LoopOperation loopOp = new LoopOperation(loopService, property); + Loop loop = this.createTestLoop(); + loopService.saveOrUpdateLoop(loop); + LoopState newState1 = loopOp.updateLoopStatus(loop, TempLoopState.SUBMITTED, TempLoopState.DEPLOYED); + LoopState dbState1 = loopService.getLoop(loop.getName()).getLastComputedState(); + assertThat(newState1).isEqualTo(LoopState.DEPLOYED); + assertThat(dbState1).isEqualTo(LoopState.DEPLOYED); + + LoopState newState2 = loopOp.updateLoopStatus(loop, TempLoopState.SUBMITTED, TempLoopState.NOT_DEPLOYED); + LoopState dbState2 = loopService.getLoop(loop.getName()).getLastComputedState(); + assertThat(newState2).isEqualTo(LoopState.SUBMITTED); + assertThat(dbState2).isEqualTo(LoopState.SUBMITTED); + + LoopState newState3 = loopOp.updateLoopStatus(loop, TempLoopState.SUBMITTED, TempLoopState.PROCESSING); + assertThat(newState3).isEqualTo(LoopState.WAITING); + + LoopState newState4 = loopOp.updateLoopStatus(loop, TempLoopState.SUBMITTED, TempLoopState.IN_ERROR); + assertThat(newState4).isEqualTo(LoopState.IN_ERROR); + + LoopState newState5 = loopOp.updateLoopStatus(loop, TempLoopState.NOT_SUBMITTED, TempLoopState.DEPLOYED); + assertThat(newState5).isEqualTo(LoopState.IN_ERROR); + + LoopState newState6 = loopOp.updateLoopStatus(loop, TempLoopState.NOT_SUBMITTED, TempLoopState.PROCESSING); + assertThat(newState6).isEqualTo(LoopState.IN_ERROR); + + LoopState newState7 = loopOp.updateLoopStatus(loop, TempLoopState.NOT_SUBMITTED, TempLoopState.NOT_DEPLOYED); + assertThat(newState7).isEqualTo(LoopState.DESIGN); + + LoopState newState8 = loopOp.updateLoopStatus(loop, TempLoopState.IN_ERROR, TempLoopState.DEPLOYED); + assertThat(newState8).isEqualTo(LoopState.IN_ERROR); + + LoopState newState9 = loopOp.updateLoopStatus(loop, TempLoopState.IN_ERROR, TempLoopState.NOT_DEPLOYED); + assertThat(newState9).isEqualTo(LoopState.IN_ERROR); + + LoopState newState10 = loopOp.updateLoopStatus(loop, TempLoopState.IN_ERROR, TempLoopState.PROCESSING); + assertThat(newState10).isEqualTo(LoopState.IN_ERROR); + + LoopState newState11 = loopOp.updateLoopStatus(loop, TempLoopState.IN_ERROR, TempLoopState.IN_ERROR); + assertThat(newState11).isEqualTo(LoopState.IN_ERROR); + } + + @Test + public void testUpdateLoopInfo() throws ParseException { + Loop loop = this.createTestLoop(); + loopService.saveOrUpdateLoop(loop); + + Exchange camelExchange = Mockito.mock(Exchange.class); + Message mockMessage = Mockito.mock(Message.class); + Mockito.when(camelExchange.getIn()).thenReturn(mockMessage); + Mockito.when(mockMessage.getBody(String.class)) + .thenReturn("{\"links\":{\"status\":\"http://testhost/dcae-operationstatus\",\"test2\":\"test2\"}}"); + + LoopOperation loopOp = new LoopOperation(loopService, property); + loopOp.updateLoopInfo(camelExchange, loop, "testNewId"); + + Loop newLoop = loopService.getLoop(loop.getName()); + String newDeployId = newLoop.getDcaeDeploymentId(); + String newDeploymentStatusUrl = newLoop.getDcaeDeploymentStatusUrl(); + + assertThat(newDeployId).isEqualTo("testNewId"); + assertThat(newDeploymentStatusUrl).isEqualTo("http4://testhost/dcae-operationstatus"); + } + + @Test + public void testGetDeploymentId() { + Loop loop = this.createTestLoop(); + LoopOperation loopOp = new LoopOperation(loopService, property); + String deploymentId1 = loopOp.getDeploymentId(loop); + assertThat(deploymentId1).isEqualTo("123456789"); + + loop.setDcaeDeploymentId(null); + String deploymentId2 = loopOp.getDeploymentId(loop); + assertThat(deploymentId2).isEqualTo("closedLoop_ControlLoopTest_deploymentId"); + + loop.setDcaeDeploymentId(""); + String deploymentId3 = loopOp.getDeploymentId(loop); + assertThat(deploymentId3).isEqualTo("closedLoop_ControlLoopTest_deploymentId"); + } + + @Test + public void testGetDeployPayload() throws IOException { + Loop loop = this.createTestLoop(); + LoopOperation loopOp = new LoopOperation(loopService, property); + String deploymentPayload = loopOp.getDeployPayload(loop); + + String expectedPayload = "{\"serviceTypeId\":\"UUID-blueprint\",\"inputs\":{\"imports\":[\"http://www.getcloudify.org/spec/cloudify/3.4/types.yaml\"],\"node_templates\":{\"docker_service_host\":{\"type\":\"dcae.nodes.SelectedDockerHost\"}}}}"; + assertThat(deploymentPayload).isEqualTo(expectedPayload); + } +}
\ No newline at end of file diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index ecc40331f..061505a12 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -217,6 +217,11 @@ clamp.config.dcae.dispatcher.url=http://localhost:${docker.http-cache.port.host} clamp.config.dcae.dispatcher.retry.interval=100
clamp.config.dcae.dispatcher.retry.limit=1
+#DCAE Deployment Url Properties
+clamp.config.dcae.deployment.url=http4://localhost:${docker.http-cache.port.host}
+clamp.config.dcae.deployment.userName=test
+clamp.config.dcae.deployment.password=test
+
#Define user permission related parameters, the permission type can be changed but MUST be redefined in clds-users.properties in that case !
clamp.config.security.permission.type.cl=permission-type-cl
clamp.config.security.permission.type.cl.manage=permission-type-cl-manage
diff --git a/src/test/resources/http-cache/third_party_proxy.py b/src/test/resources/http-cache/third_party_proxy.py index f19aa0da4..0db977bb4 100755 --- a/src/test/resources/http-cache/third_party_proxy.py +++ b/src/test/resources/http-cache/third_party_proxy.py @@ -199,6 +199,18 @@ class Proxy(SimpleHTTPServer.SimpleHTTPRequestHandler): with open(cached_file_content, 'w+') as f: f.write(self.data_string) return True + elif self.path.startswith("/policy/api/v1/policytypes/") and http_type == "GET": + print "self.path start with /policy/api/v1/policytypes/, generating response json..." + jsonGenerated = "{\"policyTypeId\": \"onap.policies.controlloop.operational\",\"policyTypeVersion\": \"1.0.0\",\"policyId\": \"OPERATIONAL_z711F_v1_0_ResourceInstanceName1_tca\"}" + print "jsonGenerated: " + jsonGenerated + if not os.path.exists(cached_file_folder): + os.makedirs(cached_file_folder, 0777) + + with open(cached_file_header, 'w') as f: + f.write("{\"Content-Length\": \"" + str(len(jsonGenerated)) + "\", \"Content-Type\": \"application/json\"}") + with open(cached_file_content, 'w') as f: + f.write(jsonGenerated) + return True else: return False |