Skip to content

Commit

Permalink
feat(clustering): add compatible checkers for mixed mode routes (#12814)
Browse files Browse the repository at this point in the history
* add compat checker for mixed mode routes

* unit tests

* dont send mixed routes at all

* style lint

* try test but not work

* try tests

* test fixed

* more tests

* update tests

* test descriptions

* lazy setup/teardown
  • Loading branch information
chronolaw authored Apr 23, 2024
1 parent 983cc13 commit f6b64ec
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 1 deletion.
1 change: 1 addition & 0 deletions kong/clustering/compat/checkers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ local compatible_checkers = {
return has_update
end,
},

{ 3005000000, --[[ 3.5.0.0 ]]
function(config_table, dp_version, log_suffix)
local has_update
Expand Down
38 changes: 38 additions & 0 deletions kong/clustering/compat/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -402,4 +402,42 @@ function _M.update_compatible_payload(payload, dp_version, log_suffix)
end


-- If mixed config is detected and a 3.6 or lower DP is attached to the CP,
-- no config will be sent at all
function _M.check_mixed_route_entities(payload, dp_version, flavor)
if flavor ~= "expressions" then
return true
end

-- CP runs with 'expressions' flavor

local dp_version_num = version_num(dp_version)

if dp_version_num >= 3007000000 then -- [[ 3.7.0.0 ]]
return true
end

local routes = payload["config_table"].routes or {}
local routes_n = #routes
local count = 0 -- expression route count

for i = 1, routes_n do
local r = routes[i]

-- expression should be a string
if r.expression and r.expression ~= ngx.null then
count = count + 1
end
end

if count == routes_n or -- all are expression only routes
count == 0 -- all are traditional routes
then
return true
end

return false, dp_version .. " does not support mixed mode route"
end


return _M
10 changes: 10 additions & 0 deletions kong/clustering/control_plane.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ local sleep = ngx.sleep

local plugins_list_to_map = compat.plugins_list_to_map
local update_compatible_payload = compat.update_compatible_payload
local check_mixed_route_entities = compat.check_mixed_route_entities
local deflate_gzip = require("kong.tools.gzip").deflate_gzip
local yield = require("kong.tools.yield").yield
local connect_dp = clustering_utils.connect_dp
Expand Down Expand Up @@ -432,6 +433,15 @@ function _M:handle_cp_websocket(cert)
goto continue
end

ok, err = check_mixed_route_entities(self.reconfigure_payload, dp_version,
kong and kong.configuration and
kong.configuration.router_flavor)
if not ok then
ngx_log(ngx_WARN, _log_prefix, "unable to send updated configuration to data plane: ", err, log_suffix)

goto continue
end

local _, deflated_payload, err = update_compatible_payload(self.reconfigure_payload, dp_version, log_suffix)

if not deflated_payload then -- no modification or err, use the cached payload
Expand Down
118 changes: 117 additions & 1 deletion spec/01-unit/19-hybrid/03-compat_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -630,5 +630,121 @@ describe("kong.clustering.compat", function()
assert.is_nil(assert(services[3]).ca_certificates)
end)

end)
end) -- describe

describe("route entities compatible changes", function()
local function reload_modules(flavor)
_G.kong = { configuration = { router_flavor = flavor } }
_G.kong.db = nil

package.loaded["kong.db.schema.entities.routes"] = nil
package.loaded["kong.db.schema.entities.routes_subschemas"] = nil
package.loaded["spec.helpers"] = nil
package.loaded["kong.clustering.compat"] = nil
package.loaded["kong.db.declarative"] = nil

require("kong.db.schema.entities.routes")
require("kong.db.schema.entities.routes_subschemas")

compat = require("kong.clustering.compat")
helpers = require ("spec.helpers")
declarative = require("kong.db.declarative")
end

lazy_setup(function()
reload_modules("expressions")
end)

lazy_teardown(function()
reload_modules()
end)

it("won't update with mixed mode routes in expressions flavor lower than 3.7", function()
local _, db = helpers.get_db_utils(nil, {
"routes",
})
_G.kong.db = db

-- mixed mode routes
assert(declarative.load_into_db({
routes = {
route1 = {
protocols = { "http" },
id = "00000000-0000-0000-0000-000000000001",
hosts = { "example.com" },
expression = ngx.null,
},
route2 = {
protocols = { "http" },
id = "00000000-0000-0000-0000-000000000002",
expression = [[http.path == "/foo"]],
},
},
}, { _transform = true }))

local config = { config_table = declarative.export_config() }

local ok, err = compat.check_mixed_route_entities(config, "3.6.0", "expressions")
assert.is_false(ok)
assert(string.find(err, "does not support mixed mode route"))

local ok, err = compat.check_mixed_route_entities(config, "3.7.0", "expressions")
assert.is_true(ok)
assert.is_nil(err)
end)

it("updates with all traditional routes in expressions flavor", function()
local _, db = helpers.get_db_utils(nil, {
"routes",
})
_G.kong.db = db

assert(declarative.load_into_db({
routes = {
route1 = {
protocols = { "http" },
id = "00000000-0000-0000-0000-000000000001",
hosts = { "example.com" },
expression = ngx.null,
},
},
}, { _transform = true }))

local config = { config_table = declarative.export_config() }

local ok, err = compat.check_mixed_route_entities(config, "3.6.0", "expressions")
assert.is_true(ok)
assert.is_nil(err)
end)

it("updates with all expression routes in expressions flavor", function()
local _, db = helpers.get_db_utils(nil, {
"routes",
})
_G.kong.db = db

assert(declarative.load_into_db({
routes = {
route1 = {
protocols = { "http" },
id = "00000000-0000-0000-0000-000000000001",
expression = [[http.path == "/foo"]],
},
route2 = {
protocols = { "http" },
id = "00000000-0000-0000-0000-000000000002",
expression = [[http.path == "/bar"]],
},
},
}, { _transform = true }))

local config = { config_table = declarative.export_config() }

local ok, err = compat.check_mixed_route_entities(config, "3.6.0", "expressions")
assert.is_true(ok)
assert.is_nil(err)
end)

end) -- describe

end)

1 comment on commit f6b64ec

@github-actions
Copy link
Contributor

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:f6b64ecb2aadbb9957830b34ba8fdb99038e3e9e
Artifacts available https://github.com/Kong/kong/actions/runs/8797500081

Please sign in to comment.