Skip to content

Commit

Permalink
fix: add api for edge site (#201)
Browse files Browse the repository at this point in the history
Co-authored-by: 99cloud <[email protected]>
  • Loading branch information
qiaolei1 and 99cloud authored Apr 13, 2023
1 parent a8ad67d commit 0801eb2
Show file tree
Hide file tree
Showing 13 changed files with 500 additions and 153 deletions.
86 changes: 86 additions & 0 deletions apitest/edge_site.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
fixtures:
- ConfigFixture
- SampleDataFixture

defaults:
ssl: False
request_headers:
content-type: application/json
accept: application/json

vars:
- &username 'gabbi_user'
- &password 'dandelion'

tests:
- name: create_user
url: /api/v1/users
method: POST
data:
username: *username
password: *password
is_active: true
status: 200
response_json_paths:
$.username: *username

- name: user_login
url: /api/v1/login
method: POST
data:
username: *username
password: *password
status: 200
response_json_paths:
$.token_type: bearer

- name: create_edge_site
url: /api/v1/edge_site
method: POST
request_headers:
Authorization: Bearer $HISTORY['user_login'].$RESPONSE['$.access_token']
data:
name: "test create"
edgeSiteDandelionEndpoint: "http://127.0.0.1:28300/"
areaCode: "320115"
desc: "test create"
centerDandelionEndpoint: "http://127.0.0.1:28300/"
status: 201
response_json_paths:
$.name: "test create"

- name: edge_site_list
url: /api/v1/edge_site
method: GET
request_headers:
Authorization: Bearer $HISTORY['user_login'].$RESPONSE['$.access_token']
status: 200

- name: edge_site_update
url: /api/v1/edge_site/$HISTORY['create_edge_site'].$RESPONSE['$.id']
method: PATCH
request_headers:
Authorization: Bearer $HISTORY['user_login'].$RESPONSE['$.access_token']
data:
name: "test update"
areaCode: "320106"
desc: "test update"
status: 200
response_json_paths:
$.name: "test update"
$.areaCode: "320106"
$.desc: "test update"

- name: delete_edge_site
url: /api/v1/edge_site/$HISTORY['create_edge_site'].$RESPONSE['$.id']
method: DELETE
request_headers:
Authorization: Bearer $HISTORY['user_login'].$RESPONSE['$.access_token']
status: 204

- name: delete_user
url: /api/v1/users/$HISTORY['create_user'].$RESPONSE['$.id']
method: DELETE
request_headers:
Authorization: Bearer $HISTORY['user_login'].$RESPONSE['$.access_token']
status: 204
1 change: 0 additions & 1 deletion dandelion/api/api_v1/endpoints/cloud_homes.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ def route_info(
redis_conn: Redis = Depends(deps.get_redis_conn),
current_user: models.User = Depends(deps.get_current_user),
) -> schemas.RouteInfo:

key = "ROUTE_INFO"
vehicle_total = (
Optional_util.none(redis_conn.hget(key, "vehicleTotal")).map(lambda v: int(v)).orElse(0)
Expand Down
25 changes: 17 additions & 8 deletions dandelion/api/api_v1/endpoints/edge_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,23 @@ def get_all(
total, data = crud.edge_site.get_multi_with_total(
db, skip=skip, limit=page_size, name=name, area_code=area_code
)
return schemas.EdgeNodes(
total=total,
data=[
system_config = crud.system_config.get(db=db, id=1)
data_all = (
[
dict(
ip=urlparse(node.edge_site_dandelion_endpoint).netloc.split(":")[0],
name=node.name,
id=node.id,
ip=urlparse(site.edge_site_dandelion_endpoint).netloc.split(":")[0],
name=site.name,
id=site.id,
)
for node in data
],
for site in data
]
if data
else [
dict(
ip="127.0.0.1",
name="无边缘连接-默认自身站点",
id=system_config.edge_site_id if system_config else 1,
)
]
)
return schemas.EdgeNodes(total=total, data=data_all)
68 changes: 66 additions & 2 deletions dandelion/api/api_v1/endpoints/edge_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
import os

import requests
from fastapi import APIRouter, Depends, Query, status
from fastapi import APIRouter, Depends, Query, Response, status
from oslo_config import cfg
from sqlalchemy import exc as sql_exc
from sqlalchemy.orm import Session

from dandelion import constants, crud, models, schemas
from dandelion.api import deps
from dandelion.api.deps import OpenV2XHTTPException as HTTPException
from dandelion.api.deps import OpenV2XHTTPException as HTTPException, error_handle

router = APIRouter()
CONF: cfg = cfg.CONF
Expand Down Expand Up @@ -115,3 +115,67 @@ def create(
crud.edge_site.remove(db=db, id=edge_node_in_db.id)
raise HTTPException(status_code=edge_create_res.status_code, detail=edge_create_res.json())
return edge_node_in_db.to_all_dict()


@router.patch(
"/{edge_site_id}",
response_model=schemas.EdgeSite,
status_code=status.HTTP_200_OK,
description="""
Update a edge site.
""",
responses={
status.HTTP_200_OK: {"model": schemas.EdgeSite, "description": "OK"},
status.HTTP_401_UNAUTHORIZED: {
"model": schemas.ErrorMessage,
"description": "Unauthorized",
},
status.HTTP_403_FORBIDDEN: {"model": schemas.ErrorMessage, "description": "Forbidden"},
status.HTTP_404_NOT_FOUND: {"model": schemas.ErrorMessage, "description": "Not Found"},
},
)
def update(
edge_site_id: int,
edge_site_in: schemas.EdgeSiteUpdate,
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_user),
) -> schemas.EdgeSite:
edge_site_in_db = deps.crud_get(
db=db, obj_id=edge_site_id, crud_model=crud.edge_site, detail="Edge Site"
)
try:
new_edge_site_in_db = crud.edge_site.update(
db, db_obj=edge_site_in_db, obj_in=edge_site_in
)
except (sql_exc.DataError, sql_exc.IntegrityError) as ex:
raise error_handle(ex, "name", edge_site_in.name)
return new_edge_site_in_db.to_all_dict()


@router.delete(
"/{edge_site_id}",
status_code=status.HTTP_204_NO_CONTENT,
description="""
Delete a Edge Site.
""",
responses={
status.HTTP_401_UNAUTHORIZED: {
"model": schemas.ErrorMessage,
"description": "Unauthorized",
},
status.HTTP_403_FORBIDDEN: {"model": schemas.ErrorMessage, "description": "Forbidden"},
status.HTTP_404_NOT_FOUND: {"model": schemas.ErrorMessage, "description": "Not Found"},
},
response_class=Response,
response_description="No Content",
)
def delete(
edge_site_id: int,
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_user),
) -> Response:
deps.crud_get(db=db, obj_id=edge_site_id, crud_model=crud.edge_site, detail="Edge Site")
crud.edge_site.remove(db, id=edge_site_id)
return Response(content=None, status_code=status.HTTP_204_NO_CONTENT)
12 changes: 6 additions & 6 deletions dandelion/api/api_v1/endpoints/map_rsus.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

from datetime import datetime
from logging import LoggerAdapter
from typing import Dict, List, Optional, Union
from typing import Dict, List, Union

from fastapi import APIRouter, Depends, Query, Response, status
from fastapi import APIRouter, Depends, Path, Query, Response, status
from oslo_log import log
from sqlalchemy.orm import Session

Expand Down Expand Up @@ -49,9 +49,9 @@
},
)
def create(
map_id: int,
map_rsu_in: schemas.MapRSUCreate,
*,
map_id: int = Path(),
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_user),
) -> schemas.MapRSU:
Expand Down Expand Up @@ -98,9 +98,9 @@ def create(
response_description="No Content",
)
def delete(
map_id: int,
map_rsu_id: int,
*,
map_id: int = Path(),
map_rsu_id: int = Path(),
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_user),
) -> Response:
Expand Down Expand Up @@ -130,7 +130,7 @@ def delete(
},
)
def get_all(
map_id: Optional[int] = Query(None, alias="mapId", description="Filter by mapId"),
map_id: int = Path(),
page_num: int = Query(1, alias="pageNum", ge=1, description="Page number"),
page_size: int = Query(10, alias="pageSize", ge=-1, description="Page size"),
db: Session = Depends(deps.get_db),
Expand Down
6 changes: 3 additions & 3 deletions dandelion/api/api_v1/endpoints/mngs.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from logging import LoggerAdapter
from typing import List, Optional

from fastapi import APIRouter, Body, Depends, Query, status
from fastapi import APIRouter, Body, Depends, Path, Query, status
from oslo_log import log
from sqlalchemy import exc as sql_exc
from sqlalchemy.orm import Session
Expand Down Expand Up @@ -118,7 +118,7 @@ def update(
},
)
def down(
mng_id: int = Query(..., alias="mng_id", gt=0, description="MNG id"),
mng_id: int = Path(),
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_user),
Expand Down Expand Up @@ -150,7 +150,7 @@ def down(
},
)
def copy(
mng_id: int = Query(..., alias="mng_id", gt=0, description="MNG id"),
mng_id: int = Path(),
mng_copy_in: schemas.MNGCopy = Body(..., alias="mng_copy_in", description="MNG copy"),
*,
db: Session = Depends(deps.get_db),
Expand Down
3 changes: 2 additions & 1 deletion dandelion/db/redis_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import urllib
from logging import LoggerAdapter
from typing import List

import redis
from oslo_config import cfg
Expand Down Expand Up @@ -94,7 +95,7 @@ def setup_redis() -> None:
# sentinel arg.
global REDIS_CONN
if "sentinel" in kwargs:
sentinel_hosts = [
sentinel_hosts: List = [
tuple(fallback.split(":")) for fallback in kwargs.get("sentinel_fallback", [])
]
sentinel_hosts.insert(0, (kwargs["host"], kwargs["port"]))
Expand Down
22 changes: 9 additions & 13 deletions dandelion/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@

mode_conf = CONF.mode

if CONF.cors.origins:
app.add_middleware(
CORSMiddleware,
allow_origins=CONF.cors.origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)


# Startup
@app.on_event("startup")
Expand Down Expand Up @@ -77,19 +86,6 @@ def setup_redis() -> None:
redis_pool.setup_redis()


@app.on_event("startup")
def setup_app():
# Set all CORS enabled origins
if CONF.cors.origins:
app.add_middleware(
CORSMiddleware,
allow_origins=CONF.cors.origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)


@app.on_event("startup")
def setup_rsu_running():
job_stores = {"default": MemoryJobStore()}
Expand Down
4 changes: 2 additions & 2 deletions dandelion/schemas/edge_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ class Config:

# Additional properties to return via API
class EdgeNode(EdgeNodeInDBBase):
name: str = Field(None, alias="name", description="Edge Node Name")
ip: str = Field(None, alias="ip", description="Edge Node ip")
name: str = Field(..., alias="name", description="Edge Node Name")
ip: str = Field(..., alias="ip", description="Edge Node ip")


class EdgeNodes(BaseModel):
Expand Down
2 changes: 2 additions & 0 deletions dandelion/schemas/edge_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class EdgeSiteUpdate(BaseModel):
""""""

name: Optional[str] = Field(None, alias="name", description="Edge Site Name")
area_code: Optional[str] = Field(None, alias="areaCode", description="Edge Site Area Code")
desc: Optional[str] = Field(None, alias="desc", description="Edge Site desc")


class EdgeSiteInDBBase(EdgeSiteBase):
Expand Down
1 change: 1 addition & 0 deletions dandelion/schemas/system_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,5 @@ class Config:

# Additional properties to return via API
class SystemConfig(SystemConfigInDBBase):
edge_site_id: Optional[int] = Field(None, alias="edgeSiteID", description="Edge Site ID")
mode: Optional[str] = Field(None, alias="mode", description="Node Mode")
1 change: 1 addition & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# https://mypy.readthedocs.io/en/stable/config_file.html
[mypy]
plugins = pydantic.mypy
# Import discovery
ignore_missing_imports = true
follow_imports = normal
Expand Down
Loading

0 comments on commit 0801eb2

Please sign in to comment.