Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • a rule name that is unique within the validation service
  • a set of named attributes (arguments)
  • a validation expression, written in the Groovy programming language, that uses the named attributes and evaluates to produce a Boolean value
  • meta-data which will appear in the violation details, including
    • category
    • severity
    • errorText

Examples

Simple Rule

...

Code Block
languagegroovytitleSimple Rule
collapsetrue
Simple Rule Collapse sourceruleentity {
    namename 'POA-EVENT'
  indexing {
    indices 'vnfdefault-namerules'
  }
  validation {
 category   useRule 'INVALID_NAME'{
    description 'Invalid naming conventionname 'vnf-name'
    errorText  attributes 'Invalid name - attribute does not match xxxxxnnnvbc (where x = alphanumeric and n = numeric)context-list.sdc.vfList[*].name'
    }
  }
}


rule {
    name        'vnf-name'
    severitycategory    'MINORINVALID_NAME'
    description attributes'Invalid naming 'nameconvention'
    validateerrorText   'Invalid 'name != null && name.matches("[a-z,0-9]{5}[0-9]{3}vbc")'
}

Complex Rule Example

The following example defines a rule that :

  • accepts two attributes
  • uses expandable error text
  • uses a triple-quoted validate section to allow multiple lines
  • defines multiple closures
name - attribute does not match xxxxxnnnvbc (where x = alphanumeric and n = numeric)'
    severity    'MINOR'
    attributes  'name'
    validate    'name != null && name.matches("[a-z,0-9]{5}[0-9]{3}vbc")'
}

Complex Rule

The following example defines a rule that :

  • accepts two attributes
  • uses expandable error text
  • uses a triple-quoted validate section to allow multiple lines
  • defines multiple closures
