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

471 lines
12 KiB
Lua

local meta = require "kong.meta"
local helpers = require "spec.helpers"
local cjson = require "cjson"
describe("reports", function()
local reports, bytes, err
local expected_data = "version"
local port = 8189
lazy_setup(function()
-- start the echo server
assert(helpers.start_kong({
nginx_conf = "spec/fixtures/custom_nginx.template",
-- we don't actually use any stream proxy features in tcp_server,
-- but this is needed in order to load the echo server defined at
-- nginx_kong_test_tcp_echo_server_custom_inject_stream.lua
stream_listen = helpers.get_proxy_ip(false) .. ":19000",
-- to fix "Database needs bootstrapping or is older than Kong 1.0" in CI.
database = "off",
log_level = "info",
}))
assert(helpers.is_echo_server_ready())
end)
lazy_teardown(function()
helpers.stop_kong()
helpers.echo_server_reset()
end)
before_each(function()
package.loaded["kong.reports"] = nil
reports = require "kong.reports"
end)
it("don't send report when anonymous_reports = false", function ()
bytes, err = reports.send()
assert.is_nil(bytes)
assert.equal(err, "disabled")
end)
describe("when anonymous_reports = true, ", function ()
lazy_setup(function()
_G.kong = _G.kong or {}
_G.kong.configuration = _G.kong.configuration or {}
if not _G.kong.configuration.anonymous_reports then
_G.kong.configuration = { anonymous_reports = true }
end
end)
lazy_teardown(function()
_G.kong.configuration.anonymous_reports = nil
end)
it("send reports", function()
bytes, err = reports.send()
assert.is_nil(bytes)
assert.equal(err, "disabled")
end)
end)
describe("toggle", function()
before_each(function()
reports.toggle(true)
end)
it("sends report over TCP[TLS]", function()
bytes, err = reports.send("stub", {
hello = "world",
foo = "bar",
baz = function() return "bat" end,
foobar = function() return { foo = "bar" } end,
bazbat = { baz = "bat" },
nilval = function() return nil end,
}, "127.0.0.1", port)
assert.truthy(bytes>0)
assert.is_nil(err)
local res = helpers.get_echo_server_received_data(expected_data)
assert.matches("^<14>", res)
res = res:sub(5)
assert.matches("cores=%d+", res)
assert.matches("uname=[%w]+", res)
assert.matches("version=" .. meta._VERSION, res, nil, true)
assert.matches("hostname=[%w]+", res)
assert.matches("foo=bar", res, nil, true)
assert.matches("hello=world", res, nil, true)
assert.matches("signal=stub", res, nil, true)
assert.matches("baz=bat", res, nil, true)
assert.not_matches("nilval", res, nil, true)
assert.matches("foobar=" .. cjson.encode({ foo = "bar" }), res, nil, true)
assert.matches("bazbat=" .. cjson.encode({ baz = "bat" }), res, nil, true)
end)
it("doesn't send if not enabled", function()
reports.toggle(false)
bytes, err = reports.send({
foo = "bar"
}, "127.0.0.1", port)
assert.is_nil(bytes)
assert.equal(err, "disabled")
local res = helpers.get_echo_server_received_data(expected_data, 0.1)
assert.equal("timeout", res)
end)
it("accepts custom immutable items", function()
reports.toggle(true)
reports.add_immutable_value("imm1", "fooval")
reports.add_immutable_value("imm2", "barval")
bytes, err = reports.send("stub", {k1 = "bazval"}, "127.0.0.1", port)
assert.truthy(bytes > 0)
assert.is_nil(err)
local res = helpers.get_echo_server_received_data(expected_data)
assert.matches("imm1=fooval", res)
assert.matches("imm2=barval", res)
assert.matches("k1=bazval", res)
end)
end)
describe("configure_ping()", function()
local conf_loader = require "kong.conf_loader"
local function send_reports_and_check_result(reports, conf, port, matches)
reports.configure_ping(conf)
reports.send_ping("127.0.0.1", port)
local res = helpers.get_echo_server_received_data(expected_data)
for _,m in ipairs(matches) do
assert.matches(m, res, nil, true)
end
end
before_each(function()
reports.toggle(true)
reports._create_counter()
end)
describe("sends 'cluster_id'", function()
it("uses mock value 123e4567-e89b-12d3-a456-426655440000", function()
local conf = assert(conf_loader(nil, {
database = "postgres",
}))
send_reports_and_check_result(
reports,
conf,
port,
{"cluster_id=123e4567-e89b-12d3-a456-426655440000"})
end)
end)
describe("sends 'database'", function()
it("postgres", function()
local conf = assert(conf_loader(nil, {
database = "postgres",
}))
send_reports_and_check_result(
reports,
conf,
port,
{"database=postgres"})
end)
it("off", function()
local conf = assert(conf_loader(nil, {
database = "off",
}))
send_reports_and_check_result(
reports,
conf,
port,
{"database=off"})
end)
end)
describe("sends 'role'", function()
it("traditional", function()
local conf = assert(conf_loader(nil))
send_reports_and_check_result(
reports,
conf,
port,
{"cluster_id=123e4567-e89b-12d3-a456-426655440000"})
end)
it("control_plane", function()
local conf = assert(conf_loader(nil, {
role = "control_plane",
cluster_cert = "spec/fixtures/kong_spec.crt",
cluster_cert_key = "spec/fixtures/kong_spec.key",
}))
send_reports_and_check_result(
reports,
conf,
port,
{"role=control_plane"})
end)
it("data_plane", function()
local conf = assert(conf_loader(nil, {
role = "data_plane",
database = "off",
cluster_cert = "spec/fixtures/kong_spec.crt",
cluster_cert_key = "spec/fixtures/kong_spec.key",
}))
send_reports_and_check_result(
reports,
conf,
port,
{"role=data_plane"})
end)
end)
describe("sends 'kic'", function()
it("default (off)", function()
local conf = assert(conf_loader(nil))
send_reports_and_check_result(
reports,
conf,
port,
{"kic=false"})
end)
it("enabled", function()
local conf = assert(conf_loader(nil, {
kic = "on",
}))
send_reports_and_check_result(
reports,
conf,
port,
{"kic=true"})
end)
end)
describe("sends '_admin' for 'admin_listen'", function()
it("off", function()
local conf = assert(conf_loader(nil, {
admin_listen = "off",
}))
send_reports_and_check_result(
reports,
conf,
port,
{"_admin=0"})
end)
it("on", function()
local conf = assert(conf_loader(nil, {
admin_listen = "127.0.0.1:8001",
}))
send_reports_and_check_result(
reports,
conf,
port,
{"_admin=1"})
end)
end)
describe("sends '_admin_gui' for 'admin_gui_listen'", function()
it("off", function()
local conf = assert(conf_loader(nil, {
admin_gui_listen = "off",
}))
send_reports_and_check_result(
reports,
conf,
port,
{"_admin_gui=0"})
end)
it("on", function()
local conf = assert(conf_loader(nil, {
admin_gui_listen = "127.0.0.1:8001",
}))
send_reports_and_check_result(
reports,
conf,
port,
{"_admin_gui=1"})
end)
end)
describe("sends '_proxy' for 'proxy_listen'", function()
it("off", function()
local conf = assert(conf_loader(nil, {
proxy_listen = "off",
}))
send_reports_and_check_result(
reports,
conf,
port,
{"_proxy=0"})
end)
it("on", function()
local conf = assert(conf_loader(nil, {
proxy_listen = "127.0.0.1:8000",
}))
send_reports_and_check_result(
reports,
conf,
port,
{"_proxy=1"})
end)
end)
describe("sends '_stream' for 'stream_listen'", function()
it("off", function()
local conf = assert(conf_loader(nil, {
stream_listen = "off",
}))
send_reports_and_check_result(
reports,
conf,
port,
{"_stream=0"})
end)
it("on", function()
local conf = assert(conf_loader(nil, {
stream_listen = "127.0.0.1:8000",
}))
send_reports_and_check_result(
reports,
conf,
port,
{"_stream=1"})
end)
end)
it("default configuration ping contents", function()
local conf = assert(conf_loader())
send_reports_and_check_result(
reports,
conf,
port,
{"database=" .. helpers.test_conf.database,
"_admin=1",
"_proxy=1",
"_stream=0"
})
end)
it("sends 'new_dns_client'", function()
local conf = assert(conf_loader())
conf.new_dns_client = true
send_reports_and_check_result(
reports,
conf,
port,
{"new_dns_client=true"}
)
conf.new_dns_client = false
send_reports_and_check_result(
reports,
conf,
port,
{"new_dns_client=false"}
)
end)
end)
describe("retrieve_redis_version()", function()
lazy_setup(function()
stub(ngx, "log")
end)
lazy_teardown(function()
ngx.log:revert() -- luacheck: ignore
end)
before_each(function()
reports.toggle(true)
reports._create_counter()
end)
it("does not query Redis if not enabled", function()
reports.toggle(false)
local red_mock = {
info = function() end,
}
local s = spy.on(red_mock, "info")
reports.retrieve_redis_version(red_mock)
assert.spy(s).was_not_called()
end)
it("queries Redis if enabled", function()
local red_mock = {
info = function()
return "redis_version:2.4.5\r\nredis_git_sha1:e09e31b1"
end,
}
local s = spy.on(red_mock, "info")
reports.retrieve_redis_version(red_mock)
assert.spy(s).was_called_with(red_mock, "server")
end)
it("queries Redis only once", function()
local red_mock = {
info = function()
return "redis_version:2.4.5\r\nredis_git_sha1:e09e31b1"
end,
}
local s = spy.on(red_mock, "info")
reports.retrieve_redis_version(red_mock)
reports.retrieve_redis_version(red_mock)
reports.retrieve_redis_version(red_mock)
assert.spy(s).was_called(1)
end)
it("retrieves major.minor version", function()
local red_mock = {
info = function()
return "redis_version:2.4.5\r\nredis_git_sha1:e09e31b1"
end,
}
reports.retrieve_redis_version(red_mock)
assert.equal("2.4", reports.get_ping_value("redis_version"))
end)
it("retrieves 'unknown' when the version could not be retrieved (1/3)", function()
local red_mock = {
info = function()
return nil
end,
}
reports.retrieve_redis_version(red_mock)
assert.equal("unknown", reports.get_ping_value("redis_version"))
end)
it("retrieves 'unknown' when the version could not be retrieved (2/3)", function()
local red_mock = {
info = function()
return ngx.null
end,
}
reports.retrieve_redis_version(red_mock)
assert.equal("unknown", reports.get_ping_value("redis_version"))
end)
it("retrieves 'unknown' when the version could not be retrieved (3/3)", function()
local red_mock = {
info = function()
return "hello world"
end,
}
reports.retrieve_redis_version(red_mock)
assert.equal("unknown", reports.get_ping_value("redis_version"))
end)
end)
end)