When I first started working with Network Query Engine (NQE), I didn’t have a traditional software engineering background and was learning Python and NQE at the same time. I needed to create a custom solution for handling certificate expiration dates across different network devices. The Python part of my brain was hoping to find a traditional for loop capability, and was a bit lost when that didn’t exist. As you may know, you can solve any given problem 10 different ways with NQE. I wanted to write a solution that would be clean, readable, easy to maintain, and share with others without having to provide too much explanation .
That’s where the WHEN statement came into play.
What is a WHEN Statement?
Within the NQE Data Model, there are some data types that have a fixed list of options.The WHEN statement in NQE allows you to evaluate different conditions based on those options. WHEN is like switch or case statements in other programming languages, but it’s more tailored to pattern matching your network data. In the context of NQE, the WHEN statement enables you to determine specific patterns based on device attributes such as vendor, OS, or routing protocols, and even more granular options such as interface type or vlan mode which can vary across devices. What makes it so powerful is that it lets you create a single query that works across different data types without having to write multiple, repetitive queries for each one.
For example, when you have a network that uses devices from multiple vendors like Cisco and Arista, their functionality may be the same, but their command outputs and syntax can be quite different. The WHEN statement lets you account for those differences within a single query by specifying what conditions or patterns apply to each vendor. This way, you maintain the ability to query multiple devices while ensuring that the logic is still vendor-agnostic. That’s important in a mixed environment because it allows the query to scale and adapt as more device types are added. I’ll share an example of this below.
How I use the WHEN statement to make life easier for everyone
When I first started writing NQEs, I focused heavily on config matching—specifically, matching device outputs or configurations to extract the information I needed. A common issue I ran into was how to handle different operating systems or vendor types in a way that made the query logical and easy to read. My goal is always to make sure that when someone else looks at the NQE, it’s clear what the logic is doing. For me, readability and maintainability are key. I want to avoid making people sift through endless lines of code trying to figure out what’s going on.
The WHEN statement allows me to keep my NQEs clean and efficient. In the example I share below, I was working with certificate expiration dates, trying to pull the relevant information from both Cisco and Arista devices. Now, these two platforms have different command outputs and patterns for displaying certificate information. Without the WHEN statement, I would have had to write two separate queries—one for each vendor—and then combine the results afterward. But with the WHEN statement, I was able to define specific patterns for each vendor within the same query. I set one custom command for Cisco, another for Arista, and used a common date pattern to evaluate the certificate expiration dates.
Here’s the beauty of it: because I used the WHEN statement, I only had to write the logic once. The NQE evaluated both Cisco and Arista platforms and returned the results in a single, unified output. This saved me a lot of time and kept my query much simpler than if I had written separate blocks of code for each device type.
An example
In this example, I was dealing with two different network operating systems: Cisco and Arista. Both platforms had similar data—such as the certificate’s expiration month and year—but their command outputs were formatted differently. Using the WHEN statement, I wrote a single NQE that evaluated both platforms by associating specific patterns with each OS.
ciscoPattern =
```
Validity Date:
end date: {string} {string} {month:string} {day:number} {year:number}
Associated Trustpoints: {string}
```;
aristaPattern =
```
Validity:
Not After: {month:string} {day:number} {string} {year:number} {string}
```;
foreach device in network.devices
foreach command in device.outputs.commands
/* Set the custom command to use based on device OS */
let customText = when device.platform.os is
ARISTA_EOS -> "show management security ssl certificate";
IOS_XE -> "show crypto pki certificates";
otherwise -> null : String
where command.commandText == customText
let response = parseConfigBlocks(device.platform.os, command.response)
/* Set the parent line pattern to search the output for based on device OS */
let certPattern = when device.platform.os is
ARISTA_EOS -> `Certificate`;
IOS_XE -> `CA Certificate`;
otherwise -> null : Pattern<{}>
/* Select the block pattern to match in the config based on device OS
* Note that the variables in the pattern do have to match */
let datePattern = when device.platform.os is
ARISTA_EOS -> aristaPattern;
IOS_XE -> ciscoPattern;
otherwise -> null : PatternBlocks<{month: String, day: Number, year: number}>
where isPresent(certPattern) && isPresent(datePattern)
foreach match in patternMatches(response, certPattern)
foreach child in blockMatches(match.line.children, datePattern)
let expires = child.data.month + " " + toString(child.data.day) + ", " +
toString(child.data.year)
select {
device: device.name,
CA_Expiration: expires
}
For example, I defined a Cisco-specific pattern to match its command output and a separate Arista pattern for the same task.
ciscoPattern =
```
Validity Date:
end date: {string} {string} {month:string} {day:number} {year:number}
Associated Trustpoints: {string}
```;
aristaPattern =
```
Validity:
Not After: {month:string} {day:number} {string} {year:number} {string}
```;
Then, in the main logic block, I used the WHEN statement to decide which pattern to apply depending on the device.
let customText = when device.platform.os is
ARISTA_EOS -> "show management security ssl certificate";
IOS_XE -> "show crypto pki certificates";
otherwise -> null : String
let certPattern = when device.platform.os is
ARISTA_EOS -> `Certificate`;
IOS_XE -> `CA Certificate`;
otherwise -> null : Pattern<{}>
let datePattern = when device.platform.os is
ARISTA_EOS -> aristaPattern;
IOS_XE -> ciscoPattern;
otherwise -> null : PatternBlocks<{month: String, day: Number, year: number}>
This way, I didn’t have to duplicate the entire query logic for each vendor; I just specified the parts that were different. The result was a concise, easy-to-read NQE that worked seamlessly across both platforms.
What if the patterns don’t match? Another important feature of the WHEN statement is the ability to handle fallback conditions using the "otherwise" statement. If a device didn’t match any of the specified conditions, I could specify a default action using "otherwise," ensuring that my query wouldn’t break or produce incomplete results. This flexibility was critical for maintaining both the accuracy and the vendor-agnostic nature of the query.
How you can use the WHEN statement
The WHEN statement is great for anyone dealing with mixed network environments or multiple operating systems. If you find yourself writing separate queries for each device type and then combining the results later, the WHEN statement can simplify that process by allowing you to handle different vendors or OSes in a single query. This not only saves time but also makes your queries more scalable and easier to maintain.
Creating effective NQEs relies on the balance of simplicity and clarity while maintaining their functionality. The WHEN statement is particularly beneficial, as it allows you to apply certain conditions for different data types. This not only enhances the readability of your queries but also helps keep them organized and free from unnecessary complexity. So, if you’re looking for a way to streamline your queries and make them easier to manage, give the WHEN statement a try. It’s an invaluable tool in the NQE toolbox when you’re working in a multi-vendor environment like I do.