Skip to content

Commit

Permalink
feat(db-labels): add labels
Browse files Browse the repository at this point in the history
  • Loading branch information
samugi committed Mar 14, 2023
1 parent dfd41ce commit 41c2ab5
Show file tree
Hide file tree
Showing 12 changed files with 135 additions and 3 deletions.
2 changes: 2 additions & 0 deletions kong-3.2.1-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ build = {
["kong.clustering.compat.removed_fields"] = "kong/clustering/compat/removed_fields.lua",
["kong.clustering.config_helper"] = "kong/clustering/config_helper.lua",
["kong.clustering.tls"] = "kong/clustering/tls.lua",
["kong.clustering.labels"] = "kong/clustering/labels.lua",

["kong.cluster_events"] = "kong/cluster_events/init.lua",
["kong.cluster_events.strategies.cassandra"] = "kong/cluster_events/strategies/cassandra.lua",
Expand Down Expand Up @@ -247,6 +248,7 @@ build = {
["kong.db.migrations.core.016_280_to_300"] = "kong/db/migrations/core/016_280_to_300.lua",
["kong.db.migrations.core.017_300_to_310"] = "kong/db/migrations/core/017_300_to_310.lua",
["kong.db.migrations.core.018_310_to_320"] = "kong/db/migrations/core/018_310_to_320.lua",
["kong.db.migrations.core.019_320_to_330"] = "kong/db/migrations/core/019_320_to_330.lua",
["kong.db.migrations.operations.200_to_210"] = "kong/db/migrations/operations/200_to_210.lua",
["kong.db.migrations.operations.210_to_211"] = "kong/db/migrations/operations/210_to_211.lua",
["kong.db.migrations.operations.212_to_213"] = "kong/db/migrations/operations/212_to_213.lua",
Expand Down
7 changes: 7 additions & 0 deletions kong.conf.default
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,13 @@
# to be sent across from CP to DP in Hybrid mode
# Default is 4Mb - 4 * 1024 * 1024 due to historical reasons

#cluster_dp_labels = # Labels for the data plane. These key-value entries are
# exposed via the clustering/data_planes endpoint.
# The value must be configured as a string in JSON format.
#
# Example:
# `{ "deployment" : "aws", "region" : "us-east-1" }`

#------------------------------------------------------------------------------
# HYBRID MODE CONTROL PLANE
#------------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions kong/clustering/control_plane.lua
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ function _M:handle_cp_websocket()
ip = dp_ip,
version = dp_version,
sync_status = sync_status, -- TODO: import may have been failed though
labels = data.labels or {}
}, { ttl = purge_delay })
if not ok then
ngx_log(ngx_ERR, _log_prefix, "unable to update clustering data plane status: ", err, log_suffix)
Expand Down
16 changes: 13 additions & 3 deletions kong/clustering/data_plane.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ local declarative = require("kong.db.declarative")
local constants = require("kong.constants")
local utils = require("kong.tools.utils")
local pl_stringx = require("pl.stringx")
local dp_labels = require("kong.clustering.labels")


local assert = assert
Expand Down Expand Up @@ -124,12 +125,21 @@ function _M:communicate(premature)
return
end

-- load dp labels
local labels, load_err = dp_labels.load_labels()
ngx.log(ngx.ERR, "LABELS LOADED AS "..require('inspect')(labels))
if load_err then
ngx_log(ngx_ERR, _log_prefix, load_err)
end

-- connection established
-- first, send out the plugin list to CP so it can make decision on whether
-- sync will be allowed later
-- first, send out the plugin list and DP labels to CP
-- The CP will make the decision on whether sync will be allowed
-- based no the received information
local _
_, err = c:send_binary(cjson_encode({ type = "basic_info",
plugins = self.plugins_list, }))
plugins = self.plugins_list,
labels = labels }))
if err then
ngx_log(ngx_ERR, _log_prefix, "unable to send basic information to control plane: ", uri,
" err: ", err, " (retrying after ", reconnection_delay, " seconds)", log_suffix)
Expand Down
62 changes: 62 additions & 0 deletions kong/clustering/labels.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
local cjson = require "cjson.safe"
local pl_tablex = require "pl.tablex"

local fmt = string.format
local re_match = ngx.re.match

local MAX_KEY_SIZE = 63
local MAX_VALUE_SIZE = MAX_KEY_SIZE
local MAX_KEYS = 10

