Files
murano-dashboard/muranodashboard/packages/forms.py
Kirill Zaitsev 67223ea1f0 Rename 'murano' dashboard to 'app-catalog'
Before this commit murano used 'murano' as the name of it's dashboard.
This is too specific and contradicts with general practice of naming
dashboards after the names of the service.
This also prevents us from re-using the same dashboard in
murano-dashboard and app-catalog-ui

Targets bp: catalog-dashboard-reorg

Change-Id: I3df3865f6bf82626325e66120c408552260c7e2b
2016-09-06 12:46:46 +03:00

291 lines
11 KiB
Python

# Copyright (c) 2013 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import json
import sys
from django.core.urlresolvers import reverse
from django.core import validators
from django import forms
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms as horizon_forms
from horizon import messages
from oslo_log import log as logging
from muranoclient.common import exceptions as exc
from muranodashboard import api
from muranodashboard.packages import consts
LOG = logging.getLogger(__name__)
IMPORT_TYPE_CHOICES = [
('upload', _('File')),
('by_name', _('Repository')),
('by_url', _('URL')),
]
IMPORT_BUNDLE_TYPE_CHOICES = [
('by_name', _('Repository')),
('by_url', _('URL')),
]
class PackageURLField(forms.URLField):
default_validators = [validators.URLValidator(schemes=["http", "https"])]
class ImportBundleForm(forms.Form):
import_type = forms.ChoiceField(
label=_("Package Bundle Source"),
choices=IMPORT_BUNDLE_TYPE_CHOICES,
widget=forms.Select(attrs={
'class': 'switchable',
'data-slug': 'source'}))
url = PackageURLField(
label=_("Bundle URL"),
required=False,
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'source',
'data-source-by_url': _('Bundle URL')}),
help_text=_('An external http/https URL to load the bundle from.'))
name = forms.CharField(
label=_("Bundle Name"),
required=False,
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'source',
'data-source-by_name': _('Bundle Name')}),
help_text=_("Name of the bundle."))
def clean(self):
cleaned_data = super(ImportBundleForm, self).clean()
import_type = cleaned_data.get('import_type')
if import_type == 'by_name' and not cleaned_data.get('name'):
msg = _('Please supply a bundle name')
raise forms.ValidationError(msg)
elif import_type == 'by_url' and not cleaned_data.get('url'):
msg = _('Please supply a bundle url')
raise forms.ValidationError(msg)
return cleaned_data
class ImportPackageForm(forms.Form):
import_type = forms.ChoiceField(
label=_("Package Source"),
choices=IMPORT_TYPE_CHOICES,
widget=forms.Select(attrs={
'class': 'switchable',
'data-slug': 'source'}))
url = PackageURLField(
label=_("Package URL"),
required=False,
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'source',
'data-source-by_url': _('Package URL')}),
help_text=_('An external http/https URL to load the package from.'))
repo_name = horizon_forms.CharField(
label=_("Package Name"),
required=False,
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'source',
'data-source-by_name': _('Package Name')}),
help_text=_(
'Package name in the repository, usually a fully qualified name'),
)
package = forms.FileField(
label=_('Application Package'),
required=False,
widget=forms.FileInput(attrs={
'class': 'switched',
'data-switch-on': 'source',
'data-source-upload': _('Application Package')}),
help_text=_('A local zip file to upload'))
repo_version = horizon_forms.CharField(
label=_("Package version"),
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'source',
'data-source-by_name': _('Package version')}),
required=False)
def __init__(self, *args, **kwargs):
super(ImportPackageForm, self).__init__(*args, **kwargs)
self.fields['repo_version'].widget.attrs['placeholder'] = \
_('Optional')
def clean_package(self):
package = self.cleaned_data.get('package')
if package:
max_size_in_bytes = consts.MAX_FILE_SIZE_MB << 20
if package.size > max_size_in_bytes:
msg = _('It is forbidden to upload files larger than '
'{0} MB.').format(consts.MAX_FILE_SIZE_MB)
LOG.error(msg)
raise forms.ValidationError(msg)
return package
def clean(self):
cleaned_data = super(ImportPackageForm, self).clean()
import_type = cleaned_data.get('import_type')
if import_type == 'upload' and not cleaned_data.get('package'):
msg = _('Please supply a package file')
LOG.error(msg)
raise forms.ValidationError(msg)
elif import_type == 'by_name' and not cleaned_data.get('repo_name'):
msg = _('Please supply a package name')
LOG.error(msg)
raise forms.ValidationError(msg)
elif import_type == 'by_url' and not cleaned_data.get('url'):
msg = _('Please supply a package url')
LOG.error(msg)
raise forms.ValidationError(msg)
return cleaned_data
class PackageParamsMixin(forms.Form):
name = forms.CharField(label=_('Name'),
max_length=80,
help_text=_('80 characters max.'))
tags = forms.CharField(label=_('Tags'),
required=False,
help_text=_('Provide comma-separated list of words,'
' associated with the package'))
is_public = forms.BooleanField(label=_('Public'),
required=False,
widget=forms.CheckboxInput)
enabled = forms.BooleanField(label=_('Active'),
required=False,
widget=forms.CheckboxInput)
description = forms.CharField(label=_('Description'),
widget=forms.Textarea,
required=False)
def set_initial(self, package):
self.fields['name'].initial = package.name
self.fields['tags'].initial = ', '.join(package.tags)
self.fields['is_public'].initial = package.is_public
self.fields['enabled'].initial = package.enabled
self.fields['description'].initial = package.description
class UpdatePackageForm(PackageParamsMixin):
def __init__(self, *args, **kwargs):
package = kwargs.pop('package')
super(UpdatePackageForm, self).__init__(*args, **kwargs)
self.set_initial(package)
class ModifyPackageForm(PackageParamsMixin, horizon_forms.SelfHandlingForm):
def __init__(self, request, *args, **kwargs):
super(ModifyPackageForm, self).__init__(request, *args, **kwargs)
package = kwargs['initial']['package']
self.set_initial(package)
if package.type == 'Application':
self.fields['categories'] = forms.MultipleChoiceField(
label=_('Application Category'),
choices=[('', 'No categories available')],
required=False)
try:
categories = api.muranoclient(request).packages.categories()
if categories:
self.fields['categories'].choices = [(c, c)
for c in categories]
if package.categories:
self.fields['categories'].initial = dict(
(key, True) for key in package.categories)
except (exc.HTTPException, Exception):
msg = _('Unable to get list of categories')
LOG.exception(msg)
redirect = reverse('horizon:app-catalog:packages:index')
exceptions.handle(request,
msg,
redirect=redirect)
def handle(self, request, data):
app_id = self.initial.get('app_id')
LOG.debug('Updating package {0} with {1}'.format(app_id, data))
try:
data['tags'] = [t.strip() for t in data['tags'].split(',')]
result = api.muranoclient(request).packages.update(app_id, data)
messages.success(request, _('Package modified.'))
return result
except exc.HTTPForbidden:
msg = _("You are not allowed to perform this operation")
LOG.exception(msg)
exceptions.handle(
request,
msg,
redirect=reverse('horizon:app-catalog:packages:index'))
except exc.HTTPConflict:
msg = _('Package or Class with the same name is already made '
'public')
LOG.exception(msg)
messages.error(request, msg)
exceptions.handle(
request,
msg,
redirect=reverse('horizon:app-catalog:packages:index'))
except Exception as original_e:
reason = ''
exc_info = sys.exc_info()
if hasattr(original_e, 'details'):
try:
error = json.loads(original_e.details).get('error')
if error:
reason = error.get('message')
except ValueError:
# Let horizon operate with original exception
raise exc_info[0], exc_info[1], exc_info[2]
msg = _('Failed to modify the package. {0}').format(reason)
LOG.exception(msg)
redirect = reverse('horizon:app-catalog:packages:index')
exceptions.handle(request,
msg,
redirect=redirect)
class SelectCategories(forms.Form):
categories = forms.MultipleChoiceField(
label=_('Application Category'),
choices=[('', _('No categories available'))],
required=False)
def __init__(self, *args, **kwargs):
request = kwargs.pop('request')
super(SelectCategories, self).__init__(*args, **kwargs)
try:
categories = api.muranoclient(request).packages.categories()
if categories:
self.fields['categories'].choices = [(c, c)
for c in categories]
except (exc.HTTPException, Exception):
msg = _('Unable to get list of categories')
LOG.exception(msg)
redirect = reverse('horizon:app-catalog:packages:index')
exceptions.handle(request,
msg,
redirect=redirect)