This is an automated email from the ASF dual-hosted git repository.
AlinsRan 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 89c782ee2 fix(etcd): do not block writes when the deployment role
cannot be read (#13885)
89c782ee2 is described below
commit 89c782ee2e7b04e3f0ed3b6818ebc10281e561e4
Author: AlinsRan <[email protected]>
AuthorDate: Thu Aug 27 16:22:59 2026 +0800
fix(etcd): do not block writes when the deployment role cannot be read
(#13885)
---
apisix/core/etcd.lua | 12 +++++--
t/core/etcd-write.t | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 108 insertions(+), 3 deletions(-)
diff --git a/apisix/core/etcd.lua b/apisix/core/etcd.lua
index 09a6b45f4..0845a5669 100644
--- a/apisix/core/etcd.lua
+++ b/apisix/core/etcd.lua
@@ -50,7 +50,7 @@ local function is_data_plane()
local role = try_read_attr(local_conf, "deployment", "role")
if role == "data_plane" then
- return true
+ return true
end
return false
@@ -62,7 +62,9 @@ local function disable_write_if_data_plane()
local data_plane, err = is_data_plane()
if err then
log.error("failed to check data plane role: ", err)
- return true, err
+ -- the guard only warns for now, so failing to read the local config
+ -- must not be stricter than a confirmed data plane role
+ return false, err
end
if data_plane then
@@ -144,7 +146,11 @@ local function _new(etcd_conf)
return nil, nil, err
end
- etcd_cli = wrap_etcd_client(etcd_cli)
+ local wrap_err
+ etcd_cli, wrap_err = wrap_etcd_client(etcd_cli)
+ if not etcd_cli then
+ return nil, nil, wrap_err
+ end
return etcd_cli, prefix
end
diff --git a/t/core/etcd-write.t b/t/core/etcd-write.t
index 457cb76ed..8d70b6726 100644
--- a/t/core/etcd-write.t
+++ b/t/core/etcd-write.t
@@ -1105,3 +1105,102 @@ deployment:
GET /t
--- no_error_log
Data plane role should not write to etcd. This operation will be deprecated in
future releases.
+
+
+
+=== TEST 34: an unreadable local config does not block the write
+--- yaml_config
+deployment:
+ role: control_plane
+ role_control_plane:
+ config_provider: etcd
+ etcd:
+ host:
+ - "http://127.0.0.1:2379"
+ prefix: "/apisix"
+ tls:
+ verify: false
+--- config
+ location /t {
+ content_by_lua_block {
+ local config_local = require("apisix.core.config_local")
+ local origin_local_conf = config_local.local_conf
+ local fail = false
+ config_local.local_conf = function(...)
+ if fail then
+ return nil, "mocked local conf failure"
+ end
+ return origin_local_conf(...)
+ end
+
+ -- reload so that the module picks up the patched local_conf
+ package.loaded["apisix.core.etcd"] = nil
+ local etcd = require("apisix.core.etcd")
+
+ -- the first write caches the etcd client
+ local res, err = etcd.set("/foo", "bar")
+ if not res then
+ ngx.say("first set failed: ", err)
+ return
+ end
+
+ fail = true
+ res, err = etcd.set("/foo", "bar")
+ ngx.say("second set: ", res and "ok" or ("failed: " .. (err or
"nil")))
+
+ fail = false
+ etcd.delete("/foo")
+ config_local.local_conf = origin_local_conf
+ package.loaded["apisix.core.etcd"] = nil
+ }
+ }
+--- request
+GET /t
+--- response_body
+second set: ok
+--- error_log
+failed to check data plane role: mocked local conf failure
+--- no_error_log
+Data plane role should not write to etcd. This operation will be deprecated in
future releases.
+
+
+
+=== TEST 35: a client missing a wrapped method reports the reason
+--- yaml_config
+deployment:
+ role: control_plane
+ role_control_plane:
+ config_provider: etcd
+ etcd:
+ host:
+ - "http://127.0.0.1:2379"
+ prefix: "/apisix"
+ tls:
+ verify: false
+--- config
+ location /t {
+ content_by_lua_block {
+ local origin_etcd = package.loaded["resty.etcd"]
+ package.loaded["resty.etcd"] = {
+ new = function()
+ -- every other wrapped method is missing
+ return {set = function() end}
+ end,
+ }
+
+ package.loaded["apisix.core.etcd"] = nil
+ local etcd = require("apisix.core.etcd")
+
+ local res, err = etcd.set("/foo", "bar")
+ ngx.say("res: ", res and "ok" or "nil", ", err: ", err or "nil")
+
+ package.loaded["resty.etcd"] = origin_etcd
+ package.loaded["apisix.core.etcd"] = nil
+ }
+ }
+--- request
+GET /t
+--- response_body
+res: nil, err: method setnx not found in etcd client
+--- error_log
+method setnx not found in etcd client