Пример #1
0
def get_plugin_api_data(request: Request, plugin_code: str, data_api_path: str):
    """获取插件服务提供的数据接口数据"""
    try:
        client = PluginServiceApiClient(plugin_code)
    except PluginServiceException as e:
        message = f"[get_plugin_api_data] error: {e}"
        logger.error(message)
        return JsonResponse({"message": message, "result": False, "data": None})
    # 注入插件特定前缀HEADER
    http_headers = dict(
        [(key[5:].replace("_", "-"), value) for key, value in request.META.items() if key.startswith("HTTP_BK_PLUGIN_")]
    )
    params = {
        "method": request.method,
        "url": "/" + data_api_path,
        "username": request.user.username,
        "data": request.data,
    }
    # 对于get请求带参数的情况,直接将参数拼接到url中
    if request.query_params:
        params["url"] = params["url"].rstrip("/") + "/?" + request.query_params.urlencode()
    result = client.dispatch_plugin_api_request(params, inject_headers=http_headers)
    # 如果请求成功,只返回接口原始data数据
    result = result["data"] if result.get("result") else result
    return Response(result)
Пример #2
0
def get_plugin_detail_list(request: Request):
    """获取插件服务列表及详情信息"""
    search_term = request.validated_data.get("search_term")
    limit = request.validated_data.get("limit")
    offset = request.validated_data.get("offset")
    exclude_not_deployed = request.validated_data.get("exclude_not_deployed")

    if exclude_not_deployed:
        plugins = []
        cur_offset = offset
        # 考虑到会有一些未部署到对应环境的情况,这里适当放大limit,减少请求次数
        cur_limit = limit * 2
        while True:
            result = PluginServiceApiClient.get_plugin_detail_list(
                search_term=search_term, limit=cur_limit, offset=cur_offset, order_by="name"
            )
            if not result["result"]:
                return JsonResponse(result)
            cur_plugins = result["data"]["plugins"]
            plugins.extend(
                [
                    (idx + cur_offset, plugin)
                    for idx, plugin in enumerate(cur_plugins)
                    if plugin["deployed_statuses"][env.APIGW_ENVIRONMENT]["deployed"]
                ]
            )
            cur_offset = cur_offset + cur_limit
            if result["data"]["count"] <= cur_offset or len(plugins) >= limit:
                break
        plugins = plugins[:limit]
        next_offset = plugins[-1][0] + 1 if len(plugins) > 0 else cur_offset
        response = {
            "result": True,
            "message": None,
            "data": {
                "next_offset": next_offset,
                "plugins": [plugin[1] for plugin in plugins],
                "return_plugin_count": len(plugins),
            },
        }
    else:
        result = PluginServiceApiClient.get_plugin_detail_list(
            search_term=search_term, limit=limit, offset=offset, order_by="name"
        )
        if not result["result"]:
            return JsonResponse(result)
        response = result
        plugins = result["data"]["plugins"]
        response["data"] = {"next_offset": limit + offset, "plugins": plugins, "return_plugin_count": len(plugins)}
    return JsonResponse(response)
Пример #3
0
def get_remote_plugin_name(limit=100, offset=0):
    """
    @summary: 拉取第三方插件名
    @param: limit: 拉取第三方插件数据默认limit,默认为100
    @param: offset: 拉取第三方插件分页起点,默认为0
    return plugin_info:dict() 第三方插件信息
    """
    TOTAL = limit
    CUR_TOTAL = 0

    plugin_info = {}
    if not env.USE_PLUGIN_SERVICE == "1":
        return plugin_info
    while CUR_TOTAL < TOTAL:
        result = PluginServiceApiClient.get_paas_plugin_info(
            search_term=None, environment="prod", limit=limit, offset=offset
        )
        if result.get("result") is False:
            return plugin_info
        for plugin in result["results"]:
            plugin_info.setdefault(plugin["code"], plugin["name"])
            CUR_TOTAL += 1
        TOTAL = result.get("count", 0)
        offset += 1
    return plugin_info
Пример #4
0
def get_plugin_list(request: Request):
    """获取插件服务列表信息"""
    search_term = request.validated_data.get("search_term")
    limit = request.validated_data.get("limit")
    offset = request.validated_data.get("offset")
    result = PluginServiceApiClient.get_plugin_list(search_term=search_term, limit=limit, offset=offset)
    return JsonResponse(result)
Пример #5
0
    def execute(self, data, parent_data):
        plugin_code = data.get_one_of_inputs("plugin_code")
        plugin_version = data.get_one_of_inputs("plugin_version")

        try:
            plugin_client = PluginServiceApiClient(plugin_code)
        except PluginServiceException as e:
            message = f"[remote plugin service client] error: {e}"
            logger.error(message)
            data.set_outputs("ex_data", message)
            return False

        detail_result = plugin_client.get_detail(plugin_version)
        if not detail_result["result"]:
            message = f"[remote plugin service detail] error: {detail_result['message']}"
            logger.error(message)
            data.set_outputs("ex_data", message)
            return False

        plugin_context = dict([(key, parent_data.inputs[key])
                               for key in detail_result["data"]
                               ["context_inputs"]["properties"].keys()
                               if key in parent_data.inputs])
        ok, result_data = plugin_client.invoke(plugin_version, {
            "inputs": data.inputs,
            "context": plugin_context
        })

        if not ok:
            message = (
                f"[remote plugin service invoke] error: {result_data['message']}, "
                f"trace_id: {result_data.get('trace_id')}")
            logger.error(message)
            data.set_outputs("ex_data", message)
            return False

        data.set_outputs("trace_id", result_data["trace_id"])
        self._inject_result_data_outputs(data, result_data)

        state = result_data["state"]
        if state == State.FAIL:
            data.set_outputs("ex_data", result_data["err"])
            return False
        if state == State.POLL:
            setattr(self, "__need_schedule__", True)
        return True
