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