diff --git a/octodns/record/a.py b/octodns/record/a.py index 313f53c..c36d83d 100644 --- a/octodns/record/a.py +++ b/octodns/record/a.py @@ -13,6 +13,7 @@ from .ip import _IpValue class Ipv4Value(_IpValue): _address_type = _IPv4Address _address_name = 'IPv4' + _format = 'ipv4' Ipv4Address = Ipv4Value diff --git a/octodns/record/aaaa.py b/octodns/record/aaaa.py index 3d0a3e4..2e60eba 100644 --- a/octodns/record/aaaa.py +++ b/octodns/record/aaaa.py @@ -13,6 +13,7 @@ from .ip import _IpValue class Ipv6Value(_IpValue): _address_type = _IPv6Address _address_name = 'IPv6' + _format = 'ipv6' Ipv6Address = Ipv6Value diff --git a/octodns/record/base.py b/octodns/record/base.py index ab35755..501820b 100644 --- a/octodns/record/base.py +++ b/octodns/record/base.py @@ -41,6 +41,54 @@ class Record(EqualityTupleMixin): def registered_types(cls): return cls._CLASSES + @classmethod + def jsonschema(cls): + schema = { + # base Record requirements + 'title': 'Record', + 'type': 'object', + 'properties': { + 'type': {'type': 'string', 'enum': list(cls._CLASSES.keys())} + }, + } + + class_schemas = [] + for _type, _class in cls._CLASSES.items(): + _value_type = _class._value_type + if not hasattr(_value_type, 'jsonschema'): + # type does not support schema + continue + class_schemas.append( + { + 'if': {'properties': {'type': {'enum': [_type]}}}, + 'then': { + 'title': _type, + 'properties': { + 'type': {}, + 'ttl': { + 'type': 'integer', + 'minimum': 0, + 'maximum': 86400, + }, + 'value': _class._value_type.jsonschema(), + }, + 'required': ['ttl', 'type', 'value'], + "unevaluatedProperties": False, + }, + } + ) + + if class_schemas: + schema['allOf'] = class_schemas + + # validate(schema=schema, instance={ + # 'type': 'A', + # 'ttl': 42, + # 'value': 'nope', + # }, format_checker=Draft202012Validator.FORMAT_CHECKER) + + return schema + @classmethod def new(cls, zone, name, data, source=None, lenient=False): reasons = [] diff --git a/octodns/record/ip.py b/octodns/record/ip.py index ab838af..3adbe55 100644 --- a/octodns/record/ip.py +++ b/octodns/record/ip.py @@ -4,6 +4,14 @@ class _IpValue(str): + @classmethod + def jsonschema(cls): + return { + 'type': 'string', + #'pattern': cls._regex, + 'format': cls._format, + } + @classmethod def parse_rdata_text(cls, value): return value diff --git a/octodns/record/srv.py b/octodns/record/srv.py index 9a49c47..8335dfb 100644 --- a/octodns/record/srv.py +++ b/octodns/record/srv.py @@ -39,6 +39,35 @@ class SrvValue(EqualityTupleMixin, dict): 'target': target, } + @classmethod + def jsonschema(cls): + return { + 'type': 'object', + 'properties': { + 'priority': { + 'type': 'integer', + 'minimum': 0, + 'maximum': 9999999999, + }, + 'weight': { + 'type': 'integer', + 'minimum': 0, + 'maximum': 9999999999, + }, + 'port': { + 'type': 'integer', + 'minimum': 0, + 'maximum': 9999999999, + }, + 'target': { + 'type': 'string', + # TODO: pattern FQDN + }, + }, + 'required': ['priority', 'weight', 'port', 'target'], + "unevaluatedProperties": False, + } + @classmethod def validate(cls, data, _type): reasons = []