예제 #1
0
 def test_delete_book(self):
     data = self.get_data('book')
     playbook = self.get_data('playbook')
     data['name'] = str(uuid.uuid4())
     result = Book.insert_one(data.copy())
     book_id = result.inserted_id
     playbook['book_id'] = str(book_id)
     Playbook.insert_one(playbook)
     self.trash += [
         [Book, book_id],
         [Playbook, playbook['_id']],
     ]
     url = self.get_api_path('/books/' + str(book_id))
     not_found_url = self.get_api_path('/books/' + str(ObjectId()))
     response = self.client.delete(not_found_url, headers=self.jwt_headers)
     self.assert404(response)
     self.assertResponseCode(response, 154041)
     response = self.client.delete(url, headers=self.jwt_headers)
     self.assert200(response)
     record = Book.find_by_id(book_id)
     self.assertEqual(record, None)
     record = Book().collection.find_one({'_id': book_id})
     self.assertIsNotNone(record)
     self.assertEqual(record['_id'], book_id)
     self.assertEqual(record['status'], -1)
     playbook_record = Playbook().collection.find_one(
         {'_id': playbook['_id']})
     self.assertIsNotNone(playbook_record)
     self.assertEqual(playbook_record['status'], -1)
예제 #2
0
def book_detail(_id):
    record = Book.find_by_id(_id)
    if not record:
        return jsonify({'message': 'record not found', 'code': 154041}), 400

    return jsonify({
        'message': 'ok',
        'code': 0,
        'data': record,
    })
예제 #3
0
파일: book.py 프로젝트: eclogue/eclogue
def dispatch(book_id, entry, payload):
    print('xxxx', book_id, entry, payload)
    book = Book.find_by_id(book_id)
    if not book:
        return False

    username = payload.get('username')
    run_id = payload.get('req_id') or str(uuid.uuid4())
    params = [book_id, run_id]
    options = payload.get('options')
    if not entry:
        return False
    if type(options) == str:
        args = options.split(' ')
        pb = PlaybookCLI(args)
        pb.init_parser()
        options, args = pb.parser.parse_args(args[1:])
        options, args = pb.post_process_args(options, args)
        options = options.__dict__
        options['entry'] = args
        for i in options['inventory']:
            if not os.path.isfile(i):
                i = os.path.basename(i)
                options['inventory'] = i
                break
    queue_name = 'book_runtime'
    func = run
    task = Task(tiger,
                func=func,
                args=params,
                kwargs=options,
                queue=queue_name,
                unique=True,
                lock=True,
                lock_key=book_id)
    run_record = {
        'book_id': book_id,
        'run_id': run_id,
        'run_by': username,
        'options': options,
        'result': '',
        'state': 'pending',
        'created_at': 1,
        'updated_at': 2,
    }
    result = Perform.insert_one(run_record)
    task.delay()

    return result.inserted_id
예제 #4
0
파일: book.py 프로젝트: eclogue/eclogue
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()
    with build_book_from_db(name) as bookspace:
        filename = name + '.zip'
        with NamedTemporaryFile('w+t', delete=False) as fd:
            make_zip(bookspace, fd.name)

            return send_file(fd.name,
                             attachment_filename=filename,
                             as_attachment=True)
예제 #5
0
파일: playbook.py 프로젝트: eclogue/eclogue
def get_playbook(_id):
    book = Book.find_by_id(_id)
    if not book or int(book.get('status') == -1):
        return jsonify({
            'message': 'invalid id',
            'code': 154001,
        }), 400

    cursor = Playbook.find({'book_id': str(book.get('_id'))})
    cursor = cursor.sort([('is_edit', pymongo.ASCENDING),
                          ('path', pymongo.ASCENDING)])
    # for item in cursor:
    #     db.collection('playbook').update_one({'_id': item['_id']}, {'$set': {'book_id': str(item.get('book_id'))}})
    return jsonify({
        'message': 'ok',
        'code': 0,
        'data': list(cursor),
    })
예제 #6
0
파일: book.py 프로젝트: eclogue/eclogue
def run(_id):
    book = Book.find_by_id(_id)
    if not book:
        return jsonify({'message': 'record not found', 'code': 10404}), 404

    payload = request.get_json()
    options = payload.get('options')
    entry = options.get('entry')
    args = options.get('args')
    req_id = str(current_request_id())
    params = {
        'username': login_user.get('username'),
        'req_id': req_id,
        'args': args,
        'options': options
    }
    result = dispatch(_id, entry, params)
    if not result:
        return jsonify({'message': 'invalid request', 'code': 104008}), 400

    return jsonify({'message': 'ok', 'code': 0, 'data': {'taskId': result}})
