Skip to content

Commit fa69d85

Browse files
author
georgeji
committed
Merge remote-tracking branch 'origin/master'
2 parents 043128e + 271c432 commit fa69d85

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

apisix/upstream.lua

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,35 @@ local function fill_node_info(up_conf, scheme, is_stream)
278278
return true
279279
end
280280

281+
local function match_metadata_filters(inst, filters)
282+
local metadata = inst.metadata or {}
283+
for _, f in ipairs(filters) do
284+
local key = f.key
285+
local allowed_vals = f.allowed_vals
286+
local val = metadata[key]
287+
local matched = false
288+
for _, allowed in ipairs(allowed_vals) do
289+
if val == allowed then
290+
matched = true
291+
break
292+
end
293+
end
294+
if not matched then
295+
return false
296+
end
297+
end
298+
return true
299+
end
300+
301+
local function match_nodes_by_metadata(nodes, filters)
302+
local result = {}
303+
for _, node in ipairs(nodes) do
304+
if match_metadata_filters(node, filters) then
305+
core.table.insert(result, node)
306+
end
307+
end
308+
return result
309+
end
281310

282311
function _M.set_by_route(route, api_ctx)
283312
if api_ctx.upstream_conf then
@@ -310,6 +339,14 @@ function _M.set_by_route(route, api_ctx)
310339
return HTTP_CODE_UPSTREAM_UNAVAILABLE, "no valid upstream node: " .. (err or "nil")
311340
end
312341

342+
if up_conf.metadata_match then
343+
new_nodes = match_nodes_by_metadata(new_nodes, up_conf.metadata_match)
344+
if #new_nodes == 0 then
345+
return HTTP_CODE_UPSTREAM_UNAVAILABLE, "no matched node filterd by metadata_match"
346+
end
347+
core.log.info("filterd by metadata_match: ", core.json.delay_encode(new_nodes, true))
348+
end
349+
313350
local same = upstream_util.compare_upstream_node(up_conf, new_nodes)
314351
if not same then
315352
if not up_conf._nodes_ver then

t/node/upstream-discovery.t

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,3 +508,64 @@ qr/compare upstream nodes by value|fill node info for upstream/
508508
fill node info for upstream
509509
compare upstream nodes by value
510510
fill node info for upstream
511+
512+
=== TEST 11: test metadata_match for upstream nodes selection
513+
--- log_level: debug
514+
--- apisix_yaml
515+
routes:
516+
-
517+
uri: /hello
518+
upstream:
519+
type: roundrobin
520+
nodes:
521+
"127.0.0.1:1980":
522+
weight: 1
523+
metadata:
524+
version: v1
525+
"127.0.0.2:1980":
526+
weight: 1
527+
metadata:
528+
version: v2
529+
metadata_match:
530+
version: v2
531+
--- config
532+
location /t {
533+
content_by_lua_block {
534+
local discovery = require("apisix.discovery.init").discovery
535+
-- mock nodes with metadata
536+
discovery.mock = {
537+
nodes = function()
538+
return {
539+
{host = "127.0.0.1", port = 1980, weight = 1, metadata = {version = "v1"}},
540+
{host = "127.0.0.2", port = 1980, weight = 1, metadata = {version = "v2"}},
541+
}
542+
end
543+
}
544+
545+
local http = require "resty.http"
546+
local uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello"
547+
local httpc = http.new()
548+
549+
-- do 5 requests and expect upstream node with metadata.version == v2 (127.0.0.2)
550+
for i = 1, 5 do
551+
local res = httpc:request_uri(uri, {method = "GET", keepalive = false})
552+
if res.status ~= 200 then
553+
ngx.say("request failed: ", res.status)
554+
return
555+
end
556+
if not string.find(res.body, "127.0.0.2") then
557+
ngx.say("unexpected upstream node: ", res.body)
558+
return
559+
end
560+
end
561+
ngx.say("pass")
562+
}
563+
}
564+
--- response_body
565+
pass
566+
--- grep_error_log eval
567+
qr/compare upstream nodes by value|fill node info for upstream|metadata_match/
568+
--- grep_error_log_out
569+
fill node info for upstream
570+
compare upstream nodes by value
571+
metadata_match found for upstream

0 commit comments

Comments
 (0)