From 6125315fa4e7b57ee4a3b902668910ea2b472d80 Mon Sep 17 00:00:00 2001 From: Antoine Jacquemin Date: Thu, 28 Nov 2024 15:38:59 +0100 Subject: [PATCH 1/6] add feature online plugins filter flag --- cmd/gateway_validate.go | 4 ++++ tests/integration/validate_test.go | 5 +++++ validate/validate.go | 14 +++++++++++--- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/cmd/gateway_validate.go b/cmd/gateway_validate.go index 0d2ee3690..37fe97e2d 100644 --- a/cmd/gateway_validate.go +++ b/cmd/gateway_validate.go @@ -19,6 +19,7 @@ import ( var ( validateCmdKongStateFile []string validateCmdRBACResourcesOnly bool + validateCmdCheckOnlinePluginsOnly bool validateOnline bool validateWorkspace string validateParallelism int @@ -237,6 +238,8 @@ this command unless --online flag is used. validateCmd.Flags().BoolVar(&validateCmdRBACResourcesOnly, "rbac-resources-only", false, "indicate that the state file(s) contains RBAC resources only (Kong Enterprise only).") + validateCmd.Flags().BoolVar(&validateCmdCheckOnlinePluginsOnly, "check-online-plugins-only", + false, "indicate that the online validation will be done only on plugins.") if deprecated { validateCmd.Flags().StringSliceVarP(&validateCmdKongStateFile, "state", "s", []string{"kong.yaml"}, "file(s) containing Kong's configuration.\n"+ @@ -284,6 +287,7 @@ func validateWithKong( Client: kongClient, Parallelism: validateParallelism, RBACResourcesOnly: validateCmdRBACResourcesOnly, + CheckOnlinePluginsOnly: validateCmdCheckOnlinePluginsOnly, } validator := validate.NewValidator(opts) return validator.Validate(parsedFormatVersion) diff --git a/tests/integration/validate_test.go b/tests/integration/validate_test.go index 410bce2ef..6b2468137 100644 --- a/tests/integration/validate_test.go +++ b/tests/integration/validate_test.go @@ -133,6 +133,11 @@ func Test_Validate_File(t *testing.T) { stateFile: "testdata/validate/rbac-resources.yaml", additionalArgs: []string{"--rbac-resources-only"}, }, + { + name: "file validate with --check-online-plugins-only", + stateFile: "testdata/validate/kong3x.yaml", + additionalArgs: []string{"--check-online-plugins-only"}, + }, } for _, tc := range tests { diff --git a/validate/validate.go b/validate/validate.go index 256b33718..baeb572a6 100644 --- a/validate/validate.go +++ b/validate/validate.go @@ -21,6 +21,7 @@ type Validator struct { client *kong.Client parallelism int rbacResourcesOnly bool + CheckOnlinePluginsOnly bool } type ValidatorOpts struct { @@ -29,6 +30,7 @@ type ValidatorOpts struct { Client *kong.Client Parallelism int RBACResourcesOnly bool + CheckOnlinePluginsOnly bool } func NewValidator(opt ValidatorOpts) *Validator { @@ -38,6 +40,7 @@ func NewValidator(opt ValidatorOpts) *Validator { client: opt.Client, parallelism: opt.Parallelism, rbacResourcesOnly: opt.RBACResourcesOnly, + CheckOnlinePluginsOnly: opt.CheckOnlinePluginsOnly, } } @@ -130,6 +133,14 @@ func (v *Validator) Validate(formatVersion semver.Version) []error { return allErr } + // validate Plugins resources then. + if err := v.entities(v.state.Plugins, "plugins"); err != nil { + allErr = append(allErr, err...) + } + if v.CheckOnlinePluginsOnly { + return allErr + } + if err := v.entities(v.state.Services, "services"); err != nil { allErr = append(allErr, err...) } @@ -163,9 +174,6 @@ func (v *Validator) Validate(formatVersion semver.Version) []error { if err := v.entities(v.state.Oauth2Creds, "oauth2_credentials"); err != nil { allErr = append(allErr, err...) } - if err := v.entities(v.state.Plugins, "plugins"); err != nil { - allErr = append(allErr, err...) - } if err := v.entities(v.state.Routes, "routes"); err != nil { allErr = append(allErr, err...) } From 6fe17eede9164794c21bb1ba296b461a0f678d9c Mon Sep 17 00:00:00 2001 From: Antoine Jacquemin Date: Thu, 28 Nov 2024 20:09:37 +0100 Subject: [PATCH 2/6] list refactor fix reflection add test fix lint fix lint add valid entities fux lint Updated go-apiops (#1452) * chore: updated go-apiops to v0.1.40 * chore: release prep for v1.41.4 fux lint fix lint fix lint --- CHANGELOG.md | 17 ++ README.md | 4 +- cmd/gateway_validate.go | 51 ++++-- go.mod | 8 +- go.sum | 19 ++- tests/integration/sync_test.go | 3 + .../expected-no-skip_konnect.yaml | 1 + tests/integration/validate_test.go | 20 ++- validate/validate.go | 159 +++++++++--------- 9 files changed, 169 insertions(+), 113 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 341b793e1..e03bc6636 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Table of Contents +- [v1.41.4](#v1414) - [v1.41.3](#v1413) - [v1.41.2](#v1412) - [v1.41.1](#v1411) @@ -100,6 +101,21 @@ - [v0.2.0](#v020) - [v0.1.0](#v010) +## [v1.41.4] +> Release date: 2024/11/26 + +### Fixes +- Added validation for ensuring that cookie parameters in parameter schemas are skipped +and a warning is logged for the user while using `deck file openapi2kong` command. +[#1452](https://github.com/Kong/deck/pull/1452) +[go-apiops #255](https://github.com/Kong/go-apiops/pull/225) +- Fixed issue where creating arrays with mixed types using oneOf in OAS specifications were +failing while using `deck file openapi2kong` command. +[#1452](https://github.com/Kong/deck/pull/1452) +[go-apiops #231](https://github.com/Kong/go-apiops/pull/231) + + + ## [v1.41.3] > Release date: 2024/11/25 @@ -1867,6 +1883,7 @@ No breaking changes have been introduced in this release. Debut release of decK +[v1.41.4]: https://github.com/Kong/deck/compare/v1.41.3...v1.41.4 [v1.41.3]: https://github.com/Kong/deck/compare/v1.41.2...v1.41.3 [v1.41.2]: https://github.com/Kong/deck/compare/v1.41.1...v1.41.2 [v1.41.1]: https://github.com/Kong/deck/compare/v1.40.0...v1.41.1 diff --git a/README.md b/README.md index 356bbba30..5122cefca 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ the GitHub [release page](https://github.com/kong/deck/releases) or install by downloading the binary: ```shell -$ curl -sL https://github.com/kong/deck/releases/download/v1.41.3/deck_1.41.3_linux_amd64.tar.gz -o deck.tar.gz +$ curl -sL https://github.com/kong/deck/releases/download/v1.41.4/deck_1.41.4_linux_amd64.tar.gz -o deck.tar.gz $ tar -xf deck.tar.gz -C /tmp $ sudo cp /tmp/deck /usr/local/bin/ ``` @@ -84,7 +84,7 @@ If you are on Windows, you can download the binary from the GitHub [release page](https://github.com/kong/deck/releases) or via PowerShell: ```shell -$ curl -sL https://github.com/kong/deck/releases/download/v1.41.3/deck_1.41.3_windows_amd64.tar.gz -o deck.tar.gz +$ curl -sL https://github.com/kong/deck/releases/download/v1.41.4/deck_1.41.4_windows_amd64.tar.gz -o deck.tar.gz $ tar -xzvf deck.tar.gz ``` diff --git a/cmd/gateway_validate.go b/cmd/gateway_validate.go index 37fe97e2d..2625d9284 100644 --- a/cmd/gateway_validate.go +++ b/cmd/gateway_validate.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "sort" "github.com/blang/semver/v4" "github.com/kong/deck/utils" @@ -17,13 +18,13 @@ import ( ) var ( - validateCmdKongStateFile []string - validateCmdRBACResourcesOnly bool - validateCmdCheckOnlinePluginsOnly bool - validateOnline bool - validateWorkspace string - validateParallelism int - validateKonnectCompatibility bool + validateCmdKongStateFile []string + validateCmdOnlineEntitiesFilter []string + validateCmdRBACResourcesOnly bool + validateOnline bool + validateKonnectCompatibility bool + validateWorkspace string + validateParallelism int ) func executeValidate(cmd *cobra.Command, _ []string) error { @@ -211,6 +212,26 @@ this command unless --online flag is used. if len(validateCmdKongStateFile) == 0 { validateCmdKongStateFile = []string{"-"} } + + // Iterate over the input values and validate them against the keys in entityMap + for _, value := range validateCmdOnlineEntitiesFilter { + // Check if the value is valid by comparing it with keys in EntityMap + if _, exists := validate.EntityMap[value]; !exists { + // Generate an error message with the list of valid keys + listOfKeys := make([]string, 0, len(validate.EntityMap)) + for key := range validate.EntityMap { + listOfKeys = append(listOfKeys, key) + } + // Sort the keys alphabetically + sort.Strings(listOfKeys) + + return fmt.Errorf( + "invalid value '%s' for --check-online-plugins-only; it should be a valid Kong entity. "+ + "Valid entities: %v", + value, listOfKeys, + ) + } + } return preRunSilenceEventsFlag() } @@ -238,8 +259,8 @@ this command unless --online flag is used. validateCmd.Flags().BoolVar(&validateCmdRBACResourcesOnly, "rbac-resources-only", false, "indicate that the state file(s) contains RBAC resources only (Kong Enterprise only).") - validateCmd.Flags().BoolVar(&validateCmdCheckOnlinePluginsOnly, "check-online-plugins-only", - false, "indicate that the online validation will be done only on plugins.") + validateCmd.Flags().StringSliceVarP(&validateCmdOnlineEntitiesFilter, "online-entities-list", + "", []string{}, "indicate the list of entitied that should be validate online validation.") if deprecated { validateCmd.Flags().StringSliceVarP(&validateCmdKongStateFile, "state", "s", []string{"kong.yaml"}, "file(s) containing Kong's configuration.\n"+ @@ -282,12 +303,12 @@ func validateWithKong( return []error{fmt.Errorf("parsing Kong version: %w", err)} } opts := validate.ValidatorOpts{ - Ctx: ctx, - State: ks, - Client: kongClient, - Parallelism: validateParallelism, - RBACResourcesOnly: validateCmdRBACResourcesOnly, - CheckOnlinePluginsOnly: validateCmdCheckOnlinePluginsOnly, + Ctx: ctx, + State: ks, + Client: kongClient, + Parallelism: validateParallelism, + RBACResourcesOnly: validateCmdRBACResourcesOnly, + OnlineEntitiesFilter: validateCmdOnlineEntitiesFilter, } validator := validate.NewValidator(opts) return validator.Validate(parsedFormatVersion) diff --git a/go.mod b/go.mod index 3db19f98e..4df4ce063 100644 --- a/go.mod +++ b/go.mod @@ -12,14 +12,14 @@ require ( github.com/daveshanley/vacuum v0.9.15 github.com/fatih/color v1.17.0 github.com/google/go-cmp v0.6.0 - github.com/kong/go-apiops v0.1.39 + github.com/kong/go-apiops v0.1.40 github.com/kong/go-database-reconciler v1.16.1 github.com/kong/go-kong v0.60.0 github.com/mitchellh/go-homedir v1.1.0 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 golang.org/x/sync v0.8.0 k8s.io/api v0.31.2 k8s.io/apiextensions-apiserver v0.31.2 @@ -189,8 +189,8 @@ require ( golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect golang.org/x/mod v0.21.0 // indirect golang.org/x/net v0.30.0 // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/term v0.25.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/term v0.26.0 // indirect golang.org/x/text v0.19.0 // indirect golang.org/x/tools v0.26.0 // indirect google.golang.org/protobuf v1.34.2 // indirect diff --git a/go.sum b/go.sum index 11ad319b8..dc7be4dfe 100644 --- a/go.sum +++ b/go.sum @@ -245,8 +245,8 @@ github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuOb github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/kong/go-apiops v0.1.39 h1:OXUzHb6tyZ+bb1xWzpPvmZK7FNk4xtrcka8d0bRTQkI= -github.com/kong/go-apiops v0.1.39/go.mod h1:WghIt61r2b+HaeGVNWCd+aswTMHIjeP3GYK09/yYWA8= +github.com/kong/go-apiops v0.1.40 h1:Dp4IHJ3h61VeOAeQkOisf1BcOP+Ww+gpqnv14HvC6DQ= +github.com/kong/go-apiops v0.1.40/go.mod h1:CNfsa9mHFRfAhT9E2IWTul0Mi1/BldTDmFu5fWcp2us= github.com/kong/go-database-reconciler v1.16.1 h1:qcQzEuMGfpNjx3UgulBOKulKA+upmHwqw4dy6TMEV7A= github.com/kong/go-database-reconciler v1.16.1/go.mod h1:7CGvStUvUOmUnodUFsWcW3PX2bJgnaKClJ/yhNGEVIE= github.com/kong/go-kong v0.60.0 h1:CVrLXRLVE+Gl4IZ3tdvpO7xNDz3c9YLTmra/HvT4oM8= @@ -325,8 +325,8 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= -github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= +github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -419,8 +419,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= @@ -566,16 +567,16 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= -golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/tests/integration/sync_test.go b/tests/integration/sync_test.go index 746de8f0e..ca5e084ad 100644 --- a/tests/integration/sync_test.go +++ b/tests/integration/sync_test.go @@ -1397,6 +1397,7 @@ var ( ID: kong.String("77e6691d-67c0-446a-9401-27be2b141aae"), }, Config: kong.Configuration{ + "compound_identifier": nil, "consumer_groups": nil, "dictionary_name": string("kong_rate_limiting_counters"), "disable_penalty": bool(false), @@ -1447,6 +1448,7 @@ var ( ID: kong.String("5bcbd3a7-030b-4310-bd1d-2721ff85d236"), }, Config: kong.Configuration{ + "compound_identifier": nil, "consumer_groups": nil, "dictionary_name": string("kong_rate_limiting_counters"), "disable_penalty": bool(false), @@ -1494,6 +1496,7 @@ var ( { Name: kong.String("rate-limiting-advanced"), Config: kong.Configuration{ + "compound_identifier": nil, "consumer_groups": nil, "dictionary_name": string("kong_rate_limiting_counters"), "disable_penalty": bool(false), diff --git a/tests/integration/testdata/dump/002-skip-consumers/expected-no-skip_konnect.yaml b/tests/integration/testdata/dump/002-skip-consumers/expected-no-skip_konnect.yaml index aea340bc6..b99f56505 100644 --- a/tests/integration/testdata/dump/002-skip-consumers/expected-no-skip_konnect.yaml +++ b/tests/integration/testdata/dump/002-skip-consumers/expected-no-skip_konnect.yaml @@ -5,6 +5,7 @@ consumer_groups: - name: basic plugins: - config: + compound_identifier: null consumer_groups: null dictionary_name: kong_rate_limiting_counters disable_penalty: false diff --git a/tests/integration/validate_test.go b/tests/integration/validate_test.go index 6b2468137..03051e040 100644 --- a/tests/integration/validate_test.go +++ b/tests/integration/validate_test.go @@ -76,6 +76,22 @@ func Test_Validate_Konnect(t *testing.T) { additionalArgs: []string{"--konnect-runtime-group-name=default"}, errorExpected: false, }, + { + name: "validate with wrong online list, passed via --online-entities-list cli flag", + stateFile: "testdata/validate/kong3x.yaml", + additionalArgs: []string{"--online-entities-list=services,Routes,Plugins"}, + errorExpected: true, + errorString: "invalid value 'services' for --check-online-plugins-only; it should be a valid " + + "Kong entity. Valid entities: [ACLGroups BasicAuths CACertificates Certificates Consumers Documents " + + "FilterChains HMACAuths JWTAuths KeyAuths Oauth2Creds Plugins RBACEndpointPermissions RBACRoles Routes " + + "SNIs Services Targets Upstreams Vaults]", + }, + { + name: "validate with correct online list, passed via --online-entities-list cli flag", + stateFile: "testdata/validate/kong3x.yaml", + additionalArgs: []string{"--online-entities-list=Services,Routes,Plugins"}, + errorExpected: false, + }, } for _, tc := range tests { @@ -134,9 +150,9 @@ func Test_Validate_File(t *testing.T) { additionalArgs: []string{"--rbac-resources-only"}, }, { - name: "file validate with --check-online-plugins-only", + name: "file validate with --online-entities-list", stateFile: "testdata/validate/kong3x.yaml", - additionalArgs: []string{"--check-online-plugins-only"}, + additionalArgs: []string{"--online-entities-list=Services,Routes,Plugins"}, }, } diff --git a/validate/validate.go b/validate/validate.go index baeb572a6..2372b8cac 100644 --- a/validate/validate.go +++ b/validate/validate.go @@ -16,31 +16,55 @@ import ( ) type Validator struct { - ctx context.Context - state *state.KongState - client *kong.Client - parallelism int - rbacResourcesOnly bool - CheckOnlinePluginsOnly bool + ctx context.Context + state *state.KongState + client *kong.Client + parallelism int + rbacResourcesOnly bool + onlineEntitiesFilter []string } type ValidatorOpts struct { - Ctx context.Context - State *state.KongState - Client *kong.Client - Parallelism int - RBACResourcesOnly bool - CheckOnlinePluginsOnly bool + Ctx context.Context + State *state.KongState + Client *kong.Client + Parallelism int + RBACResourcesOnly bool + OnlineEntitiesFilter []string +} + +// Define a map of entity object field names and their corresponding string names +var EntityMap = map[string]string{ + "ACLGroups": "acls", + "BasicAuths": "basicauth_credentials", + "CACertificates": "ca_certificates", + "Certificates": "certificates", + "Consumers": "consumers", + "Documents": "documents", + "FilterChains": "filter_chains", + "HMACAuths": "hmacauth_credentials", + "JWTAuths": "jwt_secrets", + "KeyAuths": "keyauth_credentials", + "Oauth2Creds": "oauth2_credentials", + "Plugins": "plugins", + "RBACEndpointPermissions": "rbac-endpointpermission", + "RBACRoles": "rbac-role", + "Routes": "routes", + "SNIs": "snis", + "Services": "services", + "Targets": "targets", + "Upstreams": "upstreams", + "Vaults": "vaults", } func NewValidator(opt ValidatorOpts) *Validator { return &Validator{ - ctx: opt.Ctx, - state: opt.State, - client: opt.Client, - parallelism: opt.Parallelism, - rbacResourcesOnly: opt.RBACResourcesOnly, - CheckOnlinePluginsOnly: opt.CheckOnlinePluginsOnly, + ctx: opt.Ctx, + state: opt.State, + client: opt.Client, + parallelism: opt.Parallelism, + rbacResourcesOnly: opt.RBACResourcesOnly, + onlineEntitiesFilter: opt.OnlineEntitiesFilter, } } @@ -122,75 +146,48 @@ func (v *Validator) entities(obj interface{}, entityType string) []error { func (v *Validator) Validate(formatVersion semver.Version) []error { allErr := []error{} - // validate RBAC resources first. - if err := v.entities(v.state.RBACEndpointPermissions, "rbac-endpointpermission"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.RBACRoles, "rbac-role"); err != nil { - allErr = append(allErr, err...) - } if v.rbacResourcesOnly { + // validate RBAC resources first. + if err := v.entities(v.state.RBACEndpointPermissions, "rbac-endpointpermission"); err != nil { + allErr = append(allErr, err...) + } + if err := v.entities(v.state.RBACRoles, "rbac-role"); err != nil { + allErr = append(allErr, err...) + } return allErr } - // validate Plugins resources then. - if err := v.entities(v.state.Plugins, "plugins"); err != nil { - allErr = append(allErr, err...) - } - if v.CheckOnlinePluginsOnly { - return allErr + // Create a copy of entityMap with only the specififed resources to check online. + filteredEntityMap := make(map[string]string) + if len(v.onlineEntitiesFilter) > 0 { + for _, value := range v.onlineEntitiesFilter { + for key, entityName := range EntityMap { + if value == key { + filteredEntityMap[key] = entityName + } + } + } + } else { + // If no filter is specified, use the original entityMap. + filteredEntityMap = EntityMap } - if err := v.entities(v.state.Services, "services"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.ACLGroups, "acls"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.BasicAuths, "basicauth_credentials"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.CACertificates, "ca_certificates"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.Certificates, "certificates"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.Consumers, "consumers"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.Documents, "documents"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.HMACAuths, "hmacauth_credentials"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.JWTAuths, "jwt_secrets"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.KeyAuths, "keyauth_credentials"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.Oauth2Creds, "oauth2_credentials"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.Routes, "routes"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.SNIs, "snis"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.Targets, "targets"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.Upstreams, "upstreams"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.FilterChains, "filter_chains"); err != nil { - allErr = append(allErr, err...) - } - if err := v.entities(v.state.Vaults, "vaults"); err != nil { - allErr = append(allErr, err...) + // Validate each entity using the filtered entityMap + for fieldName, entityName := range filteredEntityMap { + // Use reflection to get the value of the field from v.state + valueOfState := reflect.ValueOf(v.state) + if valueOfState.Kind() == reflect.Ptr { + valueOfState = valueOfState.Elem() // Dereference if it's a pointer + } + + fieldValue := valueOfState.FieldByName(fieldName) + if fieldValue.IsValid() && fieldValue.CanInterface() { + if err := v.entities(fieldValue.Interface(), entityName); err != nil { + allErr = append(allErr, err...) + } + } else { + allErr = append(allErr, fmt.Errorf("invalid field '%s' in state", fieldName)) + } } // validate routes format with Kong 3.x From 135819032432d20ec241d89c0a8c7e545898d264 Mon Sep 17 00:00:00 2001 From: Antoine Jacquemin Date: Wed, 4 Dec 2024 17:02:41 +0100 Subject: [PATCH 3/6] fix test --- .../dump/002-skip-consumers/expected-no-skip_konnect.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration/testdata/dump/002-skip-consumers/expected-no-skip_konnect.yaml b/tests/integration/testdata/dump/002-skip-consumers/expected-no-skip_konnect.yaml index b99f56505..7080d6137 100644 --- a/tests/integration/testdata/dump/002-skip-consumers/expected-no-skip_konnect.yaml +++ b/tests/integration/testdata/dump/002-skip-consumers/expected-no-skip_konnect.yaml @@ -33,6 +33,7 @@ consumer_groups: password: null port: 6379 read_timeout: 2000 + redis_proxy_type: null send_timeout: 2000 sentinel_addresses: null sentinel_master: null From 366993886854e98489313b93a933f591c172e9da Mon Sep 17 00:00:00 2001 From: Antoine Jacquemin Date: Thu, 5 Dec 2024 11:32:51 +0100 Subject: [PATCH 4/6] fix err msg --- cmd/gateway_validate.go | 4 ++-- tests/integration/validate_test.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/gateway_validate.go b/cmd/gateway_validate.go index 2625d9284..e3dca9ec5 100644 --- a/cmd/gateway_validate.go +++ b/cmd/gateway_validate.go @@ -226,7 +226,7 @@ this command unless --online flag is used. sort.Strings(listOfKeys) return fmt.Errorf( - "invalid value '%s' for --check-online-plugins-only; it should be a valid Kong entity. "+ + "invalid value '%s' for --online-entities-list; it should be a valid Kong entity (case-sensitive). "+ "Valid entities: %v", value, listOfKeys, ) @@ -260,7 +260,7 @@ this command unless --online flag is used. validateCmd.Flags().BoolVar(&validateCmdRBACResourcesOnly, "rbac-resources-only", false, "indicate that the state file(s) contains RBAC resources only (Kong Enterprise only).") validateCmd.Flags().StringSliceVarP(&validateCmdOnlineEntitiesFilter, "online-entities-list", - "", []string{}, "indicate the list of entitied that should be validate online validation.") + "", []string{}, "indicate the list of entities that should be validated online validation.") if deprecated { validateCmd.Flags().StringSliceVarP(&validateCmdKongStateFile, "state", "s", []string{"kong.yaml"}, "file(s) containing Kong's configuration.\n"+ diff --git a/tests/integration/validate_test.go b/tests/integration/validate_test.go index 03051e040..95a65c472 100644 --- a/tests/integration/validate_test.go +++ b/tests/integration/validate_test.go @@ -81,10 +81,10 @@ func Test_Validate_Konnect(t *testing.T) { stateFile: "testdata/validate/kong3x.yaml", additionalArgs: []string{"--online-entities-list=services,Routes,Plugins"}, errorExpected: true, - errorString: "invalid value 'services' for --check-online-plugins-only; it should be a valid " + - "Kong entity. Valid entities: [ACLGroups BasicAuths CACertificates Certificates Consumers Documents " + - "FilterChains HMACAuths JWTAuths KeyAuths Oauth2Creds Plugins RBACEndpointPermissions RBACRoles Routes " + - "SNIs Services Targets Upstreams Vaults]", + errorString: "invalid value 'services' for --online-entities-list; it should be a valid " + + "Kong entity (case-sensitive). Valid entities: [ACLGroups BasicAuths CACertificates Certificates Consumers " + + "Documents FilterChains HMACAuths JWTAuths KeyAuths Oauth2Creds Plugins RBACEndpointPermissions RBACRoles " + + "Routes SNIs Services Targets Upstreams Vaults]", }, { name: "validate with correct online list, passed via --online-entities-list cli flag", From 22737157a4b74c04cf4e6b33b0e032860309d4de Mon Sep 17 00:00:00 2001 From: Antoine Jacquemin Date: Thu, 5 Dec 2024 11:41:37 +0100 Subject: [PATCH 5/6] add tests --- tests/integration/validate_test.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/integration/validate_test.go b/tests/integration/validate_test.go index 95a65c472..c1c257000 100644 --- a/tests/integration/validate_test.go +++ b/tests/integration/validate_test.go @@ -149,11 +149,6 @@ func Test_Validate_File(t *testing.T) { stateFile: "testdata/validate/rbac-resources.yaml", additionalArgs: []string{"--rbac-resources-only"}, }, - { - name: "file validate with --online-entities-list", - stateFile: "testdata/validate/kong3x.yaml", - additionalArgs: []string{"--online-entities-list=Services,Routes,Plugins"}, - }, } for _, tc := range tests { @@ -239,6 +234,16 @@ func Test_Validate_Gateway_EE(t *testing.T) { stateFile: "testdata/validate/kong-ee.yaml", additionalArgs: []string{"--workspace=default"}, }, + { + name: "validate format version 3.0 with --online-entities-list", + stateFile: "testdata/validate/kong-ee.yaml", + additionalArgs: []string{"--online-entities-list=Services,Routes,Plugins"}, + }, + { + name: "validate with konnect and --online-entities-list", + stateFile: "testdata/validate/konnect.yaml", + additionalArgs: []string{"--online-entities-list=Services,Routes,Plugins"}, + }, // TODO: Add a rbac flag test, once the behaviour is fixed } From 4862fa7bf8161588cea22b0fb66cc676946ead70 Mon Sep 17 00:00:00 2001 From: Antoine Jacquemin Date: Thu, 5 Dec 2024 11:43:21 +0100 Subject: [PATCH 6/6] add tests --- tests/integration/validate_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/integration/validate_test.go b/tests/integration/validate_test.go index c1c257000..f8e5e40c3 100644 --- a/tests/integration/validate_test.go +++ b/tests/integration/validate_test.go @@ -189,6 +189,16 @@ func Test_Validate_Gateway(t *testing.T) { stateFile: "testdata/validate/konnect.yaml", additionalArgs: []string{"--konnect-compatibility"}, }, + { + name: "validate format version 3.0 with --online-entities-list", + stateFile: "testdata/validate/kong3x.yaml", + additionalArgs: []string{"--online-entities-list=Services,Routes,Plugins"}, + }, + { + name: "validate with konnect and --online-entities-list", + stateFile: "testdata/validate/konnect.yaml", + additionalArgs: []string{"--online-entities-list=Services,Routes,Plugins"}, + }, } for _, tc := range tests {