250 lines
8.6 KiB
Python
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
|