377 lines
10 KiB
Lua
377 lines
10 KiB
Lua
local helpers = require "spec.helpers"
|
|
local cjson = require "cjson"
|
|
|
|
local function client_send(req)
|
|
local client = helpers.http_client("127.0.0.1", 9500, 20000)
|
|
local res = assert(client:send(req))
|
|
local status, body = res.status, res:read_body()
|
|
client:close()
|
|
return status, body
|
|
end
|
|
|
|
local strategy = "off"
|
|
|
|
describe("Status API #" .. strategy, function()
|
|
local bp
|
|
local client
|
|
|
|
local apis, healthcheck_apis = {}, {}
|
|
|
|
local upstream, empty_upstream, healthcheck_upstream
|
|
|
|
lazy_setup(function()
|
|
local fixtures = {
|
|
dns_mock = helpers.dns_mock.new()
|
|
}
|
|
fixtures.dns_mock:A {
|
|
name = "custom_localhost",
|
|
address = "127.0.0.1",
|
|
}
|
|
|
|
bp = helpers.get_db_utils(strategy, {
|
|
"upstreams",
|
|
"targets",
|
|
})
|
|
|
|
upstream = bp.upstreams:insert {}
|
|
|
|
for i=1, 4 do
|
|
apis[i] = bp.targets:insert {
|
|
target = string.format("api-%d:80", i),
|
|
weight = 10 * i,
|
|
upstream = { id = upstream.id },
|
|
}
|
|
end
|
|
|
|
healthcheck_upstream = bp.upstreams:insert {
|
|
healthchecks = {
|
|
passive = {
|
|
healthy = {
|
|
successes = 1,
|
|
},
|
|
unhealthy = {
|
|
tcp_failures = 1,
|
|
http_failures = 1,
|
|
timeouts = 1,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
for i=1, 4 do
|
|
healthcheck_apis[i] = bp.targets:insert {
|
|
target = string.format("hc-api-%d:80", i),
|
|
weight = 10 * i,
|
|
upstream = { id = healthcheck_upstream.id },
|
|
}
|
|
end
|
|
|
|
empty_upstream = bp.upstreams:insert {}
|
|
|
|
assert(helpers.start_kong({
|
|
status_listen = "127.0.0.1:9500",
|
|
database = strategy,
|
|
nginx_conf = "spec/fixtures/custom_nginx.template",
|
|
}, nil, nil, fixtures))
|
|
end)
|
|
|
|
lazy_teardown(function()
|
|
assert(helpers.stop_kong())
|
|
end)
|
|
|
|
before_each(function()
|
|
client = assert(helpers.http_client("127.0.0.1", 9500, 20000))
|
|
end)
|
|
|
|
after_each(function()
|
|
if client then client:close() end
|
|
end)
|
|
|
|
describe("/upstreams/{upstream}/targets/", function()
|
|
|
|
describe("POST", function()
|
|
it("is not exposed", function()
|
|
local res = assert(client:post(
|
|
"/upstreams/" .. upstream.name .. "/targets/", {
|
|
body = {
|
|
target = "mashape.com",
|
|
},
|
|
headers = {["Content-Type"] = "application/json"}
|
|
}))
|
|
assert.response(res).has.status(405)
|
|
end)
|
|
end)
|
|
|
|
describe("GET", function()
|
|
it("shows all targets", function()
|
|
for _, append in ipairs({ "", "/" }) do
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/upstreams/" .. upstream.name .. "/targets" .. append,
|
|
})
|
|
assert.response(res).has.status(200)
|
|
local json = assert.response(res).has.jsonbody()
|
|
|
|
-- we got three active targets for this upstream
|
|
assert.equal(4, #json.data)
|
|
|
|
local apis_targets = {}
|
|
for _, t in ipairs(apis) do
|
|
apis_targets[t.id] = t.target
|
|
end
|
|
|
|
local data_targets = {}
|
|
for _, t in ipairs(json.data) do
|
|
data_targets[t.id] = t.target
|
|
end
|
|
|
|
assert.same(apis_targets, data_targets)
|
|
end
|
|
end)
|
|
|
|
describe("empty results", function()
|
|
it("data property is an empty array", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/upstreams/" .. empty_upstream.name .. "/targets",
|
|
})
|
|
local body = assert.response(res).has.status(200)
|
|
assert.match('"data":%[%]', body)
|
|
end)
|
|
end)
|
|
end)
|
|
end)
|
|
|
|
describe("/upstreams/{upstream}/health/", function()
|
|
|
|
describe("GET", function()
|
|
|
|
-- Performs tests similar to /upstreams/:upstream_id/targets,
|
|
-- and checks for the "health" field of each target.
|
|
-- @param targets the array of target data produced by add_targets
|
|
-- @param n the expected number of targets in the response
|
|
-- It is different from #targets because add_targets adds
|
|
-- zero-weight targets as well.
|
|
-- @param health the expected "health" response for all targets
|
|
local function check_health_endpoint(targets, upstream, n, health)
|
|
for _, append in ipairs({ "", "/" }) do
|
|
local status, body = client_send({
|
|
method = "GET",
|
|
path = "/upstreams/" .. upstream.name .. "/health" .. append,
|
|
})
|
|
assert.same(200, status)
|
|
local res = assert(cjson.decode(body))
|
|
|
|
assert.equal(n, #res.data)
|
|
|
|
|
|
local apis_targets = {}
|
|
for _, t in ipairs(targets) do
|
|
apis_targets[t.id] = t.target
|
|
end
|
|
|
|
local data_targets = {}
|
|
for _, t in ipairs(res.data) do
|
|
data_targets[t.id] = t.target
|
|
end
|
|
|
|
assert.same(apis_targets, data_targets)
|
|
|
|
for i = 1, n do
|
|
if res.data[i].data ~= nil and res.data[i].data.addresses ~= nil then
|
|
for j = 1, #res.data[i].data.addresses do
|
|
assert.equal(health, res.data[i].data.addresses[j].health)
|
|
end
|
|
assert.equal(health, res.data[i].health)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe("with healthchecks off", function()
|
|
it("returns HEALTHCHECKS_OFF for targets that resolve", function()
|
|
check_health_endpoint(apis, upstream, 4, "HEALTHCHECKS_OFF")
|
|
end)
|
|
|
|
end)
|
|
|
|
describe("with healthchecks on", function()
|
|
|
|
it("returns DNS_ERROR if DNS cannot be resolved", function()
|
|
|
|
check_health_endpoint(healthcheck_apis, healthcheck_upstream, 4, "DNS_ERROR")
|
|
|
|
end)
|
|
|
|
pending("returns HEALTHY if failure not detected", function()
|
|
|
|
check_health_endpoint(healthcheck_apis, healthcheck_upstream, 4, "HEALTHY")
|
|
|
|
end)
|
|
|
|
end)
|
|
end)
|
|
end)
|
|
|
|
describe("/upstreams/{upstream}/targets/all/", function()
|
|
|
|
describe("GET", function()
|
|
it("retrieves the first page", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/upstreams/" .. upstream.name .. "/targets/all",
|
|
})
|
|
assert.response(res).has.status(200)
|
|
local json = assert.response(res).has.jsonbody()
|
|
assert.equal(4, #json.data)
|
|
end)
|
|
it("offset is a string", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/upstreams/" .. upstream.name .. "/targets",
|
|
query = {size = 2},
|
|
})
|
|
assert.response(res).has.status(200)
|
|
local json = assert.response(res).has.jsonbody()
|
|
assert.is_string(json.offset)
|
|
end)
|
|
it("paginates a set", function()
|
|
local pages = {}
|
|
local offset
|
|
|
|
for i = 1, 3 do
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/upstreams/" .. upstream.name .. "/targets/all",
|
|
query = {size = 2, offset = offset}
|
|
})
|
|
assert.response(res).has.status(200)
|
|
local json = assert.response(res).has.jsonbody()
|
|
|
|
if i < 3 then
|
|
assert.equal(2, #json.data)
|
|
else
|
|
assert.equal(0, #json.data)
|
|
end
|
|
|
|
if i > 1 then
|
|
-- check all pages are different
|
|
assert.not_same(pages[i-1], json)
|
|
end
|
|
|
|
offset = json.offset
|
|
pages[i] = json
|
|
end
|
|
end)
|
|
it("ignores filters", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/upstreams/" .. upstream.name .. "/targets/all",
|
|
query = {foo = "bar"},
|
|
})
|
|
assert.response(res).has.status(200)
|
|
end)
|
|
it("ignores an invalid body", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/upstreams/" .. upstream.name .. "/targets/all",
|
|
body = "this fails if decoded as json",
|
|
headers = {
|
|
["Content-Type"] = "application/json",
|
|
}
|
|
})
|
|
assert.response(res).has.status(200)
|
|
end)
|
|
|
|
describe("empty results", function()
|
|
it("data property is an empty array", function()
|
|
local res = assert(client:send {
|
|
method = "GET",
|
|
path = "/upstreams/" .. empty_upstream.name .. "/targets/all",
|
|
})
|
|
local body = assert.response(res).has.status(200)
|
|
local json = cjson.decode(body)
|
|
assert.same({
|
|
data = {},
|
|
next = ngx.null,
|
|
}, json)
|
|
-- ensure JSON representation is correct
|
|
assert.match('"data":%[%]', body)
|
|
end)
|
|
end)
|
|
end)
|
|
end)
|
|
|
|
describe("/upstreams/{upstream}/targets/{target}/(un)healthy", function()
|
|
|
|
describe("POST", function()
|
|
|
|
it("is not exposed", function()
|
|
local status, body
|
|
status, body = assert(client_send {
|
|
method = "POST",
|
|
path = "/upstreams/" .. upstream.name .. "/targets/" .. apis[1].target .. "/unhealthy"
|
|
})
|
|
assert.same(404, status, body)
|
|
end)
|
|
end)
|
|
end)
|
|
|
|
describe("/upstreams/{upstream}/targets/{target}", function()
|
|
local target = apis[1]
|
|
|
|
describe("GET", function()
|
|
|
|
it("returns target entity", function()
|
|
local res = client:get("/upstreams/" .. upstream.name .. "/targets/" .. target.target)
|
|
assert.response(res).has.status(200)
|
|
local json = assert.response(res).has.jsonbody()
|
|
json.tags = nil
|
|
if json.upstream.id then
|
|
json.upstream = json.upstream.id
|
|
end
|
|
assert.same(target, json)
|
|
end)
|
|
end)
|
|
|
|
describe("PATCH", function()
|
|
|
|
it("is not exposed", function()
|
|
local res = client:patch("/upstreams/" .. upstream.name .. "/targets/" .. target.target, {
|
|
body = {
|
|
weight = 659,
|
|
},
|
|
headers = { ["Content-Type"] = "application/json" }
|
|
})
|
|
assert.response(res).has.status(405)
|
|
end)
|
|
end)
|
|
|
|
describe("PUT", function()
|
|
|
|
it("is not exposed", function()
|
|
local res = client:put("/upstreams/" .. upstream.name .. "/targets/" .. target.target, {
|
|
body = {
|
|
target = target.target
|
|
},
|
|
headers = { ["Content-Type"] = "application/json" }
|
|
})
|
|
|
|
assert.response(res).has.status(405)
|
|
end)
|
|
|
|
end)
|
|
|
|
describe("DELETE", function()
|
|
|
|
it("is not exposed", function()
|
|
local res = assert(client:send {
|
|
method = "DELETE",
|
|
path = "/upstreams/" .. upstream.name .. "/targets/" .. target.target
|
|
})
|
|
assert.response(res).has.status(405)
|
|
end)
|
|
end)
|
|
end)
|
|
end)
|