netbox-plugin-dns: Webhook payload does not conform to NetBox OpenAPI schema

First of all - thanks for taking over this project.

Versions NetBox Version: netbox-docker NetBox DNS Version: pypi Python Version: netbox-docker

Describe the bug Using netbox webhooks …

Usually the format of the payload you get is

{
    "event": "updated",
    "timestamp": "2023-08-01 11:57:37.987666+00:00",
    "model": "zone",
    "username": "admin",
    "request_id": "36bc8845-03c8-490b-a466-552b9d10a77e",
    "data": <…>
    "snapshots": {
        "prechange": {
            <…Request>
        },
        "postchange": {
            <…Request>
    }
}

You can lookup the format of <…> and <…> from the openapi.yaml and have some python glue do the magic to create models, inject these into fastapi, and voiola, there is your webhook with perfect validation & parsing of the data, using models instead of basic python data structures. A project I’m working on "netbox-webhook`, meant to use netbox-dns webhooks to interface a name using TSIG.

Currently the format of the webhook payload data of netbox-dns does not match the <…>Request JSON schemas from the description document.

For one, some fields are missing allow_null

--- serializers.py.1	2023-08-01 14:24:37.138861089 +0200
+++ serializers.py	2023-08-01 13:33:01.938615897 +0200
@@ -54,6 +54,7 @@
     active = serializers.BooleanField(
         required=False,
         read_only=True,
+        allow_null=True,
     )
 
     def create(self, validated_data):
@@ -141,6 +142,7 @@
         many=False,
         read_only=True,
         required=False,
+        allow_null=True,        
         help_text="PTR record generated from an address",
     )
     address_record = NestedRecordSerializer(
@@ -157,6 +159,7 @@
     active = serializers.BooleanField(
         required=False,
         read_only=True,
+        allow_null=True,        
     )
 
     class Meta:

Next, …

fastapi.exceptions.RequestValidationError: [
{'type': 'model_attributes_type', 'loc': ('body', 'zone', 'snapshots', 'prechange', 'view'), 'msg': 'Input should be a valid dictionary or object to extract fields from', 'input': 1, 'url': 'https://errors.pydantic.dev/2.0.3/v/model_attributes_type'}, 
{'type': 'model_attributes_type', 'loc': ('body', 'zone', 'snapshots', 'prechange', 'nameservers', 0), 'msg': 'Input should be a valid dictionary or object to extract fields from', 'input': 4, 'url': 'https://errors.pydantic.dev/2.0.3/v/model_attributes_type'}, 
{'type': 'model_attributes_type', 'loc': ('body', 'zone', 'snapshots', 'prechange', 'soa_mname'), 'msg': 'Input should be a valid dictionary or object to extract fields from', 'input': 4, 'url': 'https://errors.pydantic.dev/2.0.3/v/model_attributes_type'}, 
…

The Payload looks like this:

{
    "event": "updated",
    "timestamp": "2023-08-01 12:26:09.992279+00:00",
    "model": "zone",
    …
    },
    "snapshots": {
        "prechange": {
            "created": "2023-08-01T11:00:22.010Z",
            "last_updated": "2023-08-01T11:57:37.949Z",
            "view": 1,
            "name": "example.org",
            "status": "active",
            "default_ttl": 86400,
            "soa_ttl": 86400,
            "soa_mname": 4,
            "soa_rname": "hostmaster.example.org",
            "soa_serial": 1,
            "soa_refresh": 172800,
            "soa_retry": 7200,
            "soa_expire": 2592000,
            "soa_minimum": 3600,
            "soa_serial_auto": false,
            "description": "",
            "arpa_network": null,
            "nameservers": [
                4
            ],
            "custom_fields": {},
            "tags": []
        },
…

The Schema for ZoneRequest - retrieved via /api/schema :

    ZoneRequest:
      type: object
      description: Adds support for custom fields and tags.
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 255
        view:
          allOf:
          - $ref: '#/components/schemas/NestedViewRequest'
          description: View the zone belongs to
        nameservers:
          type: array
          items:
            $ref: '#/components/schemas/NestedNameServerRequest'
          description: Nameservers for the zone
…

I’ve found WritableZoneRequest - which does better wrt. to views, but fails for nameservers as well. And there is no WritableViewRequest either.

    WritableZoneRequest:
      type: object
      description: Adds support for custom fields and tags.
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 255
        view:
          type: integer
          nullable: true
        nameservers:
          type: array
          items:
            $ref: '#/components/schemas/NestedNameServerRequest'
          description: Nameservers for the zone

I lack the insight in django serialization to get this done by myself.

I currently hook ipam.IPAddress for dns_name and would like to extend to netbox-dns.

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 16 (10 by maintainers)

Most upvoted comments

We’ll meet again once the requirements of netbox-webhook are met by netbox.