Add output enrichment validation
[ccsdk/cds.git] / ms / controllerblueprints / modules / blueprint-validation / src / main / kotlin / org / onap / ccsdk / cds / controllerblueprints / validation / BluePrintNodeTemplateValidatorImpl.kt
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2018-2019 IBM.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package org.onap.ccsdk.cds.controllerblueprints.validation
19
20 import com.att.eelf.configuration.EELFLogger
21 import com.att.eelf.configuration.EELFManager
22 import org.onap.ccsdk.cds.controllerblueprints.validation.utils.PropertyAssignmentValidationUtils
23 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
24 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
25 import org.onap.ccsdk.cds.controllerblueprints.core.data.*
26 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintNodeTemplateValidator
27 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintTypeValidatorService
28 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
29 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
30 import org.springframework.beans.factory.config.ConfigurableBeanFactory
31 import org.springframework.context.annotation.Scope
32 import org.springframework.stereotype.Service
33
34
35 @Service("default-node-template-validator")
36 @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
37 open class BluePrintNodeTemplateValidatorImpl(private val bluePrintTypeValidatorService: BluePrintTypeValidatorService) : BluePrintNodeTemplateValidator {
38
39     private val log: EELFLogger = EELFManager.getInstance().getLogger(BluePrintNodeTemplateValidatorImpl::class.toString())
40
41     lateinit var bluePrintRuntimeService: BluePrintRuntimeService<*>
42     lateinit var bluePrintContext: BluePrintContext
43     lateinit var propertyAssignmentValidationUtils: PropertyAssignmentValidationUtils
44     var paths: MutableList<String> = arrayListOf()
45
46     override fun validate(bluePrintRuntimeService: BluePrintRuntimeService<*>, name: String, nodeTemplate: NodeTemplate) {
47         log.info("Validating NodeTemplate($name)")
48
49         this.bluePrintRuntimeService = bluePrintRuntimeService
50         this.bluePrintContext = bluePrintRuntimeService.bluePrintContext()
51
52         propertyAssignmentValidationUtils = PropertyAssignmentValidationUtils(bluePrintContext)
53
54         paths.add(name)
55
56         val type: String = nodeTemplate.type
57
58         val nodeType: NodeType = bluePrintContext.serviceTemplate.nodeTypes?.get(type)
59                 ?: throw BluePrintException("Failed to get NodeType($type) definition for NodeTemplate($name)")
60
61         nodeTemplate.properties?.let {
62             propertyAssignmentValidationUtils
63                     .validatePropertyAssignments(nodeType.properties!!, nodeTemplate.properties!!)
64         }
65         nodeTemplate.capabilities?.let { validateCapabilityAssignments(nodeType, name, nodeTemplate) }
66         nodeTemplate.requirements?.let { validateRequirementAssignments(nodeType, name, nodeTemplate) }
67         nodeTemplate.interfaces?.let { validateInterfaceAssignments(nodeType, name, nodeTemplate) }
68         nodeTemplate.artifacts?.let { validateArtifactDefinitions(nodeTemplate.artifacts!!) }
69
70         // Perform Extension Validation
71         validateExtension("$type-node-template-validator", name, nodeTemplate)
72
73         paths.removeAt(paths.lastIndex)
74     }
75
76     @Throws(BluePrintException::class)
77     open fun validateArtifactDefinitions(artifacts: MutableMap<String, ArtifactDefinition>) {
78         paths.add("artifacts")
79         artifacts.forEach { artifactDefinitionName, artifactDefinition ->
80             bluePrintTypeValidatorService.validateArtifactDefinition(bluePrintRuntimeService,
81                     artifactDefinitionName, artifactDefinition)
82         }
83         paths.removeAt(paths.lastIndex)
84     }
85
86     @Throws(BluePrintException::class)
87     open fun validateCapabilityAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {
88         val capabilities = nodeTemplate.capabilities
89         paths.add("capabilities")
90         capabilities?.forEach { capabilityName, capabilityAssignment ->
91             paths.add(capabilityName)
92
93             val capabilityDefinition = nodeType.capabilities?.get(capabilityName)
94                     ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) capability definition ($capabilityName) " +
95                             "from NodeType(${nodeTemplate.type})")
96
97             validateCapabilityAssignment(nodeTemplateName, capabilityName, capabilityDefinition, capabilityAssignment)
98
99             paths.removeAt(paths.lastIndex)
100         }
101         paths.removeAt(paths.lastIndex)
102     }
103
104     @Throws(BluePrintException::class)
105     open fun validateCapabilityAssignment(nodeTemplateName: String, capabilityName: String,
106                                           capabilityDefinition: CapabilityDefinition, capabilityAssignment: CapabilityAssignment) {
107
108         capabilityAssignment.properties?.let {
109             propertyAssignmentValidationUtils
110                     .validatePropertyAssignments(capabilityDefinition.properties!!, capabilityAssignment.properties!!)
111         }
112
113     }
114
115     @Throws(BluePrintException::class)
116     open fun validateRequirementAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {
117         val requirements = nodeTemplate.requirements
118         paths.add("requirements")
119         requirements?.forEach { requirementName, requirementAssignment ->
120             paths.add(requirementName)
121             val requirementDefinition = nodeType.requirements?.get(requirementName)
122                     ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) requirement definition ($requirementName) from" +
123                             " NodeType(${nodeTemplate.type})")
124             // Validate Requirement Assignment
125             validateRequirementAssignment(nodeTemplateName, requirementName, requirementDefinition, requirementAssignment)
126             paths.removeAt(paths.lastIndex)
127         }
128         paths.removeAt(paths.lastIndex)
129
130     }
131
132     @Throws(BluePrintException::class)
133     open fun validateRequirementAssignment(nodeTemplateName: String, requirementAssignmentName: String,
134                                            requirementDefinition: RequirementDefinition, requirementAssignment: RequirementAssignment) {
135         log.info("Validating NodeTemplate({}) requirement assignment ({}) ", nodeTemplateName, requirementAssignmentName)
136         val requirementNodeTemplateName = requirementAssignment.node!!
137         val capabilityName = requirementAssignment.capability
138         val relationship = requirementAssignment.relationship!!
139
140         check(BluePrintTypes.validRelationShipDerivedFroms.contains(relationship)) {
141             throw BluePrintException("Failed to get relationship type ($relationship) for NodeTemplate($nodeTemplateName)'s requirement($requirementAssignmentName)")
142         }
143
144         val relationShipNodeTemplate = bluePrintContext.serviceTemplate.topologyTemplate?.nodeTemplates?.get(requirementNodeTemplateName)
145                 ?: throw BluePrintException("Failed to get requirement NodeTemplate($requirementNodeTemplateName)'s " +
146                         "for NodeTemplate($nodeTemplateName) requirement($requirementAssignmentName)")
147
148         relationShipNodeTemplate.capabilities?.get(capabilityName)
149                 ?: throw BluePrintException("Failed to get requirement NodeTemplate($requirementNodeTemplateName)'s " +
150                         "capability($capabilityName) for NodeTemplate ($nodeTemplateName)'s requirement($requirementAssignmentName)")
151
152
153     }
154
155     @Throws(BluePrintException::class)
156     open fun validateInterfaceAssignments(nodeType: NodeType, nodeTemplateName: String, nodeTemplate: NodeTemplate) {
157
158         val interfaces = nodeTemplate.interfaces
159         paths.add("interfaces")
160         interfaces?.forEach { interfaceAssignmentName, interfaceAssignment ->
161             paths.add(interfaceAssignmentName)
162             val interfaceDefinition = nodeType.interfaces?.get(interfaceAssignmentName)
163                     ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) interface definition ($interfaceAssignmentName) from" +
164                             " NodeType(${nodeTemplate.type})")
165
166             validateInterfaceAssignment(nodeTemplateName, interfaceAssignmentName, interfaceDefinition,
167                     interfaceAssignment)
168             paths.removeAt(paths.lastIndex)
169         }
170         paths.removeAt(paths.lastIndex)
171
172
173     }
174
175     @Throws(BluePrintException::class)
176     open fun validateInterfaceAssignment(nodeTemplateName: String, interfaceAssignmentName: String,
177                                          interfaceDefinition: InterfaceDefinition,
178                                          interfaceAssignment: InterfaceAssignment) {
179
180         val operations = interfaceAssignment.operations
181         operations?.let {
182             validateInterfaceOperationsAssignment(nodeTemplateName, interfaceAssignmentName, interfaceDefinition,
183                     interfaceAssignment)
184         }
185
186     }
187
188     @Throws(BluePrintException::class)
189     open fun validateInterfaceOperationsAssignment(nodeTemplateName: String, interfaceAssignmentName: String,
190                                                    interfaceDefinition: InterfaceDefinition,
191                                                    interfaceAssignment: InterfaceAssignment) {
192
193         val operations = interfaceAssignment.operations
194         operations?.let {
195             it.forEach { operationAssignmentName, operationAssignments ->
196
197                 val operationDefinition = interfaceDefinition.operations?.get(operationAssignmentName)
198                         ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) operation definition ($operationAssignmentName)")
199
200                 log.info("Validation NodeTemplate($nodeTemplateName) Interface($interfaceAssignmentName) Operation ($operationAssignmentName)")
201
202                 val inputs = operationAssignments.inputs
203                 val outputs = operationAssignments.outputs
204
205                 inputs?.forEach { propertyName, propertyAssignment ->
206                     val propertyDefinition = operationDefinition.inputs?.get(propertyName)
207                             ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) operation " +
208                                     "definition ($operationAssignmentName) property definition($propertyName)")
209                     // Check the property values with property definition
210                     propertyAssignmentValidationUtils
211                             .validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)
212                 }
213
214                 outputs?.forEach { propertyName, propertyAssignment ->
215                     val propertyDefinition = operationDefinition.outputs?.get(propertyName)
216                             ?: throw BluePrintException("Failed to get NodeTemplate($nodeTemplateName) operation definition ($operationAssignmentName) " +
217                                     "output property definition($propertyName)")
218                     // Check the property values with property definition
219                     propertyAssignmentValidationUtils
220                             .validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)
221                 }
222
223             }
224         }
225
226     }
227
228
229     private fun validateExtension(referencePrefix: String, name: String, nodeTemplate: NodeTemplate) {
230         val customValidator = bluePrintTypeValidatorService
231                 .bluePrintValidator(referencePrefix, BluePrintNodeTemplateValidator::class.java)
232
233         customValidator?.let {
234             it.validate(bluePrintRuntimeService, name, nodeTemplate)
235         }
236     }
237
238 }