Added Camel Endpoints for decommissioning 91/122691/2
authorsaul.gill <saul.gill@est.tech>
Thu, 15 Jul 2021 10:45:02 +0000 (11:45 +0100)
committersaul.gill <saul.gill@est.tech>
Mon, 19 Jul 2021 14:15:54 +0000 (15:15 +0100)
Added endpoint in camel for decommissioning

Changed get tosca service template get endpoint
to return snake case

Added endpoints in camel to retrieve control loop
definitions and element definitions

Added integration tests

Allowed error messages and status codes to come through
from runtime-controlloop backend

Small refactor of clamp python emulator

Issue-ID: POLICY-3443
Change-Id: I2f6103ca0f2058651a43e7ae1e0974cb1d3e69a7
Signed-off-by: saul.gill <saul.gill@est.tech>
runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java
runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java
runtime/src/main/resources/clds/camel/rest/clamp-api-v2.xml
runtime/src/main/resources/clds/camel/routes/controlloop-flows.xml
runtime/src/test/java/org/onap/policy/clamp/runtime/RuntimeCommissioningResponseTestItCase.java
runtime/src/test/resources/http-cache/third_party_proxy.py

index f291c4e..e5dccde 100644 (file)
@@ -252,7 +252,8 @@ public class CommissioningProvider implements Closeable {
                 mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaTopologyTemplate.class), visitor);
                 break;
             case "node_templates":
-                mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaNodeTemplate.class), visitor);
+                mapper.acceptJsonFormatVisitor(mapper.getTypeFactory()
+                    .constructCollectionType(List.class, ToscaNodeTemplate.class), visitor);
                 break;
             default:
                 mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaServiceTemplate.class), visitor);