예제 #7
0
def delete_book(_id):
    record = Book.find_by_id(_id)
    if not record:
        return jsonify({'message': 'record not found', 'code': 154041}), 404

    update = {
        '$set': {
            'status': -1,
            'delete_at': time.time(),
            'delete_by': login_user.get('username'),
            'version': str(ObjectId()),
        }
    }
    Book.update_one({'_id': record['_id']}, update=update)
    db.collection('playbook').update_many({'book_id': str(record['_id'])},
                                          update=update)

    return jsonify({
        'message': 'ok',
        'code': 0,
    })
예제 #8
0
파일: book.py 프로젝트: eclogue/eclogue
def lint_book(_id):
    # lint book use ansibleint
    book = Book.find_by_id(_id)
    if not book:
        return jsonify({'message': 'record not found', 'code': 104040}), 404

    body = request.get_json() or {}
    tags = body.get('tags')
    skiptags = body.get('skiptags')
    tasks = body.get('tasks')
    roles = body.get('roles')
    opts = dict()
    if tags:
        opts['tags'] = tags
    if tasks:
        opts['tasks'] = tasks
    if roles:
        opts['roles'] = roles
    if skiptags:
        opts['skiptags'] = skiptags

    result = lint(_id, options=opts)
    return jsonify({'message': 'ok', 'code': 0, 'data': result})
예제 #9
0
def upload_playbook(_id):
    files = request.files
    record = Book.find_by_id(_id)
    if not record:
        return jsonify({
            "message": "book not found",
            "code": 104004,
        }), 400

    if not files:
        return jsonify({
            'message': 'invalid files params',
            'code': 104001
        }), 400

    file = files['file']
    filename = file.filename.lstrip('/')
    path_list = filename.split('/')
    filename = '/'.join(path_list[1:])
    filename = '/' + filename
    home_path, basename = os.path.split(filename)
    file_list = set(_make_path(filename))
    for dirname in file_list:
        check = Playbook.find_one({
            'book_id': _id,
            'path': dirname,
        })
        if not check:
            parent_path, name = os.path.split(dirname)
            parent_path = parent_path if parent_path != '/' else None
            parent = {
                'path': dirname,
                'is_dir': True,
                'is_edit': False,
                'book_id': _id,
                'parent': parent_path,
                'name': name,
                'created_at': time.time(),
            }
            meta = get_meta(dirname)
            parent.update(meta)
            parent['additions'] = meta
            Playbook.insert_one(parent)

    data = {
        'path': filename,
        'is_dir': False,
        'parent': home_path or None,
        'book_id': _id
    }

    can_edit = is_edit(file)
    if not can_edit:
        file_id = db.save_file(filename=filename, fileobj=file)
        data['file_id'] = file_id
    else:
        content = file.stream.read()
        content = content.decode('utf-8')
        data['is_encrypt'] = Vault.is_encrypted(content)
        if data['is_encrypt']:
            # @todo vault password
            vault = Vault()
            data['content'] = vault.encrypt_string(content)
            data['md5'] = md5(content)
        else:
            data['content'] = content
            data['md5'] = md5(content)

    meta = get_meta(data['path'])
    data.update(meta)
    data['additions'] = meta
    data['is_edit'] = can_edit
    data['created_at'] = time.time()
    data['updated_at'] = time.time()
    Playbook.update_one({
        'path': filename,
        'book_id': _id
    }, {'$set': data},
                        upsert=True)

    return jsonify({
        "message": "ok",
        "code": 0,
    })
