import uuid from sqlalchemy import select, insert, delete, and_, 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, Environment, EnvironmentAssignment from pillar_tool.db.models.top_data import State, StateAssignment from pillar_tool.util.validation import validate_state_name router = APIRouter( prefix="/top", tags=["top"], ) @router.get("/query/{host}") def top_get(req: Request, host: str): db: Session = req.state.db # build the hierarchy host_stmt = select(Host).where(Host.name == host) result = db.execute(host_stmt).fetchall() if len(result) == 0: return JSONResponse(status_code=404, content={"message": "Host '{}' not found".format(host)}) elif len(result) > 1: return JSONResponse(status_code=500, content={"message": "More than one host found"}) else: target_host = result[0][0] parent_stmt = select(Host).where(Host.id == bindparam("parent_id")) parents = [] current = target_host while current is not None: result = db.execute(parent_stmt, {'parend_id': current.id}).fetchall() if len(result) == 0: current = None elif len(result) > 1: return JSONResponse(status_code=500, content={"message": "More than one parent host found"}) else: parents.append(result[0][0]) current = result[0][0] # TODO: states should be hierarchical, same as pillars are select_stmt = (select(Host, EnvironmentAssignment, Environment) .where(and_(Host.name == host, Host.is_hostgroup == False)) .join(EnvironmentAssignment, EnvironmentAssignment.host_id == Host.id) .join(Environment, EnvironmentAssignment.environment_id == Environment.id) ) result = db.execute(select_stmt).fetchall() print(result[0]) return JSONResponse(status_code=200, content={}) @router.post("/setenv/{host}/{environment}") def top_setenv(req: Request, host: str, environment: str): db: Session = req.state.db # get the target host id host_stmt = select(Host).where(and_(Host.name == host, Host.is_hostgroup == False)) host_res = db.execute(host_stmt).fetchall() if len(host_res) == 0: return JSONResponse(status_code=404, content={"error": "No host found"}) elif len(host_res) == 1: host_res = host_res[0][0] else: # Note that this should be prevented by the database return JSONResponse(status_code=404, content={"error": "Too many hosts found??? This should not happen"}) # get the environment id env_stmt = select(Environment).where(Environment.name == environment) env_res = db.execute(env_stmt).fetchall() if len(env_res) == 0: return JSONResponse(status_code=404, content={"error": "No environment found"}) elif len(env_res) == 1: env_res = env_res[0][0] else: # Note that this should be prevented by the database return JSONResponse(status_code=404, content={"error": "Too many environments found??? This should not happen"}) insert_stmt = insert(EnvironmentAssignment).values(environment_id=env_res.id, host_id=host_res.id) result = db.execute(insert_stmt) return JSONResponse(status_code=200, content={}) def top_state_assign(req: Request): pass