Skip to content

Commit 43d3c66

Browse files
committed
Merge branch 'Computroniks-computroniks/bug/#311-fix-field-validation'
2 parents b52a383 + af7cf95 commit 43d3c66

File tree

3 files changed

+21
-13
lines changed

3 files changed

+21
-13
lines changed

docs/pages/configuration/directives.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ your-directive:
166166
- condition: null
167167
command: show ip route {target}
168168
field:
169+
description: IP of target
169170
validation: '[0-9a-f\.\:]+'
170171
```
171172

@@ -178,6 +179,7 @@ your-directive:
178179
- condition: null
179180
command: show ip bgp community {target}
180181
field:
182+
description: BGP community to show
181183
options:
182184
- value: "65001:1"
183185
description: Provider A Routes

hyperglass/models/api/query.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
from datetime import datetime
88

99
# Third Party
10-
from pydantic import Field, BaseModel, ConfigDict, field_validator
10+
from pydantic import BaseModel, ConfigDict, field_validator, StringConstraints
11+
from typing_extensions import Annotated
1112

1213
# Project
1314
from hyperglass.log import log
@@ -21,6 +22,11 @@
2122
from ..config.devices import Device
2223

2324

25+
QueryLocation = Annotated[str, StringConstraints(strict=True, min_length=1, strip_whitespace=True)]
26+
QueryTarget = Annotated[str, StringConstraints(min_length=1, strip_whitespace=True)]
27+
QueryType = Annotated[str, StringConstraints(strict=True, min_length=1, strip_whitespace=True)]
28+
29+
2430
class SimpleQuery(BaseModel):
2531
"""A simple representation of a post-validated query."""
2632

@@ -39,12 +45,12 @@ class Query(BaseModel):
3945
model_config = ConfigDict(extra="allow", alias_generator=snake_to_camel, populate_by_name=True)
4046

4147
# Device `name` field
42-
query_location: str = Field(strict=True, min_length=1, strip_whitespace=True)
48+
query_location: QueryLocation
4349

44-
query_target: t.Union[t.List[str], str] = Field(min_length=1, strip_whitespace=True)
50+
query_target: t.Union[t.List[QueryTarget], QueryTarget]
4551

4652
# Directive `id` field
47-
query_type: str = Field(strict=True, min_length=1, strip_whitespace=True)
53+
query_type: QueryType
4854
_kwargs: t.Dict[str, t.Any]
4955

5056
def __init__(self, **data) -> None:

hyperglass/models/config/devices.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -170,22 +170,22 @@ def _validate_directive_attrs(self) -> None:
170170

171171
@field_validator("address")
172172
def validate_address(
173-
cls, value: t.Union[IPv4Address, IPv6Address, str], values: t.Dict[str, t.Any]
173+
cls, value: t.Union[IPv4Address, IPv6Address, str], info: ValidationInfo
174174
) -> t.Union[IPv4Address, IPv6Address, str]:
175175
"""Ensure a hostname is resolvable."""
176176

177177
if not isinstance(value, (IPv4Address, IPv6Address)):
178178
if not any(resolve_hostname(value)):
179179
raise ConfigError(
180180
"Device '{d}' has an address of '{a}', which is not resolvable.",
181-
d=values["name"],
181+
d=info.data["name"],
182182
a=value,
183183
)
184184
return value
185185

186186
@field_validator("avatar")
187187
def validate_avatar(
188-
cls, value: t.Union[FilePath, None], values: t.Dict[str, t.Any]
188+
cls, value: t.Union[FilePath, None], info: ValidationInfo
189189
) -> t.Union[FilePath, None]:
190190
"""Migrate avatar to static directory."""
191191
if value is not None:
@@ -198,7 +198,7 @@ def validate_avatar(
198198
target = Settings.static_path / "images" / value.name
199199
copied = shutil.copy2(value, target)
200200
log.bind(
201-
device=values["name"],
201+
device=info.data["name"],
202202
source=str(value),
203203
destination=str(target),
204204
).debug("Copied device avatar")
@@ -210,24 +210,24 @@ def validate_avatar(
210210
return value
211211

212212
@field_validator("platform", mode="before")
213-
def validate_platform(cls: "Device", value: t.Any, values: t.Dict[str, t.Any]) -> str:
213+
def validate_platform(cls: "Device", value: t.Any, info: ValidationInfo) -> str:
214214
"""Validate & rewrite device platform, set default `directives`."""
215215

216216
if value == "http":
217-
if values.get("http") is None:
217+
if info.data.get("http") is None:
218218
raise ConfigError(
219219
"Device '{device}' has platform 'http' configured, but no http parameters are defined.",
220-
device=values["name"],
220+
device=info.data["name"],
221221
)
222222

223223
if value is None:
224-
if values.get("http") is not None:
224+
if info.data.get("http") is not None:
225225
value = "http"
226226
else:
227227
# Ensure device platform is defined.
228228
raise ConfigError(
229229
"Device '{device}' is missing a 'platform' (Network Operating System) property",
230-
device=values["name"],
230+
device=info.data["name"],
231231
)
232232

233233
if value in SCRAPE_HELPERS.keys():

0 commit comments

Comments
 (0)