예제 #10
0
def get_job(_id):
    username = login_user.get('username')
    is_admin = login_user.get('is_admin')
    job = Job.find_by_id(_id)
    if not job:
        return jsonify({
            'message': 'record not found',
            'code': 154001,
        }), 400

    if not is_admin and username not in job['maintainer']:
        return jsonify({'message': 'permission deny', 'code': 104031}), 403

    template = job.get('template')
    inventory_type = template.get('inventory_type')
    inventory = template.get('inventory')
    if job.get('type') == 'adhoc':
        inventory_content = parse_cmdb_inventory(inventory)
        logs = None
        task = Task.find_one({'job_id': _id})
        if task:
            log = db.collection('logs').find_one({'task_id': str(task['_id'])})
            if log:
                logs = log.get('message')

        return jsonify({
            'message': 'ok',
            'code': 0,
            'data': {
                'record': job,
                'previewContent': inventory_content,
                'logs': logs
            },
        })

    if inventory_type == 'file':
        inventory_content = parse_file_inventory(inventory)
    else:
        inventory_content = parse_cmdb_inventory(inventory)

    check_playbook(job['book_id'])
    if inventory_type == 'file':
        book = Book.find_by_id(job['book_id'])
        if not book:
            hosts = []
        else:
            hosts = get_inventory_by_book(book.get('_id'),
                                          book_name=book.get('name'))
    else:
        hosts = get_inventory_from_cmdb()

    roles = []
    condition = {
        'book_id': str(job['book_id']),
        'role': 'roles',
        'is_dir': True
    }
    parent = Playbook.find_one(condition)
    if parent:
        where = {
            'book_id': job['book_id'],
            'is_dir': True,
            'parent': parent.get('path')
        }
        cursor = Playbook.find(where)
        roles = list(cursor)

    logs = None
    task = Task.find_one({'job_id': _id})
    if task:
        log = db.collection('logs').find_one({'task_id': str(task['_id'])})
        if log:
            logs = log.get('message')

    return jsonify({
        'message': 'ok',
        'code': 0,
        'data': {
            'record': job,
            'previewContent': inventory_content,
            'hosts': hosts,
            'roles': roles,
            'logs': logs,
        },
    })
예제 #11
0
파일: book.py 프로젝트: eclogue/eclogue
def run(book_id, run_id, **options):
    perform = Perform.find_one({'run_id': run_id})
    book = Book.find_by_id(book_id)
    start_at = time.time()
    state = 'progressing'
    result = ''
    old_stdout = sys.stdout
    old_stderr = sys.stderr
    sys.stderr = sys.stdout = temp_stdout = Reporter(run_id)
    try:
        if book.get('repo') == 'git':
            vcs = GitDownload(book.get('repo_options'))
            install_path = vcs.install()
            # @todo

        book_name = book.get('name')
        with build_book_from_db(book_name, build_id=run_id) as dest:
            if not dest:
                result = 'install book failed'
                logger.warning(result)
                state = 'finish'
            else:
                inventory = options['inventory']
                if type(inventory == str):
                    inventory = os.path.join(dest, inventory)

                entry = os.path.join(dest, options['entry'].pop())
                if type(options['tags']) == str:
                    options['tags'] = options['tags'].split(',')
                options['basedir'] = dest
                print('xxxxxxxxxxxxx????', inventory, options)
                runner = PlayBookRunner(inventory, options)
                runner.run([entry])
                result = runner.get_result()
                print('result', result)
                state = 'finish'
    except Exception as err:
        result = str(err)
        extra = {'run_id': run_id}
        logger.error('run task with exception: {}'.format(result), extra=extra)
        state = 'error'
        raise err

    finally:
        content = temp_stdout.getvalue()
        temp_stdout.close(True)
        sys.stdout = old_stdout
        sys.stderr = old_stderr
        print(content)
        finish_at = time.time()
        update = {
            '$set': {
                'start_at': start_at,
                'finish_at': finish_at,
                'state': state,
                'duration': finish_at - start_at,
                'result': str(result),
                'trace': content,
            }
        }
        Perform.update_one({'_id': perform['_id']}, update=update)
예제 #12
0
파일: book.py 프로젝트: eclogue/eclogue
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,
    })
예제 #13
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, '')
        })
