Fresh Updates for Data Validation Engine

Blog Detail

A fresh release brings several exciting new features to the Data Validation Engine Nautobot app!

For those who have not yet used the Data Validation Engine app in their Nautobot deployment, I’ll start with a quick overview. Data Validation Engine (I’ll refer to it as ‘DVE’ for short) provides users with a simple, customizable way to define and enforce business rules on their data within Nautobot. Rather than having a limited set of predetermined constraints that are hardcoded into Nautobot’s source code, DVE allows you to define what rules are important and create any data boundaries you’d like right within the Nautobot UI. No programming or coding required! This also enables the capability to set additional validation rules on top of your own database constraints. The rule validation applies to the Nautobot GUI, API, and even the ORM when validated_save is called.

Say your enterprise has standards for how a new device should be named. For example, the device name must follow a specific pattern like aaa00-descriptor-01, where aaa is a three-character location, 00 is an optional location number, descriptor is some text for the device of varying length, and 01 is the unit number (e.g., nyc00-rtr-03 or sfo01-fw-01). With DVE, this requirement can be easily created and enforced whenever someone goes to create a new device. With Nautobot as your company’s Source of Truth (SoT), the importance of clean and consistent data to achieving network automation cannot be overstated! The Data Validation Engine app provides a simple, user-friendly way to ensure data that is added meets all your standards.

In version 1.0 of Data Validation Engine, we introduced two rule types—Min/Max Rules and Regular Expression Rules. You can read more about these and see additional examples in the app’s User Guide and the Data Validation Engine introductory blog post.

In the most recent 2.X releases, we added:

  • Required Rules
  • Unique Rules
  • Data Compliance

Required Rules

Required Rules allow users to make specific fields within data objects required in just a few simple clicks. Imagine your manager wants to ensure that all devices being added to Nautobot have a serial number. By default within the Device object, the serial number field is optional. However, with the extensibility power that the Nautobot app ecosystem offers, you can install Data Validation Engine and create a Required Rule that enforces this custom requirement.

The DVE rules are found under the ‘Extensibility’ dropdown, where you can click to add a new Required Rule.

We’ll name this rule Device Serial Number, select the dcim | device content type, and enter serial as the field that we want to make required. We’ll also add a helpful error message, should the user not add a value.

After clicking “Create”, we can now see our newly added Required Rule.

Let’s try it out! We’ll go add a new device and will leave the Serial number field empty when we click “Create”. And, just like that, we’ve successfully made the field required and get our helpful reminder to add the serial number!

The DVE rules are also enforced in the use of the Nautobot API, in addition to the GUI. With the Device Serial Number required rule enabled, if we try to send this API request without including a value for serial number:

POST /api/dcim/devices/ HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Authorization: Token 0123456789abcdef0123456789abcdef01234567

{
    "name": "ams01-leaf-09",
    "device_type": {
        "model": "DCS-7150S-24"
    },
    "device_role": {
        "name": "leaf"
    },
    "site": {
        "name": "AMS01"
    },
    "status": "Active"
}

The following 400: BAD REQUEST response is returned:

{
    "serial": [
        "Please enter the serial number for the device!"
    ]
}

Unique Rules

Unique Rules enable you to enforce uniqueness on object fields of your choice. Let’s continue with the example from before. Pretend your manager also wants to enforce data validation that prevents duplicate device serial numbers within Nautobot.

Under the ‘Extensibility’ dropdown again, we’ll add a new Unique Rule.

Let’s call this Unique Serial Number. It will again be applied to the dcim | device content type and the serial field. We’ll set the Max instances value to 1, but it’s important to note that this can be modified for your specific implementation. For example, you could create a Unique Rule that limits the allowed occurrences of a specific value for a field to no more than 3 or whatever number you’d like. We’ll then add an optional error message and click “Create”.

Also, please note that although these examples apply rules to the dcim | device serial number field, the available object/field options you can create rules for are not limited.

Now that we have our Unique Serial Number rule created, we can test it. I added the serial number SN123ABC to an existing device and will now try adding that same value to another one.

As expected, we’re prevented from adding a duplicate serial number thanks to our Unique Serial Number rule!

Data Compliance

