mumui/deployment/views.py
2023-09-22 22:47:24 +02:00

137 lines
4.0 KiB
Python

from uuid import uuid4
from celery.result import AsyncResult
from celery.contrib.abortable import AbortableAsyncResult
from django.core.paginator import Paginator
from django.http import (
HttpResponseRedirect,
HttpResponseServerError,
HttpResponseBadRequest,
)
from django.shortcuts import render, get_object_or_404
from django_eventstream import send_event
from deployment.forms import DeploymentForm
from deployment.models import Deployment, Status
from deployment.tasks import deploy as launch_deploy
def index(request):
deployments = Deployment.objects.filter(user=request.user.id).order_by(
"-created_at"
)
paginator = Paginator(deployments, 10)
page_number = request.GET.get("page")
page_obj = paginator.get_page(page_number)
return render(
request,
"deployment/board.html",
{
"page_obj": page_obj,
"range_pages": [i + 1 for i in range(page_obj.paginator.num_pages)],
"url": "events/",
},
)
def deploy(request, deployment_id):
deployment = get_object_or_404(Deployment, id=deployment_id)
if request.method == "POST":
if deployment.status not in (Status.READY.name, Status.FAILED.name):
return HttpResponseBadRequest("deployment is undeployable")
# override previous errors
if deployment.error:
deployment.error = None
deployment.status = Status.PENDING.name
deployment.save()
launch_deploy.delay(deployment_id)
if page := request.GET.get("page", ""):
return HttpResponseRedirect(f"/deployment?page={page}")
return HttpResponseRedirect("/deployment")
def abort(request, deployment_id):
deployment = get_object_or_404(Deployment, id=deployment_id)
if request.method == "POST":
if deployment.status not in (Status.RUNNING.name, Status.PENDING.name):
return HttpResponseBadRequest("deployment is unabortable")
res = AbortableAsyncResult(str(deployment.task_id))
progress = res.info.get("progress", 0)
res.abort()
res.revoke(terminate=True)
deployment.status = Status.FAILED.name
deployment.error = f"aborted by {request.user}"
deployment.task_id = None
deployment.save()
# first event in details
send_event(
f"deployment-{deployment.id}",
"message",
{
"id": deployment.id,
"status": deployment.status,
"progress": progress,
},
)
# global event
send_event(
"deployment",
"message",
{"id": deployment.id, "status": deployment.status},
)
return HttpResponseRedirect(f"/deployment/{deployment.id}")
def details(request, deployment_id):
deployment = get_object_or_404(Deployment, id=deployment_id)
if deployment.status == Status.RUNNING.name:
# retrieve the progression task in Redis
res = AsyncResult(str(deployment.task_id))
deployment.progress = res.info.get("progress", 0)
if request.method == "POST":
if deployment.status == Status.RUNNING.name:
return HttpResponseBadRequest("deployment is running")
if deployment.status == Status.PENDING.name:
return HttpResponseBadRequest("deployment is pending")
try:
deployment.delete()
except Exception as e:
return HttpResponseServerError(e)
return HttpResponseRedirect("/deployment")
return render(
request,
"deployment/details.html",
{"deployment": deployment, "url": f"{deployment.id}/events/"},
)
def create(request):
if request.method == "POST":
form = DeploymentForm(request.POST)
if form.is_valid():
try:
Deployment.objects.create(
user=request.user, id=uuid4(), **form.cleaned_data
)
except Exception as e:
return HttpResponseServerError(e)
return HttpResponseRedirect("/deployment")