Skip to content

Commit

Permalink
refactor(api-support): remove unused urls/apis for api-support (#87)
Browse files Browse the repository at this point in the history
  • Loading branch information
wklken authored Jul 13, 2023
1 parent 4b86c09 commit d86fd2c
Show file tree
Hide file tree
Showing 4 changed files with 5 additions and 342 deletions.
16 changes: 0 additions & 16 deletions src/dashboard/apigateway/apigateway/apis/open/support/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,6 @@
from . import views

urlpatterns = [
# TODO: for api-support, should be removed after the frontend merge is completed
path(
"apis/<int:gateway_id>/support/resources/<int:resource_id>/doc/",
views.ResourceDocViewSet.as_view({"get": "retrieve"}),
name="openapi.support.resource_doc",
),
path(
"apis/<int:gateway_id>/support/stages/<slug:stage_name>/resources/<slug:resource_name>/doc/",
views.ResourceDocViewSet.as_view({"get": "get_doc"}),
name="openapi.support.resource_doc.stage",
),
path(
"apis/<int:gateway_id>/support/stages/sdks/",
views.APISDKV1ViewSet.as_view({"get": "list_stage_sdks"}),
name="openapi.support.sdk.stage",
),
# for apigw-manager
path(
"apis/<slug:gateway_name>/resource-docs/import/by-archive/",
Expand Down
166 changes: 4 additions & 162 deletions src/dashboard/apigateway/apigateway/apis/open/support/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,138 +17,32 @@
# to the current version of the project delivered to anyone in the future.
#
import logging
import operator

from bkapi_client_generator import ExpandSwaggerError, GenerateMarkdownError
from django.db import transaction
from django.http import Http404
from django.shortcuts import get_object_or_404
from django.utils.translation import gettext as _
from drf_yasg.utils import swagger_auto_schema
from rest_framework import status, viewsets
from tencent_apigateway_common.django.translation import get_current_language_code
from rest_framework import viewsets

from apigateway.apis.open.support import serializers
from apigateway.apps.support.api_sdk import exceptions
from apigateway.apps.support.api_sdk.helper import SDKHelper
from apigateway.apps.support.api_sdk.models import SDKFactory
from apigateway.apps.support.constants import DocLanguageEnum, ProgrammingLanguageEnum
from apigateway.apps.support.models import APISDK, ReleasedResourceDoc, ResourceDoc
from apigateway.apps.support.constants import DocLanguageEnum
from apigateway.apps.support.models import APISDK
from apigateway.apps.support.resource_doc.exceptions import NoResourceDocError, ResourceDocJinja2TemplateError
from apigateway.apps.support.resource_doc.import_doc.managers import ArchiveImportDocManager, SwaggerImportDocManager
from apigateway.apps.support.resource_doc.serializers import ResourceDocSLZ
from apigateway.apps.support.utils import get_doc_language
from apigateway.biz.resource_url import ResourceURLHandler
from apigateway.common.contexts import APIAuthContext
from apigateway.common.error_codes import error_codes
from apigateway.common.exceptions import SchemaValidationError
from apigateway.common.funcs import get_resource_version_display
from apigateway.common.permissions import GatewayRelatedAppPermission
from apigateway.core.models import Gateway, Release, ReleasedResource, ResourceVersion
from apigateway.core.utils import get_path_display, get_resource_url
from apigateway.core.models import Gateway, Release, ResourceVersion
from apigateway.utils.responses import OKJsonResponse

logger = logging.getLogger(__name__)


class ResourceDocViewSet(viewsets.ModelViewSet):
serializer_class = ResourceDocSLZ
lookup_field = "resource_id"
api_permission_exempt = True

def get_queryset(self):
return ResourceDoc.objects.all()

@swagger_auto_schema(
responses={status.HTTP_200_OK: ResourceDocSLZ()},
tags=["OpenAPI.Support"],
)
def retrieve(self, request, *args, **kwargs):
if not request.gateway.is_active_and_public:
return OKJsonResponse("OK", data={})

api_id = request.gateway.id
resource_id = kwargs["resource_id"]

resource = ReleasedResource.objects.get_latest_released_resource(api_id, resource_id)
# 资源在已发布版本中不存在,或者资源未公开
if not resource or not resource["is_public"]:
return OKJsonResponse("OK", data={})

doc = ReleasedResourceDoc.objects.get_latest_released_resource_doc(api_id, resource_id)
stages = Release.objects.get_released_stage_names(api_id)
latest_sdk = APISDK.objects.filter_recommended_sdks(
language=ProgrammingLanguageEnum.PYTHON.value,
gateway_id=api_id,
).first()

return OKJsonResponse(
"OK",
data={
"resource": resource,
"stages": stages,
"doc": doc,
"sdk": self._get_python_sdk_info(latest_sdk),
},
)

@swagger_auto_schema(
responses={status.HTTP_200_OK: ResourceDocSLZ()},
tags=["OpenAPI.Support"],
)
def get_doc(self, request, stage_name: str, resource_name: str, *args, **kwargs):
if not request.gateway.is_active_and_public:
raise Http404

resource_version_id = Release.objects.get_released_resource_version_id(request.gateway.id, stage_name)
if not resource_version_id:
raise Http404

resource = ReleasedResource.objects.get_released_resource(
request.gateway.id, resource_version_id, resource_name
)
# 资源在已发布版本中不存在,或者资源未公开
if not resource or not resource["is_public"] or stage_name in resource["disabled_stages"]:
raise Http404

doc = ReleasedResourceDoc.objects.get_released_resource_doc(
request.gateway.id,
resource_version_id,
resource["id"],
language=get_doc_language(get_current_language_code()),
)

return OKJsonResponse(
"OK",
data={
"resource": resource,
"doc": doc,
"resource_url": get_resource_url(
resource_url_tmpl=ResourceURLHandler.get_resource_url_tmpl(request.gateway.name, stage_name),
gateway_name=request.gateway.name,
stage_name=stage_name,
resource_path=get_path_display(resource["path"], resource["match_subpath"]),
),
},
)

def _get_python_sdk_info(self, sdk):
if not sdk:
return {}

is_uploaded_to_pypi = sdk.config.get(ProgrammingLanguageEnum.PYTHON.value, {}).get(
"is_uploaded_to_pypi", False
)
if not is_uploaded_to_pypi:
return {}

return {
"version_number": sdk.version_number,
"filename": sdk.filename,
"download_url": sdk.download_url,
}


class APISDKV1ViewSet(viewsets.ModelViewSet):
serializer_class = serializers.APISDKV1SLZ
lookup_field = "id"
Expand Down Expand Up @@ -184,58 +78,6 @@ def list_latest_sdks(self, request, *args, **kwargs):
)
return OKJsonResponse("OK", data=slz.data)

def list_stage_sdks(self, request, *args, **kwargs):
if not request.gateway.is_active_and_public:
return OKJsonResponse("OK", data=[])

released_resource_version_ids = Release.objects.get_released_resource_version_ids(request.gateway.id)
public_latest_sdks = {
k: SDKFactory.create(v)
for k, v in APISDK.objects.filter_resource_version_public_latest_sdk(
gateway_id=request.gateway.id,
resource_version_ids=released_resource_version_ids,
).items()
}

releases = Release.objects.filter(api_id=request.gateway.id).values(
"stage__id",
"stage__name",
"stage__is_public",
"resource_version__id",
"resource_version__name",
"resource_version__title",
"resource_version__version",
)
stage_sdks = []
for release in releases:
if not release["stage__is_public"]:
continue

sdk = public_latest_sdks.get(release["resource_version__id"])
stage_sdks.append(
{
"stage_id": release["stage__id"],
"stage_name": release["stage__name"],
"resource_version_id": release["resource_version__id"],
"resource_version_name": release["resource_version__name"],
"resource_version_title": release["resource_version__title"],
"resource_version_display": get_resource_version_display(
{
"version": release["resource_version__version"],
"name": release["resource_version__name"],
"title": release["resource_version__title"],
}
),
"language": sdk.language.value if sdk else "",
"sdk_version_number": sdk.version if sdk else "",
"sdk_download_url": sdk.url if sdk else "",
"sdk_name": sdk.name if sdk else "",
"sdk_install_command": sdk.install_command if sdk else "",
}
)

return OKJsonResponse("OK", data=sorted(stage_sdks, key=operator.itemgetter("stage_name")))


class ResourceDocImportViewSet(viewsets.ViewSet):
permission_classes = [GatewayRelatedAppPermission]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,156 +37,6 @@ def has_related_app_permission(mocker):
)


class TestResourceDocViewSet:
@pytest.mark.parametrize(
"mocked_resource_version_id, mocked_released_resource, mocked_resource_doc, will_error, expected",
[
# ok
(
1,
{
"id": 1,
"is_public": True,
"name": "test",
"path": "/test/",
"match_subpath": False,
"disabled_stages": [],
},
{
"content": "test",
},
False,
{
"resource": {
"id": 1,
"is_public": True,
"name": "test",
"path": "/test/",
"match_subpath": False,
"disabled_stages": [],
},
"doc": {
"content": "test",
},
"resource_url": "http://bking.test.com/prod/test/",
},
),
# resource_version_id is none
(
None,
{
"id": 1,
"is_public": True,
"name": "test",
"path": "/test/",
"match_subpath": False,
"disabled_stages": [],
},
{
"content": "test",
},
True,
None,
),
# released_resource is none
(
1,
None,
{
"content": "test",
},
True,
None,
),
# released_resource is_public is False
(
1,
None,
{
"content": "test",
},
True,
None,
),
(
1,
{
"id": 1,
"is_public": True,
"name": "test",
"path": "/test/",
"match_subpath": False,
"disabled_stages": ["prod"],
},
{
"content": "test",
},
True,
None,
),
],
)
def test_get_doc(
self,
mocker,
settings,
request_factory,
fake_gateway,
mocked_resource_version_id,
mocked_released_resource,
mocked_resource_doc,
will_error,
expected,
):
settings.API_RESOURCE_URL_TMPL = "http://bking.test.com/{stage_name}/{resource_path}"

get_released_resource_version_id_mock = mocker.patch(
"apigateway.apis.open.support.views.Release.objects.get_released_resource_version_id",
return_value=mocked_resource_version_id,
)
get_released_resource_mock = mocker.patch(
"apigateway.apis.open.support.views.ReleasedResource.objects.get_released_resource",
return_value=mocked_released_resource,
)
get_released_resource_doc_mock = mocker.patch(
"apigateway.apis.open.support.views.ReleasedResourceDoc.objects.get_released_resource_doc",
return_value=mocked_resource_doc,
)

request = request_factory.get("/")
request.gateway = fake_gateway
stage_name = "prod"
resource_name = mocked_released_resource and mocked_released_resource["name"]

view = views.ResourceDocViewSet.as_view({"get": "get_doc"})
response = view(request, gateway_id=fake_gateway.id, stage_name=stage_name, resource_name=resource_name)
result = get_response_json(response)

if will_error:
response.status_code == 404
assert result["code"] == 40000
return

assert result["code"] == 0
assert result["data"] == expected

get_released_resource_version_id_mock.assert_called_once_with(
fake_gateway.id,
stage_name,
)
get_released_resource_mock.assert_called_once_with(
fake_gateway.id,
mocked_resource_version_id,
resource_name,
)
get_released_resource_doc_mock.assert_called_once_with(
fake_gateway.id,
mocked_resource_version_id,
mocked_released_resource["id"],
language="zh",
)


class TestAPISDKV1ViewSet:
def test_list_latest_sdk(self, mocker, request_factory, faker):
fake_gateway = G(Gateway, is_public=True, status=1)
Expand Down
Loading

0 comments on commit d86fd2c

Please sign in to comment.