deploy.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # @Author: wushuiyong
  4. # @Created Time : 日 1/ 1 23:43:12 2017
  5. # @Description:
  6. from sqlalchemy import String, Integer, Text, DateTime
  7. from flask import current_app
  8. # from flask_cache import Cache
  9. from datetime import datetime
  10. from walle.model.database import SurrogatePK, db, Model
  11. from walle.model.user import UserModel
  12. from walle.service.rbac.role import *
  13. from walle.service.extensions import permission
  14. # 上线单
  15. class TaskModel(SurrogatePK, Model):
  16. __tablename__ = 'tasks'
  17. current_time = datetime.now()
  18. # 状态0:新建提交,1审核通过,2审核拒绝,3上线完成,4上线失败
  19. status_new = 0
  20. status_pass = 1
  21. status_reject = 2
  22. status_success = 3
  23. status_fail = 4
  24. # 表的结构:
  25. id = db.Column(Integer, primary_key=True, autoincrement=True)
  26. name = db.Column(String(100))
  27. user_id = db.Column(Integer)
  28. project_id = db.Column(Integer)
  29. action = db.Column(Integer)
  30. status = db.Column(Integer)
  31. link_id = db.Column(String(100))
  32. ex_link_id = db.Column(String(100))
  33. servers = db.Column(Text)
  34. commit_id = db.Column(String(40))
  35. branch = db.Column(String(100))
  36. tag = db.Column(String(100))
  37. file_transmission_mode = db.Column(Integer)
  38. file_list = db.Column(Text)
  39. enable_rollback = db.Column(Integer)
  40. created_at = db.Column(DateTime, default=current_time)
  41. updated_at = db.Column(DateTime, default=current_time, onupdate=current_time)
  42. taskMdl = None
  43. def table_name(self):
  44. return self.__tablename__
  45. #
  46. # def list(self, page=0, size=10, kw=''):
  47. # data = Task.query.order_by('id').offset(int(size) * int(page)).limit(size).all()
  48. # return [p.to_json() for p in data]
  49. #
  50. # def one(self):
  51. # project_info = Project.query.filter_by(id=self.taskMdl.get('project_id')).one().to_json()
  52. # return dict(project_info, **self.taskMdl)
  53. #
  54. def list(self, page=0, size=10, kw=None):
  55. """
  56. 获取分页列表
  57. :param page:
  58. :param size:
  59. :param kw:
  60. :return:
  61. """
  62. query = TaskModel.query.filter(TaskModel.status.notin_([self.status_remove]))
  63. if kw:
  64. query = query.filter(TaskModel.name.like('%' + kw + '%'))
  65. count = query.count()
  66. data = query.order_by('id desc') \
  67. .offset(int(size) * int(page)).limit(size) \
  68. .all()
  69. task_list = []
  70. for task in data:
  71. task = task.to_json()
  72. project = ProjectModel().get_by_id(task['project_id']).to_dict()
  73. task['project_name'] = project['name'] if project else u'未知项目'
  74. task_list.append(task)
  75. return task_list, count
  76. def item(self, id=None):
  77. """
  78. 获取单条记录
  79. :param role_id:
  80. :return:
  81. """
  82. id = id if id else self.id
  83. data = self.query.filter(TaskModel.status.notin_([self.status_remove])).filter_by(id=id).first()
  84. if not data:
  85. return []
  86. task = data.to_json()
  87. project = ProjectModel().get_by_id(task['project_id']).to_dict()
  88. task['project_name'] = project['name'] if project else u'未知项目'
  89. task['project_info'] = project
  90. return task
  91. def add(self, *args, **kwargs):
  92. # todo permission_ids need to be formated and checked
  93. data = dict(*args)
  94. project = TaskModel(**data)
  95. db.session.add(project)
  96. db.session.commit()
  97. if project.id:
  98. self.id = project.id
  99. return project.id
  100. def update(self, *args, **kwargs):
  101. # todo permission_ids need to be formated and checked
  102. # a new type to update a model
  103. update_data = dict(*args)
  104. return super(TaskModel, self).update(**update_data)
  105. def remove(self, id=None):
  106. """
  107. :param role_id:
  108. :return:
  109. """
  110. id = id if id else self.id
  111. self.query.filter_by(id=id).update({'status': self.status_remove})
  112. ret = db.session.commit()
  113. return ret
  114. def to_json(self):
  115. item = {
  116. 'id': self.id,
  117. 'name': self.name,
  118. 'user_id': int(self.user_id),
  119. 'project_id': int(self.project_id),
  120. 'action': self.action,
  121. 'status': self.status,
  122. 'link_id': self.link_id,
  123. 'ex_link_id': self.ex_link_id,
  124. 'servers': self.servers,
  125. 'servers_info': ServerModel.fetch_by_id(self.servers.split(',')) if self.servers else '',
  126. 'commit_id': self.commit_id,
  127. 'branch': self.branch,
  128. 'tag': self.tag,
  129. 'file_transmission_mode': self.file_transmission_mode,
  130. 'file_list': self.file_list,
  131. 'enable_rollback': self.enable_rollback,
  132. 'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S'),
  133. 'updated_at': self.updated_at.strftime('%Y-%m-%d %H:%M:%S'),
  134. }
  135. item.update(self.enable())
  136. return item
  137. def enable(self):
  138. return {
  139. # 'enable_update': permission.enable_uid(self.user_id) or permission.enable_role(DEVELOPER),
  140. # 'enable_delete': permission.enable_uid(self.user_id) or permission.enable_role(DEVELOPER),
  141. 'enable_create': False,
  142. # 'enable_online': permission.enable_uid(self.user_id) or permission.enable_role(DEVELOPER),
  143. # 'enable_audit': permission.enable_role(DEVELOPER),
  144. 'enable_block': False,
  145. }
  146. # 上线记录表
  147. class TaskRecordModel(Model):
  148. # 表的名字:
  149. __tablename__ = 'task_records'
  150. current_time = datetime.now()
  151. # 表的结构:
  152. id = db.Column(Integer, primary_key=True, autoincrement=True)
  153. stage = db.Column(String(20))
  154. sequence = db.Column(Integer)
  155. user_id = db.Column(Integer)
  156. task_id = db.Column(Integer)
  157. status = db.Column(Integer)
  158. command = db.Column(String(200))
  159. host = db.Column(String(200))
  160. user = db.Column(String(200))
  161. success = db.Column(String(2000))
  162. error = db.Column(String(2000))
  163. created_at = db.Column(DateTime, default=current_time)
  164. updated_at = db.Column(DateTime, default=current_time, onupdate=current_time)
  165. def save_record(self, stage, sequence, user_id, task_id, status, host, user, command, success=None, error=None):
  166. record = TaskRecordModel(stage=stage, sequence=sequence, user_id=user_id,
  167. task_id=task_id, status=status, host=host, user=user, command=command,
  168. success=success, error=error)
  169. db.session.add(record)
  170. ret = db.session.commit()
  171. return ret
  172. def fetch(self, task_id):
  173. data = self.query.filter_by(task_id=task_id).order_by('id desc').all()
  174. return [p.to_json() for p in data]
  175. def to_json(self):
  176. return {
  177. 'id': self.id,
  178. 'stage': self.stage,
  179. 'sequence': self.sequence,
  180. 'user_id': self.user_id,
  181. 'task_id': self.task_id,
  182. 'status': self.status,
  183. 'host': self.host,
  184. 'user': self.user,
  185. 'command': self.command,
  186. 'success': self.success,
  187. 'error': self.error,
  188. 'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S'),
  189. 'updated_at': self.updated_at.strftime('%Y-%m-%d %H:%M:%S'),
  190. }
  191. # 环境级别
  192. class EnvironmentModel(Model):
  193. # 表的名字:
  194. __tablename__ = 'environments'
  195. status_open = 1
  196. status_close = 2
  197. current_time = datetime.now()
  198. # 表的结构:
  199. id = db.Column(Integer, primary_key=True, autoincrement=True)
  200. name = db.Column(String(20))
  201. status = db.Column(Integer)
  202. created_at = db.Column(DateTime, default=current_time)
  203. updated_at = db.Column(DateTime, default=current_time, onupdate=current_time)
  204. def list(self, page=0, size=10, kw=None):
  205. """
  206. 获取分页列表
  207. :param page:
  208. :param size:
  209. :param kw:
  210. :return:
  211. """
  212. query = self.query.filter(EnvironmentModel.status.notin_([self.status_remove]))
  213. if kw:
  214. query = query.filter(EnvironmentModel.name.like('%' + kw + '%'))
  215. count = query.count()
  216. data = query.order_by('id desc').offset(int(size) * int(page)).limit(size).all()
  217. env_list = [p.to_json() for p in data]
  218. return env_list, count
  219. def item(self, env_id=None):
  220. """
  221. 获取单条记录
  222. :param role_id:
  223. :return:
  224. """
  225. data = self.query.filter(EnvironmentModel.status.notin_([self.status_remove])).filter_by(id=self.id).first()
  226. return data.to_json() if data else []
  227. def add(self, env_name):
  228. # todo permission_ids need to be formated and checked
  229. env = EnvironmentModel(name=env_name, status=self.status_open)
  230. db.session.add(env)
  231. db.session.commit()
  232. if env.id:
  233. self.id = env.id
  234. return env.id
  235. def update(self, env_name, status, env_id=None):
  236. # todo permission_ids need to be formated and checked
  237. role = EnvironmentModel.query.filter_by(id=self.id).first()
  238. role.name = env_name
  239. role.status = status
  240. ret = db.session.commit()
  241. return ret
  242. def remove(self, env_id=None):
  243. """
  244. :param role_id:
  245. :return:
  246. """
  247. self.query.filter_by(id=self.id).update({'status': self.status_remove})
  248. ret = db.session.commit()
  249. return ret
  250. def to_json(self):
  251. item = {
  252. 'id': self.id,
  253. 'status': self.status,
  254. 'env_name': self.name,
  255. 'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S'),
  256. 'updated_at': self.updated_at.strftime('%Y-%m-%d %H:%M:%S'),
  257. }
  258. item.update(self.enable())
  259. return item
  260. def enable(self):
  261. return {
  262. 'enable_update': permission.enable_role(DEVELOPER),
  263. 'enable_delete': permission.enable_role(DEVELOPER),
  264. 'enable_create': False,
  265. 'enable_online': False,
  266. 'enable_audit': False,
  267. 'enable_block': False,
  268. }
  269. # server
  270. class ServerModel(SurrogatePK, Model):
  271. __tablename__ = 'servers'
  272. current_time = datetime.now()
  273. # 表的结构:
  274. id = db.Column(Integer, primary_key=True, autoincrement=True)
  275. name = db.Column(String(100))
  276. host = db.Column(String(100))
  277. status = db.Column(Integer)
  278. created_at = db.Column(DateTime, default=current_time)
  279. updated_at = db.Column(DateTime, default=current_time, onupdate=current_time)
  280. def list(self, page=0, size=10, kw=None):
  281. """
  282. 获取分页列表
  283. :param page:
  284. :param size:
  285. :param kw:
  286. :return:
  287. """
  288. query = self.query.filter(ServerModel.status.notin_([self.status_remove]))
  289. if kw:
  290. query = query.filter(ServerModel.name.like('%' + kw + '%'))
  291. count = query.count()
  292. data = query.order_by('id desc') \
  293. .offset(int(size) * int(page)).limit(size) \
  294. .all()
  295. server_list = [p.to_json() for p in data]
  296. return server_list, count
  297. def item(self, id=None):
  298. """
  299. 获取单条记录
  300. :param role_id:
  301. :return:
  302. """
  303. id = id if id else self.id
  304. data = self.query.filter(ServerModel.status.notin_([self.status_remove])).filter_by(id=id).first()
  305. return data.to_json() if data else []
  306. def add(self, name, host):
  307. # todo permission_ids need to be formated and checked
  308. server = ServerModel(name=name, host=host, status=self.status_available)
  309. db.session.add(server)
  310. db.session.commit()
  311. if server.id:
  312. self.id = server.id
  313. return server.id
  314. def update(self, name, host, id=None):
  315. # todo permission_ids need to be formated and checked
  316. id = id if id else self.id
  317. role = ServerModel.query.filter_by(id=id).first()
  318. if not role:
  319. return False
  320. role.name = name
  321. role.host = host
  322. ret = db.session.commit()
  323. return ret
  324. def remove(self, id=None):
  325. """
  326. :param role_id:
  327. :return:
  328. """
  329. id = id if id else self.id
  330. self.query.filter_by(id=id).update({'status': self.status_remove})
  331. ret = db.session.commit()
  332. return ret
  333. @classmethod
  334. def fetch_by_id(cls, ids=None):
  335. """
  336. 用户列表
  337. :param uids: []
  338. :return:
  339. """
  340. if not ids:
  341. return None
  342. query = ServerModel.query.filter(ServerModel.id.in_(ids))
  343. data = query.order_by('id desc').all()
  344. return [p.to_json() for p in data]
  345. def to_json(self):
  346. item = {
  347. 'id': self.id,
  348. 'name': self.name,
  349. 'host': self.host,
  350. 'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S'),
  351. 'updated_at': self.updated_at.strftime('%Y-%m-%d %H:%M:%S'),
  352. }
  353. item.update(self.enable())
  354. return item
  355. def enable(self):
  356. # current_app.logger.info(dir(permission.app))
  357. current_app.logger.info(permission.enable_uid(3))
  358. return {
  359. 'enable_update': permission.enable_role(DEVELOPER),
  360. # 'enable_delete': permission.enable_role(DEVELOPER),
  361. 'enable_create': False,
  362. 'enable_online': False,
  363. # 'enable_audit': permission.enable_role(OWNER),
  364. 'enable_block': False,
  365. }
  366. # 项目配置表
  367. class ProjectModel(SurrogatePK, Model):
  368. # 表的名字:
  369. __tablename__ = 'projects'
  370. current_time = datetime.now()
  371. status_close = 0
  372. status_open = 1
  373. # 表的结构:
  374. id = db.Column(Integer, primary_key=True, autoincrement=True)
  375. user_id = db.Column(Integer)
  376. name = db.Column(String(100))
  377. environment_id = db.Column(Integer)
  378. space_id = db.Column(Integer)
  379. status = db.Column(Integer)
  380. master = db.Column(String(100))
  381. version = db.Column(String(40))
  382. excludes = db.Column(Text)
  383. target_user = db.Column(String(50))
  384. target_port = db.Column(String(20))
  385. target_root = db.Column(String(200))
  386. target_releases = db.Column(String(200))
  387. server_ids = db.Column(Text)
  388. task_vars = db.Column(Text)
  389. prev_deploy = db.Column(Text)
  390. post_deploy = db.Column(Text)
  391. prev_release = db.Column(Text)
  392. post_release = db.Column(Text)
  393. keep_version_num = db.Column(Integer)
  394. repo_url = db.Column(String(200))
  395. repo_username = db.Column(String(50))
  396. repo_password = db.Column(String(50))
  397. repo_mode = db.Column(String(50))
  398. repo_type = db.Column(String(10))
  399. notice_type = db.Column(String(10))
  400. notice_hook = db.Column(Text)
  401. enable_audit = db.Column(Integer)
  402. created_at = db.Column(DateTime, default=current_time)
  403. updated_at = db.Column(DateTime, default=current_time, onupdate=current_time)
  404. def list(self, page=0, size=10, kw=None, space_id=None, environment_id=None):
  405. """
  406. 获取分页列表
  407. :param page:
  408. :param size:
  409. :return:
  410. """
  411. query = self.query.filter(ProjectModel.status.notin_([self.status_remove]))
  412. if kw:
  413. query = query.filter(ProjectModel.name.like('%' + kw + '%'))
  414. if environment_id:
  415. query = query.filter_by(environment_id=environment_id)
  416. if space_id:
  417. query = query.filter_by(space_id=space_id)
  418. count = query.count()
  419. data = query.order_by('id desc').offset(int(size) * int(page)).limit(size).all()
  420. list = [p.to_json() for p in data]
  421. return list, count
  422. def item(self, id=None):
  423. """
  424. 获取单条记录
  425. :param role_id:
  426. :return:
  427. """
  428. id = id if id else self.id
  429. data = self.query.filter(ProjectModel.status.notin_([self.status_remove])).filter_by(id=id).first()
  430. if not data:
  431. return []
  432. data = data.to_json()
  433. server_ids = data['server_ids']
  434. data['servers_info'] = ServerModel.fetch_by_id(map(int, server_ids.split(',')))
  435. return data
  436. def add(self, *args, **kwargs):
  437. # todo permission_ids need to be formated and checked
  438. data = dict(*args)
  439. project = ProjectModel(**data)
  440. db.session.add(project)
  441. db.session.commit()
  442. self.id = project.id
  443. return self.id
  444. def update(self, *args, **kwargs):
  445. # todo permission_ids need to be formated and checked
  446. # a new type to update a model
  447. update_data = dict(*args)
  448. return super(ProjectModel, self).update(**update_data)
  449. def remove(self, role_id=None):
  450. """
  451. :param role_id:
  452. :return:
  453. """
  454. role_id = role_id if role_id else self.id
  455. ProjectModel.query.filter_by(id=role_id).update({'status': self.status_remove})
  456. ret = db.session.commit()
  457. return ret
  458. def to_json(self):
  459. item = {
  460. 'id': self.id,
  461. 'user_id': self.user_id,
  462. 'name': self.name,
  463. 'environment_id': self.environment_id,
  464. 'space_id': self.space_id,
  465. 'status': self.status,
  466. 'master': UserModel.fetch_by_uid(self.master.split(',')) if self.master else '',
  467. 'version': self.version,
  468. 'excludes': self.excludes,
  469. 'target_user': self.target_user,
  470. 'target_port': self.target_port,
  471. 'target_root': self.target_root,
  472. 'target_releases': self.target_releases,
  473. 'server_ids': self.server_ids,
  474. 'task_vars': self.task_vars,
  475. 'prev_deploy': self.prev_deploy,
  476. 'post_deploy': self.post_deploy,
  477. 'prev_release': self.prev_release,
  478. 'post_release': self.post_release,
  479. 'keep_version_num': self.keep_version_num,
  480. 'repo_url': self.repo_url,
  481. 'repo_username': self.repo_username,
  482. 'repo_password': self.repo_password,
  483. 'repo_mode': self.repo_mode,
  484. 'repo_type': self.repo_type,
  485. 'notice_type': self.notice_type,
  486. 'notice_hook': self.notice_hook,
  487. 'enable_audit': self.enable_audit,
  488. 'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S'),
  489. 'updated_at': self.updated_at.strftime('%Y-%m-%d %H:%M:%S'),
  490. }
  491. item.update(self.enable())
  492. return item
  493. def enable(self):
  494. current_app.logger.info(self.id)
  495. return {
  496. 'enable_update': permission.is_gte_develop_or_uid(self.user_id),
  497. 'enable_delete': permission.enable_uid(self.user_id) or permission.enable_role(DEVELOPER),
  498. 'enable_create': False,
  499. 'enable_online': False,
  500. 'enable_audit': False,
  501. 'enable_block': False,
  502. }
  503. class TagModel(SurrogatePK, Model):
  504. # 表的名字:
  505. __tablename__ = 'tags'
  506. current_time = datetime.now()
  507. # 表的结构:
  508. id = db.Column(Integer, primary_key=True, autoincrement=True)
  509. name = db.Column(String(30))
  510. label = db.Column(String(30))
  511. label_id = db.Column(Integer, default=0)
  512. # users = db.relationship('Group', backref='group', lazy='dynamic')
  513. created_at = db.Column(DateTime, default=current_time)
  514. updated_at = db.Column(DateTime, default=current_time, onupdate=current_time)
  515. def list(self):
  516. data = TagModel.query.filter(TagModel.status.notin_([self.status_remove])).filter_by(id=1).first()
  517. # # return data.tag.count('*').to_json()
  518. # # print(data)
  519. # return []
  520. return data.to_json() if data else []
  521. def remove(self, tag_id):
  522. """
  523. :param role_id:
  524. :return:
  525. """
  526. TagModel.query.filter_by(id=tag_id).update({'status': self.status_remove})
  527. ret = db.session.commit()
  528. return ret
  529. def to_json(self):
  530. # user_ids = []
  531. # for user in self.users.all():
  532. # user_ids.append(user.user_id)
  533. return {
  534. 'id': self.id,
  535. 'group_id': self.id,
  536. 'group_name': self.name,
  537. # 'users': user_ids,
  538. # 'user_ids': user_ids,
  539. 'label': self.label,
  540. 'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S'),
  541. 'updated_at': self.updated_at.strftime('%Y-%m-%d %H:%M:%S'),
  542. }