From 5b420ededadfb5efe0bebdf2333b7b8bbd957156 Mon Sep 17 00:00:00 2001 From: Michael Martin Date: Fri, 3 Nov 2023 17:25:06 -0700 Subject: [PATCH] fix(clustering): ensure data plane config hash is never nil The previous logic defaulted the config_hash to nil when it was detected to be an empty string. This can cause update_sync_status() to fail, because config_hash is a required attribute: > 2023/11/03 17:13:30 [debug] 4052224#0: *150 [lua] connector.lua:560: execute(): SQL query throw error: ERROR: null value in column "config_hash" of relation "clustering_data_planes" violates not-null constraint > Failing row contains (4fb29006-8db1-48bb-b68c-34b582e1d91a, soup, 127.0.0.1, 2023-11-04 00:13:30+00, null, 2023-11-18 00:13:30.799+00, 3.6.0, filter_set_incompatible, 2023-11-04 00:13:30+00, {})., close connection > 2023/11/03 17:13:30 [notice] 4052224#0: *150 [lua] init.lua:275: upsert(): ERROR: null value in column "config_hash" of relation "clustering_data_planes" violates not-null constraint This change addresses the problem from two angles: 1. when empty, config_hash is set to the default DECLARATIVE_EMPTY_CONFIG_HASH constant instead of nil 2. an additional guard was added to the dp reader thread, which checks the length of ping frame data and returns an error if it is not a proper config hash --- .../kong/clustering-empty-data-plane-hash-fix.yml | 3 +++ kong/clustering/control_plane.lua | 8 +++++++- kong/clustering/data_plane.lua | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 changelog/unreleased/kong/clustering-empty-data-plane-hash-fix.yml diff --git a/changelog/unreleased/kong/clustering-empty-data-plane-hash-fix.yml b/changelog/unreleased/kong/clustering-empty-data-plane-hash-fix.yml new file mode 100644 index 00000000000..1c405ecd53f --- /dev/null +++ b/changelog/unreleased/kong/clustering-empty-data-plane-hash-fix.yml @@ -0,0 +1,3 @@ +message: Fix a bug causing data-plane status updates to fail when an empty PING frame is received from a data-plane +type: bugfix +scope: Clustering diff --git a/kong/clustering/control_plane.lua b/kong/clustering/control_plane.lua index 6939d7a78a5..7efa3d40d25 100644 --- a/kong/clustering/control_plane.lua +++ b/kong/clustering/control_plane.lua @@ -234,7 +234,9 @@ function _M:handle_cp_websocket() local ok ok, err = kong.db.clustering_data_planes:upsert({ id = dp_id, }, { last_seen = last_seen, - config_hash = config_hash ~= "" and config_hash or nil, + config_hash = config_hash ~= "" + and config_hash + or DECLARATIVE_EMPTY_CONFIG_HASH, hostname = dp_hostname, ip = dp_ip, version = dp_version, @@ -341,6 +343,10 @@ function _M:handle_cp_websocket() if not data then return nil, "did not receive ping frame from data plane" + + elseif #data ~= 32 then + return nil, "received a ping frame from the data plane with an invalid" + .. " hash: '" .. tostring(data) .. "'" end -- dps only send pings diff --git a/kong/clustering/data_plane.lua b/kong/clustering/data_plane.lua index 4030b3174b0..f82dda86bfc 100644 --- a/kong/clustering/data_plane.lua +++ b/kong/clustering/data_plane.lua @@ -91,7 +91,7 @@ local function send_ping(c, log_suffix) local hash = declarative.get_current_hash() - if hash == true then + if hash == "" or type(hash) ~= "string" then hash = DECLARATIVE_EMPTY_CONFIG_HASH end