diff --git a/apps/assets/api/__init__.py b/apps/assets/api/__init__.py index 5dba09522..c14d8999f 100644 --- a/apps/assets/api/__init__.py +++ b/apps/assets/api/__init__.py @@ -1,4 +1,5 @@ from .mixin import * +from .category import * from .platform import * from .asset import * from .label import * diff --git a/apps/assets/api/category.py b/apps/assets/api/category.py index e69de29bb..cfcfd8c3c 100644 --- a/apps/assets/api/category.py +++ b/apps/assets/api/category.py @@ -0,0 +1,22 @@ +from rest_framework.generics import ListAPIView + +from assets.serializers import CategorySerializer, TypeSerializer +from assets.const import AllTypes + +__all__ = ['CategoryListApi', 'TypeListApi'] + + +class CategoryListApi(ListAPIView): + serializer_class = CategorySerializer + permission_classes = () + + def get_queryset(self): + return AllTypes.categories() + + +class TypeListApi(ListAPIView): + serializer_class = TypeSerializer + permission_classes = () + + def get_queryset(self): + return AllTypes.types() diff --git a/apps/assets/const/types.py b/apps/assets/const/types.py index ebee189aa..b98e208c3 100644 --- a/apps/assets/const/types.py +++ b/apps/assets/const/types.py @@ -1,14 +1,12 @@ from common.db.models import IncludesTextChoicesMeta, ChoicesMixin from common.tree import TreeNode -from .base import BaseType from .category import Category from .host import HostTypes from .device import DeviceTypes from .database import DatabaseTypes from .web import WebTypes from .cloud import CloudTypes -from .protocol import Protocol class AllTypes(ChoicesMixin, metaclass=IncludesTextChoicesMeta): @@ -17,6 +15,7 @@ class AllTypes(ChoicesMixin, metaclass=IncludesTextChoicesMeta): HostTypes, DeviceTypes, DatabaseTypes, WebTypes, CloudTypes ] + _category_constrains = {} @classmethod def get_constraints(cls, category, tp): @@ -24,7 +23,54 @@ class AllTypes(ChoicesMixin, metaclass=IncludesTextChoicesMeta): if not types_cls: return {} type_constraints = types_cls.get_constrains() - return type_constraints.get(tp, {}) + constraints = type_constraints.get(tp, {}) + cls.set_automation_methods(category, tp, constraints) + return constraints + + @classmethod + def set_automation_methods(cls, category, tp, constraints): + from assets.playbooks import filter_platform_methods + automation = constraints.get('automation', {}) + automation_methods = {} + for item, enabled in automation.items(): + if not enabled: + continue + item_name = item.replace('_enabled', '') + methods = filter_platform_methods(category, tp, item_name) + methods = [{'name': m['name'], 'id': m['id']} for m in methods] + automation_methods[item_name+'_methods'] = methods + automation.update(automation_methods) + constraints['automation'] = automation + return constraints + + @classmethod + def types(cls): + types = [] + for category, tps in cls.category_types(): + for tp in tps: + types.append(cls.serialize_type(category, tp)) + return types + + @classmethod + def categories(cls): + categories = [] + for category, tps in cls.category_types(): + category_data = { + 'id': category.value, + 'name': category.label, + 'children': [cls.serialize_type(category, tp) for tp in tps] + } + categories.append(category_data) + return categories + + @classmethod + def serialize_type(cls, category, tp): + return { + 'id': tp.value, + 'name': tp.label, + 'category': category, + 'constraints': cls.get_constraints(category, tp) + } @classmethod def category_types(cls): diff --git a/apps/assets/playbooks/__init__.py b/apps/assets/playbooks/__init__.py index 0acc08789..59f705fb9 100644 --- a/apps/assets/playbooks/__init__.py +++ b/apps/assets/playbooks/__init__.py @@ -22,7 +22,7 @@ def check_platform_methods(methods): raise ValueError("Duplicate id: {}".format(_id)) -def get_platform_methods(): +def get_platform_automation_methods(): methods = [] for root, dirs, files in os.walk(BASE_DIR, topdown=False): for name in files: @@ -47,8 +47,8 @@ def filter_key(manifest, attr, value): return value in manifest_value or 'all' in manifest_value -def filter_platform_methods(category, tp, method): - methods = platform_ops_methods +def filter_platform_methods(category, tp, method=None): + methods = platform_automation_methods if category: methods = filter(partial(filter_key, attr='category', value=category), methods) if tp: @@ -58,8 +58,8 @@ def filter_platform_methods(category, tp, method): return methods -platform_ops_methods = get_platform_methods() +platform_automation_methods = get_platform_automation_methods() if __name__ == '__main__': - print(get_platform_methods()) + print(get_platform_automation_methods()) diff --git a/apps/assets/serializers/__init__.py b/apps/assets/serializers/__init__.py index ef4b40abe..e638e84b3 100644 --- a/apps/assets/serializers/__init__.py +++ b/apps/assets/serializers/__init__.py @@ -10,3 +10,4 @@ from .favorite_asset import * from .account import * from .backup import * from .platform import * +from .cagegory import * diff --git a/apps/assets/serializers/asset/category.py b/apps/assets/serializers/asset/category.py deleted file mode 100644 index 8cf62d99d..000000000 --- a/apps/assets/serializers/asset/category.py +++ /dev/null @@ -1,9 +0,0 @@ -from assets.models import Device -from .common import AssetSerializer - -__all__ = ['NetworkingSerializer'] - - -class NetworkingSerializer(AssetSerializer): - class Meta(AssetSerializer.Meta): - model = Device diff --git a/apps/assets/serializers/asset/device.py b/apps/assets/serializers/asset/device.py index 1c6e59f9f..edad96ad1 100644 --- a/apps/assets/serializers/asset/device.py +++ b/apps/assets/serializers/asset/device.py @@ -2,9 +2,9 @@ from assets.models import Device from .common import AssetSerializer -__all__ = ['NetworkingSerializer'] +__all__ = ['DeviceSerializer'] -class NetworkingSerializer(AssetSerializer): +class DeviceSerializer(AssetSerializer): class Meta(AssetSerializer.Meta): model = Device diff --git a/apps/assets/serializers/cagegory.py b/apps/assets/serializers/cagegory.py new file mode 100644 index 000000000..f0b1bf67e --- /dev/null +++ b/apps/assets/serializers/cagegory.py @@ -0,0 +1,15 @@ +from rest_framework import serializers +from django.utils.translation import gettext_lazy as _ + + +class TypeSerializer(serializers.Serializer): + id = serializers.CharField(max_length=64, required=False, allow_blank=True, label=_('id')) + name = serializers.CharField(max_length=64, required=False, allow_blank=True, label=_('Name')) + category = serializers.CharField(max_length=64, required=False, allow_blank=True, label=_('Category')) + constraints = serializers.JSONField(required=False, allow_null=True, label=_('Constraints')) + + +class CategorySerializer(serializers.Serializer): + id = serializers.CharField(max_length=64, required=False, allow_blank=True, label=_('id')) + name = serializers.CharField(max_length=64, required=False, allow_blank=True, label=_('Name')) + children = TypeSerializer(many=True, required=False, label=_('Children'), read_only=True) diff --git a/apps/assets/urls/api_urls.py b/apps/assets/urls/api_urls.py index 04df314f9..57b265245 100644 --- a/apps/assets/urls/api_urls.py +++ b/apps/assets/urls/api_urls.py @@ -31,6 +31,8 @@ router.register(r'account-backup-plan-executions', api.AccountBackupPlanExecutio urlpatterns = [ # path('assets//gateways/', api.AssetGatewayListApi.as_view(), name='asset-gateway-list'), + path('categories/', api.CategoryListApi.as_view(), name='category-list'), + path('categories/types/', api.TypeListApi.as_view(), name='type-list'), path('assets//tasks/', api.AssetTaskCreateApi.as_view(), name='asset-task-create'), path('assets/tasks/', api.AssetsTaskCreateApi.as_view(), name='assets-task-create'), path('assets//perm-users/', api.AssetPermUserListApi.as_view(), name='asset-perm-user-list'),