kong/spec/02-integration/03-db/03-plugins_spec.lua (256 lines of code) (raw):
local helpers = require "spec.helpers"
assert:set_parameter("TableFormatLevel", 10)
local UUID_PATTERN = "%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x"
for _, strategy in helpers.each_strategy() do
describe("kong.db [#" .. strategy .. "]", function()
local db, bp, service, route
local global_plugin
lazy_setup(function()
bp, db = helpers.get_db_utils(strategy, {
"routes",
"services",
"plugins",
})
global_plugin = db.plugins:insert({ name = "key-auth",
protocols = { "http" },
})
assert.truthy(global_plugin)
end)
describe("Plugins #plugins", function()
before_each(function()
service = bp.services:insert()
route = bp.routes:insert({ service = { id = service.id },
protocols = { "tcp" },
sources = { { ip = "127.0.0.1" } },
})
end)
describe(":insert()", function()
it("checks composite uniqueness", function()
local route = bp.routes:insert({ methods = {"GET"} })
local plugin, err, err_t = db.plugins:insert({
name = "key-auth",
route = { id = route.id },
})
assert.is_nil(err_t)
assert.is_nil(err)
assert.matches(UUID_PATTERN, plugin.id)
assert.is_number(plugin.created_at)
plugin.id = nil
plugin.created_at = nil
assert.same({
config = {
hide_credentials = false,
run_on_preflight = true,
key_in_header = true,
key_in_query = true,
key_in_body = false,
key_names = { "apikey" },
},
protocols = { "grpc", "grpcs", "http", "https" },
enabled = true,
name = "key-auth",
route = {
id = route.id,
},
}, plugin)
plugin, err, err_t = db.plugins:insert({
name = "key-auth",
route = route,
})
assert.falsy(plugin)
assert.match("UNIQUE violation", err)
assert.same("unique constraint violation", err_t.name)
assert.same([[UNIQUE violation detected on '{consumer=null,name="key-auth",]] ..
[[route={id="]] .. route.id ..
[["},service=null}']], err_t.message)
end)
it("does not validate when associated to an incompatible route, or a service with only incompatible routes", function()
local plugin, _, err_t = db.plugins:insert({ name = "key-auth",
protocols = { "http" },
route = { id = route.id },
})
assert.is_nil(plugin)
assert.equals(err_t.fields.protocols, "must match the associated route's protocols")
local plugin, _, err_t = db.plugins:insert({ name = "key-auth",
protocols = { "http" },
service = { id = service.id },
})
assert.is_nil(plugin)
assert.equals(err_t.fields.protocols,
"must match the protocols of at least one route pointing to this Plugin's service")
end)
it("validates when associated to a service with no routes", function()
local service_with_no_routes = bp.services:insert()
local plugin, _, err_t = db.plugins:insert({ name = "key-auth",
protocols = { "http" },
service = { id = service_with_no_routes.id },
})
assert.truthy(plugin)
assert.is_nil(err_t)
end)
end)
describe(":update()", function()
it("checks composite uniqueness", function()
local route = bp.routes:insert({ methods = {"GET"} })
local plugin, err, err_t = db.plugins:insert({
name = "key-auth",
route = { id = route.id },
})
assert.is_nil(err_t)
assert.is_nil(err)
assert.matches(UUID_PATTERN, plugin.id)
assert.is_number(plugin.created_at)
plugin.id = nil
plugin.created_at = nil
assert.same({
config = {
hide_credentials = false,
run_on_preflight = true,
key_in_header = true,
key_in_query = true,
key_in_body = false,
key_names = { "apikey" },
},
protocols = { "grpc", "grpcs", "http", "https" },
enabled = true,
name = "key-auth",
route = {
id = route.id,
},
}, plugin)
plugin, err, err_t = db.plugins:insert({
name = "key-auth",
route = route,
})
assert.falsy(plugin)
assert.match("UNIQUE violation", err)
assert.same("unique constraint violation", err_t.name)
assert.same([[UNIQUE violation detected on '{consumer=null,name="key-auth",]] ..
[[route={id="]] .. route.id ..
[["},service=null}']], err_t.message)
end)
end)
it("returns an error when updating mismatched plugins", function()
local p, _, err_t = db.plugins:update({ id = global_plugin.id },
{ route = { id = route.id } })
assert.is_nil(p)
assert.equals(err_t.fields.protocols, "must match the associated route's protocols")
local p, _, err_t = db.plugins:update({ id = global_plugin.id },
{ service = { id = service.id } })
assert.is_nil(p)
assert.equals(err_t.fields.protocols,
"must match the protocols of at least one route pointing to this Plugin's service")
end)
end)
describe(":upsert()", function()
it("returns an error when upserting mismatched plugins", function()
local p, _, err_t = db.plugins:upsert({ id = global_plugin.id },
{ route = { id = route.id }, protocols = { "http" } })
assert.is_nil(p)
assert.equals(err_t.fields.protocols, "must match the associated route's protocols")
local p, _, err_t = db.plugins:upsert({ id = global_plugin.id },
{ service = { id = service.id }, protocols = { "http" } })
assert.is_nil(p)
assert.equals(err_t.fields.protocols,
"must match the protocols of at least one route pointing to this Plugin's service")
end)
end)
describe(":load_plugin_schemas()", function()
it("loads custom entities with specialized methods", function()
local ok, err = db.plugins:load_plugin_schemas({
["plugin-with-custom-dao"] = true,
})
assert.is_nil(err)
assert.truthy(ok)
assert.same("I was implemented for " .. strategy, db.custom_dao:custom_method())
end)
it("reports failure with missing plugins", function()
local ok, err = db.plugins:load_plugin_schemas({
["missing"] = true,
})
assert.falsy(ok)
assert.match("missing plugin is enabled but not installed", err, 1, true)
end)
describe("with bad PRIORITY fails; ", function()
setup(function()
local schema = {}
package.loaded["kong.plugins.NaN_priority.schema"] = schema
package.loaded["kong.plugins.NaN_priority.handler"] = { PRIORITY = 0/0, VERSION = "1.0" }
package.loaded["kong.plugins.huge_negative.schema"] = schema
package.loaded["kong.plugins.huge_negative.handler"] = { PRIORITY = -math.huge, VERSION = "1.0" }
package.loaded["kong.plugins.string_priority.schema"] = schema
package.loaded["kong.plugins.string_priority.handler"] = { PRIORITY = "abc", VERSION = "1.0" }
end)
teardown(function()
package.loaded["kong.plugins.NaN_priority.schema"] = nil
package.loaded["kong.plugins.NaN_priority.handler"] = nil
package.loaded["kong.plugins.huge_negative.schema"] = nil
package.loaded["kong.plugins.huge_negative.handler"] = nil
package.loaded["kong.plugins.string_priority.schema"] = nil
package.loaded["kong.plugins.string_priority.handler"] = nil
end)
it("NaN", function()
local ok, err = db.plugins:load_plugin_schemas({
["NaN_priority"] = true,
})
assert.falsy(ok)
assert.match('Plugin "NaN_priority" cannot be loaded because its PRIORITY field is not a valid integer number, got: "nan"', err, 1, true)
end)
it("-math.huge", function()
local ok, err = db.plugins:load_plugin_schemas({
["huge_negative"] = true,
})
assert.falsy(ok)
assert.match('Plugin "huge_negative" cannot be loaded because its PRIORITY field is not a valid integer number, got: "-inf"', err, 1, true)
end)
it("string", function()
local ok, err = db.plugins:load_plugin_schemas({
["string_priority"] = true,
})
assert.falsy(ok)
assert.match('Plugin "string_priority" cannot be loaded because its PRIORITY field is not a valid integer number, got: "abc"', err, 1, true)
end)
end)
describe("with bad VERSION fails; ", function()
setup(function()
local schema = {}
package.loaded["kong.plugins.no_version.schema"] = schema
package.loaded["kong.plugins.no_version.handler"] = { PRIORITY = 1000, VERSION = nil }
package.loaded["kong.plugins.too_many.schema"] = schema
package.loaded["kong.plugins.too_many.handler"] = { PRIORITY = 1000, VERSION = "1.0.0.0" }
package.loaded["kong.plugins.number.schema"] = schema
package.loaded["kong.plugins.number.handler"] = { PRIORITY = 1000, VERSION = 123 }
end)
teardown(function()
package.loaded["kong.plugins.no_version.schema"] = nil
package.loaded["kong.plugins.no_version.handler"] = nil
package.loaded["kong.plugins.too_many.schema"] = nil
package.loaded["kong.plugins.too_many.handler"] = nil
package.loaded["kong.plugins.number.schema"] = nil
package.loaded["kong.plugins.number.handler"] = nil
end)
it("without version", function()
local ok, err = db.plugins:load_plugin_schemas({
["no_version"] = true,
})
assert.falsy(ok)
assert.match('Plugin "no_version" cannot be loaded because its VERSION field does not follow the "x.y.z" format, got: "nil"', err, 1, true)
end)
it("too many components", function()
local ok, err = db.plugins:load_plugin_schemas({
["too_many"] = true,
})
assert.falsy(ok)
assert.match('Plugin "too_many" cannot be loaded because its VERSION field does not follow the "x.y.z" format, got: "1.0.0.0"', err, 1, true)
end)
it("number", function()
local ok, err = db.plugins:load_plugin_schemas({
["number"] = true,
})
assert.falsy(ok)
assert.match('Plugin "number" cannot be loaded because its VERSION field does not follow the "x.y.z" format, got: "123"', err, 1, true)
end)
end)
end)
end) -- kong.db [strategy]
end