Clean restconf duplicate models and Implementation. 25/91825/2
authorBrinda Santh <brindasanth@in.ibm.com>
Mon, 22 Jul 2019 17:09:18 +0000 (13:09 -0400)
committerBrinda Santh <brindasanth@in.ibm.com>
Tue, 23 Jul 2019 19:31:17 +0000 (15:31 -0400)
Change-Id: Id439ac5ded631aac0ee7fc69846ebe9bca650bb2
Issue-ID: CCSDK-1499
Signed-off-by: Brinda Santh <brindasanth@in.ibm.com>
19 files changed:
components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json
components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/node_types.json
components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/activation-blueprint.json
components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/node_types.json
components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Scripts/python/RestconfConfigDeploy.py
components/model-catalog/definition-type/starter-type/node_type/component-restconf-executor.json [deleted file]
components/scripts/python/ccsdk_restconf/restconf_client.py
ms/blueprintsprocessor/functions/resource-resolution/src/test/resources/logback-test.xml
ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/internal/scripts/InternalSimpleRestconf.kt [moved from ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/scripts/InternalSimpleRestconf.cba.kts with 86% similarity]
ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ComponentRestconfExecutor.kt [deleted file]
ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt [deleted file]
ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfExecutorExtensions.kt
ms/blueprintsprocessor/functions/restconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ComponentRestconfExecutorTest.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BlueprintWebClientService.kt
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintProcessorException.kt
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/dsl/BluePrintTemplateDSLBuilder.kt
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/BluePrintIOUtils.kt [new file with mode: 0644]
ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/BluePrintIOUtilsTest.kt [new file with mode: 0644]
ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/JsonParserUtilsTest.kt

index 135016a..112014b 100644 (file)
         }
       },
       "activate-restconf": {
-        "type": "component-restconf-executor",
+        "type": "component-script-executor",
         "interfaces": {
-          "ComponentRestconfExecutor": {
+          "ComponentScriptExecutor": {
             "operations": {
               "process": {
                 "implementation": {
                 },
                 "inputs": {
                   "script-type": "kotlin",
-                  "script-class-reference": "DefaultRestconf_cba$MountNEditConfigure",
-                  "instance-dependencies": []
+                  "script-class-reference": "DefaultRestconf_cba$MountNEditConfigure"
                 },
                 "outputs": {
                   "response-data": "",
index 6de1fe3..3595a9f 100644 (file)
       },
       "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",
index b3f5272..d185128 100644 (file)
         }
       },
       "config-deploy" : {
-        "type" : "component-restconf-executor",
+        "type" : "component-script-executor",
         "interfaces" : {
-          "ComponentRestconfExecutor" : {
+          "ComponentScriptExecutor" : {
             "operations" : {
               "process" : {
                 "implementation" : {
                 "inputs" : {
                   "script-type" : "jython",
                   "script-class-reference" : "Scripts/python/RestconfConfigDeploy.py",
-                  "instance-dependencies" : [ ],
                   "dynamic-properties" : "*config-deploy-properties"
                 },
                 "outputs" : {
index d6f702a..8c2c0ab 100644 (file)
@@ -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" : {
                   "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,
index d65aefa..17dd561 100644 (file)
@@ -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 (file)
index cb28a4a..0000000
+++ /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
index 6d18b03..ec25853 100644 (file)
 # ============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"}
index c37e0b5..305c59f 100644 (file)
@@ -26,6 +26,7 @@
 \r
     <logger name="org.springframework" level="warn"/>\r
     <logger name="org.hibernate" level="info"/>\r
+    <logger name="org.mockserver.mock" level="warn"/>\r
     <logger name="org.onap.ccsdk.cds.controllerblueprints" level="warn"/>\r
     <logger name="org.onap.ccsdk.cds.blueprintsprocessor" level="info"/>\r
 \r
@@ -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.
  *  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 (file)
index 53828d7..0000000
+++ /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 (file)
index ede833c..0000000
+++ /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
index 6e0c3b6..49fd025 100644 (file)
 
 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
index a651dad..fb47b6a 100644 (file)
@@ -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
index 5d35186..1acd07b 100644 (file)
@@ -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?
index 6d11f03..0a53070 100644 (file)
@@ -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)
+}
index eec59d1..fd747f0 100644 (file)
@@ -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 (file)
index 0000000..226c62d
--- /dev/null
@@ -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 (file)
index 0000000..2aea4bc
--- /dev/null
@@ -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
index 810dae7..8a37a4b 100644 (file)
@@ -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