263 lines
7.7 KiB
Lua
263 lines
7.7 KiB
Lua
local endpoints = require "kong.api.endpoints"
|
|
local uuid = require "kong.tools.uuid"
|
|
|
|
|
|
local kong = kong
|
|
local escape_uri = ngx.escape_uri
|
|
local unescape_uri = ngx.unescape_uri
|
|
local null = ngx.null
|
|
local tostring = tostring
|
|
local fmt = string.format
|
|
|
|
|
|
local function set_target_health(self, db, is_healthy)
|
|
local upstream, _, err_t = endpoints.select_entity(self, db, db.upstreams.schema)
|
|
if err_t then
|
|
return endpoints.handle_error(err_t)
|
|
end
|
|
|
|
if not upstream then
|
|
return kong.response.exit(404, { message = "Not found" })
|
|
end
|
|
|
|
local target
|
|
if uuid.is_valid_uuid(unescape_uri(self.params.targets)) then
|
|
target, _, err_t = endpoints.select_entity(self, db, db.targets.schema)
|
|
|
|
else
|
|
local opts
|
|
opts, _, err_t = endpoints.extract_options(db, self.args.uri, db.targets.schema, "select")
|
|
if err_t then
|
|
return endpoints.handle_error(err_t)
|
|
end
|
|
|
|
local upstream_pk = db.upstreams.schema:extract_pk_values(upstream)
|
|
local filter = { target = unescape_uri(self.params.targets) }
|
|
target, _, err_t = db.targets:select_by_upstream_filter(upstream_pk, filter, opts)
|
|
end
|
|
|
|
if err_t then
|
|
return endpoints.handle_error(err_t)
|
|
end
|
|
|
|
if not target or target.upstream.id ~= upstream.id then
|
|
return kong.response.exit(404, { message = "Not found" })
|
|
end
|
|
|
|
local ok, err = db.targets:post_health(upstream, target, self.params.address, is_healthy)
|
|
if not ok then
|
|
return kong.response.exit(400, { message = err })
|
|
end
|
|
|
|
return kong.response.exit(204)
|
|
end
|
|
|
|
|
|
local function select_target_cb(self, db, upstream, target)
|
|
if target then
|
|
return kong.response.exit(200, target)
|
|
end
|
|
|
|
return kong.response.exit(404, { message = "Not found" })
|
|
end
|
|
|
|
|
|
local function update_target_cb(self, db, upstream, target)
|
|
self.params.targets = db.targets.schema:extract_pk_values(target)
|
|
local entity, _, err_t = endpoints.update_entity(self, db, db.targets.schema)
|
|
if err_t then
|
|
return endpoints.handle_error(err_t)
|
|
end
|
|
|
|
return kong.response.exit(200, entity)
|
|
end
|
|
|
|
|
|
local function delete_target_cb(self, db, upstream, target)
|
|
self.params.targets = db.targets.schema:extract_pk_values(target)
|
|
local _, _, err_t = endpoints.delete_entity(self, db, db.targets.schema)
|
|
if err_t then
|
|
return endpoints.handle_error(err_t)
|
|
end
|
|
|
|
return kong.response.exit(204) -- no content
|
|
end
|
|
|
|
|
|
local function target_endpoint(self, db, callback)
|
|
local upstream, _, err_t = endpoints.select_entity(self, db, db.upstreams.schema)
|
|
if err_t then
|
|
return endpoints.handle_error(err_t)
|
|
end
|
|
|
|
if not upstream then
|
|
return kong.response.exit(404, { message = "Not found" })
|
|
end
|
|
|
|
local target
|
|
if uuid.is_valid_uuid(unescape_uri(self.params.targets)) then
|
|
target, _, err_t = endpoints.select_entity(self, db, db.targets.schema)
|
|
|
|
else
|
|
local opts
|
|
opts, _, err_t = endpoints.extract_options(db, self.args.uri, db.targets.schema, "select")
|
|
if err_t then
|
|
return endpoints.handle_error(err_t)
|
|
end
|
|
local upstream_pk = db.upstreams.schema:extract_pk_values(upstream)
|
|
local filter = { target = unescape_uri(self.params.targets) }
|
|
target, _, err_t = db.targets:select_by_upstream_filter(upstream_pk, filter, opts)
|
|
end
|
|
|
|
if err_t then
|
|
return endpoints.handle_error(err_t)
|
|
end
|
|
|
|
if not target or target.upstream.id ~= upstream.id then
|
|
return kong.response.exit(404, { message = "Not found" })
|
|
end
|
|
|
|
return callback(self, db, upstream, target)
|
|
end
|
|
|
|
|
|
local api_routes = {
|
|
["/upstreams/:upstreams/health"] = {
|
|
GET = function(self, db)
|
|
local upstream, _, err_t = endpoints.select_entity(self, db, db.upstreams.schema)
|
|
if err_t then
|
|
return endpoints.handle_error(err_t)
|
|
end
|
|
|
|
if not upstream then
|
|
return kong.response.exit(404, { message = "Not found" })
|
|
end
|
|
|
|
local node_id, err = kong.node.get_id()
|
|
if err then
|
|
kong.log.err("failed to get node id: ", err)
|
|
end
|
|
|
|
if tostring(self.params.balancer_health) == "1" then
|
|
local upstream_pk = db.upstreams.schema:extract_pk_values(upstream)
|
|
local balancer_health = db.targets:get_balancer_health(upstream_pk)
|
|
return kong.response.exit(200, {
|
|
data = balancer_health,
|
|
next = null,
|
|
node_id = node_id,
|
|
})
|
|
end
|
|
|
|
self.params.targets = db.upstreams.schema:extract_pk_values(upstream)
|
|
local targets_with_health, _, err_t, offset =
|
|
endpoints.page_collection(self, db, db.targets.schema, "page_for_upstream_with_health")
|
|
|
|
if err_t then
|
|
return endpoints.handle_error(err_t)
|
|
end
|
|
|
|
local next_page = offset and fmt("/upstreams/%s/health?offset=%s",
|
|
self.params.upstreams,
|
|
escape_uri(offset)) or null
|
|
|
|
return kong.response.exit(200, {
|
|
data = targets_with_health,
|
|
offset = offset,
|
|
next = next_page,
|
|
node_id = node_id,
|
|
})
|
|
end
|
|
},
|
|
|
|
["/upstreams/:upstreams/targets"] = {
|
|
GET = endpoints.get_collection_endpoint(kong.db.targets.schema,
|
|
kong.db.upstreams.schema,
|
|
"upstream",
|
|
"page_for_upstream"),
|
|
POST = function(self, db)
|
|
local create = endpoints.post_collection_endpoint(kong.db.targets.schema,
|
|
kong.db.upstreams.schema, "upstream")
|
|
return create(self, db)
|
|
end,
|
|
},
|
|
|
|
["/upstreams/:upstreams/targets/all"] = {
|
|
GET = function(self, db)
|
|
local schema = db.targets.schema
|
|
local foreign_schema = db.upstreams.schema
|
|
local foreign_entity, _, err_t = endpoints.select_entity(self, db, foreign_schema)
|
|
if err_t then
|
|
return endpoints.handle_error(err_t)
|
|
end
|
|
|
|
if not foreign_entity then
|
|
return endpoints.not_found()
|
|
end
|
|
|
|
self.params[schema.name] = schema:extract_pk_values(foreign_entity)
|
|
|
|
local method = "page_for_upstream_raw"
|
|
local data, _, err_t, offset = endpoints.page_collection(self, db, schema, method)
|
|
if err_t then
|
|
return endpoints.handle_error(err_t)
|
|
end
|
|
|
|
local foreign_key = self.params[foreign_schema.name]
|
|
local next_page = offset and fmt("/upstreams/%s/targets/all?offset=%s",
|
|
foreign_key,
|
|
escape_uri(offset)) or null
|
|
|
|
return kong.response.exit(200, {
|
|
data = data,
|
|
offset = offset,
|
|
next = next_page,
|
|
})
|
|
end
|
|
},
|
|
|
|
["/upstreams/:upstreams/targets/:targets"] = {
|
|
DELETE = function(self, db)
|
|
return target_endpoint(self, db, delete_target_cb)
|
|
end,
|
|
GET = function(self, db)
|
|
return target_endpoint(self, db, select_target_cb)
|
|
end,
|
|
PATCH = function(self, db)
|
|
return target_endpoint(self, db, update_target_cb)
|
|
end,
|
|
PUT = function(self, db)
|
|
return target_endpoint(self, db, update_target_cb)
|
|
end,
|
|
},
|
|
}
|
|
|
|
-- upstream targets' healthcheck management is not available in the hybrid mode
|
|
if kong.configuration.role ~= "control_plane" then
|
|
api_routes["/upstreams/:upstreams/targets/:targets/healthy"] = {
|
|
PUT = function(self, db)
|
|
return set_target_health(self, db, true)
|
|
end,
|
|
}
|
|
|
|
api_routes["/upstreams/:upstreams/targets/:targets/unhealthy"] = {
|
|
PUT = function(self, db)
|
|
return set_target_health(self, db, false)
|
|
end,
|
|
}
|
|
|
|
api_routes["/upstreams/:upstreams/targets/:targets/:address/healthy"] = {
|
|
PUT = function(self, db)
|
|
return set_target_health(self, db, true)
|
|
end,
|
|
}
|
|
|
|
api_routes["/upstreams/:upstreams/targets/:targets/:address/unhealthy"] = {
|
|
PUT = function(self, db)
|
|
return set_target_health(self, db, false)
|
|
end,
|
|
}
|
|
|
|
end
|
|
|
|
return api_routes
|