More robust bash backends using heredoc

This commit is contained in:
Marc Aymerich 2015-05-21 13:34:12 +00:00
parent 2ac063ef23
commit eec571d56f
12 changed files with 71 additions and 55 deletions

View file

@ -284,7 +284,6 @@ https://code.djangoproject.com/ticket/24576
# TODO orchestra related services code reload: celery/uwsgi reloading find aonther way without root and implement reload # TODO orchestra related services code reload: celery/uwsgi reloading find aonther way without root and implement reload
# password validation cracklib on change password form=?????
# reset setting button # reset setting button
# admin edit relevant djanog settings # admin edit relevant djanog settings
@ -301,8 +300,7 @@ https://code.djangoproject.com/ticket/24576
# TASK_BEAT_BACKEND = ('cron', 'celerybeat', 'uwsgi') # TASK_BEAT_BACKEND = ('cron', 'celerybeat', 'uwsgi')
# Ship orchestra production-ready (no DEBUG etc) # Ship orchestra production-ready (no DEBUG etc)
# import module and sed # Settings.parser.changes: if setting.value == default. remove
# if setting.value == default. remove
# reload generic admin view ?redirect=http... # reload generic admin view ?redirect=http...
# inspecting django db connection for asserting db readines? or performing a query # inspecting django db connection for asserting db readines? or performing a query
# wake up django mailer on send_mail # wake up django mailer on send_mail
@ -363,7 +361,6 @@ pip3 install https://github.com/fantix/gevent/archive/master.zip
# SIgnal handler for notify workers to reload stuff, like resource sync: https://docs.python.org/2/library/signal.html # SIgnal handler for notify workers to reload stuff, like resource sync: https://docs.python.org/2/library/signal.html
# BUG Delete related services also deletes account! # BUG Delete related services also deletes account!
# auto apend trailing slash
# get_related service__rates__isnull=TRue is that correct? # get_related service__rates__isnull=TRue is that correct?
@ -378,3 +375,7 @@ method(
# dovecot sieve only allolws one fucking active script. refactor mailbox shit to replace active script symlink by orchestra. Create a generic wrapper that includes al filters (rc, imp and orchestra) # dovecot sieve only allolws one fucking active script. refactor mailbox shit to replace active script symlink by orchestra. Create a generic wrapper that includes al filters (rc, imp and orchestra)
http://wiki2.dovecot.org/Pigeonhole/Sieve/Examples http://wiki2.dovecot.org/Pigeonhole/Sieve/Examples
# orders ignorign default filter is not very effective, because of selecting all orders for billing will select ignored too

View file

@ -8,6 +8,7 @@ from django.contrib import admin, messages
from django.contrib.admin.utils import unquote from django.contrib.admin.utils import unquote
from django.contrib.auth import admin as auth from django.contrib.auth import admin as auth
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.templatetags.static import static
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -160,11 +161,11 @@ class AccountAdminMixin(object):
def display_active(self, instance): def display_active(self, instance):
if not instance.is_active: if not instance.is_active:
return '<img src="/static/admin/img/icon-no.gif" alt="False">' return '<img src="%s" alt="False">' % static('admin/img/icon-no.gif')
elif not instance.account.is_active: elif not instance.account.is_active:
msg = _("Account disabled") msg = _("Account disabled")
return '<img src="/static/admin/img/icon-unknown.gif" alt="False" title="%s">' % msg return '<img src="%s" alt="False" title="%s">' % (static('admin/img/icon-unknown.gif'), msg)
return '<img src="/static/admin/img/icon-yes.gif" alt="True">' return '<img src="%s" alt="False">' % static('admin/img/icon-yes.gif')
display_active.short_description = _("active") display_active.short_description = _("active")
display_active.allow_tags = True display_active.allow_tags = True
display_active.admin_order_field = 'is_active' display_active.admin_order_field = 'is_active'

View file

@ -4,7 +4,7 @@ import textwrap
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orchestra.contrib.orchestration import ServiceController, replace from orchestra.contrib.orchestration import ServiceController
from orchestra.contrib.orchestration import Operation from orchestra.contrib.orchestration import Operation
from orchestra.utils.python import OrderedSet from orchestra.utils.python import OrderedSet
@ -44,9 +44,11 @@ class Bind9MasterDomainBackend(ServiceController):
def update_zone(self, domain, context): def update_zone(self, domain, context):
context['zone'] = ';; %(banner)s\n' % context context['zone'] = ';; %(banner)s\n' % context
context['zone'] += domain.render_zone().replace("'", '"') context['zone'] += domain.render_zone()
self.append(textwrap.dedent("""\ self.append(textwrap.dedent("""
echo -e '%(zone)s' > %(zone_path)s.tmp cat << 'EOF' > %(zone_path)s.tmp
%(zone)s
EOF
diff -N -I'^\s*;;' %(zone_path)s %(zone_path)s.tmp || UPDATED=1 diff -N -I'^\s*;;' %(zone_path)s %(zone_path)s.tmp || UPDATED=1
# Because bind reload will not display any fucking error # Because bind reload will not display any fucking error
named-checkzone -k fail -n fail %(name)s %(zone_path)s.tmp named-checkzone -k fail -n fail %(name)s %(zone_path)s.tmp
@ -55,8 +57,10 @@ class Bind9MasterDomainBackend(ServiceController):
) )
def update_conf(self, context): def update_conf(self, context):
self.append(textwrap.dedent("""\ self.append(textwrap.dedent("""
conf='%(conf)s' read -r -d '' conf << 'EOF' || true
%(conf)s
EOF
sed '/zone "%(name)s".*/,/^\s*};\s*$/!d' %(conf_path)s | diff -B -I"^\s*//" - <(echo "${conf}") || { sed '/zone "%(name)s".*/,/^\s*};\s*$/!d' %(conf_path)s | diff -B -I"^\s*//" - <(echo "${conf}") || {
sed -i -e '/zone\s\s*"%(name)s".*/,/^\s*};/d' \\ sed -i -e '/zone\s\s*"%(name)s".*/,/^\s*};/d' \\
-e 'N; /^\s*\\n\s*$/d; P; D' %(conf_path)s -e 'N; /^\s*\\n\s*$/d; P; D' %(conf_path)s
@ -82,7 +86,7 @@ class Bind9MasterDomainBackend(ServiceController):
if context['name'][0] in ('*', '_'): if context['name'][0] in ('*', '_'):
# These can never be top level domains # These can never be top level domains
return return
self.append(textwrap.dedent("""\ self.append(textwrap.dedent("""
sed -e '/zone\s\s*"%(name)s".*/,/^\s*};\s*$/d' \\ sed -e '/zone\s\s*"%(name)s".*/,/^\s*};\s*$/d' \\
-e 'N; /^\s*\\n\s*$/d; P; D' %(conf_path)s > %(conf_path)s.tmp""") % context -e 'N; /^\s*\\n\s*$/d; P; D' %(conf_path)s > %(conf_path)s.tmp""") % context
) )
@ -141,7 +145,7 @@ class Bind9MasterDomainBackend(ServiceController):
'also_notify': '; '.join(slaves) + ';' if slaves else '', 'also_notify': '; '.join(slaves) + ';' if slaves else '',
'conf_path': self.CONF_PATH, 'conf_path': self.CONF_PATH,
} }
context['conf'] = textwrap.dedent(""" context['conf'] = textwrap.dedent("""\
zone "%(name)s" { zone "%(name)s" {
// %(banner)s // %(banner)s
type master; type master;
@ -150,7 +154,7 @@ class Bind9MasterDomainBackend(ServiceController):
also-notify { %(also_notify)s }; also-notify { %(also_notify)s };
notify yes; notify yes;
};""") % context };""") % context
return replace(context, "'", '"') return context
class Bind9SlaveDomainBackend(Bind9MasterDomainBackend): class Bind9SlaveDomainBackend(Bind9MasterDomainBackend):
@ -200,4 +204,4 @@ class Bind9SlaveDomainBackend(Bind9MasterDomainBackend):
masters { %(masters)s; }; masters { %(masters)s; };
allow-notify { %(masters)s; }; allow-notify { %(masters)s; };
};""") % context };""") % context
return replace(context, "'", '"') return context

View file

@ -107,7 +107,7 @@ class Domain(models.Model):
zone += subdomain.render_records() zone += subdomain.render_records()
for subdomain in sorted(tail, key=lambda x: len(x.name), reverse=True): for subdomain in sorted(tail, key=lambda x: len(x.name), reverse=True):
zone += subdomain.render_records() zone += subdomain.render_records()
return zone return zone.strip()
def refresh_serial(self): def refresh_serial(self):
""" Increases the domain serial number by one """ """ Increases the domain serial number by one """

View file

@ -3,6 +3,7 @@ from django.contrib.auth import get_user_model
from django.utils.html import strip_tags from django.utils.html import strip_tags
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.templatetags.static import static
from markdown import markdown from markdown import markdown
from orchestra.forms.widgets import SpanWidget from orchestra.forms.widgets import SpanWidget
@ -13,7 +14,7 @@ from .models import Queue, Ticket
class MarkDownWidget(forms.Textarea): class MarkDownWidget(forms.Textarea):
""" MarkDown textarea widget with syntax preview """ """ MarkDown textarea widget with syntax preview """
markdown_url = '/static/issues/markdown_syntax.html' markdown_url = static('issues/markdown_syntax.html')
markdown_help_text = ( markdown_help_text = (
'<a href="%s" onclick=\'window.open("%s", "", "resizable=yes, ' '<a href="%s" onclick=\'window.open("%s", "", "resizable=yes, '
'location=no, width=300, height=640, menubar=no, status=no, scrollbars=yes"); ' 'location=no, width=300, height=640, menubar=no, status=no, scrollbars=yes"); '

View file

@ -6,7 +6,7 @@ import textwrap
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orchestra.contrib.orchestration import ServiceController, replace from orchestra.contrib.orchestration import ServiceController
from orchestra.contrib.resources import ServiceMonitor from orchestra.contrib.resources import ServiceMonitor
from . import settings from . import settings
@ -22,7 +22,7 @@ class SieveFilteringMixin(object):
for box in re.findall(r'fileinto\s+"([^"]+)"', content): for box in re.findall(r'fileinto\s+"([^"]+)"', content):
# create mailboxes if fileinfo is provided witout ':create' option # create mailboxes if fileinfo is provided witout ':create' option
context['box'] = box context['box'] = box
self.append(textwrap.dedent("""\ self.append(textwrap.dedent("""
mkdir -p %(maildir)s/.%(box)s mkdir -p %(maildir)s/.%(box)s
chown %(user)s:%(group)s %(maildir)s/.%(box)s chown %(user)s:%(group)s %(maildir)s/.%(box)s
if [[ ! $(grep '%(box)s' %(maildir)s/subscriptions) ]]; then if [[ ! $(grep '%(box)s' %(maildir)s/subscriptions) ]]; then
@ -34,9 +34,11 @@ class SieveFilteringMixin(object):
context['filtering_cpath'] = re.sub(r'\.sieve$', '.svbin', context['filtering_path']) context['filtering_cpath'] = re.sub(r'\.sieve$', '.svbin', context['filtering_path'])
if content: if content:
context['filtering'] = ('# %(banner)s\n' + content) % context context['filtering'] = ('# %(banner)s\n' + content) % context
self.append(textwrap.dedent("""\ self.append(textwrap.dedent("""
mkdir -p $(dirname '%(filtering_path)s') mkdir -p $(dirname '%(filtering_path)s')
echo '%(filtering)s' > %(filtering_path)s cat << 'EOF' > %(filtering_path)s
%(filtering)s
EOF
sievec %(filtering_path)s sievec %(filtering_path)s
chown %(user)s:%(group)s {%(filtering_path)s,%(filtering_cpath)s} chown %(user)s:%(group)s {%(filtering_path)s,%(filtering_cpath)s}
""") % context """) % context
@ -66,7 +68,9 @@ class UNIXUserMaildirBackend(SieveFilteringMixin, ServiceController):
# Fucking postfix SASL caches credentials # Fucking postfix SASL caches credentials
old_password=$(grep "^%(user)s:" /etc/shadow|cut -d':' -f2) old_password=$(grep "^%(user)s:" /etc/shadow|cut -d':' -f2)
usermod %(user)s --password '%(password)s' --shell %(initial_shell)s usermod %(user)s --password '%(password)s' --shell %(initial_shell)s
[[ "$old_password" != "%(password)s" ]] && RESTART_POSTFIX=1 if [[ "$old_password" != "%(password)s" ]]; then
RESTART_POSTFIX=1
fi
else else
useradd %(user)s --home %(home)s --password '%(password)s' useradd %(user)s --home %(home)s --password '%(password)s'
fi fi
@ -118,7 +122,7 @@ class UNIXUserMaildirBackend(SieveFilteringMixin, ServiceController):
'initial_shell': self.SHELL, 'initial_shell': self.SHELL,
'banner': self.get_banner(), 'banner': self.get_banner(),
} }
return replace(context, "'", '"') return context
class DovecotPostfixPasswdVirtualUserBackend(SieveFilteringMixin, ServiceController): class DovecotPostfixPasswdVirtualUserBackend(SieveFilteringMixin, ServiceController):
@ -158,7 +162,7 @@ class DovecotPostfixPasswdVirtualUserBackend(SieveFilteringMixin, ServiceControl
def delete(self, mailbox): def delete(self, mailbox):
context = self.get_context(mailbox) context = self.get_context(mailbox)
self.append(textwrap.dedent("""\ self.append(textwrap.dedent("""
nohup bash -c 'sleep 2 && killall -u %(uid)s -s KILL' &> /dev/null & nohup bash -c 'sleep 2 && killall -u %(uid)s -s KILL' &> /dev/null &
killall -u %(uid)s || true killall -u %(uid)s || true
sed -i '/^%(user)s:.*/d' %(passwd_path)s sed -i '/^%(user)s:.*/d' %(passwd_path)s
@ -186,7 +190,7 @@ class DovecotPostfixPasswdVirtualUserBackend(SieveFilteringMixin, ServiceControl
context = { context = {
'virtual_mailbox_maps': settings.MAILBOXES_VIRTUAL_MAILBOX_MAPS_PATH 'virtual_mailbox_maps': settings.MAILBOXES_VIRTUAL_MAILBOX_MAPS_PATH
} }
self.append(textwrap.dedent("""\ self.append(textwrap.dedent("""
[[ $UPDATED_VIRTUAL_MAILBOX_MAPS == 1 ]] && { [[ $UPDATED_VIRTUAL_MAILBOX_MAPS == 1 ]] && {
postmap %(virtual_mailbox_maps)s postmap %(virtual_mailbox_maps)s
}""") % context }""") % context
@ -212,7 +216,7 @@ class DovecotPostfixPasswdVirtualUserBackend(SieveFilteringMixin, ServiceControl
'passwd': '{user}:{password}:{uid}:{gid}::{home}::{extra_fields}'.format(**context), 'passwd': '{user}:{password}:{uid}:{gid}::{home}::{extra_fields}'.format(**context),
'deleted_home': settings.MAILBOXES_MOVE_ON_DELETE_PATH % context, 'deleted_home': settings.MAILBOXES_MOVE_ON_DELETE_PATH % context,
}) })
return replace(context, "'", '"') return context
class PostfixAddressVirtualDomainBackend(ServiceController): class PostfixAddressVirtualDomainBackend(ServiceController):
@ -248,7 +252,7 @@ class PostfixAddressVirtualDomainBackend(ServiceController):
def exclude_virtual_alias_domain(self, context): def exclude_virtual_alias_domain(self, context):
domain = context['domain'] domain = context['domain']
if self.is_last_domain(domain): if self.is_last_domain(domain):
self.append(textwrap.dedent("""\ self.append(textwrap.dedent("""
if [[ $(grep '^%(domain)s\s*$' %(virtual_alias_domains)s) ]]; then if [[ $(grep '^%(domain)s\s*$' %(virtual_alias_domains)s) ]]; then
sed -i '/^%(domain)s\s*/d' %(virtual_alias_domains)s sed -i '/^%(domain)s\s*/d' %(virtual_alias_domains)s
UPDATED_VIRTUAL_ALIAS_DOMAINS=1 UPDATED_VIRTUAL_ALIAS_DOMAINS=1
@ -288,7 +292,7 @@ class PostfixAddressVirtualDomainBackend(ServiceController):
'email': address.email, 'email': address.email,
'local_domain': settings.MAILBOXES_LOCAL_DOMAIN, 'local_domain': settings.MAILBOXES_LOCAL_DOMAIN,
}) })
return replace(context, "'", '"') return context
class PostfixAddressBackend(PostfixAddressVirtualDomainBackend): class PostfixAddressBackend(PostfixAddressVirtualDomainBackend):
@ -401,7 +405,7 @@ class DovecotMaildirDisk(ServiceMonitor):
'object_id': mailbox.pk 'object_id': mailbox.pk
} }
context['maildir_path'] = settings.MAILBOXES_MAILDIRSIZE_PATH % context context['maildir_path'] = settings.MAILBOXES_MAILDIRSIZE_PATH % context
return replace(context, "'", '"') return context
class PostfixMailscannerTraffic(ServiceMonitor): class PostfixMailscannerTraffic(ServiceMonitor):
@ -552,4 +556,4 @@ class PostfixMailscannerTraffic(ServiceMonitor):
'object_id': mailbox.pk, 'object_id': mailbox.pk,
'last_date': self.get_last_date(mailbox.pk).strftime("%Y-%m-%d %H:%M:%S %Z"), 'last_date': self.get_last_date(mailbox.pk).strftime("%Y-%m-%d %H:%M:%S %Z"),
} }
return replace(context, "'", '"') return context

View file

@ -284,7 +284,7 @@ class Exim4Traffic(ServiceMonitor):
'object_id': user.pk, 'object_id': user.pk,
'last_date': self.get_last_date(user.pk).strftime("%Y-%m-%d %H:%M:%S %Z"), 'last_date': self.get_last_date(user.pk).strftime("%Y-%m-%d %H:%M:%S %Z"),
} }
return replace(context, "'", '"') return context
class VsFTPdTraffic(ServiceMonitor): class VsFTPdTraffic(ServiceMonitor):

