import json from flask import Blueprint, request, Response from flask.typing import ResponseReturnValue from app.extensions import db from app.models.tfstate import TerraformState tfstate = Blueprint("tfstate", __name__) @tfstate.route("/", methods=['GET']) def handle_get(key: str) -> ResponseReturnValue: state = TerraformState.query.filter(TerraformState.key == key).first() if state is None or state.state is None: return "Not Found", 404 return Response(state.state, content_type="application/json") @tfstate.route("/", methods=['POST', 'DELETE', 'UNLOCK']) def handle_update(key: str) -> ResponseReturnValue: state = TerraformState.query.filter(TerraformState.key == key).first() if not state: if request.method in ["DELETE", "UNLOCK"]: return "OK", 200 state = TerraformState(key=key) if state.lock and not (request.method == "UNLOCK" and request.args.get('ID') is None): # force-unlock seems to not give an ID to verify so accept no ID being present if json.loads(state.lock)['ID'] != request.args.get('ID'): return Response(state.lock, status=409, content_type="application/json") if request.method == "POST": state.state = json.dumps(request.json) elif request.method == "DELETE": db.session.delete(state) elif request.method == "UNLOCK": state.lock = None db.session.commit() return "OK", 200 @tfstate.route("/", methods=['LOCK']) def handle_lock(key: str) -> ResponseReturnValue: state = TerraformState.query.filter(TerraformState.key == key).with_for_update().first() if state is None: state = TerraformState(key=key) db.session.add(state) if state.lock is not None: lock = state.lock db.session.rollback() return Response(lock, status=423, content_type="application/json") state.lock = json.dumps(request.json) db.session.commit() return "OK", 200