One of the more exciting features that was released in Data Validation Engine v2.1.0 is Data Compliance. Data Compliance can audit any object within Nautobot according to a set of rules that you can define programmatically with simple, straightforward Python code. Unlike the other rule types within DVE that only check for adherence to specified rules during the creation or modification of objects, Data Compliance will run a job that produces compliance statuses across all objects, including already existing ones (such as all preexisting devices).

This is ideal for implementing some kind of business logic or standardization requirement into Nautobot after data is already populated within the platform. Data Compliance will allow you to identify valid or invalid objects based on your specified data compliance rules. Additionally, Data Compliance has the capability to implement more complex rules using the full power of programming logic. For the technical details of how it works, check out this section in the docs.

Let’s walk through a step-by-step example of how you can implement and use it.

Step 1. Create the Data Compliance Rules

First, you’ll want to create your desired data compliance rules following whatever programming logic you want. These compliance rules will be included as methods within one or more classes that implement DataComplianceRule.

For our example, let’s create these two rules that check devices for the following:

  • audit_device_name_chars – will mark a device invalid if the device name contains any special characters other than a dash (-), underscore (_), or period (.)
  • audit_device_rack – will mark a device invalid if it is not assigned to a rack

There are two options on where to include the data compliance rule classes:

  1. In a remote Git repository (recommended)
  2. In the app’s code

Writing Data Compliance Rules in a Remote Git Repository

A Git repository can be configured to add the data compliance rules context to store DataComplianceRule classes in source control. The app looks for a folder in your remote repo called custom_validators, and any Python files within that folder containing classes that implement DataComplianceRule will be imported. No code within the app itself needs to be added, changed, or removed.

Below is the example data compliance rule class that I’ll store as custom_validators/my_data_compliance_rules.py in my remote Git repository named dve-datacompliance-demo:

import re
from nautobot_data_validation_engine.custom_validators import DataComplianceRule, ComplianceError

class DeviceDataComplianceRules(DataComplianceRule):
    model = "dcim.device"
    enforce = False
    
    # Checks if a device name contains any special characters other than a dash (-), underscore (_), or period (.) using regex
    def audit_device_name_chars(self):
        if not re.match("^[a-zA-Z0-9\-_.]+$", self.context["object"].name):
            raise ComplianceError({"name": "Device name contains unallowed special characters."})
    
    # Checks if a device is not assigned to a rack
    def audit_device_rack(self):
        if not self.context["object"].rack:
            raise ComplianceError({"rack": "Device should be assigned to a rack."})
    
    def audit(self):
        messages = {}
        for fn in [self.audit_device_name_chars, self.audit_device_rack]:
            try:
                fn()
            except ComplianceError as ex:
                messages.update(ex.message_dict)
        if messages:
            raise ComplianceError(messages)

After the Git repo is configured and rule class(es) written, add the repository to Nautobot from Extensibility -> Data Sources -> Git Repositories. Include the remote repo URL, as well as credentials if it’s not public (recommend using Nautobot Secrets for this). Also select data compliance rules for the ‘provides’ field. Then, we just use Nautobot’s Git Repositories Sync feature, and our Data Compliance rules will be automatically imported.

Writing Data Compliance Rules within the App

To write data compliance rules within the app’s code itself, add the classes that implement DataComplianceRule within nautobot_data_validation_engine/custom_validators.py.

You can use the same code snippet from above, and the only additional task will be to modify the existing custom_validators variable by casting CustomValidatorIterator() to a list and then appending the classes to it:

custom_validators = list(CustomValidatorIterator()) + [DeviceDataComplianceRules]

Step 2. Run theRunRegisteredDataComplianceRulesJob

We’ll now go to Nautobot Jobs and run the RunRegisteredDataComplianceRules job. In the pre-job settings, you can select the individual data compliance rule classes you’d like to run at that time. Otherwise, not selecting/highlighting any will default to running them all.

The job can be used to run the audit method for any number of registered DataComplianceRule classes in an ad hoc fashion. This can be used to run the data compliance rules for the first time over a set of objects or to rerun the rules after an update to the compliance logic.

Step 3. Viewing Data Compliance Results

All data compliance result objects can be found on the navigation bar under Extensibility -> Data Validation Engine -> Data Compliance. This view lists all available data compliance results produced from the RunRegisteredDataComplianceRules job.

