Files
2026-07-13 12:32:21 +08:00

251 lines
8.3 KiB
Lua

local helpers = require "spec.helpers"
local declarative = require "kong.db.declarative"
local cycle_aware_deep_copy = require("kong.tools.table").cycle_aware_deep_copy
local uuid = require("kong.tools.uuid").uuid
-- Note: include "off" strategy here as well
for _, strategy in helpers.all_strategies() do
describe("db.dao #" .. strategy, function()
local bp, db
local consumer, service, service2, plugin, plugin2, acl
local group = "The A Team"
lazy_setup(function()
bp, db = helpers.get_db_utils(strategy, {
"plugins",
"services",
"consumers",
"acls",
"keyauth_credentials",
})
_G.kong.db = db
consumer = bp.consumers:insert {
username = "andru",
custom_id = "donalds",
}
service = bp.services:insert {
name = "abc",
url = "http://localhost",
}
service2 = bp.services:insert {
name = "def",
url = "http://2-localhost",
}
plugin = bp.plugins:insert {
enabled = true,
name = "acl",
service = service,
config = {
allow = { "*" },
},
}
plugin2 = bp.plugins:insert {
enabled = true,
name = "rate-limiting",
instance_name = 'rate-limiting-instance-1',
service = service,
config = {
minute = 100,
policy = "redis",
redis = {
host = "localhost"
}
},
}
-- Note: bp in off strategy returns service=id instead of a table
plugin.service = {
id = service.id
}
acl = bp.acls:insert {
consumer = consumer,
group = group,
}
-- Note: bp in off strategy returns consumer=id instead of a table
acl.consumer = {
id = consumer.id
}
if strategy == "off" then
-- dc_blueprint stores entities in memory
-- and helpers export it to file in start_kong
-- since this test requires entities to load
-- into current nginx's shdict instead of the
-- Kong nginx started by start_kong, we need
-- to manually load the config
local cfg = bp.done()
local dc = declarative.new_config(kong.configuration)
local entities = assert(dc:parse_table(cfg))
local kong_global = require("kong.global")
local kong = _G.kong
kong.worker_events = assert(kong_global.init_worker_events(kong.configuration))
kong.cluster_events = assert(kong_global.init_cluster_events(kong.configuration, kong.db))
kong.cache = assert(kong_global.init_cache(kong.configuration, kong.cluster_events, kong.worker_events))
kong.core_cache = assert(kong_global.init_core_cache(kong.configuration, kong.cluster_events, kong.worker_events))
assert(declarative.load_into_cache(entities))
end
end)
lazy_teardown(function()
db.acls:truncate()
db.consumers:truncate()
db.plugins:truncate()
db.services:truncate()
db.keyauth_credentials:truncate()
end)
it("select_by_cache_key()", function()
local cache_key = kong.db.acls:cache_key(consumer.id, group)
local read_acl, err = kong.db.acls:select_by_cache_key(cache_key)
assert.is_nil(err)
assert.same(acl, read_acl)
-- cache_key = { "name", "route", "service", "consumer" },
cache_key = kong.db.plugins:cache_key("acl", nil, service.id, nil)
local read_plugin, err = kong.db.plugins:select_by_cache_key(cache_key)
assert.is_nil(err)
assert.same(plugin, read_plugin)
cache_key = kong.db.plugins:cache_key("rate-limiting", nil, service.id, nil)
read_plugin, err = kong.db.plugins:select_by_cache_key(cache_key)
assert.is_nil(err)
assert.same(plugin2, read_plugin)
end)
it("page_for_route", function()
local plugins_for_service, err = kong.db.plugins:page_for_service(service)
assert.is_nil(err)
assert.equal(2, #plugins_for_service)
for _, read_plugin in ipairs(plugins_for_service) do
if read_plugin.name == 'acl' then
assert.same(plugin, read_plugin)
elseif read_plugin.name == 'rate-limiting' then
assert.same(plugin2, read_plugin)
end
end
end)
it("select_by_instance_name", function()
local read_plugin, err = kong.db.plugins:select_by_instance_name(plugin2.instance_name)
assert.is_nil(err)
assert.same(plugin2, read_plugin)
end)
it("update_by_instance_name", function()
local newhost = "newhost"
local updated_plugin = cycle_aware_deep_copy(plugin2)
updated_plugin.config.redis.host = newhost
updated_plugin.config.redis_host = newhost
local read_plugin, err = kong.db.plugins:update_by_instance_name(plugin2.instance_name, updated_plugin)
assert.is_nil(err)
assert.same(updated_plugin, read_plugin)
end)
it("upsert_by_instance_name", function()
-- existing plugin upsert (update part of upsert)
local newhost = "newhost"
local updated_plugin = cycle_aware_deep_copy(plugin2)
updated_plugin.config.redis.host = newhost
updated_plugin.config.redis_host = newhost
local read_plugin, err = kong.db.plugins:upsert_by_instance_name(plugin2.instance_name, updated_plugin)
assert.is_nil(err)
assert.same(updated_plugin, read_plugin)
-- new plugin upsert (insert part of upsert)
local new_plugin_config = {
id = uuid(),
enabled = true,
name = "rate-limiting",
instance_name = 'rate-limiting-instance-2',
service = service2,
config = {
minute = 200,
policy = "redis",
redis = {
host = "new-host-2"
}
},
}
local read_plugin, err = kong.db.plugins:upsert_by_instance_name(new_plugin_config.instance_name, new_plugin_config)
assert.is_nil(err)
assert.same(new_plugin_config.id, read_plugin.id)
assert.same(new_plugin_config.instance_name, read_plugin.instance_name)
assert.same(new_plugin_config.service.id, read_plugin.service.id)
assert.same(new_plugin_config.config.minute, read_plugin.config.minute)
assert.same(new_plugin_config.config.redis.host, read_plugin.config.redis.host)
assert.same(new_plugin_config.config.redis.host, read_plugin.config.redis_host) -- legacy field is included
end)
it("keyauth_credentials can be deleted or selected before run ttl cleanup in background timer", function()
local key = uuid()
local original_keyauth_credentials = bp.keyauth_credentials:insert({
consumer = { id = consumer.id },
key = key,
}, { ttl = 5 })
-- wait for 5 seconds.
ngx.sleep(5)
-- select or delete keyauth_credentials after ttl expired.
local expired_keyauth_credentials
helpers.wait_until(function()
expired_keyauth_credentials = kong.db.keyauth_credentials:select_by_key(key)
return not expired_keyauth_credentials
end, 1)
assert.is_nil(expired_keyauth_credentials)
kong.db.keyauth_credentials:delete_by_key(key)
-- select or delete keyauth_credentials with skip_ttl=true after ttl expired.
expired_keyauth_credentials = kong.db.keyauth_credentials:select_by_key(key, { skip_ttl = true })
assert.not_nil(expired_keyauth_credentials)
assert.same(expired_keyauth_credentials.id, original_keyauth_credentials.id)
kong.db.keyauth_credentials:delete_by_key(key, { skip_ttl = true })
-- check again
expired_keyauth_credentials = kong.db.keyauth_credentials:select_by_key(key, { skip_ttl = true })
assert.is_nil(expired_keyauth_credentials)
end)
it("should not preserve expired entities as nil in the result of page method", function()
bp.keyauth_credentials:insert({
consumer = { id = consumer.id },
key = uuid(),
}, { })
bp.keyauth_credentials:insert({
consumer = { id = consumer.id },
key = uuid(),
}, { ttl = 2 })
bp.keyauth_credentials:insert({
consumer = { id = consumer.id },
key = uuid(),
}, { })
local res = kong.db.keyauth_credentials:page()
assert.equal(3, #res)
-- wait for 2+1 seconds.
ngx.sleep(3)
res = kong.db.keyauth_credentials:page()
assert.equal(2, #res)
for _, entity in ipairs(res) do
assert.is_table(entity)
end
end)
end)
end