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/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 8983a8d fix(etcd): avoid getting with prefix (#2772)
8983a8d is described below
commit 8983a8dd278fec89d40b3d9a14eca9ecf9a187fd
Author: 罗泽轩 <[email protected]>
AuthorDate: Tue Nov 17 21:28:55 2020 +0800
fix(etcd): avoid getting with prefix (#2772)
Fix #2771.
---
apisix/admin/consumers.lua | 2 +-
apisix/admin/global_rules.lua | 2 +-
apisix/admin/plugin_metadata.lua | 2 +-
apisix/admin/proto.lua | 2 +-
apisix/admin/routes.lua | 2 +-
apisix/admin/services.lua | 2 +-
apisix/admin/ssl.lua | 2 +-
apisix/admin/stream_routes.lua | 2 +-
apisix/admin/upstreams.lua | 2 +-
apisix/core/config_etcd.lua | 4 ++--
apisix/core/etcd.lua | 39 +++++++++++++++++++++++++++------------
t/core/etcd.t | 38 ++++++++++++++++++++++++++++++++++++++
12 files changed, 76 insertions(+), 23 deletions(-)
diff --git a/apisix/admin/consumers.lua b/apisix/admin/consumers.lua
index 1addea7..354ed7e 100644
--- a/apisix/admin/consumers.lua
+++ b/apisix/admin/consumers.lua
@@ -99,7 +99,7 @@ function _M.get(consumer_name)
key = key .. "/" .. consumer_name
end
- local res, err = core.etcd.get(key)
+ local res, err = core.etcd.get(key, not consumer_name)
if not res then
core.log.error("failed to get consumer[", key, "]: ", err)
return 500, {error_msg = err}
diff --git a/apisix/admin/global_rules.lua b/apisix/admin/global_rules.lua
index 2ee9d70..997f444 100644
--- a/apisix/admin/global_rules.lua
+++ b/apisix/admin/global_rules.lua
@@ -83,7 +83,7 @@ function _M.get(id)
if id then
key = key .. "/" .. id
end
- local res, err = core.etcd.get(key)
+ local res, err = core.etcd.get(key, not id)
if not res then
core.log.error("failed to get global rule[", key, "]: ", err)
return 500, {error_msg = err}
diff --git a/apisix/admin/plugin_metadata.lua b/apisix/admin/plugin_metadata.lua
index be9b796..0277f46 100644
--- a/apisix/admin/plugin_metadata.lua
+++ b/apisix/admin/plugin_metadata.lua
@@ -103,7 +103,7 @@ function _M.get(key)
path = path .. "/" .. key
end
- local res, err = core.etcd.get(path)
+ local res, err = core.etcd.get(path, not key)
if not res then
core.log.error("failed to get metadata[", key, "]: ", err)
return 500, {error_msg = err}
diff --git a/apisix/admin/proto.lua b/apisix/admin/proto.lua
index f05c7c9..2095c1f 100644
--- a/apisix/admin/proto.lua
+++ b/apisix/admin/proto.lua
@@ -79,7 +79,7 @@ function _M.get(id)
key = key .. "/" .. id
end
- local res, err = core.etcd.get(key)
+ local res, err = core.etcd.get(key, not id)
if not res then
core.log.error("failed to get proto[", key, "]: ", err)
return 500, {error_msg = err}
diff --git a/apisix/admin/routes.lua b/apisix/admin/routes.lua
index a375655..324f76b 100644
--- a/apisix/admin/routes.lua
+++ b/apisix/admin/routes.lua
@@ -170,7 +170,7 @@ function _M.get(id)
key = key .. "/" .. id
end
- local res, err = core.etcd.get(key)
+ local res, err = core.etcd.get(key, not id)
if not res then
core.log.error("failed to get route[", key, "] from etcd: ", err)
return 500, {error_msg = err}
diff --git a/apisix/admin/services.lua b/apisix/admin/services.lua
index 13347b9..9ac26aa 100644
--- a/apisix/admin/services.lua
+++ b/apisix/admin/services.lua
@@ -139,7 +139,7 @@ function _M.get(id)
key = key .. "/" .. id
end
- local res, err = core.etcd.get(key)
+ local res, err = core.etcd.get(key, not id)
if not res then
core.log.error("failed to get service[", key, "]: ", err)
return 500, {error_msg = err}
diff --git a/apisix/admin/ssl.lua b/apisix/admin/ssl.lua
index 668f9ca..1905685 100644
--- a/apisix/admin/ssl.lua
+++ b/apisix/admin/ssl.lua
@@ -126,7 +126,7 @@ function _M.get(id)
key = key .. "/" .. id
end
- local res, err = core.etcd.get(key)
+ local res, err = core.etcd.get(key, not id)
if not res then
core.log.error("failed to get ssl[", key, "]: ", err)
return 500, {error_msg = err}
diff --git a/apisix/admin/stream_routes.lua b/apisix/admin/stream_routes.lua
index 969f775..b768c8a 100644
--- a/apisix/admin/stream_routes.lua
+++ b/apisix/admin/stream_routes.lua
@@ -102,7 +102,7 @@ function _M.get(id)
key = key .. "/" .. id
end
- local res, err = core.etcd.get(key)
+ local res, err = core.etcd.get(key, not id)
if not res then
core.log.error("failed to get stream route[", key, "]: ", err)
return 500, {error_msg = err}
diff --git a/apisix/admin/upstreams.lua b/apisix/admin/upstreams.lua
index b1f862d..bee4d73 100644
--- a/apisix/admin/upstreams.lua
+++ b/apisix/admin/upstreams.lua
@@ -158,7 +158,7 @@ function _M.get(id)
key = key .. "/" .. id
end
- local res, err = core.etcd.get(key)
+ local res, err = core.etcd.get(key, not id)
if not res then
core.log.error("failed to get upstream[", key, "]: ", err)
return 500, {error_msg = err}
diff --git a/apisix/core/config_etcd.lua b/apisix/core/config_etcd.lua
index e63c16b..161eb7d 100644
--- a/apisix/core/config_etcd.lua
+++ b/apisix/core/config_etcd.lua
@@ -71,7 +71,7 @@ local function getkey(etcd_cli, key)
return nil, "failed to get key from etcd"
end
- res, err = etcd_apisix.get_format(res, key)
+ res, err = etcd_apisix.get_format(res, key, true)
if not res then
return nil, err
end
@@ -95,7 +95,7 @@ local function readdir(etcd_cli, key)
return nil, "failed to read etcd dir"
end
- res, err = etcd_apisix.get_format(res, key .. "/")
+ res, err = etcd_apisix.get_format(res, key .. '/', true)
if not res then
return nil, err
end
diff --git a/apisix/core/etcd.lua b/apisix/core/etcd.lua
index 310bdb6..07af2b0 100644
--- a/apisix/core/etcd.lua
+++ b/apisix/core/etcd.lua
@@ -82,7 +82,9 @@ local function not_found(res)
end
-function _M.get_format(res, realkey)
+-- When `is_dir` is true, returns the value of both the dir key and its
descendants.
+-- Otherwise, return the value of key only.
+function _M.get_format(res, real_key, is_dir)
if res.body.error == "etcdserver: user name is empty" then
return nil, "insufficient credentials code: 401"
end
@@ -92,17 +94,28 @@ function _M.get_format(res, realkey)
if not res.body.kvs then
return not_found(res)
end
+
res.body.action = "get"
- -- In etcd v2, the direct key asked for is `node`, others which under this
dir are `nodes`
- -- While in v3, this structure is flatten and all keys related the key
asked for are `kvs`
- res.body.node = kvs_to_node(res.body.kvs[1])
- if not res.body.kvs[1].value then
- -- remove last "/" when necesary
- if string.sub(res.body.node.key, -1, -1) == "/" then
- res.body.node.key = string.sub(res.body.node.key, 1,
#res.body.node.key-1)
+ if not is_dir then
+ local key = res.body.kvs[1].key
+ if key ~= real_key then
+ return not_found(res)
+ end
+
+ res.body.node = kvs_to_node(res.body.kvs[1])
+
+ else
+ -- In etcd v2, the direct key asked for is `node`, others which under
this dir are `nodes`
+ -- While in v3, this structure is flatten and all keys related the key
asked for are `kvs`
+ res.body.node = kvs_to_node(res.body.kvs[1])
+ if not res.body.kvs[1].value then
+ -- remove last "/" when necesary
+ if string.byte(res.body.node.key, -1) == 47 then
+ res.body.node.key = string.sub(res.body.node.key, 1,
#res.body.node.key-1)
+ end
+ res = kvs_to_nodes(res)
end
- res = kvs_to_nodes(res)
end
res.body.kvs = nil
@@ -138,20 +151,22 @@ function _M.watch_format(v3res)
end
-function _M.get(key)
+function _M.get(key, is_dir)
local etcd_cli, prefix, err = new()
if not etcd_cli then
return nil, err
end
+ key = prefix .. key
+
-- in etcd v2, get could implicitly turn into readdir
-- while in v3, we need to do it explicitly
- local res, err = etcd_cli:readdir(prefix .. key)
+ local res, err = etcd_cli:readdir(key)
if not res then
return nil, err
end
- return _M.get_format(res, prefix .. key)
+ return _M.get_format(res, key, is_dir)
end
diff --git a/t/core/etcd.t b/t/core/etcd.t
index 7dc3a38..761dd4c 100644
--- a/t/core/etcd.t
+++ b/t/core/etcd.t
@@ -333,3 +333,41 @@ Host: foo.com
--- no_error_log
[error]
--- timeout: 20
+
+
+
+=== TEST 5: get single
+--- config
+ location /t {
+ content_by_lua_block {
+ local etcd = require("apisix.core.etcd")
+ assert(etcd.set("/ab", "ab"))
+ local res, err = etcd.get("/a")
+ ngx.status = res.status
+ }
+ }
+--- request
+GET /t
+--- error_code: 404
+--- no_error_log
+[error]
+
+
+
+=== TEST 6: get prefix
+--- config
+ location /t {
+ content_by_lua_block {
+ local etcd = require("apisix.core.etcd")
+ assert(etcd.set("/ab", "ab"))
+ local res, err = etcd.get("/a", true)
+ ngx.status = res.status
+ ngx.say(res.body.node.value)
+ }
+ }
+--- request
+GET /t
+--- response_body
+ab
+--- no_error_log
+[error]