From 65331e13aca87deece7484bbbd0e23569fff2f32 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 19 Sep 2022 00:07:59 +0800 Subject: [PATCH] =?UTF-8?q?pref:=20=E4=BC=98=E5=8C=96=E5=B9=B3=E5=8F=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/const.py | 317 ---------------------------------- apps/assets/const/__init__.py | 3 + apps/assets/const/base.py | 30 ++++ apps/assets/const/category.py | 23 +++ apps/assets/const/cloud.py | 31 ++++ apps/assets/const/database.py | 36 ++++ apps/assets/const/device.py | 30 ++++ apps/assets/const/host.py | 40 +++++ apps/assets/const/protocol.py | 59 +++++++ apps/assets/const/types.py | 93 ++++++++++ apps/assets/const/web.py | 16 ++ 11 files changed, 361 insertions(+), 317 deletions(-) delete mode 100644 apps/assets/const.py create mode 100644 apps/assets/const/__init__.py create mode 100644 apps/assets/const/base.py create mode 100644 apps/assets/const/category.py create mode 100644 apps/assets/const/cloud.py create mode 100644 apps/assets/const/database.py create mode 100644 apps/assets/const/device.py create mode 100644 apps/assets/const/host.py create mode 100644 apps/assets/const/protocol.py create mode 100644 apps/assets/const/types.py create mode 100644 apps/assets/const/web.py diff --git a/apps/assets/const.py b/apps/assets/const.py deleted file mode 100644 index 9c5603052..000000000 --- a/apps/assets/const.py +++ /dev/null @@ -1,317 +0,0 @@ -from django.db import models -from django.utils.translation import gettext_lazy as _ - -from common.db.models import IncludesTextChoicesMeta, ChoicesMixin -from common.tree import TreeNode - - -__all__ = [ - 'Category', 'HostTypes', 'DeviceTypes', 'DatabaseTypes', - 'WebTypes', 'CloudTypes', 'Protocol', 'AllTypes', -] - - -class PlatformMixin: - @classmethod - def platform_constraints(cls): - return { - 'domain_enabled': False, - 'su_enabled': False, - 'brand_enabled': False, - 'ping_enabled': False, - 'gather_facts_enabled': False, - 'change_password_enabled': False, - 'verify_account_enabled': False, - 'create_account_enabled': False, - 'gather_accounts_enabled': False, - '_protocols': [] - } - - -class Category(PlatformMixin, ChoicesMixin, models.TextChoices): - HOST = 'host', _('Host') - DEVICE = 'device', _("Device") - DATABASE = 'database', _("Database") - CLOUD = 'cloud', _("Cloud service") - WEB = 'web', _("Web") - - @classmethod - def platform_constraints(cls) -> dict: - return { - cls.HOST: { - 'domain_enabled': True, - 'su_enabled': True, 'su_method': 'sudo', - 'ping_enabled': True, 'ping_method': 'ping', - 'gather_facts_enabled': True, 'gather_facts_method': 'gather_facts_posix', - 'verify_account_enabled': True, 'verify_account_method': 'verify_account_posix', - 'change_password_enabled': True, 'change_password_method': 'change_password_posix', - 'create_account_enabled': True, 'create_account_method': 'create_account_posix', - 'gather_accounts_enabled': True, 'gather_accounts_method': 'gather_accounts_posix', - '_protocols': ['ssh', 'telnet'], - }, - cls.DEVICE: { - 'domain_enabled': True, - 'brand_enabled': True, - 'brands': [ - ('huawei', 'Huawei'), - ('cisco', 'Cisco'), - ('juniper', 'Juniper'), - ('h3c', 'H3C'), - ('dell', 'Dell'), - ('other', 'Other'), - ], - 'su_enabled': False, - 'ping_enabled': True, 'ping_method': 'ping', - 'gather_facts_enabled': False, - 'verify_account_enabled': False, - 'change_password_enabled': False, - 'create_account_enabled': False, - 'gather_accounts_enabled': False, - '_protocols': ['ssh', 'telnet'] - }, - cls.DATABASE: { - 'domain_enabled': True, - 'su_enabled': False, - 'gather_facts_enabled': True, - 'verify_account_enabled': True, - 'change_password_enabled': True, - 'create_account_enabled': True, - 'gather_accounts_enabled': True, - '_protocols': [] - }, - cls.WEB: { - 'domain_enabled': False, - 'su_enabled': False, - 'ping_enabled': False, - 'gather_facts_enabled': False, - 'verify_account_enabled': False, - 'change_password_enabled': False, - 'create_account_enabled': False, - 'gather_accounts_enabled': False, - '_protocols': ['http', 'https'] - }, - cls.CLOUD: { - 'domain_enabled': False, - 'su_enabled': False, - 'ping_enabled': False, - 'gather_facts_enabled': False, - 'verify_account_enabled': False, - 'change_password_enabled': False, - 'create_account_enabled': False, - 'gather_accounts_enabled': False, - '_protocols': [] - } - } - - -class HostTypes(PlatformMixin, ChoicesMixin, models.TextChoices): - LINUX = 'linux', 'Linux' - WINDOWS = 'windows', 'Windows' - UNIX = 'unix', 'Unix' - OTHER_HOST = 'other', _("Other") - - @classmethod - def platform_constraints(cls): - return { - cls.LINUX: { - '_protocols': ['ssh', 'rdp', 'vnc', 'telnet'] - }, - cls.WINDOWS: { - 'gather_facts_method': 'gather_facts_windows', - 'verify_account_method': 'verify_account_windows', - 'change_password_method': 'change_password_windows', - 'create_account_method': 'create_account_windows', - 'gather_accounts_method': 'gather_accounts_windows', - '_protocols': ['rdp', 'ssh', 'vnc'], - 'su_enabled': False - }, - cls.UNIX: { - '_protocols': ['ssh', 'vnc'] - } - } - - -class DeviceTypes(PlatformMixin, ChoicesMixin, models.TextChoices): - GENERAL = 'general', _("General device") - SWITCH = 'switch', _("Switch") - ROUTER = 'router', _("Router") - FIREWALL = 'firewall', _("Firewall") - - -class DatabaseTypes(PlatformMixin, ChoicesMixin, models.TextChoices): - MYSQL = 'mysql', 'MySQL' - MARIADB = 'mariadb', 'MariaDB' - POSTGRESQL = 'postgresql', 'PostgreSQL' - ORACLE = 'oracle', 'Oracle' - SQLSERVER = 'sqlserver', 'SQLServer' - MONGODB = 'mongodb', 'MongoDB' - REDIS = 'redis', 'Redis' - - @classmethod - def platform_constraints(cls): - meta = {} - for name, label in cls.choices: - meta[name] = { - '_protocols': [name], - 'gather_facts_method': f'gather_facts_{name}', - 'verify_account_method': f'verify_account_{name}', - 'change_password_method': f'change_password_{name}', - 'create_account_method': f'create_account_{name}', - 'gather_accounts_method': f'gather_accounts_{name}', - } - return meta - - -class WebTypes(PlatformMixin, ChoicesMixin, models.TextChoices): - WEBSITE = 'website', _('General website') - - -class CloudTypes(PlatformMixin, ChoicesMixin, models.TextChoices): - K8S = 'k8s', 'Kubernetes' - - @classmethod - def platform_constraints(cls): - return { - cls.K8S: { - '_protocols': ['k8s'] - } - } - - -class AllTypes(ChoicesMixin, metaclass=IncludesTextChoicesMeta): - choices: list - includes = [ - HostTypes, DeviceTypes, DatabaseTypes, - WebTypes, CloudTypes - ] - - @classmethod - def get_constraints(cls, category, tp): - constraints = PlatformMixin.platform_constraints() - category_constraints = Category.platform_constraints().get(category) or {} - constraints.update(category_constraints) - - types_cls = dict(cls.category_types()).get(category) - if not types_cls: - return constraints - type_constraints = types_cls.platform_constraints().get(tp) or {} - constraints.update(type_constraints) - - _protocols = constraints.pop('_protocols', []) - default_ports = Protocol.default_ports() - protocols = [] - for p in _protocols: - port = default_ports.get(p, 0) - protocols.append({'name': p, 'port': port}) - constraints['protocols'] = protocols - return constraints - - @classmethod - def category_types(cls): - return ( - (Category.HOST, HostTypes), - (Category.DEVICE, DeviceTypes), - (Category.DATABASE, DatabaseTypes), - (Category.WEB, WebTypes), - (Category.CLOUD, CloudTypes) - ) - - @classmethod - def grouped_choices(cls): - grouped_types = [(str(ca), tp.choices) for ca, tp in cls.category_types()] - return grouped_types - - @classmethod - def grouped_choices_to_objs(cls): - choices = cls.serialize_to_objs(Category.choices) - mapper = dict(cls.grouped_choices()) - for choice in choices: - children = cls.serialize_to_objs(mapper[choice['value']]) - choice['children'] = children - return choices - - @staticmethod - def serialize_to_objs(choices): - title = ['value', 'display_name'] - return [dict(zip(title, choice)) for choice in choices] - - @staticmethod - def choice_to_node(choice, pid, opened=True, is_parent=True, meta=None): - node = TreeNode(**{ - 'id': choice.name, - 'name': choice.label, - 'title': choice.label, - 'pId': pid, - 'open': opened, - 'isParent': is_parent, - }) - if meta: - node.meta = meta - return node - - @classmethod - def to_tree_nodes(cls): - root = TreeNode(id='ROOT', name='类型节点', title='类型节点') - nodes = [root] - for category, types in cls.category_types(): - category_node = cls.choice_to_node(category, 'ROOT', meta={'type': 'category'}) - nodes.append(category_node) - for tp in types: - tp_node = cls.choice_to_node(tp, category_node.id, meta={'type': 'type'}) - nodes.append(tp_node) - return nodes - - -class Protocol(ChoicesMixin, models.TextChoices): - ssh = 'ssh', 'SSH' - sftp = 'sftp', 'SFTP' - rdp = 'rdp', 'RDP' - telnet = 'telnet', 'Telnet' - vnc = 'vnc', 'VNC' - - mysql = 'mysql', 'MySQL' - mariadb = 'mariadb', 'MariaDB' - oracle = 'oracle', 'Oracle' - postgresql = 'postgresql', 'PostgreSQL' - sqlserver = 'sqlserver', 'SQLServer' - redis = 'redis', 'Redis' - mongodb = 'mongodb', 'MongoDB' - - k8s = 'k8s', 'K8S' - http = 'http', 'HTTP' - https = 'https', 'HTTPS' - - @classmethod - def host_protocols(cls): - return [cls.ssh, cls.rdp, cls.telnet, cls.vnc] - - @classmethod - def db_protocols(cls): - return [ - cls.mysql, cls.mariadb, cls.postgresql, cls.oracle, - cls.sqlserver, cls.redis, cls.mongodb, - ] - - @classmethod - def default_ports(cls): - return { - cls.ssh: 22, - cls.sftp: 22, - cls.rdp: 3389, - cls.vnc: 5900, - cls.telnet: 21, - - cls.mysql: 3306, - cls.mariadb: 3306, - cls.postgresql: 5432, - cls.oracle: 1521, - cls.sqlserver: 1433, - cls.mongodb: 27017, - cls.redis: 6379, - - cls.k8s: 0, - - cls.http: 80, - cls.https: 443 - } - diff --git a/apps/assets/const/__init__.py b/apps/assets/const/__init__.py new file mode 100644 index 000000000..e3e822fb3 --- /dev/null +++ b/apps/assets/const/__init__.py @@ -0,0 +1,3 @@ +from .protocol import * +from .category import * +from .types import * diff --git a/apps/assets/const/base.py b/apps/assets/const/base.py new file mode 100644 index 000000000..cb1419636 --- /dev/null +++ b/apps/assets/const/base.py @@ -0,0 +1,30 @@ + + +class ConstrainMixin: + def get_constrains(self): + pass + + def _get_category_constrains(self) -> dict: + raise NotImplementedError + + def _get_protocol_constrains(self) -> dict: + raise NotImplementedError + + def _get_automation_constrains(self) -> dict: + raise NotImplementedError + + @classmethod + def platform_constraints(cls): + return { + 'domain_enabled': False, + 'su_enabled': False, + 'brand_enabled': False, + 'ping_enabled': False, + 'gather_facts_enabled': False, + 'change_password_enabled': False, + 'verify_account_enabled': False, + 'create_account_enabled': False, + 'gather_accounts_enabled': False, + '_protocols': [] + } + diff --git a/apps/assets/const/category.py b/apps/assets/const/category.py new file mode 100644 index 000000000..db3c96ebc --- /dev/null +++ b/apps/assets/const/category.py @@ -0,0 +1,23 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from common.db.models import IncludesTextChoicesMeta, ChoicesMixin + + + +__all__ = [ + 'Category', 'ConstrainMixin' +] + + + +class Category(ConstrainMixin, ChoicesMixin, models.TextChoices): + HOST = 'host', _('Host') + DEVICE = 'device', _("Device") + DATABASE = 'database', _("Database") + CLOUD = 'cloud', _("Cloud service") + WEB = 'web', _("Web") + + + + diff --git a/apps/assets/const/cloud.py b/apps/assets/const/cloud.py new file mode 100644 index 000000000..95e0be171 --- /dev/null +++ b/apps/assets/const/cloud.py @@ -0,0 +1,31 @@ +from django.db import models + +from common.db.models import ChoicesMixin + + +from .category import ConstrainMixin + + +class CloudTypes(ConstrainMixin, ChoicesMixin, models.TextChoices): + K8S = 'k8s', 'Kubernetes' + + def category_constrains(self): + return { + 'domain_enabled': False, + 'su_enabled': False, + 'ping_enabled': False, + 'gather_facts_enabled': False, + 'verify_account_enabled': False, + 'change_password_enabled': False, + 'create_account_enabled': False, + 'gather_accounts_enabled': False, + '_protocols': [] + } + + @classmethod + def platform_constraints(cls): + return { + cls.K8S: { + '_protocols': ['k8s'] + } + } diff --git a/apps/assets/const/database.py b/apps/assets/const/database.py new file mode 100644 index 000000000..a80b89529 --- /dev/null +++ b/apps/assets/const/database.py @@ -0,0 +1,36 @@ + + +class DatabaseTypes(ConstrainMixin, ChoicesMixin, models.TextChoices): + MYSQL = 'mysql', 'MySQL' + MARIADB = 'mariadb', 'MariaDB' + POSTGRESQL = 'postgresql', 'PostgreSQL' + ORACLE = 'oracle', 'Oracle' + SQLSERVER = 'sqlserver', 'SQLServer' + MONGODB = 'mongodb', 'MongoDB' + REDIS = 'redis', 'Redis' + + def category_constrains(self): + return { + 'domain_enabled': True, + 'su_enabled': False, + 'gather_facts_enabled': True, + 'verify_account_enabled': True, + 'change_password_enabled': True, + 'create_account_enabled': True, + 'gather_accounts_enabled': True, + '_protocols': [] + } + + @classmethod + def platform_constraints(cls): + meta = {} + for name, label in cls.choices: + meta[name] = { + '_protocols': [name], + 'gather_facts_method': f'gather_facts_{name}', + 'verify_account_method': f'verify_account_{name}', + 'change_password_method': f'change_password_{name}', + 'create_account_method': f'create_account_{name}', + 'gather_accounts_method': f'gather_accounts_{name}', + } + return meta diff --git a/apps/assets/const/device.py b/apps/assets/const/device.py new file mode 100644 index 000000000..488806b3d --- /dev/null +++ b/apps/assets/const/device.py @@ -0,0 +1,30 @@ + + +class DeviceTypes(ConstrainMixin, ChoicesMixin, models.TextChoices): + GENERAL = 'general', _("General device") + SWITCH = 'switch', _("Switch") + ROUTER = 'router', _("Router") + FIREWALL = 'firewall', _("Firewall") + + @classmethod + def category_constrains(cls): + return { + 'domain_enabled': True, + 'brand_enabled': True, + 'brands': [ + ('huawei', 'Huawei'), + ('cisco', 'Cisco'), + ('juniper', 'Juniper'), + ('h3c', 'H3C'), + ('dell', 'Dell'), + ('other', 'Other'), + ], + 'su_enabled': False, + 'ping_enabled': True, 'ping_method': 'ping', + 'gather_facts_enabled': False, + 'verify_account_enabled': False, + 'change_password_enabled': False, + 'create_account_enabled': False, + 'gather_accounts_enabled': False, + '_protocols': ['ssh', 'telnet'] + } diff --git a/apps/assets/const/host.py b/apps/assets/const/host.py new file mode 100644 index 000000000..1ffc0e728 --- /dev/null +++ b/apps/assets/const/host.py @@ -0,0 +1,40 @@ + +class HostTypes(ConstrainMixin, ChoicesMixin, models.TextChoices): + LINUX = 'linux', 'Linux' + WINDOWS = 'windows', 'Windows' + UNIX = 'unix', 'Unix' + OTHER_HOST = 'other', _("Other") + + @staticmethod + def category_constrains(): + return { + 'domain_enabled': True, + 'su_enabled': True, 'su_method': 'sudo', + 'ping_enabled': True, 'ping_method': 'ping', + 'gather_facts_enabled': True, 'gather_facts_method': 'gather_facts_posix', + 'verify_account_enabled': True, 'verify_account_method': 'verify_account_posix', + 'change_password_enabled': True, 'change_password_method': 'change_password_posix', + 'create_account_enabled': True, 'create_account_method': 'create_account_posix', + 'gather_accounts_enabled': True, 'gather_accounts_method': 'gather_accounts_posix', + '_protocols': ['ssh', 'telnet'], + } + + @classmethod + def platform_constraints(cls): + return { + cls.LINUX: { + '_protocols': ['ssh', 'rdp', 'vnc', 'telnet'] + }, + cls.WINDOWS: { + 'gather_facts_method': 'gather_facts_windows', + 'verify_account_method': 'verify_account_windows', + 'change_password_method': 'change_password_windows', + 'create_account_method': 'create_account_windows', + 'gather_accounts_method': 'gather_accounts_windows', + '_protocols': ['rdp', 'ssh', 'vnc'], + 'su_enabled': False + }, + cls.UNIX: { + '_protocols': ['ssh', 'vnc'] + } + } \ No newline at end of file diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py new file mode 100644 index 000000000..7b283428b --- /dev/null +++ b/apps/assets/const/protocol.py @@ -0,0 +1,59 @@ +from django.db import models +from common.db.models import ChoicesMixin + +__all__ = ['Protocol'] + + +class Protocol(ChoicesMixin, models.TextChoices): + ssh = 'ssh', 'SSH' + sftp = 'sftp', 'SFTP' + rdp = 'rdp', 'RDP' + telnet = 'telnet', 'Telnet' + vnc = 'vnc', 'VNC' + + mysql = 'mysql', 'MySQL' + mariadb = 'mariadb', 'MariaDB' + oracle = 'oracle', 'Oracle' + postgresql = 'postgresql', 'PostgreSQL' + sqlserver = 'sqlserver', 'SQLServer' + redis = 'redis', 'Redis' + mongodb = 'mongodb', 'MongoDB' + + k8s = 'k8s', 'K8S' + http = 'http', 'HTTP' + https = 'https', 'HTTPS' + + @classmethod + def host_protocols(cls): + return [cls.ssh, cls.rdp, cls.telnet, cls.vnc] + + @classmethod + def db_protocols(cls): + return [ + cls.mysql, cls.mariadb, cls.postgresql, cls.oracle, + cls.sqlserver, cls.redis, cls.mongodb, + ] + + @classmethod + def default_ports(cls): + return { + cls.ssh: 22, + cls.sftp: 22, + cls.rdp: 3389, + cls.vnc: 5900, + cls.telnet: 21, + + cls.mysql: 3306, + cls.mariadb: 3306, + cls.postgresql: 5432, + cls.oracle: 1521, + cls.sqlserver: 1433, + cls.mongodb: 27017, + cls.redis: 6379, + + cls.k8s: 0, + + cls.http: 80, + cls.https: 443 + } + diff --git a/apps/assets/const/types.py b/apps/assets/const/types.py new file mode 100644 index 000000000..e19a7c28d --- /dev/null +++ b/apps/assets/const/types.py @@ -0,0 +1,93 @@ +from common.db.models import IncludesTextChoicesMeta, ChoicesMixin +from common.tree import TreeNode + +from .category import Category +from .host import HostTypes +from .device import DeviceTypes +from .database import DatabaseTypes +from .web import WebTypes +from .cloud import CloudTypes + + +class AllTypes(ChoicesMixin, metaclass=IncludesTextChoicesMeta): + choices: list + includes = [ + HostTypes, DeviceTypes, DatabaseTypes, + WebTypes, CloudTypes + ] + + @classmethod + def get_constraints(cls, category, tp): + constraints = ConstrainMixin.platform_constraints() + category_constraints = Category.platform_constraints().get(category) or {} + constraints.update(category_constraints) + + types_cls = dict(cls.category_types()).get(category) + if not types_cls: + return constraints + type_constraints = types_cls.platform_constraints().get(tp) or {} + constraints.update(type_constraints) + + _protocols = constraints.pop('_protocols', []) + default_ports = Protocol.default_ports() + protocols = [] + for p in _protocols: + port = default_ports.get(p, 0) + protocols.append({'name': p, 'port': port}) + constraints['protocols'] = protocols + return constraints + + @classmethod + def category_types(cls): + return ( + (Category.HOST, HostTypes), + (Category.DEVICE, DeviceTypes), + (Category.DATABASE, DatabaseTypes), + (Category.WEB, WebTypes), + (Category.CLOUD, CloudTypes) + ) + + @classmethod + def grouped_choices(cls): + grouped_types = [(str(ca), tp.choices) for ca, tp in cls.category_types()] + return grouped_types + + @classmethod + def grouped_choices_to_objs(cls): + choices = cls.serialize_to_objs(Category.choices) + mapper = dict(cls.grouped_choices()) + for choice in choices: + children = cls.serialize_to_objs(mapper[choice['value']]) + choice['children'] = children + return choices + + @staticmethod + def serialize_to_objs(choices): + title = ['value', 'display_name'] + return [dict(zip(title, choice)) for choice in choices] + + @staticmethod + def choice_to_node(choice, pid, opened=True, is_parent=True, meta=None): + node = TreeNode(**{ + 'id': choice.name, + 'name': choice.label, + 'title': choice.label, + 'pId': pid, + 'open': opened, + 'isParent': is_parent, + }) + if meta: + node.meta = meta + return node + + @classmethod + def to_tree_nodes(cls): + root = TreeNode(id='ROOT', name='类型节点', title='类型节点') + nodes = [root] + for category, types in cls.category_types(): + category_node = cls.choice_to_node(category, 'ROOT', meta={'type': 'category'}) + nodes.append(category_node) + for tp in types: + tp_node = cls.choice_to_node(tp, category_node.id, meta={'type': 'type'}) + nodes.append(tp_node) + return nodes diff --git a/apps/assets/const/web.py b/apps/assets/const/web.py new file mode 100644 index 000000000..f9bcffef4 --- /dev/null +++ b/apps/assets/const/web.py @@ -0,0 +1,16 @@ + +class WebTypes(ConstrainMixin, ChoicesMixin, models.TextChoices): + WEBSITE = 'website', _('General website') + + def category_constrains(self): + return { + 'domain_enabled': False, + 'su_enabled': False, + 'ping_enabled': False, + 'gather_facts_enabled': False, + 'verify_account_enabled': False, + 'change_password_enabled': False, + 'create_account_enabled': False, + 'gather_accounts_enabled': False, + '_protocols': ['http', 'https'] + } \ No newline at end of file