import uuid from sqlalchemy import select, insert, delete, bindparam from sqlalchemy.orm import Session from starlette.exceptions import HTTPException from starlette.requests import Request from fastapi import APIRouter, Depends from starlette.responses import JSONResponse from pillar_tool.db import Host from pillar_tool.db.models.top_data import State, StateAssignment from pillar_tool.db.queries.pillar_queries import get_pillar_for_target from pillar_tool.schemas import PillarParams, get_model_from_query from pillar_tool.util.pillar_utilities import merge from pillar_tool.util.validation import validate_state_name, validate_fqdn router = APIRouter( prefix="/pillar", tags=["pillar"], ) # Note: there is no list of all pillars, as this would not be helpful @router.get("/{fqdn}") def pillar_get(req: Request, fqdn: str): # TODO: implement # this function should: # - get the affected host hierarchy # - get all the relevant pillar dictionaries # - merge the pillar directories # - return the merged pillar directory # if any error happens, return non-200 status and an empty dictionary so that salt does not shit itself db: Session = req.state.db # get the host hierarchy host_stmt = select(Host).where(Host.name == fqdn and Host.is_hostgroup == False) result = db.execute(host_stmt).fetchall() if len(result) == 0: return JSONResponse(status=404, content={}) # NOTE: should be enforced by the database assert len(result) == 1 host: Host = result[0][0] path: list[Host] = [host] parent_stmt = select(Host).where(Host.id == bindparam('parent')) while path[-1].parent_id is not None: result = db.execute(parent_stmt, {'parent': path[-1].parent_id}).fetchall() # NOTE: should be enforced by the database assert len(result) == 1 tmp: Host = result[0][0] path.append(tmp) path.reverse() out = merge(get_pillar_for_target(db, host.id) for host in path) return JSONResponse(status_code=200, content={}) @router.post("/{name}") def pillar_create(req: Request, name: str, params: PillarParams): db = req.state.db # ensure that value and type have been set in the request parameters if params.type is None or params.value is None: target_stmt = select(Host).where(Host.name == name) result = db.execute(target_stmt).fetchall() if len(result) == 0: return JSONResponse(status_code=404, content={}) # this should be enforced by the database assert len(result) == 1 target: Host = result[0][0] @router.delete("/{name}") def pillar_delete(req: Request, name: str): # TODO: implement db = req.state.db