codosdk 1.0.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codosdk-1.0.0.data/data/share/doc/codo_sdk/README.md +50 -0
- codosdk-1.0.0.dist-info/LICENSE +674 -0
- codosdk-1.0.0.dist-info/METADATA +35 -0
- codosdk-1.0.0.dist-info/RECORD +45 -0
- codosdk-1.0.0.dist-info/WHEEL +6 -0
- codosdk-1.0.0.dist-info/top_level.txt +2 -0
- opssdk/__init__.py +0 -0
- opssdk/utils/__init__.py +24 -0
- websdk2/__init__.py +0 -0
- websdk2/api_set.py +43 -0
- websdk2/apis/__init__.py +9 -0
- websdk2/apis/admin_apis.py +160 -0
- websdk2/apis/agent_apis.py +44 -0
- websdk2/apis/cmdb_apis.py +22 -0
- websdk2/apis/kerrigan_apis.py +21 -0
- websdk2/apis/mgv4_apis.py +95 -0
- websdk2/apis/task_apis.py +80 -0
- websdk2/application.py +77 -0
- websdk2/base_handler.py +275 -0
- websdk2/cache.py +128 -0
- websdk2/cache_context.py +38 -0
- websdk2/client.py +173 -0
- websdk2/cloud/__init__.py +0 -0
- websdk2/cloud/qcloud_api.py +57 -0
- websdk2/cloud/ucloud_api.py +73 -0
- websdk2/cloud_utils.py +26 -0
- websdk2/configs.py +97 -0
- websdk2/consts.py +212 -0
- websdk2/db_context.py +150 -0
- websdk2/error.py +50 -0
- websdk2/fetch_coroutine.py +12 -0
- websdk2/jwt_token.py +135 -0
- websdk2/ldap.py +117 -0
- websdk2/logger.py +42 -0
- websdk2/model_utils.py +156 -0
- websdk2/mqhelper.py +120 -0
- websdk2/program.py +20 -0
- websdk2/salt_api.py +107 -0
- websdk2/sqlalchemy_pagination.py +73 -0
- websdk2/tools.py +198 -0
- websdk2/utils/__init__.py +257 -0
- websdk2/utils/cc_crypto.py +85 -0
- websdk2/utils/date_format.py +35 -0
- websdk2/utils/pydantic_utils.py +55 -0
- websdk2/web_logs.py +127 -0
websdk2/jwt_token.py
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding:utf-8 -*-
|
|
3
|
+
import jwt, datetime, hashlib
|
|
4
|
+
from .configs import configs as my_configs
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class AuthToken:
|
|
8
|
+
def __init__(self):
|
|
9
|
+
self.token_secret = my_configs.get('token_secret', '3AIiOq18i~H=WWTIGq4ODQyMzcsIdfghs')
|
|
10
|
+
|
|
11
|
+
def encode_auth_token(self, **kwargs):
|
|
12
|
+
"""
|
|
13
|
+
生成认证Token
|
|
14
|
+
:param user_id: string
|
|
15
|
+
:param username: string
|
|
16
|
+
:param nickname: string
|
|
17
|
+
:return: string
|
|
18
|
+
"""
|
|
19
|
+
try:
|
|
20
|
+
exp_time = kwargs.get('exp_time', 1)
|
|
21
|
+
payload = {
|
|
22
|
+
'exp': datetime.datetime.utcnow() + datetime.timedelta(days=int(exp_time), seconds=10),
|
|
23
|
+
'nbf': datetime.datetime.utcnow() - datetime.timedelta(seconds=10),
|
|
24
|
+
'iat': datetime.datetime.utcnow(),
|
|
25
|
+
'iss': 'auth: ss',
|
|
26
|
+
'sub': 'my token',
|
|
27
|
+
'id': '15618718060',
|
|
28
|
+
'data': {
|
|
29
|
+
'user_id': kwargs.get('user_id', ''),
|
|
30
|
+
'username': kwargs.get('username', ''),
|
|
31
|
+
'nickname': kwargs.get('nickname', ''),
|
|
32
|
+
'email': kwargs.get('email', ''),
|
|
33
|
+
'is_superuser': kwargs.get('is_superuser', False)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return jwt.encode(
|
|
37
|
+
payload,
|
|
38
|
+
self.token_secret,
|
|
39
|
+
algorithm='HS256'
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
except Exception as e:
|
|
43
|
+
return e
|
|
44
|
+
|
|
45
|
+
def encode_auth_token_v2(self, **kwargs):
|
|
46
|
+
### 支持到自定义小时
|
|
47
|
+
"""
|
|
48
|
+
生成认证Token
|
|
49
|
+
:param user_id: string
|
|
50
|
+
:param username: string
|
|
51
|
+
:param nickname: string
|
|
52
|
+
:param exp_time: int
|
|
53
|
+
:param exp_hour: int
|
|
54
|
+
:return: string
|
|
55
|
+
"""
|
|
56
|
+
try:
|
|
57
|
+
exp_days = kwargs.get('exp_days', 1)
|
|
58
|
+
exp_hours = kwargs.get('exp_hours')
|
|
59
|
+
if exp_hours and isinstance(exp_hours, int) and exp_days == 1:
|
|
60
|
+
exp_time = datetime.datetime.utcnow() + datetime.timedelta(hours=int(exp_hours), seconds=30)
|
|
61
|
+
else:
|
|
62
|
+
exp_time = datetime.datetime.utcnow() + datetime.timedelta(days=int(exp_days), seconds=30)
|
|
63
|
+
|
|
64
|
+
payload = {
|
|
65
|
+
'exp': exp_time,
|
|
66
|
+
'nbf': datetime.datetime.utcnow() - datetime.timedelta(seconds=10),
|
|
67
|
+
'iat': datetime.datetime.utcnow(),
|
|
68
|
+
'iss': 'auth: ss',
|
|
69
|
+
'sub': 'my token',
|
|
70
|
+
'id': '15618718060',
|
|
71
|
+
'data': {
|
|
72
|
+
'user_id': kwargs.get('user_id', ''),
|
|
73
|
+
'username': kwargs.get('username', ''),
|
|
74
|
+
'nickname': kwargs.get('nickname', ''),
|
|
75
|
+
'email': kwargs.get('email', ''),
|
|
76
|
+
'is_superuser': kwargs.get('is_superuser', False)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return jwt.encode(
|
|
80
|
+
payload,
|
|
81
|
+
self.token_secret,
|
|
82
|
+
algorithm='HS256'
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
except Exception as e:
|
|
86
|
+
return e
|
|
87
|
+
|
|
88
|
+
def encode_mfa_token(self, **kwargs):
|
|
89
|
+
try:
|
|
90
|
+
exp_days = kwargs.get('exp_days', 1)
|
|
91
|
+
exp_hours = kwargs.get('exp_hours')
|
|
92
|
+
|
|
93
|
+
current_time = datetime.datetime.utcnow()
|
|
94
|
+
exp_time = (datetime.datetime.utcnow() + datetime.timedelta(hours=exp_hours) if exp_hours
|
|
95
|
+
else datetime.datetime.utcnow() + datetime.timedelta(days=exp_days)) + datetime.timedelta(
|
|
96
|
+
seconds=30)
|
|
97
|
+
|
|
98
|
+
payload = {
|
|
99
|
+
'exp': exp_time,
|
|
100
|
+
'nbf': current_time - datetime.timedelta(seconds=10),
|
|
101
|
+
'iat': current_time,
|
|
102
|
+
'data': {
|
|
103
|
+
'user_id': kwargs.get('user_id', ''),
|
|
104
|
+
'email': kwargs.get('email', '')
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return jwt.encode(payload, self.token_secret, algorithm='HS256')
|
|
109
|
+
|
|
110
|
+
except Exception as e:
|
|
111
|
+
return str(e)
|
|
112
|
+
|
|
113
|
+
def decode_auth_token(self, auth_token):
|
|
114
|
+
"""
|
|
115
|
+
验证Token
|
|
116
|
+
:param auth_token:
|
|
117
|
+
:return: dict
|
|
118
|
+
"""
|
|
119
|
+
try:
|
|
120
|
+
payload = jwt.decode(auth_token, self.token_secret, algorithms=['HS256'],
|
|
121
|
+
leeway=datetime.timedelta(seconds=10))
|
|
122
|
+
if 'data' in payload and 'user_id' in payload['data']:
|
|
123
|
+
return payload['data']
|
|
124
|
+
else:
|
|
125
|
+
raise jwt.InvalidTokenError
|
|
126
|
+
except jwt.ExpiredSignatureError:
|
|
127
|
+
return dict(status=-1, msg='Token过期')
|
|
128
|
+
except jwt.InvalidTokenError:
|
|
129
|
+
return dict(status=-2, msg='无效Token')
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def gen_md5(pd):
|
|
133
|
+
m2 = hashlib.md5()
|
|
134
|
+
m2.update(pd.encode("utf-8"))
|
|
135
|
+
return m2.hexdigest()
|
websdk2/ldap.py
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Contact : 191715030@qq.com
|
|
5
|
+
Author : shenshuo
|
|
6
|
+
Date : 2023/3/17
|
|
7
|
+
Desc : 对接LDAP登录认证
|
|
8
|
+
"""
|
|
9
|
+
import json
|
|
10
|
+
from ldap3 import Server, Connection, ALL, SUBTREE, ServerPool
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class LdapApi:
|
|
14
|
+
def __init__(self, ldap_server_host, ldap_admin_dn, ldap_admin_password, ldap_server_port=389, ldap_use_ssl=False):
|
|
15
|
+
self._ldap_admin_dn = ldap_admin_dn
|
|
16
|
+
self._ldap_admin_password = ldap_admin_password
|
|
17
|
+
# ldap_server_pool = ServerPool(["172.16.0.102",'172.16.0.103'])
|
|
18
|
+
use_ssl = True if ldap_use_ssl in ['y', 'yes', True] else False
|
|
19
|
+
self.ldap_server = Server(ldap_server_host, port=ldap_server_port, use_ssl=ldap_use_ssl)
|
|
20
|
+
|
|
21
|
+
def ldap_server_test(self):
|
|
22
|
+
try:
|
|
23
|
+
conn = Connection(self.ldap_server, user=self._ldap_admin_dn, password=self._ldap_admin_password,
|
|
24
|
+
check_names=True, lazy=False, raise_exceptions=False)
|
|
25
|
+
conn.open()
|
|
26
|
+
conn.bind()
|
|
27
|
+
return True
|
|
28
|
+
except Exception as e:
|
|
29
|
+
print("auth fail {}".format(e))
|
|
30
|
+
return False
|
|
31
|
+
|
|
32
|
+
def ldap_auth_v2(self, username, password, search_base, search_filter='cn'):
|
|
33
|
+
if not self.ldap_server_test(): return False, None, None
|
|
34
|
+
|
|
35
|
+
conn = Connection(self.ldap_server, user=self._ldap_admin_dn, password=self._ldap_admin_password,
|
|
36
|
+
check_names=True, lazy=False, raise_exceptions=False)
|
|
37
|
+
conn.open()
|
|
38
|
+
conn.bind()
|
|
39
|
+
res = conn.search(search_base=search_base, search_filter=f'({search_filter}={username})',
|
|
40
|
+
search_scope=SUBTREE, attributes=[search_filter, 'cn', 'sAMAccountName'], paged_size=5)
|
|
41
|
+
if not res: return False, None, None
|
|
42
|
+
entry = conn.response[0]
|
|
43
|
+
dn = entry['dn']
|
|
44
|
+
attr_dict = entry['attributes']
|
|
45
|
+
|
|
46
|
+
# check password by dn
|
|
47
|
+
try:
|
|
48
|
+
conn2 = Connection(self.ldap_server, user=dn, password=password, check_names=True, lazy=False,
|
|
49
|
+
raise_exceptions=False)
|
|
50
|
+
conn2.bind()
|
|
51
|
+
if conn2.result["description"] == "success":
|
|
52
|
+
try:
|
|
53
|
+
if 'email' in attr_dict and isinstance(attr_dict["email"], list) and attr_dict["email"]:
|
|
54
|
+
email = attr_dict["email"][0]
|
|
55
|
+
elif 'email' in attr_dict and not isinstance(attr_dict["email"], list) and attr_dict["email"]:
|
|
56
|
+
email = attr_dict["email"]
|
|
57
|
+
elif 'mail' in attr_dict and isinstance(attr_dict["mail"], list) and attr_dict["mail"]:
|
|
58
|
+
email = attr_dict["mail"][0]
|
|
59
|
+
elif 'mail' in attr_dict and not isinstance(attr_dict["mail"], list) and attr_dict["mail"]:
|
|
60
|
+
email = attr_dict["mail"]
|
|
61
|
+
else:
|
|
62
|
+
email = None
|
|
63
|
+
except Exception as err:
|
|
64
|
+
print(f"email fail, {err}")
|
|
65
|
+
email = None
|
|
66
|
+
|
|
67
|
+
return True, attr_dict[search_filter], email
|
|
68
|
+
else:
|
|
69
|
+
print("auth fail")
|
|
70
|
+
return False, None, None
|
|
71
|
+
except Exception as e:
|
|
72
|
+
print("auth fail {}".format(e))
|
|
73
|
+
return False, None, None
|
|
74
|
+
|
|
75
|
+
def ldap_auth_v3(self, username, password, search_base, conf_attr_dict, search_filter='cn'):
|
|
76
|
+
# 用户 密码 用户ou 映射数据 查询过滤 应和登录的账户关联
|
|
77
|
+
if not self.ldap_server_test():
|
|
78
|
+
return False, None
|
|
79
|
+
|
|
80
|
+
conn = Connection(self.ldap_server, user=self._ldap_admin_dn, password=self._ldap_admin_password,
|
|
81
|
+
check_names=True, lazy=False, raise_exceptions=False)
|
|
82
|
+
conn.open()
|
|
83
|
+
conn.bind()
|
|
84
|
+
try:
|
|
85
|
+
if isinstance(conf_attr_dict, str): conf_attr_dict = json.loads(conf_attr_dict)
|
|
86
|
+
attr_list = list(conf_attr_dict.values())
|
|
87
|
+
except Exception as err:
|
|
88
|
+
attr_list = ['cn', 'sAMAccountName']
|
|
89
|
+
res = conn.search(search_base=search_base, search_filter=f'({search_filter}={username})',
|
|
90
|
+
search_scope=SUBTREE, attributes=attr_list, paged_size=1000)
|
|
91
|
+
|
|
92
|
+
if not res:
|
|
93
|
+
return False, None
|
|
94
|
+
entry = conn.response[0]
|
|
95
|
+
dn = entry['dn']
|
|
96
|
+
attr_dict = entry['attributes']
|
|
97
|
+
|
|
98
|
+
# check password by dn
|
|
99
|
+
try:
|
|
100
|
+
conn2 = Connection(self.ldap_server, user=dn, password=password, check_names=True, lazy=False,
|
|
101
|
+
raise_exceptions=False)
|
|
102
|
+
conn2.bind()
|
|
103
|
+
if conn2.result["description"] == "success":
|
|
104
|
+
return True, {k: attr_dict.get(v) for k, v in conf_attr_dict.items()}
|
|
105
|
+
else:
|
|
106
|
+
print("auth fail 2")
|
|
107
|
+
return False, None
|
|
108
|
+
except Exception as e:
|
|
109
|
+
print(f"auth fail 3 {e}")
|
|
110
|
+
return False, None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
if __name__ == "__main__":
|
|
114
|
+
obj = LdapApi('172.16.0.102', 'cn=Manager,DC=sz,DC=com', '070068')
|
|
115
|
+
print(obj.ldap_server_test())
|
|
116
|
+
print('____________')
|
|
117
|
+
print(obj.ldap_auth_v2("yanghongfei", "123456", 'ou=opendevops,dc=sz,dc=com', 'cn'))
|
websdk2/logger.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*-coding:utf-8-*-
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import logging
|
|
6
|
+
import sys
|
|
7
|
+
import datetime
|
|
8
|
+
import tornado.log
|
|
9
|
+
|
|
10
|
+
# from tornado.options import options
|
|
11
|
+
#
|
|
12
|
+
# options.log_file_prefix = os.path.join(os.path.dirname(os.path.dirname(__file__)), f'/tmp/codo.log')
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class LogFormatter(tornado.log.LogFormatter):
|
|
16
|
+
default_msec_format = '%s.%03d'
|
|
17
|
+
|
|
18
|
+
def __init__(self):
|
|
19
|
+
super(LogFormatter, self).__init__(
|
|
20
|
+
fmt='%(color)s%(asctime)s | %(levelname)s%(end_color)s | %(filename)s:%(funcName)s:%(lineno)s - %(message)s',
|
|
21
|
+
datefmt='%Y-%m-%d %H:%M:%S.%f'
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def formatTime(self, record, datefmt=None):
|
|
25
|
+
ct = datetime.datetime.now()
|
|
26
|
+
t = ct.strftime(self.default_time_format)
|
|
27
|
+
s = self.default_msec_format % (t, record.msecs)
|
|
28
|
+
return s
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def init_logging():
|
|
32
|
+
# write file
|
|
33
|
+
[
|
|
34
|
+
i.setFormatter(LogFormatter())
|
|
35
|
+
for i in logging.getLogger().handlers
|
|
36
|
+
]
|
|
37
|
+
logging.getLogger().setLevel(logging.INFO)
|
|
38
|
+
# write stdout
|
|
39
|
+
stdout_handler = logging.StreamHandler(sys.stdout)
|
|
40
|
+
stdout_handler.setFormatter(LogFormatter())
|
|
41
|
+
logging.getLogger().addHandler(stdout_handler)
|
|
42
|
+
logging.info('[APP Logging Init] logging has been started')
|
websdk2/model_utils.py
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*-coding:utf-8-*-
|
|
3
|
+
"""
|
|
4
|
+
Author : shenshuo
|
|
5
|
+
Date : 2019年12月11日
|
|
6
|
+
Desc : models类
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Type, Union
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from sqlalchemy.orm import class_mapper
|
|
12
|
+
from sqlalchemy.ext.declarative import DeclarativeMeta
|
|
13
|
+
from sqlalchemy import text
|
|
14
|
+
from sqlalchemy.exc import IntegrityError
|
|
15
|
+
from .utils import get_contain_dict
|
|
16
|
+
from .db_context import DBContextV2 as DBContext
|
|
17
|
+
from .utils.pydantic_utils import sqlalchemy_to_pydantic, ValidationError, PydanticDelList
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def model_to_dict(model):
|
|
21
|
+
model_dict = {}
|
|
22
|
+
for key, column in class_mapper(model.__class__).c.items():
|
|
23
|
+
if isinstance(getattr(model, key), datetime):
|
|
24
|
+
model_dict[column.name] = str(getattr(model, key))
|
|
25
|
+
else:
|
|
26
|
+
model_dict[column.name] = getattr(model, key, None)
|
|
27
|
+
|
|
28
|
+
if isinstance(getattr(model, "custom_extend_column_dict", None), dict):
|
|
29
|
+
model_dict.update(**getattr(model, "custom_extend_column_dict", {}))
|
|
30
|
+
return model_dict
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def queryset_to_list(queryset, **kwargs) -> list:
|
|
34
|
+
if kwargs: return [model_to_dict(q) for q in queryset if get_contain_dict(kwargs, model_to_dict(q))]
|
|
35
|
+
return [model_to_dict(q) for q in queryset]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def GetInsertOrUpdateObj(cls: Type, str_filter: str, **kw) -> classmethod:
|
|
39
|
+
"""
|
|
40
|
+
cls: Model 类名
|
|
41
|
+
str_filter: filter的参数.eg:"name='name-14'" 必须设置唯一 支持 and or
|
|
42
|
+
**kw: 【属性、值】字典,用于构建新实例,或修改存在的记录
|
|
43
|
+
session.add(GetInsertOrUpdateObj(TableTest, "name='name-114'", age=33114, height=123.14, name='name-114'))
|
|
44
|
+
"""
|
|
45
|
+
with DBContext('r') as session:
|
|
46
|
+
existing = session.query(cls).filter(text(str_filter)).first()
|
|
47
|
+
if not existing:
|
|
48
|
+
res = cls()
|
|
49
|
+
for k, v in kw.items():
|
|
50
|
+
if hasattr(res, k):
|
|
51
|
+
setattr(res, k, v)
|
|
52
|
+
return res
|
|
53
|
+
else:
|
|
54
|
+
res = existing
|
|
55
|
+
for k, v in kw.items():
|
|
56
|
+
if hasattr(res, k):
|
|
57
|
+
setattr(res, k, v)
|
|
58
|
+
|
|
59
|
+
return res
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def insert_or_update(cls: Type[DeclarativeMeta], str_filter: str, **kwargs) -> Union[None, DeclarativeMeta]:
|
|
63
|
+
"""
|
|
64
|
+
Insert or update a record in the database.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
cls (Type[DeclarativeMeta]): Model class.
|
|
68
|
+
str_filter (str): Filter parameters. e.g., "name='name-14'". Must be unique. Supports 'and' and 'or'.
|
|
69
|
+
**kwargs: Attributes and values dictionary used to construct a new instance or modify an existing record.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Union[None, DeclarativeMeta]: Returns None if no existing record found, otherwise returns the updated or inserted record.
|
|
73
|
+
"""
|
|
74
|
+
with DBContext('r') as session:
|
|
75
|
+
existing = session.query(cls).filter(text(str_filter)).first()
|
|
76
|
+
if not existing:
|
|
77
|
+
res = cls(**kwargs)
|
|
78
|
+
for k, v in kwargs.items():
|
|
79
|
+
if hasattr(res, k):
|
|
80
|
+
setattr(res, k, v)
|
|
81
|
+
return res
|
|
82
|
+
else:
|
|
83
|
+
res = existing
|
|
84
|
+
for k, v in kwargs.items():
|
|
85
|
+
if hasattr(res, k):
|
|
86
|
+
setattr(res, k, v)
|
|
87
|
+
|
|
88
|
+
return res
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class CommonOptView:
|
|
92
|
+
def __init__(self, model, **kwargs):
|
|
93
|
+
self.model = model
|
|
94
|
+
self.pydantic_model_base = sqlalchemy_to_pydantic(model)
|
|
95
|
+
self.pydantic_model = sqlalchemy_to_pydantic(model, exclude=['id'])
|
|
96
|
+
|
|
97
|
+
def prepare(self):
|
|
98
|
+
pass
|
|
99
|
+
|
|
100
|
+
@staticmethod
|
|
101
|
+
def del_data(data) -> dict:
|
|
102
|
+
if '_index' in data:
|
|
103
|
+
del data['_index']
|
|
104
|
+
if '_rowKey' in data:
|
|
105
|
+
del data['_rowKey']
|
|
106
|
+
return data
|
|
107
|
+
|
|
108
|
+
def handle_add(self, data: dict) -> dict:
|
|
109
|
+
self.prepare()
|
|
110
|
+
data = self.del_data(data)
|
|
111
|
+
try:
|
|
112
|
+
self.pydantic_model(**data)
|
|
113
|
+
except ValidationError as e:
|
|
114
|
+
return dict(code=-1, msg=str(e))
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
with DBContext('w', None, True) as db:
|
|
118
|
+
db.add(self.model(**data))
|
|
119
|
+
except IntegrityError as e:
|
|
120
|
+
return dict(code=-2, msg='不要重复添加')
|
|
121
|
+
|
|
122
|
+
except Exception as e:
|
|
123
|
+
return dict(code=-3, msg=f'{e}')
|
|
124
|
+
|
|
125
|
+
return dict(code=0, msg="创建成功")
|
|
126
|
+
|
|
127
|
+
def handle_update(self, data: dict) -> dict:
|
|
128
|
+
self.prepare()
|
|
129
|
+
data = self.del_data(data)
|
|
130
|
+
try:
|
|
131
|
+
valid_data = self.pydantic_model_base(**data)
|
|
132
|
+
except ValidationError as e:
|
|
133
|
+
return dict(code=-1, msg=str(e))
|
|
134
|
+
|
|
135
|
+
try:
|
|
136
|
+
with DBContext('w', None, True) as db:
|
|
137
|
+
db.query(self.model).filter(self.model.id == valid_data.id).update(data)
|
|
138
|
+
|
|
139
|
+
except IntegrityError as e:
|
|
140
|
+
return dict(code=-2, msg=f'修改失败,已存在')
|
|
141
|
+
|
|
142
|
+
except Exception as err:
|
|
143
|
+
return dict(code=-3, msg=f'修改失败, {err}')
|
|
144
|
+
|
|
145
|
+
return dict(code=0, msg="修改成功")
|
|
146
|
+
|
|
147
|
+
def handle_delete(self, data: dict) -> dict:
|
|
148
|
+
self.prepare()
|
|
149
|
+
try:
|
|
150
|
+
valid_data = PydanticDelList(**data)
|
|
151
|
+
except ValidationError as e:
|
|
152
|
+
return dict(code=-1, msg=str(e))
|
|
153
|
+
|
|
154
|
+
with DBContext('w', None, True) as session:
|
|
155
|
+
session.query(self.model).filter(self.model.id.in_(valid_data.id_list)).delete(synchronize_session=False)
|
|
156
|
+
return dict(code=0, msg=f"删除成功")
|
websdk2/mqhelper.py
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# !/usr/bin/env python
|
|
2
|
+
# -*-coding:utf-8-*-
|
|
3
|
+
"""
|
|
4
|
+
Author : ming
|
|
5
|
+
date : 2017/3/3 下午9:31
|
|
6
|
+
role : rabbitMQ 操作类
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
import traceback
|
|
11
|
+
import pika
|
|
12
|
+
from .consts import const
|
|
13
|
+
from .configs import configs
|
|
14
|
+
from .error import ConfigError
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger('pika')
|
|
17
|
+
logger.setLevel(logging.WARNING)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MessageQueueBase(object):
|
|
21
|
+
def __init__(self, exchange, exchange_type, routing_key='', routing_keys=None, queue_name='', no_ack=False,
|
|
22
|
+
mq_key=const.DEFAULT_MQ_KEY):
|
|
23
|
+
mq_config = configs[const.MQ_CONFIG_ITEM][mq_key]
|
|
24
|
+
if const.MQ_ADDR not in mq_config:
|
|
25
|
+
raise ConfigError(const.MQ_ADDR)
|
|
26
|
+
if const.MQ_PORT not in mq_config:
|
|
27
|
+
raise ConfigError(const.MQ_PORT)
|
|
28
|
+
if const.MQ_VHOST not in mq_config:
|
|
29
|
+
raise ConfigError(const.MQ_VHOST)
|
|
30
|
+
if const.MQ_USER not in mq_config:
|
|
31
|
+
raise ConfigError(const.MQ_USER)
|
|
32
|
+
if const.MQ_PWD not in mq_config:
|
|
33
|
+
raise ConfigError(const.MQ_PWD)
|
|
34
|
+
self.addr = mq_config[const.MQ_ADDR]
|
|
35
|
+
self.port = int(mq_config[const.MQ_PORT])
|
|
36
|
+
self.vhost = mq_config[const.MQ_VHOST]
|
|
37
|
+
self.user = mq_config[const.MQ_USER]
|
|
38
|
+
self.pwd = mq_config[const.MQ_PWD]
|
|
39
|
+
self.__exchange = exchange
|
|
40
|
+
self.__exchange_type = exchange_type
|
|
41
|
+
self.__routing_key = routing_key
|
|
42
|
+
self.__routing_keys = routing_keys
|
|
43
|
+
self.__queue_name = queue_name
|
|
44
|
+
self.__no_ack = no_ack
|
|
45
|
+
self.__channel = None
|
|
46
|
+
self.__connection = None
|
|
47
|
+
|
|
48
|
+
def start_consuming(self, exchange_durable=False):
|
|
49
|
+
channel = self.create_channel()
|
|
50
|
+
|
|
51
|
+
channel.exchange_declare(exchange=self.__exchange, exchange_type=self.__exchange_type, durable=exchange_durable)
|
|
52
|
+
if self.__queue_name:
|
|
53
|
+
result = channel.queue_declare(queue=self.__queue_name, durable=True)
|
|
54
|
+
else:
|
|
55
|
+
result = channel.queue_declare('', exclusive=True)
|
|
56
|
+
if self.__routing_keys and isinstance(self.__routing_keys, list):
|
|
57
|
+
for binding_key in self.__routing_keys:
|
|
58
|
+
channel.queue_bind(exchange=self.__exchange, queue=result.method.queue, routing_key=binding_key)
|
|
59
|
+
else:
|
|
60
|
+
channel.queue_bind(exchange=self.__exchange, queue=result.method.queue, routing_key=self.__routing_key)
|
|
61
|
+
|
|
62
|
+
channel.basic_qos(prefetch_count=1)
|
|
63
|
+
channel.basic_consume(result.method.queue, self.call_back, self.__no_ack)
|
|
64
|
+
logging.info('[*]Queue %s started.' % (result.method.queue))
|
|
65
|
+
|
|
66
|
+
channel.start_consuming()
|
|
67
|
+
|
|
68
|
+
def __enter__(self):
|
|
69
|
+
self.__channel = self.create_channel()
|
|
70
|
+
return self
|
|
71
|
+
|
|
72
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
73
|
+
self.__connection.close()
|
|
74
|
+
|
|
75
|
+
def close_channel(self):
|
|
76
|
+
self.__connection.close()
|
|
77
|
+
|
|
78
|
+
def create_channel(self):
|
|
79
|
+
credentials = pika.PlainCredentials(self.user, self.pwd)
|
|
80
|
+
self.__connection = pika.BlockingConnection(
|
|
81
|
+
pika.ConnectionParameters(self.addr, self.port, self.vhost, credentials=credentials))
|
|
82
|
+
channel = self.__connection.channel()
|
|
83
|
+
return channel
|
|
84
|
+
|
|
85
|
+
def new_channel(self):
|
|
86
|
+
self.__channel = self.create_channel()
|
|
87
|
+
return self
|
|
88
|
+
|
|
89
|
+
def call_back(self, ch, method, properties, body):
|
|
90
|
+
try:
|
|
91
|
+
logging.info('get message')
|
|
92
|
+
self.on_message(body)
|
|
93
|
+
|
|
94
|
+
if not self.__no_ack:
|
|
95
|
+
ch.basic_ack(delivery_tag=method.delivery_tag)
|
|
96
|
+
except:
|
|
97
|
+
logging.error(traceback.format_exc())
|
|
98
|
+
if not self.__no_ack:
|
|
99
|
+
ch.basic_nack(delivery_tag=method.delivery_tag)
|
|
100
|
+
|
|
101
|
+
def on_message(self, body):
|
|
102
|
+
pass
|
|
103
|
+
|
|
104
|
+
def publish_message(self, body, durable=True, exchange_durable=False):
|
|
105
|
+
self.__channel.exchange_declare(exchange=self.__exchange, exchange_type=self.__exchange_type,
|
|
106
|
+
durable=exchange_durable)
|
|
107
|
+
if self.__queue_name:
|
|
108
|
+
result = self.__channel.queue_declare(queue=self.__queue_name)
|
|
109
|
+
else:
|
|
110
|
+
result = self.__channel.queue_declare("", exclusive=True, auto_delete=True)
|
|
111
|
+
|
|
112
|
+
self.__channel.queue_bind(exchange=self.__exchange, queue=result.method.queue)
|
|
113
|
+
|
|
114
|
+
if durable:
|
|
115
|
+
properties = pika.BasicProperties(delivery_mode=2)
|
|
116
|
+
self.__channel.basic_publish(exchange=self.__exchange, routing_key=self.__routing_key, body=body,
|
|
117
|
+
properties=properties)
|
|
118
|
+
else:
|
|
119
|
+
self.__channel.basic_publish(exchange=self.__exchange, routing_key=self.__routing_key, body=body)
|
|
120
|
+
logging.info('Publish message %s sucessfuled.' % body)
|
websdk2/program.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*-coding:utf-8-*-
|
|
3
|
+
'''
|
|
4
|
+
Author : ming
|
|
5
|
+
date : 2017/4/11 下午3:21
|
|
6
|
+
desc :
|
|
7
|
+
'''
|
|
8
|
+
import fire
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class MainProgram(object):
|
|
12
|
+
def __init__(self, progressid=''):
|
|
13
|
+
print(progressid)
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def run(cls_inst):
|
|
17
|
+
if issubclass(cls_inst, MainProgram):
|
|
18
|
+
fire.Fire(cls_inst)
|
|
19
|
+
else:
|
|
20
|
+
raise Exception('')
|