diff options
author | saul.gill <saul.gill@est.tech> | 2021-07-15 11:45:02 +0100 |
---|---|---|
committer | saul.gill <saul.gill@est.tech> | 2021-07-19 15:15:54 +0100 |
commit | 41811daa6079e07d95daf3d32719afe7ec15acbd (patch) | |
tree | 220c2235db383eff5db4181601f89800e8e82b0e | |
parent | 258fdc2ddb8b5e130ccc2b287c10c3fd782b7ee9 (diff) |
Added Camel Endpoints for decommissioning
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>
6 files changed, 284 insertions, 23 deletions
diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java index f291c4e89..e5dccde7b 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java @@ -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); diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java index b50e7a0ed..74548e724 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java @@ -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); } - } /** diff --git a/runtime/src/main/resources/clds/camel/rest/clamp-api-v2.xml b/runtime/src/main/resources/clds/camel/rest/clamp-api-v2.xml index 8a7523c2b..3addb55f8 100644 --- a/runtime/src/main/resources/clds/camel/rest/clamp-api-v2.xml +++ b/runtime/src/main/resources/clds/camel/rest/clamp-api-v2.xml @@ -1475,7 +1475,7 @@ <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 @@ -1509,7 +1509,7 @@ <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> @@ -1543,6 +1543,50 @@ </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> @@ -1610,6 +1654,76 @@ </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" diff --git a/runtime/src/main/resources/clds/camel/routes/controlloop-flows.xml b/runtime/src/main/resources/clds/camel/routes/controlloop-flows.xml index a888d6bf0..c33aa5924 100644 --- a/runtime/src/main/resources/clds/camel/routes/controlloop-flows.xml +++ b/runtime/src/main/resources/clds/camel/routes/controlloop-flows.xml @@ -54,6 +54,37 @@ </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]}&version=${exchangeProperty[version]}&bridgeEndpoint=true&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.controlloop.runtime.userName}}&authPassword={{clamp.config.controlloop.runtime.password}}&authenticationPreemptive=true&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> @@ -132,4 +163,54 @@ </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&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.controlloop.runtime.userName}}&authPassword={{clamp.config.controlloop.runtime.password}}&authenticationPreemptive=true&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&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.controlloop.runtime.userName}}&authPassword={{clamp.config.controlloop.runtime.password}}&authenticationPreemptive=true&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> diff --git a/runtime/src/test/java/org/onap/policy/clamp/runtime/RuntimeCommissioningResponseTestItCase.java b/runtime/src/test/java/org/onap/policy/clamp/runtime/RuntimeCommissioningResponseTestItCase.java index 7616d7a49..a1eaf27d0 100644 --- a/runtime/src/test/java/org/onap/policy/clamp/runtime/RuntimeCommissioningResponseTestItCase.java +++ b/runtime/src/test/java/org/onap/policy/clamp/runtime/RuntimeCommissioningResponseTestItCase.java @@ -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(); + } } diff --git a/runtime/src/test/resources/http-cache/third_party_proxy.py b/runtime/src/test/resources/http-cache/third_party_proxy.py index 1aaf4024d..2a28c65d3 100644 --- a/runtime/src/test/resources/http-cache/third_party_proxy.py +++ b/runtime/src/test/resources/http-cache/third_party_proxy.py @@ -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 |