NetBox (Export Template)
This guide shows how to use NetBox Export Templates with the HTTP provider to discover and sync targets.
Export Templates offer powerful filtering, transformation, and formatting directly in NetBox, reducing the load on the operator.
Overview
An Export Template is a Jinja2 template defined in NetBox that:
- Queries NetBox’s internal database (devices, interfaces, etc.)
- Filters results based on custom criteria
- Transforms data into your desired output format (JSON, YAML, CSV, etc.)
- Returns the formatted output via a custom REST API endpoint
When used with gNMIc’s HTTP provider, the operator simply fetches the rendered template and parses the result — no additional gNMIc Operator transformation needed if done correctly.
Prerequisites
- A running Kubernetes cluster with gNMIc Operator installed
kubectlaccess to your cluster- A reachable NetBox instance with permissions to create Export Templates
- A NetBox API token
- Familiarity with Jinja2 templates
Step 1: Create a NetBox API Token and Store It Securely
Step 1a: Create the API Token in NetBox
Create a dedicated API token in NetBox for gNMIc Operator access.
- Log in to NetBox.
- Open your user profile or go to User > API Tokens.
- Click Add or Add token.
- Enter a descriptive name such as
gNMIc Operator. - Grant the minimum permissions required for read-only device discovery.
- Copy the token value and store it safely; NetBox will not show it again.
Step 1b: Store the Token in a Kubernetes Secret
Create a Kubernetes Secret containing the token so it is not embedded in manifests.
# Substitute YOUR_NETBOX_API_TOKEN with your actual token
# Bearer Token Format (v2): nbt_<key>.<token>
kubectl create secret generic netbox-api-token \
--from-literal=token=YOUR_NETBOX_API_TOKEN \
-n your-namespace
Verify the Secret was created:
kubectl get secret netbox-api-token -n your-namespace -o yaml
Step 2: Create an Export Template in NetBox
Log in to your NetBox instance and navigate to Customization > Export Templates.
Step 2a: Create a New Template
Click Add Export Template and fill in the details:
| Field | Value | Notes |
|---|---|---|
| Name | gNMIc Device Export | Descriptive name for your template |
| Content Type | dcim > device | Export template applies to Device objects |
| Template Code | (see below) | Jinja2 template |
| File Extension | json | Output format |
| Mime Type | application/json | Correct MIME type for JSON |
Step 2b: Template Code Example
Basic Template (All Devices)
[
{% for device in queryset %}
{
"name": "{{ device.name }}",
"address": "{{ device.primary_ip4.address.split('/')[0] }}",
"labels": {
"site": "{{ device.site.name }}",
"role": "{{ device.device_role.name }}",
"region": "{{ device.site.region.name }}",
"type": "{{ device.device_type.model }}"
}
}{{ "," if not loop.last }}
{% endfor %}
]
Advanced Template (Filtered by Status and Role)
[
{% for device in queryset.filter(status='active', device_role__name__in=['leaf', 'spine']) %}
{
"name": "{{ device.name }}",
"address": "{{ device.primary_ip4.address.split('/')[0] }}",
"labels": {
"site": "{{ device.site.name }}",
"role": "{{ device.device_role.name }}",
"region": "{{ device.site.region.name }}",
"model": "{{ device.device_type.model }}",
"serial": "{{ device.serial }}",
"asset_tag": "{{ device.asset_tag }}"
}
}{{ "," if not loop.last }}
{% endfor %}
]
Key template elements:
queryset: The filtered set of devices (all unless you add.filter())device.name: Device hostnamedevice.primary_ip4.address.split('/')[0]: Extract IP from CIDR (e.g.,192.0.2.1/24to192.0.2.1)device.site.name,device.device_role.name: NetBox relationships (site, role, etc.)loop.last: Jinja2 loop variable to avoid trailing comma on last item
Step 2c: Save and Access the Template
Once saved, NetBox exposes the template via:
http://netbox.example.com:8000/api/dcim/devices/?export=gNMIc+Device+Export
Or fetch it directly:
# Replace with your NetBox URL and template name
# Substitute YOUR_NETBOX_API_TOKEN with your actual token
# Bearer Token Format (v2): nbt_<key>.<token>
curl -H "Authorization: Bearer YOUR_NETBOX_API_TOKEN" \
"http://netbox.example.com:8000/api/dcim/devices/?export=gNMIc%20Device%20Export"
The response is a JSON array of targets ready for gNMIc.
If you instead return a JSON object with a nested array, add a mapping section such as
targetsField: "self.targets"to the TargetSource CR.
Step 3: Create a TargetProfile
Define how discovered targets should be configured. The TargetProfile points to a Secret containing device credentials, such as username/password or client certificates.
Create a credentials Secret first, then reference it from the profile.
# Replace YOUR_DEVICE_USERNAME and YOUR_DEVICE_PASSWORD with your corresponding default device username and password
apiVersion: v1
kind: Secret
metadata:
name: device-credentials
namespace: your-namespace
type: Opaque
stringData:
username: YOUR_DEVICE_USERNAME
password: YOUR_DEVICE_PASSWORD
apiVersion: operator.gnmic.dev/v1alpha1
kind: TargetProfile
metadata:
name: netbox-device
namespace: your-namespace
spec:
credentialsRef: device-credentials
timeout: 10s
For more TargetProfile options and credential handling, see the operator documentation for TargetProfile.
Step 4: Create a TargetSource Using Export Template
Create a TargetSource that references your NetBox export template endpoint:
apiVersion: operator.gnmic.dev/v1alpha1
kind: TargetSource
metadata:
name: netbox-export-source
namespace: your-namespace
spec:
targetPort: 57400
targetProfile: netbox-device
targetLabels:
inventory: netbox
sync-source: export-template
provider:
http:
url: "http://netbox.example.com:8000/api/dcim/devices/?export=gNMIc%20Device%20Export"
method: GET
interval: 30m
timeout: 30s
authentication:
token:
scheme: Token
tokenSecretRef:
name: netbox-api-token
key: token
Step 5: Verify Target Discovery
Once the TargetSource is deployed, verify that targets are being discovered:
# List discovered targets
kubectl get targets -n your-namespace
# Check TargetSource status and sync details
kubectl describe targetsource netbox-export-source -n your-namespace
Successful sync shows:
status.status: “success” (or similar)status.targetsCount: number of devicesstatus.lastSync: recent timestamp
Example: Complete Setup
Here’s a full example combining all components:
---
# Secret for NetBox API token
apiVersion: v1
kind: Secret
metadata:
name: netbox-api-token
namespace: your-namespace
type: Opaque
data:
# base64-encoded token (echo -n "YOUR_TOKEN" | base64)
token: YOUR_BASE64_ENCODED_TOKEN
---
# Secret for Target Credential
apiVersion: v1
kind: Secret
metadata:
name: device-credentials
namespace: your-namespace
type: Opaque
stringData:
username: YOUR_DEVICE_USERNAME
password: YOUR_DEVICE_PASSWORD
---
# TargetProfile
apiVersion: operator.gnmic.dev/v1alpha1
kind: TargetProfile
metadata:
name: netbox-device
namespace: your-namespace
spec:
credentialsRef: device-credentials
timeout: 10s
---
# TargetSource using Export Template
apiVersion: operator.gnmic.dev/v1alpha1
kind: TargetSource
metadata:
name: netbox-export-source
namespace: your-namespace
spec:
targetPort: 57400
targetProfile: netbox-device
targetLabels:
inventory: netbox
sync-source: export-template
provider:
http:
url: "http://netbox.example.com:8000/api/dcim/devices/?export=gNMIc%20Device%20Export"
method: GET
interval: 30m
timeout: 30s
authentication:
token:
scheme: Token
tokenSecretRef:
name: netbox-api-token
key: token
Advantages of Export Templates
- Powerful Filtering: Filter devices by site, status, role, tags, etc. directly in NetBox
- Reduced Operator Load: NetBox handles data transformation; operator just fetches JSON
- Reusability: One template can serve multiple consumers
- Maintainability: Update discovery logic in NetBox without changing Kubernetes manifests
- Performance: Avoids REST API pagination for large inventories
Limitations & Considerations
1. Reverse Proxy and URL Path Rewriting
If NetBox is behind a reverse proxy with URL path rewriting:
- Issue: The export template endpoint uses query parameters that may not survive proxy transformation.
- Solution:
- Ensure the proxy preserves query strings exactly.
- Test the export URL directly:
curl -H "Authorization: Token YOUR_TOKEN" \ "http://netbox.example.com:8000/api/dcim/devices/?export=gNMIc%20Device%20Export" - If the proxy blocks or modifies parameters, consider using a direct NetBox endpoint without proxying.
2. Large Inventory Rendering
- Very large device counts can cause NetBox to take time rendering the template.
- Solution:
- Use
.filter()in your template to limit results. - Create separate export templates for different device groups (e.g., by site or role).
- Use
3. Complex Jinja2 Logic
- NetBox’s Jinja2 sandbox restricts some Python functions for security.
- Solution: Keep templates simple and use NetBox’s built-in filters and objects. Test URL with curl or similar before deploying.
Template Troubleshooting
Missing Targets in Kubernetes
- Check: Are all required fields populated in NetBox? (e.g.,
primary_ip4may beNoneif not set) - Solution: Add conditional checks:
{% if device.primary_ip4 %} "address": "{{ device.primary_ip4.address.split('/')[0] }}" {% endif %}
Authorization Fails
If you get a 403 error:
- Verify the token is valid and not expired.
- Ensure the API token is enabled.