Runtime services for Relationship Type and Templates 28/99928/2
authorBrinda Santh <bs2796@att.com>
Fri, 27 Dec 2019 20:43:53 +0000 (15:43 -0500)
committerKAPIL SINGAL <ks220y@att.com>
Mon, 30 Dec 2019 18:18:57 +0000 (18:18 +0000)
Added and improved blueprint runtime service property resolution api.

Relationship template CBA sample

Performance improvement on  Artifact resolutions.

Added connection config DSL for DB, GRPC connections.

Added starter relationship connection config models.

Issue-ID: CCSDK-1054
Signed-off-by: Brinda Santh <bs2796@att.com>
Change-Id: I73e1deed708dc924352867ddd1d1b2271c8ea106

30 files changed:
components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/activation-blueprint.json
components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/relationship_types.json
components/model-catalog/blueprint-model/test-blueprint/capability_cli/Definitions/capability-cli-blueprint.json
components/model-catalog/blueprint-model/test-blueprint/capability_cli/Scripts/kotlin/cba/capability/cli/CapabilityCli.kt
components/model-catalog/blueprint-model/test-blueprint/capability_cli/Scripts/kotlin/cba/capability/cli/CapabilityCliDefinitions.kt
components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.Db.json [new file with mode: 0644]
components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.GrpcClient.json [new file with mode: 0644]
components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.GrpcServer.json [new file with mode: 0644]
components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.MessageConsumer.json [new file with mode: 0644]
components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.MessageProducer.json [new file with mode: 0644]
components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.Nats.json [new file with mode: 0644]
components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.RestClient.json [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt
ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentJythonExecutor.kt
ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/scripts/BlueprintJythonServiceImpl.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintChainedService.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintContext.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintRuntimeService.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/PropertyAssignmentService.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/ServiceTemplateUtils.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintRuntimeServiceTest.kt
ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt
ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BluePrintDBLibData.kt
ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/DatabasePropertiesDSL.kt
ms/blueprintsprocessor/modules/commons/db-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/DatabasePropertiesDSLTest.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/commons/grpc-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/grpc/GrpcPropertiesDSL.kt
ms/blueprintsprocessor/modules/commons/grpc-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/grpc/GrpcPropertiesDSLTest.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/load/ResourceDictionaryLoadService.kt
ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt

index 70c1bc3..639c214 100644 (file)
         }
       }
     },
+    "relationship_templates": {
+      "cli-device-properties": {
+        "type": "tosca.relationships.ConnectsTo.SshClient",
+        "description": "SSH Connection",
+        "properties": {
+          "connection-config": {
+            "password": "sample-password",
+            "host": {
+              "get_input": "hostname"
+            },
+            "type": "basic-auth",
+            "connectionTimeOut": 30,
+            "username": "sample-user"
+          }
+        }
+      }
+    },
     "workflows": {
       "resource-assignment": {
         "inputs": {
index 87d2dc5..b56c77a 100644 (file)
@@ -4,6 +4,21 @@
       "description": "Relationship tosca.relationships.ConnectsTo",
       "version": "1.0.0",
       "derived_from": "tosca.relationships.Root"
+    },
+    "tosca.relationships.ConnectsTo.SshClient": {
+      "description": "Relationship connects to through SSH Client.",
+      "version": "1.0.0",
+      "properties": {
+        "connection-config": {
+          "description": "Connection Config details.",
+          "required": true,
+          "type": "map"
+        }
+      },
+      "derived_from": "tosca.relationships.ConnectsTo",
+      "valid_target_types": [
+        "tosca.capabilities.Endpoint"
+      ]
     }
   }
 }
\ No newline at end of file
index e73f96d..04d0752 100644 (file)
       "file": "Definitions/policy_types.json"
     }
   ],
-  "dsl_definitions": {
-    "config-deploy-properties": {
-      "resolution-key": {
-        "get_input": "resolution-key"
-      }
-    },
-    "device-properties": {
-      "type": "basic-auth",
-      "host": {
-        "get_input": "hostname"
-      },
-      "username": {
-        "get_input": "username"
-      },
-      "password": {
-        "get_input": "password"
-      }
-    }
-  },
   "topology_template": {
     "workflows": {
       "check": {
index 7bda628..e290556 100644 (file)
@@ -24,7 +24,6 @@ import org.onap.ccsdk.cds.controllerblueprints.core.asJsonString
 import org.onap.ccsdk.cds.controllerblueprints.core.logger
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
 
-
 open class Check : AbstractScriptComponentFunction() {
 
     private val log = logger(Check::class)
@@ -45,8 +44,8 @@ open class Check : AbstractScriptComponentFunction() {
 
         log.info("Check Commands :$checkCommands")
 
-        // Get the Device Information from the DSL Model
-        val deviceInformation = bluePrintRuntimeService.resolveDSLExpression("device-properties")
+        // Get the Device Information from the Relationship Model
+        val deviceInformation = relationshipProperty("ssh-connection-config", "connection-config")
 
         log.info("Device Info :$deviceInformation")
 
@@ -54,10 +53,9 @@ open class Check : AbstractScriptComponentFunction() {
         val sshClientService = BluePrintDependencyService.sshClientService(deviceInformation)
 
         log.info("Client service is ready")
-
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
         log.info("Executing Recovery")
     }
-}
\ No newline at end of file
+}
index 3700a0b..a4a2ccf 100644 (file)
@@ -18,8 +18,11 @@ package cba.capability.cli
 
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.nodeTemplateComponentScriptExecutor
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.nodeTypeComponentScriptExecutor
-import org.onap.ccsdk.cds.blueprintsprocessor.ssh.basicAuthSshProperties
+import org.onap.ccsdk.cds.blueprintsprocessor.ssh.relationshipTemplateSshClient
+import org.onap.ccsdk.cds.blueprintsprocessor.ssh.relationshipTypeConnectsToSshClient
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonString
 import org.onap.ccsdk.cds.controllerblueprints.core.data.ServiceTemplate
 import org.onap.ccsdk.cds.controllerblueprints.core.dsl.artifactTypeTemplateVelocity
 import org.onap.ccsdk.cds.controllerblueprints.core.dsl.getAttribute
@@ -43,13 +46,6 @@ fun CapabilityCliDefinitions.defaultServiceTemplate() =
         author = "Brinda Santh Muthuramalingam",
         tags = "brinda, tosca"
     ) {
-
-        dsl("device-properties", BluePrintTypes.basicAuthSshProperties {
-            host(getInput("hostname"))
-            password(getInput("password"))
-            username(getInput("username"))
-        })
-
         topologyTemplate {
             workflow(id = "check", description = "CLI Check Workflow") {
                 inputs {
@@ -69,8 +65,8 @@ fun CapabilityCliDefinitions.defaultServiceTemplate() =
             val checkComponent = BluePrintTypes.nodeTemplateComponentScriptExecutor(id = "check", description = "") {
                 definedOperation(description = "") {
                     inputs {
-                        type("kotlin")
-                        scriptClassReference("cba.capability.cli.Check")
+                        type(BluePrintConstants.SCRIPT_KOTLIN)
+                        scriptClassReference(Check::class)
                     }
                     outputs {
                         status(getAttribute("status"))
@@ -83,6 +79,15 @@ fun CapabilityCliDefinitions.defaultServiceTemplate() =
                 )
             }
             nodeTemplate(checkComponent)
+
+            /** Connection Configuration through Relationship **/
+            relationshipTemplateSshClient("ssh-connection-config", "Device connection config") {
+                basicAuth {
+                    host(getInput("hostname"))
+                    password(getInput("password"))
+                    username(getInput("username"))
+                }
+            }
         }
 
         /** Artifact Types */
@@ -91,6 +96,6 @@ fun CapabilityCliDefinitions.defaultServiceTemplate() =
         nodeType(BluePrintTypes.nodeTypeComponent())
         nodeType(BluePrintTypes.nodeTypeComponentScriptExecutor())
         /** Relationship Types */
+        relationshipType(BluePrintTypes.relationshipTypeConnectsToSshClient())
         relationshipType(BluePrintTypes.relationshipTypeConnectsTo())
-
     }
diff --git a/components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.Db.json b/components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.Db.json
new file mode 100644 (file)
index 0000000..01e87d5
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "description": "Relationship connects to through Database.",
+  "version": "1.0.0",
+  "properties": {
+    "connection-config": {
+      "description": "Connection Config details.",
+      "required": true,
+      "type": "map"
+    }
+  },
+  "derived_from": "tosca.relationships.ConnectsTo",
+  "valid_target_types": [
+    "tosca.capabilities.Endpoint"
+  ]
+}
\ No newline at end of file
diff --git a/components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.GrpcClient.json b/components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.GrpcClient.json
new file mode 100644 (file)
index 0000000..eea7a0d
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "description": "Relationship connects to through GRPC Client.",
+  "version": "1.0.0",
+  "properties": {
+    "connection-config": {
+      "description": "Connection Config details.",
+      "required": true,
+      "type": "map"
+    }
+  },
+  "derived_from": "tosca.relationships.ConnectsTo",
+  "valid_target_types": [
+    "tosca.capabilities.Endpoint"
+  ]
+}
\ No newline at end of file
diff --git a/components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.GrpcServer.json b/components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.GrpcServer.json
new file mode 100644 (file)
index 0000000..d981143
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "description": "Relationship connects to through GRPC Server.",
+  "version": "1.0.0",
+  "properties": {
+    "connection-config": {
+      "description": "Connection Config details.",
+      "required": true,
+      "type": "map"
+    }
+  },
+  "derived_from": "tosca.relationships.ConnectsTo",
+  "valid_target_types": [
+    "tosca.capabilities.Endpoint"
+  ]
+}
\ No newline at end of file
diff --git a/components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.MessageConsumer.json b/components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.MessageConsumer.json
new file mode 100644 (file)
index 0000000..7de2fc2
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "description": "Relationship type connects to message consumer.",
+  "version": "1.0.0",
+  "properties": {
+    "connection-config": {
+      "description": "Connection Config details.",
+      "required": true,
+      "type": "map"
+    }
+  },
+  "derived_from": "tosca.relationships.ConnectsTo",
+  "valid_target_types": [
+    "tosca.capabilities.Endpoint"
+  ]
+}
\ No newline at end of file
diff --git a/components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.MessageProducer.json b/components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.MessageProducer.json
new file mode 100644 (file)
index 0000000..d3c3580
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "description": "Relationship connects to through message producer.",
+  "version": "1.0.0",
+  "properties": {
+    "connection-config": {
+      "description": "Connection Config details.",
+      "required": true,
+      "type": "map"
+    }
+  },
+  "derived_from": "tosca.relationships.ConnectsTo",
+  "valid_target_types": [
+    "tosca.capabilities.Endpoint"
+  ]
+}
\ No newline at end of file
diff --git a/components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.Nats.json b/components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.Nats.json
new file mode 100644 (file)
index 0000000..be03484
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "description": "Relationship connects to through NATS Client.",
+  "version": "1.0.0",
+  "properties": {
+    "connection-config": {
+      "description": "Connection Config details.",
+      "required": true,
+      "type": "map"
+    }
+  },
+  "derived_from": "tosca.relationships.ConnectsTo",
+  "valid_target_types": [
+    "tosca.capabilities.Endpoint"
+  ]
+}
\ No newline at end of file
diff --git a/components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.RestClient.json b/components/model-catalog/definition-type/starter-type/relationship_type/tosca.relationships.ConnectsTo.RestClient.json
new file mode 100644 (file)
index 0000000..9182dbf
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "description": "Relationship connects to through",
+  "version": "1.0.0",
+  "properties": {
+    "connection-config": {
+      "description": "Connection Config details.",
+      "required": true,
+      "type": "map"
+    }
+  },
+  "derived_from": "tosca.relationships.ConnectsTo",
+  "valid_target_types": [
+    "tosca.capabilities.Endpoint"
+  ]
+}
\ No newline at end of file
index 58e6151..bb35381 100644 (file)
@@ -55,8 +55,8 @@ abstract class NetconfComponentFunction : AbstractScriptComponentFunction() {
             "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.artifactContent"
         )
     )
