Skip to content

Commit

Permalink
Merge pull request #4275 from Kong/feat/core-entity-tags
Browse files Browse the repository at this point in the history
feat(core) implement entity tagging
  • Loading branch information
hishamhm authored Feb 13, 2019
2 parents 271a388 + 9f69772 commit abcfdf1
Show file tree
Hide file tree
Showing 35 changed files with 1,984 additions and 67 deletions.
5 changes: 5 additions & 0 deletions kong-1.0.3-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ build = {
["kong.api.routes.targets"] = "kong/api/routes/targets.lua",
["kong.api.routes.certificates"] = "kong/api/routes/certificates.lua",
["kong.api.routes.snis"] = "kong/api/routes/snis.lua",
["kong.api.routes.tags"] = "kong/api/routes/tags.lua",

["kong.tools.cluster_ca"] = "kong/tools/cluster_ca.lua",
["kong.tools.ciphers"] = "kong/tools/ciphers.lua",
Expand All @@ -126,6 +127,7 @@ build = {
["kong.db.dao.snis"] = "kong/db/dao/snis.lua",
["kong.db.dao.targets"] = "kong/db/dao/targets.lua",
["kong.db.dao.plugins"] = "kong/db/dao/plugins.lua",
["kong.db.dao.tags"] = "kong/db/dao/tags.lua",
["kong.db.schema"] = "kong/db/schema/init.lua",
["kong.db.schema.entities.cluster_ca"] = "kong/db/schema/entities/cluster_ca.lua",
["kong.db.schema.entities.consumers"] = "kong/db/schema/entities/consumers.lua",
Expand All @@ -136,6 +138,7 @@ build = {
["kong.db.schema.entities.upstreams"] = "kong/db/schema/entities/upstreams.lua",
["kong.db.schema.entities.targets"] = "kong/db/schema/entities/targets.lua",
["kong.db.schema.entities.plugins"] = "kong/db/schema/entities/plugins.lua",
["kong.db.schema.entities.tags"] = "kong/db/schema/entities/tags.lua",
["kong.db.schema.others.migrations"] = "kong/db/schema/others/migrations.lua",
["kong.db.schema.entity"] = "kong/db/schema/entity.lua",
["kong.db.schema.metaschema"] = "kong/db/schema/metaschema.lua",
Expand All @@ -146,9 +149,11 @@ build = {
["kong.db.strategies.cassandra.connector"] = "kong/db/strategies/cassandra/connector.lua",
["kong.db.strategies.cassandra.plugins"] = "kong/db/strategies/cassandra/plugins.lua",
["kong.db.strategies.cassandra.services"] = "kong/db/strategies/cassandra/services.lua",
["kong.db.strategies.cassandra.tags"] = "kong/db/strategies/cassandra/tags.lua",
["kong.db.strategies.postgres"] = "kong/db/strategies/postgres/init.lua",
["kong.db.strategies.postgres.plugins"] = "kong/db/strategies/postgres/plugins.lua",
["kong.db.strategies.postgres.connector"] = "kong/db/strategies/postgres/connector.lua",
["kong.db.strategies.postgres.tags"] = "kong/db/strategies/postgres/tags.lua",
["kong.db.migrations.state"] = "kong/db/migrations/state.lua",
["kong.db.migrations.helpers"] = "kong/db/migrations/helpers.lua",
["kong.db.migrations.core"] = "kong/db/migrations/core/init.lua",
Expand Down
4 changes: 4 additions & 0 deletions kong/api/arguments.lua
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,10 @@ infer = function(args, schema)
end
end

if schema.ttl == true and args.ttl then
args.ttl = tonumber(args.ttl) or args.ttl
end

return args
end

Expand Down
48 changes: 43 additions & 5 deletions kong/api/endpoints.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ local unescape_uri = ngx.unescape_uri
local tonumber = tonumber
local tostring = tostring
local select = select
local concat = table.concat
local null = ngx.null
local type = type
local fmt = string.format
local concat = table.concat
local re_match = ngx.re.match
local split = utils.split


-- error codes http status codes
Expand Down Expand Up @@ -125,9 +127,32 @@ local function extract_options(args, schema, context)
if schema.ttl == true and args.ttl ~= nil and (context == "insert" or
context == "update" or
context == "upsert") then
options.ttl = tonumber(args.ttl) or args.ttl
options.ttl = args.ttl
args.ttl = nil
end

if schema.fields.tags and args.tags ~= nil and context == "page" then
local tags = args.tags
if type(tags) == "table" then
tags = tags[1]
end

if re_match(tags, [=[^([a-zA-Z0-9\.\-\_~]+(?:,|$))+$]=], 'jo') then
-- 'a,b,c' or 'a'
options.tags_cond = 'and'
options.tags = split(tags, ',')
elseif re_match(tags, [=[^([a-zA-Z0-9\.\-\_~]+(?:/|$))+$]=], 'jo') then
-- 'a/b/c'
options.tags_cond = 'or'
options.tags = split(tags, '/')
else
options.tags = tags
-- not setting tags_cond since we can't determine the cond
-- will raise an error in db/dao/init.lua:validate_options_value
end

args.tags = nil
end
end

return options
Expand Down Expand Up @@ -158,7 +183,11 @@ local function query_entity(context, self, db, schema, method)
args = self.args.uri
end

local opts = extract_options(args, schema, context)
local opts, err = extract_options(args, schema, context)
if err then
return nil, err, db[schema.name].errors:invalid_size(err)
end

local dao = db[schema.name]

if is_insert then
Expand Down Expand Up @@ -249,14 +278,23 @@ end
-- /services
local function get_collection_endpoint(schema, foreign_schema, foreign_field_name, method)
return not foreign_schema and function(self, db, helpers)
local next_page_tags = ""

local args = self.args.uri
if args.tags then
next_page_tags = "&tags=" .. (type(args.tags) == "table" and args.tags[1] or args.tags)
end

local data, _, err_t, offset = page_collection(self, db, schema, method)

if err_t then
return handle_error(err_t)
end

local next_page = offset and fmt("/%s?offset=%s",
local next_page = offset and fmt("/%s?offset=%s%s",
schema.name,
escape_uri(offset)) or null
escape_uri(offset),
next_page_tags) or null

return ok {
data = data,
Expand Down
32 changes: 32 additions & 0 deletions kong/api/routes/tags.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
local endpoints = require "kong.api.endpoints"

local fmt = string.format
local escape_uri = ngx.escape_uri


return {
["/tags/:tags"] = {
GET = function(self, db, helpers, parent)
local data, _, err_t, offset =
endpoints.page_collection(self, db, db.tags.schema, "page_by_tag")

if err_t then
return endpoints.handle_error(err_t)
end

local next_page
if offset then
next_page = fmt("/tags/%s?offset=%s", self.params.tags, escape_uri(offset))

else
next_page = ngx.null
end

return kong.response.exit(200, {
data = data,
offset = offset,
next = next_page,
})
end,
},
}
27 changes: 26 additions & 1 deletion kong/db/dao/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ local type = type
local next = next
local log = ngx.log
local fmt = string.format
local match = string.match


local ERR = ngx.ERR
Expand Down Expand Up @@ -131,7 +132,7 @@ local function validate_options_value(options, schema, context)
context ~= "update" and
context ~= "upsert" then
errors.ttl = fmt("option can only be used with inserts, updates and upserts, not with '%ss'",
tostring(context))
context)

elseif floor(options.ttl) ~= options.ttl or
options.ttl < 0 or
Expand All @@ -145,6 +146,30 @@ local function validate_options_value(options, schema, context)
errors.ttl = fmt("cannot be used with '%s'", schema.name)
end

if schema.fields.tags and options.tags ~= nil then
if context ~= "select" then
errors.tags = fmt("option can only be used with selects and pages, not with '%ss'",
tostring(context))
elseif type(options.tags) ~= "table" then
if not options.tags_cond then
-- If options.tags is not a table and options.tags_cond is nil at the same time
-- it means arguments.lua gets an invalid tags arg from the Admin API
errors.tags = "invalid filter syntax"
else
errors.tags = "must be a table"
end
elseif #options.tags > 5 then
errors.tags = "cannot query more than 5 tags"
elseif not match(concat(options.tags), "^[%w%.%-%_~]+$") then
errors.tags = "must only contain alphanumeric and '., -, _, ~' characters"
elseif #options.tags > 1 and options.tags_cond ~= "and" and options.tags_cond ~= "or" then
errors.tags_cond = "must be a either 'and' or 'or' when more than one tag is specified"
end

elseif schema.fields.tags == nil and options.tags ~= nil then
errors.tags = fmt("cannot be used with '%s'", schema.name)
end

if next(errors) then
return nil, errors
end
Expand Down
27 changes: 27 additions & 0 deletions kong/db/dao/tags.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
local Tags = {}

function Tags:page_by_tag(tag, size, offset, options)
local ok, err = self.schema:validate_field(self.schema.fields.tag, tag)
if not ok then
local err_t = self.errors:invalid_unique('tag', err)
return nil, tostring(err_t), err_t
end

local rows, err_t, offset = self.strategy:page_by_tag(tag, size or 100, offset, options)
if err_t then
return rows, tostring(err_t), err_t
end
return rows, nil, nil, offset
end

local function noop(self, ...)
local err_t = self.errors:schema_violation({ tags = 'does not support insert/upsert/update/delete operations' })
return nil, tostring(err_t), err_t
end

Tags.insert = noop
Tags.delete = noop
Tags.update = noop
Tags.upsert = noop

return Tags
1 change: 1 addition & 0 deletions kong/db/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ local CORE_ENTITIES = {
"targets",
"plugins",
"cluster_ca",
"tags",
}


Expand Down
Loading

0 comments on commit abcfdf1

Please sign in to comment.