You can add filters such as showing only invalid objects or only ones from a specific compliance rule class. Let’s filter on only the objects that are out of compliance.

Additionally, the nautobot_data_validation_engine app automatically creates template extensions to add a Data Compliance tab to the detail view of all objects. This tab makes it easy to check an individual object’s compliance with any applicable data compliance rules.

We can see that this device has an invalid name and is not assigned to a rack. Let’s fix these two things. After editing the device to correct the noncompliance, it’s automatically rechecked and is now valid and in compliance:

Note: A second job, DeleteOrphanedDataComplianceData, associated with Data Compliance can be run to remove/clean up any data compliance results that might be left dangling over time due to the parent object having since been deleted.


Conclusion

We’re super excited to share these new updates with you! You can find the full documentation for Data Validation Engine here. Additionally, checkout demo.nautobot.com to play around with the app and try out these new features. Everything discussed above is available now from release v2.1.0 onward. If you have any ideas, feedback, or wants for the Data Validation Engine app, feel free to interact at github.com/nautobot/nautobot-plugin-data-validation-engine.

As always, happy automating!

-Steven



ntc img
ntc img

Contact Us to Learn More

Share details about yourself & someone from our team will reach out to you ASAP!

Keeping Data Clean with Nautobot Config Contexts, Schemas, and Git

Blog Detail

Nautobot is an extensible Source of Truth with a focus on clean network automation data. In a network automation context, clean data is correct (error-free) and properly formatted to be usable by the automation.

Nautobot’s Config ContextsConfig Context Schemas, and Git as a data source extensibility features help ensure data is clean when it is imported into Nautobot and stays clean once it is there. This post discusses the use cases of each feature and how each makes data cleaner. This post will also demonstrate how to import Config Contexts and Config Context Schemas into Nautobot from a Git repository.

Config Contexts

Nautobot’s configuration contexts are used to assign attributes to one or more devices based on some type of context for that device. By “context”, we mean some characteristic of not just the device, but of the device’s circumstances. For example, when a device resides in a certain region or site, there may be special or unique attributes the device needs to inherit that are specific to the region or site.

Config contexts make contextual data easy to associate to devices, which helps minimize errors.

Note: Nautobot has built-in models to hold data for object instances (those objects in DCIM, IPAM, VLANs, etc.), but config contexts allow users to store structured, but unmodeled (by default), data tied to an object.

Nautobot’s Config Context documentation uses syslog servers as an example: devices in a given region need to have region-specific syslog servers configured.

For this demo, we’ll add two config contexts to Nautobot:

  • One for United States regional NTP and syslog servers, which should apply to all devices in the region
  • One for the atl site syslog servers, which should be used only for devices in the atl site, instead of the regional syslog servers

To create a config context, from the top menu navigate to Extensibility–>Config Contexts–> +.

The United States regional data for the NTP and syslog servers will:

  • Have a weight of 1000
  • Apply to all devices in the United States region
Config Contexts

The atl site data for the syslog servers will:

  • Have a weight of 2000
  • Apply only to devices in the atl site
Config Contexts

For a device at site atl, such as “atl-edge-01”, the atl site syslog data (weight 2000) will override the United States regional syslog data (weight 1000) because Nautobot uses hierarchical rendering, in which greater weights prevail.

Config Contexts

The atl site has site-unique syslog data, while den uses the data from the United States region

JSON and YAML Formatting

Nautobot accepts config context data in the UI in JSON format, but may be viewed as JSON or YAML in the web UI by selecting the appropriate button:

SON and YAML Formatting

Note: When importing config context data from a Git repository, the data may be in either JSON or YAML format. Git repositories are covered in a later section of this post.

Config Context Schemas

Config contexts allow for arbitrary data structures to be stored within Nautobot, but, at scale, organizations will want to ensure that config contexts adhere to a uniform structure, e.g., a schema or model.

Take the NTP servers as an example. If you have three NTP server config contexts for three regions, you may want to enforce a general data structure uniformity across devices in all three regions, in order to prevent something like this:

Americas NTP Servers:

{
  "ntp-servers": [
    "172.16.10.22",
    "172.16.10.33"
  ]
}

APAC NTP Servers:

{
  "ntp-servers": [
    "172.16.13.22",
    "172.16.13.33"
  ]
}

EMEA NTP Servers:

