Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

优化请求 bk-apigateway 接口失败时,打印的错误消息 #136

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions sdks/apigw-manager/CHANGE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## Change logs

### 2.0.2
- 优化请求 bk-apigateway 接口失败时,打印的错误消息
- 添加指令 add_related_apps,支持为网关添加关联应用

### 2.0.1
- 修复镜像 sync-apigateway 中,同步任务失败时,脚本退出码为 0 的问题

Expand Down
5 changes: 5 additions & 0 deletions sdks/apigw-manager/definition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ grant_permissions:
apply_permissions:
- api_name: "{{ settings.BK_APIGW_NAME }}"

# 为网关添加关联应用,关联应用可以通过网关 bk-apigateway 的接口操作网关数据;每个网关最多可有 10 个关联应用
related_apps:
target_app_codes:
- "{{ settings.BK_APP_CODE }}"
alex-smile marked this conversation as resolved.
Show resolved Hide resolved

# 网关资源,建议资源配置采用单独的配置文件,可通过网关管理端导出资源配置
resources:
swagger: "2.0"
Expand Down
2 changes: 1 addition & 1 deletion sdks/apigw-manager/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "apigw-manager"
version = "2.0.1"
version = "2.0.2"
description = "The SDK for managing blueking gateway resource."
readme = "README.md"
authors = ["blueking <[email protected]>"]
Expand Down
27 changes: 23 additions & 4 deletions sdks/apigw-manager/src/apigw_manager/apigw/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
* specific language governing permissions and limitations under the License.
"""
import os
import sys
import typing

from django.conf import settings
from django.core.management.base import BaseCommand

from apigw_manager.apigw.helper import Definition
from apigw_manager.apigw.utils import get_configuration, parse_value_list
from apigw_manager.core.exceptions import ApiResponseError
from apigw_manager.core.fetch import Fetcher
from apigw_manager.core.permission import Manager as PermissionManager
from apigw_manager.core.sync import Synchronizer
Expand All @@ -32,6 +34,19 @@ def add_arguments(self, parser):
def get_configuration(self, **kwargs):
return get_configuration(**{k: v for k, v in kwargs.items() if v is not None})

def handle(self, *args, **kwargs):
configuration = self.get_configuration(**kwargs)
manager = self.manager_class(configuration)

try:
self.do(manager=manager, configuration=configuration, *args, **kwargs)
except ApiResponseError as err:
self.stderr.write(str(err))
sys.exit(1)
alex-smile marked this conversation as resolved.
Show resolved Hide resolved

def do(self, manager, configuration, *args, **kwargs):
pass


class DefinitionCommand(ApiCommand):
default_namespace = ""
Expand Down Expand Up @@ -67,16 +82,20 @@ def get_definition(self, define, file, namespace, **kwargs):

return definition.get(namespace, {})

def do(self, manager, definition, *args, **kwargs):
pass

def handle(self, *args, **kwargs):
configuration = self.get_configuration(**kwargs)

manager = self.manager_class(configuration)
definition = self.get_definition(**kwargs)

self.do(manager=manager, definition=definition, configuration=configuration, *args, **kwargs)
try:
self.do(manager=manager, definition=definition, configuration=configuration, *args, **kwargs)
except ApiResponseError as err:
self.stderr.write(str(err))
sys.exit(1)

def do(self, manager, definition, *args, **kwargs):
pass


class FetchCommand(ApiCommand):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
"""
* TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-蓝鲸 PaaS 平台(BlueKing-PaaS) available.
* Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
"""
from apigw_manager.apigw.command import SyncCommand
from apigw_manager.core.exceptions import ApiResponseError


class Command(SyncCommand):
"""Add related apps for gateway"""

default_namespace = "related_apps"

def do(self, manager, definition, *args, **kwargs):
if not definition:
print("no related apps found, skip")
return

try:
manager.add_related_apps(**definition)
except ApiResponseError as err:
print("warning!! Add related apps error, %s" % str(err))
return

print(
"Add related apps for gateway %s: %s"
% (
manager.config.api_name,
", ".join(definition["target_app_codes"])
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
"""
import sys

from apigw_manager.apigw import helper
from apigw_manager.apigw.command import FetchCommand

Expand All @@ -25,9 +27,7 @@ def add_arguments(self, parser):
parser.add_argument("--bk-app-secret", dest="bk_app_secret", help="app secret")
parser.add_argument("--no-save", default=False, action="store_true", help="do not save the public key")