Code Block
languagegroovy
collapsetrue
entity {
  name 'POA-EVENT'
  indexing {
    indices 'default-rules'
  }
  validation {
    useRule {
      name 'NDCB-AAI-attribute-comparison
Code Block
languagegroovy
titleComplex Rule
collapsetrue
rule {
  name        'NDCB-AAI-attribute-comparison'
  category    'Attribute Mismatch'
  description 'Verify that all attributes in Network-Discovery are the same as in AAI'
  errorText   'Error found with attribute "{0}"; value "{1}" does not exist in Network-Discovery'
  severity    'ERROR'
  attributes  'ndcbItems', 'aaiItems'
  validate    '''
      attributes  Closure<java.util.Map> getAttributes = { parsedData ->
     'context-list.ndcb.vfList[*].vfModuleList[*]', 'context-list.aai.vfList[*].vfModuleList[*]'
    }
  }
}


rule {
  name     java.util.Map attributeMap = new java.util.HashMap()
 'NDCB-AAI-attribute-comparison'
  category    'Attribute Mismatch'
  description def'Verify isAttributeDataQualityOkthat =all {attributes attributein ->
      Network-Discovery are the same as in AAI'
  errorText   'Error found with attribute.findResult{ k, v -> if(k.equals("dataQuality") ) {return v.get("status")}}.equals("ok")
          }

          def addToMap = { attrKey, attrValue ->
   "{0}"; value "{1}" does not exist in Network-Discovery'
  severity    'ERROR'
  attributes  'ndcbItems', 'aaiItems'
  validate    '''
        Closure<java.util.Map> getAttributes = { parsedData ->
          java.util.SetMap valuesattributeMap = new attributeMapjava.util.getHashMap("$attrKey")

          def  if(valuesisAttributeDataQualityOk == null) {
 attribute ->
            values = new java.util.HashSet(attribute.findResult{ k, v -> if(k.equals("dataQuality") ) {return v.get("status")}}.equals("ok")
           }

   attributeMap.put("$attrKey", values)
      def addToMap = { attrKey, attrValue }->
            java.util.Set values = attributeMap.addget("$attrValue$attrKey")
          }

  if(values == null) {
     def addAttributeToMap = { attribute ->
    values = new java.util.HashSet()
     if(isAttributeDataQualityOk(attribute)) {
        attributeMap.put("$attrKey", values)
     String    key, value
  }
            attribute.each { k, v ->
values.add("$attrValue")
          }

          if(k.equals("name")) {keydef addAttributeToMap = "$v"}
{ attribute   ->
            if(k.equals("value")isAttributeDataQualityOk(attribute)) {value
 = "$v"}
            String key, }value
              addToMap("$key", "$value")
   attribute.each { k, v ->
         }
       if(k.equals("name")) {key = "$v"}

          def processKeyValue = { key, value -> if(k.equals("value")) {value = "$v"}
            if(value instanceof java.util.ArrayList) { }
              if(key.equals("attributeList")) {addToMap("$key", "$value")
            }
    value.each {
     }

          def processKeyValue  addAttributeToMap(it)= { key, value ->
            if(value instanceof java.util.ArrayList) {
 }
              }if(key.equals("attributeList")) {
            } else if(!(value instanceof groovy.json.internal.LazyMap))value.each {
               // only add key-value attributes, skip the rest
 addAttributeToMap(it)
                  addToMap("$key", "$value")
}
              }
            }

 else if(!(value instanceof groovy.json.internal.LazyMap)) {
             if(parsedData instanceof java.util.ArrayList) {
            parsedData.each// only add key-value attributes, skip the rest
              addToMap("$key", "$value")
            }
          }

          if(parsedData instanceof java.util.ArrayList) {
            parsedData.each {
              it.each { key, value -> processKeyValue(key, value) }
            }
          } else {
            parsedData.each { key, value -> processKeyValue(key, value) }
          }
          return attributeMap
        }

        def slurper = new groovy.json.JsonSlurper()
        java.util.Map ndcb = getAttributes(slurper.parseText(ndcbItems.toString()))
        java.util.Map aai = getAttributes(slurper.parseText(aaiItems.toString()))

        boolean result = true
        List<String> details = new ArrayList<>();
        ndcb.any{ ndcbKey, ndcbValueList ->
          def aaiValueList = aai.get("$ndcbKey")
          aaiValueList.each{ aaiValue ->
            if(!ndcbValueList.any{ it == "$aaiValue" }) {
              result = false
              details.add("$ndcbKey")
              details.add("$aaiValue")
            }
          }
          if(result == false) {
            // break out of 'any' loop
            return true
          }
        }
        return new Tuple2(result, details)
        '''
}

Data-Dictionary rule

The following example defines a rule that uses the data-dictionary interfaced defined here.

By default, the URI template is configured as "/commonModelElements/{0}~{1}~1.0/validateInstance"

With the arguments used for calling validate() below, the resulting URL would be: [ddict-host:port]/commonModelElements/instance~vfModuleNetworkType~1.0/validateInstance

And the body would be:  {"type" : "some-value"}

Code Block
languagegroovy
collapsetrue
entity {
  name 'POA-EVENT'
  indexing {
              it.each { key, value -> processKeyValue(key, value)indices 'default-rules'
  }
       validation {
    useRule }{
      name 'Data-Dictionary validate VF }type'
 else {
    attributes 'context-list.ndcb.vfList[*].vfModuleList[*].networkList[*].type'
    }
   parsedData.each { key, value -> processKeyValue(key, value) }
}
}


rule {
    name        'Data-Dictionary validate VF }type'
    category    'INVALID_VALUE'
  return attributeMap
 description 'Validate all VF type values  }
against data-dictionary'
    errorText   'VF def slurper = new groovy.json.JsonSlurper()type [{0}] failed data-dictionary validation: {1}'
    severity    java.util.Map ndcb = getAttributes(slurper.parseText(ndcbItems.toString()))
   'ERROR'
    attributes  'typeList'
    validate java.util.Map aai = getAttributes(slurper.parseText(aaiItems.toString()))
 '''
        boolean resultsuccess = true
        List<String> details = new ArrayList<>();
        ndcbtypeList.any{ ndcbKey, ndcbValueList -> {
          def aaiValueList = aai.get("$ndcbKey")
    if(!success) {
      aaiValueList.each{ aaiValue ->
        // break   if(!ndcbValueList.any{ it == "$aaiValue" }) {
out of 'any' loop
               result =return false
            }
  details.add("$ndcbKey")
          def result   details.add("$aaiValue")
   = org.onap.aai.validation.ruledriven.rule.builtin.DataDictionary.validate("instance", "vfModuleNetworkType", "type", "$it")
         }
   if(!result.isEmpty()) {
      }
          if(resultsuccess == false)
  {
            // break out of 'any' loop
 details.add("$it")
               return true
 details.add("$result")
            }
        }
        return new Tuple2(resultsuccess, details)
        '''
}



Entity Configuration


The entity configuration element defines which rules are applied to a specific entity type. The configuration is comprised of the following properties:

type / indexing

if using type, the value is a unique name of the type of entity

if using indexing, the value is a list of runtime indices extracted from the event; or a pre-configured default value

validationthe set of rules to apply to this entity and (for each rule) the attributes to be read from the entity (in order to create the rule's arguments)

The validation comprises a set of useRule elements. Each specifies a rule to be applied to the entity.

...

This element is repeated within the validation element as illustrated in the example below. The following properties may be defined:

name(Mandatory)The name of the rule to apply to this entity. This rule must be defined within a.groovy file stored in the rules directory.
The referenced rule does not need to be defined in the same file as the entity.
attributes(Optional)A comma-separated list of attribute(s) to extract from the entity. Each list item is a string storing a (JSON) path within the entity. The path is used to extract a value (or set of values) to be passed to the rule as an argument. Therefore the number of attributes defined must match with the number of attributes defined by the rule.
If the attribute specifiers are omitted then the attribute paths are implicitly taken from the rule definition.

Example entity

Code Block
languagegroovy
titleExample entity configurationcollapsetrue
entity {
	type 'complex'
	validation {
		useRule {
			name 'CLLI'
			attributes 'physical-location-id'
		}
		useRule {name 'complex is related to 1 oam-network' }
		useRule {
			name 'if a customer is related to an oam-network then oam-network.network-name must match naming convention'
			attributes 'relationship-list.relationship[*]'
		}
	}
}

...

Rules are determined based on the incoming event's values

model-version-idmodel-invariant-idRule
version-1invariant-1rule-1
version-2invariant-2rule-2
version-1invariant-2default-rule
version-3invariant-3default-rule

Configuration

The event type and attributes must be pre-configured. The attributes are defined as JSON path expression within an event entity.

...