예제 #14
0
def lint(book_id, options, config=None):
    """
    base on ansiblelint
    refer to ansiblelint.__main__.py
    :param book_id:
    :param options:
    :param config:
    :return: None
    """
    formatter = formatters.Formatter()
    options = get_default_options(options)
    where = {
        'book_id': str(book_id),
        'role': 'entry',
    }
    entries = Playbook.find(where)
    if not entries:
        return False

    book = Book.find_by_id(book_id)
    if not book:
        return False

    if config:
        if 'quiet' in config:
            options.quiet = options.quiet or config['quiet']

        if 'parseable' in config:
            options.parseable = options.parseable or config['parseable']

        if 'parseable_severity' in config:
            options.parseable_severity = options.parseable_severity or \
                                         config['parseable_severity']

        if 'use_default_rules' in config:
            options.use_default_rules = options.use_default_rules or config['use_default_rules']

        if 'verbosity' in config:
            options.verbosity = options.verbosity + config['verbosity']

        options.exclude_paths.extend(
            config.get('exclude_paths', []))

        if 'rulesdir' in config:
            options.rulesdir = options.rulesdir + config['rulesdir']

        if 'skip_list' in config:
            options.skip_list = options.skip_list + config['skip_list']

        if 'tags' in config:
            options.tags = options.tags + config['tags']

    if options.quiet:
        formatter = formatters.QuietFormatter()

    if options.parseable:
        formatter = formatters.ParseableFormatter()

    if options.parseable_severity:
        formatter = formatters.ParseableSeverityFormatter()

    # no args triggers auto-detection mode
    # if len(args) == 0 and not (options.listrules or options.listtags):
    #     args = get_playbooks_and_roles(options=options)

    if options.use_default_rules:
        rulesdirs = options.rulesdir + [default_rulesdir]
    else:
        rulesdirs = options.rulesdir or [default_rulesdir]

    rules = RulesCollection()
    for rulesdir in rulesdirs:
        rules.extend(RulesCollection.create_from_directory(rulesdir))

    if options.listrules:
        return 0

    if options.listtags:
        return 0

    if isinstance(options.tags, six.string_types):
        options.tags = options.tags.split(',')

    skip = set()
    for s in options.skip_list:
        skip.update(str(s).split(','))

    options.skip_list = frozenset(skip)
    with build_book_from_db(book.get('name'), options.get('roles')) as book_path:
        playbooks = []
        for record in entries:
            entry = os.path.join(book_path, record['path'][1:])
            playbooks.append(entry)

        playbooks = sorted(set(playbooks))
        matches = list()
        checked_files = set()
        for playbook in playbooks:
            runner = Runner(rules, playbook, options.tags,
                            options.skip_list, options.exclude_paths,
                            options.verbosity, checked_files)
            matches.extend(runner.run())

        matches.sort(key=lambda x: (normpath(x.filename), x.linenumber, x.rule.id))
        results = []
        for match in matches:
            filename = str(match.filename)
            filename = filename.replace(book_path, '')
            results.append({
                'lineNumber': match.linenumber,
                'line': str(match.line),
                'rule': match.rule.id,
                'filename': filename,
                'message': match.message,
            })

        return results
