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]

Reply via email to