Exemple #1
0
def add_folder():
    params = request.get_json()
    if not params or not params.get('id') or not params.get('folder'):
        return jsonify({
            'message': 'illegal param',
            'code': 104000,
        }), 400

    record_id = params.get('id')
    folder = params.get('folder')
    parent = params.get('parent')
    book_id = params.get('book_id')
    parent = parent if parent != '.' else '/'
    parent_path = None
    if parent != '/':
        parent_record = Playbook.find_one({
            '_id': ObjectId(record_id),
            'is_dir': True
        })
        if not parent_record:
            return jsonify({
                'message': 'invalid params',
                'code': 104001,
            }), 400

        parent_path = parent_record.get('path')

    file_path = os.path.join(parent, folder)
    record = {
        'path': file_path,
        'book_id': book_id,
        'parent': parent_path,
        'is_dir': True,
        'content': '',
        'is_edit': False,
        'add_by': login_user.get('username'),
        'created_at': int(time.time()),
        'updated_at': datetime.datetime.now().isoformat(),
    }
    meta = get_meta(file_path)
    record.update(meta)
    record['additions'] = meta
    check = Playbook.find_one({'book_id': book_id, 'path': record['path']})
    if check:
        additions = check.get('additions') or {}
        additions.update(meta)
        record['additions'] = additions
        Playbook.update_one({'_id': check['_id']}, {'$set': record})
    else:
        Playbook.insert_one(record)

    return jsonify({
        'message': 'ok',
        'code': 0,
    })
Exemple #2
0
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
Exemple #3
0
def delete(_id):
    record = db.collection('configurations').find_one({'_id': ObjectId(_id)})
    if not record:
        return jsonify({
            'message': 'record not found',
            'code': 104040,
        }), 404

    is_register = Playbook.find_one({'register': {'$in': [str(_id)]}})
    if is_register:
        return jsonify({
            'message':
            'target record is bind to playbook: %s' % is_register.get('name'),
            'code':
            104038
        }), 403

    Configuration.delete_one({'_id': record['_id']})
    msg = 'update configuration, name: {}'.format(record.get('name'))
    logger.info(msg, extra={'record': record, 'force': False})

    return jsonify({
        'message': 'ok',
        'code': 0,
    })
Exemple #4
0
    def test_upload(self):
        url = self.get_api_path('/books/%s/playbook' % str(ObjectId()))
        response = self.client.post(url, headers=self.jwt_headers)
        self.assert400(response)
        self.assertResponseCode(response, 104004)
        data = self.get_data('book')
        data['name'] = str(uuid.uuid4())
        result = Book.insert_one(data.copy())
        book_id = result.inserted_id
        self.trash += [
            [Book, book_id],
        ]
        url = self.get_api_path('/books/%s/playbook' % str(book_id))
        response = self.client.post(url, headers=self.jwt_headers)
        self.assert400(response)
        self.assertResponseCode(response, 104001)
        headers = self.jwt_headers.copy()
        headers.update({'Content-Type': 'multipart/form-data'})
        stream = BytesIO(bytes('mock test', 'utf-8'))
        params = {'file': (stream, 'test.yaml')}
        response = self.client.post(url,
                                    data=params,
                                    headers=headers,
                                    content_type='multipart/form-data')
        self.assert200(response)
        record = Playbook.find_one({'book_id': str(book_id)})
        assert record is not None
        db.fs().delete(record.get('file_id'))
        with patch('eclogue.api.book.is_edit') as build_mock:
            build_mock.return_value = False
            stream = BytesIO(bytes('mock test', 'utf-8'))
            params = {'file': (stream, 'binary.mock')}
            response = self.client.post(url,
                                        data=params,
                                        headers=headers,
                                        content_type='multipart/form-data')
            self.assert200(response)
            record = Playbook.find_one({
                'book_id': str(book_id),
                'file_id': {
                    '$exists': True
                }
            })
            assert record is not None
            db.fs().delete(record.get('file_id'))

        Playbook().collection.delete_many({'book_id': str(book_id)})
