This is an automated email from the ASF dual-hosted git repository.

bzp2010 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 783660158 fix: missing etcd init_dir and unable to list resource 
(#10569)
783660158 is described below

commit 7836601581651061287c4bc7d8ed0c515b3bfb8b
Author: AlinsRan <alins...@apache.org>
AuthorDate: Thu Nov 30 21:41:01 2023 +0800

    fix: missing etcd init_dir and unable to list resource (#10569)
---
 apisix/core/etcd.lua | 32 +++++++++++++++-----------------
 t/admin/routes.t     | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 t/core/config_etcd.t |  2 +-
 t/core/etcd.t        | 28 +++++++++++++++++++++++++++-
 4 files changed, 95 insertions(+), 19 deletions(-)

diff --git a/apisix/core/etcd.lua b/apisix/core/etcd.lua
index 5cd103858..a537c8840 100644
--- a/apisix/core/etcd.lua
+++ b/apisix/core/etcd.lua
@@ -154,16 +154,6 @@ local function kvs_to_node(kvs)
 end
 _M.kvs_to_node = kvs_to_node
 
-local function kvs_to_nodes(res)
-    res.body.node.dir = true
-    res.body.node.nodes = setmetatable({}, array_mt)
-    for i=2, #res.body.kvs do
-        res.body.node.nodes[i-1] = kvs_to_node(res.body.kvs[i])
-    end
-    return res
-end
-
-
 local function not_found(res)
     res.body.message = "Key not found"
     res.reason = "Not found"
@@ -211,13 +201,22 @@ function _M.get_format(res, real_key, is_dir, formatter)
     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 necessary
-            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)
+        res.body.node = {
+            key = real_key,
+            dir = true,
+            nodes = setmetatable({}, array_mt)
+        }
+        local kvs = res.body.kvs
+        if #kvs >= 1 and not kvs[1].value then
+            res.body.node.createdIndex = tonumber(kvs[1].create_revision)
+            res.body.node.modifiedIndex = tonumber(kvs[1].mod_revision)
+            for i=2, #kvs do
+                res.body.node.nodes[i-1] = kvs_to_node(kvs[i])
+            end
+        else
+            for i=1, #kvs do
+                res.body.node.nodes[i] = kvs_to_node(kvs[i])
             end
-            res = kvs_to_nodes(res)
         end
     end
 
@@ -316,7 +315,6 @@ function _M.get(key, is_dir)
     if not res then
         return nil, err
     end
-
     return _M.get_format(res, key, is_dir)
 end
 
diff --git a/t/admin/routes.t b/t/admin/routes.t
index 17b30dc4c..835d4b390 100644
--- a/t/admin/routes.t
+++ b/t/admin/routes.t
@@ -734,3 +734,55 @@ GET /t
 --- error_code: 400
 --- response_body_like
 {"error_msg":"invalid configuration: property \\"host\\" validation failed: 
failed to match pattern .*
+
+
+
+=== TEST 23: removing the init_dir key from etcd can still list all routes
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local json = require("toolkit.json")
+            local etcd = require("apisix.core.etcd")
+
+            local code, body = t('/apisix/admin/routes/del_init_dir_1',
+                 ngx.HTTP_PUT,
+                 [[{
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:8080": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "uri": "/index.html"
+                }]]
+                )
+            assert(code == 200 or code == 201, "failed to add route")
+
+            local code, body = t('/apisix/admin/routes/del_init_dir_2',
+                 ngx.HTTP_PUT,
+                 [[{
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:8080": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "uri": "/index.html"
+                }]]
+                )
+            assert(code == 200 or code == 201, "failed to add route")
+
+            -- remove the init_dir key from etcd
+            assert(etcd.delete("/routes/"))
+
+            -- list all routes and check them
+            local code, body, res = t('/apisix/admin/routes', ngx.HTTP_GET)
+            ngx.status = code
+            ngx.say(res)
+        }
+    }
+--- request
+GET /t
+--- response_body eval
+qr/del_init_dir_1.*del_init_dir_2/
diff --git a/t/core/config_etcd.t b/t/core/config_etcd.t
index d81cf5615..659c15285 100644
--- a/t/core/config_etcd.t
+++ b/t/core/config_etcd.t
@@ -354,7 +354,7 @@ GET /t
 --- grep_error_log eval
 qr/readdir key: fake res: .+/
 --- grep_error_log_out eval
-qr/readdir key: fake res: 
\{("value":"bar","key":"foo"|"key":"foo","value":"bar")\}/
+qr/readdir key: fake res: 
\[\{("value":"bar","key":"foo"|"key":"foo","value":"bar")\}\]/
 --- wait: 1
 --- no_error_log
 [error]
diff --git a/t/core/etcd.t b/t/core/etcd.t
index 670ada081..d6f5d7085 100644
--- a/t/core/etcd.t
+++ b/t/core/etcd.t
@@ -351,8 +351,10 @@ GET /t
             local etcd = require("apisix.core.etcd")
             assert(etcd.set("/ab", "ab"))
             local res, err = etcd.get("/a", true)
+            assert(err == nil)
+            assert(#res.body.list == 1)
             ngx.status = res.status
-            ngx.say(res.body.node.value)
+            ngx.say(res.body.list[1].value)
         }
     }
 --- request
@@ -401,3 +403,27 @@ qr/init_by_lua.*: \S+/
 qr{init_by_lua.* ab
 init_by_lua.* 200
 init_by_lua.* 404}
+
+
+
+=== TEST 8: list multiple kv, get prefix
+--- config
+    location /t {
+        content_by_lua_block {
+            local etcd = require("apisix.core.etcd")
+            assert(etcd.set("/ab", "ab"))
+            assert(etcd.set("/abc", "abc"))
+            -- get prefix
+            local res, err = etcd.get("/a", true)
+            assert(err == nil)
+            assert(#res.body.list == 2)
+            ngx.status = res.status
+            ngx.say(res.body.list[1].value)
+            ngx.say(res.body.list[2].value)
+        }
+    }
+--- request
+GET /t
+--- response_body
+ab
+abc

Reply via email to