资产相关模型、数据库实例增删查改接口

This commit is contained in:
chenzuoqing 2021-12-07 20:29:20 +08:00
parent be95b7aa5b
commit ae5e4b5de1
8 changed files with 269 additions and 17 deletions

View File

@ -15,6 +15,7 @@ HostFields = {
"cpu_num": fields.Integer,
"cpu_core": fields.Integer,
"memory": fields.Integer,
"data": fields.Raw,
"tags": fields.List(fields.String),
"labels": fields.Raw,
"created": DateTime,
@ -25,3 +26,56 @@ HostSimpleFields = {
"public_ip": fields.String,
"private_ip": fields.String,
}
DatabaseServerFields = {
"id": fields.String,
"name": fields.String,
"domain": fields.String,
"host": fields.String,
"manage": fields.String,
"data": fields.Raw,
"tags": fields.List(fields.String),
"labels": fields.Raw,
}
DatabaseFields = {
"id": fields.String,
"name": fields.String,
"username": fields.String,
"password": fields.String,
}
MySQLInstanceFields = {
"port": fields.Integer,
"username": fields.String,
"password": fields.String,
"storage": fields.Integer,
"memory": fields.Integer,
"core": fields.Integer,
"databases": fields.List(fields.Nested(DatabaseFields))
}
# 合并 DatabaseServerFields
MySQLInstanceFields.update(DatabaseServerFields)
RedisInstanceFields = {
"port": fields.Integer,
"memory": fields.Integer,
"replicas": fields.Integer,
"password": fields.String,
}
# 合并 DatabaseServerFields
RedisInstanceFields.update(DatabaseServerFields)
MiddlewareFields = {
"host": fields.String,
"manage": fields.String,
"data": fields.Raw,
"tags": fields.List(fields.String),
"labels": fields.Raw,
}
NginxInstance = {
"port": fields.Integer,
"url": fields.String,
}
NginxInstance.update(MiddlewareFields)

View File

@ -1,7 +1,8 @@
from bson import ObjectId
import mongoengine as mongo
from common.document import DocumentBase
from common.validator import is_ipaddr
from common.validator import is_ipaddr, is_hex_string
class Host(DocumentBase):
@ -20,9 +21,83 @@ class Host(DocumentBase):
cpu_num = mongo.IntField(default=1) # cpu物理个数
cpu_core = mongo.IntField(default=1) # 每个cpu的核心数
memory = mongo.IntField(default=0) # 内存大小单位GB
data = mongo.DictField(default=dict)
# 标记和标签
tags = mongo.ListField(mongo.StringField(), default=list) # tags 默认是空列表
labels = mongo.DictField(default=dict)
created = mongo.DateTimeField()
class DatabaseServer(DocumentBase):
"""数据库服务器实例包括mysql、redis、mongodb"""
meta = {'allow_inheritance': True}
name = mongo.StringField(required=True)
domain = mongo.StringField(required=False) # 域名连接的地址
host = mongo.StringField(required=True) # 内网连接地址
# 管理者,预留
manage = mongo.StringField(max_length=128, required=True)
data = mongo.DictField(default=dict)
# 标记和标签
tags = mongo.ListField(mongo.StringField(), default=list) # tags 默认是空列表
labels = mongo.DictField(default=dict)
class Database(mongo.EmbeddedDocument):
"""数据库对象的结构描述,一个数据库实例下包含多个数据库,并授权不同用户"""
# 为数据库对象生成id非主键
# 查询方式: MySQLInstance.objects.filter(databases__id='61adfcd5726440e0eb8b28bc').first()
id = mongo.ObjectIdField(required=True, default=ObjectId)
name = mongo.StringField(required=True)
username = mongo.StringField(default="")
password = mongo.StringField(default="")
class MySQLInstance(DatabaseServer):
"""MySQL数据库实例"""
# 库名、连接的用户名密码
port = mongo.IntField(default=3306)
username = mongo.StringField(max_length=32, required=True)
password = mongo.StringField(max_length=128, required=True)
# 配置
storage = mongo.IntField(required=True)
memory = mongo.IntField(required=True)
core = mongo.IntField(required=True)
# 实例数据库,包含多个数据库
databases = mongo.EmbeddedDocumentListField(Database)
class RedisInstance(DatabaseServer):
"""Redis数据库实例"""
# 内存大小、副本数、密码
port = mongo.IntField(default=6379)
memory = mongo.IntField(required=True)
replicas = mongo.IntField(required=True, default=0)
password = mongo.StringField(max_length=128, required=True)
class Middleware(DocumentBase):
"""中间件"""
meta = {'allow_inheritance': True}
host = mongo.StringField(required=True)
# 管理者,预留
manage = mongo.StringField(max_length=128, required=True)
data = mongo.DictField(default=dict)
# 标记和标签
tags = mongo.ListField(mongo.StringField(), default=list) # tags 默认是空列表
labels = mongo.DictField(default=dict)
class NginxInstance(Middleware):
"""nginx服务器"""
port = mongo.IntField(default=80)
url = mongo.StringField(required=True)
class CDN(DocumentBase):
"""cdn域名"""
domain = mongo.StringField(max_length=256, required=True) # cdn域名
# 标记和标签
tags = mongo.ListField(mongo.StringField(), default=list) # tags 默认是空列表
labels = mongo.DictField(default=dict)

View File

@ -1,7 +1,7 @@
from flask import Blueprint
from flask_restful import Api
from asset import views
from asset.views import views
# 当前app的蓝图以app名为前缀
@ -11,3 +11,6 @@ asset_v1 = Blueprint('asset', __name__, url_prefix="/asset")
api = Api(asset_v1)
api.add_resource(views.HostViews, '/host/', endpoint="host")
api.add_resource(views.HostDetailViews, '/host/<string:pk>/', endpoint="host-detail")
api.add_resource(views.MySQLInstanceViews, '/database/mysql/', endpoint="db-mysql")
api.add_resource(views.MySQLInstanceDetail, '/database/mysql/<string:pk>/', endpoint="db-mysql-detail")

View File

@ -1,14 +0,0 @@
from asset import fields
from asset.models import Host
from common.views import ListCreateViewSet, DetailViewSet
class HostViews(ListCreateViewSet):
model = Host
fields = fields.HostFields
class HostDetailViews(DetailViewSet):
model = Host
fields = fields.HostFields

View File

127
src/asset/views/views.py Normal file
View File

@ -0,0 +1,127 @@
import datetime
from flask_restful import reqparse
from asset import fields
from asset import models
from common.views import ListCreateViewSet, DetailViewSet
from common.utils import abort_response
class HostParse:
model = None
request_parse = None
def init_parse(self):
self.request_parse = reqparse.RequestParser()
# 创建时必须,修改时可选
# self.request_parse.add_argument("public_ip", type=str, required=True,
# help='not public_ip provided', location='json')
self.request_parse.add_argument("private_ip", required=False, type=str, location='json')
self.request_parse.add_argument("minion_id", required=False, type=str, location='json')
self.request_parse.add_argument("weights", required=False, type=int, location='json')
self.request_parse.add_argument("cpu_num", required=False, type=int, location='json')
self.request_parse.add_argument("cpu_core", required=False, type=int, location='json')
self.request_parse.add_argument("memory", required=False, type=int, location='json')
self.request_parse.add_argument("tags", required=False, type=list, location='json')
self.request_parse.add_argument("labels", required=False, type=dict, location='json')
def validate_or_abort(self, args, obj=None):
"""判断是否冲突"""
exists = self.model.objects(public_ip=args.get('public_ip', '')).first()
if exists:
if obj and exists.id == obj.id: # 同个对象,不算冲突
return
# 截断请求
abort_response(400, 1001, msg="ip已存在")
def pre_create(self, args):
# 标记创建时间
args["created"] = datetime.datetime.now()
self.validate_or_abort(args)
return args
def pre_update(self, obj, args):
if "created" in args:
args.pop("created")
self.validate_or_abort(args, obj)
return args
class HostViews(HostParse, ListCreateViewSet):
model = models.Host
fields = fields.HostFields
def __init__(self):
self.init_parse()
self.request_parse.add_argument("public_ip", type=str, required=True,
help='not public_ip provided', location='json')
super(HostViews, self).__init__()
class HostDetailViews(HostParse, DetailViewSet):
model = models.Host
fields = fields.HostFields
def __init__(self):
self.init_parse()
self.request_parse.add_argument("public_ip", type=str, location='json')
super(HostDetailViews, self).__init__()
class DatabaseServerParse:
model = None
request_parse = None
def init_parse(self):
self.request_parse = reqparse.RequestParser()
self.request_parse.add_argument("domain", required=False, type=str, location='json')
self.request_parse.add_argument("tags", required=False, type=list, location='json')
self.request_parse.add_argument("labels", required=False, type=dict, location='json')
class RedisInstanceParse(DatabaseServerParse):
def init_parse(self):
super(RedisInstanceParse, self).init_parse()
self.request_parse.add_argument("port", required=False, type=int, location='json')
class MySQLInstanceViews(DatabaseServerParse, ListCreateViewSet):
model = models.MySQLInstance
fields = fields.MySQLInstanceFields
def __init__(self):
self.init_parse()
self.request_parse.add_argument("name", required=True, type=str, location='json')
self.request_parse.add_argument("host", required=True, type=str, location='json')
self.request_parse.add_argument("manage", required=True, type=str, location='json')
self.request_parse.add_argument("port", required=False, type=str, location='json')
self.request_parse.add_argument("username", required=True, type=str, location='json')
self.request_parse.add_argument("password", required=True, type=str, location='json')
self.request_parse.add_argument("storage", required=True, type=int, location='json')
self.request_parse.add_argument("memory", required=True, type=int, location='json')
self.request_parse.add_argument("core", required=True, type=int, location='json')
super(MySQLInstanceViews, self).__init__()
class MySQLInstanceDetail(DatabaseServerParse, DetailViewSet):
model = models.MySQLInstance
fields = fields.MySQLInstanceFields
def __init__(self):
"""对象修改的参数解析"""
self.init_parse()
self.request_parse.add_argument("host", required=False, type=str, location='json')
self.request_parse.add_argument("name", required=False, type=str, location='json')
self.request_parse.add_argument("manage", required=False, type=str, location='json')
self.request_parse.add_argument("port", required=False, type=str, location='json')
self.request_parse.add_argument("username", required=False, type=str, location='json')
self.request_parse.add_argument("password", required=False, type=str, location='json')
self.request_parse.add_argument("storage", required=False, type=int, location='json')
self.request_parse.add_argument("memory", required=False, type=int, location='json')
self.request_parse.add_argument("core", required=False, type=int, location='json')
super(MySQLInstanceDetail, self).__init__()

View File

@ -1,4 +1,5 @@
from flask import jsonify
from flask_restful import abort
def make_response(status, code, msg, **kwargs):
@ -16,3 +17,9 @@ def make_response(status, code, msg, **kwargs):
response = jsonify(content)
response.status_code = status
return response
def abort_response(status, code, **kwargs):
"""中断请求返回响应"""
abort(status, code=code, **kwargs)

View File

@ -125,7 +125,7 @@ class RetrieveMixin(ModelViewBase):
class UpdateMixin(ModelViewBase):
def pre_update(self, obj, args):
def pre_update(self, obj, args: dict):
"""更新前钩子"""
data = {}
for k, v in args.items():