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

feature: supported PATCH method for admin routes API. #365

Merged
merged 3 commits into from
Aug 4, 2019
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
30 changes: 20 additions & 10 deletions lua/apisix/admin/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ local resources = {
}


local _M = {version = 0.1}
local _M = {version = 0.2}
local router


Expand Down Expand Up @@ -46,7 +46,7 @@ local function run(params)
req_body = data
end

local code, data = resource[method](params.id, req_body)
local code, data = resource[method](params.id, req_body, params.sub_path)
if code then
core.response.exit(code, data)
end
Expand All @@ -60,25 +60,36 @@ end
local uri_route = {
{
path = [[/apisix/admin/{res:routes|services|upstreams|consumers|ssl}]],
handler = run
handler = run,
method = {"GET", "PUT", "POST", "DELETE"},
},
{
path = [[/apisix/admin/{res:routes|services|upstreams|consumers|ssl}]]
.. [[/{id:[\d\w_]+}]],
handler = run
.. [[/{id}]],
handler = run,
method = {"GET", "PUT", "POST", "DELETE"},
},
{
path = [[/apisix/admin/schema/{res:plugins}/{id:[\d\w-]+}]],
handler = run
path = [[/apisix/admin/schema/{res:plugins}/{id}]],
handler = run,
method = {"GET", "PUT", "POST", "DELETE"},
},
{
path = [[/apisix/admin/{res:schema}/]]
.. [[{id:route|service|upstream|consumer|ssl}]],
handler = run
handler = run,
method = {"GET", "PUT", "POST", "DELETE"},
},
{
path = [[/apisix/admin/plugins/list]],
handler = get_plugins_list
handler = get_plugins_list,
method = {"GET", "PUT", "POST", "DELETE"},
},
{
path = [[/apisix/admin/{res:routes|services|upstreams|consumers|ssl}]]
.. [[/{id}/{sub_path:.*}]],
handler = run,
method = {"PATCH"},
},
}

Expand All @@ -89,7 +100,6 @@ function _M.init_worker()
end

router = route.new(uri_route)

router:compile()
end

Expand Down
78 changes: 77 additions & 1 deletion lua/apisix/admin/routes.lua
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
local core = require("apisix.core")
local schema_plugin = require("apisix.admin.plugins").check_schema
local tostring = tostring
local type = type


local _M = {
version = 0.1,
version = 0.2,
}


Expand Down Expand Up @@ -146,4 +147,79 @@ function _M.delete(id)
end


function _M.patch(id, conf, sub_path)
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

local key = "/routes"
if id then
key = key .. "/" .. id
end

local res_old, err = core.etcd.get(key)
if not res_old then
core.log.error("failed to delete route[", key, "]: ", err)
return 500, {error_msg = err}
end

if res_old.status ~= 200 then
return res_old.status, res_old.body
end
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

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 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, node_value)
if not res then
core.log.error("failed to set new route[", key, "]: ", err)
return 500, {error_msg = err}
end

return res.status, res.body
end


return _M
138 changes: 128 additions & 10 deletions t/admin/routes.t
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ __DATA__
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"methods": ["GET"],
"upstream": {
"nodes": {
"127.0.0.1:8080": 1
},
"type": "roundrobin"
ngx.HTTP_PUT,
[[{
"methods": ["GET"],
"upstream": {
"nodes": {
"127.0.0.1:8080": 1
},
"desc": "new route",
"uri": "/index.html"
"type": "roundrobin"
},
"desc": "new route",
"uri": "/index.html"
}]],
[[{
"node": {
Expand Down Expand Up @@ -970,3 +970,121 @@ GET /t
passed
--- no_error_log
[error]



=== TEST 28: patch route(new methods)
--- 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,
'["GET"]',
[[{
"node": {
"value": {
"methods": [
"GET"
]
},
"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(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_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 30: 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": 1
},
"type": "roundrobin"
},
"desc": "new route",
"uri": "/index.html"
}]],
[[{
"node": {
"value": {
"methods": [
"GET"
],
"uri": "/index.html",
"desc": "new route",
"upstream": {
"nodes": {
"127.0.0.1:8080": 1
},
"type": "roundrobin"
}
},
"key": "/apisix/routes/1"
},
"action": "set"
}]]
)

ngx.status = code
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
--- no_error_log
[error]