def gitlab_job(token): payload = request.get_json() object_type = payload.get('object_type') tag = payload.get('tag') job_id = payload.get('job_id') project_id = payload.get('project_id') job_status = payload.get('job_status') repository = payload.get('repository') record = Job().collection.find_one({'token': token}) if not record: return jsonify({'message': 'invalid token', 'code': 104010}), 401 if object_type != 'job': return jsonify({ 'message': 'only job event allow', 'code': 104031 }), 403 if not job_id or not project_id or job_status != 'success': return jsonify({'message': 'invalid params', 'code': 104000}), 400 if not tag: return jsonify({'message': 'only tag allow', 'code': 104032}), 403 app_info = db.collection('apps').find_one( {'_id': ObjectId(record.get('app_id'))}) if not app_info: return jsonify({ 'message': 'job must be bind with gitlab app', 'code': 104002 }), 400 params = app_info.get('params') or {} if params.get('project_id') != project_id: return jsonify({'message': 'illegal project', 'code': 104003}), 400 # if params.get('extract') == 'artifacts': # wk = Workspace() # filename = wk.get_gitlab_artifacts_file(record.get('name'), project_id, job_id) # gitlab = GitlabApi().dowload_artifact(project_id, job_id, filename) # # if params.get('extract') == 'docker': # pass integration = Integration(app_info.get('type'), params) integration.install() ansible_params = load_ansible_playbook(record) if ansible_params.get('message') is not 'ok': return jsonify(payload), 400 data = ansible_params.get('data') wk = Workspace() res = wk.load_book_from_db(name=data.get('book_name'), roles=data.get('roles')) if not res: return jsonify({ 'message': 'load book failed', 'code': 104000, }), 400 return jsonify({'message': 'ok', 'code': 0, 'data': 1})
def test_import_playbook_from_dir(self): book = self.get_data('book') self.add_data(Book, book) book_id = str(book['_id']) try: wk = Workspace() home_path = os.path.dirname(wk.get_book_space(book['name'])) result = wk.import_book_from_dir(home_path, str(book_id), prefix='/') self.assertIs(len(result) > 0, True) finally: Playbook().collection.delete_many({'book_id': book_id})
def install(self, workspace='job'): project_id = self.config.get('project_id') job_id = self.config.get('job_id') if workspace == 'job': home_path = self.job_space(project_id) else: home_path = self.build_space(project_id) Workspace.mkdir(home_path) store = home_path + '/' + job_id + '.zip' result = self.dowload_artifact(project_id, job_id, store) if not result: raise Exception('gitlab download artifacts failed') return home_path
def default_options(self): wk = Workspace() roles_path = [wk.get_galaxy_space()] return { 'verbosity': 3, 'force': False, 'role_file': None, 'keep_scm_meta': False, 'roles_path': roles_path, 'api_server': 'https://galaxy.ansible.com', 'ignore_certs': True, 'ignore_errors': False, 'no_deps': False, 'offline': False, }
def check_playbook(book_id): record = book.find_by_id(book_id) if not record: raise Exception('invalid playbook') records = Playbook.find({'book_id': book_id}) for item in records: parent = item.get('parent') if not item.get('parent'): continue p_item = Playbook.find_one({'book_id': book_id, 'path': parent}) if not p_item: p_path = os.path.dirname(parent) p_path = p_path if p_path != '/' else None data = { 'path': parent, 'parent': p_path, 'is_dir': True, 'is_edit': False, 'book_id': book_id, 'role': os.path.basename(parent), 'created_at': time.time(), } meta = Workspace.get_meta(parent) data.update(meta) data['additions'] = meta Playbook.insert_one(data) return True
def download_book(_id): record = Book.find_by_id(_id) if not record: return jsonify({'message': 'record not found', 'code': 104040}), 404 name = record.get('name') wk = Workspace() wk.load_book_from_db(name) dirname = wk.get_book_space(name) filename = name + '.zip' with NamedTemporaryFile('w+t', delete=False) as fd: make_zip(dirname, fd.name) return send_file(fd.name, attachment_filename=filename, as_attachment=True)
def sync_mirror(self): dirname = self.cache_dir + '/' + self.project if not self.is_cached(): Workspace.mkdir(dirname) git = Git(dirname) git.execute(['git', 'clone', '--mirror', self.repository, dirname]) command = ['git', 'remote', 'add', 'eclogue', self.repository] git.execute(command) self.logger.info(' '.join(command)) command = [ 'git', 'remote', 'set-url', '--push', 'origin', self.repository ] git.execute(command) self.logger.info(' '.join(command)) command = ['git', 'remote', 'update', '--prune', 'origin'] git.execute(command) self.logger.info(' '.join(command))
def get_tags(): body = request.get_json() if not body: return jsonify({ 'message': 'miss required params', 'code': 104000, }), 400 template = body.get('template') listtags = template.get('listtags') listtasks = template.get('listtasks') if not listtags or not listtasks: return jsonify({ 'message': 'invalid params', 'code': 104001, }), 400 payload = load_ansible_playbook(body) if payload.get('message') is not 'ok': return jsonify(payload), 400 data = payload.get('data') options = data.get('options') wk = Workspace() with build_book_from_db(name=data.get('book_name'), roles=data.get('roles')) as bookspace: if not bookspace: return jsonify({ 'message': 'book not found', 'code': 104000, }), 400 entry = wk.get_book_entry(data.get('book_name'), data.get('entry')) play = PlayBookRunner([data['inventory']], options) play.run(entry) return jsonify({ 'message': 'ok', 'code': 0, 'data': { 'tags': list(play.tags), 'tasks': list(play.tasks), } })
def install_book_from_dir(dirname, book_id): wk = Workspace() bucket = wk.import_book_from_dir(dirname, book_id) playbooks = Playbook.find({'book_id': book_id}) files = map(lambda i: i['path'], bucket) paths = map(lambda i: i['path'], playbooks) diff = list(set(paths) - set(files)) for item in diff: Playbook.delete_one({'book_id': book_id, 'path': item}) mapping = {} map(lambda i: {mapping['path']: i}, playbooks) for item in bucket: record = mapping.get(item['path']) if not record: Playbook.insert_one(item) continue if record['additions']: item['additions'].update(record['additions']) Playbook.update_one({'_id': record['_id']}, {'$set': item})
def install(self, workspace='job'): app_path = self.image.replace(':', '/') if workspace == 'job': home_path = self.job_space(app_path) else: home_path = self.build_space(app_path) working_dir = self.config.get('working_dir') Workspace.mkdir(home_path) filename = md5(str(uuid.uuid4())) store = home_path + '/' + filename + '.tar' with open(store, 'wb') as tar: bits, stat = self.get_archive(working_dir) for chunk in bits: tar.write(chunk) extract(store, home_path) os.unlink(store) # @todo store to mongodb gridfs if self.config.get('task_id'): pass
def __init__(self, options, build_type='job'): self.options = options repository, project, version = self.parse_repository() self.repository = repository self.project = project self.version = version self.cache_dir = Workspace().get_vcs_space('git') self.build_type = build_type self.workspace = self.cwd self.git = Git(working_dir=self.cwd) self.refs = None self.logger = get_logger('console')
def load_book_from_db(self, name, roles=None): wk = Workspace() workspace = wk.workspace wk.check_workspace() books = db.collection('playbook').find({ 'book_name': name }).sort('seq_no', pymongo.ASCENDING) for item in books: if roles: folder = item.get('name') if folder and folder not in roles: continue filename = workspace + item['path'] if item['is_dir']: if os.path.isdir(filename): continue else: os.mkdir(filename, 0o600) else: if os.path.isfile(filename): file_hash = self.file_md5(filename) if item.get('md5') and item['md5'] == file_hash: continue dirname = os.path.dirname(filename) if not os.path.exists(dirname): os.makedirs(dirname) if item['is_edit']: db.collection('playbook').update_one( {'_id': item['_id']}, {'$set': { 'md5': md5(item['content'].encode('utf8')) }}) with open(filename, 'w') as stream: stream.write(item['content']) else: with open(filename, 'wb') as stream: db.fs_bucket().download_to_stream( item['file_id'], stream) return books
def check_job(_id): record = Job.find_one({'_id': ObjectId(_id)}) if not record: return jsonify({'message': 'job not found', 'code': 104001}), 400 body = {'template': record.get('template'), 'extra': record.get('extra')} payload = load_ansible_playbook(body) if payload.get('message') is not 'ok': return jsonify(payload), 400 data = payload.get('data') options = data.get('options') private_key = data.get('private_key') wk = Workspace() res = wk.load_book_from_db(name=data.get('book_name'), roles=data.get('roles')) if not res: return jsonify({ 'message': 'book not found', 'code': 104000, }), 400 entry = wk.get_book_entry(data.get('book_name'), data.get('entry')) with NamedTemporaryFile('w+t', delete=True) as fd: key_text = get_credential_content_by_id(private_key, 'private_key') if not key_text: return jsonify({ 'message': 'invalid private_key', 'code': 104033, }), 401 fd.write(key_text) fd.seek(0) options['private_key'] = fd.name play = PlayBookRunner(data['inventory'], options) play.run(entry) result = play.get_result() return jsonify({'message': 'ok', 'code': 0, 'data': result})
def build_book_from_db(name, roles=None, build_id=None, history_id=None): bookspace = '' wk = Workspace() try: if history_id: bookspace = wk.build_book_from_history(history_id) else: bookspace = wk.load_book_from_db(name, roles=roles, build_id=build_id) yield bookspace finally: if bookspace: wk.remove_directory(bookspace)
def setup(): wk = Workspace() workspace = wk.workspace check_workspace() if not os.path.exists(workspace): os.makedirs(workspace, 0o755) books = db.collection('playbook').find().sort('path', pymongo.ASCENDING) # books = collection_array(books) start = time.time() for item in books: filename = workspace + item['path'] if item['is_dir']: if os.path.isdir(filename): continue else: os.makedirs(filename, 0o755) else: if os.path.isfile(filename): file_hash = file_md5(filename) if item.get('md5') and item['md5'] == file_hash: continue dirname = os.path.dirname(filename) if not os.path.exists(dirname): os.makedirs(dirname) if item['is_edit']: db.collection('playbook').update_one({'_id': item['_id']}, {'$set': {'md5': md5(item['content'])}}) with open(filename, 'w+') as stream: stream.write(item['content']) else: with open(filename, 'wb') as stream: db.fs_bucket().download_to_stream(item['file_id'], stream) end = time.time() return jsonify({ "message": "ok", "code": 0, 'runtime': end - start })
def install(self, book_id=None): """ copy from ansible-galaxy uses the args list of roles to be installed, unless -f was specified. The list of roles can be a name (which will be downloaded via the galaxy API and github), or it can be a local .tar.gz file. """ role_file = self.options.role_file if len(self.repo) == 0 and role_file is None: # the user needs to specify one of either --role-file or specify a single user/role name raise AnsibleOptionsError("- you must specify a user/role name or a roles file") no_deps = self.options.no_deps force = self.options.force roles_left = [] if role_file: try: f = open(role_file, 'r') if role_file.endswith('.yaml') or role_file.endswith('.yml'): try: required_roles = yaml.safe_load(f.read()) except Exception as e: raise AnsibleError("Unable to load data from the requirements file: %s" % role_file) if required_roles is None: raise AnsibleError("No roles found in file: %s" % role_file) for role in required_roles: if "include" not in role: role = RoleRequirement.role_yaml_parse(role) if "name" not in role and "scm" not in role: raise AnsibleError("Must specify name or src for role") roles_left.append(GalaxyRole(self.galaxy, **role)) else: with open(role["include"]) as f_include: try: roles_left += [ GalaxyRole(self.galaxy, **r) for r in (RoleRequirement.role_yaml_parse(i) for i in yaml.safe_load(f_include)) ] except Exception as e: msg = "Unable to load data from the include requirements file: %s %s" raise AnsibleError(msg % (role_file, e)) else: raise AnsibleError("Invalid role requirements file") f.close() except (IOError, OSError) as e: raise AnsibleError('Unable to open %s: %s' % (role_file, str(e))) else: # roles were specified directly, so we'll just go out grab them # (and their dependencies, unless the user doesn't want us to). for rname in self.repo: role = RoleRequirement.role_yaml_parse(rname.strip()) roles_left.append(GalaxyRole(self.galaxy, **role)) installed_role = [] for role in roles_left: # only process roles in roles files when names matches if given if role_file and self.repo and role.name not in self.repo: print('Skipping role %s' % role.name) continue # query the galaxy API for the role data if role.install_info is not None: if role.install_info['version'] != role.version or force: if force: print('- changing role %s from %s to %s' % (role.name, role.install_info['version'], role.version or "unspecified")) role.remove() else: print('- %s (%s) is already installed - use --force to change version to %s' % (role.name, role.install_info['version'], role.version or "unspecified")) installed_role.append(role.name) continue else: if not force: print('- %s is already installed, skipping.' % str(role)) continue try: installed = role.install() if installed and book_id: wk = Workspace() documents = wk.import_book_from_dir(os.path.dirname(role.path), book_id) for doc in documents: if doc.get('role') != 'entry': doc['path'] = '/roles' + doc.get('path') print(doc['path']) Playbook().collection.update_one({'path': doc.get('path')}, {'$set': doc}, upsert=True) except AnsibleError as e: print("- %s was NOT installed successfully: %s " % (role.name, str(e))) # self.exit_without_ignore() continue # install dependencies, if we want them if not no_deps and installed: if not role.metadata: print("Meta file %s is empty. Skipping dependencies." % role.path) else: role_dependencies = role.metadata.get('dependencies') or [] for dep in role_dependencies: logger.debug('Installing dep %s' % dep) dep_req = RoleRequirement() dep_info = dep_req.role_yaml_parse(dep) dep_role = GalaxyRole(self.galaxy, **dep_info) if '.' not in dep_role.name and '.' not in dep_role.src and dep_role.scm is None: # we know we can skip this, as it's not going to # be found on galaxy.ansible.com continue if dep_role.install_info is None: if dep_role not in roles_left: print('- adding dependency: %s' % str(dep_role)) roles_left.append(dep_role) else: print('- dependency %s already pending installation.' % dep_role.name) else: if dep_role.install_info['version'] != dep_role.version: print( '- dependency %s from role %s differs from already installed version (%s), skipping' % (str(dep_role), role.name, dep_role.install_info['version'])) else: print('- dependency %s is already installed, skipping.' % dep_role.name) if not installed: print("- %s was NOT installed successfully." % role.name) # self.exit_without_ignore() for role in installed_role: wk = Workspace() # wk.import_book_from_dir(self.options.roles_path) return 0
def add_jobs(): """ add job TODO(sang) :return: json """ body = request.get_json() user = login_user if not body: return jsonify({ 'message': 'miss required params', 'code': 104000, }), 400 job_type = body.get('type') if job_type == 'adhoc': return add_adhoc() current_id = body.get('currentId') record = None if current_id: record = Job.find_by_id(current_id) if not record: return jsonify({'message': 'job not found', 'code': 104044}), 400 payload = load_ansible_playbook(body) if payload.get('message') is not 'ok': return jsonify(payload), 400 data = payload.get('data') options = data.get('options') is_check = body.get('check') private_key = data.get('private_key') wk = Workspace() res = wk.load_book_from_db(name=data.get('book_name'), roles=data.get('roles')) if not res: return jsonify({ 'message': 'book not found', 'code': 104000, }), 400 entry = wk.get_book_entry(data.get('book_name'), data.get('entry')) dry_run = bool(is_check) options['check'] = dry_run if dry_run: with NamedTemporaryFile('w+t', delete=True) as fd: if private_key: key_text = get_credential_content_by_id( private_key, 'private_key') if not key_text: return jsonify({ 'message': 'invalid private_key', 'code': 104033, }), 401 fd.write(key_text) fd.seek(0) options['private_key'] = fd.name play = PlayBookRunner(data['inventory'], options, callback=CallbackModule()) play.run(entry) return jsonify({ 'message': 'ok', 'code': 0, 'data': { 'result': play.get_result(), 'options': options } }) name = data.get('name') existed = Job.find_one({'name': name}) if existed and not current_id: return jsonify({ 'message': 'name existed', 'code': 104001, }), 400 token = str(base64.b64encode(bytes(current_request_id(), 'utf8')), 'utf8') new_record = { 'name': name, 'type': 'playbook', 'token': token, 'description': data.get('description'), 'book_id': data.get('book_id'), 'template': data.get('template'), 'extra': data.get('extra'), 'entry': data['entry'], 'status': data['status'], 'maintainer': [user.get('username')], 'created_at': int(time.time()), 'updated_at': datetime.datetime.now().isoformat(), } if record: Job.update_one({'_id': record['_id']}, update={'$set': new_record}) else: Job.insert_one(new_record) return jsonify({ 'message': 'ok', 'code': 0, })
def playbook(payload): payload = payload or {} print(payload) book_id = payload.get('book_id') cmd = payload.get('cmd') if not book_id and not cmd: emit('playbook', {'code': 1404, 'message': 'invalid params'}) book = Book.find_by_id(book_id) if not book: emit('playbook', {'code': 1404, 'message': 'book not found'}) args = cmd.lstrip().split() allow_cmd = ['ls', 'll', 'cat', 'ansible-playbook', 'cd', 'pwd'] if args[0] not in allow_cmd: return emit('playbook', {'code': 1403, 'message': 'invalid command'}) # with build_book_from_db(book.get('name')) as cwd: cwd = payload.get('cwd') or '' cwd = cwd.strip('/') wk = Workspace() book_space = wk.load_book_from_db(book['name']) try: if args[0] == 'ansible-playbook': task_id = dispatch( book_id, 'entry.yml', {'options': 'ansible-playbook -i hosts entry.yml -t test'}) if not task_id: return emit('playbook', {'message': ''}) print('fuckkkkkkkkkkkkkk', task_id) return emit( 'book_task', { 'code': 0, 'type': 'task', 'message': 'waiting for task launch...', 'data': { 'state': 'pending', 'taskId': str(task_id), } }) cwd = os.path.join(book_space, cwd) if args[0] == 'cd': if not args[1]: return emit({'code': 1400, 'message': 'invalid args'}) cwd = os.path.join(cwd, './' + args[1]) cwd = os.path.realpath(cwd) if len(cwd) < len(book_space): cwd = book_space args = ['ls', '-a'] process = subprocess.Popen( args, cwd=cwd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) stdout, stderr = process.communicate() emit( 'playbook', { 'code': 0, 'result': { 'stdout': stdout.decode().replace(book_space, ''), 'stderr': stdout.decode().replace(book_space, ''), 'cwd': cwd.replace(book_space, '') } }) except Exception as err: print(err) emit('playbook', { 'code': 1500, 'message': str(err).replace(book_space, '') })
def add_book(): params = request.get_json() or request.form if not params: return jsonify({ 'message': 'invalid params', 'code': 154000, }), 400 name = params.get('name') if not name: return jsonify({ 'message': 'name param required', 'code': 154001, }), 400 existed = Book.find_one({'name': name}) if existed: return jsonify({ 'message': 'book exist', 'code': 154003, }), 400 description = params.get('description') status = params.get('status', 0) book_id = params.get('_id') import_type = params.get('importType') repo = params.get('repo') maintainer = params.get('maintainer', []) readonly = params.get('readonly', False) if book_id: record = Book.find_by_id(book_id) if not record: return jsonify({ 'message': 'record not found', 'code': 154041, }), 404 else: data = { 'name': name, 'readonly': readonly, 'description': description, 'maintainer': maintainer, 'import_type': import_type, 'repo': repo, 'created_at': int(time.time()) } result = Book.insert_one(data) book_id = result.inserted_id if import_type == 'galaxy' and repo: galaxy = AnsibleGalaxy([repo]) galaxy.install(book_id) logger.info('import galaxy', extra={'repo': repo}) elif import_type == 'git' and repo: git = GitDownload({'repository': repo}) dest = git.install() Workspace().import_book_from_dir(dest, book_id, exclude=['.git']) data = { 'readonly': readonly, 'description': description, 'maintainer': maintainer, 'import_type': import_type, 'repo': repo, 'status': int(status), 'updated_at': time.time(), } Book.update_one({'_id': ObjectId(book_id)}, {'$set': data}, upsert=True) data['_id'] = book_id return jsonify({ 'message': 'ok', 'code': 0, 'data': data, })
def run_playbook_task(_id, request_id, username, history_id, **kwargs): db = Mongo() record = Job.find_by_id(ObjectId(_id)) task_record = TaskModel.find_one({'request_id': request_id}) if not task_record: return False start_at = time() state = 'progressing' result = '' task_id = task_record.get('_id') job_id = task_record.get('job_id') old_stdout = sys.stdout old_stderr = sys.stderr sys.stderr = sys.stdout = temp_stdout = Reporter(str(task_id)) try: if history_id: history = db.collection('build_history').find_one( {'_id': ObjectId(history_id)}) record = history['job_info'] kwargs = task_record.get('kwargs') template = record.get('template') body = { 'template': record.get('template'), 'extra': record.get('extra') } payload = load_ansible_playbook(body) if payload.get('message') is not 'ok': raise Exception('load ansible options error: ' + payload.get('message')) app_id = template.get('app') if app_id: app_info = Application.find_by_id(ObjectId(app_id)) if not app_info: raise Exception('app not found: {}'.format(app_id)) app_type = app_info.get('type') app_params = app_info.get('params') if kwargs: app_params.update(kwargs) integration = Integration(app_type, app_params) integration.install() data = payload.get('data') options = data.get('options') private_key = data.get('private_key') wk = Workspace() roles = data.get('roles') if history_id: bookspace = wk.build_book(history_id) else: bookname = data.get('book_name') bookspace = wk.load_book_from_db(name=bookname, roles=roles, build_id=task_id) if not bookspace or not os.path.isdir(bookspace): raise Exception('install playbook failed, book name: {}'.format( data.get('book_name'))) entry = os.path.join(bookspace, data.get('entry')) with NamedTemporaryFile('w+t', delete=False) as fd: if private_key: key_text = get_credential_content_by_id( private_key, 'private_key') if not key_text: raise Exception('invalid private_key') fd.write(key_text) fd.seek(0) options['private-key'] = fd.name options['tags'] = ['uptime'] options['verbosity'] = 2 inventory = data.get('inventory') logger.info('ansible-playbook run load inventory: \n{}'.format( yaml.safe_dump(inventory))) play = PlayBookRunner(data.get('inventory'), options, job_id=job_id) play.run(entry) result = play.get_result() builds = db.collection('build_history').count({'job_id': _id}) state = 'finish' # @todo if builds > cache_result_numer: last_one = db.collection('build_history').find_one( {'job_id': _id}, sort=[('_id', 1)]) if last_one: db.fs().delete(last_one.get('file_id')) db.collection('build_history').delete_one( {'_id': last_one['_id']}) with TemporaryDirectory() as dir_name: bookname = data.get('book_name') zip_file = os.path.join(dir_name, bookname) zip_file = make_zip(bookspace, zip_file) with open(zip_file, mode='rb') as stream: filename = bookname + '.zip' file_id = db.save_file(filename=filename, fileobj=stream) store_info = { 'task_id': str(task_id), 'file_id': str(file_id), 'job_id': str(_id), 'job_info': record, 'filename': filename, 'created_at': time(), 'kwargs': kwargs, } db.collection('build_history').insert_one(store_info) shutil.rmtree(bookspace) except Exception as e: result = str(e) extra = {'task_id': task_id} logger.error('run task with exception: {}'.format(str(e)), extra=extra) state = 'error' extra_options = record.get('extra') user = User.find_one({'username': username}) if user: user_id = str(user['_id']) notification = extra_options.get('notification') message = '[error]run job: {}, message: {}'.format( record.get('name'), str(e)) sys.stdout.write(message) if notification and type(notification) == list: Notify().dispatch(user_id=user_id, msg_type='task', content=message, channel=notification) finally: content = temp_stdout.getvalue() temp_stdout.close(True) sys.stdout = old_stdout sys.stderr = old_stderr finish_at = time() update = { '$set': { 'start_at': start_at, 'finish_at': finish_at, 'state': state, 'duration': finish_at - start_at, 'result': result, } } TaskModel.update_one({'_id': task_id}, update=update) trace = { 'task_id': str(task_id), 'request_id': request_id, 'username': username, 'content': str(content), 'created_at': time(), } db.collection('task_logs').insert_one(trace)
def edit_file(_id): """ edit playbook file @todo add lock :param _id: ObjectId string :return: json """ params = request.get_json() or request.form if not params: return jsonify({ 'message': 'invalid params', 'code': 154000, }), 400 edit_type = params.get('type') if edit_type == 'upload': return upload_file(_id) name = params.get('name') role = params.get('role') description = params.get('description') status = params.get('status', 1) maintainer = params.get('maintainer', []) can_edit = params.get('is_edit') is_dir = params.get('is_dir') is_encrypt = params.get('is_encrypt') folder = params.get('folder') register = params.get('register') content = params.get('content') record = Playbook.find_by_id(_id) if not record: return jsonify({ 'message': 'record not found', 'code': 154041, }), 404 data = { 'status': status, } if name: data['name'] = name if role: data['role'] = role if folder: data['folder'] = folder if content: data['content'] = content data['md5'] = md5(content) if description: data['description'] = description if maintainer: data['maintainer'] = maintainer if can_edit is not None: data['is_edit'] = bool(is_edit) data['is_encrypt'] = bool(is_encrypt) if is_dir is not None: data['is_dir'] = bool(is_dir) if register: c_ids = map(lambda i: ObjectId(i), register) where = {'_id': {'$in': c_ids}} register_config = Configuration.find(where) if not register_config: return jsonify({ 'message': 'invalid register config', 'code': 154042, }), 404 data['register'] = register Playbook.update_one({'_id': ObjectId(_id)}, {'$set': data}, upsert=True) data['_id'] = _id book = Book.find_one({'_id': ObjectId(record['book_id'])}) wk = Workspace() wk.write_book_file(book.get('name'), record) return jsonify({ 'message': 'ok', 'code': 0, 'data': data, })