Using JQ in Cortex

JQ is a lightweight, flexible command-line JSON processor that allows users to do arbitrary JSON manipulations.

Cortex leverages JQ within CQL to enable complex queries, including queries on YAML files. For instance:

jq(custom("foo"), ".property | length")

The above query would cycle through the foo object and retrieve the length of all .property components. This type of query is often used on Kubernetes resources.

JQ and datatypes

JQ can provide additional flexibility around data types. For instance, let's say you have a string associated with a numerical value in your Custom Data.

x-cortex-custom-metadata:
  my-key:
    line: "100"

If you wanted to query on the line value as a number rather than string, the following JQ functionality could be used within CQL:

jq(custom("my-key"), ".line | tonumber") > 99

This would result in the respective entity passing this CQL check.

JQ examples

The following examples demonstrate ways you could use JQ in Cortex:

Use JQ to implement conditional logic for selecting file paths dynamically

git.fileContents(jq(custom("git"), "if . != null then .[\"dockerfile-path\"] else \"Dockerfile\" end

This checks if custom git data exists, uses the custom dockerfile path if present, or falls back to the default "Dockerfile" path.

Accessing properties with special characters

Use bracket notation to access JSON properties containing dots, slashes, or other special characters:

jq(k8s.spec().firstOrNull().selector.matchLabels, ".[\"app.kubernetes.io/instance\"]")

Handling null values

Prevent errors by checking for null values before accessing properties:

jq(custom("data-key"), 'if .retryConfigurations != null then .retryConfigurations | map(.retryAttemptTime) else "Not Found" end')

For Scorecard rules, you can use a similar approach:

custom("retry-circuit-breaker") != null

Wildcard pattern matching

Find packages containing specific strings using the matches() function:

jq(custom("data-source").packages.filter((package)=>package.packageName.matches(".*<string-text-here>.*")).map((package) => package.packageVersion), ".")

Finding team members by role

Filter team members by role using JQ:

jq(entity.descriptor().info.`x-cortex-team`.members, "map(select(.role == \"engineering-manager\")) | .[].name")

Handling complex YAML structures

When working with complex YAML files like GitLab CI configurations:

jq(git.fileContents('gitlab-ci.yaml').split(' ').filter((section) => section.matchesIn('NODE_VERSION:')).firstOrNull(), '.variables.NODE_VERSION')

Extract the scheme of an AWS load balancer for resource metadata

jq(aws.details(), ".resources[0].Scheme")

Or, for nested metadata:

jq(aws.details(), ".resources[0].metadata.Scheme")

Extracting version from pom.xml file

This query extracts the version number from a Maven pom.xml file. You might use this to automate dependency version checks:

jq(jq(git.fileContents("pom.xml").split("<version>"),".[1]").split("</version>"), ".[0]")

Display a parent entity name in a CQL report

This query would allow you to display a parent entity name value, rather than an array, in a CQL report:

jq(entity.parents().map((parentEntity) => parentEntity.parents.map((parentEntity) => parentEntity.name)), ".[0]")

Last updated

Was this helpful?