-    fun generateMessage(artifactName: String): String {
-        return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName)
+    fun generateMessage(artifactName: String): String = runBlocking {
+        bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName)
     }
 
     @Deprecated(
index 99e6c6c..03daf2a 100644 (file)
@@ -60,7 +60,7 @@ open class ComponentJythonExecutor(
                 .addError("Failed in ComponentJythonExecutor : ${runtimeException.message}")
     }
 
-    private fun populateJythonComponentInstance() {
+    private suspend fun populateJythonComponentInstance() {
         val bluePrintContext = bluePrintRuntimeService.bluePrintContext()
 
         val operationAssignment: OperationAssignment = bluePrintContext
index 7f4afe6..9000d65 100644 (file)
@@ -85,7 +85,7 @@ class BlueprintJythonServiceImpl(
         )
     }
 
-    fun jythonComponentInstance(abstractComponentFunction: AbstractComponentFunction): AbstractComponentFunction {
+    suspend fun jythonComponentInstance(abstractComponentFunction: AbstractComponentFunction): AbstractComponentFunction {
 
         val bluePrintRuntimeService = abstractComponentFunction.bluePrintRuntimeService
         val bluePrintContext = bluePrintRuntimeService.bluePrintContext()
index f0e2c5b..d1254b2 100644 (file)
@@ -81,6 +81,7 @@ object BluePrintConstants {
     const val PATH_INPUTS: String = "inputs"
     const val PATH_NODE_WORKFLOWS: String = "workflows"
     const val PATH_NODE_TEMPLATES: String = "node_templates"
+    const val PATH_RELATIONSHIP_TEMPLATES: String = "relationship_templates"
     const val PATH_CAPABILITIES: String = "capabilities"
     const val PATH_REQUIREMENTS: String = "requirements"
     const val PATH_INTERFACES: String = "interfaces"
@@ -97,6 +98,10 @@ object BluePrintConstants {
     const val MODEL_DEFINITION_TYPE_CAPABILITY_TYPE: String = "capability_type"
     const val MODEL_DEFINITION_TYPE_RELATIONSHIP_TYPE: String = "relationship_type"
     const val MODEL_DEFINITION_TYPE_DATA_TYPE: String = "data_type"
+    const val MODEL_DEFINITION_TYPE_NODE_TEMPLATE: String = "node_template"
+    const val MODEL_DEFINITION_TYPE_RELATIONSHIP_TEMPLATE: String = "relationship_template"
+    const val MODEL_DEFINITION_TYPE_WORKFLOW: String = "workflow"
+    const val MODEL_DEFINITION_TYPE_DSL: String = "dsl"
 
     const val MODEL_TYPE_DATATYPES_ROOT: String = "tosca.datatypes.Root"
     const val MODEL_TYPE_NODES_ROOT: String = "tosca.nodes.Root"
index 52fdbb5..a112b6e 100644 (file)
@@ -325,6 +325,16 @@ class BluePrintContext(val serviceTemplate: ServiceTemplate) {
         return nodeTemplateByName(relationshipTemplateName).properties?.get(propertyName)
     }
 
+    fun relationshipTemplateForRelationshipType(name: String): MutableMap<String, RelationshipTemplate>? {
+        return relationshipTemplates()?.filterValues { relationshipTemplate -> relationshipTemplate.type == name }
+            ?.toMutableMap()
+    }
+
+    fun relationshipTemplateRelationshipType(relationshipName: String): RelationshipType {
+        val relationshipTemplateType: String = relationshipTemplateByName(relationshipName).type
+        return relationshipTypeByName(relationshipTemplateType)
+    }
+
     // Chained Functions
 
     fun nodeTypeChained(nodeTypeName: String): NodeType {
index 841cc52..d68d680 100644 (file)
@@ -69,20 +69,50 @@ interface BluePrintRuntimeService<T> {
 
     fun loadEnvironments(type: String, fileName: String)
 
-    fun resolveNodeTemplatePropertyAssignments(
-        nodeTemplateName: String,
+    fun resolveWorkflowOutputs(workflowName: String): MutableMap<String, JsonNode>
+
+    fun resolveDSLExpression(dslPropertyName: String): JsonNode
+
+    /** Resolve Property Definition [definitionName] for type [definitionType] with [propertyDefinitions]
+     * Definition Type may be : node_template, relationship_template, dsl, workflow
+     * Assumption is Definition holds the expressions or value assigned in it. Mainly used for workflow outputs.
+     */
+    fun resolvePropertyDefinitions(
+        definitionType: String,
+        definitionName: String,
+        propertyDefinitions: MutableMap<String, PropertyDefinition>
+    ): MutableMap<String, JsonNode>
+
+    /** Resolve Property Assignments [definitionName] for type [definitionType] with [propertyDefinitions]
+     * and [propertyAssignments]
+     * Definition Type may be : node_template, relationship_template, dsl, workflow
+     */
+    fun resolvePropertyAssignments(
+        definitionType: String,
+        definitionName: String,
         propertyDefinitions: MutableMap<String, PropertyDefinition>,
         propertyAssignments: MutableMap<String, JsonNode>
     ): MutableMap<String, JsonNode>
 
-    fun resolvePropertyDefinitions(name: String, propertyDefinitions: MutableMap<String, PropertyDefinition>):
-        MutableMap<String, JsonNode>
-
-    fun resolvePropertyAssignments(name: String, propertyAssignments: MutableMap<String, JsonNode>):
-        MutableMap<String, JsonNode>
+    /** Resolve Property Assignments [definitionName] for type [definitionType] with  [propertyAssignments]
+     *  Definition Type may be : node_template, relationship_template, dsl, workflow
+     */
+    fun resolvePropertyAssignments(
+        definitionType: String,
+        definitionName: String,
+        propertyAssignments: MutableMap<String, JsonNode>
+    ): MutableMap<String, JsonNode>
 
+    /** Resolve Node Template [nodeTemplateName] Property Assignments */
     fun resolveNodeTemplateProperties(nodeTemplateName: String): MutableMap<String, JsonNode>
 
+    /** Resolve Node Template [nodeTemplateName] Property Assignments with [propertyDefinitions] and  [propertyAssignments]*/
+    fun resolveNodeTemplatePropertyAssignments(
+        nodeTemplateName: String,
+        propertyDefinitions: MutableMap<String, PropertyDefinition>,
+        propertyAssignments: MutableMap<String, JsonNode>
+    ): MutableMap<String, JsonNode>
+
     fun resolveNodeTemplateCapabilityProperties(nodeTemplateName: String, capabilityName: String): MutableMap<String,
         JsonNode>
 
@@ -98,13 +128,20 @@ interface BluePrintRuntimeService<T> {
         operationName: String
     ): MutableMap<String, JsonNode>
 
-    fun resolveNodeTemplateArtifact(nodeTemplateName: String, artifactName: String): String
+    suspend fun resolveNodeTemplateArtifact(nodeTemplateName: String, artifactName: String): String
 
     fun resolveNodeTemplateArtifactDefinition(nodeTemplateName: String, artifactName: String): ArtifactDefinition
 
+    /** Resolve Node Template [relationshipTemplateName] Property Assignments */
     fun resolveRelationshipTemplateProperties(relationshipTemplateName: String): MutableMap<String, JsonNode>
 
-    fun resolveDSLExpression(dslPropertyName: String): JsonNode
+    /** Resolve Relationship Template [relationshipTemplateName] Property Assignments with
+     * [propertyDefinitions] and  [propertyAssignments] */
+    fun resolveRelationshipTemplatePropertyAssignments(
+        relationshipTemplateName: String,
+        propertyDefinitions: MutableMap<String, PropertyDefinition>,
+        propertyAssignments: MutableMap<String, JsonNode>
+    ): MutableMap<String, JsonNode>
 
     fun setInputValue(propertyName: String, value: JsonNode)
 
@@ -156,13 +193,17 @@ interface BluePrintRuntimeService<T> {
 
     fun getNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String): JsonNode?
 
+    fun getRelationshipTemplatePropertyValue(relationshipTemplateName: String, propertyName: String): JsonNode?
+
+    fun getRelationshipTemplateAttributeValue(relationshipTemplateName: String, attributeName: String): JsonNode?
+
     fun assignInputs(jsonNode: JsonNode)
 
     fun assignWorkflowInputs(workflowName: String, jsonNode: JsonNode)
 
-    fun resolveWorkflowOutputs(workflowName: String): MutableMap<String, JsonNode>
-
     fun getJsonForNodeTemplateAttributeProperties(nodeTemplateName: String, keys: List<String>): JsonNode
+
+    suspend fun close()
 }
 
 /**
@@ -256,15 +297,68 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
         }
     }
 
+    override fun resolveWorkflowOutputs(workflowName: String): MutableMap<String, JsonNode> {
+        log.info("resolveWorkflowOutputs for workflow($workflowName)")
+        val outputs = bluePrintContext.workflowByName(workflowName).outputs ?: mutableMapOf()
+        return resolvePropertyDefinitions(BluePrintConstants.MODEL_DEFINITION_TYPE_WORKFLOW, "WORKFLOW", outputs)
+    }
+
     /**
-     * Resolve any property assignments for the node
+     * Read the DSL Property reference, If there is any expression, then resolve those expression and return as Json
+     * Type
      */
-    override fun resolveNodeTemplatePropertyAssignments(
-        nodeTemplateName: String,
+    override fun resolveDSLExpression(dslPropertyName: String): JsonNode {
+        val propertyAssignments = bluePrintContext.dslPropertiesByName(dslPropertyName)
+        return if (BluePrintExpressionService.checkContainsExpression(propertyAssignments) &&
+            propertyAssignments is ObjectNode
+        ) {
+            val rootKeyMap = propertyAssignments.rootFieldsToMap()
+            val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
+            rootKeyMap.forEach { (propertyName, propertyValue) ->
+                val propertyAssignmentExpression = PropertyAssignmentService(this)
+                propertyAssignmentValue[propertyName] = propertyAssignmentExpression
+                    .resolveAssignmentExpression(
+                        BluePrintConstants.MODEL_DEFINITION_TYPE_DSL,
+                        "DSL",
+                        propertyName,
+                        propertyValue
+                    )
+            }
+            propertyAssignmentValue.asJsonNode()
+        } else {
+            propertyAssignments
+        }
+    }
+
+    override fun resolvePropertyDefinitions(
+        definitionType: String,
+        definitionName: String,
+        propertyDefinitions: MutableMap<String, PropertyDefinition>
+    ): MutableMap<String, JsonNode> {
+        val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
+
+        propertyDefinitions.forEach { (propertyName, propertyDefinition) ->
+            val propertyAssignmentExpression = PropertyAssignmentService(this)
+            val expression = propertyDefinition.value ?: propertyDefinition.defaultValue
+            if (expression != null) {
+                propertyAssignmentValue[propertyName] =
+                    propertyAssignmentExpression.resolveAssignmentExpression(
+                        definitionType,
+                        definitionName,
+                        propertyName,
+                        expression
+                    )
+            }
+        }
+        return propertyAssignmentValue
+    }
+
+    override fun resolvePropertyAssignments(
+        definitionType: String,
+        definitionName: String,
         propertyDefinitions: MutableMap<String, PropertyDefinition>,
         propertyAssignments: MutableMap<String, JsonNode>
-    ):
-        MutableMap<String, JsonNode> {
+    ): MutableMap<String, JsonNode> {
 
         val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
 
@@ -277,7 +371,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
                 // Resolve the Expressing
                 val propertyAssignmentExpression = PropertyAssignmentService(this)
                 resolvedValue = propertyAssignmentExpression.resolveAssignmentExpression(
-                    nodeTemplateName, nodeTypePropertyName, propertyAssignment
+                    definitionType, definitionName, nodeTypePropertyName, propertyAssignment
                 )
             }
 
@@ -286,11 +380,13 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
                 nodeTypeProperty.defaultValue?.let { resolvedValue = nodeTypeProperty.defaultValue!! }
             }
 
-            /** If property is Map type, then resolve the property value, It may have expressiong */
+            /** If property is Map type, then resolve the property value, It may have expressions */
             if (nodeTypeProperty.type == BluePrintConstants.DATA_TYPE_MAP &&
                 resolvedValue.returnNullIfMissing() != null
             ) {
-                val mapResolvedValue = resolvePropertyAssignments(nodeTemplateName, resolvedValue.rootFieldsToMap())
+                val mapResolvedValue = resolvePropertyAssignments(
+                    definitionType, definitionName, resolvedValue.rootFieldsToMap()
+                )
                 resolvedValue = mapResolvedValue.asJsonNode()
             }
 
@@ -300,29 +396,19 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
         return propertyAssignmentValue
     }
 
-    override fun resolvePropertyDefinitions(name: String, propertyDefinitions: MutableMap<String, PropertyDefinition>):
-        MutableMap<String, JsonNode> {
-        val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
-
-        propertyDefinitions.forEach { propertyName, propertyDefinition ->
-            val propertyAssignmentExpression = PropertyAssignmentService(this)
-            val expression = propertyDefinition.value ?: propertyDefinition.defaultValue
-            if (expression != null) {
-                propertyAssignmentValue[propertyName] =
-                    propertyAssignmentExpression.resolveAssignmentExpression(name, propertyName, expression)
-            }
-        }
-        return propertyAssignmentValue
-    }
-
-    override fun resolvePropertyAssignments(name: String, propertyAssignments: MutableMap<String, JsonNode>):
-        MutableMap<String, JsonNode> {
+    override fun resolvePropertyAssignments(
+        definitionType: String,
+        definitionName: String,
+        propertyAssignments: MutableMap<String, JsonNode>
+    ): MutableMap<String, JsonNode> {
         val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
 
         propertyAssignments.forEach { (propertyName, propertyExpression) ->
             val propertyAssignmentExpression = PropertyAssignmentService(this)
             propertyAssignmentValue[propertyName] =
-                propertyAssignmentExpression.resolveAssignmentExpression(name, propertyName, propertyExpression)
+                propertyAssignmentExpression.resolveAssignmentExpression(
+                    definitionType, definitionName, propertyName, propertyExpression
+                )
         }
         return propertyAssignmentValue
     }
@@ -348,6 +434,20 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
         )
     }
 
+    /**
+     * Resolve any property assignments for the node
+     */
+    override fun resolveNodeTemplatePropertyAssignments(
+        nodeTemplateName: String,
+        propertyDefinitions: MutableMap<String, PropertyDefinition>,
+        propertyAssignments: MutableMap<String, JsonNode>
+    ): MutableMap<String, JsonNode> {
+        return resolvePropertyAssignments(
+            BluePrintConstants.MODEL_DEFINITION_TYPE_NODE_TEMPLATE,
+            nodeTemplateName, propertyDefinitions, propertyAssignments
+        )
+    }
+
     override fun resolveNodeTemplateCapabilityProperties(nodeTemplateName: String, capabilityName: String):
         MutableMap<String, JsonNode> {
         log.info("resolveNodeTemplateCapabilityProperties for node template($nodeTemplateName) capability($capabilityName)")
@@ -432,7 +532,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
         return propertyAssignmentValue
     }
 
-    override fun resolveNodeTemplateArtifact(nodeTemplateName: String, artifactName: String): String {
+    override suspend fun resolveNodeTemplateArtifact(nodeTemplateName: String, artifactName: String): String {
         val artifactDefinition: ArtifactDefinition =
             resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName)
         val propertyAssignmentExpression = PropertyAssignmentService(this)
@@ -464,36 +564,23 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
 
         /**
          * Resolve the RelationshipTemplate Property Assignment Values.
-         * TODO("Now it supports only input, node not SELF(propert, attribute, artifact) expressions, later it will support SELF expressions")
          */
-        return resolveNodeTemplatePropertyAssignments(
-            "DSL",
+        return resolveRelationshipTemplatePropertyAssignments(
+            relationshipTemplateName,
             propertiesDefinitions,
             propertyAssignments
         )
     }
 
-    /**
-     * Read the DSL Property reference, If there is any expression, then resolve those expression and return as Json
-     * Type
-     */
-    override fun resolveDSLExpression(dslPropertyName: String): JsonNode {
-        val propertyAssignments = bluePrintContext.dslPropertiesByName(dslPropertyName)
-        return if (BluePrintExpressionService.checkContainsExpression(propertyAssignments) &&
-            propertyAssignments is ObjectNode
-        ) {
-
-            val rootKeyMap = propertyAssignments.rootFieldsToMap()
-            val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
-            rootKeyMap.forEach { (propertyName, propertyValue) ->
-                val propertyAssignmentExpression = PropertyAssignmentService(this)
-                propertyAssignmentValue[propertyName] = propertyAssignmentExpression
-                    .resolveAssignmentExpression("DSL", propertyName, propertyValue)
-            }
-            propertyAssignmentValue.asJsonNode()
-        } else {
-            propertyAssignments
-        }
+    override fun resolveRelationshipTemplatePropertyAssignments(
+        relationshipTemplateName: String,
+        propertyDefinitions: MutableMap<String, PropertyDefinition>,
+        propertyAssignments: MutableMap<String, JsonNode>
+    ): MutableMap<String, JsonNode> {
+        return resolvePropertyAssignments(
+            BluePrintConstants.MODEL_DEFINITION_TYPE_RELATIONSHIP_TYPE,
+            relationshipTemplateName, propertyDefinitions, propertyAssignments
+        )
     }
 
     override fun setInputValue(propertyName: String, value: JsonNode) {
@@ -628,6 +715,28 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
         return getJsonNode(path)
     }
 
+    override fun getRelationshipTemplatePropertyValue(
+        relationshipTemplateName: String,
+        propertyName: String
+    ): JsonNode? {
+        val path: String = StringBuilder(BluePrintConstants.PATH_RELATIONSHIP_TEMPLATES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(relationshipTemplateName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
+        return getJsonNode(path)
+    }
+
+    override fun getRelationshipTemplateAttributeValue(
+        relationshipTemplateName: String,
+        attributeName: String
+    ): JsonNode? {
+        val path: String = StringBuilder(BluePrintConstants.PATH_RELATIONSHIP_TEMPLATES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(relationshipTemplateName)
+            .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
+            .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString()
+        return getJsonNode(path)
+    }
+
     override fun assignInputs(jsonNode: JsonNode) {
         log.info("assignInputs from input JSON ({})", jsonNode.toString())
         bluePrintContext.inputs()?.forEach { propertyName, property ->
@@ -644,32 +753,26 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
         val dynamicInputPropertiesName = "$workflowName-properties"
 
         bluePrintContext.workflowByName(workflowName).inputs
-                ?.filter { (propertyName, property) -> propertyName != dynamicInputPropertiesName }
-                ?.forEach { propertyName, property -> findAndSetInputValue(propertyName, property, jsonNode) }
+            ?.filter { (propertyName, property) -> propertyName != dynamicInputPropertiesName }
+            ?.forEach { propertyName, property -> findAndSetInputValue(propertyName, property, jsonNode) }
         // Load Dynamic data Types
         jsonNode.get(dynamicInputPropertiesName)?.let {
             bluePrintContext.dataTypeByName("dt-$dynamicInputPropertiesName")
-                    ?.properties
-                    ?.forEach { propertyName, property -> findAndSetInputValue(propertyName, property, it) }
+                ?.properties
+                ?.forEach { propertyName, property -> findAndSetInputValue(propertyName, property, it) }
         }
     }
 
     private fun findAndSetInputValue(propertyName: String, property: PropertyDefinition, jsonNode: JsonNode) {
         val valueNode = jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName)
-                .returnNullIfMissing()
-                ?: property.defaultValue
-                ?: NullNode.getInstance()
+            .returnNullIfMissing()
+            ?: property.defaultValue
+            ?: NullNode.getInstance()
         val loggableValue = if (hasLogProtect(property)) LOG_REDACTED else valueNode.toString()
-        log.info("Setting input data - attribute:($propertyName) value:($loggableValue)")
+        log.trace("Setting input data - attribute:($propertyName) value:($loggableValue)")
         setInputValue(propertyName, valueNode)
     }
 
-    override fun resolveWorkflowOutputs(workflowName: String): MutableMap<String, JsonNode> {
-        log.info("resolveWorkflowOutputs for workflow($workflowName)")
-        val outputs = bluePrintContext.workflowByName(workflowName).outputs ?: mutableMapOf()
-        return resolvePropertyDefinitions("WORKFLOW", outputs)
-    }
-
     override fun getJsonForNodeTemplateAttributeProperties(nodeTemplateName: String, keys: List<String>): JsonNode {
 
         val jsonNode: ObjectNode = jacksonObjectMapper().createObjectNode()
@@ -688,4 +791,8 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
         }
         return jsonNode
     }
+
+    override suspend fun close() {
+        store.clear()
+    }
 }
index 2dc8b5c..4ae01c0 100644 (file)
@@ -24,11 +24,9 @@ import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
 import org.onap.ccsdk.cds.controllerblueprints.core.data.ArtifactDefinition
 import org.onap.ccsdk.cds.controllerblueprints.core.data.ArtifactExpression
-import org.onap.ccsdk.cds.controllerblueprints.core.data.AttributeDefinition
 import org.onap.ccsdk.cds.controllerblueprints.core.data.AttributeExpression
 import org.onap.ccsdk.cds.controllerblueprints.core.data.ExpressionData
 import org.onap.ccsdk.cds.controllerblueprints.core.data.OperationOutputExpression
-import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
 import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyExpression
 import org.onap.ccsdk.cds.controllerblueprints.core.format
 import org.onap.ccsdk.cds.controllerblueprints.core.isComplexType
@@ -42,7 +40,7 @@ import org.slf4j.LoggerFactory
  *
  * @author Brinda Santh
  */
-class PropertyAssignmentService(var bluePrintRuntimeService: BluePrintRuntimeService<MutableMap<String, JsonNode>>) {
+internal class PropertyAssignmentService(var bluePrintRuntimeService: BluePrintRuntimeService<MutableMap<String, JsonNode>>) {
 
     private val log = LoggerFactory.getLogger(this::class.toString())
 
@@ -56,23 +54,27 @@ class PropertyAssignmentService(var bluePrintRuntimeService: BluePrintRuntimeSer
      */
 
     fun resolveAssignmentExpression(
-        nodeTemplateName: String,
+        definitionType: String,
+        definitionName: String,
         assignmentName: String,
         assignment: JsonNode
     ): JsonNode {
-        val valueNode: JsonNode
         log.trace("Assignment ({})", assignment)
         val expressionData = BluePrintExpressionService.getExpressionData(assignment)
 
-        if (expressionData.isExpression) {
-            valueNode = resolveExpression(nodeTemplateName, assignmentName, expressionData)
+        return if (expressionData.isExpression) {
+            resolveExpression(definitionType, definitionName, assignmentName, expressionData)
         } else {
-            valueNode = expressionData.valueNode
+            expressionData.valueNode
         }
-        return valueNode
     }
 
-    fun resolveExpression(nodeTemplateName: String, propName: String, expressionData: ExpressionData): JsonNode {
+    fun resolveExpression(
+        definitionType: String,
+        definitionName: String,
+        propName: String,
+        expressionData: ExpressionData
+    ): JsonNode {
 
         var valueNode: JsonNode = NullNode.getInstance()
 
@@ -84,24 +86,31 @@ class PropertyAssignmentService(var bluePrintRuntimeService: BluePrintRuntimeSer
                     valueNode = bluePrintRuntimeService.getInputValue(expressionData.inputExpression?.propertyName!!)
                 }
                 BluePrintConstants.EXPRESSION_GET_ATTRIBUTE -> {
-                    valueNode = resolveAttributeExpression(nodeTemplateName, expressionData.attributeExpression!!)
+                    valueNode =
+                        resolveAttributeExpression(definitionType, definitionName, expressionData.attributeExpression!!)
                 }
                 BluePrintConstants.EXPRESSION_GET_PROPERTY -> {
-                    valueNode = resolvePropertyExpression(nodeTemplateName, expressionData.propertyExpression!!)
+                    valueNode =
+                        resolvePropertyExpression(definitionType, definitionName, expressionData.propertyExpression!!)
                 }
                 BluePrintConstants.EXPRESSION_GET_OPERATION_OUTPUT -> {
-                    valueNode = resolveOperationOutputExpression(nodeTemplateName, expressionData.operationOutputExpression!!)
+                    valueNode =
+                        resolveOperationOutputExpression(definitionName, expressionData.operationOutputExpression!!)
                 }
                 BluePrintConstants.EXPRESSION_GET_ARTIFACT -> {
-                    valueNode = resolveArtifactExpression(nodeTemplateName, expressionData.artifactExpression!!)
+                    valueNode = resolveArtifactExpression(definitionName, expressionData.artifactExpression!!)
                 }
                 BluePrintConstants.EXPRESSION_DSL_REFERENCE -> {
-                    valueNode = bluePrintRuntimeService.resolveDSLExpression(expressionData.dslExpression!!.propertyName)
+                    valueNode =
+                        bluePrintRuntimeService.resolveDSLExpression(expressionData.dslExpression!!.propertyName)
                 }
                 BluePrintConstants.EXPRESSION_GET_NODE_OF_TYPE -> {
                 }
                 else -> {
-                    throw BluePrintException(format("for property ({}), command ({}) is not supported ", propName, command))
+                    throw BluePrintException(
+                        "for $definitionType($definitionName) property ($propName), " +
+                            "command ($command) is not supported "
+                    )
                 }
             }
         }
@@ -112,13 +121,17 @@ class PropertyAssignmentService(var bluePrintRuntimeService: BluePrintRuntimeSer
     get_attribute: [ <modelable_entity_name>, <optional_req_or_cap_name>, <property_name>,
     <nested_property_name_or_index_1>, ..., <nested_property_name_or_index_n> ]
  */
-    fun resolveAttributeExpression(nodeTemplateName: String, attributeExpression: AttributeExpression): JsonNode {
+    fun resolveAttributeExpression(
+        definitionType: String,
+        definitionName: String,
+        attributeExpression: AttributeExpression
+    ): JsonNode {
         var valueNode: JsonNode
 
         val attributeName = attributeExpression.attributeName
         val subAttributeName: String? = attributeExpression.subAttributeName
 
-        var attributeNodeTemplateName = nodeTemplateName
+        var attributeDefinitionName = definitionName
         /**
          * Attributes are dynamic runtime properties information. There are multiple types of Attributes,
          * ENV : Environment Variables
@@ -128,27 +141,52 @@ class PropertyAssignmentService(var bluePrintRuntimeService: BluePrintRuntimeSer
          */
         when (attributeExpression.modelableEntityName) {
             BluePrintConstants.PROPERTY_ENV -> {
-                val environmentValue = System.getProperty(attributeName)
+                val environmentValue = System.getenv(attributeName)
                 valueNode = environmentValue.asJsonPrimitive()
             }
             BluePrintConstants.PROPERTY_APP -> {
-                TODO("Get property from application properties")
+                val environmentValue = System.getProperty(attributeName)
+                valueNode = environmentValue.asJsonPrimitive()
             }
             BluePrintConstants.PROPERTY_BPP -> {
-                valueNode = bluePrintRuntimeService.getNodeTemplateAttributeValue(BluePrintConstants.PROPERTY_BPP, attributeName)
-                    ?: throw BluePrintException("failed to get env attribute name ($attributeName) ")
+                valueNode = bluePrintRuntimeService.getNodeTemplateAttributeValue(
+                    BluePrintConstants.PROPERTY_BPP,
+                    attributeName
+                ) ?: throw BluePrintException("failed to get env attribute name ($attributeName) ")
             }
             else -> {
                 if (!attributeExpression.modelableEntityName.equals(BluePrintConstants.PROPERTY_SELF, true)) {
-                    attributeNodeTemplateName = attributeExpression.modelableEntityName
+                    attributeDefinitionName = attributeExpression.modelableEntityName
                 }
 
-                var attributeDefinition: AttributeDefinition = bluePrintContext
-                    .nodeTemplateNodeType(attributeNodeTemplateName).attributes?.get(attributeName)
-                    ?: throw BluePrintException("failed to get attribute definitions for node template ($attributeNodeTemplateName)'s attribute name ($attributeName) ")
-
-                valueNode = bluePrintRuntimeService.getNodeTemplateAttributeValue(attributeNodeTemplateName, attributeName)
-                    ?: throw BluePrintException("failed to get node template ($attributeNodeTemplateName)'s attribute name ($attributeName) ")
+                /** This block is to Validate, if Attribute definition is present */
+                when (definitionType) {
+                    BluePrintConstants.MODEL_DEFINITION_TYPE_NODE_TEMPLATE,
+                    BluePrintConstants.MODEL_DEFINITION_TYPE_WORKFLOW,
+                    BluePrintConstants.MODEL_DEFINITION_TYPE_DSL ->
+                        bluePrintContext.nodeTemplateNodeType(attributeDefinitionName).attributes
+                    BluePrintConstants.MODEL_DEFINITION_TYPE_RELATIONSHIP_TEMPLATE ->
+                        bluePrintContext.relationshipTemplateRelationshipType(attributeDefinitionName).attributes
+                    else -> throw BluePrintException("failed to understand template type($definitionType), it is not supported")
+                }?.get(attributeName)
+                    ?: throw BluePrintException(
+                        "failed to get attribute definitions for " +
+                            "$definitionType ($attributeDefinitionName)'s attribute name ($attributeName) "
+                    )
+
+                valueNode = when (definitionType) {
+                    BluePrintConstants.MODEL_DEFINITION_TYPE_NODE_TEMPLATE,
+                    BluePrintConstants.MODEL_DEFINITION_TYPE_WORKFLOW,
+                    BluePrintConstants.MODEL_DEFINITION_TYPE_DSL ->
+                        bluePrintRuntimeService.getNodeTemplateAttributeValue(attributeDefinitionName, attributeName)
+                    BluePrintConstants.MODEL_DEFINITION_TYPE_RELATIONSHIP_TEMPLATE ->
+                        bluePrintRuntimeService.getRelationshipTemplateAttributeValue(
+                            attributeDefinitionName,
+                            attributeName
+                        )
+                    else -> throw BluePrintException("failed to understand template type($definitionType), it is not supported")
+                }
+                    ?: throw BluePrintException("failed to get node template ($attributeDefinitionName)'s attribute name ($attributeName) ")
             }
         }
         if (subAttributeName != null) {
@@ -162,38 +200,56 @@ class PropertyAssignmentService(var bluePrintRuntimeService: BluePrintRuntimeSer
         get_property: [ <modelable_entity_name>, <optional_req_or_cap_name>, <property_name>,
         <nested_property_name_or_index_1>, ..., <nested_property_name_or_index_n> ]
      */
-    fun resolvePropertyExpression(nodeTemplateName: String, propertyExpression: PropertyExpression): JsonNode {
+    fun resolvePropertyExpression(
+        definitionType: String,
+        definitionName: String,
+        propertyExpression: PropertyExpression
+    ): JsonNode {
         var valueNode: JsonNode
 
         val propertyName = propertyExpression.propertyName
         val subPropertyName: String? = propertyExpression.subPropertyName
 
-        var propertyNodeTemplateName = nodeTemplateName
+        var propertyDefinitionName = definitionName
 
         if (!propertyExpression.modelableEntityName.equals(BluePrintConstants.PROPERTY_SELF, true)) {
-            propertyNodeTemplateName = propertyExpression.modelableEntityName
+            propertyDefinitionName = propertyExpression.modelableEntityName
         }
 
-        val nodeTemplatePropertyExpression = bluePrintContext.nodeTemplateByName(propertyNodeTemplateName).properties?.get(propertyName)
-            ?: throw BluePrintException(
-                format(
-                    "failed to get property definitions for node template ({})'s property name ({}) ",
-                    nodeTemplateName,
-                    propertyName
-                )
-            )
-
-        var propertyDefinition: PropertyDefinition = bluePrintContext.nodeTemplateNodeType(propertyNodeTemplateName).properties?.get(propertyName)!!
+        val nodeTemplatePropertyExpression = when (definitionType) {
+            BluePrintConstants.MODEL_DEFINITION_TYPE_NODE_TEMPLATE,
+            BluePrintConstants.MODEL_DEFINITION_TYPE_WORKFLOW,
+            BluePrintConstants.MODEL_DEFINITION_TYPE_DSL ->
+                bluePrintContext.nodeTemplateByName(propertyDefinitionName).properties
+            BluePrintConstants.MODEL_DEFINITION_TYPE_RELATIONSHIP_TEMPLATE ->
+                bluePrintContext.relationshipTemplateByName(propertyDefinitionName).properties
+            else -> throw BluePrintException("failed to understand template type($definitionType), it is not supported")
+        }?.get(propertyName)
+            ?: throw BluePrintException("failed to get property assignment for node template ($definitionName)'s property name ($propertyName).")
+
+        /** This block is to Validate, if Property definition is present */
+        when (definitionType) {
+            BluePrintConstants.MODEL_DEFINITION_TYPE_NODE_TEMPLATE,
+            BluePrintConstants.MODEL_DEFINITION_TYPE_WORKFLOW,
+            BluePrintConstants.MODEL_DEFINITION_TYPE_DSL ->
+                bluePrintContext.nodeTemplateNodeType(propertyDefinitionName).properties
+            BluePrintConstants.MODEL_DEFINITION_TYPE_RELATIONSHIP_TEMPLATE ->
+                bluePrintContext.relationshipTemplateRelationshipType(propertyDefinitionName).properties
+            else -> throw BluePrintException("failed to understand template type($definitionType), it is not supported")
+        }?.get(propertyName)
+            ?: throw BluePrintException("failed to get property definition for node template ($definitionName)'s property name ($propertyName).")
 
         log.info(
-            "node template name ({}), property Name ({}) resolved value ({})",
-            propertyNodeTemplateName,
-            propertyName,
-            nodeTemplatePropertyExpression
+            "$definitionType($propertyDefinitionName), property($propertyName) resolved value ($nodeTemplatePropertyExpression)"
         )
 
         // Check it it is a nested expression
-        valueNode = resolveAssignmentExpression(propertyNodeTemplateName, propertyName, nodeTemplatePropertyExpression)
+        valueNode = resolveAssignmentExpression(
+            definitionType,
+            propertyDefinitionName,
+            propertyName,
+            nodeTemplatePropertyExpression
+        )
 
         if (subPropertyName != null) {
             if (valueNode.isComplexType())
@@ -205,7 +261,10 @@ class PropertyAssignmentService(var bluePrintRuntimeService: BluePrintRuntimeSer
     /*
     get_operation_output: <modelable_entity_name>, <interface_name>, <operation_name>, <output_variable_name>
      */
-    fun resolveOperationOutputExpression(nodeTemplateName: String, operationOutputExpression: OperationOutputExpression): JsonNode {
+    fun resolveOperationOutputExpression(
+        nodeTemplateName: String,
+        operationOutputExpression: OperationOutputExpression
+    ): JsonNode {
         var outputNodeTemplateName = nodeTemplateName
         if (!operationOutputExpression.modelableEntityName.equals("SELF", true)) {
             outputNodeTemplateName = operationOutputExpression.modelableEntityName
@@ -239,7 +298,7 @@ class PropertyAssignmentService(var bluePrintRuntimeService: BluePrintRuntimeSer
             ?: throw BluePrintException(
                 format(
                     "failed to get artifact definitions for node template ({})'s " +
-                            "artifact name ({}) ", nodeTemplateName, artifactExpression.artifactName
+                        "artifact name ({}) ", nodeTemplateName, artifactExpression.artifactName
                 )
             )
 
index a74722f..9903b57 100644 (file)
@@ -36,7 +36,11 @@ object ServiceTemplateUtils {
         return JacksonUtils.readValue(content)
     }
 
-    fun merge(parentServiceTemplate: ServiceTemplate, toMerge: ServiceTemplate, removeImports: Boolean? = true): ServiceTemplate {
+    fun merge(
+        parentServiceTemplate: ServiceTemplate,
+        toMerge: ServiceTemplate,
+        removeImports: Boolean? = true
+    ): ServiceTemplate {
         if (removeImports!!) {
             parentServiceTemplate.imports = null
             toMerge.imports = null
@@ -62,6 +66,11 @@ object ServiceTemplateUtils {
             parentServiceTemplate.nodeTypes?.putAll(toMerge.nodeTypes as MutableMap)
         }
 
+        toMerge.relationshipTypes?.let {
+            parentServiceTemplate.relationshipTypes = parentServiceTemplate.relationshipTypes ?: hashMapOf()
+            parentServiceTemplate.relationshipTypes?.putAll(toMerge.relationshipTypes as MutableMap)
+        }
+
         toMerge.artifactTypes?.let {
             parentServiceTemplate.artifactTypes = parentServiceTemplate.artifactTypes ?: hashMapOf()
             parentServiceTemplate.artifactTypes?.putAll(toMerge.artifactTypes as MutableMap)
@@ -81,14 +90,16 @@ object ServiceTemplateUtils {
         }
 
         toMerge.topologyTemplate?.nodeTemplates?.let {
-            parentServiceTemplate.topologyTemplate?.nodeTemplates = parentServiceTemplate.topologyTemplate?.nodeTemplates
-                ?: hashMapOf()
+            parentServiceTemplate.topologyTemplate?.nodeTemplates =
+                parentServiceTemplate.topologyTemplate?.nodeTemplates
+                    ?: hashMapOf()
             parentServiceTemplate.topologyTemplate?.nodeTemplates?.putAll(parentServiceTemplate.topologyTemplate?.nodeTemplates as MutableMap)
         }
 
         toMerge.topologyTemplate?.relationshipTemplates?.let {
-            parentServiceTemplate.topologyTemplate?.relationshipTemplates = parentServiceTemplate.topologyTemplate?.relationshipTemplates
-                ?: hashMapOf()
+            parentServiceTemplate.topologyTemplate?.relationshipTemplates =
+                parentServiceTemplate.topologyTemplate?.relationshipTemplates
+                    ?: hashMapOf()
             parentServiceTemplate.topologyTemplate?.relationshipTemplates?.putAll(parentServiceTemplate.topologyTemplate?.relationshipTemplates as MutableMap)
         }
 
index b079d42..871f8af 100644 (file)
@@ -57,6 +57,28 @@ class BluePrintRuntimeServiceTest {
         assertNotNull(propContext, "Failed to populate interface property values")
     }
 
+    @Test
+    fun `test Resolve Relationship Properties`() {
+        log.info("************************ testResolveRelationshipTemplateProperties **********************")
+
+        val bluePrintRuntimeService = getBluePrintRuntimeService()
+
+        val inputDataPath = "src/test/resources/data/default-context.json"
+
+        val inputNode: JsonNode = JacksonUtils.jsonNodeFromFile(inputDataPath)
+        bluePrintRuntimeService.assignInputs(inputNode)
+
+        val propContext: MutableMap<String, JsonNode> = bluePrintRuntimeService
+            .resolveRelationshipTemplateProperties("cli-device-properties")
+
+        assertNotNull(propContext, "Failed to populate relationship property values")
+        assertEquals(
+            "localhost".asJsonPrimitive(),
+            propContext["connection-config"]!!.get("host"),
+            "failed to resolve expression"
+        )
+    }
+
     @Test
     fun `test resolve NodeTemplate Capability Properties`() {
         log.info("************************ testResolveNodeTemplateRequirementProperties **********************")
index a746aba..4ed98dd 100644 (file)
@@ -34,8 +34,9 @@ open class ResourceDefinition {
 
     var tags: String? = null
 
-    @JsonProperty(value = "group")
-    lateinit var group: String
+    /** The default group for Resource Definition is "default" */
+    @JsonProperty(value = "group", required = true)
+    var group: String = "default"
 
     @JsonProperty(value = "updated-by")
     lateinit var updatedBy: String
index d4d8048..f78334f 100644 (file)
@@ -17,6 +17,7 @@
 package org.onap.ccsdk.cds.blueprintsprocessor.db
 
 open class DBDataSourceProperties {
+    var type: String = DBLibConstants.MARIA_DB
     lateinit var url: String
     lateinit var username: String
     lateinit var password: String
@@ -34,7 +35,6 @@ open class MariaDataSourceProperties : DBDataSourceProperties() {
     lateinit var hibernateHbm2ddlAuto: String
     lateinit var hibernateDDLAuto: String
     lateinit var hibernateNamingStrategy: String
-    lateinit var type: String
     lateinit var hibernateDialect: String
     override var driverClassName = DBLibConstants.DRIVER_MARIA_DB
 }
@@ -43,7 +43,6 @@ open class MySqlDataSourceProperties : DBDataSourceProperties() {
     lateinit var hibernateHbm2ddlAuto: String
     lateinit var hibernateDDLAuto: String
     lateinit var hibernateNamingStrategy: String
-    lateinit var type: String
     lateinit var hibernateDialect: String
     override var driverClassName = DBLibConstants.DRIVER_MYSQL_DB
 }
index 036beb3..2bf56f4 100644 (file)
  */
 
 package org.onap.ccsdk.cds.blueprintsprocessor.db
+
+import com.fasterxml.jackson.databind.JsonNode
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
+import org.onap.ccsdk.cds.controllerblueprints.core.data.RelationshipType
+import org.onap.ccsdk.cds.controllerblueprints.core.dsl.PropertiesAssignmentBuilder
+import org.onap.ccsdk.cds.controllerblueprints.core.dsl.RelationshipTemplateBuilder
+import org.onap.ccsdk.cds.controllerblueprints.core.dsl.TopologyTemplateBuilder
+import org.onap.ccsdk.cds.controllerblueprints.core.dsl.relationshipType
+
+/** Relationships Types DSL for Database Producer */
+fun BluePrintTypes.relationshipTypeConnectsToDb(): RelationshipType {
+    return relationshipType(
+        id = BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO_DB,
+        version = BluePrintConstants.DEFAULT_VERSION_NUMBER,
+        derivedFrom = BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO,
+        description = "Relationship connects to through Database."
+    ) {
+        property(
+            BluePrintConstants.PROPERTY_CONNECTION_CONFIG,
+            BluePrintConstants.DATA_TYPE_MAP,
+            true,
+            "Connection Config details."
+        )
+        validTargetTypes(arrayListOf(BluePrintConstants.MODEL_TYPE_CAPABILITY_TYPE_ENDPOINT))
+    }
+}
+
+/** Relationships Templates for Database Server */
+fun TopologyTemplateBuilder.relationshipTemplateDb(
+    name: String,
+    description: String,
+    block: DbRelationshipTemplateBuilder.() -> Unit
+) {
+    if (relationshipTemplates == null) relationshipTemplates = hashMapOf()
+    val relationshipTemplate = DbRelationshipTemplateBuilder(name, description).apply(block).build()
+    relationshipTemplates!![relationshipTemplate.id!!] = relationshipTemplate
+}
+
+class DbRelationshipTemplateBuilder(name: String, description: String) :
+    RelationshipTemplateBuilder(
+        name,
+        BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO_DB, description
+    ) {
+
+    fun mariaDb(block: DbMariaDataSourcePropertiesAssignmentBuilder.() -> Unit) {
+        property(BluePrintConstants.PROPERTY_CONNECTION_CONFIG, BluePrintTypes.mariaDbProperties(block))
+    }
+
+    fun mySqlDb(block: DbMySqlDataSourcePropertiesAssignmentBuilder.() -> Unit) {
+        property(BluePrintConstants.PROPERTY_CONNECTION_CONFIG, BluePrintTypes.mySqlDbProperties(block))
+    }
+}
+
+fun BluePrintTypes.mariaDbProperties(block: DbMariaDataSourcePropertiesAssignmentBuilder.() -> Unit): JsonNode {
+    val assignments = DbMariaDataSourcePropertiesAssignmentBuilder().apply(block).build()
+    assignments[DBDataSourceProperties::type.name] = DBLibConstants.MARIA_DB.asJsonPrimitive()
+    return assignments.asJsonNode()
+}
+
+fun BluePrintTypes.mySqlDbProperties(block: DbMySqlDataSourcePropertiesAssignmentBuilder.() -> Unit): JsonNode {
+    val assignments = DbMySqlDataSourcePropertiesAssignmentBuilder().apply(block).build()
+    assignments[DBDataSourceProperties::type.name] = DBLibConstants.MYSQL_DB.asJsonPrimitive()
+    return assignments.asJsonNode()
+}
+
+open class DbPropertiesAssignmentBuilder : PropertiesAssignmentBuilder() {
+
+    fun url(url: String) = url(url.asJsonPrimitive())
+
+    fun url(url: JsonNode) =
+        property(DBDataSourceProperties::url, url)
+
+    fun username(username: String) = username(username.asJsonPrimitive())
+
+    fun username(username: JsonNode) = property(DBDataSourceProperties::username, username)
+
+    fun password(password: String) = password(password.asJsonPrimitive())
+
+    fun password(password: JsonNode) = property(DBDataSourceProperties::password, password)
+}
+
+open class DbMariaDataSourcePropertiesAssignmentBuilder : DbPropertiesAssignmentBuilder() {
+
+    fun hibernateHbm2ddlAuto(hibernateHbm2ddlAuto: String) =
+        hibernateHbm2ddlAuto(hibernateHbm2ddlAuto.asJsonPrimitive())
+
+    fun hibernateHbm2ddlAuto(hibernateHbm2ddlAuto: JsonNode) =
+        property(MariaDataSourceProperties::hibernateHbm2ddlAuto, hibernateHbm2ddlAuto)
+
+    fun hibernateDDLAuto(hibernateDDLAuto: String) =
+        hibernateDDLAuto(hibernateDDLAuto.asJsonPrimitive())
+
+    fun hibernateDDLAuto(hibernateDDLAuto: JsonNode) =
+        property(MariaDataSourceProperties::hibernateDDLAuto, hibernateDDLAuto)
+
+    fun hibernateNamingStrategy(hibernateNamingStrategy: String) =
+        hibernateNamingStrategy(hibernateNamingStrategy.asJsonPrimitive())
+
+    fun hibernateNamingStrategy(hibernateNamingStrategy: JsonNode) =
+        property(MariaDataSourceProperties::hibernateNamingStrategy, hibernateNamingStrategy)
+}
+
+open class DbMySqlDataSourcePropertiesAssignmentBuilder : DbMariaDataSourcePropertiesAssignmentBuilder()
diff --git a/ms/blueprintsprocessor/modules/commons/db-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/DatabasePropertiesDSLTest.kt b/ms/blueprintsprocessor/modules/commons/db-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/DatabasePropertiesDSLTest.kt
new file mode 100644 (file)
index 0000000..b0c7d8b
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2018-2019 AT&T Intellectual Property.
+ *
+ * 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.db
+
+import org.junit.Test
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
+import org.onap.ccsdk.cds.controllerblueprints.core.dsl.relationshipTypeConnectsTo
+import org.onap.ccsdk.cds.controllerblueprints.core.dsl.serviceTemplate
+import kotlin.test.assertEquals
+import kotlin.test.assertNotNull
+
+class DatabasePropertiesDSLTest {
+
+    @Test
+    fun testDatabasePropertiesDSL() {
+        val serviceTemplate = serviceTemplate("database-properties-test", "1.0.0", "xxx.@xx.com", "database") {
+            topologyTemplate {
+                relationshipTemplateDb("sample-maria-db", "Database Server") {
+                    mariaDb {
+                        url("jdbc://mariadb:3600")
+                        username("user")
+                        password("credential")
+                        hibernateDDLAuto("hibernateDDLAuto")
+                        hibernateHbm2ddlAuto("hibernateHbm2ddlAuto")
+                        hibernateDDLAuto("hibernateDDLAuto")
+                        hibernateNamingStrategy("hibernateNamingStrategy")
+                    }
+                }
+                relationshipTemplateDb("sample-mysql-db", "Database Server") {
+                    mySqlDb {
+                        url("jdbc://mysql:3600")
+                        username("user")
+                        password("credential")
+                        hibernateDDLAuto("hibernateDDLAuto")
+                        hibernateHbm2ddlAuto("hibernateHbm2ddlAuto")
+                        hibernateDDLAuto("hibernateDDLAuto")
+                        hibernateNamingStrategy("hibernateNamingStrategy")
+                    }
+                }
+            }
+            relationshipTypes(
+                arrayListOf(
+                    BluePrintTypes.relationshipTypeConnectsToDb(),
+                    BluePrintTypes.relationshipTypeConnectsTo()
+                )
+            )
+        }
+        assertNotNull(serviceTemplate, "failed to create service template")
+        val relationshipTemplates = serviceTemplate.topologyTemplate?.relationshipTemplates
+        assertNotNull(relationshipTemplates, "failed to get relationship templates")
+        assertEquals(2, relationshipTemplates.size, "relationshipTemplates doesn't match")
+        assertNotNull(relationshipTemplates["sample-maria-db"], "failed to get sample-maria-db")
+        assertNotNull(relationshipTemplates["sample-mysql-db"], "failed to get sample-mysql-db")
+        // println(serviceTemplate.asJsonString(true))
+    }
+}
index 3a0e9c6..354e38d 100644 (file)
  */
 
 package org.onap.ccsdk.cds.blueprintsprocessor.grpc
+
+import com.fasterxml.jackson.databind.JsonNode
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
+import org.onap.ccsdk.cds.controllerblueprints.core.data.RelationshipType
+import org.onap.ccsdk.cds.controllerblueprints.core.dsl.PropertiesAssignmentBuilder
+import org.onap.ccsdk.cds.controllerblueprints.core.dsl.RelationshipTemplateBuilder
+import org.onap.ccsdk.cds.controllerblueprints.core.dsl.TopologyTemplateBuilder
+import org.onap.ccsdk.cds.controllerblueprints.core.dsl.relationshipType
+
+/** Relationships Types DSL for GRPC Server Producer */
+fun BluePrintTypes.relationshipTypeConnectsToGrpcServer(): RelationshipType {
+    return relationshipType(
+        id = BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO_GRPC_SERVER,
+        version = BluePrintConstants.DEFAULT_VERSION_NUMBER,
+        derivedFrom = BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO,
+        description = "Relationship connects to through GRPC Server."
+    ) {
+        property(
+            BluePrintConstants.PROPERTY_CONNECTION_CONFIG,
+            BluePrintConstants.DATA_TYPE_MAP,
+            true,
+            "Connection Config details."
+        )
+        validTargetTypes(arrayListOf(BluePrintConstants.MODEL_TYPE_CAPABILITY_TYPE_ENDPOINT))
+    }
+}
+
+fun BluePrintTypes.relationshipTypeConnectsToGrpcClient(): RelationshipType {
+    return relationshipType(
+        id = BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO_GRPC_CLIENT,
+        version = BluePrintConstants.DEFAULT_VERSION_NUMBER,
+        derivedFrom = BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO,
+        description = "Relationship connects to through GRPC Client."
+    ) {
+        property(
+            BluePrintConstants.PROPERTY_CONNECTION_CONFIG,
+            BluePrintConstants.DATA_TYPE_MAP,
+            true,
+            "Connection Config details."
+        )
+        validTargetTypes(arrayListOf(BluePrintConstants.MODEL_TYPE_CAPABILITY_TYPE_ENDPOINT))
+    }
+}
+
+/** Relationships Templates for GRPC Server */
+fun TopologyTemplateBuilder.relationshipTemplateGrpcServer(
+    name: String,
+    description: String,
+    block: GrpcServerRelationshipTemplateBuilder.() -> Unit
+) {
+    if (relationshipTemplates == null) relationshipTemplates = hashMapOf()
+    val relationshipTemplate = GrpcServerRelationshipTemplateBuilder(name, description).apply(block).build()
+    relationshipTemplates!![relationshipTemplate.id!!] = relationshipTemplate
+}
+
+class GrpcServerRelationshipTemplateBuilder(name: String, description: String) :
+    RelationshipTemplateBuilder(
+        name,
+        BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO_GRPC_SERVER, description
+    ) {
+
+    fun tokenAuth(block: GrpcServerTokenAuthPropertiesAssignmentBuilder.() -> Unit) {
+        property(BluePrintConstants.PROPERTY_CONNECTION_CONFIG, BluePrintTypes.tokenAuthGrpcServerProperties(block))
+    }
+
+    fun tlsAuth(block: GrpcServerTLSAuthPropertiesAssignmentBuilder.() -> Unit) {
+        property(BluePrintConstants.PROPERTY_CONNECTION_CONFIG, BluePrintTypes.tlsAuthGrpcServerProperties(block))
+    }
+}
+
+fun BluePrintTypes.tokenAuthGrpcServerProperties(block: GrpcServerTokenAuthPropertiesAssignmentBuilder.() -> Unit): JsonNode {
+    val assignments = GrpcServerTokenAuthPropertiesAssignmentBuilder().apply(block).build()
+    assignments[GrpcServerProperties::type.name] = GRPCLibConstants.TYPE_TOKEN_AUTH.asJsonPrimitive()
+    return assignments.asJsonNode()
+}
+
+fun BluePrintTypes.tlsAuthGrpcServerProperties(block: GrpcServerTLSAuthPropertiesAssignmentBuilder.() -> Unit): JsonNode {
+    val assignments = GrpcServerTLSAuthPropertiesAssignmentBuilder().apply(block).build()
+    assignments[GrpcServerProperties::type.name] = GRPCLibConstants.TYPE_TLS_AUTH.asJsonPrimitive()
+    return assignments.asJsonNode()
+}
+
+open class GrpcServerPropertiesAssignmentBuilder : PropertiesAssignmentBuilder() {
+
+    fun port(port: Int) = port(port.asJsonPrimitive())
+
+    fun port(port: JsonNode) =
+        property(GrpcServerProperties::port, port)
+}
+
+open class GrpcServerTokenAuthPropertiesAssignmentBuilder : GrpcServerPropertiesAssignmentBuilder() {
+
+    fun token(selector: String) = token(selector.asJsonPrimitive())
+
+    fun token(selector: JsonNode) = property(TokenAuthGrpcServerProperties::token, selector)
+}
+
+open class GrpcServerTLSAuthPropertiesAssignmentBuilder : GrpcServerPropertiesAssignmentBuilder() {
+
+    fun certChain(certChain: String) = certChain(certChain.asJsonPrimitive())
+
+    fun certChain(certChain: JsonNode) = property(TLSAuthGrpcServerProperties::certChain, certChain)
+
+    fun privateKey(privateKey: String) = privateKey(privateKey.asJsonPrimitive())
+
+    fun privateKey(privateKey: JsonNode) = property(TLSAuthGrpcServerProperties::privateKey, privateKey)
+
+    fun trustCertCollection(trustCertCollection: String) = trustCertCollection(trustCertCollection.asJsonPrimitive())
+
+    fun trustCertCollection(trustCertCollection: JsonNode) =
+        property(TLSAuthGrpcServerProperties::trustCertCollection, trustCertCollection)
+}
+
+/** Relationships Templates for GRPC Client */
+fun TopologyTemplateBuilder.relationshipTemplateGrpcClient(
+    name: String,
+    description: String,
+    block: GrpcClientRelationshipTemplateBuilder.() -> Unit
+) {
+    if (relationshipTemplates == null) relationshipTemplates = hashMapOf()
+    val relationshipTemplate = GrpcClientRelationshipTemplateBuilder(name, description).apply(block).build()
+    relationshipTemplates!![relationshipTemplate.id!!] = relationshipTemplate
+}
+
+class GrpcClientRelationshipTemplateBuilder(name: String, description: String) :
+    RelationshipTemplateBuilder(
+        name,
+        BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO_GRPC_CLIENT, description
+    ) {
+
+    fun basicAuth(block: GrpcClientBasicAuthPropertiesAssignmentBuilder.() -> Unit) {
+        property(BluePrintConstants.PROPERTY_CONNECTION_CONFIG, BluePrintTypes.basicAuthGrpcClientProperties(block))
+    }
+
+    fun tokenAuth(block: GrpcClientTokenAuthPropertiesAssignmentBuilder.() -> Unit) {
+        property(BluePrintConstants.PROPERTY_CONNECTION_CONFIG, BluePrintTypes.tokenAuthGrpcClientProperties(block))
+    }
+
+    fun tlsAuth(block: GrpcClientTLSAuthPropertiesAssignmentBuilder.() -> Unit) {
+        property(BluePrintConstants.PROPERTY_CONNECTION_CONFIG, BluePrintTypes.tlsAuthGrpcClientProperties(block))
+    }
+}
+
+fun BluePrintTypes.basicAuthGrpcClientProperties(block: GrpcClientBasicAuthPropertiesAssignmentBuilder.() -> Unit): JsonNode {
+    val assignments = GrpcClientBasicAuthPropertiesAssignmentBuilder().apply(block).build()
+    assignments[GrpcClientProperties::type.name] = GRPCLibConstants.TYPE_BASIC_AUTH.asJsonPrimitive()
+    return assignments.asJsonNode()
+}
+
+fun BluePrintTypes.tokenAuthGrpcClientProperties(block: GrpcClientTokenAuthPropertiesAssignmentBuilder.() -> Unit): JsonNode {
+    val assignments = GrpcClientTokenAuthPropertiesAssignmentBuilder().apply(block).build()
+    assignments[GrpcClientProperties::type.name] = GRPCLibConstants.TYPE_TOKEN_AUTH.asJsonPrimitive()
+    return assignments.asJsonNode()
+}
+
+fun BluePrintTypes.tlsAuthGrpcClientProperties(block: GrpcClientTLSAuthPropertiesAssignmentBuilder.() -> Unit): JsonNode {
+    val assignments = GrpcClientTLSAuthPropertiesAssignmentBuilder().apply(block).build()
+    assignments[GrpcClientProperties::type.name] = GRPCLibConstants.TYPE_TLS_AUTH.asJsonPrimitive()
+    return assignments.asJsonNode()
+}
+
+open class GrpcClientPropertiesAssignmentBuilder : PropertiesAssignmentBuilder() {
+
+    fun host(host: String) = host(host.asJsonPrimitive())
+
+    fun host(host: JsonNode) =
+        property(GrpcClientProperties::host, host)
+
+    fun port(port: Int) = port(port.asJsonPrimitive())
+
+    fun port(port: JsonNode) =
+        property(GrpcClientProperties::port, port)
+}
+
+open class GrpcClientBasicAuthPropertiesAssignmentBuilder : GrpcClientPropertiesAssignmentBuilder() {
+
+    fun username(username: String) = username(username.asJsonPrimitive())
+
+    fun username(username: JsonNode) = property(BasicAuthGrpcClientProperties::username, username)
+
+    fun password(password: String) = password(password.asJsonPrimitive())
+
+    fun password(password: JsonNode) = property(BasicAuthGrpcClientProperties::password, password)
+}
+
+open class GrpcClientTokenAuthPropertiesAssignmentBuilder : GrpcClientPropertiesAssignmentBuilder() {
+
+    fun token(selector: String) = token(selector.asJsonPrimitive())
+
+    fun token(selector: JsonNode) = property(TokenAuthGrpcClientProperties::token, selector)
+}
+
+open class GrpcClientTLSAuthPropertiesAssignmentBuilder : GrpcClientPropertiesAssignmentBuilder() {
+
+    fun trustCertCollection(trustCertCollection: String) = trustCertCollection(trustCertCollection.asJsonPrimitive())
+
+    fun trustCertCollection(trustCertCollection: JsonNode) =
+        property(TLSAuthGrpcClientProperties::trustCertCollection, trustCertCollection)
+
+    fun clientCertChain(clientCertChain: String) = clientCertChain(clientCertChain.asJsonPrimitive())
+
+    fun clientCertChain(clientCertChain: JsonNode) =
+        property(TLSAuthGrpcClientProperties::clientCertChain, clientCertChain)
+
+    fun clientPrivateKey(clientPrivateKey: String) = clientPrivateKey(clientPrivateKey.asJsonPrimitive())
+
+    fun clientPrivateKey(clientPrivateKey: JsonNode) =
+        property(TLSAuthGrpcClientProperties::clientPrivateKey, clientPrivateKey)
+}
diff --git a/ms/blueprintsprocessor/modules/commons/grpc-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/grpc/GrpcPropertiesDSLTest.kt b/ms/blueprintsprocessor/modules/commons/grpc-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/grpc/GrpcPropertiesDSLTest.kt
new file mode 100644 (file)
index 0000000..9b3cf80
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright © 2018-2019 AT&T Intellectual Property.
+ *
+ * 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.grpc
+
+import org.junit.Test
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
+import org.onap.ccsdk.cds.controllerblueprints.core.dsl.relationshipTypeConnectsTo
+import org.onap.ccsdk.cds.controllerblueprints.core.dsl.serviceTemplate
+import kotlin.test.assertEquals
+import kotlin.test.assertNotNull
+
+class GrpcPropertiesDSLTest {
+
+    @Test
+    fun testGrpcServerPropertiesDSL() {
+        val serviceTemplate = serviceTemplate("grpc-properties-test", "1.0.0", "xxx.@xx.com", "grpc") {
+            topologyTemplate {
+                relationshipTemplateGrpcServer("sample-tls-auth", "Grpc Server") {
+                    tlsAuth {
+                        port(40002)
+                        certChain("sample-cert-chains")
+                        privateKey("sample-private-key")
+                        trustCertCollection("sample-trust-cert-collection")
+                    }
+                }
+                relationshipTemplateGrpcServer("sample-token-auth", "Grpc Server") {
+                    tokenAuth {
+                        port(40002)
+                        token("sample-token")
+                    }
+                }
+            }
+            relationshipTypes(
+                arrayListOf(
+                    BluePrintTypes.relationshipTypeConnectsToGrpcServer(),
+                    BluePrintTypes.relationshipTypeConnectsTo()
+                )
+            )
+        }
+        assertNotNull(serviceTemplate, "failed to create service template")
+        val relationshipTemplates = serviceTemplate.topologyTemplate?.relationshipTemplates
+        assertNotNull(relationshipTemplates, "failed to get relationship templates")
+        assertEquals(2, relationshipTemplates.size, "relationshipTemplates doesn't match")
+        assertNotNull(relationshipTemplates["sample-tls-auth"], "failed to get sample-tls-auth")
+        assertNotNull(relationshipTemplates["sample-token-auth"], "failed to get sample-token-auth")
+        // println(serviceTemplate.asJsonString(true))
+    }
+
+    @Test
+    fun testGrpcClientPropertiesDSL() {
+        val serviceTemplate = serviceTemplate("grpc-properties-test", "1.0.0", "xxx.@xx.com", "grpc") {
+            topologyTemplate {
+                relationshipTemplateGrpcClient("sample-tls-auth", "Grpc Server") {
+                    tlsAuth {
+                        host("localhost")
+                        port(40002)
+                        clientCertChain("sample-certchains")
+                        clientPrivateKey("sample-private-key")
+                        trustCertCollection("sample-trust-cert-collection")
+                    }
+                }
+                relationshipTemplateGrpcClient("sample-basic-auth", "Grpc Server") {
+                    basicAuth {
+                        host("localhost")
+                        port(40002)
+                        username("sample-user")
+                        password("credential")
+                    }
+                }
+                relationshipTemplateGrpcClient("sample-token-auth", "Grpc Server") {
+                    tokenAuth {
+                        host("localhost")
+                        port(40002)
+                        token("sample-token")
+                    }
+                }
+            }
+            relationshipTypes(
+                arrayListOf(
+                    BluePrintTypes.relationshipTypeConnectsToGrpcClient(),
+                    BluePrintTypes.relationshipTypeConnectsTo()
+                )
+            )
+        }
+        assertNotNull(serviceTemplate, "failed to create service template")
+        val relationshipTemplates = serviceTemplate.topologyTemplate?.relationshipTemplates
+        assertNotNull(relationshipTemplates, "failed to get relationship templates")
+        assertEquals(3, relationshipTemplates.size, "relationshipTemplates doesn't match")
+        assertNotNull(relationshipTemplates["sample-tls-auth"], "failed to get sample-tls-auth")
+        assertNotNull(relationshipTemplates["sample-basic-auth"], "failed to get sample-basic-auth")
+        assertNotNull(relationshipTemplates["sample-token-auth"], "failed to get sample-token-auth")
+        // println(serviceTemplate.asJsonString(true))
+    }
+}
index 0350bc7..432ef0f 100644 (file)
@@ -70,7 +70,7 @@ open class ResourceDictionaryLoadService(private val resourceDictionaryHandler:
 
     private suspend fun loadResourceDictionary(errorBuilder: StrBuilder, file: File) {
         try {
-            log.trace("Loading NodeType(${file.name}}")
+            log.trace("Loading Resource Dictionary(${file.name}}")
             val definitionContent = file.readNBText()
             val resourceDefinition = JacksonUtils.readValue(definitionContent, ResourceDefinition::class.java)
             if (resourceDefinition != null) {
@@ -102,7 +102,7 @@ open class ResourceDictionaryLoadService(private val resourceDictionaryHandler:
                 throw BluePrintException("couldn't get dictionary from content information")
             }
         } catch (e: Exception) {
-            errorBuilder.appendln("Couldn't load Resource dictionary (${file.name}: ${e.message}")
+            errorBuilder.appendln("Couldn't load Resource dictionary (${file.name}: ${e.message})")
         }
     }
 }
index e2a594b..3e329d7 100644 (file)
@@ -184,10 +184,15 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic
         return executionServiceInput.payload.jsonPathParse(".$requestExpression")
     }
 
-    fun artifactContent(artifactName: String): String {
+    suspend fun artifactContent(artifactName: String): String {
         return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName)
     }
 
+    suspend fun relationshipProperty(relationshipName: String, propertyName: String): JsonNode {
+        return bluePrintRuntimeService.resolveRelationshipTemplateProperties(relationshipName).get(propertyName)
+            ?: throw BluePrintProcessorException("failed to get relationship($relationshipName) property($propertyName)")
+    }
+
     suspend fun mashTemplateNData(artifactName: String, json: String): String {
         val content = artifactContent(artifactName)
         return BluePrintVelocityTemplateService.generateContent(content, json)