local BASE_PTRN = "[a-z0-9]([\\w\\.:-]*[a-z0-9]|)$"
local KEY_PTRN = "(?!kong)(?!konnect)(?!insomnia)(?!mesh)(?!kic)" .. BASE_PTRN
local VAL_PTRN = BASE_PTRN


local function validate_table(labels_t)
return pl_tablex.size(labels_t) <= MAX_KEYS
end


local function validate_pattern(str, max_size, pattern)
if str == "" or #str > max_size then
return false, fmt(
"%s must have between 1 and %d characters", str, max_size)
end
if not re_match(str, pattern, "ajoi") then
return false, fmt("%s not conforming with pattern %s", str, pattern)
end
return true
end


local function load_labels()
local labels, err = cjson.decode(kong.configuration.cluster_dp_labels or "{}")
if not labels then
return nil, err
end

local ok
ok, err = validate_table(labels)
if not ok then
return nil, "labels validation failed: " .. err
end

for k, v in pairs(labels) do
ok, err = validate_pattern(k, MAX_KEY_SIZE, KEY_PTRN)
if not ok then
return nil, "label name validation failed: " .. err
end
ok, err = validate_pattern(v, MAX_VALUE_SIZE, VAL_PTRN)
if not ok then
return nil, "label value validation failed: " .. err
end
end

return labels
end


return {
load_labels = load_labels
}
1 change: 1 addition & 0 deletions kong/conf_loader/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ local CONF_PARSERS = {
cluster_ocsp = { enum = { "on", "off", "optional" } },
cluster_max_payload = { typ = "number" },
cluster_use_proxy = { typ = "boolean" },
cluster_dp_labels = { typ = "string" },

kic = { typ = "boolean" },
pluginserver_names = { typ = "array" },
Expand Down
19 changes: 19 additions & 0 deletions kong/db/migrations/core/019_320_to_330.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
return {
postgres = {
up = [[
DO $$
BEGIN
ALTER TABLE IF EXISTS ONLY "clustering_data_planes" ADD "labels" JSONB;
EXCEPTION WHEN DUPLICATE_COLUMN THEN
-- Do nothing, accept existing state
END;
$$;
]]
},

cassandra = {
up = [[
ALTER TABLE clustering_data_planes ADD labels map<text,text>;
]]
},
}
1 change: 1 addition & 0 deletions kong/db/migrations/core/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ return {
"016_280_to_300",
"017_300_to_310",
"018_310_to_320",
"019_320_to_330",
}
1 change: 1 addition & 0 deletions kong/db/schema/entities/clustering_data_planes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ return {
default = "unknown",
}
},
{ labels = typedefs.labels },
},
}
20 changes: 20 additions & 0 deletions kong/db/schema/typedefs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -828,4 +828,24 @@ typedefs.ttl = Schema.define {
between = { 0, DAO_MAX_TTL },
}


local function validate_labels(field)
local pattern = (field == "k" and "(?!kong)(?!konnect)(?!insomnia)(?!mesh)(?!kic)" or "") ..
"[a-z0-9]([\\w\\.:-]*[a-z0-9]|)$"

return function(expr)
if not ngx.re.match(expr, pattern, "ajoi") then
return false, string.format("field %s does not match allowed pattern %s", expr, pattern)
end
return true
end
end

typedefs.labels = Schema.define {
type = "map",
keys = { type = "string", len_min = 1, len_max = 63, custom_validator = validate_labels("k") },
values = { type = "string", len_min = 1, len_max = 63, custom_validator = validate_labels("v") },
len_max = 10,
}

return typedefs
1 change: 1 addition & 0 deletions kong/templates/kong_defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ cluster_data_plane_purge_delay = 1209600
cluster_ocsp = off
cluster_max_payload = 4194304
cluster_use_proxy = off
cluster_dp_labels = NONE
lmdb_environment_path = dbless.lmdb
lmdb_map_size = 128m
Expand Down
7 changes: 7 additions & 0 deletions spec/05-migration/db/migrations/core/019_320_to_330_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
local uh = require "spec/upgrade_helpers"

describe("database migration", function()
uh.old_after_up("has created the expected new columns", function()
assert.table_has_column("clustering_data_planes", "labels", "jsonb", "map<text,text>")
end)
end)

0 comments on commit 41c2ab5

Please sign in to comment.