-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore(tests): add a test case for /metrics
endpoint
#12695
Open
liverpool8056
wants to merge
5
commits into
master
Choose a base branch
from
database-outage-testcase
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+292
−0
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
c6f411b
chore(tests): add a test case for `/metrics` endpoint
liverpool8056 e94dc5c
remove license
liverpool8056 798a869
export db_proxy
liverpool8056 ff7c582
add usage and description for db_proxy
liverpool8056 ba343ed
update helpers
liverpool8056 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
-- This software is copyright Kong Inc. and its licensors. | ||
-- Use of the software is subject to the agreement between your organization | ||
-- and Kong Inc. If there is no such agreement, use is governed by and | ||
-- subject to the terms of the Kong Master Software License Agreement found | ||
-- at https://konghq.com/enterprisesoftwarelicense/. | ||
-- [ END OF LICENSE 0867164ffc95e54f04670b5169c09574bdbd9bba ] | ||
|
||
local helpers = require "spec.helpers" | ||
|
||
|
||
for _, strategy in helpers.all_strategies() do | ||
describe("Metrics API - with strategy #" .. strategy, function() | ||
describe("`/metrics` endpoint", function() | ||
local client | ||
local db_port = strategy == "postgres" and 5432 or 9042 | ||
local db_proxy = helpers.db_proxy.new({ db_port = db_port }) | ||
|
||
setup(function() | ||
assert(db_proxy:start()) | ||
|
||
assert(helpers.start_kong({ | ||
database = strategy, | ||
pg_port = db_proxy.db_proxy_port, | ||
status_listen = "127.0.0.1:9500", | ||
db_cache_warmup_entities = "workspaces", | ||
nginx_conf = "spec/fixtures/custom_nginx.template", | ||
})) | ||
|
||
client = helpers.http_client("127.0.0.1", 9500, 60000) | ||
end) | ||
|
||
lazy_teardown(function() | ||
if client then client:close() end | ||
assert(helpers.stop_kong()) | ||
assert(db_proxy:stop()) | ||
end) | ||
|
||
it(" can work even if database is down", function() | ||
local res = assert(client:send { | ||
method = "GET", | ||
path = "/metrics" | ||
}) | ||
assert.res_status(200, res) | ||
assert.res_status(200, db_proxy:status(false)) | ||
|
||
res = assert(client:send { | ||
method = "GET", | ||
path = "/metrics" | ||
}) | ||
assert.res_status(200, res) | ||
end) | ||
end) | ||
end) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4156,6 +4156,243 @@ do | |
end | ||
end | ||
|
||
-------------- | ||
-- A kong based database proxy class for the simulation of database abnormal behavior. | ||
-- @section db_proxy | ||
-- @usage | ||
-- local helpers = require "spec.helpers" | ||
-- local db_port = 5432 | ||
-- local db_proxy = helpers.db_proxy.new({ db_port = db_port }) | ||
-- assert(db_proxy:start()) | ||
-- db_proxy:status(false) | ||
-- db_proxy:delay(5) | ||
-- db_proxy:stop() | ||
local db_proxy = {} | ||
local db_proxy_mt = { | ||
__index = db_proxy, | ||
} | ||
|
||
--- Creates a db_proxy. | ||
-- @function db_proxy | ||
-- @field db_port The actual port of the database. | ||
-- @field db_proxy_port The proxy port of the database. | ||
-- @field api_port The port of the api server of the database | ||
-- proxy by which you can control the behavior of the db proxy | ||
-- to simulate abnormal cases. | ||
-- @field tcp_port The port of the tcp server of the database | ||
-- proxy. When invoking the api of the db proxy, it will transfer | ||
-- the config through this port, so that the config will take | ||
-- effects. Thus it is used internally. | ||
-- @param opts (table) Specifies the ports of the database proxy. | ||
-- The opts.db_port is the only one required, but all the others | ||
-- are optional. | ||
-- @return db proxy | ||
-- @see db_proxy:start | ||
-- @see db_proxy:stop | ||
-- @see db_proxy:get_fixtures | ||
-- @see db_proxy:delay | ||
-- @see db_proxy:status | ||
function db_proxy.new(opts) | ||
opts = opts or {} | ||
|
||
if type(opts.db_port) ~= "number" then | ||
error("db_port must be a number") | ||
end | ||
|
||
local self = { | ||
db_port = opts.db_port, | ||
db_proxy_port = get_available_port(), | ||
api_port = get_available_port(), | ||
tcp_port = get_available_port(), | ||
Comment on lines
+4203
to
+4206
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These ports should have documentation describing their purposes |
||
} | ||
|
||
return setmetatable(self, db_proxy_mt) | ||
end | ||
|
||
-- Start the db proxy. | ||
-- @function db_proxy:start | ||
-- @param opts(optional) Same as the opts used in `start_kong`. | ||
-- Strongly recommend not feed this parameter. | ||
function db_proxy:start(opts) | ||
local kong_conf = type(opts) == "table" and opts or { | ||
prefix = "servroot_db_proxy", | ||
database = "off", | ||
-- the proxy should be in the data plane as this can avoid port conflict with the other kong instances. | ||
role = "data_plane", | ||
nginx_conf = "spec/fixtures/custom_nginx.template", | ||
-- this is unused, but required for the template to include a http {} block | ||
proxy_listen = "0.0.0.0:" .. get_available_port(), | ||
-- this is unused, but required for the template to include a stream {} block | ||
-- and this won't occupy 5555 port actually. | ||
stream_listen = "0.0.0.0:5555", | ||
-- As we specify the proxy working as a data plane, we need to specify the following certs | ||
cluster_cert = "spec/fixtures/kong_clustering.crt", | ||
cluster_cert_key = "spec/fixtures/kong_clustering.key", | ||
} | ||
|
||
self.prefix = kong_conf.prefix | ||
|
||
return start_kong(kong_conf, nil, nil, self:get_fixtures()) | ||
end | ||
|
||
-- Stop the db proxy. | ||
-- @function db_proxy:stop | ||
function db_proxy:stop() | ||
if self.client then | ||
self.client:close() | ||
end | ||
|
||
return stop_kong(self.prefix, true) | ||
end | ||
|
||
-- Get the fixtures of the db proxy. | ||
-- @function db_proxy:get_fixtures | ||
function db_proxy:get_fixtures() | ||
return { | ||
http_mock = { | ||
db_proxy_api_server = [[ | ||
server { | ||
error_log logs/db_proxy_http_error.log; | ||
listen 127.0.0.1:]] .. self.api_port .. [[; | ||
location /db_proxy_conf { | ||
content_by_lua_block { | ||
local cjson = require "cjson.safe" | ||
|
||
local function toboolean(value) | ||
if value == "true" then | ||
return true | ||
else | ||
return false | ||
end | ||
end | ||
|
||
ngx.req.read_body() | ||
local args, err = ngx.req.get_post_args() | ||
if not args then | ||
ngx.say("cannot get args in req: " .. err) | ||
ngx.exit(ngx.ERROR) | ||
end | ||
|
||
args.delay = args.delay and tonumber(args.delay) or 0 | ||
if args.status then | ||
args.status = toboolean(args.status) | ||
|
||
else | ||
args.status = true | ||
end | ||
|
||
local sock = assert(ngx.socket.tcp()) | ||
sock:settimeout(3000) | ||
local ok, err = sock:connect('127.0.0.1', ']] .. self.tcp_port .. [[') | ||
if not ok then | ||
ngx.say("failed to connect to db_proxy_server: " .. err) | ||
ngx.exit(ngx.ERROR) | ||
end | ||
|
||
local bytes, err = sock:send(cjson.encode(args)) | ||
if err then | ||
ngx.say("failed to send data to db_proxy: " .. err) | ||
ngx.exit(ngx.ERROR) | ||
end | ||
|
||
sock:close() | ||
} | ||
} | ||
} | ||
]], | ||
}, | ||
|
||
stream_mock = { | ||
db_proxy_server = [[ | ||
upstream backend { | ||
server 0.0.0.1:1234; | ||
balancer_by_lua_block { | ||
local balancer = require "ngx.balancer" | ||
|
||
local function sleep(n) | ||
local t = os.clock() | ||
while os.clock() - t <= n do end | ||
end | ||
|
||
if status == false then | ||
ngx.exit(ngx.ERROR) | ||
end | ||
|
||
if delay and delay > 0 then | ||
sleep(delay) | ||
end | ||
|
||
local ok, err = balancer.set_current_peer("127.0.0.1", ]] .. self.db_port .. [[) | ||
if not ok then | ||
ngx.log(ngx.ERR, "failed to set the current peer: ", err) | ||
ngx.exit(ngx.ERROR) | ||
end | ||
} | ||
} | ||
|
||
server { | ||
listen ]] .. self.db_proxy_port .. [[; | ||
error_log logs/db_proxy_error.log; | ||
proxy_pass backend; | ||
} | ||
|
||
server { | ||
listen ]] .. self.tcp_port .. [[; | ||
error_log logs/db_proxy_error.log; | ||
content_by_lua_block { | ||
local cjson = require "cjson.safe" | ||
local sock = assert(ngx.req.socket()) | ||
local data, err = sock:receive("*a") | ||
if data then | ||
local opts = cjson.decode(data) | ||
if opts then | ||
_G.delay = opts.delay | ||
_G.status = opts.status | ||
end | ||
end | ||
} | ||
} | ||
]], | ||
}, | ||
} | ||
end | ||
|
||
-- Set the delay for the db proxy to simulate a slow network. | ||
-- Notice: you have to assert the success of execution of | ||
-- this function by yourself like: | ||
-- `assert.res_status(200, db_proxy:delay(10))`. | ||
-- @function db_proxy:delay | ||
-- @param delay (number) The delay in seconds. | ||
function db_proxy:delay(delay) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A documentation describing how to use these functions would also be better |
||
if type(delay) ~= "number" then | ||
error("delay must be a number and greater than 0") | ||
end | ||
|
||
if not self.client then | ||
self.client = proxy_client(3000, self.api_port) | ||
end | ||
|
||
return self.client:post("/db_proxy_conf", { delay = delay }) | ||
end | ||
|
||
-- Set the status for the db proxy to simulate an outage. | ||
-- Notice: you have to assert the success of execution of | ||
-- this function by yourself like: | ||
-- `assert.res_status(200, db_proxy:status(false))`. | ||
-- @function db_proxy:status | ||
-- @param status (boolean) The status of the database, | ||
-- false means an outage. | ||
function db_proxy:status(on_off) | ||
if type(on_off) ~= 'boolean' then | ||
error("on_off must be a boolean") | ||
end | ||
|
||
if not self.client then | ||
self.client = proxy_client(3000, self.api_port) | ||
end | ||
|
||
return self.client:post("/db_proxy_conf", { status = on_off }) | ||
end | ||
|
||
---------------- | ||
-- Variables/constants | ||
|
@@ -4211,6 +4448,7 @@ end | |
|
||
-- Kong testing properties | ||
db = db, | ||
db_proxy = db_proxy, | ||
blueprints = blueprints, | ||
get_db_utils = get_db_utils, | ||
get_cache = get_cache, | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it make sense to move this to a separate file?