Exemple #5
0
def check_playbook_node(node):
    """
    loop check playbook parent node
    @param {dict} node
    """
    parent_path = os.path.dirname(node['path'])
    record = Playbook.find_one({
        'book_id': node['book_id'],
        'path': parent_path
    })
    if not record:
        current = node.copy()
        current['path'] = parent_path
        current['parent'] = None if parent_path == '/' else os.path.dirname(
            parent_path)
        Playbook.insert_one(current)
        return check_playbook_node(current)
    where = {
        'book_id': node['book_id'],
        'path': node['path'],
    }
    return Playbook.update_one(where, node, upsert=True)
Exemple #6
0
def parse_file_inventory(inventory_params):
    data = {}
    if type(inventory_params) != list:
        inventory_params = [inventory_params]

    for inventory_str in inventory_params:
        inventory_list = inventory_str.split('@')
        if len(inventory_list) is not 3:
            return False

        mark_name, _id, group = inventory_list
        record = Playbook.find_one({'_id': ObjectId(_id)})
        if not record:
            return False

        node = parser_inventory(record['content'], True)
        # @todo make same as cmdb
        # record['content'] = json.dumps(record['content'])
        # record['limit'] = group
        data.update(node)

    return data
Exemple #7
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,
    })
Exemple #8
0
def books():
    query = request.args
    page = int(query.get('page', 1))
    size = int(query.get('pageSize', 50))
    offset = (page - 1) * size
    keyword = query.get('keyword')
    is_admin = login_user.get('is_admin')
    start = query.get('start')
    end = query.get('end')
    maintainer = query.get('maintainer')
    where = {'status': {'$ne': -1}}
    if keyword:
        where['name'] = {'$regex': keyword}

    if not is_admin:
        where['maintainer'] = {'$in': [login_user.get('username')]}
    elif maintainer:
        where['maintainer'] = {'$in': [maintainer]}

    date = []
    if start:
        date.append({
            'created_at': {
                '$gte': int(time.mktime(time.strptime(start, '%Y-%m-%d')))
            }
        })

    if end:
        date.append({
            'created_at': {
                '$lte': int(time.mktime(time.strptime(end, '%Y-%m-%d')))
            }
        })

    if date:
        where['$and'] = date

    cursor = Book.find(where, skip=offset, limit=size)
    total = cursor.count()
    records = list(cursor)
    data = []
    for item in records:

        item['job'] = None
        where = {
            'type': 'playbook',
            'template.entry': {
                '$in': [str(item['_id'])]
            }
        }
        job = db.collection('jobs').find_one(where)
        if job:
            item['job'] = {
                '_id': job.get('_id'),
                'name': job.get('name'),
                'type': job.get('type'),
            }

        if item.get('status'):
            data.append(item)
            continue

        where = {
            'role': 'entry',
            'book_id': item['_id'],
        }
        entry = Playbook.find_one(where)
        if not entry:
            Book.update_one({'_id': item['_id']}, {'$set': {'status': 0}})
            item['status'] = 0

        data.append(item)

    return jsonify({
        'message': 'ok',
        'code': 0,
        'data': {
            'list': records,
            'page': page,
            'pageSize': size,
            'total': total,
        }
    })
Exemple #9
0
def get_job(_id):
    username = login_user.get('username')
    if not _id:
        return jsonify({'message': 'invalid id', 'code': 154000}), 400

    job = Job.find_one({
        '_id': ObjectId(_id),
        'maintainer': {
            '$in': [username]
        }
    })

    # @todo job status
    if not job:
        return jsonify({
            'message': 'invalid id',
            'code': 154001,
        }), 400

    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)
        return jsonify({
            'message': 'ok',
            'code': 0,
            'data': {
                'record': job,
                'previewContent': inventory_content,
            },
        })

    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_one({'_id': ObjectId(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,
        },
    })
