2 * ============LICENSE_START===================================================
3 * Copyright (c) 2018 Amdocs
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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 * ============LICENSE_END=====================================================
22 indices 'default-rules'
26 // NDCB-AAI comparison: Context level
28 name 'Attribute-comparison'
29 attributes 'context-list.ndcb', 'context-list.aai'
32 // NDCB-AAI comparison: Service entity
34 name 'Attribute-comparison'
35 attributes 'context-list.ndcb.service', 'context-list.aai.service'
38 // NDCB-AAI comparison: Context level network list
40 name 'Attribute-comparison'
41 attributes 'context-list.ndcb.networkList[*]', 'context-list.aai.networkList[*]'
44 // NDCB-AAI comparison: VNF list
46 name 'Attribute-comparison'
47 attributes 'context-list.ndcb.vnfList[*]', 'context-list.aai.vnfList[*]'
50 // NDCB-AAI comparison: VNF network list
52 name 'Attribute-comparison'
53 attributes 'context-list.ndcb.vnfList[*].networkList[*]', 'context-list.aai.vnfList[*].networkList[*]'
56 // NDCB-AAI comparison: VF-Module list
58 name 'Attribute-comparison'
59 attributes 'context-list.ndcb.vnfList[*].vfModuleList[*]', 'context-list.aai.vnfList[*].vfModuleList[*]'
62 // NDCB-AAI comparison: VF-Module network list
64 name 'Attribute-comparison'
65 attributes 'context-list.ndcb.vnfList[*].vfModuleList[*].networkList[*]', 'context-list.aai.vnfList[*].vfModuleList[*].networkList[*]'
68 // NDCB-AAI comparison: VNFC list
70 name 'Attribute-comparison'
71 attributes 'context-list.ndcb.vnfList[*].vnfcList[*]', 'context-list.aai.vnfList[*].vnfcList[*]'
74 // NDCB-AAI comparison: VM list
76 name 'Attribute-comparison'
77 attributes 'context-list.ndcb.vnfList[*].vfModuleList[*].vmList[*]', 'context-list.aai.vnfList[*].vfModuleList[*].vmList[*]'
81 // SDNC-AAI comparison: Context level
83 name 'Attribute-comparison'
84 attributes 'context-list.sdnc', 'context-list.aai'
87 // SDNC-AAI comparison: Service entity
89 name 'Attribute-comparison'
90 attributes 'context-list.sdnc.service', 'context-list.aai.service'
93 // SDNC-AAI comparison: Context level network list
95 name 'Attribute-comparison'
96 attributes 'context-list.sdnc.networkList[*]', 'context-list.aai.networkList[*]'
99 // SDNC-AAI comparison: VNF list
101 name 'Attribute-comparison'
102 attributes 'context-list.sdnc.vnfList[*]', 'context-list.aai.vnfList[*]'
105 // SDNC-AAI comparison: VNF network list
107 name 'Attribute-comparison'
108 attributes 'context-list.sdnc.vnfList[*].networkList[*]', 'context-list.aai.vnfList[*].networkList[*]'
111 // SDNC-AAI comparison: VF-Module list
113 name 'Attribute-comparison'
114 attributes 'context-list.sdnc.vnfList[*].vfModuleList[*]', 'context-list.aai.vnfList[*].vfModuleList[*]'
117 // SDNC-AAI comparison: VF-Module network list
119 name 'Attribute-comparison'
120 attributes 'context-list.sdnc.vnfList[*].vfModuleList[*].networkList[*]', 'context-list.aai.vnfList[*].vfModuleList[*].networkList[*]'
123 // SDNC-AAI comparison: VNFC list
125 name 'Attribute-comparison'
126 attributes 'context-list.sdnc.vnfList[*].vnfcList[*]', 'context-list.aai.vnfList[*].vnfcList[*]'
129 // SDNC-AAI comparison: VM list
131 name 'Attribute-comparison'
132 attributes 'context-list.sdnc.vnfList[*].vfModuleList[*].vmList[*]', 'context-list.aai.vnfList[*].vfModuleList[*].vmList[*]'
137 // SDNC-NDCB comparison: Context level
139 name 'Attribute-comparison'
140 attributes 'context-list.sdnc', 'context-list.ndcb'
143 // SDNC-NDCB comparison: Service entity
145 name 'Attribute-comparison'
146 attributes 'context-list.sdnc.service', 'context-list.ndcb.service'
149 // SDNC-NDCB comparison: Context level network list
151 name 'Attribute-comparison'
152 attributes 'context-list.sdnc.networkList[*]', 'context-list.ndcb.networkList[*]'
155 // SDNC-NDCB comparison: VNF list
157 name 'Attribute-comparison'
158 attributes 'context-list.sdnc.vnfList[*]', 'context-list.ndcb.vnfList[*]'
161 // SDNC-NDCB comparison: VNF network list
163 name 'Attribute-comparison'
164 attributes 'context-list.sdnc.vnfList[*].networkList[*]', 'context-list.ndcb.vnfList[*].networkList[*]'
167 // SDNC-NDCB comparison: VF-Module list
169 name 'Attribute-comparison'
170 attributes 'context-list.sdnc.vnfList[*].vfModuleList[*]', 'context-list.ndcb.vnfList[*].vfModuleList[*]'
173 // SDNC-NDCB comparison: VF-Module network list
175 name 'Attribute-comparison'
176 attributes 'context-list.sdnc.vnfList[*].vfModuleList[*].networkList[*]', 'context-list.ndcb.vnfList[*].vfModuleList[*].networkList[*]'
179 // SDNC-NDCB comparison: VNFC list
181 name 'Attribute-comparison'
182 attributes 'context-list.sdnc.vnfList[*].vnfcList[*]', 'context-list.ndcb.vnfList[*].vnfcList[*]'
185 // SDNC-NDCB comparison: VM list
187 name 'Attribute-comparison'
188 attributes 'context-list.sdnc.vnfList[*].vfModuleList[*].vmList[*]', 'context-list.ndcb.vnfList[*].vfModuleList[*].vmList[*]'
195 name 'SDC-AAI-vnfc-type'
196 attributes 'context-list.sdc.vnfList[*].vnfcList[*]', 'context-list.aai.vnfList[*].vnfcList[*]'
199 // SDC-AAI VNFC node count
201 name 'SDC-AAI-vnfc-node-count'
202 attributes 'context-list.sdc.vnfList[*].vnfcList[*]', 'context-list.aai.vnfList[*].vnfcList[*]'
205 // SDC-AAI VF-Module instance
207 name 'SDC-AAI-vf-module-instance-check'
208 attributes 'context-list.sdc.vnfList[*].vfModuleList[*]', 'context-list.aai.vnfList[*].vfModuleList[*]'
214 name 'SDC-AAI-vnfc-type'
215 category 'VNFC Consistency'
216 description 'Validate that each VNFC instance in AAI conforms to a VNFC type defined in SDC model'
217 errorText 'AAI VNFC instance includes non-specified type in design SDC model'
219 attributes 'sdcList', 'aaiList'
221 def getVnfcTypes = { parsedData ->
222 parsedData.collect{ it.findResult{ k, v -> if(k.equals("type")) {return "$v"}}}
225 def slurper = new groovy.json.JsonSlurper()
226 def sdcTypes = getVnfcTypes(slurper.parseText(sdcList.toString()))
227 def aaiTypes = getVnfcTypes(slurper.parseText(aaiList.toString()))
229 // each type in AAI must exist in SDC
230 return sdcTypes.containsAll(aaiTypes)
235 name 'SDC-AAI-vnfc-node-count'
236 category 'VNFC Consistency'
237 description 'Validate that for each VNFC node defined in SDC model, there is at least one VNFC instance in AAI'
238 errorText 'Design has specified types but not all of them exist in AAI'
240 attributes 'sdcList', 'aaiList'
242 def getVnfcNodes = { parsedData ->
243 parsedData.collect { new Tuple2(
244 it.findResult{ k, v -> if(k.equals("name")) {return "$v"}},
245 it.findResult{ k, v -> if(k.equals("type")) {return "$v"}})
249 def slurper = new groovy.json.JsonSlurper()
250 def sdcNodes = getVnfcNodes(slurper.parseText(sdcList.toString()))
251 def aaiNodes = getVnfcNodes(slurper.parseText(aaiList.toString()))
253 // each node in AAI must exist in SDC
254 return aaiNodes.containsAll(sdcNodes)
259 name 'SDC-AAI-vf-module-instance-check'
260 category 'VF Consistency'
261 description 'Validate that each VF module instance in AAI conforms to a VF module defined in SDC service model'
262 errorText 'One or more AAI VF module instance(s) not defined in SDC model'
264 attributes 'sdcList', 'aaiList'
266 def getVfModules = { parsedData ->
267 parsedData.collect{ it.findResult{ k, v -> if(k.equals("name")) {return "$v"}}}
270 def slurper = new groovy.json.JsonSlurper()
271 def sdcVfModules = getVfModules(slurper.parseText(sdcList.toString()))
272 def aaiVfModules = getVfModules(slurper.parseText(aaiList.toString()))
274 // all VF modules in AAI must exist in SDC
275 return aaiVfModules.containsAll(sdcVfModules)
280 name 'Attribute-comparison'
281 category 'Attribute Mismatch'
282 description 'Determine all discrepancies between values for attributes with matching names from each model'
283 errorText 'Error found with attribute(s) and values: {0}'
285 attributes 'lhsObject', 'rhsObject'
287 // This closure extracts the given object's root level attributes and contents of the attribute list.
288 // Complex items like lists are excluded.
289 // Returns a map containing attribute names as keys, mapping to a list of values for each attribute.
290 Closure<java.util.Map> getAttributes = { parsedData ->
291 java.util.Map attributeMap = new java.util.HashMap()
293 def isAttributeDataQualityOk = { attribute ->
294 attribute.findResult{ k, v -> if(k.equals("dataQuality") ) {return v.get("status")}}.equals("ok")
297 def addToMap = { attrKey, attrValue ->
298 java.util.Set values = attributeMap.get("$attrKey")
300 values = new java.util.HashSet()
301 attributeMap.put("$attrKey", values)
303 values.add("$attrValue")
306 def addAttributeToMap = { attribute ->
307 if(isAttributeDataQualityOk(attribute)) {
309 attribute.each { k, v ->
310 if(k.equals("name")) {key = "$v"}
311 if(k.equals("value")) {value = "$v"}
313 addToMap("$key", "$value")
317 def processKeyValue = { key, value ->
318 if(value instanceof java.util.ArrayList) {
319 if(key.equals("attributeList")) {
321 addAttributeToMap(it)
324 } else if(!(value instanceof groovy.json.internal.LazyMap)) {
325 // only add key-value attributes, skip the rest
326 addToMap("$key", "$value")
330 if(parsedData instanceof java.util.ArrayList) {
332 it.each { key, value -> processKeyValue(key, value) }
335 parsedData.each { key, value -> processKeyValue(key, value) }
340 // This closure compares all values for each key from the left map, to values of the same key from the right map.
341 // Returns a map of attributes with mismatched or missing values (i.e. attribute name mapped to list of failed values).
342 Closure<java.util.Map> compareAttributes = { java.util.Map left, java.util.Map right ->
343 java.util.Map violationMap = new java.util.HashMap()
344 left.each{ leftKey, leftValueList ->
345 def rightValueList = right.get("$leftKey")
346 rightValueList.each{ rightValue ->
347 if(!leftValueList.any{ it == "$rightValue" }) {
348 def existingValues = violationMap.get(leftKey)
350 existingValues.add("$rightValue")
352 java.util.Set newValues = new HashSet()
353 newValues.add("$rightValue")
354 violationMap.put("$leftKey", newValues)
362 // This closure merges the given maps into a new map.
363 // Returns a map containing all keys and their values from both maps.
364 Closure<java.util.Map> mergeMaps = { java.util.Map left, java.util.Map right ->
365 if(left.isEmpty() && right.isEmpty()) {
367 } else if(left.isEmpty()) {
369 } else if(right.isEmpty()) {
372 java.util.Map merged = new java.util.HashMap()
374 right.each{ rightKey, rightValues ->
375 java.util.Set mergedValues = merged.get(rightKey)
376 if(mergedValues == null) {
377 merged.put(rightKey, rightValues)
379 mergedValues.addAll(rightValues)
385 def slurper = new groovy.json.JsonSlurper()
386 java.util.Map lhsAttributes = getAttributes(slurper.parseText(lhsObject.toString()))
387 java.util.Map rhsAttributes = getAttributes(slurper.parseText(rhsObject.toString()))
389 def leftToRight = compareAttributes(lhsAttributes, rhsAttributes)
390 def rightToLeft = compareAttributes(rhsAttributes, lhsAttributes)
391 def mergedResults = mergeMaps(leftToRight, rightToLeft)
393 boolean success = true
394 List<String> details = new ArrayList<>()
395 if(!mergedResults.isEmpty()) {
397 details.add(mergedResults.toString())
399 return new Tuple2(success, details)
404 * The data-dictionary rule below can be used with this useRule clause:
406 * name 'Data-Dictionary validate VF type'
407 * attributes 'context-list.ndcb.vnfList[*].vfModuleList[*].networkList[*].type'
411 name 'Data-Dictionary validate VF type'
412 category 'INVALID_VALUE'
413 description 'Validate all VF type values against data-dictionary'
414 errorText 'VF type [{0}] failed data-dictionary validation: {1}'
416 attributes 'typeList'
418 boolean success = true
419 List<String> details = new ArrayList<>()
422 // break out of 'any' loop
425 def result = org.onap.aai.validation.ruledriven.rule.builtin.DataDictionary.validate("instance", "vfModuleNetworkType", "type", "$it")
426 if(!result.isEmpty()) {
429 details.add("$result")
432 return new Tuple2(success, details)