enable sparky to interact with schema ms and aaf
[oom.git] / kubernetes / pomba / charts / pomba-validation-service / resources / bundleconfig / etc / rules / poa-event / default-rules.groovy
1 /*
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
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  * ============LICENSE_END=====================================================
17  */
18
19 entity {
20     name 'POA-EVENT'
21     indexing {
22         indices 'default-rules'
23     }
24   validation {
25
26     // NDCB-AAI comparison: Context level
27     useRule {
28       name 'Attribute-comparison'
29       attributes 'context-list.ndcb', 'context-list.aai'
30     }
31
32     // NDCB-AAI comparison: Service entity
33     useRule {
34       name 'Attribute-comparison'
35       attributes 'context-list.ndcb.service', 'context-list.aai.service'
36     }
37
38     // NDCB-AAI comparison: Context level network list
39     useRule {
40       name 'Attribute-comparison'
41       attributes 'context-list.ndcb.networkList[*]', 'context-list.aai.networkList[*]'
42     }
43         
44     // NDCB-AAI comparison: VNF list
45     useRule {
46       name 'Attribute-comparison'
47       attributes 'context-list.ndcb.vnfList[*]', 'context-list.aai.vnfList[*]'
48     }
49
50     // NDCB-AAI comparison: VNF network list
51     useRule {
52       name 'Attribute-comparison'
53       attributes 'context-list.ndcb.vnfList[*].networkList[*]', 'context-list.aai.vnfList[*].networkList[*]'
54     }
55         
56     // NDCB-AAI comparison: VF-Module list
57     useRule {
58       name 'Attribute-comparison'
59       attributes 'context-list.ndcb.vnfList[*].vfModuleList[*]', 'context-list.aai.vnfList[*].vfModuleList[*]'
60     }
61
62     // NDCB-AAI comparison: VF-Module network list
63     useRule {
64       name 'Attribute-comparison'
65       attributes 'context-list.ndcb.vnfList[*].vfModuleList[*].networkList[*]', 'context-list.aai.vnfList[*].vfModuleList[*].networkList[*]'
66     }
67
68     // NDCB-AAI comparison: VNFC list
69     useRule {
70       name 'Attribute-comparison'
71       attributes 'context-list.ndcb.vnfList[*].vnfcList[*]', 'context-list.aai.vnfList[*].vnfcList[*]'
72     }
73
74     // NDCB-AAI comparison: VM list
75     useRule {
76       name 'Attribute-comparison'
77       attributes 'context-list.ndcb.vnfList[*].vfModuleList[*].vmList[*]', 'context-list.aai.vnfList[*].vfModuleList[*].vmList[*]'
78     }
79         
80         
81     // SDNC-AAI comparison: Context level
82     useRule {
83       name 'Attribute-comparison'
84       attributes 'context-list.sdnc', 'context-list.aai'
85     }
86
87     // SDNC-AAI comparison: Service entity
88     useRule {
89       name 'Attribute-comparison'
90       attributes 'context-list.sdnc.service', 'context-list.aai.service'
91     }
92
93     // SDNC-AAI comparison: Context level network list
94     useRule {
95       name 'Attribute-comparison'
96       attributes 'context-list.sdnc.networkList[*]', 'context-list.aai.networkList[*]'
97     }
98
99     // SDNC-AAI comparison: VNF list
100     useRule {
101       name 'Attribute-comparison'
102       attributes 'context-list.sdnc.vnfList[*]', 'context-list.aai.vnfList[*]'
103     }
104
105     // SDNC-AAI comparison: VNF network list
106     useRule {
107       name 'Attribute-comparison'
108       attributes 'context-list.sdnc.vnfList[*].networkList[*]', 'context-list.aai.vnfList[*].networkList[*]'
109     }
110
111     // SDNC-AAI comparison: VF-Module list
112     useRule {
113       name 'Attribute-comparison'
114       attributes 'context-list.sdnc.vnfList[*].vfModuleList[*]', 'context-list.aai.vnfList[*].vfModuleList[*]'
115     }
116
117     // SDNC-AAI comparison: VF-Module network list
118     useRule {
119       name 'Attribute-comparison'
120       attributes 'context-list.sdnc.vnfList[*].vfModuleList[*].networkList[*]', 'context-list.aai.vnfList[*].vfModuleList[*].networkList[*]'
121     }
122
123     // SDNC-AAI comparison: VNFC list
124     useRule {
125       name 'Attribute-comparison'
126       attributes 'context-list.sdnc.vnfList[*].vnfcList[*]', 'context-list.aai.vnfList[*].vnfcList[*]'
127     }
128
129     // SDNC-AAI comparison: VM list
130     useRule {
131       name 'Attribute-comparison'
132       attributes 'context-list.sdnc.vnfList[*].vfModuleList[*].vmList[*]', 'context-list.aai.vnfList[*].vfModuleList[*].vmList[*]'
133     }
134
135     // AAI-SDNC PNF name validation
136     useRule {
137       name 'AAI-SDNC-pnf-name-check'
138       attributes 'context-list.aai.pnfList[*].name', 'context-list.sdnc.pnfList[*].name'
139     }
140
141
142     // SDNC-NDCB comparison: Context level
143     useRule {
144       name 'Attribute-comparison'
145       attributes 'context-list.sdnc', 'context-list.ndcb'
146     }
147
148     // SDNC-NDCB comparison: Service entity
149     useRule {
150       name 'Attribute-comparison'
151       attributes 'context-list.sdnc.service', 'context-list.ndcb.service'
152     }
153
154     // SDNC-NDCB comparison: Context level network list
155     useRule {
156       name 'Attribute-comparison'
157       attributes 'context-list.sdnc.networkList[*]', 'context-list.ndcb.networkList[*]'
158     }
159
160     // SDNC-NDCB comparison: VNF list
161     useRule {
162       name 'Attribute-comparison'
163       attributes 'context-list.sdnc.vnfList[*]', 'context-list.ndcb.vnfList[*]'
164     }
165
166     // SDNC-NDCB comparison: VNF network list
167     useRule {
168       name 'Attribute-comparison'
169       attributes 'context-list.sdnc.vnfList[*].networkList[*]', 'context-list.ndcb.vnfList[*].networkList[*]'
170     }
171
172     // SDNC-NDCB comparison: VF-Module list
173     useRule {
174       name 'Attribute-comparison'
175       attributes 'context-list.sdnc.vnfList[*].vfModuleList[*]', 'context-list.ndcb.vnfList[*].vfModuleList[*]'
176     }
177
178     // SDNC-NDCB comparison: VF-Module network list
179     useRule {
180       name 'Attribute-comparison'
181       attributes 'context-list.sdnc.vnfList[*].vfModuleList[*].networkList[*]', 'context-list.ndcb.vnfList[*].vfModuleList[*].networkList[*]'
182     }
183
184     // SDNC-NDCB comparison: VNFC list
185     useRule {
186       name 'Attribute-comparison'
187       attributes 'context-list.sdnc.vnfList[*].vnfcList[*]', 'context-list.ndcb.vnfList[*].vnfcList[*]'
188     }
189
190     // SDNC-NDCB comparison: VM list
191     useRule {
192       name 'Attribute-comparison'
193       attributes 'context-list.sdnc.vnfList[*].vfModuleList[*].vmList[*]', 'context-list.ndcb.vnfList[*].vfModuleList[*].vmList[*]'
194     }
195
196         
197         
198     // SDC-AAI VNFC type
199     useRule {
200       name 'SDC-AAI-vnfc-type'
201       attributes 'context-list.sdc.vnfList[*].vnfcList[*]', 'context-list.aai.vnfList[*].vnfcList[*]'
202     }
203
204     // SDC-AAI VNFC node count
205     useRule {
206       name 'SDC-AAI-vnfc-node-count'
207       attributes 'context-list.sdc.vnfList[*].vnfcList[*]', 'context-list.aai.vnfList[*].vnfcList[*]'
208     }
209
210     // SDC-AAI VF-Module instance
211     useRule {
212       name 'SDC-AAI-vf-module-instance-check'
213       attributes 'context-list.sdc.vnfList[*].vfModuleList[*]', 'context-list.aai.vnfList[*].vfModuleList[*]'
214     }
215   }
216 }
217
218 rule {
219   name        'SDC-AAI-vnfc-type'
220   category    'VNFC Consistency'
221   description 'Validate that each VNFC instance in AAI conforms to a VNFC type defined in SDC model'
222   errorText   'AAI VNFC instance includes non-specified type in design SDC model'
223   severity    'ERROR'
224   attributes  'sdcList', 'aaiList'
225   validate    '''
226         def getVnfcTypes = { parsedData ->
227           parsedData.collect{ it.findResult{ k, v -> if(k.equals("type")) {return "$v"}}}
228         }
229
230         def slurper = new groovy.json.JsonSlurper()
231         def sdcTypes = getVnfcTypes(slurper.parseText(sdcList.toString()))
232         def aaiTypes = getVnfcTypes(slurper.parseText(aaiList.toString()))
233
234         // each type in AAI must exist in SDC
235         return sdcTypes.containsAll(aaiTypes)
236                 '''
237 }
238
239 rule {
240   name        'SDC-AAI-vnfc-node-count'
241   category    'VNFC Consistency'
242   description 'Validate that for each VNFC node defined in SDC model, there is at least one VNFC instance in AAI'
243   errorText   'Design has specified types but not all of them exist in AAI'
244   severity    'WARNING'
245   attributes  'sdcList', 'aaiList'
246   validate    '''
247         def getVnfcNodes = { parsedData ->
248           parsedData.collect { new Tuple2(
249               it.findResult{ k, v -> if(k.equals("name")) {return "$v"}},
250               it.findResult{ k, v -> if(k.equals("type")) {return "$v"}})
251           }
252         }
253
254         def slurper = new groovy.json.JsonSlurper()
255         def sdcNodes = getVnfcNodes(slurper.parseText(sdcList.toString()))
256         def aaiNodes = getVnfcNodes(slurper.parseText(aaiList.toString()))
257
258         // each node in AAI must exist in SDC
259         return aaiNodes.containsAll(sdcNodes)
260                 '''
261 }
262
263 rule {
264   name        'SDC-AAI-vf-module-instance-check'
265   category    'VF Consistency'
266   description 'Validate that each VF module instance in AAI conforms to a VF module defined in SDC service model'
267   errorText   'One or more AAI VF module instance(s) not defined in SDC model'
268   severity    'CRITICAL'
269   attributes  'sdcList', 'aaiList'
270   validate    '''
271         def getVfModules = { parsedData ->
272           parsedData.collect{ it.findResult{ k, v -> if(k.equals("name")) {return "$v"}}}
273         }
274
275         def slurper = new groovy.json.JsonSlurper()
276         def sdcVfModules = getVfModules(slurper.parseText(sdcList.toString()))
277         def aaiVfModules = getVfModules(slurper.parseText(aaiList.toString()))
278
279         // all VF modules in AAI must exist in SDC
280         return aaiVfModules.containsAll(sdcVfModules)
281                 '''
282 }
283
284 rule {
285   name        'Attribute-comparison'
286   category    'Attribute Mismatch'
287   description 'Determine all discrepancies between values for attributes with matching names from each model'
288   errorText   'Error found with attribute(s) and values: {0}'
289   severity    'ERROR'
290   attributes  'lhsObject', 'rhsObject'
291   validate    '''
292                 // This closure extracts the given object's root level attributes and contents of the attribute list.
293                 // Complex items like lists are excluded.
294                 // Returns a map containing attribute names as keys, mapping to a list of values for each attribute.
295                 Closure<java.util.Map> getAttributes = { parsedData ->
296                         java.util.Map attributeMap = new java.util.HashMap()
297
298                         def isAttributeDataQualityOk = { attribute ->
299                                 attribute.findResult{ k, v -> if(k.equals("dataQuality") ) {return v.get("status")}}.equals("ok")
300                         }
301
302                         def addToMap = { attrKey, attrValue ->
303                                 java.util.Set values = attributeMap.get("$attrKey")
304                                 if(values == null) {
305                                         values = new java.util.HashSet()
306                                         attributeMap.put("$attrKey", values)
307                                 }
308                                 values.add("$attrValue")
309                         }
310
311                         def addAttributeToMap = { attribute ->
312                                 if(isAttributeDataQualityOk(attribute)) {
313                                         String key, value
314                                         attribute.each { k, v ->
315                                                 if(k.equals("name")) {key = "$v"}
316                                                 if(k.equals("value")) {value = "$v"}
317                                         }
318                                         addToMap("$key", "$value")
319                                 }
320                         }
321
322                         def processKeyValue = { key, value ->
323                                 if(value instanceof java.util.ArrayList) {
324                                         if(key.equals("attributeList")) {
325                                                 value.each {
326                                                         addAttributeToMap(it)
327                                                 }
328                                         }
329                                 } else if(!(value instanceof groovy.json.internal.LazyMap)) {
330                                         // only add key-value attributes, skip the rest
331                                         addToMap("$key", "$value")
332                                 }
333                         }
334
335                         if(parsedData instanceof java.util.ArrayList) {
336                                 parsedData.each {
337                                         it.each { key, value -> processKeyValue(key, value) }
338                                 }
339                         } else {
340                                 parsedData.each { key, value -> processKeyValue(key, value) }
341                         }
342                         return attributeMap
343                 }
344
345                 // This closure compares all values for each key from the left map, to values of the same key from the right map.
346                 // Returns a map of attributes with mismatched or missing values (i.e. attribute name mapped to list of failed values).
347                 Closure<java.util.Map> compareAttributes = { java.util.Map left, java.util.Map right ->
348                         java.util.Map violationMap = new java.util.HashMap()
349                         left.each{ leftKey, leftValueList ->
350                                 def rightValueList = right.get("$leftKey")
351                                 rightValueList.each{ rightValue ->
352                                         if(!leftValueList.any{ it == "$rightValue" }) {
353                                                 def existingValues = violationMap.get(leftKey)
354                                                 if(existingValues) {
355                                                         existingValues.add("$rightValue")
356                                                 } else {
357                                                         java.util.Set newValues = new HashSet()
358                                                         newValues.add("$rightValue")
359                                                         violationMap.put("$leftKey", newValues)
360                                                 }
361                                         }
362                                 }
363                         }
364                         return violationMap
365                 }
366
367                 // This closure merges the given maps into a new map.
368                 // Returns a map containing all keys and their values from both maps.
369                 Closure<java.util.Map> mergeMaps = { java.util.Map left, java.util.Map right ->
370                         if(left.isEmpty() && right.isEmpty()) {
371                                 return [:]
372                         } else if(left.isEmpty()) {
373                                 return right
374                         } else if(right.isEmpty()) {
375                                 return left
376                         }
377                         java.util.Map merged = new java.util.HashMap()
378                         merged.putAll(left)
379                         right.each{ rightKey, rightValues ->
380                                 java.util.Set mergedValues = merged.get(rightKey)
381                                 if(mergedValues == null) {
382                                         merged.put(rightKey, rightValues)
383                                 } else {
384                                         mergedValues.addAll(rightValues)
385                                 }
386                         }
387                         return merged
388                 }
389
390                 def slurper = new groovy.json.JsonSlurper()
391                 java.util.Map lhsAttributes = getAttributes(slurper.parseText(lhsObject.toString()))
392                 java.util.Map rhsAttributes = getAttributes(slurper.parseText(rhsObject.toString()))
393
394                 def leftToRight = compareAttributes(lhsAttributes, rhsAttributes)
395                 def rightToLeft = compareAttributes(rhsAttributes, lhsAttributes)
396                 def mergedResults = mergeMaps(leftToRight, rightToLeft)
397
398                 boolean success = true
399                 List<String> details = new ArrayList<>()
400                 if(!mergedResults.isEmpty()) {
401                         success = false
402                         details.add(mergedResults.toString())
403                 }
404                 return new Tuple2(success, details)
405         '''
406 }
407
408 /*
409  * The data-dictionary rule below can be used with this useRule clause:
410  *   useRule {
411  *     name 'Data-Dictionary validate VF type'
412  *     attributes 'context-list.ndcb.vnfList[*].vfModuleList[*].networkList[*].type'
413  *   }
414  */
415 rule {
416     name        'Data-Dictionary validate VF type'
417     category    'INVALID_VALUE'
418     description 'Validate all VF type values against data-dictionary'
419     errorText   'VF type [{0}] failed data-dictionary validation: {1}'
420     severity    'ERROR'
421     attributes  'typeList'
422     validate    '''
423         boolean success = true
424         List<String> details = new ArrayList<>()
425         typeList.any {
426             if(!success) {
427                 // break out of 'any' loop
428                 return false
429             }
430             def result = org.onap.aai.validation.ruledriven.rule.builtin.DataDictionary.validate("instance", "vfModuleNetworkType", "type", "$it")
431             if(!result.isEmpty()) {
432                 success = false
433                 details.add("$it")
434                 details.add("$result")
435             }
436         }
437         return new Tuple2(success, details)
438         '''
439 }
440
441 rule {
442   name        'AAI-SDNC-pnf-name-check'
443   category    'PNF Consistency'
444   description 'Validate that each PNF name in AAI matches a PNF name in the SDNC model'
445   errorText   'AAI PNF names do not match SDNC - {0}'
446   severity    'ERROR'
447   attributes  'aaiNames', 'sdncNames'
448   validate    '''
449         def addName = { values, key ->
450                 values.add("$key")
451         }
452
453         List<String> errorReasons = new ArrayList();
454
455         if (aaiNames.size() != sdncNames.size()) {
456             errorReasons.add("Number of PNFs don't match; aai has ${aaiNames.size()}, sdnc has ${sdncNames.size()}")
457             return new Tuple2(false, errorReasons)
458         }
459
460         // collect all the "name" values from AAI and SDNC into two Sets.
461         Set aaiNameSet = new java.util.HashSet()
462         aaiNames.each {
463            aValue -> addName(aaiNameSet, aValue)
464         }
465
466         Set sdncNameSet = new java.util.HashSet()
467         sdncNames.each {
468             aValue -> addName(sdncNameSet, aValue)
469         }
470
471         // Validate that the names match by comparing the size of the two Sets.
472         if (aaiNameSet.size() != sdncNameSet.size()) {
473             errorReasons.add("Number of distinct PNF names don't match; aai: ${aaiNameSet}, sdnc: ${sdncNameSet}")
474             return new Tuple2(false, errorReasons)
475         }
476
477         Set combinedSet = new HashSet();
478         combinedSet.addAll(aaiNameSet);
479         combinedSet.addAll(sdncNameSet);
480         if (combinedSet.size() != aaiNameSet.size()) {
481             errorReasons.add("PNF names don't match; aai names: ${aaiNameSet}, sdnc names: ${sdncNameSet}")
482             return new Tuple2(false, errorReasons)
483         }
484
485         return true
486
487         '''
488 }