diff --git a/.gitattributes b/.gitattributes index 0601cb69d02130a712c0a48cf29ba3e193930304..c86405d3bf8e789fca771f69d8116c16193a6c6e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4239,6 +4239,11 @@ SAS/LSMR/bin/lsmr_testdatabase -text SAS/LSMR/bin/lsmr_testldap -text SAS/LSMR/doc/LSMR.md -text SAS/LSMR/doc/package.dox -text +SAS/LSMR/docker/README.md -text +SAS/LSMR/docker/lsmr-postgres/Dockerfile -text +SAS/LSMR/docker/lsmr-postgres/init.sql -text +SAS/LSMR/docker/lsmr/Dockerfile -text +SAS/LSMR/docker/lsmr/dbcreds.ini -text SAS/LSMR/src/CMakeLists.txt -text SAS/LSMR/src/lsmr/CMakeLists.txt -text SAS/LSMR/src/lsmr/__init__.py -text @@ -4262,6 +4267,7 @@ SAS/LSMR/src/lsmr/lsmrapp/serializers/scheduling.py -text SAS/LSMR/src/lsmr/lsmrapp/serializers/specification.py -text SAS/LSMR/src/lsmr/lsmrapp/viewsets/CMakeLists.txt -text SAS/LSMR/src/lsmr/lsmrapp/viewsets/__init__.py -text +SAS/LSMR/src/lsmr/lsmrapp/viewsets/lofar_viewset.py -text SAS/LSMR/src/lsmr/lsmrapp/viewsets/scheduling.py -text SAS/LSMR/src/lsmr/lsmrapp/viewsets/specification.py -text SAS/LSMR/src/lsmr/settings.py -text diff --git a/SAS/LSMR/doc/LSMR.md b/SAS/LSMR/doc/LSMR.md index 907432d367d36ab9aa1777c2fc583565a1cbac91..d41cdb56415cc2e018c0c7a076e231fbab841d9f 100644 --- a/SAS/LSMR/doc/LSMR.md +++ b/SAS/LSMR/doc/LSMR.md @@ -37,6 +37,7 @@ meetings with stakeholders.* TODO ### Testing + TODO tests are missing - *How do you run unit tests?* TODO - *How do you run integration tests?* TODO @@ -45,8 +46,10 @@ TODO tests are missing ### Build & Deploy There is cmake integration for development work and testing. -For production deplyoment, the production database has to be configured in settings.py. -This should be best served through Nginx or Apache, so you want to collect static files and reference the wsgi.py. +For production deployment, the production database has to be configured in settings.py. +This should be best served through Nginx or Apache, so you want to collect static files and reference the wsgi.py. + +A docker environment is setup in ../docker, see ../docker/README.md - - - ## OPERATIONS @@ -93,4 +96,4 @@ TODO ### Operations Documentation -*e.g. Please refer to URL X for Operations Documentation* \ No newline at end of file +*e.g. Please refer to URL X for Operations Documentation* diff --git a/SAS/LSMR/docker/README.md b/SAS/LSMR/docker/README.md new file mode 100644 index 0000000000000000000000000000000000000000..6f11534aa1f72f882faa713d7975b9c2adc3d718 --- /dev/null +++ b/SAS/LSMR/docker/README.md @@ -0,0 +1,14 @@ +To build: + + docker build -t lsmr-postgres lsmr-postgres + docker build -t lsmr [--build-arg BRANCH=LSMR-epic] lsmr + +To start the PostgreSQL container: + + docker run [-it] --name=postgres-$USER --rm lsmr-postgres + +To start the LSMR container (exposing port 8001 to surf to): + + docker run [-it] --rm -p 0.0.0.0:8001:8000 --link=postgres-$USER:postgres lsmr + +Note: "-it" allows one to abort the container with ^C. diff --git a/SAS/LSMR/docker/lsmr-postgres/Dockerfile b/SAS/LSMR/docker/lsmr-postgres/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..7626c70899231474956bb81d762678156a6f9b5e --- /dev/null +++ b/SAS/LSMR/docker/lsmr-postgres/Dockerfile @@ -0,0 +1,2 @@ +FROM library/postgres +COPY init.sql /docker-entrypoint-initdb.d/ diff --git a/SAS/LSMR/docker/lsmr-postgres/init.sql b/SAS/LSMR/docker/lsmr-postgres/init.sql new file mode 100644 index 0000000000000000000000000000000000000000..58a17e105a2ced5d8486090d54b1188b35b5c3b8 --- /dev/null +++ b/SAS/LSMR/docker/lsmr-postgres/init.sql @@ -0,0 +1,3 @@ +CREATE USER lsmr WITH SUPERUSER PASSWORD 'lsmr'; +CREATE DATABASE lsmr; +GRANT ALL PRIVILEGES ON DATABASE lsmr TO lsmr; diff --git a/SAS/LSMR/docker/lsmr/Dockerfile b/SAS/LSMR/docker/lsmr/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..94e7d4bb39f568431618b16d580d26ca7bffeb9d --- /dev/null +++ b/SAS/LSMR/docker/lsmr/Dockerfile @@ -0,0 +1,43 @@ +FROM ubuntu:18.04 + +# LOFAR branch to build +ARG BRANCH=LSMR-epic + +# Export build-time variables to containters +ENV BRANCH=$BRANCH + +RUN apt-get -y update && apt-get -y upgrade + +# LOFAR checkout and compile dependencies +RUN apt-get -y install make cmake g++ subversion python3 git + +# LOFAR build dependencies +RUN apt-get -y install liblog4cplus-dev python3-dev libldap2-dev libsasl2-dev +RUN apt-get -y install python3-pip && pip3 install django djangorestframework django-filter django-auth-ldap coreapi python-ldap-test django-jsonforms django-json-widget "git+git://github.com/nnseva/django-jsoneditor.git" psycopg2-binary markdown ldap3 drf-yasg flex swagger-spec-validator + +# LOFAR test dependencies +RUN apt-get -y install uuid-runtime iproute2 postgresql-10 openjdk-10-jre-headless +RUN pip3 install testing.postgresql + +# Install LOFAR packages +RUN mkdir /src && \ + cd /src && \ + svn co -N https://svn.astron.nl/LOFAR/branches/$BRANCH/ && \ + cd $BRANCH/ && \ + svn up CMake +RUN mkdir -p /build/gnu_debug && cd /build/gnu_debug && cmake /src/$BRANCH/ -DBUILD_PACKAGES=LSMR -DCMAKE_INSTALL_PREFIX=/opt/lofar && make -j 8 && make -j 8 install + +# Configure authentication +ADD dbcreds.ini /opt/lofar/etc/dbcredentials/lsmr.ini +RUN echo "REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES']=[]" >> /opt/lofar/lib/python3.6/site-packages/lofar/sas/lsmr/lsmr/settings.py +RUN echo "REST_FRAMEWORK['DEFAULT_PERMISSION_CLASSES']=[]" >> /opt/lofar/lib/python3.6/site-packages/lofar/sas/lsmr/lsmr/settings.py + +# Allow Django HTTP access +EXPOSE 8000 +RUN echo "ALLOWED_HOSTS=['*']" >> /opt/lofar/lib/python3.6/site-packages/lofar/sas/lsmr/lsmr/settings.py + +# Hot patches + +# Run LOFAR app +CMD bash -c 'source /opt/lofar/lofarinit.sh && lsmr' + diff --git a/SAS/LSMR/docker/lsmr/dbcreds.ini b/SAS/LSMR/docker/lsmr/dbcreds.ini new file mode 100644 index 0000000000000000000000000000000000000000..bdec6c5ef772e27b51b34d809f262c1e5cbad2dd --- /dev/null +++ b/SAS/LSMR/docker/lsmr/dbcreds.ini @@ -0,0 +1,5 @@ +[database:lsmr] +host=postgres +user=lsmr +password=lsmr +database=lsmr diff --git a/SAS/LSMR/src/CMakeLists.txt b/SAS/LSMR/src/CMakeLists.txt index 47ceed97437c8675741fec7ece3cb554e5c7b9e9..d5c88c6a6af8752bcb47af25afc7b7be70a577f7 100644 --- a/SAS/LSMR/src/CMakeLists.txt +++ b/SAS/LSMR/src/CMakeLists.txt @@ -15,6 +15,11 @@ find_python_module(django_auth_ldap REQUIRED) # sudo apt-get install python3-d find_python_module(coreapi REQUIRED) # sudo apt-get install python3-coreapi #find_python_module(jsoneditor REQUIRED) # pip install "git+git://github.com/nnseva/django-jsoneditor.git" +# modules for swagger API export +find_python_module(drf_yasg REQUIRED) # pip install drf-yasg +find_python_module(flex REQUIRED) # pip install flex +find_python_module(swagger_spec_validator REQUIRED) # pip install swagger-spec-validator + set(_py_files manage.py remakemigrations.py diff --git a/SAS/LSMR/src/lsmr/lsmrapp/viewsets/CMakeLists.txt b/SAS/LSMR/src/lsmr/lsmrapp/viewsets/CMakeLists.txt index 0a5d6a30f70d54d5f32cf4c081d340eaf1e63345..7bcf74595efb04b788425b8632a99833eb081bdf 100644 --- a/SAS/LSMR/src/lsmr/lsmrapp/viewsets/CMakeLists.txt +++ b/SAS/LSMR/src/lsmr/lsmrapp/viewsets/CMakeLists.txt @@ -3,6 +3,7 @@ include(PythonInstall) set(_py_files __init__.py + lofar_viewset.py specification.py scheduling.py ) diff --git a/SAS/LSMR/src/lsmr/lsmrapp/viewsets/lofar_viewset.py b/SAS/LSMR/src/lsmr/lsmrapp/viewsets/lofar_viewset.py new file mode 100644 index 0000000000000000000000000000000000000000..a69bbc095fa9546bb65715eb6b2e3a923862bc8d --- /dev/null +++ b/SAS/LSMR/src/lsmr/lsmrapp/viewsets/lofar_viewset.py @@ -0,0 +1,40 @@ +""" +A viewset extended with annotation and other common generic behaviours. + +Adds the following functionality: +- Swagger API annotation +""" + +from rest_framework import viewsets +from drf_yasg.utils import swagger_auto_schema + +class LOFARViewSet(viewsets.ModelViewSet): + """ + If you're using format suffixes, make sure to also include + the `format=None` keyword argument for each action. + """ + + @swagger_auto_schema(responses={403: 'forbidden'}) + def list(self, request): + return super(LOFARViewSet, self).list(request) + + @swagger_auto_schema(responses={400: 'invalid specification', 403: 'forbidden'}) + def create(self, request): + return super(LOFARViewSet, self).create(request) + + @swagger_auto_schema(responses={403: 'forbidden', 404: 'not found'}) + def retrieve(self, request, pk=None): + return super(LOFARViewSet, self).retrieve(request, pk) + + @swagger_auto_schema(responses={400: 'invalid specification', 403: 'forbidden', 404: 'not found'}) + def update(self, request, pk=None): + return super(LOFARViewSet, self).update(request, pk) + + @swagger_auto_schema(responses={400: 'invalid specification', 403: 'forbidden', 404: 'not found'}) + def partial_update(self, request, pk=None): + return super(LOFARViewSet, self).partial_update(request, pk) + + @swagger_auto_schema(responses={403: 'forbidden', 404: 'not found'}) + def destroy(self, request, pk=None): + return super(LOFARViewSet, self).destroy(request, pk) + diff --git a/SAS/LSMR/src/lsmr/lsmrapp/viewsets/scheduling.py b/SAS/LSMR/src/lsmr/lsmrapp/viewsets/scheduling.py index 3c4cbbfa94f02e6909cef40134eabaa7cbf6bf2c..dad52d650b9300e1e63afbcf0bb82876cfaba020 100644 --- a/SAS/LSMR/src/lsmr/lsmrapp/viewsets/scheduling.py +++ b/SAS/LSMR/src/lsmr/lsmrapp/viewsets/scheduling.py @@ -4,70 +4,71 @@ This file contains the viewsets (based on the elsewhere defined data models and from django.shortcuts import get_object_or_404 from rest_framework import viewsets +from .lofar_viewset import LOFARViewSet from .. import models from .. import serializers -class SubtaskConnectorViewSet(viewsets.ModelViewSet): +class SubtaskConnectorViewSet(LOFARViewSet): queryset = models.SubtaskConnector.objects.all() serializer_class = serializers.SubtaskConnectorSerializer -class SubtaskStateChoiceViewSet(viewsets.ModelViewSet): +class SubtaskStateChoiceViewSet(LOFARViewSet): queryset = models.SubtaskStateChoice.objects.all() serializer_class = serializers.SubtaskStateChoiceSerializer -class SubtaskTypeChoiceViewSet(viewsets.ModelViewSet): +class SubtaskTypeChoiceViewSet(LOFARViewSet): queryset = models.SubtaskTypeChoice.objects.all() serializer_class = serializers.SubtaskTypeChoiceSerializer -class StationTypeChoiceViewSet(viewsets.ModelViewSet): +class StationTypeChoiceViewSet(LOFARViewSet): queryset = models.StationTypeChoice.objects.all() serializer_class = serializers.StationTypeChoiceSerializer -class AlgorithmViewSet(viewsets.ModelViewSet): +class AlgorithmViewSet(LOFARViewSet): queryset = models.Algorithm.objects.all() serializer_class = serializers.AlgorithmSerializer -class ScheduleMethodViewSet(viewsets.ModelViewSet): +class ScheduleMethodViewSet(LOFARViewSet): queryset = models.ScheduleMethod.objects.all() serializer_class = serializers.ScheduleMethodSerializer -class SubtaskTemplateViewSet(viewsets.ModelViewSet): +class SubtaskTemplateViewSet(LOFARViewSet): queryset = models.SubtaskTemplate.objects.all() serializer_class = serializers.SubtaskTemplateSerializer -class DefaultSubtaskTemplateViewSet(viewsets.ModelViewSet): +class DefaultSubtaskTemplateViewSet(LOFARViewSet): queryset = models.DefaultSubtaskTemplate.objects.all() serializer_class = serializers.DefaultSubtaskTemplateSerializer -class DataproductSpecificationsTemplateViewSet(viewsets.ModelViewSet): +class DataproductSpecificationsTemplateViewSet(LOFARViewSet): queryset = models.DataproductSpecificationsTemplate.objects.all() serializer_class = serializers.DataproductSpecificationsTemplateSerializer -class DefaultDataproductSpecificationsTemplateViewSet(viewsets.ModelViewSet): +class DefaultDataproductSpecificationsTemplateViewSet(LOFARViewSet): queryset = models.DefaultDataproductSpecificationsTemplate.objects.all() serializer_class = serializers.DefaultDataproductSpecificationsTemplateSerializer -class SubtaskInputSelectionTemplateViewSet(viewsets.ModelViewSet): +class SubtaskInputSelectionTemplateViewSet(LOFARViewSet): queryset = models.SubtaskInputSelectionTemplate.objects.all() serializer_class = serializers.SubtaskInputSelectionTemplateSerializer -class DataproductFeedbackTemplateViewSet(viewsets.ModelViewSet): +class DataproductFeedbackTemplateViewSet(LOFARViewSet): queryset = models.DataproductFeedbackTemplate.objects.all() serializer_class = serializers.DataproductFeedbackTemplateSerializer -class SubtaskViewSet(viewsets.ModelViewSet): +class SubtaskViewSet(LOFARViewSet): queryset = models.Subtask.objects.all() serializer_class = serializers.SubtaskSerializer @@ -79,46 +80,46 @@ class SubtaskViewSet(viewsets.ModelViewSet): return models.Subtask.objects.all() -class SubtaskInputViewSet(viewsets.ModelViewSet): +class SubtaskInputViewSet(LOFARViewSet): queryset = models.SubtaskInput.objects.all() serializer_class = serializers.SubtaskInputSerializer -class SubtaskOutputViewSet(viewsets.ModelViewSet): +class SubtaskOutputViewSet(LOFARViewSet): queryset = models.SubtaskOutput.objects.all() serializer_class = serializers.SubtaskOutputSerializer -class DataproductViewSet(viewsets.ModelViewSet): +class DataproductViewSet(LOFARViewSet): queryset = models.Dataproduct.objects.all() serializer_class = serializers.DataproductSerializer -class AntennaSetViewSet(viewsets.ModelViewSet): +class AntennaSetViewSet(LOFARViewSet): queryset = models.AntennaSet.objects.all() serializer_class = serializers.AntennaSetSerializer -class DataproductTransformViewSet(viewsets.ModelViewSet): +class DataproductTransformViewSet(LOFARViewSet): queryset = models.DataproductTransform.objects.all() serializer_class = serializers.DataproductTransformSerializer -class FilesystemViewSet(viewsets.ModelViewSet): +class FilesystemViewSet(LOFARViewSet): queryset = models.Filesystem.objects.all() serializer_class = serializers.FilesystemSerializer -class ClusterViewSet(viewsets.ModelViewSet): +class ClusterViewSet(LOFARViewSet): queryset = models.Cluster.objects.all() serializer_class = serializers.ClusterSerializer -class DataproductArchiveInfoViewSet(viewsets.ModelViewSet): +class DataproductArchiveInfoViewSet(LOFARViewSet): queryset = models.DataproductArchiveInfo.objects.all() serializer_class = serializers.DataproductArchiveInfoSerializer -class DataproductHashViewSet(viewsets.ModelViewSet): +class DataproductHashViewSet(LOFARViewSet): queryset = models.DataproductHash.objects.all() serializer_class = serializers.DataproductHashSerializer diff --git a/SAS/LSMR/src/lsmr/lsmrapp/viewsets/specification.py b/SAS/LSMR/src/lsmr/lsmrapp/viewsets/specification.py index 53c9ebccd94aa56dfd9f3dfffd18b3c0e641b5d6..779b43a9811e4c196ab59a56a42c4def7423f978 100644 --- a/SAS/LSMR/src/lsmr/lsmrapp/viewsets/specification.py +++ b/SAS/LSMR/src/lsmr/lsmrapp/viewsets/specification.py @@ -4,85 +4,86 @@ This file contains the viewsets (based on the elsewhere defined data models and from django.shortcuts import get_object_or_404 from rest_framework import viewsets +from .lofar_viewset import LOFARViewSet from .. import models, serializers from rest_framework.renderers import BrowsableAPIRenderer, TemplateHTMLRenderer -class TagsViewSet(viewsets.ModelViewSet): +class TagsViewSet(LOFARViewSet): queryset = models.Tags.objects.all() serializer_class = serializers.TagsSerializer -class GeneratorTemplateViewSet(viewsets.ModelViewSet): +class GeneratorTemplateViewSet(LOFARViewSet): queryset = models.GeneratorTemplate.objects.all() serializer_class = serializers.GeneratorTemplateSerializer -class DefaultGeneratorTemplateViewSet(viewsets.ModelViewSet): +class DefaultGeneratorTemplateViewSet(LOFARViewSet): queryset = models.DefaultGeneratorTemplate.objects.all() serializer_class = serializers.DefaultGeneratorTemplateSerializer -class SchedulingUnitTemplateViewSet(viewsets.ModelViewSet): +class SchedulingUnitTemplateViewSet(LOFARViewSet): queryset = models.SchedulingUnitTemplate.objects.all() serializer_class = serializers.SchedulingUnitTemplateSerializer -class DefaultSchedulingUnitTemplateViewSet(viewsets.ModelViewSet): +class DefaultSchedulingUnitTemplateViewSet(LOFARViewSet): queryset = models.DefaultSchedulingUnitTemplate.objects.all() serializer_class = serializers.DefaultSchedulingUnitTemplateSerializer -class TaskTemplateViewSet(viewsets.ModelViewSet): +class TaskTemplateViewSet(LOFARViewSet): queryset = models.TaskTemplate.objects.all() serializer_class = serializers.TaskTemplateSerializer -class DefaultTaskTemplateViewSet(viewsets.ModelViewSet): +class DefaultTaskTemplateViewSet(LOFARViewSet): queryset = models.DefaultTaskTemplate.objects.all() serializer_class = serializers.DefaultTaskTemplateSerializer -class WorkRelationSelectionTemplateViewSet(viewsets.ModelViewSet): +class WorkRelationSelectionTemplateViewSet(LOFARViewSet): queryset = models.WorkRelationSelectionTemplate.objects.all() serializer_class = serializers.WorkRelationSelectionTemplateSerializer -class DefaultWorkRelationSelectionTemplateViewSet(viewsets.ModelViewSet): +class DefaultWorkRelationSelectionTemplateViewSet(LOFARViewSet): queryset = models.DefaultWorkRelationSelectionTemplate.objects.all() serializer_class = serializers.DefaultWorkRelationSelectionTemplateSerializer -class RoleChoiceViewSet(viewsets.ModelViewSet): +class RoleChoiceViewSet(LOFARViewSet): queryset = models.RoleChoice.objects.all() serializer_class = serializers.RoleChoiceSerializer -class DatatypeChoiceViewSet(viewsets.ModelViewSet): +class DatatypeChoiceViewSet(LOFARViewSet): queryset = models.DatatypeChoice.objects.all() serializer_class = serializers.DatatypeChoiceSerializer -class DataformatChoiceViewSet(viewsets.ModelViewSet): +class DataformatChoiceViewSet(LOFARViewSet): queryset = models.DataformatChoice.objects.all() serializer_class = serializers.DataformatChoiceSerializer -class CopyReasonChoiceViewSet(viewsets.ModelViewSet): +class CopyReasonChoiceViewSet(LOFARViewSet): queryset = models.CopyReasonChoice.objects.all() serializer_class = serializers.CopyReasonChoiceSerializer -class TaskConnectorsViewSet(viewsets.ModelViewSet): +class TaskConnectorsViewSet(LOFARViewSet): queryset = models.TaskConnectors.objects.all() serializer_class = serializers.TaskConnectorsSerializer -class CycleViewSet(viewsets.ModelViewSet): +class CycleViewSet(LOFARViewSet): queryset = models.Cycle.objects.all() serializer_class = serializers.CycleSerializer -class ProjectViewSet(viewsets.ModelViewSet): +class ProjectViewSet(LOFARViewSet): queryset = models.Project.objects.all() serializer_class = serializers.ProjectSerializer @@ -94,12 +95,12 @@ class ProjectViewSet(viewsets.ModelViewSet): return models.Project.objects.all() -class SchedulingSetViewSet(viewsets.ModelViewSet): +class SchedulingSetViewSet(LOFARViewSet): queryset = models.SchedulingSet.objects.all() serializer_class = serializers.SchedulingSetSerializer -class SchedulingUnitDraftViewSet(viewsets.ModelViewSet): +class SchedulingUnitDraftViewSet(LOFARViewSet): queryset = models.SchedulingUnitDraft.objects.all() serializer_class = serializers.SchedulingUnitDraftSerializer @@ -111,7 +112,7 @@ class SchedulingUnitDraftViewSet(viewsets.ModelViewSet): return models.SchedulingUnitDraft.objects.all() -class SchedulingUnitBlueprintViewSet(viewsets.ModelViewSet): +class SchedulingUnitBlueprintViewSet(LOFARViewSet): queryset = models.SchedulingUnitBlueprint.objects.all() serializer_class = serializers.SchedulingUnitBlueprintSerializer @@ -123,7 +124,7 @@ class SchedulingUnitBlueprintViewSet(viewsets.ModelViewSet): return models.SchedulingUnitBlueprint.objects.all() -class TaskDraftViewSet(viewsets.ModelViewSet): +class TaskDraftViewSet(LOFARViewSet): queryset = models.TaskDraft.objects.all() serializer_class = serializers.TaskDraftSerializer @@ -135,7 +136,7 @@ class TaskDraftViewSet(viewsets.ModelViewSet): return models.TaskDraft.objects.all() -class TaskBlueprintViewSet(viewsets.ModelViewSet): +class TaskBlueprintViewSet(LOFARViewSet): queryset = models.TaskBlueprint.objects.all() serializer_class = serializers.TaskBlueprintSerializer @@ -147,7 +148,7 @@ class TaskBlueprintViewSet(viewsets.ModelViewSet): return models.TaskBlueprint.objects.all() -class TaskRelationDraftViewSet(viewsets.ModelViewSet): +class TaskRelationDraftViewSet(LOFARViewSet): queryset = models.TaskRelationDraft.objects.all() serializer_class = serializers.TaskRelationDraftSerializer @@ -159,7 +160,7 @@ class TaskRelationDraftViewSet(viewsets.ModelViewSet): return models.TaskRelationDraft.objects.all() -class TaskRelationBlueprintViewSet(viewsets.ModelViewSet): +class TaskRelationBlueprintViewSet(LOFARViewSet): queryset = models.TaskRelationBlueprint.objects.all() serializer_class = serializers.TaskRelationBlueprintSerializer @@ -178,23 +179,23 @@ class TaskRelationBlueprintViewSet(viewsets.ModelViewSet): # --- JSON -class TaskBlueprintViewSetReactJSONform(viewsets.ModelViewSet): +class TaskBlueprintViewSetReactJSONform(LOFARViewSet): queryset = models.TaskBlueprint.objects.all() serializer_class = serializers.TaskBlueprintSerializerReactJSONform -class TaskBlueprintViewSetJSONeditor(viewsets.ModelViewSet): +class TaskBlueprintViewSetJSONeditor(LOFARViewSet): queryset = models.TaskBlueprint.objects.all() serializer_class = serializers.TaskBlueprintSerializerJSONeditor -class TaskBlueprintViewSetJSONeditorOnline(viewsets.ModelViewSet): +class TaskBlueprintViewSetJSONeditorOnline(LOFARViewSet): queryset = models.TaskBlueprint.objects.all() serializer_class = serializers.TaskBlueprintSerializerJSONeditorOnline # # todo: this is experimental / for demo purposes. Remove or make functional. -# class JSONEditorViewSet(viewsets.ModelViewSet): +# class JSONEditorViewSet(LOFARViewSet): # renderer_classes = [TemplateHTMLRenderer] # template_name = 'react_jsonschema_form.html' # queryset = models.TaskBlueprint.objects.all() diff --git a/SAS/LSMR/src/lsmr/settings.py b/SAS/LSMR/src/lsmr/settings.py index 61c60cde25e8d23de840201c3e63d6a91e035499..df738f0de392f40f8df7b3245c23adcc86466e50 100644 --- a/SAS/LSMR/src/lsmr/settings.py +++ b/SAS/LSMR/src/lsmr/settings.py @@ -52,7 +52,9 @@ INSTALLED_APPS = [ 'rest_framework', 'django_jsonforms', 'django_json_widget', - 'jsoneditor' + 'jsoneditor', + 'drf_yasg', + 'django_filters', ] MIDDLEWARE = [ @@ -116,7 +118,7 @@ DATABASES = { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': django_db_credentials.database, 'USER': django_db_credentials.user, - 'PASS': django_db_credentials.password, + 'PASSWORD': django_db_credentials.password, 'HOST': django_db_credentials.host, 'PORT': django_db_credentials.port, } @@ -136,6 +138,14 @@ REST_FRAMEWORK = { ], 'PAGE_SIZE': 50, 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination' + 'DEFAULT_FILTER_BACKENDS': ( + # allows ?field=value filtering in URLs + # (fields allowed for filtering must be annotated in viewsets using filter_fields = ('field', ...)) + 'django_filters.rest_framework.DjangoFilterBackend', + + # allows ?ordering=[-]field to order list results + 'rest_framework.filters.OrderingFilter', + ), } # LDAP diff --git a/SAS/LSMR/src/lsmr/urls.py b/SAS/LSMR/src/lsmr/urls.py index 3232c894283582dd5af264b4e7201c364bcdf98d..efc0b5de2f5eee8485a723bcbec8f44b5ca5c1d1 100644 --- a/SAS/LSMR/src/lsmr/urls.py +++ b/SAS/LSMR/src/lsmr/urls.py @@ -15,22 +15,40 @@ Including another URLconf """ from django.contrib import admin -from django.urls import path +from django.urls import path, re_path from django.views.generic.base import TemplateView -from rest_framework import routers +from rest_framework import routers, permissions from .lsmrapp import viewsets, models, serializers from rest_framework.documentation import include_docs_urls - +from drf_yasg.views import get_schema_view +from drf_yasg import openapi # # Django style patterns # +# schema for Swagger API +swagger_schema_view = get_schema_view( + openapi.Info( + title="LOFAR Internal API", + default_version='v1', + description="ReST API for internal LOFAR services", + terms_of_service="", + contact=openapi.Contact(email="softwaresupport@astron.nl"), + license=openapi.License(name="GPL License v3"), + ), + validators=['flex', 'ssv'], + public=True, + permission_classes=(permissions.AllowAny,), +) urlpatterns = [ path('admin/', admin.site.urls), - path('docs/', include_docs_urls(title='LSMR API')) + path('docs/', include_docs_urls(title='LSMR API')), + re_path(r'^swagger(?P<format>\.json|\.yaml)$', swagger_schema_view.without_ui(cache_timeout=0), name='schema-json'), + path('swagger/', swagger_schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'), + path('redoc/', swagger_schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'), ]