View file

@ -1,8 +1,6 @@
import pkgutil import pkgutil
import textwrap import textwrap
from orchestra.contrib.orchestration.backends import replace
from .. import settings from .. import settings
@ -57,7 +55,7 @@ class WebAppServiceMixin(object):
'is_mounted': webapp.content_set.exists(), 'is_mounted': webapp.content_set.exists(),
} }
context['deleted_app_path'] = settings.WEBAPPS_MOVE_ON_DELETE_PATH % context context['deleted_app_path'] = settings.WEBAPPS_MOVE_ON_DELETE_PATH % context
return replace(context, "'", '"') return context
for __, module_name, __ in pkgutil.walk_packages(__path__): for __, module_name, __ in pkgutil.walk_packages(__path__):

View file

@ -5,7 +5,7 @@ from collections import OrderedDict
from django.template import Template, Context from django.template import Template, Context
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orchestra.contrib.orchestration import ServiceController, replace from orchestra.contrib.orchestration import ServiceController
from . import WebAppServiceMixin from . import WebAppServiceMixin
from .. import settings from .. import settings
@ -43,8 +43,10 @@ class PHPBackend(WebAppServiceMixin, ServiceController):
self.set_under_construction(context) self.set_under_construction(context)
def save_fpm(self, webapp, context): def save_fpm(self, webapp, context):
self.append(textwrap.dedent("""\ self.append(textwrap.dedent("""
fpm_config='%(fpm_config)s' read -r -d '' fpm_config << 'EOF' || true
%(fpm_config)s
EOF
{ {
echo -e "${fpm_config}" | diff -N -I'^\s*;;' %(fpm_path)s - echo -e "${fpm_config}" | diff -N -I'^\s*;;' %(fpm_path)s -
} || { } || {
@ -57,7 +59,9 @@ class PHPBackend(WebAppServiceMixin, ServiceController):
def save_fcgid(self, webapp, context): def save_fcgid(self, webapp, context):
self.append("mkdir -p %(wrapper_dir)s" % context) self.append("mkdir -p %(wrapper_dir)s" % context)
self.append(textwrap.dedent("""\ self.append(textwrap.dedent("""\
wrapper='%(wrapper)s' read -r -d '' wrapper << 'EOF' || true
%(wrapper)s
EOF
{ {
echo -e "${wrapper}" | diff -N -I'^\s*#' %(wrapper_path)s - echo -e "${wrapper}" | diff -N -I'^\s*#' %(wrapper_path)s -
} || { } || {
@ -73,8 +77,10 @@ class PHPBackend(WebAppServiceMixin, ServiceController):
self.append("chmod 550 %(wrapper_path)s" % context) self.append("chmod 550 %(wrapper_path)s" % context)
self.append("chown -R %(user)s:%(group)s %(wrapper_dir)s" % context) self.append("chown -R %(user)s:%(group)s %(wrapper_dir)s" % context)
if context['cmd_options']: if context['cmd_options']:
self.append(textwrap.dedent(""" self.append(textwrap.dedent("""\
cmd_options='%(cmd_options)s' read -r -d '' cmd_options << 'EOF' || true
%(cmd_options)s
EOF
{ {
echo -e "${cmd_options}" | diff -N -I'^\s*#' %(cmd_options_path)s - echo -e "${cmd_options}" | diff -N -I'^\s*#' %(cmd_options_path)s -
} || { } || {
@ -233,7 +239,6 @@ class PHPBackend(WebAppServiceMixin, ServiceController):
'wrapper_path': wrapper_path, 'wrapper_path': wrapper_path,
'wrapper_dir': os.path.dirname(wrapper_path), 'wrapper_dir': os.path.dirname(wrapper_path),
}) })
replace(context, "'", '"')
context.update({ context.update({
'cmd_options': self.get_fcgid_cmd_options(webapp, context), 'cmd_options': self.get_fcgid_cmd_options(webapp, context),
'cmd_options_path': settings.WEBAPPS_FCGID_CMD_OPTIONS_PATH % context, 'cmd_options_path': settings.WEBAPPS_FCGID_CMD_OPTIONS_PATH % context,
@ -255,7 +260,5 @@ class PHPBackend(WebAppServiceMixin, ServiceController):
'max_requests': settings.WEBAPPS_PHP_MAX_REQUESTS, 'max_requests': settings.WEBAPPS_PHP_MAX_REQUESTS,
}) })
self.update_fpm_context(webapp, context) self.update_fpm_context(webapp, context)
# Fcgid context do contain special charactes
replace(context, "'", '"')
self.update_fcgid_context(webapp, context) self.update_fcgid_context(webapp, context)
return context return context

View file

@ -5,7 +5,7 @@ import textwrap
from django.template import Template, Context from django.template import Template, Context
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orchestra.contrib.orchestration import ServiceController, replace from orchestra.contrib.orchestration import ServiceController
from orchestra.contrib.resources import ServiceMonitor from orchestra.contrib.resources import ServiceMonitor
from .. import settings from .. import settings
@ -99,9 +99,11 @@ class Apache2Backend(ServiceController):
apache_conf += self.render_virtual_host(site, context, ssl=True) apache_conf += self.render_virtual_host(site, context, ssl=True)
if site.protocol == site.HTTPS_ONLY: if site.protocol == site.HTTPS_ONLY:
apache_conf += self.render_redirect_https(context) apache_conf += self.render_redirect_https(context)
context['apache_conf'] = apache_conf.replace("'", '"') context['apache_conf'] = apache_conf
self.append(textwrap.dedent("""\ self.append(textwrap.dedent("""\
apache_conf='%(apache_conf)s' read -r -d '' apache_conf << 'EOF' || true
%(apache_conf)s
EOF
{ {
echo -e "${apache_conf}" | diff -N -I'^\s*#' %(sites_available)s - echo -e "${apache_conf}" | diff -N -I'^\s*#' %(sites_available)s -
} || { } || {
@ -376,7 +378,7 @@ class Apache2Backend(ServiceController):
} }
if not context['ips']: if not context['ips']:
raise ValueError("WEBSITES_DEFAULT_IPS is empty.") raise ValueError("WEBSITES_DEFAULT_IPS is empty.")
return replace(context, "'", '"') return context
def set_content_context(self, content, context): def set_content_context(self, content, context):
content_context = { content_context = {
@ -385,7 +387,6 @@ class Apache2Backend(ServiceController):
'app_name': content.webapp.name, 'app_name': content.webapp.name,
'app_path': content.webapp.get_path(), 'app_path': content.webapp.get_path(),
} }
content_context = replace(content_context, "'", '"')
context.update(content_context) context.update(content_context)
@ -458,4 +459,4 @@ class Apache2Traffic(ServiceMonitor):
'last_date': self.get_last_date(site.pk).strftime("%Y-%m-%d %H:%M:%S %Z"), 'last_date': self.get_last_date(site.pk).strftime("%Y-%m-%d %H:%M:%S %Z"),
'object_id': site.pk, 'object_id': site.pk,
} }
return replace(context, "'", '"') return context

View file

@ -3,7 +3,7 @@ import textwrap
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orchestra.contrib.orchestration import ServiceController, replace from orchestra.contrib.orchestration import ServiceController
from .. import settings from .. import settings
@ -26,7 +26,9 @@ class WebalizerBackend(ServiceController):
if [[ ! -e %(webalizer_path)s/index.html ]]; then if [[ ! -e %(webalizer_path)s/index.html ]]; then
echo 'Webstats are coming soon' > %(webalizer_path)s/index.html echo 'Webstats are coming soon' > %(webalizer_path)s/index.html
fi fi
echo '%(webalizer_conf)s' > %(webalizer_conf_path)s cat << 'EOF' > %(webalizer_conf_path)s
%(webalizer_conf)s
EOF
chown %(user)s:www-data %(webalizer_path)s chown %(user)s:www-data %(webalizer_path)s
chmod g+xr %(webalizer_path)s chmod g+xr %(webalizer_path)s
""") % context """) % context
@ -98,4 +100,4 @@ class WebalizerBackend(ServiceController):
SearchEngine alltheweb.com query= SearchEngine alltheweb.com query=
DumpSites yes""") % context DumpSites yes""") % context
return replace(context, "'", '"') return context

View file

@ -152,6 +152,7 @@ class Command(BaseCommand):
'project_dir': paths.get_project_dir(), 'project_dir': paths.get_project_dir(),
'site_dir': paths.get_site_dir(), 'site_dir': paths.get_site_dir(),
'static_root': settings.STATIC_ROOT, 'static_root': settings.STATIC_ROOT,
'static_url': (settings.STATIC_URL or '/static').rstrip('/')
'user': user, 'user': user,
'group': options.get('group') or user, 'group': options.get('group') or user,
'home': expanduser("~%s" % options.get('user')), 'home': expanduser("~%s" % options.get('user')),
@ -178,7 +179,7 @@ class Command(BaseCommand):
uwsgi_pass unix:///var/run/uwsgi/app/%(project_name)s/socket; uwsgi_pass unix:///var/run/uwsgi/app/%(project_name)s/socket;
include uwsgi_params; include uwsgi_params;
} }
location /static { location %(static_url)s {
alias %(static_root)s; alias %(static_root)s;
expires 30d; expires 30d;
} }