From c8c4cd151732fa6e9be45f403244de307456b923 Mon Sep 17 00:00:00 2001 From: "Muthuramalingam, Brinda Santh(bs2796)" Date: Thu, 6 Sep 2018 20:18:24 +0000 Subject: Controller Blueprints Microservice Add Blueprint Dervied from NodeType, Requirement Definitions and Assignments validations. Change-Id: I1cc643b5a83c5a707c8e3ae1342a439f122da55e Issue-ID: CCSDK-484 Signed-off-by: Muthuramalingam, Brinda Santh(bs2796) --- .../Definitions/activation-blueprint.json | 396 ++++++++++++--------- .../model_type/node_type/tosca.nodes.Artifact.json | 5 + .../controllerblueprints/core/BluePrintTypes.kt | 10 + .../core/service/BluePrintEnhancerService.kt | 20 +- .../core/service/BluePrintValidatorService.kt | 130 +++++-- .../core/service/BluePrintRuntimeServiceTest.kt | 38 +- .../src/test/resources/data/default-context.json | 2 + 7 files changed, 382 insertions(+), 219 deletions(-) create mode 100644 components/core/load/model_type/node_type/tosca.nodes.Artifact.json (limited to 'components') diff --git a/components/core/load/blueprints/baseconfiguration/Definitions/activation-blueprint.json b/components/core/load/blueprints/baseconfiguration/Definitions/activation-blueprint.json index 7b9b7dd71..3eb4fedcb 100644 --- a/components/core/load/blueprints/baseconfiguration/Definitions/activation-blueprint.json +++ b/components/core/load/blueprints/baseconfiguration/Definitions/activation-blueprint.json @@ -2,7 +2,7 @@ "metadata": { "template_author": "Brinda Santh Muthuramalingam", "author-email": "brindasanth@gmail.com", - "user-groups" : "ADMIN, OPERATION", + "user-groups": "ADMIN, OPERATION", "template_name": "baseconfiguration", "template_version": "1.0.0", "template_tags": "brinda, tosca" @@ -24,121 +24,125 @@ "hostname": { "required": true, "type": "string" + }, + "template_name": { + "required": true, + "type": "string" + }, + "template_version": { + "required": true, + "type": "string" } }, "node_templates": { - "activate-process": { - "type": "bpmn-activate", - "properties": { - "process-name": { "get_input" : "action-name" }, - "version" : { "get_property" : ["SELF", "process-name"] }, - "content": { "get_artifact" : ["SELF", "activate-process"] } - }, - "artifacts": { - "activate-process": { - "type": "artifact-bpmn-camunda", - "file": "Plans/ActivateProcess.bpmn" - } - } - }, - "resource-assignment": { - "type": "component-resource-assignment", - "properties":{ - "request-id": "1234" + "resource-assignment-ra-component": { + "capabilities": { + "component-node": {} }, "interfaces": { - "DefaultComponentNode": { + "org-onap-sdnc-config-assignment-service-ConfigAssignmentNode": { "operations": { "process": { "inputs": { - "action-name": { "get_input" : "action-name" }, + "template-names": [ + "base-config-template", + "licence-template" + ], + "action-name": { + "get_input": "action-name" + }, + "template-name": { + "get_input": "template_name" + }, + "template-version": { + "get_input": "template_version" + }, "resource-type": "vnf-type", - "request-id": { "get_input" : "request-id" }, - "resource-id": { "get_input" : "hostname" }, - "template-content": { "get_artifact" : ["SELF", "baseconfig-template"] }, - "mapping-content": { "get_artifact" : ["SELF", "baseconfig-mapping"] } + "request-id": { + "get_input": "request-id" + }, + "resource-id": { + "get_input": "hostname" + } }, "outputs": { - "resource-assignment-params": "", - "status": "" + "resource-assignment-params": "success", + "status": "status" } } } } }, - "artifacts": { - "baseconfig-template": { - "type": "artifact-template-velocity", - "file": "Templates/baseconfig-template.vtl" + "type": "component-resource-assignment" + }, + "resource-assignment-action": { + "properties": { + "mode": "sync", + "version": { + "get_input": "template_version" }, - "baseconfig-mapping": { - "type": "artifact-mapping-resource", - "file": "Mappings/baseconfig-mapping.json" + "is-start-flow": false + }, + "requirements": { + "component-dependency": { + "capability": "component-node", + "node": "resource-assignment-ra-component", + "relationship": "tosca.relationships.DependsOn" + } + }, + "capabilities": { + "dg-node": {}, + "content": { + "properties": { + "type": "json" + } } - } - }, - "resource-assignment-py": { - "type": "component-resource-assignment", - "properties":{ - "request-id": "1234" }, "interfaces": { - "DefaultComponentNode": { + "CONFIG": { "operations": { - "process": { - "implementation" :{ - "primary" : "component-script" - }, + "ResourceAssignment": { "inputs": { - "action-name": { "get_input" : "action-name" } - }, - "outputs": { - "resource-assignment-params": "", - "status": "" + "params": [] } } } } }, - "artifacts": { - "component-script": { - "type": "artifact-script-python", - "file": "Scripts/baseconfig-template.vtl" - } - } + "type": "dg-resource-assignment" } }, - "workflows":{ - "activate-process":{ - "steps" : { - "call-resource-assignment" : { - "description" : "Invoke Resource Assignment Component", - "target" : "resource-assignment", - "activities" : [ - { - "call_operation": "ResourceAssignmentNode.process" - } - ], - "on_success" : [ - "download-baseconfig" - ] - }, - "download-baseconfig" : { - "description" : "Call Download Base Config Component", - "target" : "activate-netconf", - "activities" : [ + "workflows": { + "activate-process": { + "steps": { + "call-resource-assignment": { + "description": "Invoke Resource Assignment Component", + "target": "resource-assignment", + "activities": [ + { + "call_operation": "ResourceAssignmentNode.process" + } + ], + "on_success": [ + "download-baseconfig" + ] + }, + "download-baseconfig": { + "description": "Call Download Base Config Component", + "target": "activate-netconf", + "activities": [ { "call_operation": "NetconfTransactionNode.process" } ], - "on_success" : [ + "on_success": [ "download-licence" ] }, - "download-licence" : { - "description" : "Call Download Licence Component", - "target" : "activate-netconf", - "activities" : [ + "download-licence": { + "description": "Call Download Licence Component", + "target": "activate-netconf", + "activities": [ { "call_operation": "NetconfTransactionNode.process" } @@ -199,106 +203,119 @@ } }, "node_types": { - "bpmn-activate": { - "description": "This is BPMN Activate node type", + "dg-resource-assignment": { + "description": "This is Resource Assignment Directed Graph", "version": "1.0.0", "properties": { - "content": { + "mode": { "required": false, - "type": "string" - }, - "process-name": { - "required": false, - "type": "string" + "type": "string", + "default": "sync" }, "version": { "required": false, "type": "string", - "default" : "LATEST" + "default": "LATEST" + }, + "is-start-flow": { + "required": false, + "type": "boolean", + "default": false } }, - "derived_from": "tosca.nodes.Component" - }, - "tosca.nodes.Component": { - "description": "This is Resource Assignment Component API", - "version": "1.0.0", - "properties": { - "type": { - "description": "Request Id used to store the generated configuration, in the database along with the template-name", - "required": false, - "type": "string" + "capabilities": { + "dg-node": { + "type": "tosca.capabilities.Node" + }, + "content": { + "type": "tosca.capability.Content", + "properties": { + "type": { + "required": false, + "type": "string", + "default": "json" + }, + "content": { + "required": false, + "type": "string" + } + } + } + }, + "requirements": { + "component-dependency": { + "capability": "component-node", + "node": "component-resource-assignment", + "relationship": "tosca.relationships.DependsOn" } }, "interfaces": { - "DefaultOperation": { + "CONFIG": { "operations": { - "validate": { + "ResourceAssignment": { "inputs": { - "action-name": { - "description": "validate for action", + "params": { "required": false, - "type": "string" + "type": "list", + "entry_schema": { + "type": "datatype-property" + } } } } } } }, - "artifacts" :{ - "component-jar": { - "description": "Component Jar", - "type": "artifact-component-jar", - "file": "Component/basecomponent.jar" - } - }, - "derived_from": "tosca.nodes.Root" - }, - "tosca.nodes.component.Python": { - "description": "This is Resource Assignment Python Component API", - "version": "1.0.0", - "derived_from": "tosca.nodes.Root" + "derived_from": "tosca.nodes.DG" }, "component-resource-assignment": { "description": "This is Resource Assignment Component API", "version": "1.0.0", - "properties": { - "request-id": { - "description": "Request Id used to store the generated configuration, in the database along with the template-name", - "required": true, - "type": "string" + "capabilities": { + "component-node": { + "type": "tosca.capabilities.Node" } }, "interfaces": { - "DefaultComponentNode": { + "org-onap-sdnc-config-assignment-service-ConfigAssignmentNode": { "operations": { "process": { "inputs": { "action-name": { - "description": "Recipe Name to get from Database, Either (message & mask-info ) or ( resource-id & resource-type & action-name & template-name ) should be present. Message will be given higest priority", - "required": false, + "description": "Action Name of the process", + "required": true, "type": "string" }, - "resource-type": { - "required": false, + "template-name": { + "description": "Service Template Name.", + "required": true, "type": "string" }, - "request-id": { - "description": "Request Id used to store the generated configuration, in the database along with the template-name", + "template-version": { + "description": "Service Template Version.", "required": true, "type": "string" }, - "resource-id": { - "description": "Id used to pull the data content from the data base. Either template-data or resource-id should be present", + "resource-type": { + "description": "Request type.", "required": true, "type": "string" }, - "template-content": { - "description": "Id used to pull the data content from the data base. Either template-data or resource-id should be present", + "template-names": { + "description": "Name of the artifact Node Templates, to get the template Content.", + "required": true, + "type": "list", + "entry_schema": { + "type": "string" + } + }, + "request-id": { + "description": "Request Id, Unique Id for the request.", "required": true, "type": "string" }, - "mapping-content": { - "description": "Id used to pull the data content from the data base. Either template-data or resource-id should be present", + "resource-id": { + "description": "Resource Id.", "required": true, "type": "string" } @@ -319,64 +336,95 @@ }, "derived_from": "tosca.nodes.Component" }, - "component-resource-assignment-python": { + "tosca.nodes.DG": { + "description": "This is Resource Assignment Component API", + "version": "1.0.0", + "derived_from": "tosca.nodes.Root" + }, + "tosca.nodes.Component": { "description": "This is Resource Assignment Component API", "version": "1.0.0", + "derived_from": "tosca.nodes.Root" + }, + "tosca.nodes.component.Python": { + "description": "This is Resource Assignment Python Component API", + "version": "1.0.0", + "derived_from": "tosca.nodes.Root" + } + }, + "data_types": { + "datatype-resource-assignment": { + "version": "1.0.0", + "description": "This is Resource Assignment Data Type", "properties": { - "request-id": { - "description": "Request Id used to store the generated configuration, in the database along with the template-name", + "property": { "required": true, + "type": "datatype-property" + }, + "input-param": { + "required": true, + "type": "boolean" + }, + "dictionary-name": { + "required": false, "type": "string" - } - }, - "interfaces": { - "DefaultComponentNode": { - "operations": { - "process": { - "inputs": { - "action-name": { - "description": "Recipe Name to get from Database, Either (message & mask-info ) or ( resource-id & resource-type & action-name & template-name ) should be present. Message will be given higest priority", - "required": false, - "type": "string" - } - }, - "outputs": { - "resource-assignment-params": { - "required": true, - "type": "string" - }, - "status": { - "required": true, - "type": "string" - } - } - } + }, + "dictionary-source": { + "required": false, + "type": "string" + }, + "dependencies": { + "required": true, + "type": "list", + "entry_schema": { + "type": "string" } + }, + "status": { + "required": false, + "type": "string" + }, + "message": { + "required": false, + "type": "string" + }, + "updated-date": { + "required": false, + "type": "string" + }, + "updated-by": { + "required": false, + "type": "string" } }, - "derived_from": "tosca.nodes.component.Python" - } - }, - "data_types": { - "sample-property" : { - "description": "This is sample data type", + "derived_from": "tosca.datatypes.Root" + }, + "datatype-property": { "version": "1.0.0", + "description": "This is Entry point Input Data Type, which is dynamic datatype, The parameter names will be populated during the Design time for each inputs", "properties": { - "content": { + "type": { + "required": true, + "type": "string" + }, + "description": { "required": false, "type": "string" }, - "process-name": { + "required": { + "required": false, + "type": "boolean" + }, + "default": { "required": false, "type": "string" }, - "version": { + "entry_schema": { "required": false, - "type": "string", - "default" : "LATEST" + "type": "string" } }, - "derived_from" : "tosca.datatypes.Root" + "derived_from": "tosca.datatypes.Root" } } } \ No newline at end of file diff --git a/components/core/load/model_type/node_type/tosca.nodes.Artifact.json b/components/core/load/model_type/node_type/tosca.nodes.Artifact.json new file mode 100644 index 000000000..814105277 --- /dev/null +++ b/components/core/load/model_type/node_type/tosca.nodes.Artifact.json @@ -0,0 +1,5 @@ +{ + "description": "This is Deprecated Artifact Node Type.", + "version": "1.0.0", + "derived_from": "tosca.nodes.Root" +} \ No newline at end of file diff --git a/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/BluePrintTypes.kt b/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/BluePrintTypes.kt index af3966aad..24514db50 100644 --- a/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/BluePrintTypes.kt +++ b/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/BluePrintTypes.kt @@ -50,6 +50,16 @@ object BluePrintTypes { BluePrintConstants.MODEL_TYPE_DATA_TYPE_DYNAMIC ) + @JvmStatic + val validRelationShipDerivedFroms: MutableList = arrayListOf( + BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_ROOT, + BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_DEPENDS_ON, + BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_HOSTED_ON, + BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO, + BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_ATTACH_TO, + BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_ROUTES_TO + ) + @JvmStatic fun validModelTypes(): List { val validTypes: MutableList = arrayListOf() diff --git a/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/service/BluePrintEnhancerService.kt b/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/service/BluePrintEnhancerService.kt index f38c317e7..b125c594c 100644 --- a/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/service/BluePrintEnhancerService.kt +++ b/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/service/BluePrintEnhancerService.kt @@ -130,6 +130,14 @@ open class BluePrintEnhancerDefaultService(val bluePrintRepoService: BluePrintRe @Throws(BluePrintException::class) override fun enrichNodeType(nodeTypeName: String, nodeType: NodeType) { + log.debug("Enriching NodeType({})", nodeTypeName) + val derivedFrom = nodeType.derivedFrom + + if (!BluePrintTypes.rootNodeTypes().contains(derivedFrom)) { + val derivedFromNodeType = populateNodeType(nodeTypeName) + // Enrich NodeType + enrichNodeType(derivedFrom, derivedFromNodeType) + } // NodeType Property Definitions enrichNodeTypeProperties(nodeTypeName, nodeType) @@ -172,7 +180,7 @@ open class BluePrintEnhancerDefaultService(val bluePrintRepoService: BluePrintRe open fun enrichNodeTypeInterfaces(nodeTypeName: String, nodeType: NodeType) { nodeType.interfaces?.forEach { interfaceName, interfaceObj -> // Populate Node type Interface Operation - log.info("*** ** Enriching NodeType: {} Interface {}", nodeTypeName, interfaceName) + log.debug("Enriching NodeType({}) Interface({})", nodeTypeName, interfaceName) populateNodeTypeInterfaceOperation(nodeTypeName, interfaceName, interfaceObj) } @@ -235,21 +243,25 @@ open class BluePrintEnhancerDefaultService(val bluePrintRepoService: BluePrintRe } open fun populateNodeType(nodeTypeName: String): NodeType { - val nodeType = bluePrintRepoService.getNodeType(nodeTypeName)?.block() + + val nodeType = serviceTemplate.nodeTypes?.get(nodeTypeName) + ?: bluePrintRepoService.getNodeType(nodeTypeName)?.block() ?: throw BluePrintException(format("Couldn't get NodeType({}) from repo.", nodeTypeName)) serviceTemplate.nodeTypes?.put(nodeTypeName, nodeType) return nodeType } open fun populateArtifactType(artifactTypeName: String): ArtifactType { - val artifactType = bluePrintRepoService.getArtifactType(artifactTypeName)?.block() + val artifactType = serviceTemplate.artifactTypes?.get(artifactTypeName) + ?: bluePrintRepoService.getArtifactType(artifactTypeName)?.block() ?: throw BluePrintException(format("Couldn't get ArtifactType({}) from repo.", artifactTypeName)) serviceTemplate.artifactTypes?.put(artifactTypeName, artifactType) return artifactType } open fun populateDataTypes(dataTypeName: String): DataType { - val dataType = bluePrintRepoService.getDataType(dataTypeName)?.block() + val dataType = serviceTemplate.dataTypes?.get(dataTypeName) + ?: bluePrintRepoService.getDataType(dataTypeName)?.block() ?: throw BluePrintException(format("Couldn't get DataType({}) from repo.", dataTypeName)) serviceTemplate.dataTypes?.put(dataTypeName, dataType) return dataType diff --git a/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/service/BluePrintValidatorService.kt b/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/service/BluePrintValidatorService.kt index a60f532e0..2b11589d4 100644 --- a/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/service/BluePrintValidatorService.kt +++ b/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/service/BluePrintValidatorService.kt @@ -111,7 +111,7 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { paths.add("dataTypes") dataTypes.forEach { dataTypeName, dataType -> paths.add(dataTypeName) - message.appendln("--> Data Type :" + paths.joinToString(separator)) + message.appendln("--> DataType :" + paths.joinToString(separator)) dataType.properties?.let { validatePropertyDefinitions(dataType.properties!!) } paths.removeAt(paths.lastIndex) } @@ -136,7 +136,14 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { //Check Derived From checkValidNodeTypesDerivedFrom(nodeTypeName, derivedFrom) + if(!BluePrintTypes.rootNodeTypes().contains(derivedFrom)){ + serviceTemplate.nodeTypes?.get(derivedFrom) + ?: throw BluePrintException(format("Failed to get derivedFrom NodeType({})'s for NodeType({}) ", + derivedFrom, nodeTypeName)) + } + nodeType.properties?.let { validatePropertyDefinitions(nodeType.properties!!) } + nodeType.requirements?.let { validateRequirementDefinitions(nodeTypeName, nodeType) } nodeType.interfaces?.let { validateInterfaceDefinitions(nodeType.interfaces!!) } paths.removeAt(paths.lastIndex) } @@ -144,7 +151,7 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { @Throws(BluePrintException::class) open fun checkValidNodeTypesDerivedFrom(nodeTypeName: String, derivedFrom: String) { check(BluePrintTypes.validNodeTypeDerivedFroms.contains(derivedFrom)) { - throw BluePrintException(format("Failed to get node type ({})'s derived from({}) definition ", nodeTypeName, derivedFrom)) + throw BluePrintException(format("Failed to get node type ({})'s derivedFrom({}) definition ", nodeTypeName, derivedFrom)) } } @@ -178,16 +185,16 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { @Throws(BluePrintException::class) open fun validateNodeTemplate(nodeTemplateName: String, nodeTemplate: NodeTemplate) { paths.add(nodeTemplateName) - message.appendln("---> Node Template :" + paths.joinToString(separator)) + message.appendln("---> NodeTemplate :" + paths.joinToString(separator)) val type: String = nodeTemplate.type val nodeType: NodeType = serviceTemplate.nodeTypes?.get(type) - ?: throw BluePrintException(format("Failed to get node type definition for node template : {}", nodeTemplateName)) + ?: throw BluePrintException(format("Failed to get NodeType({}) definition for NodeTemplate({})", type, nodeTemplateName)) nodeTemplate.artifacts?.let { validateArtifactDefinitions(nodeTemplate.artifacts!!) } nodeTemplate.properties?.let { validatePropertyAssignments(nodeType.properties!!, nodeTemplate.properties!!) } nodeTemplate.capabilities?.let { validateCapabilityAssignments(nodeTemplate.capabilities!!) } - nodeTemplate.requirements?.let { validateRequirementAssignments(nodeTemplate.requirements!!) } + nodeTemplate.requirements?.let { validateRequirementAssignments(nodeType, nodeTemplateName, nodeTemplate) } nodeTemplate.interfaces?.let { validateInterfaceAssignments(nodeType, nodeTemplateName, nodeTemplate) } paths.removeAt(paths.lastIndex) } @@ -199,12 +206,12 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { paths.add(artifactDefinitionName) message.appendln("Validating artifact " + paths.joinToString(separator)) val type: String = artifactDefinition.type - ?: throw BluePrintException("type is missing for artifact definition :" + artifactDefinitionName) + ?: throw BluePrintException(format("type is missing for ArtifactDefinition({})", artifactDefinitionName)) // Check Artifact Type checkValidArtifactType(artifactDefinitionName, type) val file: String = artifactDefinition.file - ?: throw BluePrintException(format("file is missing for artifact definition : {}", artifactDefinitionName)) + ?: throw BluePrintException(format("file is missing for ArtifactDefinition({})", artifactDefinitionName)) paths.removeAt(paths.lastIndex) } @@ -250,7 +257,7 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { } BluePrintTypes.validCollectionTypes().contains(dataType) -> { val entrySchemaType: String = propertyDefinition.entrySchema?.type - ?: throw BluePrintException(format("Entry schema for data type ({}) for the property ({}) not found", dataType, propertyName)) + ?: throw BluePrintException(format("Entry schema for DataType ({}) for the property ({}) not found", dataType, propertyName)) checkPrimitiveOrComplex(entrySchemaType, propertyName) } else -> checkPropertyDataType(dataType, propertyName) @@ -289,7 +296,43 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { } @Throws(BluePrintException::class) - open fun validateRequirementAssignments(requirements: MutableMap) { + open fun validateRequirementAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) { + val requirements = nodeTemplate.requirements + paths.add("requirements") + requirements?.forEach { requirementName, requirementAssignment -> + paths.add(requirementName) + val requirementDefinition = nodeType.requirements?.get(requirementName) + ?: throw BluePrintException(format("Failed to get NodeTemplate({}) requirement definition ({}) from" + + " NodeType({}) ", nodeTemplateName, requirementName, nodeTemplate.type)) + // Validate Requirement Assignment + validateRequirementAssignment(nodeTemplateName, requirementName, requirementDefinition, requirementAssignment) + paths.removeAt(paths.lastIndex) + } + paths.removeAt(paths.lastIndex) + + } + + @Throws(BluePrintException::class) + open fun validateRequirementAssignment(nodeTemplateName: String, requirementAssignmentName: String, + requirementDefinition: RequirementDefinition, requirementAssignment: RequirementAssignment) { + log.info("Validating NodeTemplate({}) requirement assignment ({}) ", nodeTemplateName, requirementAssignmentName) + val requirementNodeTemplateName = requirementAssignment.node!! + val capabilityName = requirementAssignment.capability + val relationship = requirementAssignment.relationship!! + + check(BluePrintTypes.validRelationShipDerivedFroms.contains(relationship)) { + throw BluePrintException(format("Failed to get relationship type ({}) for NodeTemplate({})'s requirement({}) ", + relationship, nodeTemplateName, requirementAssignmentName)) + } + + val relationShipNodeTemplate = serviceTemplate.topologyTemplate?.nodeTemplates?.get(requirementNodeTemplateName) + ?: throw BluePrintException(format("Failed to get requirement NodeTemplate({})'s for NodeTemplate({}) requirement({}) ", + requirementNodeTemplateName, nodeTemplateName, requirementAssignmentName)) + + relationShipNodeTemplate.capabilities?.get(capabilityName) + ?: throw BluePrintException(format("Failed to get requirement NodeTemplate({})'s capability({}) for NodeTemplate ({})'s requirement({}) ", + requirementNodeTemplateName, capabilityName, nodeTemplateName, requirementAssignmentName)) + } @@ -301,8 +344,8 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { interfaces?.forEach { interfaceAssignmentName, interfaceAssignment -> paths.add(interfaceAssignmentName) val interfaceDefinition = nodeType.interfaces?.get(interfaceAssignmentName) - ?: throw BluePrintException(format("Failed to get nodeTemplate({}) interface definition ({}) from" + - " node type ({}) ", nodeTemplateName, interfaceAssignmentName, nodeTemplate.type)) + ?: throw BluePrintException(format("Failed to get NodeTemplate({}) interface definition ({}) from" + + " NodeType({}) ", nodeTemplateName, interfaceAssignmentName, nodeTemplate.type)) validateInterfaceAssignment(nodeTemplateName, interfaceAssignmentName, interfaceDefinition, interfaceAssignment) @@ -336,10 +379,10 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { it.forEach { operationAssignmentName, operationAssignments -> val operationDefinition = interfaceDefinition.operations?.get(operationAssignmentName) - ?: throw BluePrintException(format("Failed to get nodeTemplate({}) operation definition ({}) ", + ?: throw BluePrintException(format("Failed to get NodeTemplate({}) operation definition ({}) ", nodeTemplateName, operationAssignmentName)) - log.info("Validation Node Template({}) Interface({}) Operation ({})", nodeTemplateName, + log.info("Validation NodeTemplate({}) Interface({}) Operation ({})", nodeTemplateName, interfaceAssignmentName, operationAssignmentName) val inputs = operationAssignments.inputs @@ -347,7 +390,7 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { inputs?.forEach { propertyName, propertyAssignment -> val propertyDefinition = operationDefinition.inputs?.get(propertyName) - ?: throw BluePrintException(format("Failed to get nodeTemplate({}) operation definition ({}) " + + ?: throw BluePrintException(format("Failed to get NodeTemplate({}) operation definition ({}) " + "property definition({})", nodeTemplateName, operationAssignmentName, propertyName)) // Check the property values with property definition validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment) @@ -358,6 +401,44 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { } + @Throws(BluePrintException::class) + open fun validateRequirementDefinitions(nodeName: String, nodeType: NodeType) { + paths.add("requirements") + val requirements = nodeType.requirements + + requirements?.forEach { requirementDefinitionName, requirementDefinition -> + paths.add(requirementDefinitionName) + message.appendln("Validating : " + paths.joinToString(separator)) + validateRequirementDefinition(nodeName, nodeType, requirementDefinitionName, requirementDefinition) + paths.removeAt(paths.lastIndex) + } + paths.removeAt(paths.lastIndex) + } + + @Throws(BluePrintException::class) + open fun validateRequirementDefinition(nodeTypeName: String, nodeType: NodeType, requirementDefinitionName: String, + requirementDefinition: RequirementDefinition) { + + log.info("Validating NodeType({}) RequirementDefinition ({}) ", nodeTypeName, requirementDefinitionName) + val requirementNodeTypeName = requirementDefinition.node!! + val capabilityName = requirementDefinition.capability + val relationship = requirementDefinition.relationship!! + + check(BluePrintTypes.validRelationShipDerivedFroms.contains(relationship)) { + throw BluePrintException(format("Failed to get relationship({}) for NodeType({})'s requirement({}) ", + relationship, nodeTypeName, requirementDefinitionName)) + } + + val relationShipNodeType = serviceTemplate.nodeTypes?.get(requirementNodeTypeName) + ?: throw BluePrintException(format("Failed to get requirement NodeType({})'s for requirement({}) ", + requirementNodeTypeName, requirementDefinitionName)) + + relationShipNodeType.capabilities?.get(capabilityName) + ?: throw BluePrintException(format("Failed to get requirement NodeType({})'s capability({}) for NodeType ({})'s requirement({}) ", + requirementNodeTypeName, capabilityName, nodeTypeName, requirementDefinitionName)) + + } + @Throws(BluePrintException::class) open fun validateInterfaceDefinitions(interfaces: MutableMap) { @@ -394,7 +475,7 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { open fun checkValidArtifactType(artifactDefinitionName: String, artifactTypeName: String) { val artifactType = serviceTemplate.artifactTypes?.get(artifactTypeName) - ?: throw BluePrintException(format("Failed to artifact type for artifact definition : {}", artifactDefinitionName)) + ?: throw BluePrintException(format("Failed to ArtifactType for ArtifactDefinition : {}", artifactDefinitionName)) checkValidArtifactTypeDerivedFrom(artifactTypeName, artifactType.derivedFrom) } @@ -402,14 +483,21 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { @Throws(BluePrintException::class) open fun checkValidArtifactTypeDerivedFrom(artifactTypeName: String, derivedFrom: String) { check(BluePrintTypes.validArtifactTypeDerivedFroms.contains(derivedFrom)) { - throw BluePrintException(format("Failed to get artifact type ({})'s derived from({}) definition ", artifactTypeName, derivedFrom)) + throw BluePrintException(format("Failed to get ArtifactType ({})'s derivedFrom({}) definition ", artifactTypeName, derivedFrom)) } } @Throws(BluePrintException::class) open fun checkValidDataTypeDerivedFrom(dataTypeName: String, derivedFrom: String) { check(BluePrintTypes.validDataTypeDerivedFroms.contains(derivedFrom)) { - throw BluePrintException(format("Failed to get data type ({})'s derived from({}) definition ", dataTypeName, derivedFrom)) + throw BluePrintException(format("Failed to get DataType ({})'s derivedFrom({}) definition ", dataTypeName, derivedFrom)) + } + } + + @Throws(BluePrintException::class) + open fun checkValidRelationshipTypeDerivedFrom(relationshipTypeName: String, derivedFrom: String) { + check(BluePrintTypes.validRelationShipDerivedFroms.contains(derivedFrom)) { + throw BluePrintException(format("Failed to get relationship type ({})'s derivedFrom({}) definition ", relationshipTypeName, derivedFrom)) } } @@ -423,7 +511,7 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { } else if (BluePrintTypes.validCollectionTypes().contains(propertyType)) { val entrySchemaType = propertyDefinition.entrySchema?.type - ?: throw BluePrintException(format("Failed to get Entry Schema type for the collection property ({})", propertyName)) + ?: throw BluePrintException(format("Failed to get EntrySchema type for the collection property ({})", propertyName)) if (!BluePrintTypes.validPropertyTypes().contains(entrySchemaType)) { checkPropertyDataType(entrySchemaType, propertyName) @@ -435,7 +523,7 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { } check(isValid) { - throw BluePrintException(format("property({}) defined of type({}) is not compatable with the value ({})", + throw BluePrintException(format("property({}) defined of type({}) is not comptable with the value ({})", propertyName, propertyType, propertyAssignment)) } } @@ -443,7 +531,7 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { private fun checkPropertyDataType(dataType: String, propertyName: String) { val dataType = serviceTemplate.dataTypes?.get(dataType) - ?: throw BluePrintException(format("Data type ({}) for the property ({}) not found", dataType, propertyName)) + ?: throw BluePrintException(format("DataType ({}) for the property ({}) not found", dataType, propertyName)) checkValidDataTypeDerivedFrom(propertyName, dataType.derivedFrom) @@ -453,7 +541,7 @@ open class BluePrintValidatorDefaultService : BluePrintValidatorService { if (BluePrintTypes.validPrimitiveTypes().contains(dataType) || checkDataType(dataType)) { return true } else { - throw BluePrintException(format("Data type ({}) for the property ({}) is not valid", dataType)) + throw BluePrintException(format("DataType ({}) for the property ({}) is not valid", dataType)) } } diff --git a/components/core/src/test/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/service/BluePrintRuntimeServiceTest.kt b/components/core/src/test/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/service/BluePrintRuntimeServiceTest.kt index 5d24b072f..919dc564e 100644 --- a/components/core/src/test/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/service/BluePrintRuntimeServiceTest.kt +++ b/components/core/src/test/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/service/BluePrintRuntimeServiceTest.kt @@ -55,17 +55,17 @@ class BluePrintRuntimeServiceTest { context[BluePrintConstants.PROPERTY_BLUEPRINT_BASE_PATH] = basepath.plus("/simple-baseconfig") val bluePrintRuntimeService = BluePrintRuntimeService(bluePrintContext, context) - val inputDataPath = "src/test/resources/data/default-context.json" + val inputDataPath = "src/test/resources/data/default-context.json" val inputNode: JsonNode = jsonNodeFromFile(inputDataPath) bluePrintRuntimeService.assignInputs(inputNode) - val propContext: MutableMap = bluePrintRuntimeService.resolveNodeTemplateProperties("activate-process") - log.info("Context {}" ,bluePrintRuntimeService.context) + val propContext: MutableMap = bluePrintRuntimeService.resolveNodeTemplateProperties("resource-assignment-action") + log.info("Context {}", bluePrintRuntimeService.context) assertNotNull(propContext, "Failed to populate interface property values") - assertEquals(propContext.get("process-name"), jsonNodeFromObject("sample-action"), "Failed to populate parameter process-name") - assertEquals(propContext.get("version"), jsonNodeFromObject("sample-action"), "Failed to populate parameter version") + assertEquals(propContext.get("mode"), jsonNodeFromObject("sync"), "Failed to populate parameter process-name") + assertEquals(propContext.get("version"), jsonNodeFromObject("1.0.0"), "Failed to populate parameter version") } @Test @@ -78,24 +78,22 @@ class BluePrintRuntimeServiceTest { val context: MutableMap = hashMapOf() context[BluePrintConstants.PROPERTY_BLUEPRINT_BASE_PATH] = basepath.plus("/simple-baseconfig") - val inputDataPath = "src/test/resources/data/default-context.json" + val inputDataPath = "src/test/resources/data/default-context.json" BluePrintRuntimeUtils.assignInputsFromFile(bluePrintContext, inputDataPath, context) val bluePrintRuntimeService = BluePrintRuntimeService(bluePrintContext, context) - log.info("Prepared Context {}" ,context) + log.info("Prepared Context {}", context) - val inContext: MutableMap = bluePrintRuntimeService.resolveNodeTemplateInterfaceOperationInputs("resource-assignment", - "DefaultComponentNode", "process") + val inContext: MutableMap = bluePrintRuntimeService.resolveNodeTemplateInterfaceOperationInputs("resource-assignment-ra-component", + "org-onap-sdnc-config-assignment-service-ConfigAssignmentNode", "process") - log.trace("In Context {}" ,inContext) + log.info("In Context {}", inContext) assertNotNull(inContext, "Failed to populate interface input property values") assertEquals(inContext.get("action-name"), jsonNodeFromObject("sample-action"), "Failed to populate parameter action-name") assertEquals(inContext.get("request-id"), jsonNodeFromObject("12345"), "Failed to populate parameter action-name") - assertEquals(inContext.get("template-content"), jsonNodeFromObject("This is Sample Velocity Template"), "Failed to populate parameter action-name") - } @Test @@ -106,24 +104,24 @@ class BluePrintRuntimeServiceTest { assertNotNull(bluePrintContext, "Failed to populate Blueprint context") val context: MutableMap = hashMapOf() - context[BluePrintConstants.PROPERTY_BLUEPRINT_BASE_PATH] = basepath.plus("/simple-baseconfig") + context[BluePrintConstants.PROPERTY_BLUEPRINT_BASE_PATH] = basepath.plus("/simple-baseconfig") val bluePrintRuntimeService = BluePrintRuntimeService(bluePrintContext, context) val componentContext: MutableMap = hashMapOf() - val successValue : JsonNode= jsonNodeFromObject("Success") - componentContext["resource-assignment.DefaultComponentNode.process.status"] = successValue - componentContext["resource-assignment.DefaultComponentNode.process.resource-assignment-params"] = null + val successValue: JsonNode = jsonNodeFromObject("Success") + componentContext["resource-assignment-ra-component.org-onap-sdnc-config-assignment-service-ConfigAssignmentNode.process.status"] = successValue + componentContext["resource-assignment-ra-component.org-onap-sdnc-config-assignment-service-ConfigAssignmentNode.process.resource-assignment-params"] = null - bluePrintRuntimeService.resolveNodeTemplateInterfaceOperationOutputs("resource-assignment", - "DefaultComponentNode", "process", componentContext) + bluePrintRuntimeService.resolveNodeTemplateInterfaceOperationOutputs("resource-assignment-ra-component", + "org-onap-sdnc-config-assignment-service-ConfigAssignmentNode", "process", componentContext) assertEquals(NullNode.instance, - context.get("node_templates/resource-assignment/interfaces/DefaultComponentNode/operations/process/properties/resource-assignment-params"), + context.get("node_templates/resource-assignment-ra-component/interfaces/org-onap-sdnc-config-assignment-service-ConfigAssignmentNode/operations/process/properties/resource-assignment-params"), "Failed to get operation property resource-assignment-params") assertEquals(successValue, - context.get("node_templates/resource-assignment/interfaces/DefaultComponentNode/operations/process/properties/status"), + context.get("node_templates/resource-assignment-ra-component/interfaces/org-onap-sdnc-config-assignment-service-ConfigAssignmentNode/operations/process/properties/status"), "Failed to get operation property status") diff --git a/components/core/src/test/resources/data/default-context.json b/components/core/src/test/resources/data/default-context.json index fcd4cbe26..e033f6f57 100644 --- a/components/core/src/test/resources/data/default-context.json +++ b/components/core/src/test/resources/data/default-context.json @@ -1,5 +1,7 @@ { "request-id" : "12345", "hostname" : "localhost", + "template_name": "baseconfiguration", + "template_version": "1.0.0", "action-name" : "sample-action" } \ No newline at end of file -- cgit 1.2.3-korg