Просмотр исходного кода

Feature - Schema Generation (#13353)

* Schema generation is working

* Added option to either dump to a file or the console

* Moving schema file and utilizing settings definition for file paths

* Cleaning up the imports and fixing a few pythonic issues

* Tweak command flags

* Clean up choices mapping

* Misc cleanup

* Rename & move template file

* Move management command from extras to dcim

* Update release checklist

---------

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
Daniel W. Anner 2 лет назад
Родитель
Сommit
40afe6cf36

+ 561 - 0
contrib/generated_schema.json

@@ -0,0 +1,561 @@
+{
+    "type": "object",
+    "additionalProperties": false,
+    "definitions": {
+        "airflow": {
+            "type": "string",
+            "enum": [
+                "front-to-rear",
+                "rear-to-front",
+                "left-to-right",
+                "right-to-left",
+                "side-to-rear",
+                "passive",
+                "mixed"
+            ]
+        },
+        "weight-unit": {
+            "type": "string",
+            "enum": [
+                "kg",
+                "g",
+                "lb",
+                "oz"
+            ]
+        },
+        "subdevice-role": {
+            "type": "string",
+            "enum": [
+                "parent",
+                "child"
+            ]
+        },
+        "console-port": {
+            "type": "object",
+            "properties": {
+                "type": {
+                    "type": "string",
+                    "enum": [
+                        "de-9",
+                        "db-25",
+                        "rj-11",
+                        "rj-12",
+                        "rj-45",
+                        "mini-din-8",
+                        "usb-a",
+                        "usb-b",
+                        "usb-c",
+                        "usb-mini-a",
+                        "usb-mini-b",
+                        "usb-micro-a",
+                        "usb-micro-b",
+                        "usb-micro-ab",
+                        "other"
+                    ]
+                }
+            }
+        },
+        "console-server-port": {
+            "type": "object",
+            "properties": {
+                "type": {
+                    "type": "string",
+                    "enum": [
+                        "de-9",
+                        "db-25",
+                        "rj-11",
+                        "rj-12",
+                        "rj-45",
+                        "mini-din-8",
+                        "usb-a",
+                        "usb-b",
+                        "usb-c",
+                        "usb-mini-a",
+                        "usb-mini-b",
+                        "usb-micro-a",
+                        "usb-micro-b",
+                        "usb-micro-ab",
+                        "other"
+                    ]
+                }
+            }
+        },
+        "power-port": {
+            "type": "object",
+            "properties": {
+                "type": {
+                    "type": "string",
+                    "enum": [
+                        "iec-60320-c6",
+                        "iec-60320-c8",
+                        "iec-60320-c14",
+                        "iec-60320-c16",
+                        "iec-60320-c20",
+                        "iec-60320-c22",
+                        "iec-60309-p-n-e-4h",
+                        "iec-60309-p-n-e-6h",
+                        "iec-60309-p-n-e-9h",
+                        "iec-60309-2p-e-4h",
+                        "iec-60309-2p-e-6h",
+                        "iec-60309-2p-e-9h",
+                        "iec-60309-3p-e-4h",
+                        "iec-60309-3p-e-6h",
+                        "iec-60309-3p-e-9h",
+                        "iec-60309-3p-n-e-4h",
+                        "iec-60309-3p-n-e-6h",
+                        "iec-60309-3p-n-e-9h",
+                        "iec-60906-1",
+                        "nbr-14136-10a",
+                        "nbr-14136-20a",
+                        "nema-1-15p",
+                        "nema-5-15p",
+                        "nema-5-20p",
+                        "nema-5-30p",
+                        "nema-5-50p",
+                        "nema-6-15p",
+                        "nema-6-20p",
+                        "nema-6-30p",
+                        "nema-6-50p",
+                        "nema-10-30p",
+                        "nema-10-50p",
+                        "nema-14-20p",
+                        "nema-14-30p",
+                        "nema-14-50p",
+                        "nema-14-60p",
+                        "nema-15-15p",
+                        "nema-15-20p",
+                        "nema-15-30p",
+                        "nema-15-50p",
+                        "nema-15-60p",
+                        "nema-l1-15p",
+                        "nema-l5-15p",
+                        "nema-l5-20p",
+                        "nema-l5-30p",
+                        "nema-l5-50p",
+                        "nema-l6-15p",
+                        "nema-l6-20p",
+                        "nema-l6-30p",
+                        "nema-l6-50p",
+                        "nema-l10-30p",
+                        "nema-l14-20p",
+                        "nema-l14-30p",
+                        "nema-l14-50p",
+                        "nema-l14-60p",
+                        "nema-l15-20p",
+                        "nema-l15-30p",
+                        "nema-l15-50p",
+                        "nema-l15-60p",
+                        "nema-l21-20p",
+                        "nema-l21-30p",
+                        "nema-l22-30p",
+                        "cs6361c",
+                        "cs6365c",
+                        "cs8165c",
+                        "cs8265c",
+                        "cs8365c",
+                        "cs8465c",
+                        "ita-c",
+                        "ita-e",
+                        "ita-f",
+                        "ita-ef",
+                        "ita-g",
+                        "ita-h",
+                        "ita-i",
+                        "ita-j",
+                        "ita-k",
+                        "ita-l",
+                        "ita-m",
+                        "ita-n",
+                        "ita-o",
+                        "usb-a",
+                        "usb-b",
+                        "usb-c",
+                        "usb-mini-a",
+                        "usb-mini-b",
+                        "usb-micro-a",
+                        "usb-micro-b",
+                        "usb-micro-ab",
+                        "usb-3-b",
+                        "usb-3-micro-b",
+                        "dc-terminal",
+                        "saf-d-grid",
+                        "neutrik-powercon-20",
+                        "neutrik-powercon-32",
+                        "neutrik-powercon-true1",
+                        "neutrik-powercon-true1-top",
+                        "ubiquiti-smartpower",
+                        "hardwired",
+                        "other"
+                    ]
+                }
+            }
+        },
+        "power-outlet": {
+            "type": "object",
+            "properties": {
+                "type": {
+                    "type": "string",
+                    "enum": [
+                        "iec-60320-c5",
+                        "iec-60320-c7",
+                        "iec-60320-c13",
+                        "iec-60320-c15",
+                        "iec-60320-c19",
+                        "iec-60320-c21",
+                        "iec-60309-p-n-e-4h",
+                        "iec-60309-p-n-e-6h",
+                        "iec-60309-p-n-e-9h",
+                        "iec-60309-2p-e-4h",
+                        "iec-60309-2p-e-6h",
+                        "iec-60309-2p-e-9h",
+                        "iec-60309-3p-e-4h",
+                        "iec-60309-3p-e-6h",
+                        "iec-60309-3p-e-9h",
+                        "iec-60309-3p-n-e-4h",
+                        "iec-60309-3p-n-e-6h",
+                        "iec-60309-3p-n-e-9h",
+                        "iec-60906-1",
+                        "nbr-14136-10a",
+                        "nbr-14136-20a",
+                        "nema-1-15r",
+                        "nema-5-15r",
+                        "nema-5-20r",
+                        "nema-5-30r",
+                        "nema-5-50r",
+                        "nema-6-15r",
+                        "nema-6-20r",
+                        "nema-6-30r",
+                        "nema-6-50r",
+                        "nema-10-30r",
+                        "nema-10-50r",
+                        "nema-14-20r",
+                        "nema-14-30r",
+                        "nema-14-50r",
+                        "nema-14-60r",
+                        "nema-15-15r",
+                        "nema-15-20r",
+                        "nema-15-30r",
+                        "nema-15-50r",
+                        "nema-15-60r",
+                        "nema-l1-15r",
+                        "nema-l5-15r",
+                        "nema-l5-20r",
+                        "nema-l5-30r",
+                        "nema-l5-50r",
+                        "nema-l6-15r",
+                        "nema-l6-20r",
+                        "nema-l6-30r",
+                        "nema-l6-50r",
+                        "nema-l10-30r",
+                        "nema-l14-20r",
+                        "nema-l14-30r",
+                        "nema-l14-50r",
+                        "nema-l14-60r",
+                        "nema-l15-20r",
+                        "nema-l15-30r",
+                        "nema-l15-50r",
+                        "nema-l15-60r",
+                        "nema-l21-20r",
+                        "nema-l21-30r",
+                        "nema-l22-30r",
+                        "CS6360C",
+                        "CS6364C",
+                        "CS8164C",
+                        "CS8264C",
+                        "CS8364C",
+                        "CS8464C",
+                        "ita-e",
+                        "ita-f",
+                        "ita-g",
+                        "ita-h",
+                        "ita-i",
+                        "ita-j",
+                        "ita-k",
+                        "ita-l",
+                        "ita-m",
+                        "ita-n",
+                        "ita-o",
+                        "ita-multistandard",
+                        "usb-a",
+                        "usb-micro-b",
+                        "usb-c",
+                        "dc-terminal",
+                        "hdot-cx",
+                        "saf-d-grid",
+                        "neutrik-powercon-20a",
+                        "neutrik-powercon-32a",
+                        "neutrik-powercon-true1",
+                        "neutrik-powercon-true1-top",
+                        "ubiquiti-smartpower",
+                        "hardwired",
+                        "other"
+                    ]
+                },
+                "feed-leg": {
+                    "type": "string",
+                    "enum": [
+                        "A",
+                        "B",
+                        "C"
+                    ]
+                }
+            }
+        },
+        "interface": {
+            "type": "object",
+            "properties": {
+                "type": {
+                    "type": "string",
+                    "enum": [
+                        "virtual",
+                        "bridge",
+                        "lag",
+                        "100base-fx",
+                        "100base-lfx",
+                        "100base-tx",
+                        "100base-t1",
+                        "1000base-t",
+                        "2.5gbase-t",
+                        "5gbase-t",
+                        "10gbase-t",
+                        "10gbase-cx4",
+                        "1000base-x-gbic",
+                        "1000base-x-sfp",
+                        "10gbase-x-sfpp",
+                        "10gbase-x-xfp",
+                        "10gbase-x-xenpak",
+                        "10gbase-x-x2",
+                        "25gbase-x-sfp28",
+                        "50gbase-x-sfp56",
+                        "40gbase-x-qsfpp",
+                        "50gbase-x-sfp28",
+                        "100gbase-x-cfp",
+                        "100gbase-x-cfp2",
+                        "200gbase-x-cfp2",
+                        "100gbase-x-cfp4",
+                        "100gbase-x-cxp",
+                        "100gbase-x-cpak",
+                        "100gbase-x-dsfp",
+                        "100gbase-x-sfpdd",
+                        "100gbase-x-qsfp28",
+                        "100gbase-x-qsfpdd",
+                        "200gbase-x-qsfp56",
+                        "200gbase-x-qsfpdd",
+                        "400gbase-x-qsfpdd",
+                        "400gbase-x-osfp",
+                        "400gbase-x-cdfp",
+                        "400gbase-x-cfp8",
+                        "800gbase-x-qsfpdd",
+                        "800gbase-x-osfp",
+                        "1000base-kx",
+                        "10gbase-kr",
+                        "10gbase-kx4",
+                        "25gbase-kr",
+                        "40gbase-kr4",
+                        "50gbase-kr",
+                        "100gbase-kp4",
+                        "100gbase-kr2",
+                        "100gbase-kr4",
+                        "ieee802.11a",
+                        "ieee802.11g",
+                        "ieee802.11n",
+                        "ieee802.11ac",
+                        "ieee802.11ad",
+                        "ieee802.11ax",
+                        "ieee802.11ay",
+                        "ieee802.15.1",
+                        "other-wireless",
+                        "gsm",
+                        "cdma",
+                        "lte",
+                        "sonet-oc3",
+                        "sonet-oc12",
+                        "sonet-oc48",
+                        "sonet-oc192",
+                        "sonet-oc768",
+                        "sonet-oc1920",
+                        "sonet-oc3840",
+                        "1gfc-sfp",
+                        "2gfc-sfp",
+                        "4gfc-sfp",
+                        "8gfc-sfpp",
+                        "16gfc-sfpp",
+                        "32gfc-sfp28",
+                        "64gfc-qsfpp",
+                        "128gfc-qsfp28",
+                        "infiniband-sdr",
+                        "infiniband-ddr",
+                        "infiniband-qdr",
+                        "infiniband-fdr10",
+                        "infiniband-fdr",
+                        "infiniband-edr",
+                        "infiniband-hdr",
+                        "infiniband-ndr",
+                        "infiniband-xdr",
+                        "t1",
+                        "e1",
+                        "t3",
+                        "e3",
+                        "xdsl",
+                        "docsis",
+                        "gpon",
+                        "xg-pon",
+                        "xgs-pon",
+                        "ng-pon2",
+                        "epon",
+                        "10g-epon",
+                        "cisco-stackwise",
+                        "cisco-stackwise-plus",
+                        "cisco-flexstack",
+                        "cisco-flexstack-plus",
+                        "cisco-stackwise-80",
+                        "cisco-stackwise-160",
+                        "cisco-stackwise-320",
+                        "cisco-stackwise-480",
+                        "cisco-stackwise-1t",
+                        "juniper-vcp",
+                        "extreme-summitstack",
+                        "extreme-summitstack-128",
+                        "extreme-summitstack-256",
+                        "extreme-summitstack-512",
+                        "other"
+                    ]
+                },
+                "poe_mode": {
+                    "type": "string",
+                    "enum": [
+                        "pd",
+                        "pse"
+                    ]
+                },
+                "poe_type": {
+                    "type": "string",
+                    "enum": [
+                        "type1-ieee802.3af",
+                        "type2-ieee802.3at",
+                        "type3-ieee802.3bt",
+                        "type4-ieee802.3bt",
+                        "passive-24v-2pair",
+                        "passive-24v-4pair",
+                        "passive-48v-2pair",
+                        "passive-48v-4pair"
+                    ]
+                }
+            }
+        },
+        "front-port": {
+            "type": "object",
+            "properties": {
+                "type": {
+                    "type": "string",
+                    "enum": [
+                        "8p8c",
+                        "8p6c",
+                        "8p4c",
+                        "8p2c",
+                        "6p6c",
+                        "6p4c",
+                        "6p2c",
+                        "4p4c",
+                        "4p2c",
+                        "gg45",
+                        "tera-4p",
+                        "tera-2p",
+                        "tera-1p",
+                        "110-punch",
+                        "bnc",
+                        "f",
+                        "n",
+                        "mrj21",
+                        "fc",
+                        "lc",
+                        "lc-pc",
+                        "lc-upc",
+                        "lc-apc",
+                        "lsh",
+                        "lsh-pc",
+                        "lsh-upc",
+                        "lsh-apc",
+                        "lx5",
+                        "lx5-pc",
+                        "lx5-upc",
+                        "lx5-apc",
+                        "mpo",
+                        "mtrj",
+                        "sc",
+                        "sc-pc",
+                        "sc-upc",
+                        "sc-apc",
+                        "st",
+                        "cs",
+                        "sn",
+                        "sma-905",
+                        "sma-906",
+                        "urm-p2",
+                        "urm-p4",
+                        "urm-p8",
+                        "splice",
+                        "other"
+                    ]
+                }
+            }
+        },
+        "rear-port": {
+            "type": "object",
+            "properties": {
+                "type": {
+                    "type": "string",
+                    "enum": [
+                        "8p8c",
+                        "8p6c",
+                        "8p4c",
+                        "8p2c",
+                        "6p6c",
+                        "6p4c",
+                        "6p2c",
+                        "4p4c",
+                        "4p2c",
+                        "gg45",
+                        "tera-4p",
+                        "tera-2p",
+                        "tera-1p",
+                        "110-punch",
+                        "bnc",
+                        "f",
+                        "n",
+                        "mrj21",
+                        "fc",
+                        "lc",
+                        "lc-pc",
+                        "lc-upc",
+                        "lc-apc",
+                        "lsh",
+                        "lsh-pc",
+                        "lsh-upc",
+                        "lsh-apc",
+                        "lx5",
+                        "lx5-pc",
+                        "lx5-upc",
+                        "lx5-apc",
+                        "mpo",
+                        "mtrj",
+                        "sc",
+                        "sc-pc",
+                        "sc-upc",
+                        "sc-apc",
+                        "st",
+                        "cs",
+                        "sn",
+                        "sma-905",
+                        "sma-906",
+                        "urm-p2",
+                        "urm-p4",
+                        "urm-p8",
+                        "splice",
+                        "other"
+                    ]
+                }
+            }
+        }
+    }
+}

+ 10 - 0
docs/development/release-checklist.md

@@ -70,6 +70,16 @@ Before each release, update each of NetBox's Python dependencies to its most rec
 
 In cases where upgrading a dependency to its most recent release is breaking, it should be constrained to its current minor version in `base_requirements.txt` with an explanatory comment and revisited for the next major NetBox release (see the [Address Constrained Dependencies](#address-constrained-dependencies) section above).
 
+### Rebuild the Device Type Definition Schema
+
+Run the following command to update the device type definition validation schema:
+
+```nohighlight
+./manage.py buildschema --write
+```
+
+This will automatically update the schema file at `contrib/generated_schema.json`.
+
 ### Update Version and Changelog
 
 * Update the `VERSION` constant in `settings.py` to the new release version.

+ 62 - 0
netbox/dcim/management/commands/buildschema.py

@@ -0,0 +1,62 @@
+import json
+import os
+
+from django.conf import settings
+from django.core.management.base import BaseCommand
+from jinja2 import FileSystemLoader, Environment
+
+from dcim.choices import *
+
+TEMPLATE_FILENAME = 'devicetype_schema.jinja2'
+OUTPUT_FILENAME = 'contrib/generated_schema.json'
+
+CHOICES_MAP = {
+    'airflow_choices': DeviceAirflowChoices,
+    'weight_unit_choices': WeightUnitChoices,
+    'subdevice_role_choices': SubdeviceRoleChoices,
+    'console_port_type_choices': ConsolePortTypeChoices,
+    'console_server_port_type_choices': ConsolePortTypeChoices,
+    'power_port_type_choices': PowerPortTypeChoices,
+    'power_outlet_type_choices': PowerOutletTypeChoices,
+    'power_outlet_feedleg_choices': PowerOutletFeedLegChoices,
+    'interface_type_choices': InterfaceTypeChoices,
+    'interface_poe_mode_choices': InterfacePoEModeChoices,
+    'interface_poe_type_choices': InterfacePoETypeChoices,
+    'front_port_type_choices': PortTypeChoices,
+    'rear_port_type_choices': PortTypeChoices,
+}
+
+
+class Command(BaseCommand):
+    help = "Generate JSON schema for validating NetBox device type definitions"
+
+    def add_arguments(self, parser):
+        parser.add_argument(
+            '--write',
+            action='store_true',
+            help="Write the generated schema to file"
+        )
+
+    def handle(self, *args, **kwargs):
+        # Initialize template
+        template_loader = FileSystemLoader(searchpath=f'{settings.TEMPLATES_DIR}/extras/schema/')
+        template_env = Environment(loader=template_loader)
+        template = template_env.get_template(TEMPLATE_FILENAME)
+
+        # Render template
+        context = {
+            key: json.dumps(choices.values())
+            for key, choices in CHOICES_MAP.items()
+        }
+        rendered = template.render(**context)
+
+        if kwargs['write']:
+            # $root/contrib/generated_schema.json
+            filename = os.path.join(os.path.split(settings.BASE_DIR)[0], OUTPUT_FILENAME)
+            with open(filename, mode='w', encoding='UTF-8') as f:
+                f.write(json.dumps(json.loads(rendered), indent=4))
+                f.write('\n')
+                f.close()
+            self.stdout.write(self.style.SUCCESS(f"Schema written to {filename}."))
+        else:
+            self.stdout.write(rendered)

+ 93 - 0
netbox/templates/extras/schema/devicetype_schema.jinja2

@@ -0,0 +1,93 @@
+{
+  "type": "object",
+  "additionalProperties": false,
+  "definitions": {
+    "airflow": {
+      "type": "string",
+      "enum": {{ airflow_choices }}
+    },
+    "weight-unit": {
+      "type": "string",
+      "enum": {{ weight_unit_choices }}
+    },
+    "subdevice-role": {
+      "type": "string",
+      "enum": {{ subdevice_role_choices }}
+    },
+    "console-port": {
+      "type": "object",
+      "properties": {
+        "type": {
+          "type": "string",
+          "enum": {{ console_port_type_choices }}
+        }
+      }
+    },
+    "console-server-port": {
+      "type": "object",
+      "properties": {
+        "type": {
+          "type": "string",
+          "enum": {{ console_server_port_type_choices }}
+        }
+      }
+    },
+    "power-port": {
+      "type": "object",
+      "properties": {
+        "type": {
+          "type": "string",
+          "enum": {{ power_port_type_choices }}
+        }
+      }
+    },
+    "power-outlet": {
+      "type": "object",
+      "properties": {
+        "type": {
+          "type": "string",
+          "enum": {{ power_outlet_type_choices }}
+        },
+        "feed-leg": {
+          "type": "string",
+          "enum": {{ power_outlet_feedleg_choices }}
+        }
+      }
+    },
+    "interface": {
+      "type": "object",
+      "properties": {
+        "type": {
+          "type": "string",
+          "enum": {{ interface_type_choices }}
+        },
+        "poe_mode": {
+          "type": "string",
+          "enum": {{ interface_poe_mode_choices }}
+        },
+        "poe_type": {
+          "type": "string",
+          "enum": {{ interface_poe_type_choices }}
+        }
+      }
+    },
+    "front-port": {
+      "type": "object",
+      "properties": {
+        "type": {
+          "type": "string",
+          "enum": {{ front_port_type_choices }}
+        }
+      }
+    },
+    "rear-port": {
+      "type": "object",
+      "properties": {
+        "type": {
+          "type": "string",
+          "enum": {{ rear_port_type_choices}}
+        }
+      }
+    }
+  }
+}