hobo/hobo/environment/views.py

250 lines
8.6 KiB
Python

# hobo - portal to configure and deploy applications
# Copyright (C) 2015-2019 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import datetime
import json
import string
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.http import Http404, HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import get_object_or_404
from django.urls import reverse_lazy
from django.utils.encoding import force_str
from django.utils.translation import gettext_lazy as _
from django.views.generic import View
from django.views.generic.base import TemplateView
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
from . import forms, utils
from .models import AVAILABLE_SERVICES, Variable
class AvailableService:
def __init__(self, klass):
self.id = klass.Extra.service_id
self.label = klass._meta.verbose_name
class HomeView(TemplateView):
template_name = 'environment/home.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['available_services'] = [AvailableService(x) for x in AVAILABLE_SERVICES if x.is_enabled()]
installed_services = [x for x in utils.get_installed_services() if not x.secondary]
for service in installed_services:
for legacy_url in service.legacy_urls:
try:
legacy_url['datetime'] = datetime.datetime.strptime(
legacy_url['timestamp'], '%Y-%m-%d %H:%M:%S'
)
except ValueError:
pass
context['installed_services'] = installed_services
return context
class VariablesView(TemplateView):
template_name = 'environment/variables.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['variables'] = Variable.objects.filter(auto=False, service_pk__isnull=True).order_by('label')
return context
class VariableCreateView(CreateView):
model = Variable
form_class = forms.VariableForm
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
if 'service' in self.kwargs:
service_id = self.kwargs.pop('service')
service_slug = self.kwargs.pop('slug')
for service in AVAILABLE_SERVICES:
if service.Extra.service_id == service_id:
kwargs['service'] = service.objects.get(slug=service_slug)
break
return kwargs
def form_valid(self, form):
if form.service:
service_kwargs = {
'service_pk': form.service.id,
'service_type': ContentType.objects.get_for_model(form.service),
}
else:
service_kwargs = {'service_pk__isnull': True}
try:
self.object = Variable.objects.get(name=form.instance.name, **service_kwargs)
except Variable.DoesNotExist:
self.object = form.save()
else:
self.object.auto = False
self.object.value = form.instance.value
self.object.save()
return HttpResponseRedirect(self.get_success_url())
def get_success_url(self):
if self.object.service is None:
return reverse_lazy('environment-variables')
return reverse_lazy('environment-home')
class VariableUpdateView(UpdateView):
model = Variable
form_class = forms.VariableForm
def get_success_url(self):
if self.object.service is None:
return reverse_lazy('environment-variables')
return reverse_lazy('environment-home')
class VariableDeleteView(DeleteView):
model = Variable
template_name = 'environment/generic_confirm_delete.html'
def get_success_url(self):
if self.object.service is None:
return reverse_lazy('environment-variables')
return reverse_lazy('environment-home')
class ServiceCreateView(CreateView):
success_url = reverse_lazy('environment-home')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['model_name'] = self.model._meta.verbose_name
return context
def get_initial(self):
initial = super().get_initial()
initial['base_url'] = utils.create_base_url(
self.request.build_absolute_uri(), self.model.Extra.service_default_slug
)
initial['slug'] = self.model.Extra.service_default_slug
return initial
def get_template_names(self):
return 'environment/service_form.html'
def get(self, request, *args, **kwargs):
self.service_id = kwargs.pop('service')
return super().get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.service_id = kwargs.pop('service')
return super().post(request, *args, **kwargs)
def get_form_class(self):
for service in AVAILABLE_SERVICES:
if service.Extra.service_id == self.service_id:
form_class = getattr(forms, service.__name__ + 'Form')
self.model = form_class.Meta.model
return form_class
return None
class ServiceUpdateView(UpdateView):
success_url = reverse_lazy('environment-home')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['model_name'] = self.model._meta.verbose_name
return context
def get_template_names(self):
return 'environment/service_form.html'
def get(self, request, *args, **kwargs):
self.service_id = kwargs.pop('service')
self.get_form_class()
return super().get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.service_id = kwargs.pop('service')
self.get_form_class()
return super().post(request, *args, **kwargs)
def get_form_class(self):
for service in AVAILABLE_SERVICES:
if service.Extra.service_id == self.service_id:
form_class = getattr(forms, service.__name__ + 'Form')
self.model = form_class.Meta.model
return form_class
return None
class ServiceDeleteView(DeleteView):
success_url = reverse_lazy('environment-home')
template_name = 'environment/generic_confirm_delete.html'
context_object_name = 'object'
def get_object(self):
service_id = self.kwargs.pop('service')
service_slug = self.kwargs.pop('slug')
for service in AVAILABLE_SERVICES:
if service.Extra.service_id == service_id:
return service.objects.get(slug=service_slug)
return None
class ImportView(FormView):
form_class = forms.ImportForm
template_name = 'environment/import.html'
success_url = reverse_lazy('home')
def form_valid(self, form):
try:
parameters_json = json.loads(force_str(self.request.FILES['parameters_json'].read()))
except ValueError:
form.add_error('parameters_json', _('File is not in the expected JSON format.'))
return self.form_invalid(form)
utils.import_parameters(parameters_json)
return super().form_valid(form)
class ExportView(View):
def get(self, request, *args, **kwargs):
response = JsonResponse(utils.export_parameters(), json_dumps_params={'indent': 2})
response['Content-Disposition'] = 'attachment; filename="hobo-export.json"'
return response
def operational_check_view(request, service, slug, **kwargs):
for klass in AVAILABLE_SERVICES:
if klass.Extra.service_id == service:
break
else:
raise Http404()
object = get_object_or_404(klass, slug=slug)
object.check_operational()
response = HttpResponse(content_type='application/json')
json.dump({'operational': object.is_operational()}, response)
return response
def debug_json(request):
response = HttpResponse(content_type='application/json')
json.dump((utils.get_installed_services_dict(),), response, indent=2)
return response