index b50e7a0..74548e7 100644 (file)
@@ -23,8 +23,6 @@ package org.onap.policy.clamp.controlloop.runtime.main.rest;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.PropertyNamingStrategies;
-import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
-import com.fasterxml.jackson.module.jsonSchema.factories.SchemaFactoryWrapper;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import io.swagger.annotations.ApiResponse;
@@ -347,15 +345,24 @@ public class CommissioningController extends AbstractRestController {
                     required = false) String version) {
 
         try {
-            return ResponseEntity.ok().body(provider.getToscaServiceTemplate(name, version));
+            ObjectMapper mapper = new ObjectMapper();
+            mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
+            String response = mapper.writerWithDefaultPrettyPrinter()
+                .writeValueAsString(provider.getToscaServiceTemplate(name, version));
+
+            return ResponseEntity.ok().body(response);
 
         } catch (PfModelRuntimeException | PfModelException e) {
             LOGGER.warn("Get of tosca service template failed", e);
             var resp = new CommissioningResponse();
             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
             return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
+        } catch (JsonProcessingException e) {
+            LOGGER.warn("Get of tosca service template failed", e);
+            var resp = new CommissioningResponse();
+            resp.setErrorDetails(e.getMessage());
+            return ResponseEntity.status(Status.BAD_REQUEST.getStatusCode()).body(resp);
         }
-
     }
 
     /**
index 8a7523c..3addb55 100644 (file)
                         <constant>application/json</constant>
                     </setHeader>
                     <setProperty name="raiseHttpExceptionFlag">
-                        <simple resultType="java.lang.Boolean">true</simple>
+                        <simple resultType="java.lang.Boolean">false</simple>
                     </setProperty>
                     <to uri="direct:get-service-template"/>
                     <to
             <route>
                 <removeHeaders pattern="*"/>
                 <setProperty name="raiseHttpExceptionFlag">
-                    <simple resultType="java.lang.Boolean">true</simple>
+                    <simple resultType="java.lang.Boolean">false</simple>
                 </setProperty>
                 <setHeader name="Content-Type">
                     <constant>application/json</constant>
             </route>
         </post>
 
+        <delete uri="/v2/toscaControlLoop/decommissionToscaTemplate"
+              type="java.lang.String"
+              consumes="plain/text"
+              outType="java.lang.String"
+              produces="application/json"
+              bindingMode="off">
+            <route>
+                <removeHeaders pattern="*"
+                               excludePattern="name|version|requestId"/>
+                <setProperty name="raiseHttpExceptionFlag">
+                    <simple resultType="java.lang.Boolean">true</simple>
+                </setProperty>
+                <setHeader name="Content-Type">
+                    <constant>application/json</constant>
+                </setHeader>
+                <doTry>
+                    <to
+                            uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Delete Tosca Service Template')"/>
+                    <to
+                            uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+                    <to uri="direct:decommission-service-template"/>
+                    <to
+                            uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+                    <doCatch>
+                        <exception>java.lang.Exception</exception>
+                        <handled>
+                            <constant>true</constant>
+                        </handled>
+                        <to
+                                uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+                        <log loggingLevel="ERROR"
+                             message="Decommissioning of Tosca Service Template FAILED"/>
+
+                        <setHeader name="CamelHttpResponseCode">
+                            <constant>500</constant>
+                        </setHeader>
+                        <setBody>
+                            <simple>Decommissioning Tosca Service Template FAILED</simple>
+                        </setBody>
+                    </doCatch>
+                </doTry>
+            </route>
+        </delete>
+
         <get uri="/v2/toscaControlLoop/getToscaInstantiation" outType="java.lang.String" bindingMode="off" produces="application/json">
             <route>
                 <doTry>
             </route>
         </get>
 
+        <get uri="/v2/toscaControlLoop/getElementDefinitions" outType="java.lang.String" bindingMode="off" produces="application/json">
+            <route>
+                <removeHeaders pattern="*"
+                               excludePattern="name|version|requestId"/>
+                <doTry>
+                    <to uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET Json Schema ')"/>
+                    <to uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','read')"/>
+                    <setHeader name="Content-Type">
+                        <constant>application/json</constant>
+                    </setHeader>
+                    <setProperty name="raiseHttpExceptionFlag">
+                        <simple resultType="java.lang.Boolean">true</simple>
+                    </setProperty>
+                    <to uri="direct:get-element-definitions"/>
+                    <to uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+                    <doCatch>
+                        <exception>java.lang.Exception</exception>
+                        <handled>
+                            <constant>true</constant>
+                        </handled>
+                        <to
+                                uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+                        <log loggingLevel="ERROR"
+                             message="GET Element Definitions request failed: ${exception.stacktrace}"/>
+                        <setHeader name="CamelHttpResponseCode">
+                            <constant>500</constant>
+                        </setHeader>
+                        <setBody>
+                            <simple>GET JSON Schema FAILED</simple>
+                        </setBody>
+                    </doCatch>
+                </doTry>
+            </route>
+        </get>
+
+        <get uri="/v2/toscaControlLoop/getControlLoopDefinitions" outType="java.lang.String" bindingMode="off" produces="application/json">
+            <route>
+                <removeHeaders pattern="*"
+                               excludePattern="name|version|requestId"/>
+                <doTry>
+                    <to uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET Json Schema ')"/>
+                    <to uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','read')"/>
+                    <setHeader name="Content-Type">
+                        <constant>application/json</constant>
+                    </setHeader>
+                    <setProperty name="raiseHttpExceptionFlag">
+                        <simple resultType="java.lang.Boolean">true</simple>
+                    </setProperty>
+                    <to uri="direct:get-control-loop-definitions"/>
+                    <to uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+                    <doCatch>
+                        <exception>java.lang.Exception</exception>
+                        <handled>
+                            <constant>true</constant>
+                        </handled>
+                        <to
+                                uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+                        <log loggingLevel="ERROR"
+                             message="GET Control Loop Definitions request failed: ${exception.stacktrace}"/>
+                        <setHeader name="CamelHttpResponseCode">
+                            <constant>500</constant>
+                        </setHeader>
+                        <setBody>
+                            <simple>GET Control Loop Definitions FAILED</simple>
+                        </setBody>
+                    </doCatch>
+                </doTry>
+            </route>
+        </get>
+
         <post uri="/v2/toscaControlLoop/postToscaInstantiation"
               type="java.lang.String"
               consumes="plain/text"
index a888d6b..c33aa59 100644 (file)
             </doFinally>
         </doTry>
     </route>
+    <route id="decommission-service-template">
+        <from uri="direct:decommission-service-template"/>
+        <doTry>
+            <log loggingLevel="INFO"
+                 message="Decommissioning the tosca service template"/>
+            <to
+                    uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Controlloop', 'Decommissioning the tosca service template')"/>
+            <setHeader name="CamelHttpMethod">
+                <constant>DELETE</constant>
+            </setHeader>
+            <setHeader name="Content-Type">
+                <constant>application/json</constant>
+            </setHeader>
+            <setProperty name="name">
+                <simple>${header.name}</simple>
+            </setProperty>
+            <setProperty name="version">
+                <simple>${header.version}</simple>
+            </setProperty>
+            <log loggingLevel="INFO"
+                 message="Endpoint to send Tosca Service Template: {{clamp.config.controlloop.runtime.url}}/onap/controlloop/v2/commission"></log>
+            <toD
+                    uri="{{clamp.config.controlloop.runtime.url}}/onap/controlloop/v2/commission?name=${exchangeProperty[name]}&amp;version=${exchangeProperty[version]}&amp;bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.controlloop.runtime.userName}}&amp;authPassword={{clamp.config.controlloop.runtime.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+            <convertBodyTo type="java.lang.String"/>
+            <doFinally>
+                <to uri="direct:reset-raise-http-exception-flag"/>
+                <to
+                        uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+            </doFinally>
+        </doTry>
+    </route>
     <route id="get-tosca-instantiation">
         <from uri="direct:get-tosca-instantiation"/>
         <doTry>
             </doFinally>
         </doTry>
     </route>
+    <route id="get-element-definitions">
+        <from uri="direct:get-element-definitions"/>
+        <doTry>
+            <log loggingLevel="INFO"
+                 message="Getting the Control Loop Element Definitions"/>
+            <to
+                    uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('ControlLoop', 'Getting the Controlloop Element Definitions')"/>
+            <setHeader name="CamelHttpMethod">
+                <constant>GET</constant>
+            </setHeader>
+            <setHeader name="Content-Type">
+                <constant>application/json</constant>
+            </setHeader>
+            <log loggingLevel="INFO"
+                 message="Endpoint to get Json Schema: {{clamp.config.controlloop.runtime.url}}/onap/controlloop/v2/commission/elements"></log>
+            <toD
+                    uri="{{clamp.config.controlloop.runtime.url}}/onap/controlloop/v2/commission/elements?bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.controlloop.runtime.userName}}&amp;authPassword={{clamp.config.controlloop.runtime.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+            <convertBodyTo type="java.lang.String"/>
+            <doFinally>
+                <to uri="direct:reset-raise-http-exception-flag"/>
+                <to
+                        uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+            </doFinally>
+        </doTry>
+    </route>
+    <route id="get-control-loop-definitions">
+        <from uri="direct:get-control-loop-definitions"/>
+        <doTry>
+            <log loggingLevel="INFO"
+                 message="Getting the Control Loop  Definitions"/>
+            <to
+                    uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('ControlLoop', 'Getting the Controlloop Element Definitions')"/>
+            <setHeader name="CamelHttpMethod">
+                <constant>GET</constant>
+            </setHeader>
+            <setHeader name="Content-Type">
+                <constant>application/json</constant>
+            </setHeader>
+            <log loggingLevel="INFO"
+                 message="Endpoint to get Json Schema: {{clamp.config.controlloop.runtime.url}}/onap/controlloop/v2/commission/elements"></log>
+            <toD
+                    uri="{{clamp.config.controlloop.runtime.url}}/onap/controlloop/v2/commission? bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.controlloop.runtime.userName}}&amp;authPassword={{clamp.config.controlloop.runtime.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+            <convertBodyTo type="java.lang.String"/>
+            <doFinally>
+                <to uri="direct:reset-raise-http-exception-flag"/>
+                <to
+                        uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+            </doFinally>
+        </doTry>
+    </route>
 </routes>
index 7616d7a..a1eaf27 100644 (file)
@@ -102,4 +102,49 @@ public class RuntimeCommissioningResponseTestItCase {
         assertThat(HttpStatus.valueOf((Integer) exchangeResponse.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE))
             .is2xxSuccessful()).isTrue();
     }
+
+    @Test
+    public void testDecommissioningOfToscaServiceTemplateStatus() {
+        ProducerTemplate prodTemplate = camelContext.createProducerTemplate();
+
+        Exchange exchangeResponse =
+            prodTemplate.send("direct:decommission-service-template", ExchangeBuilder.anExchange(camelContext)
+                .withProperty("name", "ToscaServiceTemplate")
+                .withProperty("version", "1.0.0")
+                .withProperty("raiseHttpExceptionFlag", "true")
+                .build());
+
+        assertThat(HttpStatus.valueOf((Integer) exchangeResponse.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE))
+            .is2xxSuccessful()).isTrue();
+    }
+
+    @Test
+    public void testGetControlLoopDefinitions() {
+        ProducerTemplate prodTemplate = camelContext.createProducerTemplate();
+
+        Exchange exchangeResponse =
+            prodTemplate.send("direct:get-control-loop-definitions", ExchangeBuilder.anExchange(camelContext)
+                .withProperty("name", "ToscaServiceTemplate")
+                .withProperty("version", "1.0.0")
+                .withProperty("raiseHttpExceptionFlag", "true")
+                .build());
+
+        assertThat(HttpStatus.valueOf((Integer) exchangeResponse.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE))
+            .is2xxSuccessful()).isTrue();
+    }
+
+    @Test
+    public void testGetControlLoopElementDefinitions() {
+        ProducerTemplate prodTemplate = camelContext.createProducerTemplate();
+
+        Exchange exchangeResponse =
+            prodTemplate.send("direct:get-element-definitions", ExchangeBuilder.anExchange(camelContext)
+                .withProperty("name", "ToscaServiceTemplate")
+                .withProperty("version", "1.0.0")
+                .withProperty("raiseHttpExceptionFlag", "true")
+                .build());
+
+        assertThat(HttpStatus.valueOf((Integer) exchangeResponse.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE))
+            .is2xxSuccessful()).isTrue();
+    }
 }
index 1aaf402..2a28c65 100644 (file)
@@ -107,6 +107,15 @@ class Proxy(SimpleHTTPServer.SimpleHTTPRequestHandler):
     def _get_cached_header_file_name(self,cached_file_folder):
         return "%s/.header" % (cached_file_folder,)
 
+    def _create_cache(self, generated_json, cached_file_folder, cached_file_header, cached_file_content):
+        print "jsonGenerated: " + generated_json
+        if not os.path.exists(cached_file_folder):
+            os.makedirs(cached_file_folder, 0775)
+        with open(cached_file_header, 'w+') as f:
+            f.write("{\"Content-Length\": \"" + str(len(generated_json)) + "\", \"Content-Type\": \"application/json\"}")
+        with open(cached_file_content, 'w+') as f:
+            f.write(generated_json)
+
     def _execute_content_generated_cases(self,http_type):
      print("Testing special cases, cache files will be sent to :" +TMP_ROOT)
      cached_file_folder = self._get_cached_file_folder_name(TMP_ROOT)
@@ -274,14 +283,7 @@ class Proxy(SimpleHTTPServer.SimpleHTTPRequestHandler):
              print ("cached file folder for onap is %s: ", cached_file_folder)
              print "self.path start with /onap/controlloop/v2/commission/, generating response json..."
              jsonGenerated =  "{\"tosca_definitions_version\": \"tosca_simple_yaml_1_1_0\",\"data_types\": {},\"node_types\": {}, \"policy_types\": {}, \"topology_template\": {}, \"name\": \"ToscaServiceTemplateSimple\", \"version\": \"1.0.0\", \"metadata\": {}}"
-             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)
+             self._create_cache(jsonGenerated, cached_file_folder, cached_file_header, cached_file_content)
          return True
      elif (self.path.startswith("/onap/controlloop/v2/commission/toscaServiceTemplateSchema")) and http_type == "GET":
          if not _file_available:
@@ -289,14 +291,19 @@ class Proxy(SimpleHTTPServer.SimpleHTTPRequestHandler):
              print ("cached file folder for onap is %s: ", cached_file_folder)
              print "self.path start with /onap/controlloop/v2/commission/, generating response json..."
              jsonGenerated =  "{\"tosca_definitions_version\": \"tosca_simple_yaml_1_1_0\",\"data_types\": {},\"node_types\": {}, \"policy_types\": {}, \"topology_template\": {}, \"name\": \"ToscaServiceTemplateSimple\", \"version\": \"1.0.0\", \"metadata\": {}}"
-             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)
+             self._create_cache(jsonGenerated, cached_file_folder, cached_file_header, cached_file_content)
+         return True
+     elif (self.path.startswith("/onap/controlloop/v2/commission/elements")) and http_type == "GET":
+         print "self.path start with /commission/elements Control Loop Elements, generating response json..."
+         #jsondata = json.loads(self.data_string)
+         jsonGenerated = "[{\"name\": ,\"org.onap.domain.pmsh.PMSH_DCAEMicroservice\": [{ \"version\": \"1.2.3\", \"derived_from\": null }]}]"
+         self._create_cache(jsonGenerated, cached_file_folder, cached_file_header, cached_file_content)
+         return True
+     elif (self.path.startswith("/onap/controlloop/v2/commission")) and http_type == "GET":
+         print "self.path start with /commission control loop definition, generating response json..."
+         #jsondata = json.loads(self.data_string)
+         jsonGenerated = "[{\"name\": ,\"org.onap.domain.pmsh.PMSHControlLoopDefinition\": [{ \"version\": \"1.2.3\", \"derived_from\": null }]}]"
+         self._create_cache(jsonGenerated, cached_file_folder, cached_file_header, cached_file_content)
          return True
      elif (self.path.startswith("/onap/controlloop/v2/commission")) and http_type == "POST":
          print "self.path start with POST /onap/controlloop/v2/commission, copying body to response ..."
@@ -307,6 +314,12 @@ class Proxy(SimpleHTTPServer.SimpleHTTPRequestHandler):
          with open(cached_file_content, 'w+') as f:
              f.write(self.data_string)
          return True
+     elif (self.path.startswith("/onap/controlloop/v2/commission")) and http_type == "DELETE":
+         print "self.path start with /commission Decommissioning, generating response json..."
+         jsonGenerated = "{\"errorDetails\": null,\"affectedControlLoopDefinitions\": [{ \"name\": \"ToscaServiceTemplateSimple\", \"version\": \"1.0.0\" }]}"
+         self._create_cache(jsonGenerated, cached_file_folder, cached_file_header, cached_file_content)
+
+         return True
      else:
         return False