Skip to content

Commit

Permalink
feat(healthcheck) set_all_target_statuses_for_hostname
Browse files Browse the repository at this point in the history
Co-Authored-By: Vinicius Mignot <vinicius.mignot@gmail.com>
  • Loading branch information
hishamhm and locao committed Feb 13, 2020
1 parent 028d2bf commit d775dd8
Show file tree
Hide file tree
Showing 2 changed files with 227 additions and 0 deletions.
26 changes: 26 additions & 0 deletions lib/resty/healthcheck.lua
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,32 @@ function checker:report_timeout(ip, port, hostname, check)
end


--- Sets the current status of all targets with the given hostname and port.
-- @param hostname hostname being checked.
-- @param port the port being checked against
-- @param is_healthy boolean: `true` for healthy, `false` for unhealthy
-- @return `true` on success, or `nil + error` on failure.
function checker:set_all_target_statuses_for_hostname(hostname, port, is_healthy)
assert(type(hostname) == "string", "no hostname provided")
port = assert(tonumber(port), "no port number provided")
assert(type(is_healthy) == "boolean")

local all_ok = true
local errs = {}
for _, target in ipairs(self.targets) do
if target.port == port and target.hostname == hostname then
local ok, err = self:set_target_status(target.ip, port, hostname, is_healthy)
if not ok then
all_ok = nil
table.insert(errs, err)
end
end
end

return all_ok, #errs > 0 and table.concat(errs, "; ") or nil
end


--- Sets the current status of the target.
-- This will immediately set the status and clear its counters.
-- @param ip IP address of the target being checked
Expand Down
201 changes: 201 additions & 0 deletions t/16-set_all_target_statuses_for_hostname.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
use Test::Nginx::Socket::Lua;
use Cwd qw(cwd);

workers(1);

plan tests => repeat_each() * blocks() * 2;

my $pwd = cwd();

our $HttpConfig = qq{
lua_package_path "$pwd/lib/?.lua;;";
lua_shared_dict test_shm 8m;
lua_shared_dict my_worker_events 8m;
};

run_tests();

__DATA__

