mirror of https://github.com/veops/cmdb.git
feat: Predefined values support executing scripts (#227)
This commit is contained in:
parent
7d53180a2f
commit
779cd1ea9e
|
@ -60,10 +60,11 @@ class AttributeManager(object):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_choice_values_from_other_ci(choice_other):
|
def _get_choice_values_from_other(choice_other):
|
||||||
from api.lib.cmdb.search import SearchError
|
from api.lib.cmdb.search import SearchError
|
||||||
from api.lib.cmdb.search.ci import search
|
from api.lib.cmdb.search.ci import search
|
||||||
|
|
||||||
|
if choice_other.get('type_ids'):
|
||||||
type_ids = choice_other.get('type_ids')
|
type_ids = choice_other.get('type_ids')
|
||||||
attr_id = choice_other.get('attr_id')
|
attr_id = choice_other.get('attr_id')
|
||||||
other_filter = choice_other.get('filter') or ''
|
other_filter = choice_other.get('filter') or ''
|
||||||
|
@ -77,6 +78,16 @@ class AttributeManager(object):
|
||||||
current_app.logger.error("get choice values from other ci failed: {}".format(e))
|
current_app.logger.error("get choice values from other ci failed: {}".format(e))
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
elif choice_other.get('script'):
|
||||||
|
try:
|
||||||
|
x = compile(choice_other['script'], '', "exec")
|
||||||
|
exec(x)
|
||||||
|
res = locals()['ChoiceValue']().values() or []
|
||||||
|
return [[i, {}] for i in res]
|
||||||
|
except Exception as e:
|
||||||
|
current_app.logger.error("get choice values from script: {}".format(e))
|
||||||
|
return []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_choice_values(cls, attr_id, value_type, choice_web_hook, choice_other,
|
def get_choice_values(cls, attr_id, value_type, choice_web_hook, choice_other,
|
||||||
choice_web_hook_parse=True, choice_other_parse=True):
|
choice_web_hook_parse=True, choice_other_parse=True):
|
||||||
|
@ -87,7 +98,7 @@ class AttributeManager(object):
|
||||||
return []
|
return []
|
||||||
elif choice_other:
|
elif choice_other:
|
||||||
if choice_other_parse and isinstance(choice_other, dict):
|
if choice_other_parse and isinstance(choice_other, dict):
|
||||||
return cls._get_choice_values_from_other_ci(choice_other)
|
return cls._get_choice_values_from_other(choice_other)
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@ -96,7 +107,8 @@ class AttributeManager(object):
|
||||||
return []
|
return []
|
||||||
choice_values = choice_table.get_by(fl=["value", "option"], attr_id=attr_id)
|
choice_values = choice_table.get_by(fl=["value", "option"], attr_id=attr_id)
|
||||||
|
|
||||||
return [[choice_value['value'], choice_value['option']] for choice_value in choice_values]
|
return [[ValueTypeMap.serialize[value_type](choice_value['value']), choice_value['option']]
|
||||||
|
for choice_value in choice_values]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add_choice_values(_id, value_type, choice_values):
|
def add_choice_values(_id, value_type, choice_values):
|
||||||
|
@ -218,9 +230,14 @@ class AttributeManager(object):
|
||||||
if name in BUILTIN_KEYWORDS:
|
if name in BUILTIN_KEYWORDS:
|
||||||
return abort(400, ErrFormat.attribute_name_cannot_be_builtin)
|
return abort(400, ErrFormat.attribute_name_cannot_be_builtin)
|
||||||
|
|
||||||
if kwargs.get('choice_other'):
|
while kwargs.get('choice_other'):
|
||||||
if (not isinstance(kwargs['choice_other'], dict) or not kwargs['choice_other'].get('type_ids') or
|
if isinstance(kwargs['choice_other'], dict):
|
||||||
not kwargs['choice_other'].get('attr_id')):
|
if kwargs['choice_other'].get('script'):
|
||||||
|
break
|
||||||
|
|
||||||
|
if kwargs['choice_other'].get('type_ids') and kwargs['choice_other'].get('attr_id'):
|
||||||
|
break
|
||||||
|
|
||||||
return abort(400, ErrFormat.attribute_choice_other_invalid)
|
return abort(400, ErrFormat.attribute_choice_other_invalid)
|
||||||
|
|
||||||
alias = kwargs.pop("alias", "")
|
alias = kwargs.pop("alias", "")
|
||||||
|
@ -232,6 +249,8 @@ class AttributeManager(object):
|
||||||
|
|
||||||
kwargs.get('is_computed') and cls.can_create_computed_attribute()
|
kwargs.get('is_computed') and cls.can_create_computed_attribute()
|
||||||
|
|
||||||
|
kwargs.get('choice_other') and kwargs['choice_other'].get('script') and cls.can_create_computed_attribute()
|
||||||
|
|
||||||
attr = Attribute.create(flush=True,
|
attr = Attribute.create(flush=True,
|
||||||
name=name,
|
name=name,
|
||||||
alias=alias,
|
alias=alias,
|
||||||
|
@ -337,9 +356,14 @@ class AttributeManager(object):
|
||||||
|
|
||||||
self._change_index(attr, attr.is_index, kwargs['is_index'])
|
self._change_index(attr, attr.is_index, kwargs['is_index'])
|
||||||
|
|
||||||
if kwargs.get('choice_other'):
|
while kwargs.get('choice_other'):
|
||||||
if (not isinstance(kwargs['choice_other'], dict) or not kwargs['choice_other'].get('type_ids') or
|
if isinstance(kwargs['choice_other'], dict):
|
||||||
not kwargs['choice_other'].get('attr_id')):
|
if kwargs['choice_other'].get('script'):
|
||||||
|
break
|
||||||
|
|
||||||
|
if kwargs['choice_other'].get('type_ids') and kwargs['choice_other'].get('attr_id'):
|
||||||
|
break
|
||||||
|
|
||||||
return abort(400, ErrFormat.attribute_choice_other_invalid)
|
return abort(400, ErrFormat.attribute_choice_other_invalid)
|
||||||
|
|
||||||
existed2 = attr.to_dict()
|
existed2 = attr.to_dict()
|
||||||
|
|
|
@ -28,6 +28,7 @@ from api.lib.cmdb.search.ci.db.query_sql import QUERY_CI_BY_NO_ATTR
|
||||||
from api.lib.cmdb.search.ci.db.query_sql import QUERY_CI_BY_TYPE
|
from api.lib.cmdb.search.ci.db.query_sql import QUERY_CI_BY_TYPE
|
||||||
from api.lib.cmdb.search.ci.db.query_sql import QUERY_UNION_CI_ATTRIBUTE_IS_NULL
|
from api.lib.cmdb.search.ci.db.query_sql import QUERY_UNION_CI_ATTRIBUTE_IS_NULL
|
||||||
from api.lib.cmdb.utils import TableMap
|
from api.lib.cmdb.utils import TableMap
|
||||||
|
from api.lib.cmdb.utils import ValueTypeMap
|
||||||
from api.lib.perm.acl.acl import ACLManager
|
from api.lib.perm.acl.acl import ACLManager
|
||||||
from api.lib.perm.acl.acl import is_app_admin
|
from api.lib.perm.acl.acl import is_app_admin
|
||||||
from api.lib.utils import handle_arg_list
|
from api.lib.utils import handle_arg_list
|
||||||
|
@ -524,15 +525,15 @@ class Search(object):
|
||||||
if k:
|
if k:
|
||||||
table_name = TableMap(attr=attr).table_name
|
table_name = TableMap(attr=attr).table_name
|
||||||
query_sql = FACET_QUERY.format(table_name, self.query_sql, attr.id)
|
query_sql = FACET_QUERY.format(table_name, self.query_sql, attr.id)
|
||||||
# current_app.logger.warning(query_sql)
|
|
||||||
result = db.session.execute(query_sql).fetchall()
|
result = db.session.execute(query_sql).fetchall()
|
||||||
facet[k] = result
|
facet[k] = result
|
||||||
|
|
||||||
facet_result = dict()
|
facet_result = dict()
|
||||||
for k, v in facet.items():
|
for k, v in facet.items():
|
||||||
if not k.startswith('_'):
|
if not k.startswith('_'):
|
||||||
a = getattr(AttributeCache.get(k), self.ret_key)
|
attr = AttributeCache.get(k)
|
||||||
facet_result[a] = [(f[0], f[1], a) for f in v]
|
a = getattr(attr, self.ret_key)
|
||||||
|
facet_result[a] = [(ValueTypeMap.serialize[attr.value_type](f[0]), f[1], a) for f in v]
|
||||||
|
|
||||||
return facet_result
|
return facet_result
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import api.models.cmdb as model
|
||||||
from api.lib.cmdb.cache import AttributeCache
|
from api.lib.cmdb.cache import AttributeCache
|
||||||
from api.lib.cmdb.const import ValueTypeEnum
|
from api.lib.cmdb.const import ValueTypeEnum
|
||||||
|
|
||||||
TIME_RE = re.compile(r"^(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d$")
|
TIME_RE = re.compile(r"^20|21|22|23|[0-1]\d:[0-5]\d:[0-5]\d$")
|
||||||
|
|
||||||
|
|
||||||
def string2int(x):
|
def string2int(x):
|
||||||
|
@ -21,7 +21,7 @@ def string2int(x):
|
||||||
|
|
||||||
def str2datetime(x):
|
def str2datetime(x):
|
||||||
try:
|
try:
|
||||||
return datetime.datetime.strptime(x, "%Y-%m-%d")
|
return datetime.datetime.strptime(x, "%Y-%m-%d").date()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ class ValueTypeMap(object):
|
||||||
ValueTypeEnum.FLOAT: float,
|
ValueTypeEnum.FLOAT: float,
|
||||||
ValueTypeEnum.TEXT: lambda x: x if isinstance(x, six.string_types) else str(x),
|
ValueTypeEnum.TEXT: lambda x: x if isinstance(x, six.string_types) else str(x),
|
||||||
ValueTypeEnum.TIME: lambda x: x if isinstance(x, six.string_types) else str(x),
|
ValueTypeEnum.TIME: lambda x: x if isinstance(x, six.string_types) else str(x),
|
||||||
ValueTypeEnum.DATE: lambda x: x.strftime("%Y-%m-%d"),
|
ValueTypeEnum.DATE: lambda x: x.strftime("%Y-%m-%d") if not isinstance(x, six.string_types) else x,
|
||||||
ValueTypeEnum.DATETIME: lambda x: x.strftime("%Y-%m-%d %H:%M:%S"),
|
ValueTypeEnum.DATETIME: lambda x: x.strftime("%Y-%m-%d %H:%M:%S") if not isinstance(x, six.string_types) else x,
|
||||||
ValueTypeEnum.JSON: lambda x: json.loads(x) if isinstance(x, six.string_types) and x else x,
|
ValueTypeEnum.JSON: lambda x: json.loads(x) if isinstance(x, six.string_types) and x else x,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +64,8 @@ class ValueTypeMap(object):
|
||||||
ValueTypeEnum.FLOAT: model.FloatChoice,
|
ValueTypeEnum.FLOAT: model.FloatChoice,
|
||||||
ValueTypeEnum.TEXT: model.TextChoice,
|
ValueTypeEnum.TEXT: model.TextChoice,
|
||||||
ValueTypeEnum.TIME: model.TextChoice,
|
ValueTypeEnum.TIME: model.TextChoice,
|
||||||
|
ValueTypeEnum.DATE: model.TextChoice,
|
||||||
|
ValueTypeEnum.DATETIME: model.TextChoice,
|
||||||
}
|
}
|
||||||
|
|
||||||
table = {
|
table = {
|
||||||
|
@ -97,7 +99,7 @@ class ValueTypeMap(object):
|
||||||
ValueTypeEnum.DATE: 'text',
|
ValueTypeEnum.DATE: 'text',
|
||||||
ValueTypeEnum.TIME: 'text',
|
ValueTypeEnum.TIME: 'text',
|
||||||
ValueTypeEnum.FLOAT: 'float',
|
ValueTypeEnum.FLOAT: 'float',
|
||||||
ValueTypeEnum.JSON: 'object'
|
ValueTypeEnum.JSON: 'object',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue