mirror of https://github.com/jumpserver/jumpserver
feat: 新增获取k8s pod namespace container接口
parent
11fd9a6567
commit
100bfe0304
|
@ -1,6 +1,6 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
#
|
#
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
from orgs.mixins.api import OrgBulkModelViewSet
|
from orgs.mixins.api import OrgBulkModelViewSet
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
|
@ -1,13 +1,21 @@
|
||||||
|
from urllib.parse import urlencode, parse_qsl
|
||||||
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
from rest_framework.generics import get_object_or_404
|
||||||
|
|
||||||
from common.tree import TreeNode
|
from common.tree import TreeNode
|
||||||
from orgs.models import Organization
|
from orgs.models import Organization
|
||||||
|
from assets.models import SystemUser
|
||||||
|
from applications.utils import KubernetesClient, KubernetesTree
|
||||||
|
from perms.utils.application.permission import get_application_system_user_ids
|
||||||
|
|
||||||
from ..models import Application
|
from ..models import Application
|
||||||
|
|
||||||
__all__ = ['SerializeApplicationToTreeNodeMixin']
|
__all__ = ['SerializeApplicationToTreeNodeMixin']
|
||||||
|
|
||||||
|
|
||||||
class SerializeApplicationToTreeNodeMixin:
|
class SerializeApplicationToTreeNodeMixin:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def filter_organizations(applications):
|
def filter_organizations(applications):
|
||||||
organization_ids = set(applications.values_list('org_id', flat=True))
|
organization_ids = set(applications.values_list('org_id', flat=True))
|
||||||
|
@ -31,25 +39,47 @@ class SerializeApplicationToTreeNodeMixin:
|
||||||
})
|
})
|
||||||
return node
|
return node
|
||||||
|
|
||||||
def serialize_applications_with_org(self, applications):
|
def serialize_applications_with_org(self, applications, tree_id, parent_info, user):
|
||||||
|
tree_nodes = []
|
||||||
if not applications:
|
if not applications:
|
||||||
return []
|
return tree_nodes
|
||||||
root_node = self.create_root_node()
|
|
||||||
tree_nodes = [root_node]
|
|
||||||
organizations = self.filter_organizations(applications)
|
|
||||||
|
|
||||||
for i, org in enumerate(organizations):
|
if not tree_id:
|
||||||
# 组织节点
|
root_node = self.create_root_node()
|
||||||
org_node = org.as_tree_node(pid=root_node.id)
|
tree_nodes.append(root_node)
|
||||||
tree_nodes.append(org_node)
|
organizations = self.filter_organizations(applications)
|
||||||
org_applications = applications.filter(org_id=org.id)
|
for i, org in enumerate(organizations):
|
||||||
count = org_applications.count()
|
tree_id = urlencode({'org_id': str(org.id)})
|
||||||
org_node.name += '({})'.format(count)
|
apps = applications.filter(org_id=org.id)
|
||||||
|
# 组织节点
|
||||||
|
org_node = org.as_tree_node(oid=tree_id, pid=root_node.id)
|
||||||
|
org_node.name += '({})'.format(apps.count())
|
||||||
|
tree_nodes.append(org_node)
|
||||||
|
category_type_nodes = Application.create_category_type_tree_nodes(
|
||||||
|
apps, tree_id, show_empty=False
|
||||||
|
)
|
||||||
|
tree_nodes += category_type_nodes
|
||||||
|
|
||||||
# 各应用节点
|
for app in apps:
|
||||||
apps_nodes = Application.create_tree_nodes(
|
app_node = app.as_tree_node(tree_id, is_luna=True)
|
||||||
queryset=org_applications, root_node=org_node,
|
tree_nodes.append(app_node)
|
||||||
show_empty=False
|
return tree_nodes
|
||||||
)
|
|
||||||
tree_nodes += apps_nodes
|
parent_info = dict(parse_qsl(parent_info))
|
||||||
|
pod_name = parent_info.get('pod')
|
||||||
|
app_id = parent_info.get('app_id')
|
||||||
|
namespace = parent_info.get('namespace')
|
||||||
|
system_user_id = parent_info.get('system_user_id')
|
||||||
|
if app_id and not any([pod_name, namespace, system_user_id]):
|
||||||
|
app = get_object_or_404(Application, id=app_id)
|
||||||
|
system_user_ids = get_application_system_user_ids(user, app)
|
||||||
|
system_users = SystemUser.objects.filter(id__in=system_user_ids).order_by('priority')
|
||||||
|
for system_user in system_users:
|
||||||
|
system_user_node = KubernetesTree(tree_id).as_system_user_tree_node(
|
||||||
|
system_user, parent_info
|
||||||
|
)
|
||||||
|
tree_nodes.append(system_user_node)
|
||||||
|
return tree_nodes
|
||||||
|
|
||||||
|
tree_nodes = KubernetesTree(tree_id).async_tree_node(parent_info)
|
||||||
return tree_nodes
|
return tree_nodes
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from urllib.parse import urlencode, parse_qsl
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -7,6 +8,8 @@ from orgs.mixins.models import OrgModelMixin
|
||||||
from common.mixins import CommonModelMixin
|
from common.mixins import CommonModelMixin
|
||||||
from common.tree import TreeNode
|
from common.tree import TreeNode
|
||||||
from assets.models import Asset, SystemUser
|
from assets.models import Asset, SystemUser
|
||||||
|
|
||||||
|
from ..utils import KubernetesTree
|
||||||
from .. import const
|
from .. import const
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,6 +19,13 @@ class ApplicationTreeNodeMixin:
|
||||||
type: str
|
type: str
|
||||||
category: str
|
category: str
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_tree_id(pid, type, v):
|
||||||
|
i = dict(parse_qsl(pid))
|
||||||
|
i[type] = v
|
||||||
|
tree_id = urlencode(i)
|
||||||
|
return tree_id
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_choice_node(cls, c, id_, pid, tp, opened=False, counts=None,
|
def create_choice_node(cls, c, id_, pid, tp, opened=False, counts=None,
|
||||||
show_empty=True, show_count=True):
|
show_empty=True, show_count=True):
|
||||||
|
@ -65,13 +75,13 @@ class ApplicationTreeNodeMixin:
|
||||||
return node
|
return node
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_category_tree_nodes(cls, root_node, counts=None, show_empty=True, show_count=True):
|
def create_category_tree_nodes(cls, pid, counts=None, show_empty=True, show_count=True):
|
||||||
nodes = []
|
nodes = []
|
||||||
categories = const.AppType.category_types_mapper().keys()
|
categories = const.AppType.category_types_mapper().keys()
|
||||||
for category in categories:
|
for category in categories:
|
||||||
i = root_node.id + '_' + category.value
|
i = cls.create_tree_id(pid, 'category', category.value)
|
||||||
node = cls.create_choice_node(
|
node = cls.create_choice_node(
|
||||||
category, i, pid=root_node.id, tp='category',
|
category, i, pid=pid, tp='category',
|
||||||
counts=counts, opened=False, show_empty=show_empty,
|
counts=counts, opened=False, show_empty=show_empty,
|
||||||
show_count=show_count
|
show_count=show_count
|
||||||
)
|
)
|
||||||
|
@ -81,17 +91,20 @@ class ApplicationTreeNodeMixin:
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_types_tree_nodes(cls, root_node, counts, show_empty=True, show_count=True):
|
def create_types_tree_nodes(cls, pid, counts, show_empty=True, show_count=True):
|
||||||
nodes = []
|
nodes = []
|
||||||
|
temp_pid = pid
|
||||||
type_category_mapper = const.AppType.type_category_mapper()
|
type_category_mapper = const.AppType.type_category_mapper()
|
||||||
for tp in const.AppType.type_category_mapper().keys():
|
types = const.AppType.type_category_mapper().keys()
|
||||||
|
for tp in types:
|
||||||
category = type_category_mapper.get(tp)
|
category = type_category_mapper.get(tp)
|
||||||
pid = root_node.id + '_' + category.value
|
pid = cls.create_tree_id(pid, 'category', category.value)
|
||||||
i = root_node.id + '_' + tp.value
|
i = cls.create_tree_id(pid, 'type', tp.value)
|
||||||
node = cls.create_choice_node(
|
node = cls.create_choice_node(
|
||||||
tp, i, pid, tp='type', counts=counts, opened=False,
|
tp, i, pid, tp='type', counts=counts, opened=False,
|
||||||
show_empty=show_empty, show_count=show_count
|
show_empty=show_empty, show_count=show_count
|
||||||
)
|
)
|
||||||
|
pid = temp_pid
|
||||||
if not node:
|
if not node:
|
||||||
continue
|
continue
|
||||||
nodes.append(node)
|
nodes.append(node)
|
||||||
|
@ -109,40 +122,63 @@ class ApplicationTreeNodeMixin:
|
||||||
return counts
|
return counts
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_tree_nodes(cls, queryset, root_node=None, show_empty=True, show_count=True):
|
def create_category_type_tree_nodes(cls, queryset, pid, show_empty=True, show_count=True):
|
||||||
counts = cls.get_tree_node_counts(queryset)
|
counts = cls.get_tree_node_counts(queryset)
|
||||||
tree_nodes = []
|
tree_nodes = []
|
||||||
|
|
||||||
|
# 类别的节点
|
||||||
|
tree_nodes += cls.create_category_tree_nodes(
|
||||||
|
pid, counts, show_empty=show_empty,
|
||||||
|
show_count=show_count
|
||||||
|
)
|
||||||
|
|
||||||
|
# 类型的节点
|
||||||
|
tree_nodes += cls.create_types_tree_nodes(
|
||||||
|
pid, counts, show_empty=show_empty,
|
||||||
|
show_count=show_count
|
||||||
|
)
|
||||||
|
|
||||||
|
return tree_nodes
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_tree_nodes(cls, queryset, root_node=None, show_empty=True, show_count=True):
|
||||||
|
tree_nodes = []
|
||||||
|
|
||||||
# 根节点有可能是组织名称
|
# 根节点有可能是组织名称
|
||||||
if root_node is None:
|
if root_node is None:
|
||||||
root_node = cls.create_root_tree_node(queryset, show_count=show_count)
|
root_node = cls.create_root_tree_node(queryset, show_count=show_count)
|
||||||
tree_nodes.append(root_node)
|
tree_nodes.append(root_node)
|
||||||
|
|
||||||
# 类别的节点
|
tree_nodes += cls.create_category_type_tree_nodes(
|
||||||
tree_nodes += cls.create_category_tree_nodes(
|
queryset, root_node.id, show_empty=show_empty, show_count=show_count
|
||||||
root_node, counts, show_empty=show_empty,
|
|
||||||
show_count=show_count
|
|
||||||
)
|
|
||||||
|
|
||||||
# 类型的节点
|
|
||||||
tree_nodes += cls.create_types_tree_nodes(
|
|
||||||
root_node, counts, show_empty=show_empty,
|
|
||||||
show_count=show_count
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 应用的节点
|
# 应用的节点
|
||||||
for app in queryset:
|
for app in queryset:
|
||||||
pid = root_node.id + '_' + app.type
|
node = app.as_tree_node(root_node.id)
|
||||||
tree_nodes.append(app.as_tree_node(pid))
|
tree_nodes.append(node)
|
||||||
return tree_nodes
|
return tree_nodes
|
||||||
|
|
||||||
def as_tree_node(self, pid):
|
def create_app_tree_pid(self, root_id):
|
||||||
|
pid = self.create_tree_id(root_id, 'category', self.category)
|
||||||
|
pid = self.create_tree_id(pid, 'type', self.type)
|
||||||
|
return pid
|
||||||
|
|
||||||
|
def as_tree_node(self, pid, is_luna=False):
|
||||||
|
if is_luna and self.type == const.AppType.k8s:
|
||||||
|
node = KubernetesTree(pid).as_tree_node(self)
|
||||||
|
else:
|
||||||
|
node = self._as_tree_node(pid)
|
||||||
|
return node
|
||||||
|
|
||||||
|
def _as_tree_node(self, pid):
|
||||||
icon_skin_category_mapper = {
|
icon_skin_category_mapper = {
|
||||||
'remote_app': 'chrome',
|
'remote_app': 'chrome',
|
||||||
'db': 'database',
|
'db': 'database',
|
||||||
'cloud': 'cloud'
|
'cloud': 'cloud'
|
||||||
}
|
}
|
||||||
icon_skin = icon_skin_category_mapper.get(self.category, 'file')
|
icon_skin = icon_skin_category_mapper.get(self.category, 'file')
|
||||||
|
pid = self.create_app_tree_pid(pid)
|
||||||
node = TreeNode(**{
|
node = TreeNode(**{
|
||||||
'id': str(self.id),
|
'id': str(self.id),
|
||||||
'name': self.name,
|
'name': self.name,
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
|
||||||
|
from .kubernetes_util import *
|
|
@ -0,0 +1,186 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from urllib3.exceptions import MaxRetryError
|
||||||
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
|
from kubernetes.client import api_client
|
||||||
|
from kubernetes.client.api import core_v1_api
|
||||||
|
from kubernetes import client
|
||||||
|
from kubernetes.client.exceptions import ApiException
|
||||||
|
|
||||||
|
from rest_framework.generics import get_object_or_404
|
||||||
|
|
||||||
|
from common.utils import get_logger
|
||||||
|
from common.tree import TreeNode
|
||||||
|
from assets.models import SystemUser
|
||||||
|
|
||||||
|
from .. import const
|
||||||
|
|
||||||
|
logger = get_logger(__file__)
|
||||||
|
|
||||||
|
|
||||||
|
class KubernetesClient:
|
||||||
|
def __init__(self, url, token):
|
||||||
|
self.url = url
|
||||||
|
self.token = token
|
||||||
|
|
||||||
|
def get_api(self):
|
||||||
|
configuration = client.Configuration()
|
||||||
|
configuration.host = self.url
|
||||||
|
configuration.verify_ssl = False
|
||||||
|
configuration.api_key = {"authorization": "Bearer " + self.token}
|
||||||
|
c = api_client.ApiClient(configuration=configuration)
|
||||||
|
api = core_v1_api.CoreV1Api(c)
|
||||||
|
return api
|
||||||
|
|
||||||
|
def get_namespace_list(self):
|
||||||
|
api = self.get_api()
|
||||||
|
namespace_list = []
|
||||||
|
for ns in api.list_namespace().items:
|
||||||
|
namespace_list.append(ns.metadata.name)
|
||||||
|
return namespace_list
|
||||||
|
|
||||||
|
def get_services(self):
|
||||||
|
api = self.get_api()
|
||||||
|
ret = api.list_service_for_all_namespaces(watch=False)
|
||||||
|
for i in ret.items:
|
||||||
|
print("%s \t%s \t%s \t%s \t%s \n" % (
|
||||||
|
i.kind, i.metadata.namespace, i.metadata.name, i.spec.cluster_ip, i.spec.ports))
|
||||||
|
|
||||||
|
def get_pod_info(self, namespace, pod):
|
||||||
|
api = self.get_api()
|
||||||
|
resp = api.read_namespaced_pod(namespace=namespace, name=pod)
|
||||||
|
return resp
|
||||||
|
|
||||||
|
def get_pod_logs(self, namespace, pod):
|
||||||
|
api = self.get_api()
|
||||||
|
log_content = api.read_namespaced_pod_log(pod, namespace, pretty=True, tail_lines=200)
|
||||||
|
return log_content
|
||||||
|
|
||||||
|
def get_pods(self):
|
||||||
|
api = self.get_api()
|
||||||
|
try:
|
||||||
|
ret = api.list_pod_for_all_namespaces(watch=False, _request_timeout=(3, 3))
|
||||||
|
except MaxRetryError:
|
||||||
|
logger.warning('Kubernetes connection timed out')
|
||||||
|
return
|
||||||
|
except ApiException as e:
|
||||||
|
if e.status == 401:
|
||||||
|
logger.warning('Kubernetes User not authenticated')
|
||||||
|
else:
|
||||||
|
logger.warning(e)
|
||||||
|
return
|
||||||
|
data = {}
|
||||||
|
for i in ret.items:
|
||||||
|
namespace = i.metadata.namespace
|
||||||
|
pod_info = {
|
||||||
|
'pod_name': i.metadata.name,
|
||||||
|
'containers': [j.name for j in i.spec.containers]
|
||||||
|
}
|
||||||
|
if namespace in data:
|
||||||
|
data[namespace].append(pod_info)
|
||||||
|
else:
|
||||||
|
data[namespace] = [pod_info, ]
|
||||||
|
return data
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_kubernetes_data(app_id, system_user_id):
|
||||||
|
from ..models import Application
|
||||||
|
app = get_object_or_404(Application, id=app_id)
|
||||||
|
system_user = get_object_or_404(SystemUser, id=system_user_id)
|
||||||
|
k8s = KubernetesClient(app.attrs['cluster'], system_user.token)
|
||||||
|
return k8s.get_pods()
|
||||||
|
|
||||||
|
|
||||||
|
class KubernetesTree:
|
||||||
|
def __init__(self, tree_id):
|
||||||
|
self.tree_id = tree_id
|
||||||
|
|
||||||
|
def as_tree_node(self, app):
|
||||||
|
pid = app.create_app_tree_pid(self.tree_id)
|
||||||
|
app_id = str(app.id)
|
||||||
|
parent_info = {'app_id': app_id}
|
||||||
|
node = self.create_tree_node(
|
||||||
|
app_id, pid, app.name, 'k8s', parent_info
|
||||||
|
)
|
||||||
|
return node
|
||||||
|
|
||||||
|
def as_system_user_tree_node(self, system_user, parent_info):
|
||||||
|
from ..models import ApplicationTreeNodeMixin
|
||||||
|
system_user_id = str(system_user.id)
|
||||||
|
username = system_user.username
|
||||||
|
username = username if username else '*'
|
||||||
|
name = f'{system_user.name}({username})'
|
||||||
|
pid = urlencode({'app_id': self.tree_id})
|
||||||
|
i = ApplicationTreeNodeMixin.create_tree_id(pid, 'system_user_id', system_user_id)
|
||||||
|
parent_info.update({'system_user_id': system_user_id})
|
||||||
|
node = self.create_tree_node(
|
||||||
|
i, pid, name, 'system_user', parent_info, icon='user-tie'
|
||||||
|
)
|
||||||
|
return node
|
||||||
|
|
||||||
|
def as_namespace_pod_tree_node(self, name, meta, type, counts=0, is_container=False):
|
||||||
|
from ..models import ApplicationTreeNodeMixin
|
||||||
|
i = ApplicationTreeNodeMixin.create_tree_id(self.tree_id, type, name)
|
||||||
|
meta.update({type: name})
|
||||||
|
name = name if is_container else f'{name}({counts})'
|
||||||
|
node = self.create_tree_node(
|
||||||
|
i, self.tree_id, name, type, meta, icon='cloud', is_container=is_container
|
||||||
|
)
|
||||||
|
return node
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_tree_node(id_, pid, name, identity, parent_info, icon='', is_container=False):
|
||||||
|
node = TreeNode(**{
|
||||||
|
'id': id_,
|
||||||
|
'name': name,
|
||||||
|
'title': name,
|
||||||
|
'pId': pid,
|
||||||
|
'isParent': not is_container,
|
||||||
|
'open': False,
|
||||||
|
'iconSkin': icon,
|
||||||
|
'parentInfo': urlencode(parent_info),
|
||||||
|
'meta': {
|
||||||
|
'type': 'application',
|
||||||
|
'data': {
|
||||||
|
'category': const.AppCategory.cloud,
|
||||||
|
'type': const.AppType.k8s,
|
||||||
|
'identity': identity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return node
|
||||||
|
|
||||||
|
def async_tree_node(self, parent_info):
|
||||||
|
pod_name = parent_info.get('pod')
|
||||||
|
app_id = parent_info.get('app_id')
|
||||||
|
namespace = parent_info.get('namespace')
|
||||||
|
system_user_id = parent_info.get('system_user_id')
|
||||||
|
|
||||||
|
tree_nodes = []
|
||||||
|
data = KubernetesClient.get_kubernetes_data(app_id, system_user_id)
|
||||||
|
if not data:
|
||||||
|
return tree_nodes
|
||||||
|
|
||||||
|
if pod_name:
|
||||||
|
for container in next(
|
||||||
|
filter(
|
||||||
|
lambda x: x['pod_name'] == pod_name, data[namespace]
|
||||||
|
)
|
||||||
|
)['containers']:
|
||||||
|
container_node = self.as_namespace_pod_tree_node(
|
||||||
|
container, parent_info, 'container', is_container=True
|
||||||
|
)
|
||||||
|
tree_nodes.append(container_node)
|
||||||
|
elif namespace:
|
||||||
|
for pod in data[namespace]:
|
||||||
|
pod_nodes = self.as_namespace_pod_tree_node(
|
||||||
|
pod['pod_name'], parent_info, 'pod', len(pod['containers'])
|
||||||
|
)
|
||||||
|
tree_nodes.append(pod_nodes)
|
||||||
|
elif system_user_id:
|
||||||
|
for namespace, pods in data.items():
|
||||||
|
namespace_node = self.as_namespace_pod_tree_node(
|
||||||
|
namespace, parent_info, 'namespace', len(pods)
|
||||||
|
)
|
||||||
|
tree_nodes.append(namespace_node)
|
||||||
|
return tree_nodes
|
|
@ -13,6 +13,7 @@ class TreeNode:
|
||||||
pId = ""
|
pId = ""
|
||||||
open = False
|
open = False
|
||||||
iconSkin = ""
|
iconSkin = ""
|
||||||
|
parentInfo = ''
|
||||||
meta = {}
|
meta = {}
|
||||||
|
|
||||||
_tree = None
|
_tree = None
|
||||||
|
@ -95,6 +96,7 @@ class TreeNodeSerializer(serializers.Serializer):
|
||||||
name = serializers.CharField(max_length=128)
|
name = serializers.CharField(max_length=128)
|
||||||
title = serializers.CharField(max_length=128)
|
title = serializers.CharField(max_length=128)
|
||||||
pId = serializers.CharField(max_length=128)
|
pId = serializers.CharField(max_length=128)
|
||||||
|
parentInfo = serializers.CharField(max_length=4096, allow_blank=True)
|
||||||
isParent = serializers.BooleanField(default=False)
|
isParent = serializers.BooleanField(default=False)
|
||||||
open = serializers.BooleanField(default=False)
|
open = serializers.BooleanField(default=False)
|
||||||
iconSkin = serializers.CharField(max_length=128, allow_blank=True)
|
iconSkin = serializers.CharField(max_length=128, allow_blank=True)
|
||||||
|
|
|
@ -234,9 +234,9 @@ class Organization(models.Model):
|
||||||
with tmp_to_org(self):
|
with tmp_to_org(self):
|
||||||
return resource_model.objects.all().count()
|
return resource_model.objects.all().count()
|
||||||
|
|
||||||
def as_tree_node(self, pid, opened=True):
|
def as_tree_node(self, oid, pid, opened=True):
|
||||||
node = TreeNode(**{
|
node = TreeNode(**{
|
||||||
'id': str(self.id),
|
'id': oid,
|
||||||
'name': self.name,
|
'name': self.name,
|
||||||
'title': self.name,
|
'title': self.name,
|
||||||
'pId': pid,
|
'pId': pid,
|
||||||
|
|
|
@ -13,7 +13,6 @@ from rest_framework.generics import (
|
||||||
from orgs.utils import tmp_to_root_org
|
from orgs.utils import tmp_to_root_org
|
||||||
from applications.models import Application
|
from applications.models import Application
|
||||||
from perms.utils.application.permission import (
|
from perms.utils.application.permission import (
|
||||||
has_application_system_permission,
|
|
||||||
get_application_system_user_ids,
|
get_application_system_user_ids,
|
||||||
validate_permission,
|
validate_permission,
|
||||||
)
|
)
|
||||||
|
|
|
@ -54,10 +54,15 @@ class ApplicationsAsTreeMixin(SerializeApplicationToTreeNodeMixin):
|
||||||
将应用序列化成树的结构返回
|
将应用序列化成树的结构返回
|
||||||
"""
|
"""
|
||||||
serializer_class = TreeNodeSerializer
|
serializer_class = TreeNodeSerializer
|
||||||
|
user: None
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
|
tree_id = request.query_params.get('tree_id', None)
|
||||||
|
parent_info = request.query_params.get('parentInfo', None)
|
||||||
queryset = self.filter_queryset(self.get_queryset())
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
tree_nodes = self.serialize_applications_with_org(queryset)
|
tree_nodes = self.serialize_applications_with_org(
|
||||||
|
queryset, tree_id, parent_info, self.user
|
||||||
|
)
|
||||||
serializer = self.get_serializer(tree_nodes, many=True)
|
serializer = self.get_serializer(tree_nodes, many=True)
|
||||||
return Response(data=serializer.data)
|
return Response(data=serializer.data)
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ PyNaCl==1.2.1
|
||||||
python-dateutil==2.6.1
|
python-dateutil==2.6.1
|
||||||
#python-gssapi==0.6.4
|
#python-gssapi==0.6.4
|
||||||
pytz==2018.3
|
pytz==2018.3
|
||||||
PyYAML==5.4
|
PyYAML==6.0
|
||||||
redis==3.5.3
|
redis==3.5.3
|
||||||
requests==2.25.1
|
requests==2.25.1
|
||||||
jms-storage==0.0.40
|
jms-storage==0.0.40
|
||||||
|
@ -125,3 +125,5 @@ pyzipper==0.3.5
|
||||||
python3-saml==1.12.0
|
python3-saml==1.12.0
|
||||||
python-keystoneclient==4.3.0
|
python-keystoneclient==4.3.0
|
||||||
pymssql==2.1.5
|
pymssql==2.1.5
|
||||||
|
kubernetes==21.7.0
|
||||||
|
websocket-client==1.2.3
|
||||||
|
|
Loading…
Reference in New Issue