Skip to content

Commit

Permalink
Pick smaller changes from app restructure: Logging configuration and …
Browse files Browse the repository at this point in the history
…docstrings for Andromeda (#253)

* Allow configuring django log level

* Add docstrings for the andromeda app

* Add docs for scripts

---------

Co-authored-by: Jeremiah Boby <[email protected]>
Co-authored-by: 0xAda <[email protected]>
  • Loading branch information
3 people authored Dec 16, 2023
1 parent b190108 commit a5b87a1
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 15 deletions.
26 changes: 15 additions & 11 deletions scripts/clean_db.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
"""Script for clearing the connected database of all data."""

import os
from os import getenv

import psycopg2

with psycopg2.connect(
user=getenv("SQL_USER"),
password=getenv("SQL_PASSWORD"),
host=getenv("SQL_HOST"),
port=getenv("SQL_PORT"),
database="template1",
) as connection:
connection.set_isolation_level(0)
with connection.cursor() as cursor:
cursor.execute(f"DROP DATABASE {os.getenv('SQL_DATABASE')}")
cursor.execute(f"CREATE DATABASE {os.getenv('SQL_DATABASE')}")

if __name__ == '__main__':
with psycopg2.connect(
user=getenv("SQL_USER"),
password=getenv("SQL_PASSWORD"),
host=getenv("SQL_HOST"),
port=getenv("SQL_PORT"),
database="template1",
) as connection:
connection.set_isolation_level(0)
with connection.cursor() as cursor:
cursor.execute(f"DROP DATABASE {os.getenv('SQL_DATABASE')}")
cursor.execute(f"CREATE DATABASE {os.getenv('SQL_DATABASE')}")
1 change: 1 addition & 0 deletions scripts/fake/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class PostgreSQL:

@classproperty
def dsn(cls) -> str:
"""Return the DSN for connecting to the configured database."""
return f"postgres://{cls.USER}:{cls.PASSWORD}@{cls.HOST}:{cls.PORT}/template1"


Expand Down
4 changes: 4 additions & 0 deletions src/andromeda/apps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
"""App for the andromeda integration."""

from django.apps import AppConfig


class AndromedaConfig(AppConfig):
"""AppConfig for the andromeda integration."""

name = "andromeda"
11 changes: 11 additions & 0 deletions src/andromeda/client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""A simple andromeda API client."""

from uuid import UUID

import requests
Expand All @@ -8,6 +10,7 @@


def post(path, **kwargs):
"""Send a post request to andromeda."""
response = requests.post(
f"{settings.ANDROMEDA_URL}/{path}",
headers={"Authorization": settings.ANDROMEDA_API_KEY},
Expand All @@ -20,6 +23,7 @@ def post(path, **kwargs):


def get(path, **kwargs):
"""Send a get request to andromeda."""
response = requests.get(
f"{settings.ANDROMEDA_URL}/{path}",
headers={"Authorization": settings.ANDROMEDA_API_KEY},
Expand All @@ -32,18 +36,22 @@ def get(path, **kwargs):


def get_instance(user_id, job_id):
"""Get a challenge instance of a given job id for a user."""
return post("", json={"user": str(user_id), "job": job_id})


def request_reset(user_id, job_id):
"""Reset a challenge instance of a given job id for a user."""
return post("reset", json={"user": str(user_id), "job": job_id})


def list_jobs():
"""Get a list of all jobs running on the andromeda host."""
return get("jobs")


def restart_job(job_id):
"""Restarts a job with a given uuid."""
try:
UUID(job_id)
except ValueError:
Expand All @@ -52,12 +60,15 @@ def restart_job(job_id):


def list_instances():
"""List all the instances of challenges on the andromeda host."""
return get("instances")


def sysinfo():
"""Get the current system info of the andromeda host."""
return get("sysinfo")


def submit_job(job_spec):
"""Submit a job to the andromeda host."""
return post("job/submit", json=job_spec)
6 changes: 6 additions & 0 deletions src/andromeda/serializers.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
"""Serializers for the andromeda integration."""

from rest_framework import serializers


class JobSubmitSerializer(serializers.Serializer):
"""Serializer for job submissions associated with a challenge id."""

challenge_id = serializers.IntegerField()
job_spec = serializers.JSONField()


class JobSubmitRawSerializer(serializers.Serializer):
"""Serializer for job submissions."""

job_spec = serializers.JSONField()
1 change: 1 addition & 0 deletions src/andromeda/urls.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""URL routes for the andromeda integration."""
from django.urls import path

from andromeda import views
Expand Down
29 changes: 27 additions & 2 deletions src/andromeda/views.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
"""API endpoints for the andromeda integration."""

from django.conf import settings
from rest_framework.generics import get_object_or_404
from rest_framework.permissions import IsAdminUser, IsAuthenticated
from rest_framework.status import HTTP_403_FORBIDDEN
from rest_framework.views import APIView

from andromeda import client
from andromeda.serializers import JobSubmitSerializer
from andromeda.serializers import JobSubmitSerializer, JobSubmitRawSerializer
from backend.response import FormattedResponse
from challenge.models import Challenge
from challenge.permissions import CompetitionOpen


class GetInstanceView(APIView):
"""Endpoint for getting an instance of a given challenge."""

permission_classes = (IsAuthenticated, CompetitionOpen)
throttle_scope = "challenge_instance_get"

def get(self, request, job_id):
"""Given a job id, return an instance of the relevant challenge for this user."""
if not settings.CHALLENGE_SERVER_ENABLED:
return FormattedResponse(m="challenge_server_disabled", status=HTTP_403_FORBIDDEN)
if not request.user.team:
Expand All @@ -24,52 +29,69 @@ def get(self, request, job_id):


class ResetInstanceView(APIView):
"""Endpoint for resetting an instance of a given challenge."""

permission_classes = (IsAuthenticated,)
throttle_scope = "challenge_instance_reset"

def get(self, request, job_id):
"""Given a job id, return a new instance of the relevant challenge for this user."""
if not settings.CHALLENGE_SERVER_ENABLED:
return FormattedResponse(m="challenge_server_disabled", status=HTTP_403_FORBIDDEN)
return FormattedResponse(client.request_reset(request.user.team.pk, job_id))


class ListJobsView(APIView):
"""Endpoint for listing the jobs on the andromeda host."""
permission_classes = (IsAdminUser,)
throttle_scope = "andromeda_view_jobs"

def get(self, request):
"""Return a list of all jobs that have been submitted to an andromeda host."""
return FormattedResponse(client.list_jobs())


class RestartJobView(APIView):
"""Endpoint for restarting a job on the andromeda host."""

permission_classes = (IsAdminUser,)
throttle_scope = "andromeda_manage_jobs"

def post(self, request):
"""Given a job id, restart all instances of that challenge on the andromeda host."""
return FormattedResponse(client.restart_job(request.data["job_id"]))


class ListInstancesView(APIView):
"""Endpoint for listing all instances of challenges on the andromeda host."""

permission_classes = (IsAdminUser,)
throttle_scope = "andromeda_view_jobs"

def get(self, request):
"""Get a list of all challenge instances on the andromeda host."""
return FormattedResponse(client.list_instances())


class SysinfoView(APIView):
"""Endpoint for getting the system info of an andromeda host."""

permission_classes = (IsAdminUser,)
throttle_scope = "andromeda_view_sysinfo"

def get(self, request):
"""Get the reported system info(free ram, cpu, etc) of the andromeda host."""
return FormattedResponse(client.sysinfo())


class JobSubmitView(APIView):
"""Endpoint to submit a job to the andromeda host and link it to a given challenge."""

permission_classes = (IsAdminUser,)
throttle_scope = "andromeda_manage_jobs"

def post(self, request):
"""Submit a job to the andromeda host then add it to the challenge's challenge_metadata."""
serializer = JobSubmitSerializer(request.data)
challenge = get_object_or_404(Challenge.objects, id=serializer.data["challenge_id"])
response = client.submit_job(serializer.data["job_spec"])
Expand All @@ -79,10 +101,13 @@ def post(self, request):


class JobSubmitRawView(APIView):
"""Endpoint to submit a job to the andromeda host."""

permission_classes = (IsAdminUser,)
throttle_scope = "andromeda_manage_jobs"

def post(self, request):
serializer = JobSubmitSerializer(request.data)
"""Submit a job to the andromeda host."""
serializer = JobSubmitRawSerializer(request.data)
response = client.submit_job(serializer.data["job_spec"])
return FormattedResponse(response)
4 changes: 2 additions & 2 deletions src/backend/settings/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,9 @@
"django.request": {
"handlers": ["console"],
"propagate": False,
"level": "DEBUG",
"level": os.getenv("DJANGO_LOG_LEVEL", "DEBUG"),
},
"core.handlers": {"level": "DEBUG", "handlers": ["console"]},
"core.handlers": {"level": os.getenv("DJANGO_LOG_LEVEL", "DEBUG"), "handlers": ["console"]},
},
}

Expand Down

0 comments on commit a5b87a1

Please sign in to comment.