diff --git a/apisix/admin/global_rules.lua b/apisix/admin/global_rules.lua index a768012f9960..e9bb0057de0e 100644 --- a/apisix/admin/global_rules.lua +++ b/apisix/admin/global_rules.lua @@ -106,7 +106,7 @@ function _M.delete(id) end -function _M.patch(id, conf) +function _M.patch(id, conf, sub_path) if not id then return 400, {error_msg = "missing global rule id"} end @@ -115,8 +115,10 @@ function _M.patch(id, conf) return 400, {error_msg = "missing new configuration"} end - if type(conf) ~= "table" then - return 400, {error_msg = "invalid configuration"} + if not sub_path or sub_path == "" then + if type(conf) ~= "table" then + return 400, {error_msg = "invalid configuration"} + end end local key = "/global_rules/" .. id @@ -134,7 +136,15 @@ function _M.patch(id, conf) local node_value = res_old.body.node.value - node_value = core.table.merge(node_value, conf); + if sub_path and sub_path ~= "" then + local code, err, node_val = core.table.patch(node_value, sub_path, conf) + node_value = node_val + if code then + return code, err + end + else + node_value = core.table.merge(node_value, conf); + end core.log.info("new conf: ", core.json.delay_encode(node_value, true)) diff --git a/apisix/admin/routes.lua b/apisix/admin/routes.lua index 2ce284be71c9..d9174356b5b8 100644 --- a/apisix/admin/routes.lua +++ b/apisix/admin/routes.lua @@ -196,7 +196,7 @@ function _M.delete(id) end -function _M.patch(id, conf, args) +function _M.patch(id, conf, sub_path, args) if not id then return 400, {error_msg = "missing route id"} end @@ -205,8 +205,10 @@ function _M.patch(id, conf, args) return 400, {error_msg = "missing new configuration"} end - if type(conf) ~= "table" then - return 400, {error_msg = "invalid configuration"} + if not sub_path or sub_path == "" then + if type(conf) ~= "table" then + return 400, {error_msg = "invalid configuration"} + end end local key = "/routes" @@ -226,10 +228,17 @@ function _M.patch(id, conf, args) core.log.info("key: ", key, " old value: ", core.json.delay_encode(res_old, true)) - local node_value = res_old.body.node.value - node_value = core.table.merge(node_value, conf); + if sub_path and sub_path ~= "" then + local code, err, node_val = core.table.patch(node_value, sub_path, conf) + node_value = node_val + if code then + return code, err + end + else + node_value = core.table.merge(node_value, conf); + end core.log.info("new conf: ", core.json.delay_encode(node_value, true)) diff --git a/apisix/admin/services.lua b/apisix/admin/services.lua index c10a215fd610..cbce7d150278 100644 --- a/apisix/admin/services.lua +++ b/apisix/admin/services.lua @@ -177,7 +177,7 @@ function _M.delete(id) end -function _M.patch(id, conf) +function _M.patch(id, conf, sub_path) if not id then return 400, {error_msg = "missing service id"} end @@ -186,8 +186,10 @@ function _M.patch(id, conf) return 400, {error_msg = "missing new configuration"} end - if type(conf) ~= "table" then - return 400, {error_msg = "invalid configuration"} + if not sub_path or sub_path == "" then + if type(conf) ~= "table" then + return 400, {error_msg = "invalid configuration"} + end end local key = "/services" .. "/" .. id @@ -203,19 +205,27 @@ function _M.patch(id, conf) core.log.info("key: ", key, " old value: ", core.json.delay_encode(res_old, true)) - local new_value = res_old.body.node.value + local node_value = res_old.body.node.value - new_value = core.table.merge(new_value, conf); + if sub_path and sub_path ~= "" then + local code, err, node_val = core.table.patch(node_value, sub_path, conf) + node_value = node_val + if code then + return code, err + end + else + node_value = core.table.merge(node_value, conf); + end - core.log.info("new value ", core.json.delay_encode(new_value, true)) + core.log.info("new value ", core.json.delay_encode(node_value, true)) - local id, err = check_conf(id, new_value, true) + local id, err = check_conf(id, node_value, true) if not id then return 400, err end -- TODO: this is not safe, we need to use compare-set - local res, err = core.etcd.set(key, new_value) + local res, err = core.etcd.set(key, node_value) if not res then core.log.error("failed to set new service[", key, "]: ", err) return 500, {error_msg = err} diff --git a/apisix/admin/upstreams.lua b/apisix/admin/upstreams.lua index f09093ec8aae..b74f46e2e1ba 100644 --- a/apisix/admin/upstreams.lua +++ b/apisix/admin/upstreams.lua @@ -211,7 +211,7 @@ function _M.delete(id) end -function _M.patch(id, conf) +function _M.patch(id, conf, sub_path) if not id then return 400, {error_msg = "missing upstream id"} end @@ -220,8 +220,10 @@ function _M.patch(id, conf) return 400, {error_msg = "missing new configuration"} end - if type(conf) ~= "table" then - return 400, {error_msg = "invalid configuration"} + if not sub_path or sub_path == "" then + if type(conf) ~= "table" then + return 400, {error_msg = "invalid configuration"} + end end local key = "/upstreams" .. "/" .. id @@ -239,7 +241,15 @@ function _M.patch(id, conf) local new_value = res_old.body.node.value - new_value = core.table.merge(new_value, conf); + if sub_path and sub_path ~= "" then + local code, err, node_val = core.table.patch(new_value, sub_path, conf) + new_value = node_val + if code then + return code, err + end + else + new_value = core.table.merge(new_value, conf); + end core.log.info("new value ", core.json.delay_encode(new_value, true)) diff --git a/apisix/core/table.lua b/apisix/core/table.lua index e666e162a229..5c84164e38d3 100644 --- a/apisix/core/table.lua +++ b/apisix/core/table.lua @@ -22,6 +22,7 @@ local new_tab = require("table.new") local nkeys = require("table.nkeys") local pairs = pairs local type = type +local ngx_re = require("ngx.re") local _M = { @@ -90,7 +91,11 @@ 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 {}) + if _M.nkeys(origin[k]) ~= #origin[k] then + merge(origin[k] or {}, extend[k] or {}) + else + origin[k] = v + end else origin[k] = v end @@ -105,4 +110,38 @@ local function merge(origin, extend) end _M.merge = merge + +local function patch(node_value, sub_path, conf) + local sub_value = node_value + local sub_paths = ngx_re.split(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: /" + .. _M.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 + + return nil, nil, node_value +end +_M.patch = patch + + return _M diff --git a/doc/admin-api.md b/doc/admin-api.md index b1112e9ab238..b404ced1ad3f 100644 --- a/doc/admin-api.md +++ b/doc/admin-api.md @@ -39,7 +39,8 @@ |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}|{...}|Update targeted content, if you want to remove an attribute, set the attribute value to null to remove| +|PATCH |/apisix/admin/routes/{id}|{...}|Standard PATCH. Update some attributes of the existing Route, and other attributes not involved will remain as they are; if you want to delete an attribute, set the value of the attribute Set to null to delete; especially, when the value of the attribute is an array, the attribute will be updated in full| +|PATCH |/apisix/admin/routes/{id}/{path}|{...}|SubPath PATCH, specify the attribute of Route to be updated through {path}, update the value of this attribute in full, and other attributes that are not involved will remain as they are. The difference between the two PATCH can refer to the following examples| > URI Request Parameters: @@ -131,6 +132,96 @@ HTTP/1.1 201 Created Date: Sat, 31 Aug 2019 01:17:15 GMT ... + +# Add an upstream node to the Route +$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "upstream": { + "nodes": { + "39.97.63.216:80": 1 + } + } +}' +HTTP/1.1 200 OK +... + +After successful execution, upstream nodes will be updated to: +{ + "39.97.63.215:80": 1, + "39.97.63.216:80": 1 +} + + +# Update the weight of an upstream node to the Route +$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "upstream": { + "nodes": { + "39.97.63.216:80": 10 + } + } +}' +HTTP/1.1 200 OK +... + +After successful execution, upstream nodes will be updated to: +{ + "39.97.63.215:80": 1, + "39.97.63.216:80": 10 +} + + +# Delete an upstream node for the Route +$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "upstream": { + "nodes": { + "39.97.63.215:80": null + } + } +}' +HTTP/1.1 200 OK +... + +After successful execution, upstream nodes will be updated to: +{ + "39.97.63.216:80": 10 +} + + +# Replace methods of the Route -- array +$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d '{ + "methods": ["GET", "POST"] +}' +HTTP/1.1 200 OK +... + +After successful execution, methods will not retain the original data, and the entire update is: +["GET", "POST"] + + +# Replace upstream nodes of the Route -- sub path +$ curl http://127.0.0.1:9080/apisix/admin/routes/1/upstream/nodes -H'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "39.97.63.200:80": 1 +}' +HTTP/1.1 200 OK +... + +After successful execution, nodes will not retain the original data, and the entire update is: +{ + "39.97.63.200:80": 1 +} + + +# Replace methods of the Route -- sub path +$ curl http://127.0.0.1:9080/apisix/admin/routes/1/methods -H'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d'["POST", "DELETE", " PATCH"]' +HTTP/1.1 200 OK +... + +After successful execution, methods will not retain the original data, and the entire update is: +["POST", "DELETE", "PATCH"] + ``` > Response Parameters @@ -183,7 +274,8 @@ 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}|{...}|Update targeted content, if you want to remove an attribute, set the attribute value to null to remove| +|PATCH |/apisix/admin/services/{id}|{...}|Standard PATCH. Update some attributes of the existing Service, and other attributes not involved will remain as they are; if you want to delete an attribute, set the value of the attribute Set to null to delete; especially, when the value of the attribute is an array, the attribute will be updated in full| +|PATCH |/apisix/admin/services/{id}/{path}|{...}|SubPath PATCH, specify the attribute of Service to be updated through {path}, update the value of this attribute in full, and other attributes that are not involved will remain as they are. The difference between the two PATCH can refer to the following examples| > Request Body Parameters: @@ -230,17 +322,78 @@ $ curl http://127.0.0.1:9080/apisix/admin/services/201 -H 'X-API-KEY: edd1c9f03 }' HTTP/1.1 201 Created -Date: Thu, 26 Dec 2019 03:48:47 GMT -Content-Type: text/plain -Transfer-Encoding: chunked -Connection: keep-alive -Access-Control-Allow-Origin: * -Access-Control-Allow-Credentials: true -Access-Control-Expose-Headers: * -Access-Control-Max-Age: 3600 -Server: APISIX web server - -{"node":{"value":{"upstream":{"nodes":{"39.97.63.215:80":1},"type":"roundrobin"},"plugins":{"limit-count":{"time_window":60,"count":2,"rejected_code":503,"key":"remote_addr","policy":"local"}}},"createdIndex":60,"key":"\/apisix\/services\/201","modifiedIndex":60},"action":"set"} +... + + +# Add an upstream node to the Service +$ curl http://127.0.0.1:9080/apisix/admin/services/201 -H'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "upstream": { + "nodes": { + "39.97.63.216:80": 1 + } + } +}' +HTTP/1.1 200 OK +... + +After successful execution, upstream nodes will be updated to: +{ + "39.97.63.215:80": 1, + "39.97.63.216:80": 1 +} + + +# Update the weight of an upstream node to the Service +$ curl http://127.0.0.1:9080/apisix/admin/services/201 -H'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "upstream": { + "nodes": { + "39.97.63.216:80": 10 + } + } +}' +HTTP/1.1 200 OK +... + +After successful execution, upstream nodes will be updated to: +{ + "39.97.63.215:80": 1, + "39.97.63.216:80": 10 +} + + +# Delete an upstream node for the Service +$ curl http://127.0.0.1:9080/apisix/admin/services/201 -H'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "upstream": { + "nodes": { + "39.97.63.215:80": null + } + } +}' +HTTP/1.1 200 OK +... + +After successful execution, upstream nodes will be updated to: +{ + "39.97.63.216:80": 10 +} + + +# Replace upstream nodes of the Service +$ curl http://127.0.0.1:9080/apisix/admin/services/201/upstream/nodes -H'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "39.97.63.200:80": 1 +}' +HTTP/1.1 200 OK +... + +After successful execution, upstream nodes will not retain the original data, and the entire update is: +{ + "39.97.63.200:80": 1 +} + ``` > Response Parameters @@ -330,7 +483,8 @@ 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}|{...}|Update targeted content, if you want to remove an attribute, set the attribute value to null to remove| +|PATCH |/apisix/admin/upstreams/{id}|{...}|Standard PATCH. Update some attributes of the existing Upstream, and other attributes not involved will remain as they are; if you want to delete an attribute, set the value of the attribute Set to null to delete; especially, when the value of the attribute is an array, the attribute will be updated in full| +|PATCH |/apisix/admin/upstreams/{id}/{path}|{...}|SubPath PATCH, specify the attribute of Upstream to be updated through {path}, update the value of this attribute in full, and other attributes that are not involved will remain as they are. The difference between the two PATCH can refer to the following example| > Request Body Parameters: @@ -396,7 +550,69 @@ Date: Thu, 26 Dec 2019 04:19:34 GMT Content-Type: text/plain ... -{"node":{"value":{"nodes":{"127.0.0.1:80":1,"foo.com:80":3,"127.0.0.2:80":2},"type":"roundrobin"},"createdIndex":61,"key":"\/apisix\/upstreams\/100","modifiedIndex":61},"action":"set"} + +# Add a node to the Upstream +$ curl http://127.0.0.1:9080/apisix/admin/upstreams/100 -H'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "nodes": { + "39.97.63.216:80": 1 + } +}' +HTTP/1.1 200 OK +... + +After successful execution, nodes will be updated to: +{ + "39.97.63.215:80": 1, + "39.97.63.216:80": 1 +} + + +# Update the weight of a node to the Upstream +$ curl http://127.0.0.1:9080/apisix/admin/upstreams/100 -H'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "nodes": { + "39.97.63.216:80": 10 + } +}' +HTTP/1.1 200 OK +... + +After successful execution, nodes will be updated to: +{ + "39.97.63.215:80": 1, + "39.97.63.216:80": 10 +} + + +# Delete a node for the Upstream +$ curl http://127.0.0.1:9080/apisix/admin/upstreams/100 -H'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "nodes": { + "39.97.63.215:80": null + } +}' +HTTP/1.1 200 OK +... + +After successful execution, nodes will be updated to: +{ + "39.97.63.216:80": 10 +} + + +# Replace the nodes of the Upstream +$ curl http://127.0.0.1:9080/apisix/admin/upstreams/100/nodes -H'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "39.97.63.200:80": 1 +}' +HTTP/1.1 200 OK +... + +After the execution is successful, nodes will not retain the original data, and the entire update is: +{ + "39.97.63.200:80": 1 +} ``` diff --git a/doc/zh-cn/admin-api.md b/doc/zh-cn/admin-api.md index 16256611d791..e0b0e912c4b6 100644 --- a/doc/zh-cn/admin-api.md +++ b/doc/zh-cn/admin-api.md @@ -40,7 +40,10 @@ |PUT |/apisix/admin/routes/{id}|{...}|根据 id 创建资源| |POST |/apisix/admin/routes |{...}|创建资源,id 由后台服务自动生成| |DELETE |/apisix/admin/routes/{id}|无|删除资源| -|PATCH |/apisix/admin/routes/{id}|{...}|修改已有 Route 的部分内容,其他不涉及部分会原样保留;如果你要删除某个属性,将该属性的值设置为null 即可删除| +|PATCH |/apisix/admin/routes/{id}|{...}|标准 PATCH ,修改已有 Route 的部分属性,其他不涉及的属性会原样保留;如果你要删除某个属性,将该属性的值设置为null 即可删除;特别地,当需要修改属性的值为数组时,该属性将全量更新| +|PATCH |/apisix/admin/routes/{id}/{path}|{...}|SubPath PATCH,通过 {path} 指定 Route 要更新的属性,全量更新该属性的数据,其他不涉及的属性会原样保留。两种 PATCH 的区别可以参考后面的示例| + + > uri 请求参数: @@ -136,6 +139,97 @@ HTTP/1.1 201 Created Date: Sat, 31 Aug 2019 01:17:15 GMT ... + +# 给路由增加一个 upstream node +$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "upstream": { + "nodes": { + "39.97.63.216:80": 1 + } + } +}' +HTTP/1.1 200 OK +... + +执行成功后,upstream nodes 将更新为: +{ + "39.97.63.215:80": 1, + "39.97.63.216:80": 1 +} + + +# 给路由更新一个 upstream node 的权重 +$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "upstream": { + "nodes": { + "39.97.63.216:80": 10 + } + } +}' +HTTP/1.1 200 OK +... + +执行成功后,upstream nodes 将更新为: +{ + "39.97.63.215:80": 1, + "39.97.63.216:80": 10 +} + + +# 给路由删除一个 upstream node +$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "upstream": { + "nodes": { + "39.97.63.215:80": null + } + } +}' +HTTP/1.1 200 OK +... + +执行成功后,upstream nodes 将更新为: +{ + "39.97.63.216:80": 10 +} + + +# 替换路由的 methods -- 数组 +$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d '{ + "methods": ["GET", "POST"] +}' +HTTP/1.1 200 OK +... + +执行成功后,methods 将不保留原来的数据,整个更新为: +["GET", "POST"] + + +# 替换路由的 upstream nodes -- sub path +$ curl http://127.0.0.1:9080/apisix/admin/routes/1/upstream/nodes -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "39.97.63.200:80": 1 +}' +HTTP/1.1 200 OK +... + +执行成功后,nodes 将不保留原来的数据,整个更新为: +{ + "39.97.63.200:80": 1 +} + + +# 替换路由的 methods -- sub path +$ curl http://127.0.0.1:9080/apisix/admin/routes/1/methods -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d '["POST", "DELETE", "PATCH"]' +HTTP/1.1 200 OK +... + +执行成功后,methods 将不保留原来的数据,整个更新为: +["POST", "DELETE", "PATCH"] + + ``` > 应答参数 @@ -189,7 +283,9 @@ 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}|{...}|修改已有 Service 的部分内容,其他不涉及部分会原样保留;如果你要删除某个属性,将该属性的值设置为null 即可删除| +|PATCH |/apisix/admin/services/{id}|{...}|标准 PATCH ,修改已有 Service 的部分属性,其他不涉及的属性会原样保留;如果你要删除某个属性,将该属性的值设置为null 即可删除;特别地,当需要修改属性的值为数组时,该属性将全量更新| +|PATCH |/apisix/admin/services/{id}/{path}|{...}|SubPath PATCH,通过 {path} 指定 Service 需要更新的属性,全量更新该属性的数据,其他不涉及的属性会原样保留| + > body 请求参数: @@ -239,17 +335,78 @@ $ curl http://127.0.0.1:9080/apisix/admin/services/201 -H 'X-API-KEY: edd1c9f03 # 返回结果 HTTP/1.1 201 Created -Date: Thu, 26 Dec 2019 03:48:47 GMT -Content-Type: text/plain -Transfer-Encoding: chunked -Connection: keep-alive -Access-Control-Allow-Origin: * -Access-Control-Allow-Credentials: true -Access-Control-Expose-Headers: * -Access-Control-Max-Age: 3600 -Server: APISIX web server - -{"node":{"value":{"upstream":{"nodes":{"39.97.63.215:80":1},"type":"roundrobin"},"plugins":{"limit-count":{"time_window":60,"count":2,"rejected_code":503,"key":"remote_addr","policy":"local"}}},"createdIndex":60,"key":"\/apisix\/services\/201","modifiedIndex":60},"action":"set"} +... + + +# 给 Service 增加一个 upstream node +$ curl http://127.0.0.1:9080/apisix/admin/services/201 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "upstream": { + "nodes": { + "39.97.63.216:80": 1 + } + } +}' +HTTP/1.1 200 OK +... + +执行成功后,upstream nodes 将更新为: +{ + "39.97.63.215:80": 1, + "39.97.63.216:80": 1 +} + + +# 给 Service 更新一个 upstream node 的权重 +$ curl http://127.0.0.1:9080/apisix/admin/services/201 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "upstream": { + "nodes": { + "39.97.63.216:80": 10 + } + } +}' +HTTP/1.1 200 OK +... + +执行成功后,upstream nodes 将更新为: +{ + "39.97.63.215:80": 1, + "39.97.63.216:80": 10 +} + + +# 给 Service 删除一个 upstream node +$ curl http://127.0.0.1:9080/apisix/admin/services/201 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "upstream": { + "nodes": { + "39.97.63.215:80": null + } + } +}' +HTTP/1.1 200 OK +... + +执行成功后,upstream nodes 将更新为: +{ + "39.97.63.216:80": 10 +} + + +# 替换 Service 的 upstream nodes +$ curl http://127.0.0.1:9080/apisix/admin/services/201/upstream/nodes -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "39.97.63.200:80": 1 +}' +HTTP/1.1 200 OK +... + +执行成功后,upstream nodes 将不保留原来的数据,整个更新为: +{ + "39.97.63.200:80": 1 +} + ``` > 应答参数 @@ -340,7 +497,8 @@ 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}|{...}|修改已有 Route 的部分内容,其他不涉及部分会原样保留;如果你要删除某个属性,将该属性的值设置为null 即可删除| +|PATCH |/apisix/admin/upstreams/{id}|{...}|标准 PATCH ,修改已有 Upstream 的部分属性,其他不涉及的属性会原样保留;如果你要删除某个属性,将该属性的值设置为null 即可删除;特别地,当需要修改属性的值为数组时,该属性将全量更新| +|PATCH |/apisix/admin/upstreams/{id}/{path}|{...}|SubPath PATCH,通过 {path} 指定 Upstream 需要更新的属性,全量更新该属性的数据,其他不涉及的属性会原样保留。| > body 请求参数: @@ -403,11 +561,71 @@ $ curl http://127.0.0.1:9080/apisix/admin/upstreams/100 -H 'X-API-KEY: edd1c9f0 } }' HTTP/1.1 201 Created -Date: Thu, 26 Dec 2019 04:19:34 GMT -Content-Type: text/plain ... -{"node":{"value":{"nodes":{"127.0.0.1:80":1,"foo.com:80":3,"127.0.0.2:80":2},"type":"roundrobin"},"createdIndex":61,"key":"\/apisix\/upstreams\/100","modifiedIndex":61},"action":"set"} + +# 给 Upstream 增加一个 node +$ curl http://127.0.0.1:9080/apisix/admin/upstreams/100 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "nodes": { + "39.97.63.216:80": 1 + } +}' +HTTP/1.1 200 OK +... + +执行成功后,nodes 将更新为: +{ + "39.97.63.215:80": 1, + "39.97.63.216:80": 1 +} + + +# 给 Upstream 更新一个 node 的权重 +$ curl http://127.0.0.1:9080/apisix/admin/upstreams/100 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "nodes": { + "39.97.63.216:80": 10 + } +}' +HTTP/1.1 200 OK +... + +执行成功后,nodes 将更新为: +{ + "39.97.63.215:80": 1, + "39.97.63.216:80": 10 +} + + +# 给 Upstream 删除一个 node +$ curl http://127.0.0.1:9080/apisix/admin/upstreams/100 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "nodes": { + "39.97.63.215:80": null + } +}' +HTTP/1.1 200 OK +... + +执行成功后,nodes 将更新为: +{ + "39.97.63.216:80": 10 +} + + +# 替换 Upstream 的 nodes +$ curl http://127.0.0.1:9080/apisix/admin/upstreams/100/nodes -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PATCH -i -d ' +{ + "39.97.63.200:80": 1 +}' +HTTP/1.1 200 OK +... + +执行成功后,nodes 将不保留原来的数据,整个更新为: +{ + "39.97.63.200:80": 1 +} ``` diff --git a/t/admin/global-rules.t b/t/admin/global-rules.t index 2cda952f205c..0babd93f8201 100644 --- a/t/admin/global-rules.t +++ b/t/admin/global-rules.t @@ -206,7 +206,53 @@ passed -=== TEST 5: delete global rules +=== TEST 5: PATCH global rules (sub path) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/global_rules/1/plugins', + ngx.HTTP_PATCH, + [[{ + "limit-count": { + "count": 3, + "time_window": 60, + "rejected_code": 503, + "key": "remote_addr" + } + }]], + [[{ + "node": { + "value": { + "plugins": { + "limit-count": { + "count": 3, + "time_window": 60, + "rejected_code": 503, + "key": "remote_addr" + } + } + }, + "key": "/apisix/global_rules/1" + }, + "action": "set" + }]] + ) + + ngx.status = code + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 6: delete global rules --- config location /t { content_by_lua_block { @@ -230,7 +276,7 @@ GET /t -=== TEST 6: delete global rules(not_found) +=== TEST 7: delete global rules(not_found) --- config location /t { content_by_lua_block { @@ -254,7 +300,7 @@ GET /t -=== TEST 7: set global rules(invalid host option) +=== TEST 8: set global rules(invalid host option) --- config location /t { content_by_lua_block { @@ -288,7 +334,7 @@ GET /t -=== TEST 8: set global rules(missing plugins) +=== TEST 9: set global rules(missing plugins) --- config location /t { content_by_lua_block { @@ -312,7 +358,7 @@ GET /t -=== TEST 9: string id +=== TEST 10: string id --- config location /t { content_by_lua_block { @@ -345,7 +391,7 @@ passed -=== TEST 10: string id(DELETE) +=== TEST 11: string id(DELETE) --- config location /t { content_by_lua_block { diff --git a/t/admin/routes.t b/t/admin/routes.t index 0e0d198892a7..a890af29df7f 100644 --- a/t/admin/routes.t +++ b/t/admin/routes.t @@ -988,7 +988,7 @@ passed -=== TEST 28: patch route(new methods) +=== TEST 28: patch route(new uri) --- config location /t { content_by_lua_block { @@ -996,14 +996,63 @@ passed local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PATCH, [[{ - "methods": ["GET", null, null, null, null, null, null, null, null] + "uri": "/patch_test" + }]], + [[{ + "node": { + "value": { + "uri": "/patch_test" + }, + "key": "/apisix/routes/1" + }, + "action": "set" + }]] + ) + + ngx.status = code + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 29: 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', + ngx.HTTP_PATCH, + [[{ + "methods": ["GET"], + "upstream": { + "nodes": { + "127.0.0.1:8080": null, + "127.0.0.2:8080": 1 + } + }, + "desc": "new route" }]], [[{ "node": { "value": { "methods": [ "GET" - ] + ], + "uri": "/patch_test", + "desc": "new route", + "upstream": { + "nodes": { + "127.0.0.2:8080": 1 + }, + "type": "roundrobin" + } }, "key": "/apisix/routes/1" }, @@ -1024,7 +1073,7 @@ passed -=== TEST 29: patch route(new uri) +=== TEST 30: patch route(new methods) --- config location /t { content_by_lua_block { @@ -1032,12 +1081,12 @@ passed local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PATCH, [[{ - "uri": "/patch_test" + "methods": ["GET", "DELETE", "PATCH", "POST", "PUT"] }]], [[{ "node": { "value": { - "uri": "/patch_test" + "methods": ["GET", "DELETE", "PATCH", "POST", "PUT"] }, "key": "/apisix/routes/1" }, @@ -1058,22 +1107,123 @@ passed -=== TEST 30: patch route(multi) +=== TEST 31: patch route(minus methods) --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PATCH, + [[{ + "methods": ["GET", "POST"] + }]], + [[{ + "node": { + "value": { + "methods": ["GET", "POST"] + }, + "key": "/apisix/routes/1" + }, + "action": "set" + }]] + ) + + ngx.status = code + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 32: patch route(new methods - sub path way) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1/methods', + ngx.HTTP_PATCH, + '["POST"]', + [[{ + "node": { + "value": { + "methods": [ + "POST" + ] + }, + "key": "/apisix/routes/1" + }, + "action": "set" + }]] + ) + + ngx.status = code + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 33: patch route(new uri) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1/uri', + ngx.HTTP_PATCH, + '"/patch_uri_test"', + [[{ + "node": { + "value": { + "uri": "/patch_uri_test" + }, + "key": "/apisix/routes/1" + }, + "action": "set" + }]] + ) + + ngx.status = code + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 34: patch route(whole) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1/', ngx.HTTP_PATCH, [[{ "methods": ["GET"], "upstream": { "nodes": { - "127.0.0.1:8080": null, - "127.0.0.2:8080": 1 - } + "127.0.0.1:8080": 1 + }, + "type": "roundrobin" }, - "desc": "new route" + "desc": "new route", + "uri": "/index.html" }]], [[{ "node": { @@ -1081,11 +1231,11 @@ passed "methods": [ "GET" ], - "uri": "/patch_test", + "uri": "/index.html", "desc": "new route", "upstream": { "nodes": { - "127.0.0.2:8080": 1 + "127.0.0.1:8080": 1 }, "type": "roundrobin" } @@ -1109,7 +1259,7 @@ passed -=== TEST 31: multiple hosts +=== TEST 35: multiple hosts --- config location /t { content_by_lua_block { @@ -1149,7 +1299,7 @@ passed -=== TEST 32: enable hosts and host together +=== TEST 36: enable hosts and host together --- config location /t { content_by_lua_block { @@ -1184,7 +1334,7 @@ GET /t -=== TEST 33: multiple remote_addrs +=== TEST 37: multiple remote_addrs --- config location /t { content_by_lua_block { @@ -1224,7 +1374,7 @@ passed -=== TEST 34: multiple vars +=== TEST 38: multiple vars --- config location /t { content_by_lua_block { @@ -1264,7 +1414,7 @@ passed -=== TEST 35: filter function +=== TEST 39: filter function --- config location /t { content_by_lua_block { @@ -1303,7 +1453,7 @@ passed -=== TEST 36: filter function (invalid) +=== TEST 40: filter function (invalid) --- config location /t { content_by_lua_block { @@ -1336,7 +1486,7 @@ GET /t -=== TEST 37: Support for multiple URIs +=== TEST 41: Support for multiple URIs --- config location /t { content_by_lua_block { @@ -1367,7 +1517,7 @@ passed -=== TEST 38: set route with ttl +=== TEST 42: set route with ttl --- config location /t { content_by_lua_block { @@ -1431,7 +1581,7 @@ message: Key not found -=== TEST 39: post route with ttl +=== TEST 43: post route with ttl --- config location /t { content_by_lua_block { @@ -1481,7 +1631,7 @@ message: Key not found -=== TEST 40: invalid argument: ttl +=== TEST 44: invalid argument: ttl --- config location /t { content_by_lua_block { @@ -1518,7 +1668,7 @@ GET /t -=== TEST 41: set route(id: 1, check priority) +=== TEST 45: set route(id: 1, check priority) --- config location /t { content_by_lua_block { @@ -1560,7 +1710,7 @@ passed -=== TEST 42: set route(id: 1 + priority: 0) +=== TEST 46: set route(id: 1 + priority: 0) --- config location /t { content_by_lua_block { @@ -1603,7 +1753,7 @@ passed -=== TEST 43: set route(id: 1) and upstream(type:chash, default hash_on: vars, missing key) +=== TEST 47: set route(id: 1) and upstream(type:chash, default hash_on: vars, missing key) --- config location /t { content_by_lua_block { @@ -1635,7 +1785,7 @@ GET /t -=== TEST 44: set route(id: 1) and upstream(type:chash, hash_on: header, missing key) +=== TEST 48: set route(id: 1) and upstream(type:chash, hash_on: header, missing key) --- config location /t { content_by_lua_block { @@ -1668,7 +1818,7 @@ GET /t -=== TEST 45: set route(id: 1) and upstream(type:chash, hash_on: cookie, missing key) +=== TEST 49: set route(id: 1) and upstream(type:chash, hash_on: cookie, missing key) --- config location /t { content_by_lua_block { @@ -1701,7 +1851,7 @@ GET /t -=== TEST 46: set route(id: 1) and upstream(type:chash, hash_on: consumer, missing key is ok) +=== TEST 50: set route(id: 1) and upstream(type:chash, hash_on: consumer, missing key is ok) --- config location /t { content_by_lua_block { @@ -1733,7 +1883,7 @@ passed -=== TEST 47: set route(id: 1 + name: test name) +=== TEST 51: set route(id: 1 + name: test name) --- config location /t { content_by_lua_block { @@ -1775,7 +1925,7 @@ passed -=== TEST 48: string id +=== TEST 52: string id --- config location /t { content_by_lua_block { @@ -1807,7 +1957,7 @@ passed -=== TEST 49: string id(delete) +=== TEST 53: string id(delete) --- config location /t { content_by_lua_block { @@ -1830,7 +1980,7 @@ passed -=== TEST 50: invalid string id +=== TEST 54: invalid string id --- config location /t { content_by_lua_block { @@ -1861,7 +2011,7 @@ GET /t -=== TEST 51: Verify Response Content-Type=applciation/json +=== TEST 55: Verify Response Content-Type=applciation/json --- config location /t { content_by_lua_block { diff --git a/t/admin/services.t b/t/admin/services.t index 546e2ce03b55..17c1b28caf55 100644 --- a/t/admin/services.t +++ b/t/admin/services.t @@ -759,7 +759,133 @@ passed -=== TEST 22: set service(id: 1) and upstream(type:chash, default hash_on: vars, missing key) +=== TEST 22: patch service(whole - sub path) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/services/1/', + ngx.HTTP_PATCH, + [[{ + "upstream": { + "nodes": { + "127.0.0.1:8080": 1 + }, + "type": "roundrobin" + }, + "desc": "new 22 service" + }]], + [[{ + "node": { + "value": { + "upstream": { + "nodes": { + "127.0.0.1:8080": 1 + }, + "type": "roundrobin" + }, + "desc": "new 22 service" + }, + "key": "/apisix/services/1" + }, + "action": "set" + }]] + ) + + ngx.status = code + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 23: patch service(new desc - sub path) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/services/1/desc', + ngx.HTTP_PATCH, + '"new 23 service"', + [[{ + "node": { + "value": { + "upstream": { + "nodes": { + "127.0.0.1:8080": 1 + }, + "type": "roundrobin" + }, + "desc": "new 23 service" + }, + "key": "/apisix/services/1" + }, + "action": "set" + }]] + ) + + ngx.status = code + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 24: patch service(new nodes - sub path) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/services/1/upstream', + ngx.HTTP_PATCH, + [[{ + "nodes": { + "127.0.0.2:8081": 3, + "127.0.0.3:8082": 4 + }, + "type": "roundrobin" + }]], + [[{ + "node": { + "value": { + "upstream": { + "nodes": { + "127.0.0.2:8081": 3, + "127.0.0.3:8082": 4 + }, + "type": "roundrobin" + } + } + } + }]] + ) + + ngx.status = code + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 25: set service(id: 1) and upstream(type:chash, default hash_on: vars, missing key) --- config location /t { content_by_lua_block { @@ -790,7 +916,7 @@ GET /t -=== TEST 23: set service(id: 1) and upstream(type:chash, hash_on: header, missing key) +=== TEST 26: set service(id: 1) and upstream(type:chash, hash_on: header, missing key) --- config location /t { content_by_lua_block { @@ -822,7 +948,7 @@ GET /t -=== TEST 24: set service(id: 1) and upstream(type:chash, hash_on: cookie, missing key) +=== TEST 27: set service(id: 1) and upstream(type:chash, hash_on: cookie, missing key) --- config location /t { content_by_lua_block { @@ -854,7 +980,7 @@ GET /t -=== TEST 25: set service(id: 1) and upstream(type:chash, hash_on: consumer, missing key is ok) +=== TEST 28: set service(id: 1) and upstream(type:chash, hash_on: consumer, missing key is ok) --- config location /t { content_by_lua_block { @@ -885,7 +1011,7 @@ GET /t -=== TEST 26: set service(id: 1 + test service name) +=== TEST 29: set service(id: 1 + test service name) --- config location /t { content_by_lua_block { @@ -931,7 +1057,7 @@ passed -=== TEST 27: invalid string id +=== TEST 30: invalid string id --- config location /t { content_by_lua_block { diff --git a/t/admin/upstream.t b/t/admin/upstream.t index d1167ab80418..77c196a37c19 100644 --- a/t/admin/upstream.t +++ b/t/admin/upstream.t @@ -808,7 +808,161 @@ passed -=== TEST 24: set upstream(type: chash) +=== TEST 24: patch upstream(whole - sub path) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/upstreams/1/', + ngx.HTTP_PATCH, + [[{ + "nodes": { + "127.0.0.1:8080": 1 + }, + "type": "roundrobin", + "desc": "new upstream 24" + }]], + [[{ + "node": { + "value": { + "nodes": { + "127.0.0.1:8080": 1 + }, + "type": "roundrobin", + "desc": "new upstream 24" + }, + "key": "/apisix/upstreams/1" + }, + "action": "set" + }]] + ) + + ngx.status = code + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 25: patch upstream(new desc - sub path) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/upstreams/1/desc', + ngx.HTTP_PATCH, + '"new 25 upstream"', + [[{ + "node": { + "value": { + "nodes": { + "127.0.0.1:8080": 1 + }, + "type": "roundrobin", + "desc": "new 25 upstream" + }, + "key": "/apisix/upstreams/1" + }, + "action": "set" + }]] + ) + + ngx.status = code + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 26: patch upstream(new nodes) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/upstreams/1/nodes', + ngx.HTTP_PATCH, + [[{ + "127.0.0.6:8081": 3, + "127.0.0.7:8082": 4 + }]], + [[{ + "node": { + "value": { + "nodes": { + "127.0.0.6:8081": 3, + "127.0.0.7:8082": 4 + }, + "type": "roundrobin", + "desc": "new 25 upstream" + } + } + }]] + ) + + ngx.status = code + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 27: patch upstream(weight is 0 - sub path) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/upstreams/1/nodes', + ngx.HTTP_PATCH, + [[{ + "127.0.0.7:8081": 0, + "127.0.0.8:8082": 4 + }]], + [[{ + "node": { + "value": { + "nodes": { + "127.0.0.7:8081": 0, + "127.0.0.8:8082": 4 + }, + "type": "roundrobin", + "desc": "new 25 upstream" + } + } + }]] + ) + + ngx.status = code + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- no_error_log +[error] + + + +=== TEST 28: set upstream(type: chash) --- config location /t { content_by_lua_block { @@ -837,7 +991,7 @@ passed -=== TEST 25: wrong upstream key, hash_on default vars +=== TEST 29: wrong upstream key, hash_on default vars --- config location /t { content_by_lua_block { @@ -869,7 +1023,7 @@ GET /t -=== TEST 26: set upstream with args(type: chash) +=== TEST 30: set upstream with args(type: chash) --- config location /t { content_by_lua_block { @@ -899,7 +1053,7 @@ passed -=== TEST 27: set upstream(type: chash) +=== TEST 31: set upstream(type: chash) --- config location /t { content_by_lua_block { @@ -928,7 +1082,7 @@ passed -=== TEST 28: wrong upstream key, hash_on default vars +=== TEST 32: wrong upstream key, hash_on default vars --- config location /t { content_by_lua_block { @@ -960,7 +1114,7 @@ GET /t -=== TEST 29: set upstream with args(type: chash) +=== TEST 33: set upstream with args(type: chash) --- config location /t { content_by_lua_block { @@ -990,7 +1144,7 @@ passed -=== TEST 30: type chash, hash_on: vars +=== TEST 34: type chash, hash_on: vars --- config location /t { content_by_lua_block { @@ -1021,7 +1175,7 @@ passed -=== TEST 31: type chash, hash_on: header, header name with '_', underscores_in_headers on +=== TEST 35: type chash, hash_on: header, header name with '_', underscores_in_headers on --- config location /t { content_by_lua_block { @@ -1052,7 +1206,7 @@ passed -=== TEST 32: type chash, hash_on: header, header name with invalid character +=== TEST 36: type chash, hash_on: header, header name with invalid character --- config location /t { content_by_lua_block { @@ -1084,7 +1238,7 @@ GET /t -=== TEST 33: type chash, hash_on: cookie +=== TEST 37: type chash, hash_on: cookie --- config location /t { content_by_lua_block { @@ -1115,7 +1269,7 @@ passed -=== TEST 34: type chash, hash_on: cookie, cookie name with invalid character +=== TEST 38: type chash, hash_on: cookie, cookie name with invalid character --- config location /t { content_by_lua_block { @@ -1147,7 +1301,7 @@ GET /t -=== TEST 35: type chash, hash_on: consumer, do not need upstream key +=== TEST 39: type chash, hash_on: consumer, do not need upstream key --- config location /t { content_by_lua_block { @@ -1177,7 +1331,7 @@ passed -=== TEST 36: type chash, hash_on: consumer, set key but invalid +=== TEST 40: type chash, hash_on: consumer, set key but invalid --- config location /t { content_by_lua_block { @@ -1208,7 +1362,7 @@ passed -=== TEST 37: type chash, invalid hash_on type +=== TEST 41: type chash, invalid hash_on type --- config location /t { content_by_lua_block { @@ -1240,7 +1394,7 @@ GET /t -=== TEST 38: set upstream(id: 1 + name: test name) +=== TEST 42: set upstream(id: 1 + name: test name) --- config location /t { content_by_lua_block { @@ -1282,7 +1436,7 @@ passed -=== TEST 39: string id +=== TEST 43: string id --- config location /t { content_by_lua_block { @@ -1311,7 +1465,7 @@ passed -=== TEST 40: string id(delete) +=== TEST 44: string id(delete) --- config location /t { content_by_lua_block { @@ -1334,7 +1488,7 @@ passed -=== TEST 41: invalid string id +=== TEST 45: invalid string id --- config location /t { content_by_lua_block {