Random fixes

This commit is contained in:
Marc Aymerich 2015-10-05 12:09:11 +00:00
parent a1f8d32ac7
commit 553be610cb
10 changed files with 91 additions and 47 deletions

View file

@ -414,3 +414,5 @@ mkhomedir_helper or create ssh homes with bash.rc and such
# warnings if some plugins are disabled, like make routes red # warnings if some plugins are disabled, like make routes red
# replace show emails by https://docs.python.org/3/library/email.contentmanager.html#module-email.contentmanager # replace show emails by https://docs.python.org/3/library/email.contentmanager.html#module-email.contentmanager
# SElect contact list breadcrumbs

View file

@ -5,6 +5,7 @@ from django.utils.translation import ugettext_lazy as _
from orchestra.admin import ExtendedModelAdmin from orchestra.admin import ExtendedModelAdmin
from orchestra.admin.utils import admin_link, admin_date, admin_colored, display_mono, display_code from orchestra.admin.utils import admin_link, admin_date, admin_colored, display_mono, display_code
from orchestra.plugins.admin import display_plugin_field
from . import settings, helpers from . import settings, helpers
from .backends import ServiceBackend from .backends import ServiceBackend
@ -27,7 +28,8 @@ STATE_COLORS = {
class RouteAdmin(ExtendedModelAdmin): class RouteAdmin(ExtendedModelAdmin):
list_display = ( list_display = (
'backend', 'host', 'match', 'display_model', 'display_actions', 'async', 'is_active' 'display_backend', 'host', 'match', 'display_model', 'display_actions', 'async',
'is_active'
) )
list_editable = ('host', 'match', 'async', 'is_active') list_editable = ('host', 'match', 'async', 'is_active')
list_filter = ('host', 'is_active', 'async', 'backend') list_filter = ('host', 'is_active', 'async', 'backend')
@ -41,6 +43,8 @@ class RouteAdmin(ExtendedModelAdmin):
backend.get_name(): backend.default_route_match for backend in ServiceBackend.get_backends() backend.get_name(): backend.default_route_match for backend in ServiceBackend.get_backends()
} }
display_backend = display_plugin_field('backend')
def display_model(self, route): def display_model(self, route):
try: try:
return escape(route.backend_class.model) return escape(route.backend_class.model)
@ -60,7 +64,8 @@ class RouteAdmin(ExtendedModelAdmin):
def formfield_for_dbfield(self, db_field, **kwargs): def formfield_for_dbfield(self, db_field, **kwargs):
""" Provides dynamic help text on backend form field """ """ Provides dynamic help text on backend form field """
if db_field.name == 'backend': if db_field.name == 'backend':
kwargs['widget'] = RouteBackendSelect('this.id', self.BACKEND_HELP_TEXT, self.DEFAULT_MATCH) kwargs['widget'] = RouteBackendSelect(
'this.id', self.BACKEND_HELP_TEXT, self.DEFAULT_MATCH)
field = super(RouteAdmin, self).formfield_for_dbfield(db_field, **kwargs) field = super(RouteAdmin, self).formfield_for_dbfield(db_field, **kwargs)
if db_field.name == 'host': if db_field.name == 'host':
# Cache host choices # Cache host choices
@ -71,7 +76,6 @@ class RouteAdmin(ExtendedModelAdmin):
field.choices = choices field.choices = choices
return field return field
def get_form(self, request, obj=None, **kwargs): def get_form(self, request, obj=None, **kwargs):
""" Include dynamic help text for existing objects """ """ Include dynamic help text for existing objects """
form = super(RouteAdmin, self).get_form(request, obj, **kwargs) form = super(RouteAdmin, self).get_form(request, obj, **kwargs)

View file

