Upgrade service tests
This commit is contained in:
parent
276c02c2fd
commit
647bc43a5a
|
@ -1,4 +1,5 @@
|
|||
from orchestra.apps.accounts.models import Account
|
||||
from orchestra.core import services
|
||||
|
||||
|
||||
def get_related_objects(origin, max_depth=2):
|
||||
|
@ -9,7 +10,6 @@ def get_related_objects(origin, max_depth=2):
|
|||
flexibility. A more comprehensive approach may be considered if
|
||||
a use-case calls for it.
|
||||
"""
|
||||
|
||||
def related_iterator(node):
|
||||
for field in node._meta.virtual_fields:
|
||||
if hasattr(field, 'ct_field'):
|
||||
|
@ -26,7 +26,7 @@ def get_related_objects(origin, max_depth=2):
|
|||
return None
|
||||
node = models[-1]
|
||||
if len(models) > 1:
|
||||
if hasattr(node, 'account') or isinstance(node, Account):
|
||||
if type(node) in services:
|
||||
return node
|
||||
for related in related_iterator(node):
|
||||
if related and related not in models:
|
||||
|
|
|
@ -14,7 +14,7 @@ from django.contrib.contenttypes.models import ContentType
|
|||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.core import accounts
|
||||
from orchestra.core import accounts, services
|
||||
from orchestra.models import queryset
|
||||
from orchestra.utils.python import import_class
|
||||
|
||||
|
@ -71,6 +71,7 @@ class OrderQuerySet(models.QuerySet):
|
|||
for order in orders:
|
||||
bp = service.handler.get_billing_point(order, **options)
|
||||
end = max(end, bp)
|
||||
# FIXME exclude cancelled except cancelled and billed > ini
|
||||
qs = qs | Q(
|
||||
Q(service=service, account=account_id, registered_on__lt=end) &
|
||||
Q(Q(billed_until__isnull=True) | Q(billed_until__lt=end))
|
||||
|
@ -236,27 +237,26 @@ class MetricStorage(models.Model):
|
|||
accounts.register(Order)
|
||||
|
||||
|
||||
_excluded_models = (MetricStorage, LogEntry, Order, ContentType, MigrationRecorder.Migration)
|
||||
|
||||
# TODO build a cache hash table {model: related, model: None}
|
||||
@receiver(post_delete, dispatch_uid="orders.cancel_orders")
|
||||
def cancel_orders(sender, **kwargs):
|
||||
if sender not in _excluded_models:
|
||||
if sender._meta.app_label not in settings.ORDERS_EXCLUDED_APPS:
|
||||
instance = kwargs['instance']
|
||||
if hasattr(instance, 'account'):
|
||||
if type(instance) in services:
|
||||
for order in Order.objects.by_object(instance).active():
|
||||
order.cancel()
|
||||
else:
|
||||
elif not hasattr(instance, 'account'):
|
||||
related = helpers.get_related_objects(instance)
|
||||
if related and related != instance:
|
||||
Order.update_orders(related)
|
||||
|
||||
@receiver(post_save, dispatch_uid="orders.update_orders")
|
||||
def update_orders(sender, **kwargs):
|
||||
if sender not in _excluded_models:
|
||||
if sender._meta.app_label not in settings.ORDERS_EXCLUDED_APPS:
|
||||
instance = kwargs['instance']
|
||||
if hasattr(instance, 'account'):
|
||||
if type(instance) in services:
|
||||
Order.update_orders(instance)
|
||||
else:
|
||||
elif not hasattr(instance, 'account'):
|
||||
related = helpers.get_related_objects(instance)
|
||||
if related and related != instance:
|
||||
Order.update_orders(related)
|
||||
|
|
|
@ -6,3 +6,16 @@ ORDERS_BILLING_BACKEND = getattr(settings, 'ORDERS_BILLING_BACKEND',
|
|||
|
||||
|
||||
ORDERS_SERVICE_MODEL = getattr(settings, 'ORDERS_SERVICE_MODEL', 'services.Service')
|
||||
|
||||
|
||||
ORDERS_EXCLUDED_APPS = getattr(settings, 'ORDERS_EXCLUDED_APPS', (
|
||||
'orders',
|
||||
'admin',
|
||||
'contenttypes',
|
||||
'auth',
|
||||
'migrations',
|
||||
'sessions',
|
||||
'orchestration',
|
||||
'bills',
|
||||
# Do not put services here (plans)
|
||||
))
|
||||
|
|
|
@ -177,8 +177,7 @@ def create_resource_relation():
|
|||
data = self.obj.resource_set.get(resource__name=attr)
|
||||
except ResourceData.DoesNotExist:
|
||||
model = self.obj._meta.model_name
|
||||
resource = Resource.objects.get(content_type__model=model,
|
||||
name=attr, is_active=True)
|
||||
resource = Resource.objects.get(content_type__model=model, name=attr, is_active=True)
|
||||
data = ResourceData(content_object=self.obj, resource=resource)
|
||||
return data
|
||||
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
from orchestra.apps.accounts.models import Account
|
||||
from orchestra.apps.users.models import User
|
||||
from orchestra.utils.tests import BaseTestCase, random_ascii
|
||||
|
||||
|
||||
# TODO remove this shit
|
||||
class BaseBillingTest(BaseTestCase):
|
||||
def create_account(self):
|
||||
account = Account.objects.create()
|
||||
username = 'account_%s' % random_ascii(5)
|
||||
user = User.objects.create_user(username=username, account=account)
|
||||
account.user = user
|
||||
account.save()
|
||||
return account
|
||||
|
||||
pass
|
||||
|
||||
# TODO web disk
|
||||
|
|
|
@ -5,7 +5,7 @@ from dateutil.relativedelta import relativedelta
|
|||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils import timezone
|
||||
|
||||
from orchestra.apps.users.models import User
|
||||
from orchestra.apps.systemusers.models import SystemUser
|
||||
from orchestra.utils.tests import random_ascii
|
||||
|
||||
from ... import settings
|
||||
|
@ -18,8 +18,8 @@ class FTPBillingTest(BaseBillingTest):
|
|||
def create_ftp_service(self):
|
||||
return Service.objects.create(
|
||||
description="FTP Account",
|
||||
content_type=ContentType.objects.get_for_model(User),
|
||||
match='not user.is_main and user.has_posix()',
|
||||
content_type=ContentType.objects.get_for_model(SystemUser),
|
||||
match='not systemuser.is_main',
|
||||
billing_period=Service.ANUAL,
|
||||
billing_point=Service.FIXED_DATE,
|
||||
is_fee=False,
|
||||
|
@ -36,10 +36,7 @@ class FTPBillingTest(BaseBillingTest):
|
|||
if not account:
|
||||
account = self.create_account()
|
||||
username = '%s_ftp' % random_ascii(10)
|
||||
user = User.objects.create_user(username=username, account=account)
|
||||
POSIX = user._meta.get_field_by_name('posix')[0].model
|
||||
POSIX.objects.create(user=user)
|
||||
return user
|
||||
return SystemUser.objects.create_user(username, account=account)
|
||||
|
||||
def test_ftp_account_1_year_fiexed(self):
|
||||
service = self.create_ftp_service()
|
||||
|
|
|
@ -13,7 +13,7 @@ from . import BaseBillingTest
|
|||
|
||||
|
||||
class BaseTrafficBillingTest(BaseBillingTest):
|
||||
METRIC = 'account.resources.traffic.used'
|
||||
TRAFFIC_METRIC = 'account.resources.traffic.used'
|
||||
|
||||
def create_traffic_service(self):
|
||||
service = Service.objects.create(
|
||||
|
@ -23,7 +23,7 @@ class BaseTrafficBillingTest(BaseBillingTest):
|
|||
billing_period=Service.MONTHLY,
|
||||
billing_point=Service.FIXED_DATE,
|
||||
is_fee=False,
|
||||
metric=self.METRIC,
|
||||
metric=self.TRAFFIC_METRIC,
|
||||
pricing_period=Service.BILLING_PERIOD,
|
||||
rate_algorithm=Service.STEP_PRICE,
|
||||
on_cancel=Service.NOTHING,
|
||||
|
@ -50,7 +50,7 @@ class BaseTrafficBillingTest(BaseBillingTest):
|
|||
return self.resource
|
||||
|
||||
def report_traffic(self, account, value):
|
||||
MonitorData.objects.create(monitor='FTPTraffic', content_object=account.user, value=value)
|
||||
MonitorData.objects.create(monitor='FTPTraffic', content_object=account.systemusers.get(), value=value)
|
||||
data = ResourceData.get_or_create(account, self.resource)
|
||||
data.update()
|
||||
|
||||
|
@ -90,7 +90,7 @@ class TrafficBillingTest(BaseTrafficBillingTest):
|
|||
|
||||
|
||||
class TrafficPrepayBillingTest(BaseTrafficBillingTest):
|
||||
METRIC = ("max("
|
||||
TRAFFIC_METRIC = ("max("
|
||||
"(account.resources.traffic.used or 0) - "
|
||||
"getattr(account.miscellaneous.filter(is_active=True, service__name='traffic prepay').last(), 'amount', 0)"
|
||||
", 0)"
|
||||
|
@ -126,8 +126,8 @@ class TrafficPrepayBillingTest(BaseTrafficBillingTest):
|
|||
def test_traffic_prepay(self):
|
||||
self.create_traffic_service()
|
||||
self.create_prepay_service()
|
||||
account = self.create_account()
|
||||
self.create_traffic_resource()
|
||||
account = self.create_account()
|
||||
now = timezone.now()
|
||||
|
||||
self.create_prepay(10, account=account)
|
||||
|
|
|
@ -5,8 +5,8 @@ from django.contrib.contenttypes.models import ContentType
|
|||
from django.utils import timezone
|
||||
|
||||
from orchestra.apps.accounts.models import Account
|
||||
from orchestra.apps.users.models import User
|
||||
from orchestra.utils.tests import BaseTestCase
|
||||
from orchestra.apps.systemusers.models import SystemUser
|
||||
from orchestra.utils.tests import BaseTestCase, random_ascii
|
||||
|
||||
from .. import helpers
|
||||
from ..models import Service, Plan
|
||||
|
@ -28,22 +28,14 @@ class Order(object):
|
|||
class HandlerTests(BaseTestCase):
|
||||
DEPENDENCIES = (
|
||||
'orchestra.apps.orders',
|
||||
'orchestra.apps.users',
|
||||
'orchestra.apps.users.roles.posix',
|
||||
'orchestra.apps.systemusers',
|
||||
)
|
||||
|
||||
def create_account(self):
|
||||
account = Account.objects.create()
|
||||
user = User.objects.create_user(username='rata_palida', account=account)
|
||||
account.user = user
|
||||
account.save()
|
||||
return account
|
||||
|
||||
def create_ftp_service(self):
|
||||
service = Service.objects.create(
|
||||
description="FTP Account",
|
||||
content_type=ContentType.objects.get_for_model(User),
|
||||
match='not user.is_main and user.has_posix()',
|
||||
content_type=ContentType.objects.get_for_model(SystemUser),
|
||||
match='not systemuser.is_main',
|
||||
billing_period=Service.ANUAL,
|
||||
billing_point=Service.FIXED_DATE,
|
||||
is_fee=False,
|
||||
|
|
|
@ -15,6 +15,7 @@ class SystemUserQuerySet(models.QuerySet):
|
|||
user = super(SystemUserQuerySet, self).create(username=username, **kwargs)
|
||||
user.set_password(password)
|
||||
user.save(update_fields=['password'])
|
||||
return user
|
||||
|
||||
|
||||
class SystemUser(models.Model):
|
||||
|
|
|
@ -2,6 +2,7 @@ from functools import partial
|
|||
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from selenium.webdriver.support.select import Select
|
||||
|
||||
from orchestra.apps.accounts.models import Account
|
||||
from orchestra.apps.orchestration.models import Server, Route
|
||||
|
@ -9,6 +10,7 @@ from orchestra.utils.system import run
|
|||
from orchestra.utils.tests import BaseLiveServerTestCase, random_ascii
|
||||
|
||||
from ... import backends
|
||||
from ...models import SystemUser
|
||||
|
||||
|
||||
r = partial(run, silent=True, display=False)
|
||||
|
@ -40,6 +42,9 @@ class SystemUserMixin(object):
|
|||
def update(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def disable(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def test_create_systemuser(self):
|
||||
username = '%s_systemuser' % random_ascii(10)
|
||||
password = '@!?%spppP001' % random_ascii(5)
|
||||
|
@ -55,7 +60,16 @@ class SystemUserMixin(object):
|
|||
self.assertEqual(0, r("id %s" % username).return_code)
|
||||
self.delete(username)
|
||||
self.assertEqual(1, r("id %s" % username, error_codes=[0,1]).return_code)
|
||||
|
||||
def test_update_systemuser(self):
|
||||
pass
|
||||
# TODO
|
||||
|
||||
def test_disable_systemuser(self):
|
||||
pass
|
||||
# TODO
|
||||
|
||||
# TODO test with ftp and ssh clients?
|
||||
|
||||
class RESTSystemUserMixin(SystemUserMixin):
|
||||
def setUp(self):
|
||||
|
@ -73,16 +87,38 @@ class RESTSystemUserMixin(SystemUserMixin):
|
|||
pass
|
||||
|
||||
|
||||
# TODO
|
||||
class AdminSystemUserMixin(SystemUserMixin):
|
||||
def setUp(self):
|
||||
super(AdminSystemUserMixin, self).setUp()
|
||||
self.admin_login()
|
||||
|
||||
def add(self, username, password):
|
||||
pass
|
||||
url = self.live_server_url + reverse('admin:systemusers_systemuser_add')
|
||||
self.selenium.get(url)
|
||||
|
||||
username_field = self.selenium.find_element_by_id('id_username')
|
||||
username_field.send_keys(username)
|
||||
|
||||
password_field = self.selenium.find_element_by_id('id_password1')
|
||||
password_field.send_keys(password)
|
||||
password_field = self.selenium.find_element_by_id('id_password2')
|
||||
password_field.send_keys(password)
|
||||
|
||||
account_input = self.selenium.find_element_by_id('id_account')
|
||||
account_select = Select(account_input)
|
||||
account_select.select_by_value(str(self.account.pk))
|
||||
|
||||
username_field.submit()
|
||||
self.assertNotEqual(url, self.selenium.current_url)
|
||||
|
||||
def delete(self, username):
|
||||
user = SystemUser.objects.get(username=username)
|
||||
url = self.live_server_url + reverse('admin:systemusers_systemuser_delete', args=(user.pk,))
|
||||
self.selenium.get(url)
|
||||
confirmation = self.selenium.find_element_by_name('post')
|
||||
confirmation.submit()
|
||||
|
||||
def disable(self, username):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
|
|
|
@ -12,6 +12,10 @@ from xvfbwrapper import Xvfb
|
|||
from orchestra.apps.accounts.models import Account
|
||||
|
||||
|
||||
def random_ascii(length):
|
||||
return ''.join([random.choice(string.hexdigits) for i in range(0, length)]).lower()
|
||||
|
||||
|
||||
class AppDependencyMixin(object):
|
||||
DEPENDENCIES = ()
|
||||
|
||||
|
@ -49,13 +53,15 @@ class AppDependencyMixin(object):
|
|||
|
||||
|
||||
class BaseTestCase(TestCase, AppDependencyMixin):
|
||||
pass
|
||||
def create_account(self, superuser=False):
|
||||
username = '%s_superaccount' % random_ascii(5)
|
||||
password = 'orchestra'
|
||||
if superuser:
|
||||
return Account.objects.create_superuser(username, password=password, email='orchestra@orchestra.org')
|
||||
return Account.objects.create_user(username, password=password, email='orchestra@orchestra.org')
|
||||
|
||||
|
||||
class BaseLiveServerTestCase(AppDependencyMixin, LiveServerTestCase):
|
||||
ACCOUNT_USERNAME = 'orchestra'
|
||||
ACCOUNT_PASSWORD = 'orchestra'
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.vdisplay = Xvfb()
|
||||
|
@ -70,11 +76,11 @@ class BaseLiveServerTestCase(AppDependencyMixin, LiveServerTestCase):
|
|||
super(BaseLiveServerTestCase, cls).tearDownClass()
|
||||
|
||||
def create_account(self, superuser=False):
|
||||
username = '%s_superaccount' % random_ascii(5)
|
||||
password = 'orchestra'
|
||||
if superuser:
|
||||
return Account.objects.create_superuser(self.ACCOUNT_USERNAME,
|
||||
password=self.ACCOUNT_PASSWORD, email='orchestra@orchestra.org')
|
||||
return Account.objects.create_user(self.ACCOUNT_USERNAME,
|
||||
password=self.ACCOUNT_PASSWORD, email='orchestra@orchestra.org')
|
||||
return Account.objects.create_superuser(username, password=password, email='orchestra@orchestra.org')
|
||||
return Account.objects.create_user(username, password=password, email='orchestra@orchestra.org')
|
||||
|
||||
def setUp(self):
|
||||
super(BaseLiveServerTestCase, self).setUp()
|
||||
|
@ -96,7 +102,3 @@ class BaseLiveServerTestCase(AppDependencyMixin, LiveServerTestCase):
|
|||
|
||||
def rest_login(self):
|
||||
self.rest.login(username=self.ACCOUNT_USERNAME, password=self.ACCOUNT_PASSWORD)
|
||||
|
||||
|
||||
def random_ascii(length):
|
||||
return ''.join([random.choice(string.hexdigits) for i in range(0, length)]).lower()
|
||||
|
|
Loading…
Reference in a new issue