{
  "ntp-servers": [
    "172.16.17.22,172.16.17.33"
  ]
}

The EMEA server data has a different structure, which may break a unified automation framework. Let’s use config context schemas to enforce a data format.

In our example situation, we want the following:

  • Exactly two servers configured
  • The two servers should be members in a list
  • The list of members should contain exactly two members
  • Each member should be a string in IPv4 format
  • No other additional data (properties) can be defined outside of ntp-servers

Using the config context schema example from the Nautobot documentation, this would be our schema:

{
    "type": "object",
    "properties": {
        "ntp-servers": {
            "type": "array",
            "minItems": 2,
            "maxItems": 2,
            "items": {
                "type": "string",
                "format": "ipv4"
            }
        }
    },
    "additionalProperties": false
}

Let’s add that schema now:

Config Context Schemas

Validating the Config Context Schema

Now that there’s a config context schema in place, we can test it by attempting to add a config context that violates the schema.

The new context schema can be applied from the Add/Edit config context page:

Validating the Config Context Schema

Once we click create, Nautobot returns an error indicating that the list of NTP servers is too long; another failed attempt tried to add syslog server data along with the NTP server data and was also flagged by Nautobot as a schema violation.

Validating the Config Context Schema

Using Git Repositories for Network Data

For some workflows and for some scaling considerations, it may make sense to store config contexts or config context schemas in a Git repository instead of Nautobot.

Scale and Data Quality

At any reasonable scale (and even at smaller scales), it can be impractical to manually input data into a system:

  • There may be a lot of data
  • The data structure may be complex

These factors make it more likely that there will be errors in data that is manually entered.

Git workflows can greatly minimize the chances of erroneous data because they allow:

  • Peer review and discussion of any changes to the data
  • Continuous integration/continuous delivery (CI/CD) pipelines to test/validate changes

These Git workflows can make data from Git repositories cleaner than data from other sources.

Importing Data from Git Repositories Into Nautobot

Nautobot’s Git as a data source feature supports importing data, including config contexts and config context schemas, from Git provider repositories. Supported providers include GitHubGitLab, and Bitbucket.

To work through this example, we will use the user-guide branch from the existing public demo-git-datasource GitHub repo.

To baseline our situation, let’s look at nyc-bb-01.infra.ntc.com, which is a Juniper vMX device. The Config Context tab on the main page for that device shows no info at present:

Importing Data from Git Repositories Into Nautobot

Note: Config contexts may be provided as JSON or YAML files located in the /config_contexts/ folder, which must be in the root of the Git repository.

Examining the Repository

There is a good amount of config context data in this repository branch. Here are the four files that will affect nyc-bb-01.infra.ntc.com:

demo-git-datasource/config_contexts/devices/nyc-bb-01.infra.ntc.com will provide the device’s local context (the data specific to that device):

Examining the Repository

demo-git-datasource/config_contexts/data-models.yml will provide global information:

Examining the Repository

demo-git-datasource/config_contexts/platform_junos.yml will provide platform-specific information:

Examining the Repository

demo-git-datasource/config_contexts/role_spine.yml will provide role-specific information:

Examining the Repository

Add a Git Repository

To add the Git repository, navigate to Extensibility–>Data Sources–>Git Repositories–>+.

This picture shows the Add a new Git repository page filled out; this repository will provide config contexts only:

Add a Git Repository

The Nautobot docs on Git as a Data Source contain details on each field on the Add a new Git repository form.

After the repository is added (by clicking the Create button), you should see a page showing a Completed synchronization status:

Add a Git Repository

Note: Importing data from Git repositories into Nautobot will be the topic of a future Nautobot blog post.

Results

Once the repository is added, when we return to the Config Context tab on the nyc-bb-01.infra.ntc.com main page, we see three main items:

  • The Rendered Context – this is the final data rendering, after all contexts and weights have been applied
  • The Local Context – this is data specific to a device and will always take precedence over any other config contexts, regardless of context weight
    • In this example, local context came from the demo-git-datasource/config_contexts/devices/nyc-bb-01.infra.ntc.com file
  • Source Context – this is data from other contexts; in this example, those contexts were globalplatform, and role
Results

Conclusion

