nautobot: Openapi schema inconsistencies

Environment

  • Python version: 3.9
  • Nautobot version: 1.2.4

Found a few mismatches between the defined schema and the returned data when generating bindings for go with openapi-generator-cli

Sample URL: /api/dcim/interfaces/XXX/ Required data: Untaagged vlans applied to interface Sample Definition: VmInterface + Interface: Field: tagged_vlans Schema type: string[] of uuids Actually returned: NestedVLAN[]

  "tagged_vlans": [
    {
      "id": "89913e46-82b4-5ced-9b54-a459b8777b3a",
      "url": "http://localhost:8080/api/ipam/vlans/XX/",
      "vid": 10,
      "name": "XX",
      "display": "XX"
    },
    {
      "id": "ec495efc-1f11-586e-88b9-427ed1659717",
      "url": "http://localhost:8080/api/ipam/vlans/XX/",
      "vid": 20,
      "name": "XX",
      "display": "XX"
    }
  ],

Sample URL: /api/dcim/interfaces/XXX/ Required data: Connection between two interfaces Sample Definition: Anywhere cable_peer / connected_endpoint is used Field: cable_peer + connected_endpoint Schema type: nullable string Actually returned: NestedInterface?

  "cable_peer": {
    "id": "4ae220eb-9161-526e-8ecf-9a338b3c0d0c",
    "url": "http://localhost:8080/api/dcim/interfaces/4ae220eb-9161-526e-8ecf-9a338b3c0d0c/",
    "device": {
      "id": "a1a6fc59-8edb-52fd-8177-f08abc23bf7c",
      "url": "http://localhost:8080/api/dcim/devices/a1a6fc59-8edb-52fd-8177-f08abc23bf7c/",
      "name": "X",
      "display": "X"
    },
    "name": "swp51",
    "cable": "61d5e1e0-66a4-55b7-8209-001bbab4df1d",
    "display": "swp51"
  },
  "cable_peer_type": "dcim.interface",
  "connected_endpoint": {
    "id": "4ae220eb-9161-526e-8ecf-9a338b3c0d0c",
    "url": "http://localhost:8080/api/dcim/interfaces/4ae220eb-9161-526e-8ecf-9a338b3c0d0c/",
    "device": {
      "id": "a1a6fc59-8edb-52fd-8177-f08abc23bf7c",
      "url": "http://localhost:8080/api/dcim/devices/a1a6fc59-8edb-52fd-8177-f08abc23bf7c/",
      "name": "X",
      "display": "X"
    },
    "name": "swp51",
    "cable": "61d5e1e0-66a4-55b7-8209-001bbab4df1d",
    "display": "swp51"
  },
  "connected_endpoint_type": "dcim.interface",

Sample URL: /api/dcim/devices/X/ Required data: Device with a status defined. Sample Definition: Anywhere status enum is used in a read state, DeviceWithConfigContext/status for example Field: $X/status Schema type: enum string Actually returned:

  "status": {
    "value": "active",
    "label": "Active"
  },

Sample URL: /api/ipam/ip-addresses/X/ Required Data: IP Address assigned to an interface Sample Definition: (Writable)IPAddress Field: assigned_object Schema type: nullable string Actually returned: NestedInterface?

  "assigned_object_type": "dcim.interface",
  "assigned_object_id": "4086c7c8-4b12-52c3-8983-8e59d829d809",
  "assigned_object": {
    "id": "4086c7c8-4b12-52c3-8983-8e59d829d809",
    "url": "http://localhost:8080/api/dcim/interfaces/4086c7c8-4b12-52c3-8983-8e59d829d809/",
    "device": {
      "id": "1e13a364-32cd-5d68-9572-488853189f93",
      "url": "http://localhost:8080/api/dcim/devices/1e13a364-32cd-5d68-9572-488853189f93/",
      "name": "X",
      "display": "X"
    },
    "name": "eth0",
    "cable": "ba53d5df-01c9-5559-9aad-7e5eb317f09d",
    "display": "eth0"
  },

Sample URL: /api/dcim/devices/X/ Required data: Device/VM with config context data. Sample Definition: (Writable)DeviceWithConfigContext, (Writable)VirtualMachineWithConfigContext Field: config_context Schema type: map[string]string Actually returned: map[string]interface{}

Sample URL: /api/dcim/cables/X/ Required data: Connection between two interfaces Sample Definition: Cable Field: termination_a+b Schema type: nullable string Actually returned: NestedInterface?

  "termination_a_type": "dcim.consoleport",
  "termination_a_id": "063a2634-ccef-5452-8c8d-0c382ae09c09",
  "termination_a": {
    "id": "063a2634-ccef-5452-8c8d-0c382ae09c09",
    "url": "http://localhost:8080/api/dcim/console-ports/063a2634-ccef-5452-8c8d-0c382ae09c09/",
    "device": {
      "id": "4616541b-aeec-584f-b45e-d06a3a6b0ab3",
      "url": "http://localhost:8080/api/dcim/devices/4616541b-aeec-584f-b45e-d06a3a6b0ab3/",
      "name": "X",
      "display": "X"
    },
    "name": "X",
    "cable": "b09fb92e-bc81-55d9-a6e5-ff7e87c4996b",
    "display": "X"
  },
  "termination_b_type": "dcim.consoleserverport",
  "termination_b_id": "0cc4023f-602f-5568-a043-d19c17bee315",
  "termination_b": {
    "id": "0cc4023f-602f-5568-a043-d19c17bee315",
    "url": "http://localhost:8080/api/dcim/console-server-ports/0cc4023f-602f-5568-a043-d19c17bee315/",
    "device": {
      "id": "15f232bf-5021-5807-b555-99e6d9c117b2",
      "url": "http://localhost:8080/api/dcim/devices/15f232bf-5021-5807-b555-99e6d9c117b2/",
      "name": "X",
      "display": "X"
    },
    "name": "X",
    "cable": "b09fb92e-bc81-55d9-a6e5-ff7e87c4996b",
    "display": "X"
  },

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 18 (12 by maintainers)

Commits related to this issue

Most upvoted comments

Corresponding code change here would be:

diff --git a/nautobot/extras/api/serializers.py b/nautobot/extras/api/serializers.py
index 9ccb18124..2c5393c4f 100644
--- a/nautobot/extras/api/serializers.py
+++ b/nautobot/extras/api/serializers.py
@@ -786,7 +786,7 @@ class JobClassDetailSerializer(JobClassSerializer):  # pylint: disable=abstract-
 
 
 class JobInputSerializer(serializers.Serializer):  # pylint: disable=abstract-method
-    data = serializers.JSONField(required=False, default="")
+    data = serializers.JSONField(required=False, default={})
     commit = serializers.BooleanField(required=False, default=None)
     schedule = NestedScheduledJobSerializer(required=False)

It might also be interesting to test setting SPECTACULAR_SETTINGS["COMPONENT_SPLIT_REQUEST"] = True or SPECTACULAR_SETTINGS["COMPONENT_NO_READ_ONLY_REQUIRED"] = True in nautobot_config.py and see whether those improve the usability of the generated schema - from some quick evaluation on my end both look like improvements, specifically around the handling of fields like id and url which are required=True but also read_only=True.