From 005fd494b54f0a19b2a0eed7c524f7681efbd5cb Mon Sep 17 00:00:00 2001 From: Prashansa Kulshrestha Date: Mon, 13 Jul 2026 15:09:01 +0530 Subject: [PATCH 1/3] test: added gw 3.15 in test matrix --- .github/workflows/integration-enterprise.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/integration-enterprise.yaml b/.github/workflows/integration-enterprise.yaml index 24b253c4a..a3e20551d 100644 --- a/.github/workflows/integration-enterprise.yaml +++ b/.github/workflows/integration-enterprise.yaml @@ -33,6 +33,7 @@ jobs: - 'kong/kong-gateway:3.12' - 'kong/kong-gateway:3.13' - 'kong/kong-gateway:3.14' + - 'kong/kong-gateway:3.15' - 'kong/kong-gateway-dev:latest' router_flavor: - 'traditional_compatible' From 3be465c86b55cbd6ced19e520fc98b27c3872dd8 Mon Sep 17 00:00:00 2001 From: Prashansa Kulshrestha Date: Mon, 3 Aug 2026 15:08:08 +0530 Subject: [PATCH 2/3] tests: separated plugin def files --- tests/integration/dump_test.go | 13 +++++++ .../plugin-definitions.yaml | 15 ++++++++ .../plugin-definitions.yaml | 37 +++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 tests/integration/testdata/sync/054-cloned-plugin-definitions/plugin-definitions.yaml create mode 100644 tests/integration/testdata/sync/055-custom-plugin-definitions/plugin-definitions.yaml diff --git a/tests/integration/dump_test.go b/tests/integration/dump_test.go index e1d3b0a31..974e30bca 100644 --- a/tests/integration/dump_test.go +++ b/tests/integration/dump_test.go @@ -1577,6 +1577,11 @@ func Test_Dump_ClonedPluginDefinitions(t *testing.T) { runWhen(t, tc.runWhen, tc.runWhenVersion) reset(t) + // Sync the plugin definitions first, in a separate run, so Kong + // has them registered before any plugin references them. + require.NoError(t, sync(ctx, + "testdata/sync/054-cloned-plugin-definitions/plugin-definitions.yaml", + "--include-plugin-definitions")) require.NoError(t, sync(ctx, "testdata/sync/054-cloned-plugin-definitions/kong.yaml", "--include-plugin-definitions")) @@ -1634,6 +1639,14 @@ func Test_Dump_CustomPluginDefinitions(t *testing.T) { runWhen(t, tc.runWhen, tc.runWhenVersion) reset(t) + // Sync the plugin definitions first, in a separate run, so Kong + // has them registered before any plugin references them. Doing + // this in a single sync is racy: a plugin may be created before + // its (custom) definition is ready, yielding an intermittent + // 404 "No plugin named ''". + require.NoError(t, sync(ctx, + "testdata/sync/055-custom-plugin-definitions/plugin-definitions.yaml", + "--include-plugin-definitions")) require.NoError(t, sync(ctx, "testdata/sync/055-custom-plugin-definitions/kong.yaml", "--include-plugin-definitions")) diff --git a/tests/integration/testdata/sync/054-cloned-plugin-definitions/plugin-definitions.yaml b/tests/integration/testdata/sync/054-cloned-plugin-definitions/plugin-definitions.yaml new file mode 100644 index 000000000..34edc020d --- /dev/null +++ b/tests/integration/testdata/sync/054-cloned-plugin-definitions/plugin-definitions.yaml @@ -0,0 +1,15 @@ +_format_version: "3.0" +cloned_plugins: +- name: new-file-log + ref: file-log + priority: 100 + tags: + - tag1 + - tag2 + - select-me +- name: new-acl + ref: acl + priority: 1000 + tags: + - tag1 + - tag2 diff --git a/tests/integration/testdata/sync/055-custom-plugin-definitions/plugin-definitions.yaml b/tests/integration/testdata/sync/055-custom-plugin-definitions/plugin-definitions.yaml new file mode 100644 index 000000000..f5f088612 --- /dev/null +++ b/tests/integration/testdata/sync/055-custom-plugin-definitions/plugin-definitions.yaml @@ -0,0 +1,37 @@ +_format_version: "3.0" +custom_plugins: +- name: set-header + handler: | + return { + VERSION = "1.0,0", + PRIORITY = 500, + access = function(self, config) + kong.service.request.set_header(config.name, config.value) + end + } + schema: | + return { + name = "set-header", + fields = { + { protocols = require("kong.db.schema.typedefs").protocols_http }, + { + config = { + type = "record", + fields = { + { name = { description = "The name of the header to set.", type = "string", required = true, }, }, + { value = { description = "The value for the header.", type = "string", required = true, }, }, + }, + }, + }, + }, + } + tags: + - tag1 + - tag2 + - select-me +- name: col-dbless + handler: 'return { PRIORITY = 1000, VERSION = "1.0.0" }' + schema: 'return { name = "col-dbless", fields = { { config = { type = "record", fields = {} } } } }' + tags: + - tag1 + - tag2 From 7da56af47f4fc50e8dd7c5ac49beb03588e0c0c3 Mon Sep 17 00:00:00 2001 From: Prashansa Kulshrestha Date: Mon, 3 Aug 2026 15:43:31 +0530 Subject: [PATCH 3/3] tests: added artificial delay between plugin defs sync and plugin sync --- tests/integration/apply_test.go | 51 ++++++++++++------- tests/integration/dump_test.go | 14 ++--- tests/integration/sync_test.go | 48 ++++++++++++----- tests/integration/test_utils.go | 5 ++ .../initial-with-plugins.yaml | 31 ----------- .../initial-with-plugins.yaml | 47 ----------------- .../plugin-definitions.yaml | 15 ------ .../plugin-definitions.yaml | 37 -------------- 8 files changed, 79 insertions(+), 169 deletions(-) delete mode 100644 tests/integration/testdata/apply/013-cloned-plugin-definitions/initial-with-plugins.yaml delete mode 100644 tests/integration/testdata/apply/014-custom-plugin-definitions/initial-with-plugins.yaml delete mode 100644 tests/integration/testdata/sync/054-cloned-plugin-definitions/plugin-definitions.yaml delete mode 100644 tests/integration/testdata/sync/055-custom-plugin-definitions/plugin-definitions.yaml diff --git a/tests/integration/apply_test.go b/tests/integration/apply_test.go index 3e12f4074..82d2c6f41 100644 --- a/tests/integration/apply_test.go +++ b/tests/integration/apply_test.go @@ -6,6 +6,7 @@ import ( "context" "os" "testing" + "time" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" @@ -823,11 +824,12 @@ func Test_Apply_ClonedPluginDefinitions(t *testing.T) { ctx := t.Context() tests := []struct { - name string - initialFile string - updateFile string - expectedState utils.KongRawState - ignoreFields []cmp.Option + name string + pluginDefsFile string + initialFile string + updateFile string + expectedState utils.KongRawState + ignoreFields []cmp.Option }{ { name: "updates cloned plugin definition priority and tags", @@ -851,9 +853,10 @@ func Test_Apply_ClonedPluginDefinitions(t *testing.T) { }, }, { - name: "updates plugin config linked with cloned definitions", - initialFile: "testdata/apply/013-cloned-plugin-definitions/initial-with-plugins.yaml", - updateFile: "testdata/apply/013-cloned-plugin-definitions/update-plugin-config.yaml", + name: "updates plugin config linked with cloned definitions", + pluginDefsFile: "testdata/apply/013-cloned-plugin-definitions/initial-cpd-only.yaml", + initialFile: "testdata/sync/054-cloned-plugin-definitions/kong.yaml", + updateFile: "testdata/apply/013-cloned-plugin-definitions/update-plugin-config.yaml", expectedState: utils.KongRawState{ ClonedPluginDefinitions: []*kong.ClonedPluginDefinition{ { @@ -903,6 +906,10 @@ func Test_Apply_ClonedPluginDefinitions(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { reset(t) + if tc.pluginDefsFile != "" { + require.NoError(t, sync(ctx, tc.pluginDefsFile, "--include-plugin-definitions")) + time.Sleep(pluginDefinitionSyncDelay) + } require.NoError(t, sync(ctx, tc.initialFile, "--include-plugin-definitions")) require.NoError(t, apply(ctx, tc.updateFile, "--include-plugin-definitions")) testKongState(t, client, false, false, tc.expectedState, tc.ignoreFields) @@ -956,7 +963,7 @@ func testApplyClonedPluginDefinitionsKonnectImpl(t *testing.T) { }, { name: "updates plugin config linked with cloned definitions", - initialFile: "testdata/apply/013-cloned-plugin-definitions/initial-with-plugins.yaml", + initialFile: "testdata/sync/054-cloned-plugin-definitions/kong.yaml", updateFile: "testdata/apply/013-cloned-plugin-definitions/update-plugin-config.yaml", expectedState: utils.KongRawState{ ClonedPluginDefinitions: []*kong.ClonedPluginDefinition{ @@ -1009,6 +1016,7 @@ func testApplyClonedPluginDefinitionsKonnectImpl(t *testing.T) { // includes plugin instances. cpdOnlyFile := "testdata/apply/013-cloned-plugin-definitions/initial-cpd-only.yaml" require.NoError(t, sync(ctx, cpdOnlyFile, "--include-plugin-definitions")) + time.Sleep(pluginDefinitionSyncDelay) require.NoError(t, sync(ctx, tc.initialFile, "--include-plugin-definitions")) require.NoError(t, apply(ctx, tc.updateFile, "--include-plugin-definitions")) @@ -1032,11 +1040,12 @@ func Test_Apply_CustomPluginDefinitions(t *testing.T) { colDblessSchema := mustReadFile(t, cpdTestdata+"/col-dbless.schema.lua") tests := []struct { - name string - initialFile string - updateFile string - expectedState utils.KongRawState - ignoreFields []cmp.Option + name string + pluginDefsFile string + initialFile string + updateFile string + expectedState utils.KongRawState + ignoreFields []cmp.Option }{ { name: "updates custom plugin definition tags", @@ -1060,9 +1069,10 @@ func Test_Apply_CustomPluginDefinitions(t *testing.T) { }, }, { - name: "updates plugin config linked with custom plugin definitions", - initialFile: "testdata/apply/014-custom-plugin-definitions/initial-with-plugins.yaml", - updateFile: "testdata/apply/014-custom-plugin-definitions/update-plugin-config.yaml", + name: "updates plugin config linked with custom plugin definitions", + pluginDefsFile: "testdata/apply/014-custom-plugin-definitions/initial-cpd-only.yaml", + initialFile: "testdata/sync/055-custom-plugin-definitions/kong.yaml", + updateFile: "testdata/apply/014-custom-plugin-definitions/update-plugin-config.yaml", expectedState: utils.KongRawState{ CustomPluginDefinitions: []*kong.CustomPluginDefinition{ { @@ -1099,6 +1109,10 @@ func Test_Apply_CustomPluginDefinitions(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { reset(t) + if tc.pluginDefsFile != "" { + require.NoError(t, sync(ctx, tc.pluginDefsFile, "--include-plugin-definitions")) + time.Sleep(pluginDefinitionSyncDelay) + } require.NoError(t, sync(ctx, tc.initialFile, "--include-plugin-definitions")) require.NoError(t, apply(ctx, tc.updateFile, "--include-plugin-definitions")) testKongState(t, client, false, false, tc.expectedState, tc.ignoreFields) @@ -1158,7 +1172,7 @@ func testApplyCustomPluginDefinitionsKonnectImpl(t *testing.T) { }, { name: "updates plugin config linked with custom plugin definitions", - initialFile: "testdata/apply/014-custom-plugin-definitions/initial-with-plugins.yaml", + initialFile: "testdata/sync/055-custom-plugin-definitions/kong.yaml", updateFile: "testdata/apply/014-custom-plugin-definitions/update-plugin-config.yaml", expectedState: utils.KongRawState{ CustomPluginDefinitions: []*kong.CustomPluginDefinition{ @@ -1202,6 +1216,7 @@ func testApplyCustomPluginDefinitionsKonnectImpl(t *testing.T) { // includes plugin instances. cpdOnlyFile := "testdata/apply/014-custom-plugin-definitions/initial-cpd-only.yaml" require.NoError(t, sync(ctx, cpdOnlyFile, "--include-plugin-definitions")) + time.Sleep(pluginDefinitionSyncDelay) require.NoError(t, sync(ctx, tc.initialFile, "--include-plugin-definitions")) require.NoError(t, apply(ctx, tc.updateFile, "--include-plugin-definitions")) testKongState(t, client, true, false, tc.expectedState, tc.ignoreFields) diff --git a/tests/integration/dump_test.go b/tests/integration/dump_test.go index 974e30bca..8db4bf165 100644 --- a/tests/integration/dump_test.go +++ b/tests/integration/dump_test.go @@ -8,6 +8,7 @@ import ( "os" "strings" "testing" + "time" "github.com/acarl005/stripansi" "github.com/kong/deck/sanitize" @@ -1580,8 +1581,9 @@ func Test_Dump_ClonedPluginDefinitions(t *testing.T) { // Sync the plugin definitions first, in a separate run, so Kong // has them registered before any plugin references them. require.NoError(t, sync(ctx, - "testdata/sync/054-cloned-plugin-definitions/plugin-definitions.yaml", + "testdata/apply/013-cloned-plugin-definitions/initial-cpd-only.yaml", "--include-plugin-definitions")) + time.Sleep(pluginDefinitionSyncDelay) require.NoError(t, sync(ctx, "testdata/sync/054-cloned-plugin-definitions/kong.yaml", "--include-plugin-definitions")) @@ -1639,14 +1641,12 @@ func Test_Dump_CustomPluginDefinitions(t *testing.T) { runWhen(t, tc.runWhen, tc.runWhenVersion) reset(t) - // Sync the plugin definitions first, in a separate run, so Kong - // has them registered before any plugin references them. Doing - // this in a single sync is racy: a plugin may be created before - // its (custom) definition is ready, yielding an intermittent - // 404 "No plugin named ''". + // Sync the custom plugin definitions on their own first and let + // Kong register them before syncing the plugins that reference require.NoError(t, sync(ctx, - "testdata/sync/055-custom-plugin-definitions/plugin-definitions.yaml", + "testdata/apply/014-custom-plugin-definitions/initial-cpd-only.yaml", "--include-plugin-definitions")) + time.Sleep(pluginDefinitionSyncDelay) require.NoError(t, sync(ctx, "testdata/sync/055-custom-plugin-definitions/kong.yaml", "--include-plugin-definitions")) diff --git a/tests/integration/sync_test.go b/tests/integration/sync_test.go index 29daf245c..8ce08cc71 100644 --- a/tests/integration/sync_test.go +++ b/tests/integration/sync_test.go @@ -12635,15 +12635,19 @@ func Test_Sync_ClonedPluginDefinitions(t *testing.T) { ctx := t.Context() tests := []struct { - name string - kongFile string - wantErr bool - expectedState utils.KongRawState - ignoreFields []cmp.Option + name string + pluginDefsFile string + kongFile string + wantErr bool + expectedState utils.KongRawState + ignoreFields []cmp.Option }{ { - name: "creates cloned plugin definitions and plugins", - kongFile: "testdata/sync/054-cloned-plugin-definitions/kong.yaml", + name: "creates cloned plugin definitions and plugins", + // Register the cloned plugin definitions on their own first so Kong + // has them ready before the plugins in kong.yaml reference them. + pluginDefsFile: "testdata/apply/013-cloned-plugin-definitions/initial-cpd-only.yaml", + kongFile: "testdata/sync/054-cloned-plugin-definitions/kong.yaml", expectedState: utils.KongRawState{ ClonedPluginDefinitions: []*kong.ClonedPluginDefinition{ { @@ -12699,6 +12703,11 @@ func Test_Sync_ClonedPluginDefinitions(t *testing.T) { t.Run(tc.name, func(t *testing.T) { reset(t) + if tc.pluginDefsFile != "" { + require.NoError(t, sync(ctx, tc.pluginDefsFile, "--include-plugin-definitions")) + time.Sleep(pluginDefinitionSyncDelay) + } + err := sync(ctx, tc.kongFile, "--include-plugin-definitions") if tc.wantErr { require.Error(t, err) @@ -12799,6 +12808,7 @@ func testSyncClonedPluginDefinitionsKonnectImpl(t *testing.T) { // config that includes plugin instances. cpdOnlyFile := "testdata/apply/013-cloned-plugin-definitions/initial-cpd-only.yaml" require.NoError(t, sync(ctx, cpdOnlyFile, "--include-plugin-definitions")) + time.Sleep(pluginDefinitionSyncDelay) err := sync(ctx, tc.kongFile, "--include-plugin-definitions") if tc.wantErr { @@ -12831,15 +12841,19 @@ func Test_Sync_CustomPluginDefinitions(t *testing.T) { colDblessSchema := mustReadFile(t, cpdTestdata+"/col-dbless.schema.lua") tests := []struct { - name string - kongFile string - wantErr bool - expectedState utils.KongRawState - ignoreFields []cmp.Option + name string + pluginDefsFile string + kongFile string + wantErr bool + expectedState utils.KongRawState + ignoreFields []cmp.Option }{ { - name: "creates custom plugin definitions and plugins", - kongFile: "testdata/sync/055-custom-plugin-definitions/kong.yaml", + name: "creates custom plugin definitions and plugins", + // Register the custom plugin definitions on their own first so Kong + // has them ready before the plugins in kong.yaml reference them. + pluginDefsFile: "testdata/apply/014-custom-plugin-definitions/initial-cpd-only.yaml", + kongFile: "testdata/sync/055-custom-plugin-definitions/kong.yaml", expectedState: utils.KongRawState{ CustomPluginDefinitions: []*kong.CustomPluginDefinition{ { @@ -12877,6 +12891,11 @@ func Test_Sync_CustomPluginDefinitions(t *testing.T) { t.Run(tc.name, func(t *testing.T) { reset(t) + if tc.pluginDefsFile != "" { + require.NoError(t, sync(ctx, tc.pluginDefsFile, "--include-plugin-definitions")) + time.Sleep(pluginDefinitionSyncDelay) + } + err := sync(ctx, tc.kongFile, "--include-plugin-definitions") if tc.wantErr { require.Error(t, err) @@ -12969,6 +12988,7 @@ func testSyncCustomPluginDefinitionsKonnectImpl(t *testing.T) { // config that includes plugin instances. cpdOnlyFile := "testdata/apply/014-custom-plugin-definitions/initial-cpd-only.yaml" require.NoError(t, sync(ctx, cpdOnlyFile, "--include-plugin-definitions")) + time.Sleep(pluginDefinitionSyncDelay) err := sync(ctx, tc.kongFile, "--include-plugin-definitions") if tc.wantErr { diff --git a/tests/integration/test_utils.go b/tests/integration/test_utils.go index cd5b9b313..46135eeab 100644 --- a/tests/integration/test_utils.go +++ b/tests/integration/test_utils.go @@ -7,6 +7,7 @@ import ( "io" "os" "testing" + "time" "github.com/acarl005/stripansi" "github.com/fatih/color" @@ -26,6 +27,10 @@ import ( // manages, mirroring the scope of `deck ai dump`. const managedByAIDeckTag = "managed_by:deck-ai" +// pluginDefinitionSyncDelay gives Kong time to register a freshly synced +// custom/cloned plugin definition before a plugin instance references it. +const pluginDefinitionSyncDelay = 3 * time.Second + func getKongAddress() string { address := os.Getenv("DECK_KONG_ADDR") if address != "" { diff --git a/tests/integration/testdata/apply/013-cloned-plugin-definitions/initial-with-plugins.yaml b/tests/integration/testdata/apply/013-cloned-plugin-definitions/initial-with-plugins.yaml deleted file mode 100644 index 8e81c7031..000000000 --- a/tests/integration/testdata/apply/013-cloned-plugin-definitions/initial-with-plugins.yaml +++ /dev/null @@ -1,31 +0,0 @@ -_format_version: "3.0" -cloned_plugins: -- name: new-file-log - ref: file-log - priority: 100 - tags: - - tag1 - - tag2 - - select-me -- name: new-acl - ref: acl - priority: 1000 - tags: - - tag1 - - tag2 -plugins: -- name: new-file-log - config: - path: /tmp/file.log - reopen: true - tags: - - plugin-tag1 - - select-me -- name: new-acl - config: - allow: - - example.com - hide_groups_header: true - enabled: true - tags: - - plugin-tag1 diff --git a/tests/integration/testdata/apply/014-custom-plugin-definitions/initial-with-plugins.yaml b/tests/integration/testdata/apply/014-custom-plugin-definitions/initial-with-plugins.yaml deleted file mode 100644 index 1299c4d03..000000000 --- a/tests/integration/testdata/apply/014-custom-plugin-definitions/initial-with-plugins.yaml +++ /dev/null @@ -1,47 +0,0 @@ -_format_version: "3.0" -custom_plugins: -- name: set-header - handler: | - return { - VERSION = "1.0,0", - PRIORITY = 500, - access = function(self, config) - kong.service.request.set_header(config.name, config.value) - end - } - schema: | - return { - name = "set-header", - fields = { - { protocols = require("kong.db.schema.typedefs").protocols_http }, - { - config = { - type = "record", - fields = { - { name = { description = "The name of the header to set.", type = "string", required = true, }, }, - { value = { description = "The value for the header.", type = "string", required = true, }, }, - }, - }, - }, - }, - } - tags: - - tag1 - - tag2 - - select-me -- name: col-dbless - handler: 'return { PRIORITY = 1000, VERSION = "1.0.0" }' - schema: 'return { name = "col-dbless", fields = { { config = { type = "record", fields = {} } } } }' - tags: - - tag1 - - tag2 - -plugins: -- name: set-header - config: - name: X-Custom-Header - value: hello-world - enabled: true - tags: - - plugin-tag1 - - select-me diff --git a/tests/integration/testdata/sync/054-cloned-plugin-definitions/plugin-definitions.yaml b/tests/integration/testdata/sync/054-cloned-plugin-definitions/plugin-definitions.yaml deleted file mode 100644 index 34edc020d..000000000 --- a/tests/integration/testdata/sync/054-cloned-plugin-definitions/plugin-definitions.yaml +++ /dev/null @@ -1,15 +0,0 @@ -_format_version: "3.0" -cloned_plugins: -- name: new-file-log - ref: file-log - priority: 100 - tags: - - tag1 - - tag2 - - select-me -- name: new-acl - ref: acl - priority: 1000 - tags: - - tag1 - - tag2 diff --git a/tests/integration/testdata/sync/055-custom-plugin-definitions/plugin-definitions.yaml b/tests/integration/testdata/sync/055-custom-plugin-definitions/plugin-definitions.yaml deleted file mode 100644 index f5f088612..000000000 --- a/tests/integration/testdata/sync/055-custom-plugin-definitions/plugin-definitions.yaml +++ /dev/null @@ -1,37 +0,0 @@ -_format_version: "3.0" -custom_plugins: -- name: set-header - handler: | - return { - VERSION = "1.0,0", - PRIORITY = 500, - access = function(self, config) - kong.service.request.set_header(config.name, config.value) - end - } - schema: | - return { - name = "set-header", - fields = { - { protocols = require("kong.db.schema.typedefs").protocols_http }, - { - config = { - type = "record", - fields = { - { name = { description = "The name of the header to set.", type = "string", required = true, }, }, - { value = { description = "The value for the header.", type = "string", required = true, }, }, - }, - }, - }, - }, - } - tags: - - tag1 - - tag2 - - select-me -- name: col-dbless - handler: 'return { PRIORITY = 1000, VERSION = "1.0.0" }' - schema: 'return { name = "col-dbless", fields = { { config = { type = "record", fields = {} } } } }' - tags: - - tag1 - - tag2