Пример #6
0
 def wrapper(request: Request):
     plugin_code = request.validated_data.get("plugin_code")
     try:
         plugin_client = PluginServiceApiClient(plugin_code)
     except PluginServiceException as e:
         logger.error(f"[inject_plugin_client] error: {e}")
         return JsonResponse({"message": e, "result": False, "data": None})
     setattr(request, "plugin_client", plugin_client)
     return func(request)
Пример #7
0
def get_plugin_detail(request: Request):
    """ 获取插件服务详情 """
    plugin_version = request.validated_data.get("plugin_version")
    with_app_detail = request.validated_data.get("with_app_detail")
    plugin_detail = request.plugin_client.get_detail(plugin_version)
    if not plugin_detail["result"]:
        return JsonResponse(plugin_detail)
    if with_app_detail:
        app_detail = PluginServiceApiClient.get_plugin_app_detail(request.validated_data.get("plugin_code"))
        if not app_detail["result"]:
            return JsonResponse(app_detail)
        plugin_detail["data"]["app"] = app_detail["data"]
    return JsonResponse(plugin_detail)
Пример #8
0
    def schedule(self, data, parent_data, callback_data=None):
        plugin_code = data.get_one_of_inputs("plugin_code")
        trace_id = data.get_one_of_outputs("trace_id")

        try:
            plugin_client = PluginServiceApiClient(plugin_code)
        except PluginServiceException as e:
            message = f"[remote plugin service client] error: {e}"
            logger.error(message)
            data.set_outputs("ex_data", message)
            return False

        ok, result_data = plugin_client.get_schedule(trace_id)

        if not ok:
            message = (
                f"remote plugin service schedule error: {result_data['message']}, "
                f"trace_id: {result_data.get('trace_id') or trace_id}")
            logger.error(message)
            data.set_outputs("ex_data", message)
            return False

        self._inject_result_data_outputs(data, result_data)

        state = result_data["state"]
        if state == State.FAIL:
            default_message = "please check the logs for the reason of task failure."
            logger.error(
                f"[remote plugin service state failed]: {result_data}")
            data.set_outputs(
                "ex_data", result_data["outputs"].get("ex_data")
                or default_message)
            return False
        if state == State.POLL:
            setattr(self, "__need_schedule__", True)
        if state == State.SUCCESS:
            self.finish_schedule()
        return True
Пример #9
0
def get_logs(request: Request):
    """ 获取插件服务执行日志 """
    trace_id = request.validated_data.get("trace_id")
    scroll_id = request.validated_data.get("scroll_id")
    plugin_code = request.validated_data.get("plugin_code")
    result = PluginServiceApiClient.get_plugin_logs(plugin_code, trace_id, scroll_id)
    if result["result"]:
        logs = [
            f'[{log["ts"]}]{log["detail"]["json.levelname"]}-{log["detail"]["json.funcName"]}: '
            f'{log["detail"]["json.message"]}'
            for log in result["data"]["logs"]
        ]
        result["data"]["logs"] = "\n".join(logs)
    return JsonResponse(result)
Пример #10
0
def get_remote_plugin_detail_list(limit=100, offset=0):
    """
    @summary: 拉取第三方插件详细信息
    @param: limit: 拉取第三方插件数据默认limit,默认为100
    @param: offset: 拉取第三方插件分页起点,默认为0
    return plugin_info:list() 第三方插件信息
    """
    TOTAL = limit
    CUR_TOTAL = 0

    plugin_info = []
    if not env.USE_PLUGIN_SERVICE == "1":
        return plugin_info

    # 取所有第三方插件code和version
    remote_plugins = list(
        TemplateNodeStatistics.objects.filter(is_remote=True).values_list("component_code", "version")
    )
    remote_plugin_dict = {}
    for plugin in remote_plugins:
        # plugin ["code","version"]
        remote_plugin_dict.setdefault(plugin[0], {plugin[1]}).add(plugin[1])
    while CUR_TOTAL < TOTAL:
        result = PluginServiceApiClient.get_paas_plugin_info(
            search_term=None, environment="prod", limit=limit, offset=offset
        )
        if result.get("result") is False:
            return plugin_info
        for plugin in result["results"]:
            CUR_TOTAL += 1
            versions = remote_plugin_dict.get(plugin["code"])
            if not versions:
                continue
            plugin_info.extend(
                [
                    {
                        "name": plugin["name"],
                        "version": version,
                        "code": plugin["code"],
                        "group_name": "第三方插件",
                        "is_remote": True,
                    }
                    for version in versions
                ]
            )
        TOTAL = result.get("count", 0)
        offset += 1
    return plugin_info
Пример #11
0
def get_plugin_app_detail(request: Request):
    """获取插件服务App详情"""
    result = PluginServiceApiClient.get_plugin_app_detail(request.validated_data.get("plugin_code"))
    return JsonResponse(result)