Skip to content

Commit

Permalink
Merge pull request #3778 from Kong/feat/plugins-schemas-to-new-db
Browse files Browse the repository at this point in the history
This merge converts the schemas of all bundled plugins to the new DB format
  • Loading branch information
hishamhm authored Oct 4, 2018
2 parents 6f3f957 + 9e0d1c4 commit 9cda865
Show file tree
Hide file tree
Showing 77 changed files with 1,364 additions and 1,945 deletions.
2 changes: 1 addition & 1 deletion kong/db/dao/plugins.lua
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ function Plugins:load_plugin_schemas(plugin_set)
end
end

ok, err = self.schema:new_subschema(plugin, schema)
ok, err = Entity.new_subschema(self.schema, plugin, schema)
if not ok then
return nil, "error initializing schema for plugin: " .. err
end
Expand Down
10 changes: 2 additions & 8 deletions kong/db/schema/entities/upstreams.lua
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,6 @@ local positive_int_or_zero = Schema.define {
}


local header_name = Schema.define {
type = "string",
custom_validator = utils.validate_header_name,
}


local check_type = Schema.define {
type = "string",
one_of = { "tcp", "http", "https" },
Expand Down Expand Up @@ -162,8 +156,8 @@ local r = {
{ name = { type = "string", required = true, unique = true, custom_validator = validate_name }, },
{ hash_on = hash_on },
{ hash_fallback = hash_on },
{ hash_on_header = header_name, },
{ hash_fallback_header = header_name, },
{ hash_on_header = typedefs.header_name, },
{ hash_fallback_header = typedefs.header_name, },
{ hash_on_cookie = { type = "string", custom_validator = utils.validate_cookie_name }, },
{ hash_on_cookie_path = typedefs.path{ default = "/", }, },
{ slots = { type = "integer", default = 10000, between = { 10, 2^16 }, }, },
Expand Down
7 changes: 7 additions & 0 deletions kong/db/schema/entity.lua
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,11 @@ function Entity.new(definition)
end


function Entity.new_subschema(schema, key, definition)
make_records_non_nullable(definition)
definition.nullable = nil
return Schema.new_subschema(schema, key, definition)
end


return Entity
112 changes: 65 additions & 47 deletions kong/db/schema/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ local validation_errors = {
-- validations
EQ = "value must be %s",
NE = "value must not be %s",
GT = "value must be greater than %s",
BETWEEN = "value should be between %d and %d",
LEN_EQ = "length must be %d",
LEN_MIN = "length must be at least %d",
Expand All @@ -69,6 +70,7 @@ local validation_errors = {
MATCH_NONE = "invalid value: %s",
MATCH_ANY = "invalid value: %s",
STARTS_WITH = "should start with: %s",
CONTAINS = "expected to contain: %s",
ONE_OF = "expected one of: %s",
IS_REGEX = "not a valid regex: %s",
TIMESTAMP = "expected a valid timestamp",
Expand Down Expand Up @@ -177,6 +179,13 @@ Schema.validators = {
return nil, validation_errors.NE:format(str)
end,

gt = function(value, limit)
if value > limit then
return true
end
return nil, validation_errors.GT:format(tostring(limit))
end,

len_eq = make_length_validator("LEN_EQ", function(len, n)
return len == n
end),
Expand Down Expand Up @@ -268,6 +277,16 @@ Schema.validators = {
return re_find(value, uuid_regex, "ioj") and true or nil
end,

contains = function(array, wanted)
for _, item in ipairs(array) do
if item == wanted then
return true
end
end

return nil, validation_errors.CONTAINS:format(wanted)
end,

custom_validator = function(value, fn)
return fn(value)
end
Expand All @@ -281,6 +300,7 @@ Schema.validators_order = {
"one_of",

-- type-dependent
"gt",
"timestamp",
"uuid",
"is_regex",
Expand All @@ -299,6 +319,9 @@ Schema.validators_order = {
"match_all",
"match_any",

-- arrays
"contains",

-- other
"custom_validator",
}
Expand Down Expand Up @@ -707,9 +730,11 @@ function Schema:validate_field(field, value)
if field[k] then
local ok, err = self.validators[k](value, field[k], field)
if not ok then
if not err then
err = (validation_errors[k:upper()]
or validation_errors.VALIDATION):format(value)
end
return nil, err
or validation_errors[k:upper()]:format(value)
or validation_errors.VALIDATION:format(value)
end
end
end
Expand Down Expand Up @@ -1147,41 +1172,33 @@ local function make_set(set)
end


local function adjust_field_for_update(field, value, nulls)
if field.type == "record" and
not field.abstract and
((value == null and field.nullable == false)
or (value == nil and field.nullable == false)
or (value ~= null and value ~= nil)) then
local field_schema = get_field_schema(field)
return field_schema:process_auto_fields(value or {}, "update", nulls)
end
if value == nil then
return nil
end
if field.type == "array" then
return make_array(value)
end
if field.type == "set" then
return make_set(value)
end

return value
end


local function adjust_field_for_context(field, value, context, nulls)
if value == null and field.nullable == false then
if context ~= "update" and value == null and field.nullable == false then
return handle_missing_field(field, value)
end
if field.type == "record" and not field.abstract
and value ~= null and
(value ~= nil or field.nullable == false) then
local field_schema = get_field_schema(field)
return field_schema:process_auto_fields(value or {}, context, nulls)
if field.type == "record" and not field.abstract then
local should_recurse
if context == "update" then
-- avoid filling defaults in partial updates of records
should_recurse = ((value == null and field.nullable == false)
or (value == nil and field.nullable == false)
or (value ~= null and value ~= nil))
else
should_recurse = (value ~= null and
(value ~= nil or field.nullable == false))
end
if should_recurse then
local field_schema = get_field_schema(field)
value = value or handle_missing_field(field, value)
return field_schema:process_auto_fields(value, context, nulls)
end
end
if value == nil then
return handle_missing_field(field, value)
if context == "update" then
return nil
else
return handle_missing_field(field, value)
end
end
if field.type == "array" then
return make_array(value)
Expand All @@ -1203,7 +1220,7 @@ end
-- for value creation and update.
-- @param input The table containing data to be processed.
-- @param context a string describing the CRUD context:
-- valid values are: "insert", "update"
-- valid values are: "insert", "update", "upsert"
-- @param nulls boolean: return nulls as explicit ngx.null values
-- @return A new table, with the auto fields containing
-- appropriate updated values.
Expand All @@ -1227,11 +1244,21 @@ function Schema:process_auto_fields(input, context, nulls)
--]]

for key, field in self:each_field(input) do

if field.legacy and field.uuid and output[key] == "" then
output[key] = null
end

if field.auto then
if field.uuid and context == "insert" and output[key] == nil then
output[key] = utils.uuid()
elseif field.uuid and context == "upsert" and output[key] == nil then
output[key] = utils.uuid()
if field.uuid then
if (context == "insert" or context == "upsert") and output[key] == nil then
output[key] = utils.uuid()
end

elseif field.type == "string" then
if (context == "insert" or context == "upsert") and output[key] == nil then
output[key] = utils.random_string()
end

elseif (key == "created_at" and (context == "insert" or
context == "upsert")) or
Expand All @@ -1244,19 +1271,10 @@ function Schema:process_auto_fields(input, context, nulls)
elseif field.type == "integer" then
output[key] = now_s
end

elseif field.type == "string" and output[key] == nil
and (context == "insert" or
context == "upsert") then
output[key] = utils.random_string()
end
end

if context == "update" then
output[key] = adjust_field_for_update(field, output[key], nulls)
else
output[key] = adjust_field_for_context(field, output[key], context, nulls)
end
output[key] = adjust_field_for_context(field, output[key], context, nulls)

if output[key] ~= nil then
if self.cache_key_set and self.cache_key_set[key] then
Expand Down
10 changes: 10 additions & 0 deletions kong/db/schema/metaschema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ local validators = {
{ between = { type = "array", elements = { type = "integer" }, len_eq = 2 }, },
{ eq = { type = "any" }, },
{ ne = { type = "any" }, },
{ gt = { type = "number" }, },
{ len_eq = { type = "integer" }, },
{ len_min = { type = "integer" }, },
{ len_max = { type = "integer" }, },
Expand All @@ -46,6 +47,7 @@ local validators = {
{ match_any = match_any_list },
{ starts_with = { type = "string" }, },
{ one_of = { type = "array", elements = { type = "string" } }, },
{ contains = { type = "any" }, },
{ is_regex = { type = "boolean" }, },
{ timestamp = { type = "boolean" }, },
{ uuid = { type = "boolean" }, },
Expand All @@ -62,6 +64,7 @@ local field_schema = {
{ on_delete = { type = "string", one_of = { "restrict", "cascade", "null" } }, },
{ default = { type = "self" }, },
{ abstract = { type = "boolean" }, },
{ legacy = { type = "boolean" }, },
}

for _, field in ipairs(validators) do
Expand Down Expand Up @@ -179,6 +182,10 @@ local attribute_types = {
["number"] = true,
["integer"] = true,
},
contains = {
["array"] = true,
["set"] = true,
},
is_regex = {
["string"] = true,
},
Expand All @@ -189,6 +196,9 @@ local attribute_types = {
uuid = {
["string"] = true,
},
legacy = {
["string"] = true,
},
unique = {
["string"] = true,
["number"] = true,
Expand Down
30 changes: 30 additions & 0 deletions kong/db/schema/typedefs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
-- @module kong.db.schema.typedefs
local utils = require "kong.tools.utils"
local Schema = require("kong.db.schema")
local socket_url = require("socket.url")


local match = string.match
Expand Down Expand Up @@ -75,6 +76,25 @@ local function validate_sni(host)
end


local function validate_url(url)
local parsed_url, err = socket_url.parse(url)

if not parsed_url then
return nil, "could not parse url. " .. err
end

if not parsed_url.host then
return nil, "missing host in url"
end

if not parsed_url.scheme then
return nil, "missing scheme in url"
end

return true
end


local typedefs = {}


Expand Down Expand Up @@ -116,6 +136,16 @@ typedefs.path = Schema.define {
custom_validator = validate_path,
}

typedefs.url = Schema.define {
type = "string",
custom_validator = validate_url,
}

typedefs.header_name = Schema.define {
type = "string",
custom_validator = utils.validate_header_name,
}


typedefs.timeout = Schema.define {
type = "integer",
Expand Down
30 changes: 17 additions & 13 deletions kong/plugins/acl/schema.lua
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
local Errors = require "kong.dao.errors"
local typedefs = require "kong.db.schema.typedefs"


return {
no_consumer = true,
name = "acl",
fields = {
whitelist = { type = "array" },
blacklist = { type = "array" },
hide_groups_header = { type = "boolean", default = false },
{ consumer = typedefs.no_consumer },
{ config = {
type = "record",
fields = {
{ whitelist = { type = "array", elements = { type = "string" }, }, },
{ blacklist = { type = "array", elements = { type = "string" }, }, },
{ hide_groups_header = { type = "boolean", default = false }, },
}
}
}
},
entity_checks = {
{ only_one_of = { "config.whitelist", "config.blacklist" }, },
{ at_least_one_of = { "config.whitelist", "config.blacklist" }, },
},
self_check = function(schema, plugin_t, dao, is_update)
if next(plugin_t.whitelist or {}) and next(plugin_t.blacklist or {}) then
return false, Errors.schema "You cannot set both a whitelist and a blacklist"
elseif not (next(plugin_t.whitelist or {}) or next(plugin_t.blacklist or {})) then
return false, Errors.schema "You must set at least a whitelist or blacklist"
end
return true
end
}
Loading

0 comments on commit 9cda865

Please sign in to comment.