取消 ReferenceField 字段,改用字符串字段存储对象id,手动关联,接口同步修改
This commit is contained in:
parent
7cb3848751
commit
8d54f9e8fd
|
@ -13,3 +13,11 @@ def is_ipaddr(ip):
|
|||
ipaddress.ip_address(ip)
|
||||
except:
|
||||
raise mongo.ValidationError('The value must be a ip address')
|
||||
|
||||
|
||||
def is_hex_string(string: str):
|
||||
"""校验 hex 字符串(十六进制)"""
|
||||
try:
|
||||
int(string, 16)
|
||||
except:
|
||||
raise mongo.ValidationError('The value must be a hex string')
|
||||
|
|
|
@ -83,6 +83,8 @@ AgentServerFields = {
|
|||
"is_cross": fields.Boolean,
|
||||
# "channel_id": fields.String,
|
||||
"project": fields.String,
|
||||
"project_name": fields.String,
|
||||
"project_fork": fields.String,
|
||||
"public_ip": fields.String,
|
||||
"private_ip": fields.String,
|
||||
# "host_id": fields.String,
|
||||
|
|
|
@ -2,7 +2,7 @@ import mongoengine as mongo
|
|||
|
||||
from settings import common
|
||||
from common.document import DocumentBase
|
||||
from common.validator import isalnum
|
||||
from common.validator import isalnum, is_hex_string
|
||||
|
||||
from asset.models import Host
|
||||
|
||||
|
@ -44,9 +44,9 @@ class Version(mongo.EmbeddedDocument):
|
|||
class Channel(DocumentBase):
|
||||
"""渠道"""
|
||||
# spid项目内唯一
|
||||
project = mongo.ReferenceField(Project, reverse_delete_rule=mongo.NULLIFY)
|
||||
project_id = mongo.StringField(max_length=128, required=True, validation=is_hex_string)
|
||||
name = mongo.StringField(max_length=32, default="")
|
||||
spid = mongo.StringField(max_length=3, min_length=3, required=True, unique_with="project", validation=isalnum)
|
||||
spid = mongo.StringField(max_length=3, min_length=3, required=True, unique_with="project_id", validation=isalnum)
|
||||
version = mongo.EmbeddedDocumentField(Version) # 缺失时获取对象的此字段为 None
|
||||
|
||||
# 项目的代码仓库地址
|
||||
|
@ -64,6 +64,20 @@ class Channel(DocumentBase):
|
|||
"""渠道 spid 在 CROSS_SPID_SET,表示跨服"""
|
||||
return self.spid in common.CROSS_SPID_SET
|
||||
|
||||
@property
|
||||
def project(self):
|
||||
if self.project_id:
|
||||
return Project.objects(id=self.project_id).first()
|
||||
return None
|
||||
|
||||
@project.setter
|
||||
def project(self, val):
|
||||
if isinstance(val, str):
|
||||
assert Project.objects(id=val).first(), f"对象不存在,id={val}"
|
||||
self.project_id = val
|
||||
if isinstance(val, Project):
|
||||
self.project_id = str(val.id)
|
||||
|
||||
|
||||
class Server(DocumentBase):
|
||||
"""服务"""
|
||||
|
@ -77,12 +91,13 @@ class Server(DocumentBase):
|
|||
"error": "异常"
|
||||
}
|
||||
|
||||
num = mongo.IntField(required=True, unique_with="channel")
|
||||
channel = mongo.ReferenceField(Channel)
|
||||
num = mongo.IntField(required=True, unique_with="channel_id")
|
||||
# 关联channel表,保存是一个channel._id的hex字符串
|
||||
channel_id = mongo.StringField(max_length=128, required=True, validation=is_hex_string)
|
||||
status = mongo.StringField(max_length=12, choices=STATUS.keys(), required=True, default="running")
|
||||
|
||||
# 机器字段,TODO 先允许为空
|
||||
host = mongo.ReferenceField(Host, null=True)
|
||||
host_id = mongo.StringField(max_length=128, null=True, validation=is_hex_string)
|
||||
domain = mongo.StringField(max_length=128, required=False, default="")
|
||||
port = mongo.IntField()
|
||||
version = mongo.EmbeddedDocumentField(Version)
|
||||
|
@ -106,17 +121,38 @@ class Server(DocumentBase):
|
|||
return ""
|
||||
|
||||
@property
|
||||
def channel_id(self):
|
||||
if self.channel:
|
||||
return self.channel.id
|
||||
def channel(self):
|
||||
"""非强关联,方便取出channel对象"""
|
||||
if self.channel_id:
|
||||
return Channel.objects(id=self.channel_id).first()
|
||||
return ""
|
||||
|
||||
@channel.setter
|
||||
def channel(self, val):
|
||||
if isinstance(val, str):
|
||||
assert Channel.objects(id=val).first(), f"对象不存在,id={val}"
|
||||
self.channel_id = val
|
||||
if isinstance(val, Channel):
|
||||
self.channel_id = str(val.id)
|
||||
|
||||
@property
|
||||
def project(self):
|
||||
if self.channel:
|
||||
if self.channel and self.channel.project:
|
||||
return self.channel.project.fullname
|
||||
return ""
|
||||
|
||||
@property
|
||||
def project_name(self):
|
||||
if self.channel and self.channel.project:
|
||||
return self.channel.project.name
|
||||
return ""
|
||||
|
||||
@property
|
||||
def project_fork(self):
|
||||
if self.channel and self.channel.project:
|
||||
return self.channel.project.fork
|
||||
return ""
|
||||
|
||||
@property
|
||||
def public_ip(self):
|
||||
if self.host:
|
||||
|
@ -130,11 +166,20 @@ class Server(DocumentBase):
|
|||
return ""
|
||||
|
||||
@property
|
||||
def host_id(self):
|
||||
if self.host:
|
||||
return self.host.id
|
||||
def host(self):
|
||||
"""非强关联,为了取出host对象"""
|
||||
if self.host_id:
|
||||
return Host.objects(id=self.host_id).first()
|
||||
return ""
|
||||
|
||||
@host.setter
|
||||
def host(self, val):
|
||||
if isinstance(val, str):
|
||||
assert Host.objects(id=val).first(), f"对象不存在,id={val}"
|
||||
self.host_id = val
|
||||
if isinstance(val, Host):
|
||||
self.host_id = str(val.id)
|
||||
|
||||
@property
|
||||
def is_cross(self):
|
||||
if self.channel:
|
||||
|
|
|
@ -65,7 +65,7 @@ class ServerSyncView(CreateMixin):
|
|||
|
||||
if count != len(data):
|
||||
return make_response(400, 1001, "quantity mismatch")
|
||||
|
||||
project_id = str(self.project.id)
|
||||
hosts = {}
|
||||
channels = {}
|
||||
errors = []
|
||||
|
@ -89,17 +89,17 @@ class ServerSyncView(CreateMixin):
|
|||
if not created and proj not in hostObj.tags:
|
||||
hostObj.tags.append(proj)
|
||||
hostObj.save()
|
||||
host = hostObj.id
|
||||
hosts[ip] = hostObj.id
|
||||
host = str(hostObj.id)
|
||||
hosts[ip] = host
|
||||
if not channel:
|
||||
channelObj, _ = Channel.get_or_create(
|
||||
project=self.project, spid=spid, defaults=dict(project=self.project, spid=spid))
|
||||
channel = channelObj.id
|
||||
channels[spid] = channelObj.id
|
||||
project_id=project_id, spid=spid, defaults=dict(project_id=project_id, spid=spid))
|
||||
channel = str(channelObj.id)
|
||||
channels[spid] = channel
|
||||
|
||||
# 更新、创建的参数
|
||||
defaults = dict(num=num, channel=channel, host=host, version=version, port=port, status=status)
|
||||
obj, created = Server.update_or_create(defaults=defaults, num=num, channel=channel)
|
||||
defaults = dict(num=num, channel_id=channel, host_id=host, version=version, port=port, status=status)
|
||||
obj, created = Server.update_or_create(defaults=defaults, num=num, channel_id=channel)
|
||||
if created: # 创建
|
||||
app.logger.debug(f"创建 {spid}_{num} 区服信息成功")
|
||||
continue
|
||||
|
@ -119,6 +119,8 @@ class ServerSyncView(CreateMixin):
|
|||
class AgentInfo(RetrieveMixin):
|
||||
"""返回对应机器的所有信息:项目、渠道、区服内容"""
|
||||
fields = {
|
||||
# marshal schedule dict
|
||||
"schedule": F.Raw,
|
||||
"host": F.Nested(HostFields),
|
||||
"project": F.List(F.Nested(fields.ProjectFields)),
|
||||
"channel": F.List(F.Nested(fields.ChannelFields)),
|
||||
|
@ -133,11 +135,19 @@ class AgentInfo(RetrieveMixin):
|
|||
# 找到机器,不存在就404
|
||||
host = Host.objects(minion_id=agent_id).first_or_404(message="resource not found")
|
||||
# 根据机器找区服集合,返回
|
||||
servers = Server.objects(host=host).all()
|
||||
channels = servers.values_list("channel").distinct("channel")
|
||||
projects = [channel.project for channel in channels]
|
||||
servers = Server.objects(host_id=str(host.id)).all()
|
||||
channels = Channel.objects(id__in=servers.values_list("channel_id").distinct("channel_id"))
|
||||
projects = {channel.project for channel in channels}
|
||||
# 填充数据
|
||||
data = {
|
||||
# TODO schedule 这里的内容可以动态配置,为 minion 增加计划任务
|
||||
# "schedule": {
|
||||
# # 如下为刷新pillar,自动请求本接口,先测试用20s
|
||||
# "job_refresh": {
|
||||
# "function": "saltutil.refresh_pillar",
|
||||
# "seconds": 20,
|
||||
# }
|
||||
# },
|
||||
"host": host,
|
||||
"project": projects,
|
||||
"channel": channels,
|
||||
|
|
Loading…
Reference in New Issue