예제 #15
0
파일: helper.py 프로젝트: eclogue/eclogue
def load_ansible_playbook(payload):
    template = payload.get('template')
    extra = payload.get('extra', {}) or {}
    if not template:
        return {
            'message': 'invalid params',
            'code': 104000,
        }
    name = template.get('name')
    if not name:
        return {
            'message': 'name required',
            'code': 104000,
        }
    entry = template.get('entry')
    if len(entry) < 2:
        return {
            'message': 'entry not found',
            'code': 104001,
        }
    book_id, entry_id = entry
    book_record = Book.find_by_id(book_id)
    if not book_record:
        return {
            'message': 'book not found',
            'code': 1040011,
        }
    entry_record = Playbook.find_by_id(entry_id)
    if not entry_record:
        return {
            'message': 'entry not found',
            'code': 104001,
        }
    inventory_type = template.get('inventory_type', 'file')
    inventory = template.get('inventory', None)
    if not inventory:
        return {'message': 'invalid param inventory', 'code': 104002}
    if inventory_type == 'file':
        inventory_record = parse_file_inventory(inventory)
    else:
        inventory_record = parse_cmdb_inventory(inventory)

    if not inventory_record:
        return {'message': 'illegal inventory', 'code': 104002}
    group_name = inventory_record.keys()
    if not inventory_record:
        return {'message': 'invalid param inventory', 'code': 104002}
    roles = template.get('roles')
    role_names = []
    if roles:
        roles = list(map(lambda i: ObjectId(i), roles))
        check = Playbook.find({
            'book_id': book_id,
            '_id': {
                '$in': roles,
            }
        })
        check = list(check)
        if not check:
            return {'message': 'invalid param role', 'code': 104003}

        role_names = list(map(lambda i: i.get('name'), check))

    extra_vars = {
        'node': list(group_name),
    }

    private_key = template.get('private_key')
    if private_key:
        key_record = Credential.find_one({
            '_id': ObjectId(private_key),
            'type': 'private_key'
        })
        if not key_record:
            return {'message': 'invalid private key', 'code': 104031}

    variables = extra.get('extraVars') or {}
    # variables.update({'node': inventory_record.get('limit')})
    if type(variables) in [dict, list]:
        variables = yaml.safe_dump(variables)

    app = template.get('app')
    if app:
        # @todo status=1
        app_record = Application.find_by_id(app)
        if not app_record:
            return {'message': 'invalid app', 'code': 104043}

        app_type = app_record.get('type')
        app_params = app_record.get('params')
        integration = Integration(app_type, app_params)
        check_app = integration.check_app_params()
        if not check_app:
            return {'message': 'invalid app', 'code': 104014}

        job_space = integration.get_job_space(name)
        if job_space and variables:
            tpl = Template(variables)
            variables = tpl.render(ECLOGUE_JOB_SPACE=job_space)

    if variables:
        variables = yaml.safe_load(variables)
        variables and extra_vars.update(variables)

    options = dict()
    extra_options = template.get('extraOptions')
    if extra_options and type(extra_options) == dict:
        options = extra_options.copy()
        # default_options = get_default_options('playbook')
        # for key, value in extra_options.items():
        #     if default_options.get(key):
        #         options[key] = value

    options['skip_tags'] = template.get('skip_tags', [])
    options['inventory'] = inventory_record
    # @todo limit
    # options['limit'] = inventory_record.get('limit', None)
    # options['credential'] = template.get('credential')
    options['limit'] = template.get('limit', 'all')
    options['forks'] = template.get('forks', 5)
    options['tags'] = template.get('tags', [])
    options['listtags'] = template.get('listtags', False)
    options['listtasks'] = template.get('listtasks', False)
    options['timeout'] = template.get('timeout', 10)
    options['verbosity'] = template.get('verbosity', 0)
    become_method = template.get('become_method')
    if become_method:
        options['become'] = 'yes'
        options['become_method'] = become_method
        if template.get('become_user'):
            options['become_user'] = template.get('become_user')

    vault_pass = template.get('vault_pass')
    if vault_pass:
        vault_record = Credential.find_one({'_id': ObjectId(vault_pass)})
        if not vault_record or not vault_record.get('body'):
            return {'message': 'invalid vault pass', 'code': 104004}

        vault_body = vault_record.get('body')
        vault = Vault({'vault_pass': config.vault.get('secret')})
        options['vault_pass'] = vault.decrypt_string(
            vault_body.get('vault_pass'))

    options['verbosity'] = template.get('verbosity', 0)
    options['diff'] = template.get('diff', False)
    # options['vault'] = template.get('vault')
    options['extra_vars'] = extra_vars
    status = int(extra.get('status', 0))

    return {
        'message': 'ok',
        'data': {
            'inventory': options['inventory'],
            'options': options,
            'name': name,
            'entry': entry_record['name'],
            'book_id': book_id,
            'book_name': book_record['name'],
            'roles': role_names,
            'inventory_type': inventory_type,
            'private_key': private_key,
            'template': template,
            'extra': extra,
            'status': status,
        }
    }
