Fix the bugs in loop state logic 93/86893/2
authorxg353y <xg353y@intl.att.com>
Fri, 3 May 2019 11:23:40 +0000 (13:23 +0200)
committerxg353y <xg353y@intl.att.com>
Fri, 3 May 2019 11:32:07 +0000 (13:32 +0200)
Fix the bugs in the logic to get the loop state

Issue-ID: CLAMP-362
Change-Id: I9d931f1a1ceed3d9e173b3ee742f8e349b7e653f
Signed-off-by: xg353y <xg353y@intl.att.com>
src/main/java/org/onap/clamp/loop/LoopOperation.java
src/main/resources/clds/camel/rest/clamp-api-v2.xml
src/main/resources/clds/camel/routes/flexible-flow.xml
src/test/java/org/onap/clamp/loop/LoopOperationTestItCase.java [new file with mode: 0644]

index f38b591..c3eb08b 100644 (file)
@@ -34,7 +34,9 @@ import com.google.gson.JsonPrimitive;
 import java.io.IOException;
 import java.lang.reflect.Array;
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
@@ -42,6 +44,7 @@ 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.policy.operational.OperationalPolicy;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.yaml.snakeyaml.Yaml;
@@ -143,10 +146,10 @@ public class LoopOperation {
         String statusUrl = (String) linksObj.get(DCAE_STATUS_FIELD);
 
         // use http4 instead of http, because camel http4 component is used to do the http call
-        statusUrl.replace("http", "http4");
+        String newStatusUrl = statusUrl.replaceAll("http:", "http4:");
 
         loop.setDcaeDeploymentId(deploymentId);
-        loop.setDcaeDeploymentStatusUrl(statusUrl);
+        loop.setDcaeDeploymentStatusUrl(newStatusUrl);
         loopService.saveOrUpdateLoop(loop);
     }
 
@@ -157,7 +160,7 @@ public class LoopOperation {
      * @return The state based on policy response
      * @throws ParseException The parse exception
      */
-    public String analysePolicyResponse(int statusCode) throws ParseException {
+    public String analysePolicyResponse(int statusCode) {
         if (statusCode == 200) {
             return TempLoopState.SUBMITTED.toString();
         } else if (statusCode == 404) {
@@ -166,6 +169,22 @@ public class LoopOperation {
         return TempLoopState.IN_ERROR.toString();
     }
 
+    /**
+     * Get the name of the first Operational policy.
+     *
+     * @param loop The closed loop
+     * @return The name of the first operational policy
+     */
+    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;
+    }
+
     /**
      * Get the Closed Loop status based on the reply from DCAE.
      *
@@ -189,13 +208,13 @@ public class LoopOperation {
             String status = (String) jsonObj.get("status");
 
             // status = processing/successded/failed
-            if (status == "successed") {
-                if (opType == "install") {
+            if (status.equals("succeeded")) {
+                if (opType.equals("install")) {
                     return TempLoopState.DEPLOYED.toString();
-                } else if (status == "successed") {
+                } else if (opType.equals("uninstall")) {
                     return TempLoopState.NOT_DEPLOYED.toString();
                 }
-            } else if (status == "processing") {
+            } else if (status.equals("processing")) {
                 return TempLoopState.PROCESSING.toString();
             }
         } else if (statusCode == 404) {
@@ -205,13 +224,14 @@ public class LoopOperation {
     }
 
     /**
-     * Get the status of the closed loop based on the response from Policy and DCAE.
+     * 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(TempLoopState policyState, TempLoopState dcaeState) {
+    public LoopState updateLoopStatus(Loop loop, TempLoopState policyState, TempLoopState dcaeState) {
         LoopState clState = LoopState.IN_ERROR;
         if (policyState == TempLoopState.SUBMITTED) {
             if (dcaeState == TempLoopState.DEPLOYED) {
@@ -226,6 +246,8 @@ public class LoopOperation {
                 clState = LoopState.DESIGN;
             }
         }
+        loop.setLastComputedState(clState);
+        loopService.saveOrUpdateLoop(loop);
         return clState;
     }
 
index 2640d6b..45cad03 100644 (file)
                                                uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" />
                                        <to
                                                uri="direct:load-loop" />
-                                       <split>
-                                               <simple>${exchangeProperty[loopObject].getOperationalPolicies()}
-                                               </simple>
-                                               <setProperty propertyName="operationalPolicy">
-                                                       <simple>${body}</simple>
-                                               </setProperty>
-                                               <to 
-                                                       uri="direct:get-status-from-policy" />
-                                       </split>
-                                       <to 
+                                       <to
+                                               uri="direct:get-status-from-policy" />
+                                       <to
                                                uri="direct:get-status-from-dcae" />
-                                       <choice>
                                        <log
                                                loggingLevel="INFO"
-                                               message="policy status0: ${exchangeProperty[policyStatus]}"></log>
-                                       <log
-                                               loggingLevel="INFO"
-                                               message="dcae status0: ${exchangeProperty[dcaeStatus]}"></log>
+                                               message="policy status0000: ${exchangeProperty[policyStatus]}"></log>
+                                       <choice>
                                                <when>
                                                        <simple> ${exchangeProperty[policyStatus]} == 'SUBMITTED' and
                                                                ${exchangeProperty[dcaeStatus]} == 'NOT_DEPLOYED'
                                        <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[policyStatus], ${exchangeProperty[dcaeStatus])" />
-
+                                               uri="bean:org.onap.clamp.loop.LoopOperation?method=updateLoopStatus(${exchangeProperty[loopObject]},${exchangeProperty[policyStatus]}, ${exchangeProperty[dcaeStatus]})" />
                                        <log
                                                loggingLevel="INFO"
-                                               message="Get Status request successfully executed for loop: ${body}" />
+                                               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
index 6813800..a116c56 100644 (file)
                                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')" />
-                       <setBody>
-                               <constant>null</constant>
-                       </setBody>
+                       <setProperty propertyName="operationalPolicyName">
+                               <method ref="org.onap.clamp.loop.LoopOperation"
+                                       method="getOperationalPolicyName(${exchangeProperty[loopObject]})" />
+                       </setProperty>
                        <setHeader headerName="CamelHttpMethod">
                                <constant>GET</constant>
                        </setHeader>
                        </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[operationalPolicy].getName()}/versions/deployed"></log>
+                               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[operationalPolicy].getName()}/versions/deployed?bridgeEndpoint=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;httpClient.connectTimeout=10000&amp;authMethod=Basic&amp;authUsername={{clamp.config.policy.pap.userName}}&amp;authPassword={{clamp.config.policy.pap.password}}" />
+                               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&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;httpClient.connectTimeout=10000&amp;authMethod=Basic&amp;authUsername={{clamp.config.policy.pap.userName}}&amp;authPassword={{clamp.config.policy.pap.password}}" />
                        <doFinally>
                                <to uri="direct:reset-raise-http-exception-flag" />
                                <to
                                        <method ref="org.onap.clamp.loop.LoopOperation"
                                        method="analysePolicyResponse(${header.CamelHttpResponseCode})" />
                                </setProperty>
-                               <log
-                                               loggingLevel="INFO"
-                                               message="policy status: ${exchangeProperty[policyStatus]}"></log>
                                <to uri="direct:dump-loop-log-http-response" />
                        </doFinally>
                </doTry>
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 (file)
index 0000000..e71b498
--- /dev/null
@@ -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