mirror of
https://github.com/netbox-community/devicetype-library.git
synced 2024-11-21 16:03:23 +01:00
Module types (#659)
* Extend tests to support moule types * Add Juniper EX9200-32XS module type * Fix YAML formatting
This commit is contained in:
parent
05787c3851
commit
8ca95dacef
@ -31,7 +31,7 @@ The following fields may optionally be declared:
|
||||
- `subdevice_role`: Indicates that this is a `parent` or `child` device. (Default: None)
|
||||
|
||||
For further detail on these attributes and those listed below, please reference the
|
||||
[schema definition](tests/schema.json).
|
||||
[schema definitions](tests/schema/).
|
||||
|
||||
### Component Definitions
|
||||
|
||||
|
69
module-types/Juniper/EX9200-32XS.yaml
Normal file
69
module-types/Juniper/EX9200-32XS.yaml
Normal file
@ -0,0 +1,69 @@
|
||||
---
|
||||
manufacturer: Juniper
|
||||
model: EX9200-32XS
|
||||
comments: 32x10GE interfaces
|
||||
interfaces:
|
||||
- name: xe-{module}/0/0
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/0/1
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/0/2
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/0/3
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/0/4
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/0/5
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/0/6
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/0/7
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/1/0
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/1/1
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/1/2
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/1/3
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/1/4
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/1/5
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/1/6
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/1/7
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/2/0
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/2/1
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/2/2
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/2/3
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/2/4
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/2/5
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/2/6
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/2/7
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/3/0
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/3/1
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/3/2
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/3/3
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/3/4
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/3/5
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/3/6
|
||||
type: 10gbase-x-sfpp
|
||||
- name: xe-{module}/3/7
|
||||
type: 10gbase-x-sfpp
|
@ -1,111 +1,7 @@
|
||||
{
|
||||
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"manufacturer": {
|
||||
"type": "string"
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"slug": {
|
||||
"type": "string",
|
||||
"pattern": "^[-a-zA-Z0-9_]+$"
|
||||
},
|
||||
"part_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"u_height": {
|
||||
"type": "integer"
|
||||
},
|
||||
"is_full_depth": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"airflow": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"front-to-rear",
|
||||
"rear-to-front",
|
||||
"left-to-right",
|
||||
"right-to-left",
|
||||
"side-to-rear",
|
||||
"passive"
|
||||
]
|
||||
},
|
||||
"subdevice_role": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"parent",
|
||||
"child"
|
||||
]
|
||||
},
|
||||
"console-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/console-port"
|
||||
}
|
||||
},
|
||||
"console-server-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/console-server-port"
|
||||
}
|
||||
},
|
||||
"power-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/power-port"
|
||||
}
|
||||
},
|
||||
"power-outlets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/power-outlet"
|
||||
}
|
||||
},
|
||||
"interfaces": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/interface"
|
||||
}
|
||||
},
|
||||
"front-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/front-port"
|
||||
}
|
||||
},
|
||||
"rear-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/rear-port"
|
||||
}
|
||||
},
|
||||
"module-bays": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/module-bay"
|
||||
}
|
||||
},
|
||||
"device-bays": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/device-bay"
|
||||
}
|
||||
},
|
||||
"inventory-items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/inventory-item"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["manufacturer", "model", "slug"],
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"console-port": {
|
107
schema/devicetype.json
Normal file
107
schema/devicetype.json
Normal file
@ -0,0 +1,107 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"manufacturer": {
|
||||
"type": "string"
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"slug": {
|
||||
"type": "string",
|
||||
"pattern": "^[-a-zA-Z0-9_]+$"
|
||||
},
|
||||
"part_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"u_height": {
|
||||
"type": "integer"
|
||||
},
|
||||
"is_full_depth": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"airflow": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"front-to-rear",
|
||||
"rear-to-front",
|
||||
"left-to-right",
|
||||
"right-to-left",
|
||||
"side-to-rear",
|
||||
"passive"
|
||||
]
|
||||
},
|
||||
"subdevice_role": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"parent",
|
||||
"child"
|
||||
]
|
||||
},
|
||||
"console-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/console-port"
|
||||
}
|
||||
},
|
||||
"console-server-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/console-server-port"
|
||||
}
|
||||
},
|
||||
"power-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/power-port"
|
||||
}
|
||||
},
|
||||
"power-outlets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/power-outlet"
|
||||
}
|
||||
},
|
||||
"interfaces": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/interface"
|
||||
}
|
||||
},
|
||||
"front-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/front-port"
|
||||
}
|
||||
},
|
||||
"rear-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/rear-port"
|
||||
}
|
||||
},
|
||||
"module-bays": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/module-bay"
|
||||
}
|
||||
},
|
||||
"device-bays": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/device-bay"
|
||||
}
|
||||
},
|
||||
"inventory-items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/inventory-item"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["manufacturer", "model", "slug"],
|
||||
"additionalProperties": false
|
||||
}
|
61
schema/moduletype.json
Normal file
61
schema/moduletype.json
Normal file
@ -0,0 +1,61 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"manufacturer": {
|
||||
"type": "string"
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"part_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"console-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/console-port"
|
||||
}
|
||||
},
|
||||
"console-server-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/console-server-port"
|
||||
}
|
||||
},
|
||||
"power-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/power-port"
|
||||
}
|
||||
},
|
||||
"power-outlets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/power-outlet"
|
||||
}
|
||||
},
|
||||
"interfaces": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/interface"
|
||||
}
|
||||
},
|
||||
"front-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/front-port"
|
||||
}
|
||||
},
|
||||
"rear-ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "components.json#/definitions/rear-port"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["manufacturer", "model"],
|
||||
"additionalProperties": false
|
||||
}
|
@ -1,21 +1,41 @@
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import pytest
|
||||
import yaml
|
||||
from jsonschema import validate
|
||||
from jsonschema import validate, RefResolver, Draft4Validator
|
||||
from jsonschema.exceptions import ValidationError
|
||||
|
||||
|
||||
SCHEMAS = (
|
||||
('device-types', 'devicetype.json'),
|
||||
('module-types', 'moduletype.json'),
|
||||
)
|
||||
|
||||
|
||||
def _get_definition_files():
|
||||
"""
|
||||
Return a list of all definition files.
|
||||
Return a list of all definition files within the specified path.
|
||||
"""
|
||||
return [f for f in glob.glob("device-types/*/*", recursive=True)]
|
||||
ret = []
|
||||
|
||||
for path, schema in SCHEMAS:
|
||||
|
||||
# Initialize the schema
|
||||
with open(f"schema/{schema}") as schema_file:
|
||||
schema = json.loads(schema_file.read())
|
||||
|
||||
# Validate that the schema exists
|
||||
assert schema, f"Schema definition for {path} is empty!"
|
||||
|
||||
# Map each definition file to its schema
|
||||
for f in glob.glob(f"{path}/*/*", recursive=True):
|
||||
ret.append((f, schema))
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
# Initialize schema
|
||||
with open("tests/schema.json") as schema_file:
|
||||
schema = json.loads(schema_file.read())
|
||||
definition_files = _get_definition_files()
|
||||
|
||||
|
||||
def test_environment():
|
||||
@ -23,16 +43,13 @@ def test_environment():
|
||||
Run basic sanity checks on the environment to ensure tests are running correctly.
|
||||
"""
|
||||
# Validate that definition files exist
|
||||
assert _get_definition_files(), "No definition files found!"
|
||||
|
||||
# Validate that the schema exists
|
||||
assert schema, "Schema definition is empty!"
|
||||
assert definition_files, "No definition files found!"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("file_path", _get_definition_files())
|
||||
def test_definition(file_path):
|
||||
@pytest.mark.parametrize(('file_path', 'schema'), definition_files)
|
||||
def test_definitions(file_path, schema):
|
||||
"""
|
||||
Validate each DeviceType definition file using the provided JSON schema.
|
||||
Validate each definition file using the provided JSON schema.
|
||||
"""
|
||||
# Check file extension
|
||||
assert file_path.split('.')[-1] in ('yaml', 'yml'), f"Invalid file extension: {file_path}"
|
||||
@ -41,14 +58,14 @@ def test_definition(file_path):
|
||||
with open(file_path) as definition_file:
|
||||
content = definition_file.read()
|
||||
|
||||
# Check for trailing newline
|
||||
assert content[-1] == '\n', "Missing trailing newline"
|
||||
# Check for trailing newline
|
||||
assert content.endswith('\n'), "Missing trailing newline"
|
||||
|
||||
# Load YAML data
|
||||
definition = yaml.load(content, Loader=yaml.SafeLoader)
|
||||
# Load YAML data from file
|
||||
definition = yaml.load(content, Loader=yaml.SafeLoader)
|
||||
|
||||
# Run validation
|
||||
try:
|
||||
validate(definition, schema=schema)
|
||||
resolver = RefResolver(f'file://{os.getcwd()}/schema/devicetype.json', schema)
|
||||
Draft4Validator(schema, resolver=resolver).validate(definition)
|
||||
except ValidationError as e:
|
||||
pytest.fail(f"{file_path} failed validation: {e}", False)
|
||||
|
Loading…
Reference in New Issue
Block a user