From 3c360b84a147314fcfbca1dc86afe381396da925 Mon Sep 17 00:00:00 2001 From: Gabriele Date: Sat, 13 Jan 2024 00:21:59 +0100 Subject: [PATCH] fix: handle consumer group plugin association (#33) * fix: check for consumer group associations when checking if plugins are bound to a single entity or multiple entities of different types. * ci: add 3.4 and 3.5 to test matrix --- .github/workflows/integration-enterprise.yaml | 2 + .github/workflows/integration.yaml | 2 + pkg/file/writer.go | 7 +- tests/integration/sync_test.go | 117 +++++++++++++++++- .../029-plugin-scoped-to-cg-route/kong.yaml | 77 ++++++++++++ 5 files changed, 199 insertions(+), 6 deletions(-) create mode 100644 tests/integration/testdata/sync/029-plugin-scoped-to-cg-route/kong.yaml diff --git a/.github/workflows/integration-enterprise.yaml b/.github/workflows/integration-enterprise.yaml index f17252f..c874a2d 100644 --- a/.github/workflows/integration-enterprise.yaml +++ b/.github/workflows/integration-enterprise.yaml @@ -21,6 +21,8 @@ jobs: - 'kong/kong-gateway:3.1' - 'kong/kong-gateway:3.2' - 'kong/kong-gateway:3.3' + - 'kong/kong-gateway:3.4' + - 'kong/kong-gateway:3.5' - 'kong/kong-gateway-dev:latest' env: KONG_ANONYMOUS_REPORTS: "off" diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml index 561c40a..7be4cda 100644 --- a/.github/workflows/integration.yaml +++ b/.github/workflows/integration.yaml @@ -23,6 +23,8 @@ jobs: - 'kong:3.1' - 'kong:3.2' - 'kong:3.3' + - 'kong:3.4' + - 'kong:3.5' - 'kong/kong:master-alpine' env: KONG_ANONYMOUS_REPORTS: "off" diff --git a/pkg/file/writer.go b/pkg/file/writer.go index e60d64c..2fd66da 100644 --- a/pkg/file/writer.go +++ b/pkg/file/writer.go @@ -294,7 +294,7 @@ func fetchService(id string, kongState *state.KongState, config WriteConfig) (*F } for _, p := range plugins { p := p - if p.Route != nil || p.Consumer != nil { + if p.Route != nil || p.Consumer != nil || p.ConsumerGroup != nil { continue } p.Service = nil @@ -364,7 +364,7 @@ func populateServicelessRoutes(kongState *state.KongState, file *Content, route := &FRoute{Route: r.Route} for _, p := range plugins { p := p - if p.Service != nil || p.Consumer != nil { + if p.Service != nil || p.Consumer != nil || p.ConsumerGroup != nil { continue } p.Route = nil @@ -764,6 +764,9 @@ func populateConsumerGroups(kongState *state.KongState, file *Content, return err } for _, plugin := range plugins { + if plugin.Service != nil || plugin.Consumer != nil || plugin.Route != nil { + continue + } if plugin.ID != nil && cg.ID != nil { if plugin.ConsumerGroup != nil && *plugin.ConsumerGroup.ID == *cg.ID { utils.ZeroOutID(plugin, plugin.Name, config.WithID) diff --git a/tests/integration/sync_test.go b/tests/integration/sync_test.go index 3d2a47b..e007ebd 100644 --- a/tests/integration/sync_test.go +++ b/tests/integration/sync_test.go @@ -781,7 +781,7 @@ var ( "database": float64(0), "host": nil, "keepalive_backlog": nil, - "keepalive_pool_size": float64(256), + "keepalive_pool_size": float64(30), "password": nil, "port": nil, "read_timeout": nil, @@ -830,7 +830,7 @@ var ( "database": float64(0), "host": nil, "keepalive_backlog": nil, - "keepalive_pool_size": float64(256), + "keepalive_pool_size": float64(30), "password": nil, "port": nil, "read_timeout": nil, @@ -876,7 +876,7 @@ var ( "database": float64(0), "host": nil, "keepalive_backlog": nil, - "keepalive_pool_size": float64(256), + "keepalive_pool_size": float64(30), "password": nil, "port": nil, "read_timeout": nil, @@ -4483,7 +4483,7 @@ func Test_Sync_ConsumerGroupsScopedPluginsKonnect(t *testing.T) { }, }, }, - Plugins: consumerGroupScopedPlugins, + Plugins: consumerGroupScopedPlugins35x, Services: svc1_207, Routes: route1_20x, KeyAuths: []*kong.KeyAuth{ @@ -4787,3 +4787,112 @@ func Test_Sync_ConsumerGroupConsumersWithCustomID(t *testing.T) { require.NoError(t, sync("testdata/sync/028-consumer-group-consumers-custom_id/kong.yaml")) testKongState(t, client, false, expectedState, nil) } + +// test scope: +// - 3.5.0+ +// - konnect +func Test_Sync_PluginScopedToConsumerGroupAndRoute(t *testing.T) { + t.Setenv("DECK_KONNECT_CONTROL_PLANE_NAME", "default") + runWhenEnterpriseOrKonnect(t, ">=3.5.0") + setup(t) + + client, err := getTestClient() + if err != nil { + t.Fatalf(err.Error()) + } + + expectedState := utils.KongRawState{ + ConsumerGroups: []*kong.ConsumerGroupObject{ + { + ConsumerGroup: &kong.ConsumerGroup{ + ID: kong.String("48df7cd3-1cd0-4e53-af73-8f57f257be18"), + Name: kong.String("cg1"), + }, + Consumers: []*kong.Consumer{ + { + ID: kong.String("bcb296c3-22bb-46f6-99c8-4828af750b77"), + Username: kong.String("foo"), + }, + }, + }, + }, + Consumers: []*kong.Consumer{ + { + ID: kong.String("bcb296c3-22bb-46f6-99c8-4828af750b77"), + Username: kong.String("foo"), + }, + }, + Routes: []*kong.Route{ + { + Name: kong.String("r1"), + ID: kong.String("a9730e9e-df7e-4042-8bc7-e8b99af70171"), + Hosts: kong.StringSlice("10.*"), + PathHandling: kong.String("v0"), + PreserveHost: kong.Bool(false), + Protocols: []*string{kong.String("http"), kong.String("https")}, + RegexPriority: kong.Int(0), + StripPath: kong.Bool(true), + HTTPSRedirectStatusCode: kong.Int(426), + RequestBuffering: kong.Bool(true), + ResponseBuffering: kong.Bool(true), + }, + }, + Plugins: []*kong.Plugin{ + { + ID: kong.String("a0b4c8d9-0f1e-4e1f-9e3a-5c8e1c8b9f1a"), + Name: kong.String("rate-limiting-advanced"), + ConsumerGroup: &kong.ConsumerGroup{ + ID: kong.String("48df7cd3-1cd0-4e53-af73-8f57f257be18"), + }, + Route: &kong.Route{ + ID: kong.String("a9730e9e-df7e-4042-8bc7-e8b99af70171"), + }, + Config: kong.Configuration{ + "consumer_groups": nil, + "dictionary_name": string("kong_rate_limiting_counters"), + "disable_penalty": bool(false), + "enforce_consumer_groups": bool(false), + "error_code": float64(429), + "error_message": string("API rate limit exceeded"), + "header_name": nil, + "hide_client_headers": bool(false), + "identifier": string("consumer"), + "limit": []any{float64(1)}, + "namespace": string("dmHiQjaGTIYimSXQmRoUDA1XkJXZqxZf"), + "path": nil, + "redis": map[string]any{ + "cluster_addresses": nil, + "connect_timeout": nil, + "database": float64(0), + "host": nil, + "keepalive_backlog": nil, + "keepalive_pool_size": float64(256), + "password": nil, + "port": nil, + "read_timeout": nil, + "send_timeout": nil, + "sentinel_addresses": nil, + "sentinel_master": nil, + "sentinel_password": nil, + "sentinel_role": nil, + "sentinel_username": nil, + "server_name": nil, + "ssl": false, + "ssl_verify": false, + "timeout": float64(2000), + "username": nil, + }, + "retry_after_jitter_max": float64(0), + "strategy": string("local"), + "sync_rate": float64(-1), + "window_size": []any{float64(60)}, + "window_type": string("sliding"), + }, + Enabled: kong.Bool(true), + Protocols: []*string{kong.String("grpc"), kong.String("grpcs"), kong.String("http"), kong.String("https")}, + }, + }, + } + require.NoError(t, sync("testdata/sync/029-plugin-scoped-to-cg-route/kong.yaml")) + testKongState(t, client, false, expectedState, nil) +} diff --git a/tests/integration/testdata/sync/029-plugin-scoped-to-cg-route/kong.yaml b/tests/integration/testdata/sync/029-plugin-scoped-to-cg-route/kong.yaml new file mode 100644 index 0000000..6dcb5ad --- /dev/null +++ b/tests/integration/testdata/sync/029-plugin-scoped-to-cg-route/kong.yaml @@ -0,0 +1,77 @@ +_format_version: "3.0" +consumer_groups: +- id: 48df7cd3-1cd0-4e53-af73-8f57f257be18 + name: cg1 +consumers: +- groups: + - id: 48df7cd3-1cd0-4e53-af73-8f57f257be18 + name: cg1 + id: bcb296c3-22bb-46f6-99c8-4828af750b77 + username: foo +plugins: +- config: + consumer_groups: null + dictionary_name: kong_rate_limiting_counters + disable_penalty: false + enforce_consumer_groups: false + error_code: 429 + error_message: API rate limit exceeded + header_name: null + hide_client_headers: false + identifier: consumer + limit: + - 1 + namespace: dmHiQjaGTIYimSXQmRoUDA1XkJXZqxZf + path: null + redis: + cluster_addresses: null + connect_timeout: null + database: 0 + host: null + keepalive_backlog: null + keepalive_pool_size: 256 + password: null + port: null + read_timeout: null + send_timeout: null + sentinel_addresses: null + sentinel_master: null + sentinel_password: null + sentinel_role: null + sentinel_username: null + server_name: null + ssl: false + ssl_verify: false + timeout: 2000 + username: null + retry_after_jitter_max: 0 + strategy: local + sync_rate: -1 + window_size: + - 60 + window_type: sliding + consumer_group: cg1 + enabled: true + id: f213aa37-6b89-4e5e-bb3f-3ebae9ba5b11 + name: rate-limiting-advanced + protocols: + - grpc + - grpcs + - http + - https + route: r1 +routes: +- hosts: + - 10.* + https_redirect_status_code: 426 + id: a9730e9e-df7e-4042-8bc7-e8b99af70171 + name: r1 + path_handling: v0 + preserve_host: false + protocols: + - http + - https + regex_priority: 0 + request_buffering: true + response_buffering: true + strip_path: true