91 lines
2.5 KiB
Python

import uuid
from sqlalchemy import select, insert, bindparam
from sqlalchemy.orm import Session
from starlette.exceptions import HTTPException
from starlette.requests import Request
from fastapi import APIRouter
from starlette.responses import JSONResponse
from pillar_tool.db import Host
from pillar_tool.db.queries.host_queries import create_host
from pillar_tool.schemas import HostCreateParams
from pillar_tool.util.validation import validate_fqdn, split_and_validate_path
router = APIRouter(
prefix="/host",
tags=["Host"],
)
@router.get("")
def hosts_get(req: Request):
db: Session = req.state.db
@router.get("/{fqdn}")
def host_get(req: Request, fqdn: str):
db: Session = req.state.db
@router.post("/{fqdn}")
async def host_add(request: Request, fqdn: str, params: HostCreateParams):
db: Session = request.state.db
if not validate_fqdn(fqdn):
raise HTTPException(status_code=400, detail="Provided host is not an FQDN")
if params.parent is not None:
parent_labels = split_and_validate_path(params.parent)
if parent_labels is None:
raise HTTPException(status_code=400, detail="Provided parent is not a valid path")
else:
parent_labels = []
parent_id = None
stmt_select_respecting_parent = select(Host).where(Host.name == bindparam("label") and Host.parent_id == bindparam("parent_id"))
for label in parent_labels:
result = db.execute(stmt_select_respecting_parent, {
'label': label,
'parent_id': parent_id
}).fetchall()
if len(result) == 0:
raise HTTPException(status_code=400, detail="Parent does not exist")
# Note: this should be enforced by the database
assert len(result) == 1
parent_id = result[0][0].parent_id
new_host = Host(
id=uuid.uuid4(),
name=fqdn,
parent_id=parent_id,
is_hostgroup=False
)
stmt_create_host_with_parent = insert(Host).values(id=new_host.id, name=new_host.name, parent_id=new_host.parent_id, is_hostgroup=new_host.is_hostgroup)
db.execute(stmt_create_host_with_parent).fetchall()
# Prepare response with creation details
output = {
"message": "Host created",
"host": new_host, # return the final host in the hierarchy
}
# include the full path to the new host if it exists
if params.parent is not None:
output.update({
"path": params.parent
})
return JSONResponse(output)
@router.delete("/{fqdn}")
async def host_delete(request: Request, fqdn: str):
pass