def handle(self, print_, no_save, *args, **kwargs):
configuration = self.get_configuration(**kwargs)
manager = self.manager_class(configuration)
def do(self, manager, configuration, print_, no_save, *args, **kwargs):
result = manager.public_key()

if print_:
Expand Down
16 changes: 7 additions & 9 deletions sdks/apigw-manager/src/apigw_manager/core/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,18 @@ def __str__(self):
return self.operation_id


class ApiResultError(Exception):
def __init__(self, code, message):
self.code = code
class ApiResponseError(Exception):
"""There was an exception that occurred while handling the response"""
def __init__(self, message):
self.message = message

def __str__(self):
return "code: %s, %s" % (self.code, self.message)
return self.message


class ApiRequestError(Exception):
def __init__(self, status_code, code, message):
self.status_code = status_code
class ApiResultError(ApiResponseError):
def __init__(self, code, message):
self.code = code
self.message = message

def __str__(self):
return "status_code: %s, code: %s, %s" % (self.status_code, self.code, self.message)
return "code: %s, %s" % (self.code, self.message)
25 changes: 5 additions & 20 deletions sdks/apigw-manager/src/apigw_manager/core/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
from bkapi.bk_apigateway.client import Client as BKAPIGatewayClient
from future.utils import raise_from

from apigw_manager.core.exceptions import ApiException, ApiRequestError, ApiResultError
from bkapi_client_core.exceptions import HTTPResponseError
from apigw_manager.core.exceptions import ApiException, ApiResponseError, ApiResultError
from bkapi_client_core.exceptions import ResponseError

if typing.TYPE_CHECKING:
from apigw_manager.core import configuration
Expand Down Expand Up @@ -92,8 +92,9 @@ def _call(self, operation, files=None, **kwargs):

try:
return operation(**data)
except HTTPResponseError as err:
raise_from(self._convert_operation_exception(err), err)
except ResponseError as err:
message = "%s\n%s\nResponse: %s" % (err, err.curl_command, err.response_text)
raise ApiResponseError(message)
except Exception as err:
raise_from(ApiException(operation_id), err)

Expand All @@ -107,19 +108,3 @@ def _parse_result(self, result, convertor, code=0):
)

return convertor(result)

def _convert_operation_exception(self, err: HTTPResponseError):
response = err.response
if response is None or response.status_code / 100 != 4:
return err

try:
result = response.json()
except Exception:
return err

return ApiRequestError(
response.status_code,
result.get("code"),
result.get("message"),
)
4 changes: 4 additions & 0 deletions sdks/apigw-manager/src/apigw_manager/core/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ def sync_resources_config(self, content, *args, **kwargs):
def sync_resource_docs_by_archive(self, *args, **kwargs):
result = self._call(self.client.api.import_resource_docs_by_archive, *args, **kwargs)
return self._parse_result(result, itemgetter("data"))

def add_related_apps(self, *args, **kwargs):
result = self._call(self.client.api.add_related_apps, *args, **kwargs)
return self._parse_result(result, itemgetter("data"))
10 changes: 5 additions & 5 deletions sdks/apigw-manager/tests/apigw_manager/core/test_hander.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from faker import Faker
from pytest import fixture, raises

from apigw_manager.core.exceptions import ApiRequestError
from apigw_manager.core.exceptions import ApiResponseError
from apigw_manager.core.handler import Handler
from bkapi_client_core.exceptions import HTTPResponseError

Expand Down Expand Up @@ -90,12 +90,12 @@ def test_call_with_cache(self, handler: Handler, operation, operation_id, faker,

def test_call_connect_error(self, handler: Handler, operation):
operation.side_effect = HTTPResponseError()
with raises(HTTPResponseError):
with raises(ApiResponseError):
handler._call(operation)

def test_call_server_error(self, handler: Handler, operation, mocker):
operation.side_effect = HTTPResponseError(response=mocker.MagicMock(status_code=500))
with raises(HTTPResponseError):
with raises(ApiResponseError):
handler._call(operation)

def test_call_request_error(self, handler: Handler, operation, mocker):
Expand All @@ -106,7 +106,7 @@ def test_call_request_error(self, handler: Handler, operation, mocker):
)
)

with raises(ApiRequestError):
with raises(ApiResponseError):
handler._call(operation)

def test_call_request_error_with_no_json(self, handler: Handler, operation, mocker):
Expand All @@ -117,5 +117,5 @@ def test_call_request_error_with_no_json(self, handler: Handler, operation, mock
)
)

with raises(HTTPResponseError):
with raises(ApiResponseError):
handler._call(operation)
Loading