Config ContextsConfig Context Schemas, and Git as a data source are three of Nautobot’s extensibility features. Each of these also plays a role in ensuring the quality of Nautobot’s data:

  • Config contexts: Allow users to easily associate specific data based on a device’s context (circumstances)
  • Config context schemas: Enforces structure on config context data, minimizing the chance for an unusable/unexpected data structure
    • This is especially important in automation, where the automation infrastructure is expecting data in a specific structure
  • Importing Git repositories: Enables users to import clean data, including config contexts and config context schemas, from Git repositories

This post has covered the use cases for those features, demonstrated how to implement them, and described the value they provide.

Thank you, and have a great day!

-Tim



ntc img
ntc img

Contact Us to Learn More

Share details about yourself & someone from our team will reach out to you ASAP!

Introducing the Nautobot Data Validation Engine Plugin

Blog Detail

Data, data, and more data, but is the data good data?

Coinciding with the coming release of Nautobot v1.1.0, the team is excited to announce the public release of the Data Validation Engine Plugin! This Nautobot plugin offers data validation and enforcement rule logic that utilizes the custom data validators functionality within the platform. Data validators allow for custom business logic to be enforced within Nautobot when changes to data occurs. This gives organizations the ability to better integrate Nautobot into their existing ecosystems and to put guardrails around its use to ensure that network data housed within Nautobot can be trusted. One of Nautobot’s core missions is to serve as a single Source of Truth (SoT) for network data, from which automation solutions can be engineered. For network automation to be successful, the data that drives that automation must be trusted, and for the data to be trusted, there must exist constraints within the data model to enforce its correctness.

The problem lies in the understanding that all organizations operate differently and each will have nuanced ways in which they manage and configure their networks that ultimately dictate constraints in their network SoT data. Something as simple as naming a device can quickly devolve into endless debate and 16 different organizational standards. As such, it is impossible for Nautobot to try to derive and implement any such direct data constraints that would apply to all users. Therefore, the custom data validators feature set exists, to empower end users to codify their business logic and be able to enforce it within Nautobot.

Data Validation Engine Plugin

So where, then, does the plugin fit? The custom data validators API is a raw Python interface that hooks into the data models’ clean() methods, allowing for ValidationErrors to be raised based on defined business logic when model instances are created or updated. If that doesn’t mean anything to you, the Data Validation Engine Plugin is for you!

The plugin offers a Web UI (and REST API) for creating and managing no-code business rules for validation. In this initial release, there are two types of supported rules, regular expressions, and min/max numeric based rules.

Regular Expression Rules

Regular expressions define search patterns for matching text and are quite pervasive in the industry for a variety of use cases. They are often used to validate that text conforms to a pattern. Here, we use them to define rules for constraining text based fields in Nautobot to user defined expressions.

regex-rules-list

Each rule defines the Nautobot model and the text based field on that model to which the validation should apply. A custom error message can be defined, else a default message will indicate validation against the regular expression has failed. The rule may also be toggled on and off in real time in the Web UI.

regex-rules-edit

When a rule has been create and enabled, it is enforced when an instance of the applicable model is either created or updated in the Web UI or REST API. Here we can see what happens when a user attempts to create a device that does no conform to the hostname standard that was defined above.

regex-rules-enforcement

Min/Max Numeric Rules

While regular expression rule work on text based fields, min/max rules work on numeric model fields.

min-max-rules-list

As the name implies, users have the ability to constrain the minimum and/or maximum values of a number-based field, and the rules are defined in the same way as regular expression rules.

min-max-rules-edit

As you might expect, the enforcement is also the same, and in this example, an organization wishes to enforce that no VLANs with ID greater than or equal to 4000 get deployed in their environment, so they create a min/max rule targeting the vid field on the VLAN model.

min-max-rules-enforcement

Install

The plugin is available as a Python package on PyPI and can be installed with pip, following the full instructions on GitHub.

Final Thoughts

Data is key to network automation and trusted, correct data is key to successful network automation. Enforcing your organization’s specific business logic constraints is an important step in building a network automation platform and Nautobot offers the feature set to enable you. The Data Validation Engine Plugin goes one step further in providing a user friendly, no-code solution to common data validation use cases. Give it a try and let us know what you think!



ntc img
ntc img

Contact Us to Learn More

Share details about yourself & someone from our team will reach out to you ASAP!