1
0
mirror of https://github.com/checktheroads/hyperglass synced 2024-05-11 05:55:08 +00:00

add API endpoint docs

This commit is contained in:
checktheroads
2020-02-01 12:50:12 -10:00
parent 0d91c79af9
commit af4a0b0ea7
4 changed files with 235 additions and 10 deletions

View File

@@ -8,10 +8,11 @@ filename=*.py
per-file-ignores= per-file-ignores=
# Disable redefinition warning for exception handlers # Disable redefinition warning for exception handlers
hyperglass/api.py:F811 hyperglass/api.py:F811
# Disable string length warnings so I can actually read the commands # Disable string length warnings so one can actually read the commands
hyperglass/configuration/models/commands.py:E501,C0301 hyperglass/configuration/models/commands.py:E501,C0301
# Disable string length warnings so I can actually read the messages hyperglass/configuration/models/docs.py:E501,C0301
hyperglass/configuration/models/messages.py:E501,C0301 hyperglass/configuration/models/messages.py:E501,C0301
hyperglass/api/models/response.py:E501,C0301
# Disable classmethod warning for validator decorators # Disable classmethod warning for validator decorators
hyperglass/configuration/models/*.py:N805,E0213,R0903 hyperglass/configuration/models/*.py:N805,E0213,R0903
hyperglass/models/*.py:N805,E0213,R0903 hyperglass/models/*.py:N805,E0213,R0903

View File

@@ -20,6 +20,8 @@ from hyperglass.api.error_handlers import validation_handler
from hyperglass.api.events import on_shutdown from hyperglass.api.events import on_shutdown
from hyperglass.api.events import on_startup from hyperglass.api.events import on_startup
from hyperglass.api.models.response import QueryResponse from hyperglass.api.models.response import QueryResponse
from hyperglass.api.models.response import RoutersResponse
from hyperglass.api.models.response import SupportedQueryResponse
from hyperglass.api.routes import docs from hyperglass.api.routes import docs
from hyperglass.api.routes import queries from hyperglass.api.routes import queries
from hyperglass.api.routes import query from hyperglass.api.routes import query
@@ -102,19 +104,33 @@ app.add_middleware(
) )
app.add_api_route( app.add_api_route(
path="/api/devices", endpoint=routers, methods=["GET"], response_class=UJSONResponse path="/api/devices",
endpoint=routers,
methods=["GET"],
response_model=RoutersResponse,
response_class=UJSONResponse,
summary=params.docs.devices.summary,
description=params.docs.devices.description,
tags=[params.docs.devices.title],
) )
app.add_api_route( app.add_api_route(
path="/api/queries", endpoint=queries, methods=["GET"], response_class=UJSONResponse path="/api/queries",
endpoint=queries,
methods=["GET"],
response_class=UJSONResponse,
response_model=SupportedQueryResponse,
summary=params.docs.queries.summary,
description=params.docs.queries.description,
tags=[params.docs.queries.title],
) )
app.add_api_route( app.add_api_route(
path="/api/query/", path="/api/query/",
endpoint=query, endpoint=query,
methods=["POST"], methods=["POST"],
summary=params.docs.endpoint_summary, summary=params.docs.query.summary,
description=params.docs.endpoint_description, description=params.docs.query.description,
response_model=QueryResponse, response_model=QueryResponse,
tags=[params.docs.group_title], tags=[params.docs.query.title],
response_class=UJSONResponse, response_class=UJSONResponse,
) )
app.add_api_route(path="/api/docs", endpoint=docs, include_in_schema=False) app.add_api_route(path="/api/docs", endpoint=docs, include_in_schema=False)

View File

@@ -4,6 +4,7 @@ from typing import List
# Third Party Imports # Third Party Imports
from pydantic import BaseModel from pydantic import BaseModel
from pydantic import StrictBool
from pydantic import StrictStr from pydantic import StrictStr
from pydantic import constr from pydantic import constr
@@ -15,6 +16,23 @@ class QueryError(BaseModel):
level: constr(regex=r"(success|warning|error|danger)") level: constr(regex=r"(success|warning|error|danger)")
keywords: List[StrictStr] keywords: List[StrictStr]
class Config:
"""Pydantic model configuration."""
title = "Query Error"
description = (
"Response received when there is an error executing the requested query."
)
schema_extra = {
"examples": [
{
"output": "192.0.2.1/32 is not allowed.",
"level": "danger",
"keywords": ["192.0.2.1/32"],
}
]
}
class QueryResponse(BaseModel): class QueryResponse(BaseModel):
"""Query response model.""" """Query response model."""
@@ -22,3 +40,173 @@ class QueryResponse(BaseModel):
output: StrictStr output: StrictStr
level: constr(regex=r"(success|warning|error|danger)") level: constr(regex=r"(success|warning|error|danger)")
keywords: List[StrictStr] = [] keywords: List[StrictStr] = []
class Config:
"""Pydantic model configuration."""
title = "Query Response"
description = "Looking glass response"
schema_extra = {
"examples": [
{
"output": """
BGP routing table entry for 1.1.1.0/24, version 224184946
BGP Bestpath: deterministic-med
Paths: (12 available, best #9, table default)
Advertised to update-groups:
1 40
13335, (aggregated by 13335 172.68.129.1), (received & used)
199.34.92.5 (metric 51) from 199.34.92.5 (199.34.92.5)
Origin IGP, metric 0, localpref 250, valid, internal
Community: 14525:1021 14525:2840 14525:3003 14525:4003 14525:5200 14525:5300 14525:5306
13335, (aggregated by 13335 172.68.129.1), (received & used)
199.34.92.6 (metric 51) from 199.34.92.6 (199.34.92.6)
Origin IGP, metric 0, localpref 250, valid, internal
Community: 14525:1021 14525:2840 14525:3003 14525:4003 14525:5200 14525:5300 14525:5306
1299 13335, (aggregated by 13335 162.158.140.1)
62.115.171.124 from 62.115.171.124 (2.255.254.51)
Origin IGP, metric 0, localpref 100, weight 200, valid, external
Community: 14525:0 14525:1021 14525:2840 14525:3001 14525:4001 14525:5100 14525:5103
1299 13335, (aggregated by 13335 162.158.140.1), (received-only)
62.115.171.124 from 62.115.171.124 (2.255.254.51)
Origin IGP, localpref 100, valid, external
Community: 1299:35000
174 13335, (aggregated by 13335 108.162.239.1)
199.34.92.7 (metric 1100) from 199.34.92.7 (199.34.92.7)
Origin IGP, metric 0, localpref 100, weight 125, valid, internal
Community: 14525:0 14525:840 14525:1021 14525:3004 14525:4004 14525:5100 14525:5101
174 13335, (aggregated by 13335 108.162.239.1), (received-only)
199.34.92.7 (metric 1100) from 199.34.92.7 (199.34.92.7)
Origin IGP, metric 0, localpref 100, valid, internal
Community: 14525:0 14525:840 14525:1021 14525:3004 14525:4004 14525:5100 14525:5101
174 13335, (aggregated by 13335 162.158.140.1), (Received from a RR-client)
199.34.92.2 (metric 26) from 199.34.92.2 (199.34.92.2)
Origin IGP, metric 0, localpref 100, weight 200, valid, internal
Community: 14525:0 14525:1021 14525:2840 14525:3001 14525:4001 14525:5100 14525:5101
174 13335, (aggregated by 13335 162.158.140.1), (Received from a RR-client), (received-only)
199.34.92.2 (metric 26) from 199.34.92.2 (199.34.92.2)
Origin IGP, metric 0, localpref 100, valid, internal
Community: 14525:0 14525:1021 14525:2840 14525:3001 14525:4001 14525:5100 14525:5101
174 13335, (aggregated by 13335 162.158.140.1)
38.140.141.25 from 38.140.141.25 (154.26.6.194)
Origin IGP, metric 0, localpref 100, weight 200, valid, external, best
Community: 14525:0 14525:1021 14525:2840 14525:3001 14525:4001 14525:5100 14525:5101
174 13335, (aggregated by 13335 162.158.140.1), (received-only)
38.140.141.25 from 38.140.141.25 (154.26.6.194)
Origin IGP, metric 2020, localpref 100, valid, external
Community: 174:21001 174:22013
3257 13335, (aggregated by 13335 141.101.72.1)
199.34.92.3 (metric 200) from 199.34.92.3 (199.34.92.3)
Origin IGP, metric 0, localpref 100, weight 200, valid, internal
Community: 14525:0 14525:840 14525:1021 14525:3002 14525:4002 14525:5100 14525:5104
3257 13335, (aggregated by 13335 141.101.72.1), (received-only)
199.34.92.3 (metric 200) from 199.34.92.3 (199.34.92.3)
Origin IGP, metric 0, localpref 100, valid, internal
Community: 14525:0 14525:840 14525:1021 14525:3002 14525:4002 14525:5100 14525:5104
""",
"level": "success",
"keywords": ["1.1.1.0/24", "best #9"],
}
]
}
class Vrf(BaseModel):
"""Response model for /api/devices VRFs."""
name: StrictStr
display_name: StrictStr
class Config:
"""Pydantic model configuration."""
title = "VRF"
description = "VRF attributes"
schema_extra = {
"examples": [
{"name": "default", "display_name": "Global Routing Table"},
{"name": "customer_vrf_name", "display_name": "Customer Name"},
]
}
class Network(BaseModel):
"""Response model for /api/devices networks."""
name: StrictStr
display_name: StrictStr
class Config:
"""Pydantic model configuration."""
title = "Network"
description = "Network/ASN attributes"
schema_extra = {"examples": [{"name": "primary", "display_name": "AS65000"}]}
class Router(BaseModel):
"""Response model for /api/devices list items."""
name: StrictStr
network: Network
location: StrictStr
display_name: StrictStr
vrfs: List[Vrf]
class Config:
"""Pydantic model configuration."""
title = "Device"
description = "Per-device attributes"
schema_extra = {
"examples": [
{
"name": "router01-nyc01",
"location": "nyc01",
"display_name": "New York City, NY",
}
]
}
class RoutersResponse(BaseModel):
"""Response model for /api/devices endpoint."""
__root__: List[Router]
class Config:
"""Pydantic model configuration."""
title = "Devices"
description = "List of all devices"
class SupportedQuery(BaseModel):
"""Response model for /api/queries list items."""
name: StrictStr
display_name: StrictStr
enable: StrictBool
class Config:
"""Pydantic model configuration."""
title = "Query Type"
description = "If enabled is `true`, the `name` field may be used to specify the query type."
schema_extra = {
"examples": [
{"name": "bgp_route", "display_name": "BGP Route", "enable": True}
]
}
class SupportedQueryResponse(BaseModel):
"""Response model for /api/queries endpoint."""
__root__: List[SupportedQuery]
class Config:
"""Pydantic model configuration."""
title = "Supported Query Types"
description = "Enabled query type attributes."

View File

@@ -9,13 +9,33 @@ from hyperglass.configuration.models._utils import AnyUri
from hyperglass.configuration.models._utils import HyperglassModel from hyperglass.configuration.models._utils import HyperglassModel
class EndpointConfig(HyperglassModel):
"""Validation model for per API endpoint documentation."""
title: StrictStr
description: StrictStr
summary: StrictStr
class Docs(HyperglassModel): class Docs(HyperglassModel):
"""Validation model for params.docs.""" """Validation model for params.docs."""
enable: StrictBool = True enable: StrictBool = True
mode: constr(regex=r"(swagger|redoc)") = "swagger" mode: constr(regex=r"(swagger|redoc)") = "swagger"
uri: AnyUri = "/docs" uri: AnyUri = "/docs"
endpoint_summary: StrictStr = "Query Endpoint"
endpoint_description: StrictStr = "Request a query response per-location."
group_title: StrictStr = "Queries"
openapi_url: AnyUri = "/openapi.json" openapi_url: AnyUri = "/openapi.json"
query: EndpointConfig = {
"title": "Submit Query",
"description": "Request a query response per-location.",
"summary": "Query the Looking Glass",
}
devices: EndpointConfig = EndpointConfig(
title="Devices",
description="List of all devices/locations with associated identifiers, display names, networks, & VRFs.",
summary="Devices List",
)
queries: EndpointConfig = EndpointConfig(
title="Supported Queries",
description="List of supported query types.",
summary="Query Types",
)