=== TEST 1: set_all_target_statuses_for_hostname() updates statuses
--- http_config eval
qq{
$::HttpConfig
}
--- config
location = /t {
content_by_lua_block {
local we = require "resty.worker.events"
assert(we.configure{ shm = "my_worker_events", interval = 0.1 })
local healthcheck = require("resty.healthcheck")
local checker = healthcheck.new({
name = "testing",
shm_name = "test_shm",
})
ngx.sleep(0.1) -- wait for initial timers to run once
checker:add_target("127.0.0.1", 2112, "rush", true)
checker:add_target("127.0.0.2", 2112, "rush", true)
ngx.say(checker:get_target_status("127.0.0.1", 2112, "rush")) -- true
ngx.say(checker:get_target_status("127.0.0.2", 2112, "rush")) -- true
checker:set_all_target_statuses_for_hostname("rush", 2112, false)
ngx.say(checker:get_target_status("127.0.0.1", 2112, "rush")) -- false
ngx.say(checker:get_target_status("127.0.0.2", 2112, "rush")) -- false
checker:set_all_target_statuses_for_hostname("rush", 2112, true)
ngx.say(checker:get_target_status("127.0.0.1", 2112, "rush")) -- true
ngx.say(checker:get_target_status("127.0.0.2", 2112, "rush")) -- true
}
}
--- request
GET /t
--- response_body
true
true
false
false
true
true
=== TEST 2: set_all_target_statuses_for_hostname() restores node after passive check disables it
--- http_config eval
qq{
$::HttpConfig
}
--- config
location = /t {
content_by_lua_block {
local we = require "resty.worker.events"
assert(we.configure{ shm = "my_worker_events", interval = 0.1 })
local healthcheck = require("resty.healthcheck")
local checker = healthcheck.new({
name = "testing",
shm_name = "test_shm",
checks = {
passive = {
unhealthy = {
tcp_failures = 2,
http_failures = 2,
}
}
}
})
ngx.sleep(0.1) -- wait for initial timers to run once
checker:add_target("127.0.0.1", 2112, "rush", true)
checker:add_target("127.0.0.2", 2112, "rush", true)
ngx.say(checker:get_target_status("127.0.0.1", 2112, "rush")) -- true
ngx.say(checker:get_target_status("127.0.0.2", 2112, "rush")) -- true
checker:report_http_status("127.0.0.1", 2112, "rush", 500)
checker:report_http_status("127.0.0.1", 2112, "rush", 500)
ngx.say(checker:get_target_status("127.0.0.1", 2112, "rush")) -- false
checker:set_all_target_statuses_for_hostname("rush", 2112, true)
ngx.say(checker:get_target_status("127.0.0.1", 2112, "rush")) -- true
ngx.say(checker:get_target_status("127.0.0.2", 2112, "rush")) -- true
}
}
--- request
GET /t
--- response_body
true
true
false
true
true
=== TEST 3: set_all_target_statuses_for_hostname() resets failure counters
--- http_config eval
qq{
$::HttpConfig
}
--- config
location = /t {
content_by_lua_block {
local we = require "resty.worker.events"
assert(we.configure{ shm = "my_worker_events", interval = 0.1 })
local healthcheck = require("resty.healthcheck")
local checker = healthcheck.new({
name = "testing",
shm_name = "test_shm",
checks = {
passive = {
healthy = {
successes = 2,
},
unhealthy = {
tcp_failures = 2,
http_failures = 2,
}
}
}
})
ngx.sleep(0.1) -- wait for initial timers to run once
checker:add_target("127.0.0.1", 2112, "rush", true)
checker:add_target("127.0.0.2", 2112, "rush", true)
ngx.say(checker:get_target_status("127.0.0.1", 2112, "rush")) -- true
ngx.say(checker:get_target_status("127.0.0.2", 2112, "rush")) -- true
checker:report_http_status("127.0.0.1", 2112, "rush", 500)
checker:set_all_target_statuses_for_hostname("rush", 2112, true)
checker:report_http_status("127.0.0.1", 2112, "rush", 500)
ngx.say(checker:get_target_status("127.0.0.1", 2112, "rush")) -- true
ngx.say(checker:get_target_status("127.0.0.2", 2112, "rush")) -- true
checker:report_http_status("127.0.0.1", 2112, "rush", 500)
ngx.say(checker:get_target_status("127.0.0.1", 2112, "rush")) -- false
ngx.say(checker:get_target_status("127.0.0.2", 2112, "rush")) -- true
}
}
--- request
GET /t
--- response_body
true
true
true
true
false
true
=== TEST 4: set_target_status() resets the success counters
--- http_config eval
qq{
$::HttpConfig
}
--- config
location = /t {
content_by_lua_block {
local we = require "resty.worker.events"
assert(we.configure{ shm = "my_worker_events", interval = 0.1 })
local healthcheck = require("resty.healthcheck")
local checker = healthcheck.new({
name = "testing",
shm_name = "test_shm",
checks = {
passive = {
healthy = {
successes = 2,
},
unhealthy = {
tcp_failures = 2,
http_failures = 2,
}
}
}
})
ngx.sleep(0.1) -- wait for initial timers to run once
checker:add_target("127.0.0.1", 2112, "rush", true)
checker:add_target("127.0.0.2", 2112, "rush", true)
checker:set_all_target_statuses_for_hostname("rush", 2112, false)
ngx.say(checker:get_target_status("127.0.0.1", 2112, "rush")) -- false
ngx.say(checker:get_target_status("127.0.0.2", 2112, "rush")) -- false
checker:report_http_status("127.0.0.1", 2112, "rush", 200)
checker:set_all_target_statuses_for_hostname("rush", 2112, false)
checker:report_http_status("127.0.0.1", 2112, "rush", 200)
ngx.say(checker:get_target_status("127.0.0.1", 2112, "rush")) -- false
ngx.say(checker:get_target_status("127.0.0.2", 2112, "rush")) -- false
checker:report_http_status("127.0.0.1", 2112, "rush", 200)
ngx.say(checker:get_target_status("127.0.0.1", 2112, "rush")) -- true
ngx.say(checker:get_target_status("127.0.0.2", 2112, "rush")) -- false
}
}
--- request
GET /t
--- response_body
false
false
false
false
true
false

0 comments on commit d775dd8

Please sign in to comment.