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

fix(apis/web/resource/view): 修复资源绑定插件未修改但触发更新问题 #1110

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
43 changes: 28 additions & 15 deletions src/dashboard/apigateway/apigateway/apis/web/plugin/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
from apigateway.core.models import Resource, Stage
from apigateway.utils.django import get_model_dict
from apigateway.utils.responses import OKJsonResponse
from apigateway.utils.yaml import yaml_loads

from .serializers import (
PluginBindingListOutputSLZ,
Expand Down Expand Up @@ -327,6 +328,16 @@ class PluginConfigRetrieveUpdateDestroyApi(

lookup_field = "id"

def _check_if_changed(self, input_data: Dict[str, Any], instance: PluginConfig) -> bool:

try:
input_yaml = yaml_loads(input_data["yaml"])
current_yaml = yaml_loads(instance.yaml)
except Exception:
return True

return input_yaml != current_yaml or input_data["type_id"].id != instance.type.id

def get_queryset(self):
return PluginConfig.objects.prefetch_related("type").filter(gateway=self.request.gateway)

Expand All @@ -339,23 +350,25 @@ def perform_update(self, serializer):
self.validate_scope()
self.validate_code(type_id=serializer.validated_data["type_id"])

data_before = get_model_dict(serializer.instance)
if self._check_if_changed(dict(serializer.validated_data), serializer.instance):

super().perform_update(serializer)
data_before = get_model_dict(serializer.instance)

# if scope_type is stage, should publish
scope_type = self.kwargs["scope_type"]
scope_id = self.kwargs["scope_id"]
self.post_modification(
source=PublishSourceEnum.PLUGIN_UPDATE,
op_type=OpTypeEnum.MODIFY,
scope_type=scope_type,
scope_id=scope_id,
instance_id=serializer.instance.id,
instance_name=serializer.instance.name,
data_before=data_before,
data_after=get_model_dict(serializer.instance),
)
super().perform_update(serializer)

# if scope_type is stage, should publish
scope_type = self.kwargs["scope_type"]
scope_id = self.kwargs["scope_id"]
self.post_modification(
source=PublishSourceEnum.PLUGIN_UPDATE,
op_type=OpTypeEnum.MODIFY,
scope_type=scope_type,
scope_id=scope_id,
instance_id=serializer.instance.id,
instance_name=serializer.instance.name,
data_before=data_before,
data_after=get_model_dict(serializer.instance),
)

@transaction.atomic
def perform_destroy(self, instance):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import pytest
from django.utils.translation import override

from apigateway.apis.web.plugin.views import PluginConfigRetrieveUpdateDestroyApi
from apigateway.utils.yaml import yaml_dumps


Expand Down Expand Up @@ -215,6 +216,48 @@ def test_delete(

assert response.status_code == 204

def test_check_if_changed(
self,
request_view,
fake_gateway,
fake_stage,
fake_plugin_bk_header_rewrite,
fake_plugin_check_changed_binding,
):

yaml = yaml_dumps(
{
"set": [{"key": "foo", "value": "bar"}],
"remove": [{"key": "baz"}],
}
)

view = PluginConfigRetrieveUpdateDestroyApi()

# update yaml
fake_input_data1 = {
"name": fake_plugin_bk_header_rewrite.name,
"type_id": fake_plugin_check_changed_binding[0],
"yaml": '',
}
assert view._check_if_changed(fake_input_data1, fake_plugin_bk_header_rewrite)

# update type_id
fake_input_data3 = {
"name": fake_plugin_bk_header_rewrite.name,
"type_id": fake_plugin_check_changed_binding[1],
"yaml": yaml,
}
assert view._check_if_changed(fake_input_data3, fake_plugin_bk_header_rewrite)

# no update
fake_input_data4 = {
"name": fake_plugin_bk_header_rewrite.name,
"type_id": fake_plugin_check_changed_binding[0],
"yaml": yaml,
}
assert not view._check_if_changed(fake_input_data4, fake_plugin_bk_header_rewrite)


class TestPluginFormRetrieveApi:
@pytest.mark.parametrize(
Expand Down
36 changes: 36 additions & 0 deletions src/dashboard/apigateway/apigateway/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,42 @@ def fake_plugin_resource_bk_cors_binding(fake_plugin_bk_cors, fake_resource):
)


@pytest.fixture()
def fake_plugin_check_changed(fake_plugin_type_bk_header_rewrite, fake_gateway):
return G(
PluginConfig,
gateway=fake_gateway,
name="bk-test",
type=fake_plugin_type_bk_header_rewrite,
yaml=yaml_dumps(
{
"set": [{"key": "foo", "value": "bar"}],
"remove": [{"key": "baz"}],
}
),
)


@pytest.fixture()
def fake_plugin_check_changed_binding(fake_plugin_bk_header_rewrite, fake_plugin_check_changed, fake_stage):
bangding1 = G(
PluginBinding,
gateway=fake_plugin_bk_header_rewrite.gateway,
config=fake_plugin_bk_header_rewrite,
scope_type=PluginBindingScopeEnum.STAGE.value,
scope_id=fake_stage.pk,
)

bangding2 = G(
PluginBinding,
gateway=fake_plugin_check_changed.gateway,
config=fake_plugin_check_changed,
scope_type=PluginBindingScopeEnum.STAGE.value,
scope_id=fake_stage.pk,
)
return [bangding1, bangding2]


@pytest.fixture()
def fake_rsa_private_key():
return """-----BEGIN RSA PRIVATE KEY-----
Expand Down
Loading