Skip to content

Commit

Permalink
feat: support force delete resource
Browse files Browse the repository at this point in the history
Signed-off-by: Ling Samuel (WSL) <lingsamuelgrace@gmail.com>
  • Loading branch information
lingsamuel committed Jul 11, 2023
1 parent ef2a96d commit 1d5e7cc
Show file tree
Hide file tree
Showing 10 changed files with 903 additions and 2 deletions.
6 changes: 6 additions & 0 deletions apisix/admin/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,12 @@ local function run()
if seg_res == "schema" or seg_res == "plugins" then
code, data = resource[method](seg_id, req_body, seg_sub_path, uri_args)
else
if method == "delete" then
if not req_body then
req_body = {}
end
req_body._force_delete = ngx.req.get_headers()["X-Force-Delete"]
end
code, data = resource[method](resource, seg_id, req_body, seg_sub_path, uri_args)
end

Expand Down
2 changes: 1 addition & 1 deletion apisix/admin/proto.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ local function check_proto_used(plugins, deleting, ptype, pid)
if type(plugins) == "table" and plugins["grpc-transcode"]
and plugins["grpc-transcode"].proto_id
and tostring(plugins["grpc-transcode"].proto_id) == deleting then
return false, {error_msg = "can not delete this proto,"
return false, {error_msg = "can not delete this proto, "
.. ptype .. " [" .. pid
.. "] is still using it now"}
end
Expand Down
2 changes: 1 addition & 1 deletion apisix/admin/resource.lua
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ function _M:delete(id, conf, sub_path)

key = key .. "/" .. id

if self.delete_checker then
if self.delete_checker and conf._force_delete ~= "true" then
local code, err = self.delete_checker(id)
if err then
return code, err
Expand Down
27 changes: 27 additions & 0 deletions docs/en/latest/admin-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,33 @@ deployment:

This will find the environment variable `ADMIN_KEY` first, and if it does not exist, it will use `edd1c9f034335f136f87ad84b625c8f1` as the default value.

### Force Delete

By default, the Admin API checks for references between resources and will refuse to delete resources in use.

You can make a force deletion by adding the request header `X-Force-Delete: true` to the delete request, for example:

```bash
$ curl http://127.0.0.1:9180/apisix/admin/upstreams/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{
"nodes": {
"127.0.0.1:8080": 1
},
"type": "roundrobin"
}'
$ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{
"uri": "/*",
"upstream_id": 1
}'
{"value":{"priority":0,"upstream_id":1,"uri":"/*","create_time":1689038794,"id":"1","status":1,"update_time":1689038916},"key":"/apisix/routes/1"}
$ curl http://127.0.0.1:9180/apisix/admin/upstreams/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X DELETE
{"error_msg":"can not delete this upstream, route [1] is still using it now"}
$ curl http://127.0.0.1:9180/apisix/admin/upstreams/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X DELETE -H 'X-Force-Delete: any-value'
{"error_msg":"can not delete this upstream, route [1] is still using it now"}
$ curl http://127.0.0.1:9180/apisix/admin/upstreams/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X DELETE -H 'X-Force-Delete: true'
{"deleted":"1","key":"/apisix/upstreams/1"}
```

## V3 new feature

The Admin API has made some breaking changes in V3 version, as well as supporting additional features.
Expand Down
27 changes: 27 additions & 0 deletions docs/zh/latest/admin-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,33 @@ deployment:

首先查找环境变量 `ADMIN_KEY`,如果该环境变量不存在,它将使用 `edd1c9f034335f136f87ad84b625c8f1` 作为默认值。

### 强制删除 {#force-delete}

默认情况下,Admin API 会检查资源间的引用关系,将会拒绝删除正在使用中的资源。

可以通过在删除请求中添加请求头 `X-Force-Delete: true` 来进行强制删除,例如:

```bash
$ curl http://127.0.0.1:9180/apisix/admin/upstreams/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{
"nodes": {
"127.0.0.1:8080": 1
},
"type": "roundrobin"
}'
$ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{
"uri": "/*",
"upstream_id": 1
}'
{"value":{"priority":0,"upstream_id":1,"uri":"/*","create_time":1689038794,"id":"1","status":1,"update_time":1689038916},"key":"/apisix/routes/1"}
$ curl http://127.0.0.1:9180/apisix/admin/upstreams/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X DELETE
{"error_msg":"can not delete this upstream, route [1] is still using it now"}
$ curl http://127.0.0.1:9180/apisix/admin/upstreams/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X DELETE -H 'X-Force-Delete: any-value'
{"error_msg":"can not delete this upstream, route [1] is still using it now"}
$ curl http://127.0.0.1:9180/apisix/admin/upstreams/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X DELETE -H 'X-Force-Delete: true'
{"deleted":"1","key":"/apisix/upstreams/1"}
```

## v3 版本新功能 {#v3-new-function}

在 APISIX v3 版本中,Admin API 支持了一些不向下兼容的新特性,比如支持新的响应体格式、支持分页查询、支持过滤资源等。
Expand Down
169 changes: 169 additions & 0 deletions t/admin/consumer-group-force-delete.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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.
#
use t::APISIX 'no_plan';

repeat_each(1);
no_long_string();
no_root_location();
no_shuffle();
log_level("info");

add_block_preprocessor(sub {
my ($block) = @_;

if (!$block->request) {
$block->set_value("request", "GET /t");
}

if (!$block->no_error_log && !$block->error_log) {
$block->set_value("no_error_log", "[error]\n[alert]");
}
});

run_tests;

__DATA__
=== TEST 1: set consumer_group(id: 1)
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/consumer_groups/1',
ngx.HTTP_PUT,
[[{
"plugins": {
"limit-count": {
"count": 200,
"time_window": 60,
"rejected_code": 503,
"group": "$consumer_group_id"
}
}
}]]
)
ngx.status = code
ngx.say(body)
}
}
--- error_code: 201
--- response_body
passed
=== TEST 2: add consumer
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, message = t('/apisix/admin/consumers/1',
ngx.HTTP_PUT,
[[{
"username": "1",
"plugins": {
"key-auth": {
"key": "auth-one"
}
},
"group_id": "1"
}]]
)
if code >= 300 then
ngx.status = code
ngx.print(message)
return
end
ngx.say(message)
}
}
--- response_body
passed
=== TEST 3: delete consumer_group(wrong header)
--- config
location /t {
content_by_lua_block {
ngx.sleep(0.3)
local t = require("lib.test_admin").test
local code, message = t('/apisix/admin/consumer_groups/1',
ngx.HTTP_DELETE, nil, nil,
{
["X-Force-Delete"] = "any-value",
}
)
ngx.print("[delete] code: ", code, " message: ", message)
}
}
--- response_body
[delete] code: 400 message: {"error_msg":"can not delete this consumer group, consumer [1] is still using it now"}
=== TEST 4: delete consumer_group(without force delete header)
--- config
location /t {
content_by_lua_block {
ngx.sleep(0.3)
local t = require("lib.test_admin").test
local code, message = t('/apisix/admin/consumer_groups/1',
ngx.HTTP_DELETE
)
ngx.print("[delete] code: ", code, " message: ", message)
}
}
--- response_body
[delete] code: 400 message: {"error_msg":"can not delete this consumer group, consumer [1] is still using it now"}
=== TEST 5: delete consumer_group(force delete)
--- config
location /t {
content_by_lua_block {
ngx.sleep(0.3)
local t = require("lib.test_admin").test
local code, message = t('/apisix/admin/consumer_groups/1',
ngx.HTTP_DELETE, nil, nil,
{
["X-Force-Delete"] = "true",
}
)
ngx.print("[delete] code: ", code, " message: ", message)
}
}
--- response_body chomp
[delete] code: 200 message: passed
=== TEST 6: delete consumer
--- config
location /t {
content_by_lua_block {
ngx.sleep(0.3)
local t = require("lib.test_admin").test
local code, message = t('/apisix/admin/consumers/1',
ngx.HTTP_DELETE
)
ngx.print("[delete] code: ", code, " message: ", message)
}
}
--- response_body chomp
[delete] code: 200 message: passed
Loading

0 comments on commit 1d5e7cc

Please sign in to comment.