@ -1,14 +1,20 @@
from django import forms from django import forms
from orchestra.forms.widgets import SpanWidget
from orchestra.forms.widgets import paddingCheckboxSelectMultiple from orchestra.forms.widgets import SpanWidget, paddingCheckboxSelectMultiple
class RouteForm(forms.ModelForm): class RouteForm(forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(RouteForm, self).__init__(*args, **kwargs) super(RouteForm, self).__init__(*args, **kwargs)
if self.instance: if self.instance:
self.fields['backend'].widget = SpanWidget()
self.fields['backend'].required = False self.fields['backend'].required = False
self.fields['async_actions'].widget = paddingCheckboxSelectMultiple(45) try:
actions = self.instance.backend_class.actions backend_class = self.instance.backend_class
self.fields['async_actions'].choices = ((action, action) for action in actions) except KeyError:
self.fields['backend'].widget = SpanWidget(
display='<span style="color:red">%s NOT AVAILABLE</span>' % self.instance.backend)
else:
self.fields['backend'].widget = SpanWidget()
actions = backend_class.actions
self.fields['async_actions'].widget = paddingCheckboxSelectMultiple(45)
self.fields['async_actions'].choices = ((action, action) for action in actions)

View file

@ -1,3 +1,4 @@
import logging
import socket import socket
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
@ -10,12 +11,14 @@ from django.utils.translation import ugettext_lazy as _
from orchestra.core.validators import validate_ip_address, ValidationError from orchestra.core.validators import validate_ip_address, ValidationError
from orchestra.models.fields import NullableCharField, MultiSelectField from orchestra.models.fields import NullableCharField, MultiSelectField
#from orchestra.utils.apps import autodiscover
from . import settings from . import settings
from .backends import ServiceBackend from .backends import ServiceBackend
logger = logging.getLogger(__name__)
class Server(models.Model): class Server(models.Model):
""" Machine runing daemons (services) """ """ Machine runing daemons (services) """
name = models.CharField(_("name"), max_length=256, unique=True) name = models.CharField(_("name"), max_length=256, unique=True)
@ -147,12 +150,17 @@ class RouteQuerySet(models.QuerySet):
cache = kwargs.get('cache', {}) cache = kwargs.get('cache', {})
if not cache: if not cache:
for route in self.filter(is_active=True).select_related('host'): for route in self.filter(is_active=True).select_related('host'):
for action in route.backend_class.get_actions(): try:
key = (route.backend, action) backend_class = route.backend_class
try: except KeyError:
cache[key].append(route) logger.warning("Backed '%s' not installed." % route.backend)
except KeyError: else:
cache[key] = [route] for action in backend_class.get_actions():
key = (route.backend, action)
try:
cache[key].append(route)
except KeyError:
cache[key] = [route]
routes = [] routes = []
backend_cls = operation.backend backend_cls = operation.backend
key = (backend_cls.get_name(), operation.action) key = (backend_cls.get_name(), operation.action)
@ -202,7 +210,13 @@ class Route(models.Model):
if not self.match: if not self.match:
self.match = 'True' self.match = 'True'
if self.backend: if self.backend:
backend_model = self.backend_class.model_class() try:
backend_class = self.backend_class
except KeyError:
raise ValidationError({
'backend': _("Backend '%s' is not installed.") % self.backend
})
backend_model = backend_class.model_class()
try: try:
obj = backend_model.objects.all()[0] obj = backend_model.objects.all()[0]
except IndexError: except IndexError:

View file

@ -14,12 +14,12 @@ class MoodleMuBackend(ServiceController):
Creates a Moodle site on a Moodle multisite installation Creates a Moodle site on a Moodle multisite installation
// config.php // config.php
// map custom domains to sites
$site_map = array( $site_map = array(
// "<HTTP_HOST>" => ["<SITE_NAME>", "<WWWROOT>"], // "<HTTP_HOST>" => ["<SITE_NAME>", "<WWWROOT>"],
); );
$site = getenv("SITE"); $site = getenv("SITE");
$wwwroot = "https://{$site}-courses.pangea.org";
if ( $site == '' ) { if ( $site == '' ) {
$http_host = $_SERVER['HTTP_HOST']; $http_host = $_SERVER['HTTP_HOST'];
if (array_key_exists($http_host, $site_map)) { if (array_key_exists($http_host, $site_map)) {
@ -32,7 +32,16 @@ class MoodleMuBackend(ServiceController):
$site = array_shift((explode(".", $http_host))); $site = array_shift((explode(".", $http_host)));
$wwwroot = "https://{$site}-courses.pangea.org"; $wwwroot = "https://{$site}-courses.pangea.org";
} }
} else {
$wwwroot = "https://{$site}-courses.pangea.org";
foreach ($site_map as $key => $value) {
if ($value[0] == $site) {
$wwwroot = $value[1];
break;
}
}
} }
$prefix = str_replace('-', '_', $site); $prefix = str_replace('-', '_', $site);
$CFG->prefix = "${prefix}_"; $CFG->prefix = "${prefix}_";
$CFG->wwwroot = $wwwroot; $CFG->wwwroot = $wwwroot;

View file

@ -9,7 +9,7 @@ from orchestra.admin.utils import change_url, get_modeladmin
from orchestra.contrib.accounts.actions import list_accounts from orchestra.contrib.accounts.actions import list_accounts
from orchestra.contrib.accounts.admin import AccountAdminMixin from orchestra.contrib.accounts.admin import AccountAdminMixin
from orchestra.forms.widgets import DynamicHelpTextSelect from orchestra.forms.widgets import DynamicHelpTextSelect
from orchestra.plugins.admin import SelectPluginAdminMixin from orchestra.plugins.admin import SelectPluginAdminMixin, display_plugin_field
from orchestra.utils.html import get_on_site_link from orchestra.utils.html import get_on_site_link
from .filters import HasWebsiteListFilter, PHPVersionListFilter from .filters import HasWebsiteListFilter, PHPVersionListFilter
@ -50,7 +50,7 @@ class WebAppOptionInline(admin.TabularInline):
class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin): class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin):
list_display = ('name', 'type', 'display_detail', 'display_websites', 'account_link') list_display = ('name', 'display_type', 'display_detail', 'display_websites', 'account_link')
list_filter = ('type', HasWebsiteListFilter, PHPVersionListFilter) list_filter = ('type', HasWebsiteListFilter, PHPVersionListFilter)
inlines = [WebAppOptionInline] inlines = [WebAppOptionInline]
readonly_fields = ('account_link', ) readonly_fields = ('account_link', )
@ -62,6 +62,8 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin)
plugin_title = _("Web application type") plugin_title = _("Web application type")
actions = (list_accounts,) actions = (list_accounts,)
display_type = display_plugin_field('type')
def display_websites(self, webapp): def display_websites(self, webapp):
websites = [] websites = []
for content in webapp.content_set.all(): for content in webapp.content_set.all():
@ -81,8 +83,12 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin)
display_websites.allow_tags = True display_websites.allow_tags = True
def display_detail(self, webapp): def display_detail(self, webapp):
return webapp.type_instance.get_detail() try:
return webapp.type_instance.get_detail()
except KeyError:
return "<span style='color:red;'>Not available</span>"
display_detail.short_description = _("detail") display_detail.short_description = _("detail")
display_detail.allow_tags = True
# def get_form(self, request, obj=None, **kwargs): # def get_form(self, request, obj=None, **kwargs):
# form = super(WebAppAdmin, self).get_form(request, obj, **kwargs) # form = super(WebAppAdmin, self).get_form(request, obj, **kwargs)

