146 lines
4.5 KiB
Python
146 lines
4.5 KiB
Python
from uuid import uuid4
|
|
|
|
from celery.result import AsyncResult
|
|
from celery.contrib.abortable import AbortableAsyncResult
|
|
from django.contrib.auth.models import User
|
|
from django.core.exceptions import ObjectDoesNotExist
|
|
from django.core.paginator import Paginator
|
|
from django.http import (
|
|
HttpResponseRedirect,
|
|
HttpResponseServerError,
|
|
HttpResponseBadRequest,
|
|
HttpResponseForbidden,
|
|
)
|
|
from django.shortcuts import render, get_object_or_404
|
|
|
|
from deployment.channel import Event
|
|
from deployment.forms import DeploymentForm
|
|
from deployment.models import Deployment, Status
|
|
from deployment.tasks import deploy as launch_deploy
|
|
|
|
|
|
def check_user_credits(user: User) -> bool:
|
|
if not user.is_superuser:
|
|
try:
|
|
dep_user = user.deploymentuser
|
|
except (ObjectDoesNotExist, AttributeError):
|
|
return False
|
|
else:
|
|
if dep_user.credits < 0:
|
|
return True
|
|
|
|
deployments = Deployment.objects.filter(user=user)
|
|
return not len(deployments) >= dep_user.credits
|
|
return True
|
|
|
|
|
|
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": f"events/{request.user.id}/",
|
|
"can_create": check_user_credits(request.user),
|
|
},
|
|
)
|
|
|
|
|
|
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()
|
|
|
|
Event.send_details(deployment, progress)
|
|
Event.send(deployment)
|
|
|
|
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"events/{request.user.id}/{deployment.id}/"},
|
|
)
|
|
|
|
|
|
def create(request):
|
|
if request.method == "POST":
|
|
if not check_user_credits(request.user):
|
|
return HttpResponseForbidden(
|
|
"unable to launch deployment, contact administrator for support"
|
|
)
|
|
|
|
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")
|