refacter: 重构application

pull/4886/head
ibuler 2020-10-19 20:13:01 +08:00 committed by 老广
parent 874a3eeebf
commit ba4e6e9a9f
12 changed files with 292 additions and 9 deletions

View File

@ -1,3 +1,4 @@
from .application import *
from .remote_app import * from .remote_app import *
from .database_app import * from .database_app import *
from .k8s_app import * from .k8s_app import *

View File

@ -0,0 +1,20 @@
# coding: utf-8
#
from orgs.mixins.api import OrgBulkModelViewSet
from .. import models
from .. import serializers
from ..hands import IsOrgAdminOrAppUser
__all__ = [
'ApplicationViewSet',
]
class ApplicationViewSet(OrgBulkModelViewSet):
model = models.Application
filter_fields = ('name',)
search_fields = filter_fields
permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.ApplicationSerializer

View File

@ -0,0 +1,37 @@
# Generated by Django 2.2.13 on 2020-10-19 12:01
from django.db import migrations, models
import django.db.models.deletion
import django_mysql.models
import uuid
class Migration(migrations.Migration):
dependencies = [
('assets', '0057_fill_node_value_assets_amount_and_parent_key'),
('applications', '0005_k8sapp'),
]
operations = [
migrations.CreateModel(
name='Application',
fields=[
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('name', models.CharField(max_length=128, verbose_name='Name')),
('category', models.CharField(choices=[('db', 'Database'), ('remote_app', 'Remote app'), ('cloud', 'Cloud')], max_length=16, verbose_name='Category')),
('type', models.CharField(choices=[('mysql', 'MySQL'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type')),
('attrs', django_mysql.models.JSONField(default=dict)),
('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')),
('domain', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.Domain')),
],
options={
'ordering': ('name',),
'unique_together': {('org_id', 'name')},
},
),
]

View File

@ -1,3 +1,4 @@
from .application import *
from .remote_app import * from .remote_app import *
from .database_app import * from .database_app import *
from .k8s_app import * from .k8s_app import *

View File

@ -0,0 +1,115 @@
from itertools import chain
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django_mysql.models import JSONField, QuerySet
from orgs.mixins.models import OrgModelMixin
from common.mixins import CommonModelMixin
from common.db.models import ChoiceSet
class DBType(ChoiceSet):
mysql = 'mysql', 'MySQL'
oracle = 'oracle', 'Oracle'
pgsql = 'postgresql', 'PostgreSQL'
mariadb = 'mariadb', 'MariaDB'
@classmethod
def get_type_serializer_cls_mapper(cls):
from ..serializers import database_app
mapper = {
cls.mysql: database_app.MySQLAttrsSerializer,
cls.oracle: database_app.OracleAttrsSerializer,
cls.pgsql: database_app.PostgreAttrsSerializer,
cls.mariadb: database_app.MariaDBAttrsSerializer,
}
return mapper
class RemoteAppType(ChoiceSet):
chrome = 'chrome', 'Chrome'
mysql_workbench = 'mysql_workbench', 'MySQL Workbench'
vmware_client = 'vmware_client', 'vSphere Client'
custom = 'custom', _('Custom')
@classmethod
def get_type_serializer_cls_mapper(cls):
from ..serializers import remote_app
mapper = {
cls.chrome: remote_app.ChromeAttrsSerializer,
cls.mysql_workbench: remote_app.MySQLWorkbenchAttrsSerializer,
cls.vmware_client: remote_app.VMwareClientAttrsSerializer,
cls.custom: remote_app.CustomRemoteAppAttrsSeralizers,
}
return mapper
class CloudType(ChoiceSet):
k8s = 'k8s', 'Kubernetes'
@classmethod
def get_type_serializer_cls_mapper(cls):
from ..serializers import k8s_app
mapper = {
cls.k8s: k8s_app.K8sAttrsSerializer,
}
return mapper
class Category(ChoiceSet):
db = 'db', _('Database')
remote_app = 'remote_app', _('Remote app')
cloud = 'cloud', 'Cloud'
@classmethod
def get_category_type_mapper(cls):
return {
cls.db: DBType,
cls.remote_app: RemoteAppType,
cls.cloud: CloudType
}
@classmethod
def get_category_type_choices_mapper(cls):
return {
name: tp.choices
for name, tp in cls.get_category_type_mapper().items()
}
@classmethod
def get_type_choices(cls, category):
return cls.get_category_type_choices_mapper().get(category, [])
@classmethod
def get_all_type_choices(cls):
all_grouped_choices = tuple(cls.get_category_type_choices_mapper().values())
return tuple(chain(*all_grouped_choices))
@classmethod
def get_all_type_serializer_mapper(cls):
mapper = {}
for tp in cls.get_category_type_mapper().values():
mapper.update(tp.get_type_serializer_cls_mapper())
return mapper
@classmethod
def get_type_serializer_cls(cls, tp):
mapper = cls.get_all_type_serializer_mapper()
return mapper.get(tp, None)
class Application(CommonModelMixin, OrgModelMixin):
name = models.CharField(max_length=128, verbose_name=_('Name'))
domain = models.ForeignKey('assets.Domain', on_delete=models.SET_NULL, null=True)
category = models.CharField(max_length=16, choices=Category.choices, verbose_name=_('Category'))
type = models.CharField(max_length=16, choices=Category.get_all_type_choices(), verbose_name=_('Type'))
attrs = JSONField()
comment = models.TextField(
max_length=128, default='', blank=True, verbose_name=_('Comment')
)
objects = QuerySet.as_manager()
class Meta:
unique_together = [('org_id', 'name')]
ordering = ('name',)

View File

@ -1,3 +1,4 @@
from .application import *
from .remote_app import * from .remote_app import *
from .database_app import * from .database_app import *
from .k8s_app import * from .k8s_app import *

View File

@ -0,0 +1,46 @@
# coding: utf-8
#
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from .. import models
__all__ = [
'ApplicationSerializer',
]
class ApplicationSerializer(BulkOrgResourceModelSerializer):
class Meta:
model = models.Application
fields = [
'id', 'name', 'category', 'type', 'get_type_display', 'attrs',
'created_by', 'date_created', 'date_updated', 'comment'
]
read_only_fields = [
'created_by', 'date_created', 'date_updated', 'get_type_display',
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
app_type = ''
attrs_data = {}
if self.instance:
app_type = self.instance.type
attrs_data = self.instance.attrs
request = self.context.get('request')
if request:
app_type = request.query_params.get('type')
if hasattr(self, 'initial_data'):
app_type = self.initial_data.get('type')
attrs_data = self.initial_data.get('attrs')
if not app_type:
return
attrs_cls = models.Category.get_type_serializer_cls(app_type)
if attrs_data:
attrs_serializer = attrs_cls(data=attrs_data)
else:
attrs_serializer = attrs_cls()
self.fields['attrs'] = attrs_serializer

View File

@ -1,14 +1,34 @@
# coding: utf-8 # coding: utf-8
# #
from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _
from orgs.mixins.serializers import BulkOrgResourceModelSerializer from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from common.serializers import AdaptedBulkListSerializer from common.serializers import AdaptedBulkListSerializer
from .. import models from .. import models
__all__ = [
'DatabaseAppSerializer', class DatabaseAttrsSerializer(serializers.Serializer):
] host = serializers.CharField()
port = serializers.IntegerField()
database = serializers.CharField(allow_blank=True, allow_null=True)
class MySQLAttrsSerializer(DatabaseAttrsSerializer):
port = serializers.IntegerField(default=3306, label=_('Port'))
class PostgreAttrsSerializer(DatabaseAttrsSerializer):
port = serializers.IntegerField(default=5432)
class OracleAttrsSerializer(DatabaseAttrsSerializer):
port = serializers.IntegerField(default=1521)
class MariaDBAttrsSerializer(MySQLAttrsSerializer):
pass
class DatabaseAppSerializer(BulkOrgResourceModelSerializer): class DatabaseAppSerializer(BulkOrgResourceModelSerializer):

View File

@ -1,11 +1,12 @@
from rest_framework import serializers from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _
from orgs.mixins.serializers import BulkOrgResourceModelSerializer from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from .. import models from .. import models
__all__ = [
'K8sAppSerializer', class K8sAttrsSerializer(serializers.Serializer):
] cluster = serializers.CharField(label=_('Cluster'))
class K8sAppSerializer(BulkOrgResourceModelSerializer): class K8sAppSerializer(BulkOrgResourceModelSerializer):

View File

@ -2,19 +2,54 @@
# #
import copy import copy
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers from rest_framework import serializers
from common.serializers import AdaptedBulkListSerializer from common.serializers import AdaptedBulkListSerializer
from common.fields.serializer import CustomMetaDictField from common.fields.serializer import CustomMetaDictField
from orgs.mixins.serializers import BulkOrgResourceModelSerializer from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from assets.models import Asset
from .. import const from .. import const
from ..models import RemoteApp from ..models import RemoteApp
__all__ = [ class RemoteAppAttrsSerializer(serializers.Serializer):
'RemoteAppSerializer', 'RemoteAppConnectionInfoSerializer', asset = serializers.PrimaryKeyRelatedField(queryset=Asset.objects, label=_("Assets"))
] path = serializers.CharField(label=_('Remote App path'))
class ChromeAttrsSerializer(RemoteAppAttrsSerializer):
REMOTE_APP_PATH = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
path = serializers.CharField(label=_('Remote App path'), default=REMOTE_APP_PATH)
chrome_target = serializers.CharField(label=_('Target URL'))
chrome_username = serializers.CharField(label=_('Username'))
chrome_password = serializers.CharField(write_only=True, label=_('Password'))
class MySQLWorkbenchAttrsSerializer(RemoteAppAttrsSerializer):
REMOTE_APP_PATH = 'C:\Program Files\MySQL\MySQL Workbench 8.0 CE\MySQLWorkbench.exe'
path = serializers.CharField(label=_('Remote App path'), default=REMOTE_APP_PATH)
mysql_workbench_ip = serializers.CharField(label=_('IP'))
mysql_workbench_port = serializers.IntegerField(label=_('Port'))
mysql_workbench_name = serializers.CharField(label=_('Database'))
mysql_workbench_username = serializers.CharField(label=_('Username'))
mysql_workbench_password = serializers.CharField(write_only=True, label=_('Password'))
class VMwareClientAttrsSerializer(RemoteAppAttrsSerializer):
REMOTE_APP_PATH = 'C:\Program Files (x86)\VMware\Infrastructure\Virtual Infrastructure Client\Launcher\VpxClient.exe'
path = serializers.CharField(label=_('Remote App path'), default=REMOTE_APP_PATH)
vmware_target = serializers.CharField(label=_('Target URL'))
vmware_username = serializers.CharField(label=_('Username'))
vmware_password = serializers.CharField(write_only=True, label=_('Password'))
class CustomRemoteAppAttrsSeralizers(RemoteAppAttrsSerializer):
custom_cmdline = serializers.CharField(label=_('Operating parameter'))
custom_target = serializers.CharField(label=_('Target url'))
custom_username = serializers.CharField(label=_('Username'))
custom_password = serializers.CharField(write_only=True, label=_('Password'))
class RemoteAppParamsDictField(CustomMetaDictField): class RemoteAppParamsDictField(CustomMetaDictField):

View File

@ -10,6 +10,7 @@ from .. import api
app_name = 'applications' app_name = 'applications'
router = BulkRouter() router = BulkRouter()
router.register(r'applications', api.ApplicationViewSet, 'application')
router.register(r'remote-apps', api.RemoteAppViewSet, 'remote-app') router.register(r'remote-apps', api.RemoteAppViewSet, 'remote-app')
router.register(r'database-apps', api.DatabaseAppViewSet, 'database-app') router.register(r'database-apps', api.DatabaseAppViewSet, 'database-app')
router.register(r'k8s-apps', api.K8sAppViewSet, 'k8s-app') router.register(r'k8s-apps', api.K8sAppViewSet, 'k8s-app')

View File

@ -7,6 +7,7 @@ from collections import OrderedDict
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.http import Http404 from django.http import Http404
from django.utils.encoding import force_text from django.utils.encoding import force_text
from rest_framework.fields import empty
from rest_framework.metadata import SimpleMetadata from rest_framework.metadata import SimpleMetadata
from rest_framework import exceptions, serializers from rest_framework import exceptions, serializers
@ -58,6 +59,10 @@ class SimpleMetadataWithFilters(SimpleMetadata):
field_info['type'] = self.label_lookup[field] field_info['type'] = self.label_lookup[field]
field_info['required'] = getattr(field, 'required', False) field_info['required'] = getattr(field, 'required', False)
default = getattr(field, 'default', False)
if default and isinstance(default, (str, int)):
field_info['default'] = default
for attr in self.attrs: for attr in self.attrs:
value = getattr(field, attr, None) value = getattr(field, attr, None)
if value is not None and value != '': if value is not None and value != '':