diff options
19 files changed, 250 insertions, 354 deletions
diff --git a/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json index 135016a11..112014b88 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json +++ b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json @@ -287,9 +287,9 @@ } }, "activate-restconf": { - "type": "component-restconf-executor", + "type": "component-script-executor", "interfaces": { - "ComponentRestconfExecutor": { + "ComponentScriptExecutor": { "operations": { "process": { "implementation": { @@ -297,8 +297,7 @@ }, "inputs": { "script-type": "kotlin", - "script-class-reference": "DefaultRestconf_cba$MountNEditConfigure", - "instance-dependencies": [] + "script-class-reference": "DefaultRestconf_cba$MountNEditConfigure" }, "outputs": { "response-data": "", diff --git a/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/node_types.json b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/node_types.json index 6de1fe320..3595a9f67 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/node_types.json +++ b/components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/node_types.json @@ -259,71 +259,6 @@ }, "derived_from": "tosca.nodes.Component" }, - "component-restconf-executor": { - "description": "This is Restconf Transaction Configuration Component API", - "version": "1.0.0", - "capabilities": { - "component-node": { - "type": "tosca.capabilities.Node" - } - }, - "interfaces": { - "ComponentRestconfExecutor": { - "operations": { - "process": { - "inputs": { - "script-type": { - "description": "Script type, kotlin type is supported", - "required": true, - "type": "string", - "constraints": [ - { - "valid_values": [ - "kotlin", - "jython", - "internal" - ] - } - ], - "default": "internal" - }, - "script-class-reference": { - "description": "Kotlin Script class name or jython script name.", - "required": true, - "type": "string" - }, - "instance-dependencies": { - "description": "Instance names to inject to Jython or Kotlin Script.", - "required": true, - "type": "list", - "entry_schema": { - "type": "string" - } - }, - "dynamic-properties": { - "description": "Dynamic Json Content or DSL Json reference.", - "required": false, - "type": "json" - } - }, - "outputs": { - "response-data": { - "description": "Execution Response Data in JSON format.", - "required": false, - "type": "string" - }, - "status": { - "description": "Status of the Component Execution ( success or failure )", - "required": true, - "type": "string" - } - } - } - } - } - }, - "derived_from": "tosca.nodes.Component" - }, "dg-generic": { "description": "This is Generic Directed Graph Type", "version": "1.0.0", diff --git a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/activation-blueprint.json b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/activation-blueprint.json index b3f5272b8..d185128d5 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/activation-blueprint.json +++ b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/activation-blueprint.json @@ -143,9 +143,9 @@ } }, "config-deploy" : { - "type" : "component-restconf-executor", + "type" : "component-script-executor", "interfaces" : { - "ComponentRestconfExecutor" : { + "ComponentScriptExecutor" : { "operations" : { "process" : { "implementation" : { @@ -154,7 +154,6 @@ "inputs" : { "script-type" : "jython", "script-class-reference" : "Scripts/python/RestconfConfigDeploy.py", - "instance-dependencies" : [ ], "dynamic-properties" : "*config-deploy-properties" }, "outputs" : { diff --git a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/node_types.json b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/node_types.json index d6f702a9f..8c2c0abea 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/node_types.json +++ b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/node_types.json @@ -79,7 +79,7 @@ }, "derived_from" : "tosca.nodes.Component" }, - "component-restconf-executor" : { + "component-script-executor" : { "description" : "This is Restconf Transaction Configuration Component API", "version" : "1.0.0", "capabilities" : { @@ -88,7 +88,7 @@ } }, "interfaces" : { - "ComponentRestconfExecutor" : { + "ComponentScriptExecutor" : { "operations" : { "process" : { "inputs" : { @@ -106,14 +106,6 @@ "required" : true, "type" : "string" }, - "instance-dependencies" : { - "description" : "Instance names to inject to Jython or Kotlin Script.", - "required" : true, - "type" : "list", - "entry_schema" : { - "type" : "string" - } - }, "dynamic-properties" : { "description" : "Dynamic Json Content or DSL Json reference.", "required" : false, diff --git a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Scripts/python/RestconfConfigDeploy.py b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Scripts/python/RestconfConfigDeploy.py index d65aefabb..17dd56104 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Scripts/python/RestconfConfigDeploy.py +++ b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Scripts/python/RestconfConfigDeploy.py @@ -19,10 +19,10 @@ from org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor import \ from java.lang import Exception as JavaException from restconf_client import RestconfClient +from org.onap.ccsdk.cds.blueprintsprocessor.services.execution import AbstractScriptComponentFunction -class RestconfConfigDeploy(RestconfComponentFunction): - +class RestconfConfigDeploy(AbstractScriptComponentFunction): log = globals()["log"] configlet_template_name = "config-assign" configlet_resource_path = "/yang-ext:mount/mynetconf:netconflist" @@ -34,11 +34,11 @@ class RestconfConfigDeploy(RestconfComponentFunction): try: restconf_client = RestconfClient(self.log, self) pnf_id, resolution_key = self.retrieve_parameters(execution_request) - web_client_service = self.restClientService(self.restconf_server_identifier) + web_client_service = restconf_client.web_client_service(self.restconf_server_identifier) try: # mount the device - mount_payload = self.resolveAndGenerateMessage("config-deploy-mapping", "config-deploy-template") + mount_payload = restconf_client.resolve_and_generate_message_from_template_prefix("config-deploy") restconf_client.mount_device(web_client_service, pnf_id, mount_payload) # log the current configuration subtree @@ -47,7 +47,7 @@ class RestconfConfigDeploy(RestconfComponentFunction): self.log.info("Current configuration subtree: {}", current_configuration) # apply configuration - configlet = self.resolveFromDatabase(resolution_key, self.configlet_template_name) + configlet = restconf_client.retrieve_resolved_template_from_database(resolution_key, self.configlet_template_name) restconf_client.configure_device_json_patch( web_client_service, pnf_id, self.configlet_resource_path, configlet) except Exception, err: diff --git a/components/model-catalog/definition-type/starter-type/node_type/component-restconf-executor.json b/components/model-catalog/definition-type/starter-type/node_type/component-restconf-executor.json deleted file mode 100644 index cb28a4a10..000000000 --- a/components/model-catalog/definition-type/starter-type/node_type/component-restconf-executor.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "description": "This is Restconf Transaction Configuration Component API", - "version": "1.0.0", - "capabilities": { - "component-node": { - "type": "tosca.capabilities.Node" - } - }, - "interfaces": { - "ComponentRestconfExecutor": { - "operations": { - "process": { - "inputs": { - "script-type": { - "description": "Script type, kotlin type is supported", - "required": true, - "type": "string", - "default": "internal", - "constraints": [ - { - "valid_values": [ - "kotlin", - "jython", - "internal" - ] - } - ] - }, - "script-class-reference": { - "description": "Kotlin Script class name or jython script name.", - "required": true, - "type": "string" - }, - "instance-dependencies": { - "required": true, - "description": "Instance names to inject to Jython or Kotlin Script.", - "type": "list", - "entry_schema": { - "type": "string" - } - }, - "dynamic-properties": { - "description": "Dynamic Json Content or DSL Json reference.", - "required": false, - "type": "json" - } - }, - "outputs": { - "response-data": { - "description": "Execution Response Data in JSON format.", - "required": false, - "type": "string" - }, - "status": { - "description": "Status of the Component Execution ( success or failure )", - "required": true, - "type": "string" - } - } - } - } - } - }, - "derived_from": "tosca.nodes.Component" -}
\ No newline at end of file diff --git a/components/scripts/python/ccsdk_restconf/restconf_client.py b/components/scripts/python/ccsdk_restconf/restconf_client.py index 6d18b03c5..ec25853f0 100644 --- a/components/scripts/python/ccsdk_restconf/restconf_client.py +++ b/components/scripts/python/ccsdk_restconf/restconf_client.py @@ -18,10 +18,11 @@ # ============LICENSE_END========================================================= # from time import sleep +from org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor import RestconfExecutorExtensionsKt +from org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution import ResourceResolutionExtensionsKt class RestconfClient: - __base_odl_url = "restconf/config/network-topology:network-topology/topology/topology-netconf/node/" __odl_status_check_limit = 10 __odl_status_check_pause = 1 @@ -32,6 +33,16 @@ class RestconfClient: self.__log = log self.__component_function = restconf_component_function + def web_client_service(self, identifier): + RestconfExecutorExtensionsKt.restconfClientService(self.__component_function, identifier) + + def resolve_and_generate_message_from_template_prefix(self, artifact_prefix): + return ResourceResolutionExtensionsKt.contentFromResolvedArtifact(self.component_function, artifact_prefix) + + def retrieve_resolved_template_from_database(self, key, artifact_template): + return ResourceResolutionExtensionsKt.storedContentFromResolvedArtifact(self.component_function, key, + artifact_template) + def mount_device(self, web_client_service, nf_id, mount_payload): self.__log.debug("mounting device {}", nf_id) headers = {"Content-Type": "application/xml"} diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/logback-test.xml b/ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/logback-test.xml index c37e0b5a0..305c59f62 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/logback-test.xml +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/logback-test.xml @@ -26,6 +26,7 @@ <logger name="org.springframework" level="warn"/>
<logger name="org.hibernate" level="info"/>
+ <logger name="org.mockserver.mock" level="warn"/>
<logger name="org.onap.ccsdk.cds.controllerblueprints" level="warn"/>
<logger name="org.onap.ccsdk.cds.blueprintsprocessor" level="info"/>
diff --git a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/scripts/InternalSimpleRestconf.cba.kts b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/internal/scripts/InternalSimpleRestconf.kt index 4ab7ddc4b..c4553abd6 100644 --- a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/scripts/InternalSimpleRestconf.cba.kts +++ b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/internal/scripts/InternalSimpleRestconf.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2018 IBM. + * Copyright © 2019 IBM. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,13 @@ * limitations under the License. */ @file:Suppress("unused") +package internal.scripts import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput -import org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor.RestconfComponentFunction +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction import org.slf4j.LoggerFactory -open class EditConfigure : RestconfComponentFunction() { +open class EditConfigure : AbstractScriptComponentFunction() { val log = LoggerFactory.getLogger(EditConfigure::class.java)!! @@ -37,7 +38,7 @@ open class EditConfigure : RestconfComponentFunction() { } } -open class MountNEditConfigure : RestconfComponentFunction() { +open class MountNEditConfigure : AbstractScriptComponentFunction() { val log = LoggerFactory.getLogger(MountNEditConfigure::class.java)!! @@ -58,7 +59,7 @@ open class MountNEditConfigure : RestconfComponentFunction() { /** * This is for used for Testing only */ -open class TestRestconfConfigure : RestconfComponentFunction() { +open class TestRestconfConfigure : AbstractScriptComponentFunction() { val log = LoggerFactory.getLogger(TestRestconfConfigure::class.java)!! diff --git a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ComponentRestconfExecutor.kt b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ComponentRestconfExecutor.kt deleted file mode 100644 index 53828d769..000000000 --- a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ComponentRestconfExecutor.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright © 2018 IBM. - * - * 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. - */ - -package org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor - -import com.fasterxml.jackson.databind.node.ArrayNode -import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput -import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants -import org.onap.ccsdk.cds.blueprintsprocessor.rest.RestLibConstants -import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction -import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentFunctionScriptingService -import org.onap.ccsdk.cds.controllerblueprints.core.getAsString -import org.springframework.beans.factory.config.ConfigurableBeanFactory -import org.springframework.context.annotation.Scope -import org.springframework.stereotype.Component - -@Component("component-restconf-executor") -@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) -open class ComponentRestconfExecutor(private var componentFunctionScriptingService: ComponentFunctionScriptingService) : - AbstractComponentFunction() { - - lateinit var scriptComponent: RestconfComponentFunction - - companion object { - const val SCRIPT_TYPE = "script-type" - const val SCRIPT_CLASS_REFERENCE = "script-class-reference" - const val INSTANCE_DEPENDENCIES = "instance-dependencies" - } - - override suspend fun processNB(executionRequest: ExecutionServiceInput) { - - val scriptType = operationInputs.getAsString(SCRIPT_TYPE) - val scriptClassReference = operationInputs.getAsString(SCRIPT_CLASS_REFERENCE) - val instanceDependenciesNode = operationInputs.get(INSTANCE_DEPENDENCIES) as? ArrayNode - - val scriptDependencies: MutableList<String> = arrayListOf() - scriptDependencies.add(RestLibConstants.SERVICE_BLUEPRINT_REST_LIB_PROPERTY) - scriptDependencies.add(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) - - instanceDependenciesNode?.forEach { instanceName -> - scriptDependencies.add(instanceName.textValue()) - } - /** - * Populate the Script Instance based on the Type - */ - scriptComponent = componentFunctionScriptingService - .scriptInstance<RestconfComponentFunction>(this, scriptType, - scriptClassReference, scriptDependencies) - - checkNotNull(scriptComponent) { "failed to get restconf script component" } - - // Handles both script processing and error handling - scriptComponent.executeScript(executionServiceInput) - } - - override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { - bluePrintRuntimeService.getBluePrintError() - .addError("Failed in ComponentRestconfExecutor : ${runtimeException.message}") - } -}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt deleted file mode 100644 index ede833cfb..000000000 --- a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright © 2018 IBM. - * - * 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. - */ -@file:Suppress("unused") - -package org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor - -import kotlinx.coroutines.runBlocking -import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants -import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionService -import org.onap.ccsdk.cds.blueprintsprocessor.rest.RestLibConstants -import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BluePrintRestLibPropertyService -import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService -import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction - -@Deprecated("Methods defined as extension function of AbstractComponentFunction") -abstract class RestconfComponentFunction : AbstractScriptComponentFunction() { - - @Deprecated("Defined in AbstractScriptComponentFunction extension class") - open fun bluePrintRestLibPropertyService(): BluePrintRestLibPropertyService = - functionDependencyInstanceAsType(RestLibConstants.SERVICE_BLUEPRINT_REST_LIB_PROPERTY) - - @Deprecated(" Use resourceResolutionService method directly", - replaceWith = ReplaceWith("resourceResolutionService()", - "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.resourceResolutionService")) - open fun resourceResolutionService(): ResourceResolutionService = - functionDependencyInstanceAsType(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) - - - @Deprecated("Defined in AbstractScriptComponentFunction extension class") - fun restClientService(selector: String): BlueprintWebClientService { - return bluePrintRestLibPropertyService().blueprintWebClientService(selector) - } - - @Deprecated(" Use storedContentFromResolvedArtifact method directly", - replaceWith = ReplaceWith("storedContentFromResolvedArtifact(resolutionKey, artifactName)", - "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.storedContentFromResolvedArtifact")) - fun resolveFromDatabase(resolutionKey: String, artifactName: String): String = runBlocking { - resourceResolutionService().resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey) - } - - @Deprecated(" Use artifactContent method directly", - replaceWith = ReplaceWith("artifactContent(artifactName)", - "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.artifactContent")) - fun generateMessage(artifactName: String): String { - return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName) - } - - @Deprecated(" Use contentFromResolvedArtifact method directly", - replaceWith = ReplaceWith("resolveAndGenerateMessage(artifactPrefix)", - "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.resolveAndGenerateMessage")) - fun resolveAndGenerateMessage(artifactPrefix: String): String = runBlocking { - resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, - artifactPrefix, mapOf()) - } -}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfExecutorExtensions.kt b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfExecutorExtensions.kt index 6e0c3b612..49fd025d9 100644 --- a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfExecutorExtensions.kt +++ b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfExecutorExtensions.kt @@ -17,21 +17,86 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor +import org.hibernate.annotations.common.util.impl.LoggerFactory +import org.onap.ccsdk.cds.blueprintsprocessor.rest.restClientService +import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintRetryException +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService + /** * Register the Restconf module exposed dependency */ +val log = LoggerFactory.logger(AbstractScriptComponentFunction::class.java)!! + +fun AbstractScriptComponentFunction.restconfClientService(selector: String): BlueprintWebClientService { + return BluePrintDependencyService.restClientService(selector) +} /** * Generic Mount function */ +suspend fun AbstractScriptComponentFunction.restconfMountDevice(webClientService: BlueprintWebClientService, + deviceId: String, payload: Any) { + val headers: MutableMap<String, String> = hashMapOf() + headers["Content-Type"] = "application/xml" + val mountUrl = "restconf/config/network-topology:network-topology/topology/topology-netconf/node/$deviceId" + log.info("sending mount request, url: $mountUrl") + webClientService.exchangeNB("PUT", mountUrl, payload, headers) + + /** Check device has mounted */ + val mountCheckUrl = "restconf/operational/network-topology:network-topology/topology/topology-netconf/node/$deviceId" + + val expectedResult = """"netconf-node-topology:connection-status":"connected"""" + val mountCheckExecutionBlock: suspend (Int) -> String = { tryCount: Int -> + val result = webClientService.exchangeNB("GET", mountCheckUrl, "") + if (result.body.contains(expectedResult)) { + log.info("NF was mounted successfully on ODL") + result.body + } else { + throw BluePrintRetryException("Wait for device($deviceId) to mount") + } + } + + log.info("url for ODL status check: $mountCheckUrl") + webClientService.retry<String>(10, 0, 1000, mountCheckExecutionBlock) +} /** * Generic Configure function */ +suspend fun AbstractScriptComponentFunction.restconfApplyDeviceConfig(webClientService: BlueprintWebClientService, + deviceId: String, configletResourcePath: String, + configletToApply: Any, + additionalHeaders: Map<String, String>?) { + log.debug("headers: $additionalHeaders") + log.info("configuring device: $deviceId, Configlet: $configletToApply") + val applyConfigUrl = "restconf/config/network-topology:network-topology/topology/topology-netconf/node/" + + "$deviceId/$configletResourcePath" + val result = webClientService.exchangeNB("PATCH", applyConfigUrl, configletToApply, additionalHeaders) + log.info("Configuration application result: $result") +} + + +suspend fun AbstractScriptComponentFunction.restconfDeviceConfig(webClientService: BlueprintWebClientService, + deviceId: String, configletResourcePath: String) + : BlueprintWebClientService.WebClientResponse<String> { + + val configPathUrl = "restconf/config/network-topology:network-topology/topology/topology-netconf/node/" + + "$deviceId/$configletResourcePath" + log.debug("sending GET request, url: $configPathUrl") + return webClientService.exchangeNB("GET", configPathUrl, "") +} /** - * Generic Unmount function - */
\ No newline at end of file + * Generic UnMount function + */ +suspend fun AbstractScriptComponentFunction.restconfUnMountDevice(webClientService: BlueprintWebClientService, + deviceId: String, payload: String) { + val unMountUrl = "restconf/config/network-topology:network-topology/topology/topology-netconf/node/$deviceId" + log.info("sending unMount request, url: $unMountUrl") + webClientService.exchangeNB("DELETE", unMountUrl, "") +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/restconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ComponentRestconfExecutorTest.kt b/ms/blueprintsprocessor/functions/restconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ComponentRestconfExecutorTest.kt index a651dad52..fb47b6ad1 100644 --- a/ms/blueprintsprocessor/functions/restconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ComponentRestconfExecutorTest.kt +++ b/ms/blueprintsprocessor/functions/restconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ComponentRestconfExecutorTest.kt @@ -17,7 +17,6 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.databind.node.ArrayNode import com.fasterxml.jackson.databind.node.ObjectNode import io.mockk.every import io.mockk.mockk @@ -28,6 +27,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ActionIdentifiers import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.CommonHeader import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentScriptExecutor import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext @@ -56,12 +56,12 @@ import kotlin.test.assertNotNull class ComponentRestconfExecutorTest { @Autowired - lateinit var componentRestconfExecutor: ComponentRestconfExecutor + lateinit var componentScriptExecutor: ComponentScriptExecutor @Test fun `test Restconf Component Instance`() { runBlocking { - assertNotNull(componentRestconfExecutor, "failed to get ComponentRestconfExecutor instance") + assertNotNull(componentScriptExecutor, "failed to get ComponentRestconfExecutor instance") val executionServiceInput = ExecutionServiceInput().apply { commonHeader = CommonHeader().apply { requestId = "1234" @@ -72,17 +72,16 @@ class ComponentRestconfExecutorTest { payload = JacksonUtils.jsonNode("{}") as ObjectNode } val bluePrintRuntime = mockk<DefaultBluePrintRuntimeService>("1234") - componentRestconfExecutor.bluePrintRuntimeService = bluePrintRuntime - componentRestconfExecutor.stepName = "sample-step" + componentScriptExecutor.bluePrintRuntimeService = bluePrintRuntime + componentScriptExecutor.stepName = "sample-step" val operationInputs = hashMapOf<String, JsonNode>() operationInputs[BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE] = "activate-restconf".asJsonPrimitive() operationInputs[BluePrintConstants.PROPERTY_CURRENT_INTERFACE] = "interfaceName".asJsonPrimitive() operationInputs[BluePrintConstants.PROPERTY_CURRENT_OPERATION] = "operationName".asJsonPrimitive() - operationInputs[ComponentRestconfExecutor.SCRIPT_TYPE] = BluePrintConstants.SCRIPT_INTERNAL.asJsonPrimitive() - operationInputs[ComponentRestconfExecutor.SCRIPT_CLASS_REFERENCE] = - "InternalSimpleRestconf_cba\$TestRestconfConfigure".asJsonPrimitive() - operationInputs[ComponentRestconfExecutor.INSTANCE_DEPENDENCIES] = JacksonUtils.jsonNode("[]") as ArrayNode + operationInputs[ComponentScriptExecutor.SCRIPT_TYPE] = BluePrintConstants.SCRIPT_INTERNAL.asJsonPrimitive() + operationInputs[ComponentScriptExecutor.SCRIPT_CLASS_REFERENCE] = + "internal.scripts.TestRestconfConfigure".asJsonPrimitive() val stepInputData = StepData().apply { name = "activate-restconf" @@ -103,7 +102,7 @@ class ComponentRestconfExecutorTest { "interfaceName", "operationName") } returns operationOutputs - componentRestconfExecutor.applyNB(executionServiceInput) + componentScriptExecutor.applyNB(executionServiceInput) } } }
\ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BlueprintWebClientService.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BlueprintWebClientService.kt index 5d35186b8..1acd07b7b 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BlueprintWebClientService.kt +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BlueprintWebClientService.kt @@ -23,18 +23,15 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.apache.commons.io.IOUtils import org.apache.http.client.ClientProtocolException -import org.apache.http.client.methods.HttpDelete -import org.apache.http.client.methods.HttpGet -import org.apache.http.client.methods.HttpPatch -import org.apache.http.client.methods.HttpPost -import org.apache.http.client.methods.HttpPut -import org.apache.http.client.methods.HttpUriRequest +import org.apache.http.client.methods.* import org.apache.http.entity.StringEntity import org.apache.http.impl.client.CloseableHttpClient import org.apache.http.impl.client.HttpClients import org.apache.http.message.BasicHeader import org.onap.ccsdk.cds.blueprintsprocessor.rest.utils.WebClientUtils import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintRetryException +import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintIOUtils import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.springframework.http.HttpMethod import java.io.IOException @@ -49,9 +46,22 @@ interface BlueprintWebClientService { fun httpClient(): CloseableHttpClient { return HttpClients.custom() - .addInterceptorFirst(WebClientUtils.logRequest()) - .addInterceptorLast(WebClientUtils.logResponse()) - .build() + .addInterceptorFirst(WebClientUtils.logRequest()) + .addInterceptorLast(WebClientUtils.logResponse()) + .build() + } + + /** High performance non blocking Retry function, If execution block [block] throws BluePrintRetryException + * exception then this will perform wait and retrigger accoring to times [times] with delay [delay] + */ + suspend fun <T> retry(times: Int = 1, initialDelay: Long = 0, delay: Long = 1000, + block: suspend (Int) -> T): T { + val exceptionBlock = { e: Exception -> + if (e !is BluePrintRetryException) { + throw e + } + } + return BluePrintIOUtils.retry(times, initialDelay, delay, block, exceptionBlock) } fun exchangeResource(methodType: String, path: String, request: String): WebClientResponse<String> { @@ -72,8 +82,7 @@ interface BlueprintWebClientService { HttpMethod.POST -> post(path, request, convertedHeaders, String::class.java) HttpMethod.PUT -> put(path, request, convertedHeaders, String::class.java) HttpMethod.PATCH -> patch(path, request, convertedHeaders, String::class.java) - else -> throw BluePrintProcessorException("Unsupported met" + - "hodType($methodType)") + else -> throw BluePrintProcessorException("Unsupported methodType($methodType)") } } @@ -126,8 +135,8 @@ interface BlueprintWebClientService { @Throws(IOException::class, ClientProtocolException::class) private fun <T> performCallAndExtractTypedWebClientResponse( - httpUriRequest: HttpUriRequest, responseType: Class<T>): - WebClientResponse<T> { + httpUriRequest: HttpUriRequest, responseType: Class<T>): + WebClientResponse<T> { val httpResponse = httpClient().execute(httpUriRequest) val statusCode = httpResponse.statusLine.statusCode httpResponse.entity.content.use { @@ -145,10 +154,9 @@ interface BlueprintWebClientService { } suspend fun <T> getNB(path: String, additionalHeaders: Array<BasicHeader>?, responseType: Class<T>): - WebClientResponse<T> = - withContext(Dispatchers.IO) { - get(path, additionalHeaders!!, responseType) - } + WebClientResponse<T> = withContext(Dispatchers.IO) { + get(path, additionalHeaders!!, responseType) + } suspend fun postNB(path: String, request: Any): WebClientResponse<String> { return postNB(path, request, null, String::class.java) @@ -159,10 +167,9 @@ interface BlueprintWebClientService { } suspend fun <T> postNB(path: String, request: Any, additionalHeaders: Array<BasicHeader>?, - responseType: Class<T>): WebClientResponse<T> = - withContext(Dispatchers.IO) { - post(path, request, additionalHeaders!!, responseType) - } + responseType: Class<T>): WebClientResponse<T> = withContext(Dispatchers.IO) { + post(path, request, additionalHeaders!!, responseType) + } suspend fun putNB(path: String, request: Any): WebClientResponse<String> { return putNB(path, request, null, String::class.java) @@ -175,39 +182,36 @@ interface BlueprintWebClientService { suspend fun <T> putNB(path: String, request: Any, additionalHeaders: Array<BasicHeader>?, - responseType: Class<T>): WebClientResponse<T> = - withContext(Dispatchers.IO) { - put(path, request, additionalHeaders!!, responseType) - } + responseType: Class<T>): WebClientResponse<T> = withContext(Dispatchers.IO) { + put(path, request, additionalHeaders!!, responseType) + } suspend fun <T> deleteNB(path: String): WebClientResponse<String> { return deleteNB(path, null, String::class.java) } suspend fun <T> deleteNB(path: String, additionalHeaders: Array<BasicHeader>?): - WebClientResponse<String> { + WebClientResponse<String> { return deleteNB(path, additionalHeaders, String::class.java) } suspend fun <T> deleteNB(path: String, additionalHeaders: Array<BasicHeader>?, responseType: Class<T>): - WebClientResponse<T> = - withContext(Dispatchers.IO) { - delete(path, additionalHeaders!!, responseType) - } + WebClientResponse<T> = withContext(Dispatchers.IO) { + delete(path, additionalHeaders!!, responseType) + } suspend fun <T> patchNB(path: String, request: Any, additionalHeaders: Array<BasicHeader>?, responseType: Class<T>): - WebClientResponse<T> = - withContext(Dispatchers.IO) { - patch(path, request, additionalHeaders!!, responseType) - } + WebClientResponse<T> = withContext(Dispatchers.IO) { + patch(path, request, additionalHeaders!!, responseType) + } suspend fun exchangeNB(methodType: String, path: String, request: Any): WebClientResponse<String> { return exchangeNB(methodType, path, request, hashMapOf(), - String::class.java) + String::class.java) } suspend fun exchangeNB(methodType: String, path: String, request: Any, additionalHeaders: Map<String, String>?): - WebClientResponse<String> { + WebClientResponse<String> { return exchangeNB(methodType, path, request, additionalHeaders, String::class.java) } @@ -224,8 +228,7 @@ interface BlueprintWebClientService { HttpMethod.DELETE -> deleteNB(path, convertedHeaders, responseType) HttpMethod.PUT -> putNB(path, request, convertedHeaders, responseType) HttpMethod.PATCH -> patchNB(path, request, convertedHeaders, responseType) - else -> throw BluePrintProcessorException("Unsupported method" + - "Type($methodType)") + else -> throw BluePrintProcessorException("Unsupported methodType($methodType)") } } @@ -246,7 +249,7 @@ interface BlueprintWebClientService { } private fun basicHeaders(headers: Map<String, String>?): - Array<BasicHeader> { + Array<BasicHeader> { val basicHeaders = mutableListOf<BasicHeader>() defaultHeaders().forEach { (name, value) -> basicHeaders.add(BasicHeader(name, value)) @@ -260,9 +263,9 @@ interface BlueprintWebClientService { // Non Blocking Rest Implementation suspend fun httpClientNB(): CloseableHttpClient { return HttpClients.custom() - .addInterceptorFirst(WebClientUtils.logRequest()) - .addInterceptorLast(WebClientUtils.logResponse()) - .build() + .addInterceptorFirst(WebClientUtils.logRequest()) + .addInterceptorLast(WebClientUtils.logResponse()) + .build() } //TODO maybe there could be cases where we care about return headers? diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintProcessorException.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintProcessorException.kt index 6d11f0349..0a530708f 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintProcessorException.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintProcessorException.kt @@ -48,3 +48,9 @@ class BluePrintProcessorException : RuntimeException { } } +class BluePrintRetryException : RuntimeException { + constructor(message: String, cause: Throwable) : super(message, cause) + constructor(message: String) : super(message) + constructor(cause: Throwable) : super(cause) + constructor(cause: Throwable, message: String, vararg args: Any?) : super(format(message, *args), cause) +} diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/dsl/BluePrintTemplateDSLBuilder.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/dsl/BluePrintTemplateDSLBuilder.kt index eec59d1a7..fd747f09c 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/dsl/BluePrintTemplateDSLBuilder.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/dsl/BluePrintTemplateDSLBuilder.kt @@ -227,6 +227,10 @@ class OperationAssignmentBuilder(private val id: String, private var operationAssignment: OperationAssignment = OperationAssignment() + fun implementation(implementation: Implementation?) { + operationAssignment.implementation = implementation + } + fun implementation(timeout: Int, operationHost: String? = BluePrintConstants.PROPERTY_SELF) { val implementation = Implementation().apply { this.operationHost = operationHost!! @@ -235,10 +239,18 @@ class OperationAssignmentBuilder(private val id: String, operationAssignment.implementation = implementation } + fun inputs(inputs: MutableMap<String, JsonNode>?) { + operationAssignment.inputs = inputs + } + fun inputs(block: PropertiesAssignmentBuilder.() -> Unit) { operationAssignment.inputs = PropertiesAssignmentBuilder().apply(block).build() } + fun outputs(outputs: MutableMap<String, JsonNode>?) { + operationAssignment.outputs = outputs + } + fun outputs(block: PropertiesAssignmentBuilder.() -> Unit) { operationAssignment.outputs = PropertiesAssignmentBuilder().apply(block).build() } diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/BluePrintIOUtils.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/BluePrintIOUtils.kt new file mode 100644 index 000000000..226c62d48 --- /dev/null +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/BluePrintIOUtils.kt @@ -0,0 +1,36 @@ +/* + * Copyright © 2019 IBM. + * + * 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. + */ + +package org.onap.ccsdk.cds.controllerblueprints.core.utils + +object BluePrintIOUtils { + + suspend fun <T> retry(times: Int = 1, initialDelay: Long = 0, delay: Long = 1000, + block: suspend (Int) -> T, exceptionBlock: (e: Exception) -> Unit): T { + var currentDelay = initialDelay + val currentTimes = times - 1 + repeat(currentTimes) { count -> + try { + return block(count) + } catch (e: Exception) { + exceptionBlock(e) + } + kotlinx.coroutines.delay(currentDelay) + currentDelay = delay + } + return block(currentTimes) + } +}
\ No newline at end of file diff --git a/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/BluePrintIOUtilsTest.kt b/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/BluePrintIOUtilsTest.kt new file mode 100644 index 000000000..2aea4bc2d --- /dev/null +++ b/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/BluePrintIOUtilsTest.kt @@ -0,0 +1,42 @@ +/* + * Copyright © 2019 IBM. + * + * 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. + */ + +package org.onap.ccsdk.cds.controllerblueprints.core.utils + +import kotlinx.coroutines.runBlocking +import org.junit.Test +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintRetryException + + +class BluePrintIOUtilsTest { + + @Test + fun testRetry() { + runBlocking { + val executionBlock: suspend (Int) -> String = { count: Int -> + "success" + } + val exceptionBlock = { e: Exception -> + if (e is BluePrintRetryException) { + println("this is blueprint error") + } else { + throw e + } + } + BluePrintIOUtils.retry<String>(4, 0, 500, executionBlock, exceptionBlock) + } + } +}
\ No newline at end of file diff --git a/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JsonParserUtilsTest.kt b/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JsonParserUtilsTest.kt index 810dae738..8a37a4b19 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JsonParserUtilsTest.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JsonParserUtilsTest.kt @@ -22,6 +22,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.jsonAsJsonType import org.onap.ccsdk.cds.controllerblueprints.core.jsonPathParse import org.onap.ccsdk.cds.controllerblueprints.core.jsonPaths import kotlin.test.assertEquals +import kotlin.test.assertNotNull class JsonParserUtilsTest { @@ -52,6 +53,6 @@ class JsonParserUtilsTest { """.trimIndent() val jsonNode = json.jsonAsJsonType() val parsedPath = jsonNode.jsonPaths("$..prop1") - println(parsedPath) + assertNotNull(parsedPath, "failed to get parsed path") } }
\ No newline at end of file |