예제 #16
0
def job_detail(_id):
    query = request.args
    record = Job.find_by_id(_id)
    if not record:
        return jsonify({
            'message': 'record not found',
            'code': 104040,
        }), 404

    if record.get('type') == 'adhoc':
        template = record.get('template')
        inventory = template.get('inventory')
        inventory_content = parse_cmdb_inventory(inventory)
        template['inventory_content'] = inventory_content
    else:
        book = Book.find_by_id(record.get('book_id'))
        record['book_name'] = book.get('name')
        template = record.get('template')
        result = load_ansible_playbook(record)
        if result['message'] == 'ok':
            record['command'] = to_playbook_command(result)
            command = to_playbook_command(result)
        else:
            record['command'] = 'invalid ansible command~!'
        if template:
            app_id = template.get('app')
            if app_id:
                app = db.collection('apps').find_one({'_id': ObjectId(app_id)})
                if app:
                    template['app_name'] = app.get('name')
                    template['app_params'] = app.get('params')

            inventory_type = template.get('inventory_type')
            inventory = template.get('inventory')
            if inventory_type == 'file':
                inventory_content = parse_file_inventory(inventory)
            else:
                inventory_content = parse_cmdb_inventory(inventory)

            template['inventory_content'] = inventory_content
            role_ids = template.get('roles')
            if role_ids:
                roles = Playbook.find_by_ids(role_ids)
                template['roles'] = list(map(lambda i: i.get('name'), roles))
            record['template'] = template
    page = int(query.get('page', 1))
    size = int(query.get('pageSize', 20))
    offset = (page - 1) * size
    tasks = get_tasks_by_job(_id, offset=offset, limit=size)
    tasks = list(tasks)
    logs = []
    sort = [('_id', -1)]
    task = db.collection('tasks').find_one({'job_id': _id}, sort=sort)
    if task:
        records = db.collection('task_logs').find(
            {'task_id': str(task['_id'])})
        for item in records:
            logs.append({
                'content': str(item.get('content')),
                'created_at': item.get('created_at')
            })

    return jsonify({
        'message': 'ok',
        'code': 0,
        'data': {
            'job': record,
            'logs': logs,
            'tasks': tasks,
        }
    })
예제 #17
0
    def import_book_from_dir(self,
                             home_path,
                             book_id,
                             exclude=None,
                             links=False,
                             prefix='/'):
        """
        import dir file to db
        @todo
        """
        book_id = str(book_id)
        exclude = exclude or ['*.retry']
        bucket = []
        cursor = 0
        home_path = home_path.rstrip('/')
        parent = home_path
        book_record = Book.find_by_id(book_id)
        model = Model.build_model('playbook')
        playbooks = model.find({'book_id': book_id})
        paths = map(lambda i: i['path'], playbooks)
        paths = list(paths)
        pattern = '|'.join(exclude).replace('*', '.*?')
        home_path = '/'.join([home_path, ''])
        for current, dirs, files in os.walk(home_path,
                                            topdown=True,
                                            followlinks=links):
            pathname = current.replace(home_path, '')
            if pathname != '/':
                pathname = os.path.join(prefix, pathname)
            if exclude:
                match = re.search(pattern, pathname)
                if match:
                    continue
            if pathname in paths:
                index = paths.index(pathname)
                paths.pop(index)
            dir_record = {
                'book_id': str(book_record.get('_id')),
                'path': pathname,
                'is_dir': True,
                'is_edit': False,
                'seq_no': cursor,
                'parent': None,
                'created_at': int(time.time()),
            }
            if not current == home_path:
                dir_record['parent'] = parent
                meta = get_meta(pathname)
                dir_record.update(meta)
                dir_record['additions'] = meta
            parent = pathname
            bucket.append(dir_record)
            for file in files:
                pathname = parent.rstrip('/') + '/' + file
                if exclude:
                    match = re.match(pattern, pathname)
                    if match:
                        continue

                cursor += 1
                filename = current + '/' + file
                can_edit = is_edit(filename)
                file_record = dir_record.copy()
                file_record['is_edit'] = can_edit
                file_record['path'] = pathname
                file_record['parent'] = parent
                file_record['is_dir'] = False
                file_record['seq_no'] = cursor
                if is_edit:
                    with open(filename, 'r', encoding='utf-8') as fd:
                        file_record['content'] = fd.read()
                        file_record['md5'] = md5(file_record['content'])
                        file_record['is_encrypt'] = Vault.is_encrypted(
                            file_record['content'])
                meta = get_meta(file_record['path'])
                file_record['additions'] = meta
                file_record.update(meta)
                bucket.append(file_record)
            cursor += 1
        is_entry = filter(lambda i: i.get('role') == 'entry', bucket)
        is_entry = list(is_entry)
        # if not entry set book status to disable
        if not is_entry:
            Book.update_one({'_id': ObjectId(book_id)},
                            {'$set': {
                                'status': 0
                            }})

        for path in paths:
            model.delete_one({'book_id': book_id, 'path': path})

        mapping = {}
        map(lambda i: {mapping['path']: i}, playbooks)
        for item in bucket:
            record = mapping.get(item['path'])
            if not record:
                model.insert_one(item)
                continue
            else:
                # inherit old additions
                if record['additions']:
                    item['additions'].update(record['additions'])
                model.update_one({'_id': record['_id']}, {'$set': item})

        return bucket