NetBox (Export Template)

Discover targets from NetBox using HTTP provider with 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:

  1. Queries NetBox’s internal database (devices, interfaces, etc.)
  2. Filters results based on custom criteria
  3. Transforms data into your desired output format (JSON, YAML, CSV, etc.)
  4. 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
  • kubectl access 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.

  1. Log in to NetBox.
  2. Open your user profile or go to User > API Tokens.
  3. Click Add or Add token.
  4. Enter a descriptive name such as gNMIc Operator.
  5. Grant the minimum permissions required for read-only device discovery.
  6. 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:

FieldValueNotes
NamegNMIc Device ExportDescriptive name for your template
Content Typedcim > deviceExport template applies to Device objects
Template Code(see below)Jinja2 template
File ExtensionjsonOutput format
Mime Typeapplication/jsonCorrect 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 hostname
  • device.primary_ip4.address.split('/')[0]: Extract IP from CIDR (e.g., 192.0.2.1/24 to 192.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 devices
  • status.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).

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_ip4 may be None if 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.