View file

@ -15,8 +15,13 @@ class SelectPluginAdminMixin(object):
def get_form(self, request, obj=None, **kwargs): def get_form(self, request, obj=None, **kwargs):
if obj: if obj:
plugin = getattr(obj, '%s_instance' % self.plugin_field) try:
self.form = getattr(plugin, 'get_change_form', plugin.get_form)() plugin = getattr(obj, '%s_instance' % self.plugin_field)
except KeyError:
plugin_name = getattr(obj, self.plugin_field)
raise KeyError(_("Plugin '%s' is not available.") % plugin_name)
else:
self.form = getattr(plugin, 'get_change_form', plugin.get_form)()
else: else:
plugin = self.plugin.get(self.plugin_value)() plugin = self.plugin.get(self.plugin_value)()
self.form = plugin.get_form() self.form = plugin.get_form()
@ -90,9 +95,12 @@ class SelectPluginAdminMixin(object):
def change_view(self, request, object_id, form_url='', extra_context=None): def change_view(self, request, object_id, form_url='', extra_context=None):
obj = self.get_object(request, unquote(object_id)) obj = self.get_object(request, unquote(object_id))
plugin = getattr(obj, '%s_class' % self.plugin_field) try:
verbose = getattr(obj, '%s_class' % self.plugin_field).verbose_name
except KeyError:
raise KeyError(_("Plugin '%s' is not available.") % getattr(obj, self.plugin_field))
context = { context = {
'title': _("Change %s") % plugin.verbose_name, 'title': _("Change %s") % verbose,
} }
context.update(extra_context or {}) context.update(extra_context or {})
return super(SelectPluginAdminMixin, self).change_view( return super(SelectPluginAdminMixin, self).change_view(
@ -102,3 +110,17 @@ class SelectPluginAdminMixin(object):
if not change: if not change:
setattr(obj, self.plugin_field, self.plugin_value) setattr(obj, self.plugin_field, self.plugin_value)
obj.save() obj.save()
def display_plugin_field(field_name):
def inner(modeladmin, obj, field_name=field_name):
try:
plugin_class = getattr(obj, '%s_class' % field_name)
except KeyError:
value = getattr(obj, field_name)
return "<span style='color:red;' title='Not available'>%s</span>" % value
return getattr(obj, 'get_%s_display' % field_name)()
inner.short_description = field_name
inner.admin_order_field = field_name
inner.allow_tags = True
return inner

View file

@ -1,22 +1,3 @@
#from django.utils.importlib import import_module
#from django.utils.module_loading import module_has_submodule
#def autodiscover(module):
# """ Auto-discover INSTALLED_APPS module.py """
# from django.conf import settings
# for app in settings.INSTALLED_APPS:
# mod = import_module(app)
# try:
# import_module('%s.%s' % (app, module))
# except ImportError:
# # Decide whether to bubble up this error. If the app just
# # doesn't have the module, we can ignore the error
# # attempting to import it, otherwise we want it to bubble up.
# if module_has_submodule(mod, module):
# print '%s module caused this error:' % module
# raise
def isinstalled(app): def isinstalled(app):
""" returns True if app is installed """ """ returns True if app is installed """
from django.conf import settings from django.conf import settings

View file

@ -1,5 +1,5 @@
from django.http import Http404 from django.http import Http404
from django.contrib.admin.util import unquote from django.contrib.admin.utils import unquote
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.db.models import get_model from django.db.models import get_model
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404

View file

@ -1,7 +1,7 @@
django==1.8.4 django==1.8.5
django-fluent-dashboard==0.5.3 django-fluent-dashboard==0.5.3
django-admin-tools==0.6.0 django-admin-tools==0.6.0
django-extensions==1.5.2 django-extensions==1.5.7
django-celery==3.1.16 django-celery==3.1.16
celery==3.1.16 celery==3.1.16
kombu==3.0.23 kombu==3.0.23