Skip to content

Commit

Permalink
feat(wasm): add /schemas/filters/:name API endpoint (#11739)
Browse files Browse the repository at this point in the history
This exposes JSON schemas for Wasm filters via a new API endpoint. For
filters without a user-supplied schema, the default schema is returned.

For better interoperability with other systems, we also ensure that each
schema has the proper draft 4 '$schema' attribute.
  • Loading branch information
flrgh committed Oct 11, 2023
1 parent 064ea58 commit 7f20bb1
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 1 deletion.
40 changes: 40 additions & 0 deletions kong/api/routes/kong.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local api_helpers = require "kong.api.api_helpers"
local Schema = require "kong.db.schema"
local Errors = require "kong.db.errors"
local process = require "ngx.process"
local wasm = require "kong.runloop.wasm"

local kong = kong
local meta = require "kong.meta"
Expand Down Expand Up @@ -44,6 +45,29 @@ local function validate_schema(db_entity_name, params)
return kong.response.exit(200, { message = "schema validation successful" })
end

local default_filter_config_schema
do
local default

function default_filter_config_schema(db)
if default then
return default
end

local dao = db.filter_chains or kong.db.filter_chains
for key, field in dao.schema:each_field() do
if key == "filters" then
for _, ffield in ipairs(field.elements.fields) do
if ffield.config and ffield.config.json_schema then
default = ffield.config.json_schema.default
return default
end
end
end
end
end
end


return {
["/"] = {
Expand Down Expand Up @@ -209,6 +233,22 @@ return {
return kong.response.exit(200, copy)
end
},
["/schemas/filters/:name"] = {
GET = function(self, db)
local name = self.params.name

if not wasm.filters_by_name[name] then
local msg = "Filter '" .. name .. "' not found"
return kong.response.exit(404, { message = msg })
end

local schema = wasm.filter_meta[name]
and wasm.filter_meta[name].config_schema
or default_filter_config_schema(db)

return kong.response.exit(200, schema)
end
},
["/timers"] = {
GET = function (self, db, helpers)
local body = {
Expand Down
2 changes: 2 additions & 0 deletions kong/db/schema/entities/filter_chains.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local typedefs = require "kong.db.schema.typedefs"
local wasm = require "kong.runloop.wasm"
local constants = require "kong.constants"
local json_schema = require "kong.db.schema.json"


---@class kong.db.schema.entities.filter_chain : table
Expand Down Expand Up @@ -38,6 +39,7 @@ local filter = {
namespace = constants.SCHEMA_NAMESPACES.PROXY_WASM_FILTERS,
optional = true,
default = {
["$schema"] = json_schema.DRAFT_4,
-- filters with no user-defined JSON schema may accept an optional
-- config, but only as a string
type = { "string", "null" },
Expand Down
4 changes: 3 additions & 1 deletion kong/db/schema/json.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ assert(type(metaschema.id) == "string",
local DRAFT_4_NO_FRAGMENT = metaschema.id:gsub("#$", "")
local DRAFT_4 = DRAFT_4_NO_FRAGMENT .. "#"

_M.DRAFT_4 = DRAFT_4


---@type table<string, table>
local schemas = {}
Expand Down Expand Up @@ -154,7 +156,7 @@ end
---@param name string
---@param schema kong.db.schema.json.schema_doc
function _M.add_schema(name, schema)
schemas[name] = schema
schemas[name] = utils.cycle_aware_deep_copy(schema, true)
end


Expand Down
1 change: 1 addition & 0 deletions kong/runloop/wasm.lua
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ local function discover_filter_metadata(filters)
for name, meta in pairs(_M.filter_meta) do
if meta.config_schema then
local schema_name = namespace .. "/" .. name
meta.config_schema["$schema"] = json_schema.DRAFT_4
json_schema.add_schema(schema_name, meta.config_schema)
end
end
Expand Down
49 changes: 49 additions & 0 deletions spec/02-integration/20-wasm/09-filter-meta_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,55 @@ describe("filter metadata [#" .. strategy .. "]", function()
end)
end)

describe("API", function()
describe("GET /schemas/filters/:name", function()
it("returns a 404 for unknown filters", function()
local res = admin:get("/schemas/filters/i-do-not-exist")
assert.response(res).has.status(404)
local json = assert.response(res).has.jsonbody()
assert.same({ message = "Filter 'i-do-not-exist' not found" }, json)
end)

it("returns a schema for filters that have it", function()
local res = admin:get("/schemas/filters/rt_with_validation")
assert.response(res).has.status(200)
local json = assert.response(res).has.jsonbody()

assert.same(
{
["$schema"] = "http://json-schema.org/draft-04/schema#",
type = "object",
properties = {
add = {
type = "object",
properties = {
headers = {
type = "array",
elements = { type = "string" },
},
},
required = { "headers" },
},
},
required = { "add" },
},
json
)
end)

it("returns the default schema for filters without schemas", function()
local res = admin:get("/schemas/filters/rt_no_validation")
assert.response(res).has.status(200)
local json = assert.response(res).has.jsonbody()

assert.same({
["$schema"] = "http://json-schema.org/draft-04/schema#",
type = { "string", "null" }
}, json)
end)
end)
end)

end)

describe("filter metadata [#" .. strategy .. "] startup errors -", function()
Expand Down

1 comment on commit 7f20bb1

@khcp-gha-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bazel Build

Docker image available kong/kong:7f20bb15dcc1782065d728a70f56c262cbab6689
Artifacts available https://github.com/Kong/kong/actions/runs/6487694724

Please sign in to comment.