You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by me...@apache.org on 2020/06/02 03:28:55 UTC
[incubator-apisix] branch master updated: feat(admin api): enhance
`PATCH` method, allow to update partial data. (#1609)
This is an automated email from the ASF dual-hosted git repository.
membphis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-apisix.git
The following commit(s) were added to refs/heads/master by this push:
new ecd684b feat(admin api): enhance `PATCH` method, allow to update partial data. (#1609)
ecd684b is described below
commit ecd684b3a0b40b885aed4ced8339027eb189b38f
Author: nic-chen <33...@users.noreply.github.com>
AuthorDate: Tue Jun 2 11:28:45 2020 +0800
feat(admin api): enhance `PATCH` method, allow to update partial data. (#1609)
---
apisix/admin/global_rules.lua | 35 ++++++-----------------------------
apisix/admin/routes.lua | 36 +++++++-----------------------------
apisix/admin/services.lua | 35 ++++++-----------------------------
apisix/admin/upstreams.lua | 35 ++++++-----------------------------
apisix/core/table.lua | 19 +++++++++++++++++++
doc/admin-api-cn.md | 6 +++---
doc/admin-api.md | 6 +++---
t/admin/global-rules.t | 5 +++--
t/admin/routes.t | 29 ++++++++++++++++-------------
t/admin/services.t | 23 ++++++++++++++---------
t/admin/upstream.t | 32 +++++++++++++++++++-------------
11 files changed, 102 insertions(+), 159 deletions(-)
diff --git a/apisix/admin/global_rules.lua b/apisix/admin/global_rules.lua
index c74d773..a29d953 100644
--- a/apisix/admin/global_rules.lua
+++ b/apisix/admin/global_rules.lua
@@ -104,19 +104,19 @@ function _M.delete(id)
end
-function _M.patch(id, conf, sub_path)
+function _M.patch(id, conf)
if not id then
return 400, {error_msg = "missing global rule id"}
end
- if not sub_path then
- return 400, {error_msg = "missing sub-path"}
- end
-
if not conf then
return 400, {error_msg = "missing new configuration"}
end
+ if type(conf) ~= "table" then
+ return 400, {error_msg = "invalid configuration"}
+ end
+
local key = "/global_rules/" .. id
local res_old, err = core.etcd.get(key)
if not res_old then
@@ -131,32 +131,9 @@ function _M.patch(id, conf, sub_path)
core.json.delay_encode(res_old, true))
local node_value = res_old.body.node.value
- local sub_value = node_value
- local sub_paths = core.utils.split_uri(sub_path)
- for i = 1, #sub_paths - 1 do
- local sub_name = sub_paths[i]
- if sub_value[sub_name] == nil then
- sub_value[sub_name] = {}
- end
- sub_value = sub_value[sub_name]
+ node_value = core.table.merge(node_value, conf);
- if type(sub_value) ~= "table" then
- return 400, "invalid sub-path: /"
- .. core.table.concat(sub_paths, 1, i)
- end
- end
-
- if type(sub_value) ~= "table" then
- return 400, "invalid sub-path: /" .. sub_path
- end
-
- local sub_name = sub_paths[#sub_paths]
- if sub_name and sub_name ~= "" then
- sub_value[sub_name] = conf
- else
- node_value = conf
- end
core.log.info("new conf: ", core.json.delay_encode(node_value, true))
local ok, err = check_conf(id, node_value, true)
diff --git a/apisix/admin/routes.lua b/apisix/admin/routes.lua
index bb7092f..6a14ce4 100644
--- a/apisix/admin/routes.lua
+++ b/apisix/admin/routes.lua
@@ -194,19 +194,19 @@ function _M.delete(id)
end
-function _M.patch(id, conf, sub_path, args)
+function _M.patch(id, conf, args)
if not id then
return 400, {error_msg = "missing route id"}
end
- if not sub_path then
- return 400, {error_msg = "missing sub-path"}
- end
-
if not conf then
return 400, {error_msg = "missing new configuration"}
end
+ if type(conf) ~= "table" then
+ return 400, {error_msg = "invalid configuration"}
+ end
+
local key = "/routes"
if id then
key = key .. "/" .. id
@@ -224,33 +224,11 @@ function _M.patch(id, conf, sub_path, args)
core.log.info("key: ", key, " old value: ",
core.json.delay_encode(res_old, true))
- local node_value = res_old.body.node.value
- local sub_value = node_value
- local sub_paths = core.utils.split_uri(sub_path)
- for i = 1, #sub_paths - 1 do
- local sub_name = sub_paths[i]
- if sub_value[sub_name] == nil then
- sub_value[sub_name] = {}
- end
-
- sub_value = sub_value[sub_name]
- if type(sub_value) ~= "table" then
- return 400, "invalid sub-path: /"
- .. core.table.concat(sub_paths, 1, i)
- end
- end
+ local node_value = res_old.body.node.value
- if type(sub_value) ~= "table" then
- return 400, "invalid sub-path: /" .. sub_path
- end
+ node_value = core.table.merge(node_value, conf);
- local sub_name = sub_paths[#sub_paths]
- if sub_name and sub_name ~= "" then
- sub_value[sub_name] = conf
- else
- node_value = conf
- end
core.log.info("new conf: ", core.json.delay_encode(node_value, true))
local id, err = check_conf(id, node_value, true)
diff --git a/apisix/admin/services.lua b/apisix/admin/services.lua
index e26ea41..7bebd3b 100644
--- a/apisix/admin/services.lua
+++ b/apisix/admin/services.lua
@@ -177,19 +177,19 @@ function _M.delete(id)
end
-function _M.patch(id, conf, sub_path)
+function _M.patch(id, conf)
if not id then
return 400, {error_msg = "missing service id"}
end
- if not sub_path then
- return 400, {error_msg = "missing sub-path"}
- end
-
if not conf then
return 400, {error_msg = "missing new configuration"}
end
+ if type(conf) ~= "table" then
+ return 400, {error_msg = "invalid configuration"}
+ end
+
local key = "/services" .. "/" .. id
local res_old, err = core.etcd.get(key)
if not res_old then
@@ -204,32 +204,9 @@ function _M.patch(id, conf, sub_path)
core.json.delay_encode(res_old, true))
local new_value = res_old.body.node.value
- local sub_value = new_value
- local sub_paths = core.utils.split_uri(sub_path)
- for i = 1, #sub_paths - 1 do
- local sub_name = sub_paths[i]
- if sub_value[sub_name] == nil then
- sub_value[sub_name] = {}
- end
- sub_value = sub_value[sub_name]
+ new_value = core.table.merge(new_value, conf);
- if type(sub_value) ~= "table" then
- return 400, "invalid sub-path: /"
- .. core.table.concat(sub_paths, 1, i)
- end
- end
-
- if type(sub_value) ~= "table" then
- return 400, "invalid sub-path: /" .. sub_path
- end
-
- local sub_name = sub_paths[#sub_paths]
- if sub_name and sub_name ~= "" then
- sub_value[sub_name] = conf
- else
- new_value = conf
- end
core.log.info("new value ", core.json.delay_encode(new_value, true))
local id, err = check_conf(id, new_value, true)
diff --git a/apisix/admin/upstreams.lua b/apisix/admin/upstreams.lua
index e989cd5..b7d2a04 100644
--- a/apisix/admin/upstreams.lua
+++ b/apisix/admin/upstreams.lua
@@ -213,19 +213,19 @@ function _M.delete(id)
end
-function _M.patch(id, conf, sub_path)
+function _M.patch(id, conf)
if not id then
return 400, {error_msg = "missing upstream id"}
end
- if not sub_path then
- return 400, {error_msg = "missing sub-path"}
- end
-
if not conf then
return 400, {error_msg = "missing new configuration"}
end
+ if type(conf) ~= "table" then
+ return 400, {error_msg = "invalid configuration"}
+ end
+
local key = "/upstreams" .. "/" .. id
local res_old, err = core.etcd.get(key)
if not res_old then
@@ -240,32 +240,9 @@ function _M.patch(id, conf, sub_path)
core.json.delay_encode(res_old, true))
local new_value = res_old.body.node.value
- local sub_value = new_value
- local sub_paths = core.utils.split_uri(sub_path)
- for i = 1, #sub_paths - 1 do
- local sub_name = sub_paths[i]
- if sub_value[sub_name] == nil then
- sub_value[sub_name] = {}
- end
- sub_value = sub_value[sub_name]
+ new_value = core.table.merge(new_value, conf);
- if type(sub_value) ~= "table" then
- return 400, "invalid sub-path: /"
- .. core.table.concat(sub_paths, 1, i)
- end
- end
-
- if type(sub_value) ~= "table" then
- return 400, "invalid sub-path: /" .. sub_path
- end
-
- local sub_name = sub_paths[#sub_paths]
- if sub_name and sub_name ~= "" then
- sub_value[sub_name] = conf
- else
- new_value = conf
- end
core.log.info("new value ", core.json.delay_encode(new_value, true))
local id, err = check_conf(id, new_value, true)
diff --git a/apisix/core/table.lua b/apisix/core/table.lua
index 14e0165..e666e16 100644
--- a/apisix/core/table.lua
+++ b/apisix/core/table.lua
@@ -85,5 +85,24 @@ local function deepcopy(orig)
end
_M.deepcopy = deepcopy
+local ngx_null = ngx.null
+local function merge(origin, extend)
+ for k,v in pairs(extend) do
+ if type(v) == "table" then
+ if type(origin[k] or false) == "table" then
+ merge(origin[k] or {}, extend[k] or {})
+ else
+ origin[k] = v
+ end
+ elseif v == ngx_null then
+ origin[k] = nil
+ else
+ origin[k] = v
+ end
+ end
+
+ return origin
+end
+_M.merge = merge
return _M
diff --git a/doc/admin-api-cn.md b/doc/admin-api-cn.md
index 7a7d355..40303f4 100644
--- a/doc/admin-api-cn.md
+++ b/doc/admin-api-cn.md
@@ -40,7 +40,7 @@
|PUT |/apisix/admin/routes/{id}|{...}|根据 id 创建资源|
|POST |/apisix/admin/routes |{...}|创建资源,id 由后台服务自动生成|
|DELETE |/apisix/admin/routes/{id}|无|删除资源|
-|PATCH |/apisix/admin/routes/{id}/{path}|{...}|修改已有 Route 的部分内容,其他不涉及部分会原样保留。|
+|PATCH |/apisix/admin/routes/{id}|{...}|修改已有 Route 的部分内容,其他不涉及部分会原样保留;如果你要删除某个属性,将该属性的值设置为null 即可删除|
> uri 请求参数:
@@ -187,7 +187,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f13
|PUT |/apisix/admin/services/{id}|{...}|根据 id 创建资源|
|POST |/apisix/admin/services |{...}|创建资源,id 由后台服务自动生成|
|DELETE |/apisix/admin/services/{id}|无|删除资源|
-|PATCH |/apisix/admin/services/{id}/{path}|{...}|修改已有 Service 的部分内容,其他不涉及部分会原样保留。|
+|PATCH |/apisix/admin/services/{id}|{...}|修改已有 Service 的部分内容,其他不涉及部分会原样保留;如果你要删除某个属性,将该属性的值设置为null 即可删除|
> body 请求参数:
@@ -336,7 +336,7 @@ Date: Thu, 26 Dec 2019 08:17:49 GMT
|PUT |/apisix/admin/upstreams/{id}|{...}|根据 id 创建资源|
|POST |/apisix/admin/upstreams |{...}|创建资源,id 由后台服务自动生成|
|DELETE |/apisix/admin/upstreams/{id}|无|删除资源|
-|PATCH |/apisix/admin/upstreams/{id}/{path}|{...}|修改已有 Route 的部分内容,其他不涉及部分会原样保留。|
+|PATCH |/apisix/admin/upstreams/{id}|{...}|修改已有 Route 的部分内容,其他不涉及部分会原样保留;如果你要删除某个属性,将该属性的值设置为null 即可删除|
> body 请求参数:
diff --git a/doc/admin-api.md b/doc/admin-api.md
index f60ccb6..4d1cc9b 100644
--- a/doc/admin-api.md
+++ b/doc/admin-api.md
@@ -41,7 +41,7 @@
|PUT |/apisix/admin/routes/{id}|{...}|Create resource by ID|
|POST |/apisix/admin/routes |{...}|Create resource, and ID is generated by server|
|DELETE |/apisix/admin/routes/{id}|NULL|Remove resource|
-|PATCH |/apisix/admin/routes/{id}/{path}|{...}|Update targeted content|
+|PATCH |/apisix/admin/routes/{id}|{...}|Update targeted content, if you want to remove an attribute, set the attribute value to null to remove|
> URI Request Parameters:
@@ -183,7 +183,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f13
|PUT |/apisix/admin/services/{id}|{...}|Create resource by ID|
|POST |/apisix/admin/services |{...}|Create resource, and ID is generated by server|
|DELETE |/apisix/admin/services/{id}|NULL|Remove resource|
-|PATCH |/apisix/admin/routes/{id}/{path}|{...}|Update targeted content|
+|PATCH |/apisix/admin/routes/{id}|{...}|Update targeted content, if you want to remove an attribute, set the attribute value to null to remove|
> Request Body Parameters:
@@ -328,7 +328,7 @@ Return response from etcd currently.
|PUT |/apisix/admin/upstreams/{id}|{...}|Create resource by ID|
|POST |/apisix/admin/upstreams |{...}|Create resource, and ID is generated by server|
|DELETE |/apisix/admin/upstreams/{id}|NULL|Remove resource|
-|PATCH |/apisix/admin/upstreams/{id}/{path}|{...}|Update targeted content|
+|PATCH |/apisix/admin/upstreams/{id}|{...}|Update targeted content, if you want to remove an attribute, set the attribute value to null to remove|
> Request Body Parameters:
diff --git a/t/admin/global-rules.t b/t/admin/global-rules.t
index aa7a0c6..ee1f10c 100644
--- a/t/admin/global-rules.t
+++ b/t/admin/global-rules.t
@@ -164,16 +164,17 @@ passed
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
- local code, body = t('/apisix/admin/global_rules/1/plugins',
+ local code, body = t('/apisix/admin/global_rules/1',
ngx.HTTP_PATCH,
[[{
+ "plugins": {
"limit-count": {
"count": 3,
"time_window": 60,
"rejected_code": 503,
"key": "remote_addr"
}
- }]],
+ }}]],
[[{
"node": {
"value": {
diff --git a/t/admin/routes.t b/t/admin/routes.t
index 78ab5c6..ac8078b 100644
--- a/t/admin/routes.t
+++ b/t/admin/routes.t
@@ -993,9 +993,11 @@ passed
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
- local code, body = t('/apisix/admin/routes/1/methods',
+ local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PATCH,
- '["GET"]',
+ [[{
+ "methods": ["GET", null, null, null, null, null, null, null, null]
+ }]],
[[{
"node": {
"value": {
@@ -1027,9 +1029,11 @@ passed
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
- local code, body = t('/apisix/admin/routes/1/uri',
+ local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PATCH,
- '"/patch_test"',
+ [[{
+ "uri": "/patch_test"
+ }]],
[[{
"node": {
"value": {
@@ -1054,23 +1058,22 @@ passed
-=== TEST 30: patch route(whole)
+=== TEST 30: patch route(multi)
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
- local code, body = t('/apisix/admin/routes/1/',
+ local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PATCH,
[[{
"methods": ["GET"],
"upstream": {
"nodes": {
- "127.0.0.1:8080": 1
- },
- "type": "roundrobin"
+ "127.0.0.1:8080": null,
+ "127.0.0.2:8080": 1
+ }
},
- "desc": "new route",
- "uri": "/index.html"
+ "desc": "new route"
}]],
[[{
"node": {
@@ -1078,11 +1081,11 @@ passed
"methods": [
"GET"
],
- "uri": "/index.html",
+ "uri": "/patch_test",
"desc": "new route",
"upstream": {
"nodes": {
- "127.0.0.1:8080": 1
+ "127.0.0.2:8080": 1
},
"type": "roundrobin"
}
diff --git a/t/admin/services.t b/t/admin/services.t
index 6c6f503..a3aaa59 100644
--- a/t/admin/services.t
+++ b/t/admin/services.t
@@ -633,7 +633,7 @@ GET /t
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
- local code, body = t('/apisix/admin/services/1/',
+ local code, body = t('/apisix/admin/services/1',
ngx.HTTP_PATCH,
[[{
"upstream": {
@@ -679,9 +679,11 @@ passed
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
- local code, body = t('/apisix/admin/services/1/desc',
+ local code, body = t('/apisix/admin/services/1',
ngx.HTTP_PATCH,
- '"new 19 service"',
+ [[{
+ "desc": "new 19 service"
+ }]],
[[{
"node": {
"value": {
@@ -717,20 +719,23 @@ passed
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
- local code, body = t('/apisix/admin/services/1/upstream',
+ local code, body = t('/apisix/admin/services/1',
ngx.HTTP_PATCH,
[[{
- "nodes": {
- "127.0.0.1:8081": 3,
- "127.0.0.1:8082": 4
- },
- "type": "roundrobin"
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:8081": 3,
+ "127.0.0.1:8082": 4
+ },
+ "type": "roundrobin"
+ }
}]],
[[{
"node": {
"value": {
"upstream": {
"nodes": {
+ "127.0.0.1:8080": 1,
"127.0.0.1:8081": 3,
"127.0.0.1:8082": 4
},
diff --git a/t/admin/upstream.t b/t/admin/upstream.t
index 6ec7b22..661186d 100644
--- a/t/admin/upstream.t
+++ b/t/admin/upstream.t
@@ -652,7 +652,7 @@ GET /t
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
- local code, body = t('/apisix/admin/upstreams/1/',
+ local code, body = t('/apisix/admin/upstreams/1',
ngx.HTTP_PATCH,
[[{
"nodes": {
@@ -694,9 +694,11 @@ passed
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
- local code, body = t('/apisix/admin/upstreams/1/desc',
+ local code, body = t('/apisix/admin/upstreams/1',
ngx.HTTP_PATCH,
- '"new 21 upstream"',
+ [[{
+ "desc": "new 21 upstream"
+ }]],
[[{
"node": {
"value": {
@@ -730,16 +732,19 @@ passed
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
- local code, body = t('/apisix/admin/upstreams/1/nodes',
+ local code, body = t('/apisix/admin/upstreams/1',
ngx.HTTP_PATCH,
[[{
- "127.0.0.1:8081": 3,
- "127.0.0.1:8082": 4
+ "nodes": {
+ "127.0.0.1:8081": 3,
+ "127.0.0.1:8082": 4
+ }
}]],
[[{
"node": {
"value": {
"nodes": {
+ "127.0.0.1:8080": 1,
"127.0.0.1:8081": 3,
"127.0.0.1:8082": 4
},
@@ -768,18 +773,20 @@ passed
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
- local code, body = t('/apisix/admin/upstreams/1/nodes',
+ local code, body = t('/apisix/admin/upstreams/1',
ngx.HTTP_PATCH,
[[{
- "127.0.0.1:8081": 0,
- "127.0.0.1:8082": 4
- }]],
+ "nodes": {
+ "127.0.0.1:8081": 3,
+ "127.0.0.1:8082": 0
+ }
+ }]],
[[{
"node": {
"value": {
"nodes": {
- "127.0.0.1:8081": 0,
- "127.0.0.1:8082": 4
+ "127.0.0.1:8081": 3,
+ "127.0.0.1:8082": 0
},
"type": "roundrobin",
"desc": "new 21 upstream"
@@ -800,7 +807,6 @@ passed
[error]
-
=== TEST 24: set upstream(type: chash)
--- config
location /t {