From 6874060fc3ef9941d1d87a7dae440d9d3a2fafeb Mon Sep 17 00:00:00 2001 From: Marc Date: Sun, 28 Sep 2014 12:28:57 +0000 Subject: [PATCH] Updated ROADMAP --- ROADMAP.md | 63 +++++++++++-------- TODO.md | 18 +++++- orchestra/admin/options.py | 21 ++++++- orchestra/apps/resources/admin.py | 3 +- orchestra/apps/saas/models.py | 3 + orchestra/apps/saas/services/bscw.py | 8 ++- orchestra/apps/saas/services/gitlab.py | 10 ++- orchestra/apps/saas/services/options.py | 11 +--- orchestra/apps/saas/settings.py | 1 + orchestra/templates/admin/base.html | 6 +- .../admin/orchestra/select_plugin.html | 2 +- 11 files changed, 95 insertions(+), 51 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index fc7acb0d..64c0f97e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,45 +1,58 @@ # Roadmap -### 1.0a1 Milestone (first alpha release on Sep '14) +### 1.0a1 Milestone (first alpha release on Oct '14) 1. [x] Automated deployment of the development environment 2. [x] Automated installation and upgrading -2. [ ] Testing framework for running unittests and functional tests -2. [ ] Continuous integration environment -2. [x] Admin interface based on django.contrib.admin foundations -3. [x] REST API based on django-rest-framework foundations +2. [ ] Testing framework for running unittests and functional tests with LXC containers +2. [ ] Continuous integration with Jenkins +2. [x] Admin interface based on django.contrib.admin +3. [x] REST API for users 2. [x] [Orchestra-orm](https://github.com/glic3rinu/orchestra-orm) a Python library for easily interacting with the REST API 3. [x] Service orchestration framework -4. [ ] Data model, input validation, admin and REST interfaces, permissions, unit and functional tests, service management, migration scripts and some documentation of: - 1. [x] Web applications - 2. [ ] FTP accounts - 2. [ ] Databases - 1. [ ] Mail accounts, aliases, forwards - 1. [x] DNS - 1. [ ] Mailing lists +4. [ ] Data model, input validation, admin and REST interfaces, permissions, unit and functional tests, service management, migration scripts and documentation of: + 1. [x] PHP/static Web applications + 1. [x] Websites with Apache + 2. [-] FTP/rsync/scp/shell system accounts + 2. [-] Databases and database users + 1. [-] Mail accounts, aliases, forwards with Postfix and Dovecot + 1. [x] DNS with Bind + 1. [-] Mailing lists with Mailman 1. [x] Contact management and service contraction -1. [ ] Object level permissions system -1. [ ] Unittests of all the logic -2. [ ] Functional tests of all Admin and REST interations +1. [-] Unittests of the bussines logic logic +2. [-] Functional tests of all Admin UI and REST interations 1. [ ] Initial documentation -### 1.0b1 Milestone (first beta release on Nov '14) +### 1.0b1 Milestone (first beta release on Dec '14) -1. [x] Resource monitoring -1. [ ] Orders -2. [ ] Pricing -3. [ ] Billing -1. [ ] Payment methods -2. [ ] Scheduling of service cancellations and deactivations +1. [x] Resource allocation and monitoring +1. [x] Order tracking +2. [x] Service definition, service plans and pricing +3. [-] Billing + 3. [x] Invoice + 3. [x] Membership fee + 3. [-] Amendment invoice + 3. [-] Amendment fee + 3. [x] Pro Forma + 3. [ ] Advanced bill handling (move lines, undo billing, ...) +1. [x] Payment methods + 1. [x] SEPA Direct Debit + 2. [x] SEPA Credit Transfer 1. [ ] Full documentation +2. [-] Additional services + 2. [-] VPS with Proxmox/OpenVZ + 2. [-] SaaS (Software as a Service) Redmine/phpList/BSCW/Wordpress/Moodle/Drupal + 2. [x] Miscellaneous services +2. [x] Issue tracking system -### 1.0 Milestone (first stable release on Feb '15) +### 1.0 Milestone (first stable release on Apr '15) 1. [ ] Stabilize data model, internal APIs and REST API 1. [ ] Integration with third-party service providers, e.g. Gandi -1. [ ] Support for additional services like VPS -2. [ ] Issue tracking system 3. [ ] Translation to Spanish and Catalan +2. [ ] Scheduling of service cancellations and deactivations +1. [ ] Object level permissions system +2. [ ] API access for superusers diff --git a/TODO.md b/TODO.md index 834265d9..ebc7b47b 100644 --- a/TODO.md +++ b/TODO.md @@ -76,7 +76,6 @@ Remember that, as always with QuerySets, any subsequent chained methods which im * help_text on readonly_fields specialy Bill.state. (eg. A bill is in OPEN state when bla bla ) - * Transaction states: CREATED, PROCESSED, EXECUTED, COMMITED, ABORTED (SECURED, REJECTED?) * bill.send() -> transacction.EXECUTED when source=None * transaction.secured() -> bill.paid when bill.total == transaction.value else Error @@ -84,8 +83,8 @@ Remember that, as always with QuerySets, any subsequent chained methods which im * bill.bad_debt() -> transaction.ABORTED * transaction.ABORTED -> bill.bad_debt - Issue new transaction when current transaction is ABORTED -* underescore *every* private function +* underescore *every* private function * create log file at /var/log/orchestra.log and rotate @@ -94,7 +93,6 @@ Remember that, as always with QuerySets, any subsequent chained methods which im def register_on(self): return order.register_at.date() - * mail backend related_models = ('resources__content_type') ?? * ignore orders @@ -103,3 +101,17 @@ Remember that, as always with QuerySets, any subsequent chained methods which im * Domain backend PowerDNS Bind validation support? * Maildir billing tests/ webdisk billing tests (avg metric) + +* move icons to apps, and use appconfig to cleanup config stuff + +* when using modeladmin to store shit like self.account, make sure to have a cleanslate in each request + +*jabber with mailbox accounts (dovecto mail notification) + +* rename accounts register to manager register + +* make accounts django auth users + - when an account is created a mirrored system user is created + - system users are independent users, so they can have different passwords and all. + +* take a look icons from ajenti ;) diff --git a/orchestra/admin/options.py b/orchestra/admin/options.py index 795378e7..cee4510c 100644 --- a/orchestra/admin/options.py +++ b/orchestra/admin/options.py @@ -4,6 +4,8 @@ from django.contrib import admin from django.contrib.admin.utils import unquote from django.forms.models import BaseInlineFormSet from django.shortcuts import render, redirect +from django.utils.text import camel_case_to_spaces +from django.utils.translation import ugettext_lazy as _ from .utils import set_url_query, action_to_view, wrap_admin_view @@ -175,11 +177,24 @@ class SelectPluginAdminMixin(object): self.plugin_value = plugin_value if not plugin_value: self.plugin_value = self.plugin.get_plugins()[0] - return super(SelectPluginAdminMixin, self).add_view(request, - form_url=form_url, extra_context=extra_context) - # TODO add plugin name on title + context = { + 'title': _("Add new %s") % camel_case_to_spaces(self.plugin_value), + } + context.update(extra_context or {}) + return super(SelectPluginAdminMixin, self).add_view(request, form_url=form_url, + extra_context=context) return redirect('./select-plugin/?%s' % request.META['QUERY_STRING']) + def change_view(self, request, object_id, form_url='', extra_context=None): + obj = self.get_object(request, unquote(object_id)) + plugin_value = getattr(obj, self.plugin_field) + context = { + 'title': _("Change %s") % camel_case_to_spaces(plugin_value), + } + context.update(extra_context or {}) + return super(SelectPluginAdminMixin, self).change_view(request, object_id, + form_url=form_url, extra_context=context) + def save_model(self, request, obj, form, change): if not change: setattr(obj, self.plugin_field, self.plugin_value) diff --git a/orchestra/apps/resources/admin.py b/orchestra/apps/resources/admin.py index 9c558246..89c55a30 100644 --- a/orchestra/apps/resources/admin.py +++ b/orchestra/apps/resources/admin.py @@ -64,11 +64,12 @@ class ResourceAdmin(ExtendedModelAdmin): class ResourceDataAdmin(admin.ModelAdmin): list_display = ( - 'id', 'resource', 'used', 'allocated', 'updated_at', 'content_object_link' + 'id', 'resource_link', 'used', 'allocated', 'updated_at', 'content_object_link' ) list_filter = ('resource',) readonly_fields = ('content_object_link',) + resource_link = admin_link('resource') content_object_link = admin_link('content_object') def get_queryset(self, request): diff --git a/orchestra/apps/saas/models.py b/orchestra/apps/saas/models.py index f0053fc2..4c071f63 100644 --- a/orchestra/apps/saas/models.py +++ b/orchestra/apps/saas/models.py @@ -18,6 +18,9 @@ class SaaS(models.Model): verbose_name = "SaaS" verbose_name_plural = "SaaS" + def __unicode__(self): + return "%s (%s)" % (self.description, self.service_class.verbose_name) + @cached_property def service_class(self): return SoftwareService.get_plugin(self.service) diff --git a/orchestra/apps/saas/services/bscw.py b/orchestra/apps/saas/services/bscw.py index ae6e2781..ab57bb37 100644 --- a/orchestra/apps/saas/services/bscw.py +++ b/orchestra/apps/saas/services/bscw.py @@ -1,10 +1,14 @@ from django import forms from django.utils.translation import ugettext_lazy as _ -from .options import SoftwareService, SoftwareServiceForm +from orchestra.forms import PluginDataForm + +from .options import SoftwareService -class BSCWForm(SoftwareServiceForm): +class BSCWForm(PluginDataForm): + username = forms.CharField(label=_("Username"), max_length=64) + password = forms.CharField(label=_("Password"), max_length=64) quota = forms.IntegerField(label=_("Quota")) diff --git a/orchestra/apps/saas/services/gitlab.py b/orchestra/apps/saas/services/gitlab.py index 7a58d20d..1510d436 100644 --- a/orchestra/apps/saas/services/gitlab.py +++ b/orchestra/apps/saas/services/gitlab.py @@ -1,12 +1,16 @@ from django import forms from django.utils.translation import ugettext_lazy as _ -from .options import SoftwareService, SoftwareServiceForm +from orchestra.forms import PluginDataForm + +from .options import SoftwareService -class GitLabForm(SoftwareServiceForm): +class GitLabForm(PluginDataForm): + username = forms.CharField(label=_("Username"), max_length=64) + password = forms.CharField(label=_("Password"), max_length=64) project_name = forms.CharField(label=_("Project name"), max_length=64) - email = forms.CharField(label=_("Email"), max_length=64) + email = forms.EmailField(label=_("Email")) class GitLabService(SoftwareService): diff --git a/orchestra/apps/saas/services/options.py b/orchestra/apps/saas/services/options.py index bcf86bca..13f1c09b 100644 --- a/orchestra/apps/saas/services/options.py +++ b/orchestra/apps/saas/services/options.py @@ -1,7 +1,6 @@ from django import forms from django.utils.translation import ugettext_lazy as _ -from orchestra.forms import PluginDataForm from orchestra.utils import plugins from orchestra.utils.functional import cached from orchestra.utils.python import import_class @@ -9,17 +8,9 @@ from orchestra.utils.python import import_class from .. import settings -class SoftwareServiceForm(PluginDataForm): - username = forms.CharField(label=_("Username"), max_length=64) - password = forms.CharField(label=_("Password"), max_length=64) - - class Meta: - exclude = ('data', 'service') - - class SoftwareService(plugins.Plugin): description_field = '' - form = SoftwareServiceForm + form = None serializer = None @classmethod diff --git a/orchestra/apps/saas/settings.py b/orchestra/apps/saas/settings.py index 081564b1..2ba71ec9 100644 --- a/orchestra/apps/saas/settings.py +++ b/orchestra/apps/saas/settings.py @@ -4,4 +4,5 @@ from django.conf import settings SAAS_ENABLED_SERVICES = getattr(settings, 'SAAS_ENABLED_SERVICES', ( 'orchestra.apps.saas.services.bscw.BSCWService', 'orchestra.apps.saas.services.gitlab.GitLabService', + 'orchestra.apps.saas.services.phplist.PHPListService', )) diff --git a/orchestra/templates/admin/base.html b/orchestra/templates/admin/base.html index bf45da0f..c4bcc98b 100644 --- a/orchestra/templates/admin/base.html +++ b/orchestra/templates/admin/base.html @@ -37,9 +37,9 @@ {% if not is_popup %} - {% block header-stetic %} {% block breadcrumbs %}{% endblock %} {% endif %} diff --git a/orchestra/templates/admin/orchestra/select_plugin.html b/orchestra/templates/admin/orchestra/select_plugin.html index 8604e36b..7f6540f7 100644 --- a/orchestra/templates/admin/orchestra/select_plugin.html +++ b/orchestra/templates/admin/orchestra/select_plugin.html @@ -9,7 +9,7 @@