Exemple #10
0
    def test_upload(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']],
        ]
        headers = self.jwt_headers.copy()
        headers.update({'Content-Type': 'multipart/form-data'})

        url = self.get_api_path('/playbook/upload')
        response = self.client.post(url, headers=headers)
        self.assert400(response)
        self.assertResponseCode(response, 104000)

        url = self.get_api_path('/playbook/upload')
        form = {'parent': '/', 'bookId': str(ObjectId())}

        response = self.client.post(url, data=form, headers=headers)
        self.assert400(response)
        self.assertResponseCode(response, 104001)
        stream = BytesIO(bytes('mock test', 'utf-8'))
        form['files'] = (stream, 'test.yaml')
        response = self.client.post(url, data=form, headers=headers)
        self.assert404(response)
        self.assertResponseCode(response, 104040)
        params = form.copy()
        stream = BytesIO(bytes('mock test', 'utf-8'))
        params['files'] = (stream, 'test.yaml')
        params['parent'] = ObjectId()
        response = self.client.post(url,
                                    data=params,
                                    headers=headers,
                                    content_type='multipart/form-data')
        self.assert400(response)
        self.assertResponseCode(response, 104004)

        stream = BytesIO(bytes('mock test', 'utf-8'))
        form['files'] = (stream, 'test.yaml')
        form['bookId'] = book_id
        response = self.client.post(url,
                                    data=form,
                                    headers=headers,
                                    content_type='multipart/form-data')
        self.assert200(response)
        record = Playbook.find_one({
            'book_id': str(book_id),
            '_id': {
                '$ne': playbook['_id']
            }
        })
        assert record is not None
        db.fs().delete(record.get('file_id'))
        with patch('eclogue.api.playbook.is_edit') as build_mock:
            build_mock.return_value = False
            stream = BytesIO(bytes('mock test', 'utf-8'))
            form['files'] = (stream, 'binary.mock')
            response = self.client.post(url,
                                        data=form,
                                        headers=headers,
                                        content_type='multipart/form-data')
            self.assert200(response)
            record = Playbook.find_one({
                'book_id': str(book_id),
                'file_id': {
                    '$exists': True
                }
            })
            assert record is not None
            db.fs().delete(record.get('file_id'))

        Playbook().collection.delete_many({'book_id': str(book_id)})
Exemple #11
0
def upload():
    files = request.files
    form = request.form
    if not form or not form.get('parent'):
        return jsonify({
            'message': 'illegal param',
            'code': 104000,
        }), 400
    if not files.get('files'):
        return jsonify({
            'message': 'illegal param',
            'code': 104001,
        }), 400
    parent_id = form.get('parent')
    book_id = form.get('bookId')
    if parent_id == '/' and book_id:
        book = Book.find_one({'_id': ObjectId(book_id)})
        if not book:
            return jsonify({
                "message": "record not found",
                "code": 104040,
            }), 404

        current = {'path': '/', 'book_id': book_id}
    else:
        current = Playbook.find_one({'_id': ObjectId(parent_id)})
    if not current:
        return jsonify({
            "message": "current path not found",
            "code": 104004,
        }), 400
    file = files['files']
    filename = file.filename
    path = os.path.join(current['path'], filename)
    # parent = Playbook.find_one({'book_id': book_id, 'path': os.path.dirname(path)})
    record = {
        'book_id': book_id,
        'path': path,
        'is_dir': False,
        'parent': os.path.dirname(path),
    }
    meta = get_meta(path)
    record.update(meta)
    can_edit = is_edit(file)
    if not can_edit:
        file_id = db.save_file(filename=filename, fileobj=file)
        record['file_id'] = file_id
    else:
        content = file.read()
        content = content.decode('utf-8')
        record['content'] = content

    record['is_edit'] = can_edit
    record['created_at'] = int(time.time())
    record['updated_at'] = datetime.datetime.now().isoformat()
    # where = {
    #     'path': path,
    #     'book_id': ObjectId(book_id)
    # }
    # update = {
    #     '$set': record,
    # }
    check_playbook_node(record)
    # Playbook.update_one(where, update=update, upsert=True)

    return jsonify({
        'message': 'ok',
        'code': 0,
    })