How to create a check in Infrahub
Checks in Infrahub allow you to validate data based on custom business logic. They are defined in external repositories and can be developed and tested locally using infrahubctl check.
If you want to know more about the differences between these two types, refer to the topic on Global vs. Targeted Checks.
TL;DR:
- Global Checks: Apply to all instances of a specific object type in the database
- Targeted Checks: Apply only to specific instances that you select (by adding them to a group)
What you'll build
In this guide, you'll build a check that:
- Reads information about tag objects from the database
- Validates that the tags follow specific naming conventions using regex patterns
- Automatically runs when changes to tags are proposed
Steps overview
- Prepare sample data in your Infrahub instance
- Create a GraphQL query to fetch data from Infrahub
- Implement a Python check that validates the data
- Configure the check in an
.infrahub.yml
file - Test the check locally with infrahubctl
- Deploy the check to Infrahub
- Validate that the check works in Infrahub's CI pipeline
Prerequisites
Before you begin, you'll need:
- Basic knowledge of Infrahub, Python, GraphQL, YAML, and Git
- Familiarity with Checks and how they work in Infrahub (see Checks topic)
- An Infrahub instance running locally or remotely
- A Git repository connected to Infrahub (see Adding an External Repository guide)
- infrahubctl installed and configured locally
- The repository cloned where you'll develop the check
Setting up your workspace
We recommend creating a new branch in your Git repository for your check development to avoid affecting the main branch. In this guide, we'll use a branch named create-tag-check
.
git checkout -b create-tag-check
git push --set-upstream origin create-tag-check
Step 1: Preparing sample data
First, let's create some sample tag data to test our check against.
This step is only necessary if you don't already have the objects affected by the check in your instance.
For targeted checks you will need to create a group that the check will target.
Create three tags with different naming patterns:
color-red
- Follows the "color-[name]" pattern (will pass validation)color-green
- Follows the "color-[name]" pattern (will pass validation)blue
- Doesn't follow the pattern (will fail our validation check)
You can create these tags using the Infrahub UI or in batch using object file:
- Targeted Check
- Global Check
For targeted checks, you will also need to create a group that includes the tags you want to validate.
- Using Object File
- Using the UI
- Create a file named
groups.yml
in theobjects
directory of your repository:
---
apiVersion: infrahub.app/v1
kind: Object
spec:
kind: CoreStandardGroup
data:
- name: colored_tags
description: Group for colored tags
- Create a file named
tags.yml
in theobjects
directory of your repository:
---
apiVersion: infrahub.app/v1
kind: Object
spec:
kind: BuiltinTag
data:
- name: "color-red"
description: "The red tag"
member_of_groups:
- ["colored_tags"]
- name: "color-green"
description: "The green tag"
member_of_groups:
- ["colored_tags"]
- name: "blue"
description: "The blue tag"
member_of_groups:
- ["colored_tags"]
- Use infrahubctl to load the objects:
infrahubctl object load objects/groups.yml --branch=create-tag-check
infrahubctl object load objects/tags.yml --branch=create-tag-check
- Open the Infrahub UI in your browser
- Select the branch
create-tag-check
- Navigate to the Groups view (Object Management > Groups)
- Create a group
- Name:
colored_tags
, Description:Group for colored tags
- Name:
- Navigate to the Tags view (Other > Tags)
- Create the tags
- Name:
color-red
, Description:The red tag
, Member of Group:colored_tags
- Name:
color-green
, Description:The green tag
, Member of Group:colored_tags
- Name:
blue
, Description:The blue tag
, Member of Group:colored_tags
- Name:
- Using Object File
- Using the UI
- Create a file named
tags.yml
in theobjects
directory of your repository:
---
apiVersion: infrahub.app/v1
kind: Object
spec:
kind: BuiltinTag
data:
- name: "color-red"
description: "The red tag"
- name: "color-green"
description: "The green tag"
- name: "blue"
description: "The blue tag"
- Use infrahubctl to load the objects:
infrahubctl object load objects/tags.yml --branch=create-tag-check
- Open the Infrahub UI in your browser
- Select the branch
create-tag-check
- Navigate to the Tags view (Other > Tags)
- Create the tags
- Name:
color-red
, Description:The red tag
- Name:
color-green
, Description:The green tag
- Name:
blue
, Description:The blue tag
- Name:
To verify the tags were created successfully, navigate to the Tags view in the Infrahub UI (Other > Tags), select the create-tag-check
branch, and check that the tags appear in the list.
Step 2: Create the GraphQL query
Next, create a GraphQL query that fetches the data your check needs to process.
Create a query to fetch the tag data
Create a tags_query.gql
file in the queries
directory of your repository:
- Targeted Check
- Global Check
query TagsQuery($name: String!) {
BuiltinTag(name__value: $name) {
edges {
node {
name {
value
}
description {
value
}
}
}
}
}
query TagsQuery {
BuiltinTag {
edges {
node {
name {
value
}
description {
value
}
}
}
}
}
Test the query
To test the query you can use Infrahub's GraphQL Sandbox.
Access the sandbox by clicking your user icon in the bottom left corner and selecting GraphQL Sandbox. This tool allows you to run GraphQL queries and provides an interactive way to explore the schema.
- Targeted Check
- Global Check
- Copy the above GraphQL query in the main section
- In the variables section, add:
{
"name": "blue"
}
- Click the Execute button, this should return a response like:
{
"data": {
"BuiltinTag": {
"edges": [
{
"node": {
"name": {
"value": "blue"
},
"description": {
"value": "The blue tag"
}
}
}
]
}
}
}
- Copy the above GraphQL query in the main section
- Click the Execute button, this should return a response like:
{
"data": {
"BuiltinTag": {
"edges": [
{
"node": {
"name": {
"value": "blue"
},
"description": {
"value": "The blue tag"
}
}
},
{
"node": {
"name": {
"value": "color-green"
},
"description": {
"value": "The green tag"
}
}
},
{
"node": {
"name": {
"value": "color-red"
},
"description": {
"value": "The red tag"
}
}
}
]
}
}
}
You now have a working GraphQL query that retrieves the necessary data from Infrahub. You might want to keep the result of the query for later reference, as it will be useful when implementing the check.
Step 3: Implement the check logic
Now create a Python class that implements your check logic. The check makes sure that every tag's name follows the pattern color-[name]
.
The class must:
- Inherit from
InfrahubCheck
from the Python SDK - Define a
query
class attribute that references your GraphQL query by name - Implement a
validate()
method that processes data from your GraphQL query - Log errors using
log_error()
when validation fails
- Create a file called
tags_check.py
in yourchecks
directory:
import re
from infrahub_sdk.checks import InfrahubCheck
RE_TAG = re.compile(r"^color-[a-z]+")
class ColorTagsCheck(InfrahubCheck):
query = "tags_query" # This references the query name in .infrahub.yml
def validate(self, data):
for tag in data["BuiltinTag"]["edges"]:
if not RE_TAG.match(tag["node"]["name"]["value"]):
self.log_error(
message=f"Invalid tag name: {tag['node']['name']['value']}. Tag names must follow pattern 'color-[name]'",
object_id=tag["node"]["name"]["value"],
object_type="BuiltinTag"
)
Step 4: Configure the check in the .infrahub.yml file
Now that you have your GraphQL query and Python check, edit your .infrahub.yml file to tie everything together.
- Add the following configuration to the file
.infrahub.yml
:
- Targeted Check
- Global Check
---
queries:
- name: tags_query
file_path: queries/tags_query.gql
check_definitions:
- name: check_color_tags_name
class_name: ColorTagsCheck
file_path: checks/tags_check.py
targets: colored_tags # This specifies the group to target
parameters:
name: "name__value"
---
queries:
- name: tags_query
file_path: queries/tags_query.gql
check_definitions:
- name: check_color_tags_name
class_name: ColorTagsCheck
file_path: checks/tags_check.py
For a complete explanation of the .infrahub.yml
file format, see the infrahub.yml topic.
- Verify the configuration
Check that your .infrahub.yml
file is correctly formatted by listing available checks:
infrahubctl check --list
If successful, you'll see output like:
- Targeted Check
- Global Check
Python checks defined in repository: 1
check_color_tags_name (checks/tags_check.py::ColorTagsCheck) Target: colored_tags
Python checks defined in repository: 1
check_color_tags_name (checks/tags_check.py::ColorTagsCheck) Target: -global-
Step 5: Test the check locally
Before deploying your check to Infrahub, test it locally using the infrahubctl
command-line tool.
- First, verify that your check is correctly configured:
infrahubctl check --list
- Run the check against your branch by specifying its name:
infrahubctl check check_color_tags_name --branch=create-tag-check
If successful, you'll see output like:
- Targeted Check
- Global Check
INFO HTTP Request: GET http://localhost:8000/api/schema?branch=create-tag-check2 "HTTP/1.1 200 OK"
INFO HTTP Request: POST http://localhost:8000/graphql/create-tag-check2 "HTTP/1.1 200 OK"
INFO HTTP Request: POST http://localhost:8000/graphql/create-tag-check2 "HTTP/1.1 200 OK"
INFO HTTP Request: POST http://localhost:8000/graphql/create-tag-check2 "HTTP/1.1 200 OK"
INFO HTTP Request: POST http://localhost:8000/graphql/create-tag-check2 "HTTP/1.1 200 OK"
INFO tags_check::ColorTagsCheck: PASSED - {'name': 'color-red'}
INFO HTTP Request: POST http://localhost:8000/graphql/create-tag-check2 "HTTP/1.1 200 OK"
INFO tags_check::ColorTagsCheck: PASSED - {'name': 'color-green'}
INFO HTTP Request: POST http://localhost:8000/graphql/create-tag-check2 "HTTP/1.1 200 OK"
ERROR tags_check::ColorTagsCheck: FAILED - {'name': 'blue'}
ERROR Invalid tag name: blue. Tag names must follow pattern 'color-[name]'
INFO HTTP Request: POST http://localhost:8000/graphql/create-tag-check "HTTP/1.1 200 OK"
ERROR tags_check::ColorTagsCheck: FAILED
ERROR Invalid tag name: blue. Tag names must follow pattern 'color-[name]'
The error message shows that our check correctly identified the tag named "blue" as invalid because it doesn't match our required naming pattern.
Step 6: Deploy the check to Infrahub
Now that you've tested your check and confirmed it works locally, deploy it to Infrahub by pushing your code to the repository.
Verify repository structure
Ensure your repository has the following structure before committing:
your-repository/
├── .infrahub.yml
├── checks/
│ └── tags_check.py
└── queries/
└── tags_query.gql
Depending on your organization, you might also have schemas
and objects
directories in your repository.
Commit and push your code
Upload your check code to the repository:
git add .
git commit -m "Add tags naming convention check"
git push
Confirm the check is imported
After pushing your changes, confirm that the check is imported correctly by checking the Infrahub UI:
- Open the Infrahub UI in your browser
- Select the
create-tag-check
branch - Navigate to the Check Definition view (Actions > Check Definitions)
- You should see your
check_color_tags_name
check listed there
If you don't see your check, verify the repository status in the Repository view (Integrations > Git Repositories) and ensure the sync status is synced
.
Your check is now successfully deployed to Infrahub.
Step 7: Validate that the check works
Let's verify that your check correctly validates data by creating a proposed change from your development branch create-tag-check
to main
.
Create a proposed change
- In the Infrahub UI, navigate to the Proposed Changes view
- Click New proposed change
- Create the Proposed Change with the following parameters:
- Source branch:
create-tag-check
- Destination branch:
main
- Name:
Add tag naming convention check
- Source branch:
Verify check results
After the proposed change is created:
- Navigate to the Checks tab of your proposed change
- Wait for the User CI check to complete
You should see that the check has failed because the tag "blue" doesn't match the expected pattern.
Fix the validation issue and merge
Now let's fix the issue with the invalid tag and complete the merge:
- Navigate to Tags view (Other > Tags)
- Select the
create-tag-check
branch - Delete the tag
blue
(as it doesn't follow the naming convention)- Alternatively, you could rename it to
color-blue
to match the pattern - For a targeted check you could also remove the tag
blue
from thecolored_tags
group
- Alternatively, you could rename it to
- Return to the Proposed Change view
- Navigate to the Data and Files tabs to review the changes
- Navigate to the Checks
- Hit the Retry button to re-run the check
- Verify that all checks now pass
- On the Overview tab, click the Merge button to merge your changes to main
Your check is now deployed to Infrahub in the main
branch and ready to be used. Any future tag creations will be validated against your naming convention rule.
Next steps
Now that you've created a basic check for data validation, you can expand your validation capabilities:
- Create more complex checks that validate relationships between objects
- Build checks that validate business logic across multiple object types
- Add detailed error messages with recommendations to help users understand and fix validation failures
Checks are a powerful way to enforce business rules in your data. By implementing validation rules that match your organization's requirements, you ensure data consistency and prevent configuration errors before they reach production environments.