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

baoyuan 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 2fb2fe708 fix: correct pre/post hook typos in Kubernetes discovery and 
improve cleanup safety (#12288)
2fb2fe708 is described below

commit 2fb2fe708748b412ed20ab7308ca49b147eefda1
Author: aie <[email protected]>
AuthorDate: Wed Dec 24 18:19:49 2025 +0800

    fix: correct pre/post hook typos in Kubernetes discovery and improve 
cleanup safety (#12288)
---
 apisix/discovery/kubernetes/informer_factory.lua |   4 +-
 apisix/discovery/kubernetes/init.lua             |  35 ++++--
 t/kubernetes/discovery/kubernetes3.t             | 136 +++++++++++++++++++++++
 3 files changed, 166 insertions(+), 9 deletions(-)

diff --git a/apisix/discovery/kubernetes/informer_factory.lua 
b/apisix/discovery/kubernetes/informer_factory.lua
index fd434c047..d31841b1e 100644
--- a/apisix/discovery/kubernetes/informer_factory.lua
+++ b/apisix/discovery/kubernetes/informer_factory.lua
@@ -285,7 +285,7 @@ local function list_watch(informer, apiserver)
 
     core.log.info("begin to list ", informer.kind)
     informer.fetch_state = "listing"
-    if informer.pre_List then
+    if informer.pre_list then
         informer:pre_list()
     end
 
@@ -298,7 +298,7 @@ local function list_watch(informer, apiserver)
     end
 
     informer.fetch_state = "list finished"
-    if informer.post_List then
+    if informer.post_list then
         informer:post_list()
     end
 
diff --git a/apisix/discovery/kubernetes/init.lua 
b/apisix/discovery/kubernetes/init.lua
index 695a9dd7f..b6092d8ee 100644
--- a/apisix/discovery/kubernetes/init.lua
+++ b/apisix/discovery/kubernetes/init.lua
@@ -51,7 +51,7 @@ local function sort_nodes_cmp(left, right)
     return left.port < right.port
 end
 
-local function on_endpoint_slices_modified(handle, endpoint)
+local function on_endpoint_slices_modified(handle, endpoint, operate)
     if handle.namespace_selector and
             not handle:namespace_selector(endpoint.metadata.namespace) then
         return
@@ -114,10 +114,15 @@ local function on_endpoint_slices_modified(handle, 
endpoint)
     if err then
         core.log.error("set endpoint into discovery DICT failed, ", err)
         handle.endpoint_dict:delete(endpoint_key .. "#version")
+        return
+    end
+    if operate == "list" then
+        handle.current_keys_hash[endpoint_key] = true
+        handle.current_keys_hash[endpoint_key .. "#version"] = true
     end
 end
 
-local function on_endpoint_modified(handle, endpoint)
+local function on_endpoint_modified(handle, endpoint, operate)
     if handle.namespace_selector and
             not handle:namespace_selector(endpoint.metadata.namespace) then
         return
@@ -177,6 +182,11 @@ local function on_endpoint_modified(handle, endpoint)
     if err then
         core.log.error("set endpoint into discovery DICT failed, ", err)
         handle.endpoint_dict:delete(endpoint_key .. "#version")
+        return
+    end
+    if operate == "list" then
+        handle.current_keys_hash[endpoint_key] = true
+        handle.current_keys_hash[endpoint_key .. "#version"] = true
     end
 end
 
@@ -195,12 +205,23 @@ end
 
 
 local function pre_list(handle)
-    handle.endpoint_dict:flush_all()
+    handle.current_keys_hash = {}
+    handle.existing_keys = handle.endpoint_dict:get_keys(0)
 end
 
 
 local function post_list(handle)
-    handle.endpoint_dict:flush_expired()
+    if not handle.existing_keys or not handle.current_keys_hash then
+        return
+    end
+    for _, key in ipairs(handle.existing_keys) do
+        if not handle.current_keys_hash[key] then
+            core.log.info("kubernetes discovery module find dirty data in 
shared dict, key:", key)
+            handle.endpoint_dict:delete(key)
+        end
+    end
+    handle.existing_keys = nil
+    handle.current_keys_hash = nil
 end
 
 
@@ -369,7 +390,7 @@ local function get_apiserver(conf)
 end
 
 local function create_endpoint_lrucache(endpoint_dict, endpoint_key, 
endpoint_port)
-    local endpoint_content = endpoint_dict:get_stale(endpoint_key)
+    local endpoint_content = endpoint_dict:get(endpoint_key)
     if not endpoint_content then
         core.log.error("get empty endpoint content from discovery DIC, this 
should not happen ",
                 endpoint_key)
@@ -497,7 +518,7 @@ local function single_mode_nodes(service_name)
     local endpoint_dict = ctx
     local endpoint_key = match[1]
     local endpoint_port = match[2]
-    local endpoint_version = endpoint_dict:get_stale(endpoint_key .. 
"#version")
+    local endpoint_version = endpoint_dict:get(endpoint_key .. "#version")
     if not endpoint_version then
         core.log.info("get empty endpoint version from discovery DICT ", 
endpoint_key)
         return nil
@@ -612,7 +633,7 @@ local function multiple_mode_nodes(service_name)
 
     local endpoint_key = match[2]
     local endpoint_port = match[3]
-    local endpoint_version = endpoint_dict:get_stale(endpoint_key .. 
"#version")
+    local endpoint_version = endpoint_dict:get(endpoint_key .. "#version")
     if not endpoint_version then
         core.log.info("get empty endpoint version from discovery DICT ", 
endpoint_key)
         return nil
diff --git a/t/kubernetes/discovery/kubernetes3.t 
b/t/kubernetes/discovery/kubernetes3.t
index 60b224820..441f55d66 100644
--- a/t/kubernetes/discovery/kubernetes3.t
+++ b/t/kubernetes/discovery/kubernetes3.t
@@ -242,6 +242,13 @@ _EOC_
             }
         }
 
+        location /t {
+            content_by_lua_block {
+                ngx.sleep(2)
+                ngx.exit(200)
+            }
+        }
+
 _EOC_
 
     $block->set_value("config", $config);
@@ -493,3 +500,132 @@ GET /dump
 GET /dump
 --- response_body_like
 .*"name":"default/kubernetes".*
+
+
+
+=== TEST 7: test pre_list and post_list work  for single-k8s with 
endpoint_slices
+--- log_level: info
+--- yaml_config eval: $::single_yaml_config
+--- extra_init_by_lua
+    local ngx = ngx
+    local core = require("apisix.core")
+
+    local dict = ngx.shared["kubernetes"]
+    local ok,err = dict:set("dirty_key", true)
+    if not ok then
+        core.log.error("set dirty_key to dict fail, err: ", err)
+    end
+--- request
+GET /t
+--- no_error_log
+[error]
+--- grep_error_log eval
+qr/kubernetes discovery module find dirty data in shared dict/
+--- grep_error_log_out
+kubernetes discovery module find dirty data in shared dict
+
+
+
+=== TEST 8: test pre_list and post_list work for multi-k8s with endpoint_slices
+--- log_level: info
+--- yaml_config eval: $::yaml_config
+--- extra_init_by_lua
+    local ngx = ngx
+    local core = require("apisix.core")
+
+    local dict = ngx.shared["kubernetes-first"]
+    local ok,err = dict:set("dirty_key", true)
+    if not ok then
+        core.log.error("set dirty_key to dict fail, err: ", err)
+    end
+--- request
+GET /t
+--- no_error_log
+[error]
+--- grep_error_log eval
+qr/kubernetes discovery module find dirty data in shared dict/
+--- grep_error_log_out
+kubernetes discovery module find dirty data in shared dict
+
+
+
+=== TEST 9: test pre_list and post_list work  for single-k8s with endpoints
+--- log_level: info
+--- yaml_config
+apisix:
+  node_listen: 1984
+deployment:
+  role: data_plane
+  role_data_plane:
+    config_provider: yaml
+discovery:
+  kubernetes:
+    service:
+      host: "127.0.0.1"
+      port: "6443"
+    client:
+      token_file: "/tmp/var/run/secrets/kubernetes.io/serviceaccount/token"
+    watch_endpoint_slices: false
+--- extra_init_by_lua
+    local ngx = ngx
+    local core = require("apisix.core")
+
+    local dict = ngx.shared["kubernetes"]
+    local ok,err = dict:set("dirty_key", true)
+    if not ok then
+        core.log.error("set dirty_key to dict fail, err: ", err)
+    end
+--- request
+GET /t
+--- no_error_log
+[error]
+--- grep_error_log eval
+qr/kubernetes discovery module find dirty data in shared dict/
+--- grep_error_log_out
+kubernetes discovery module find dirty data in shared dict
+
+
+
+=== TEST 10: test pre_list and post_list work for multi-k8s with endpoints
+--- log_level: info
+--- yaml_config
+apisix:
+  node_listen: 1984
+deployment:
+  role: data_plane
+  role_data_plane:
+    config_provider: yaml
+discovery:
+  kubernetes:
+    - id: first
+      service:
+        host: "127.0.0.1"
+        port: "6443"
+      client:
+        token_file: "/tmp/var/run/secrets/kubernetes.io/serviceaccount/token"
+      watch_endpoint_slices: false
+    - id: second
+      service:
+        schema: "http"
+        host: "127.0.0.1"
+        port: "6445"
+      client:
+        token_file: "/tmp/var/run/secrets/kubernetes.io/serviceaccount/token"
+      watch_endpoint_slices: false
+--- extra_init_by_lua
+    local ngx = ngx
+    local core = require("apisix.core")
+
+    local dict = ngx.shared["kubernetes-first"]
+    local ok,err = dict:set("dirty_key", true)
+    if not ok then
+        core.log.error("set dirty_key to dict fail, err: ", err)
+    end
+--- request
+GET /t
+--- no_error_log
+[error]
+--- grep_error_log eval
+qr/kubernetes discovery module find dirty data in shared dict/
+--- grep_error_log_out
+kubernetes discovery module find dirty data in shared dict

Reply via email to