-
Notifications
You must be signed in to change notification settings - Fork 128
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add Konnect readiness validation (#1227)
--------- Signed-off-by: John Harris <[email protected]>
- Loading branch information
1 parent
9d89a33
commit 40d355a
Showing
3 changed files
with
279 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package validate | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"strconv" | ||
|
||
"github.com/kong/go-database-reconciler/pkg/file" | ||
"github.com/kong/go-kong/kong" | ||
) | ||
|
||
var ( | ||
errKonnect = "[konnect] section not specified - ensure details are set via cli flags" | ||
errWorkspace = "[workspaces] not supported by Konnect - use control planes instead" | ||
errNoVersion = "[version] unable to determine decK file version" | ||
errBadVersion = fmt.Sprintf("[version] decK file version must be '%.1f' or greater", supportedVersion) | ||
errPluginIncompatible = "[%s] plugin is not compatible with Konnect" | ||
errPluginNoCluster = "[%s] plugin can't be used with cluster strategy" | ||
) | ||
|
||
var supportedVersion = 3.0 | ||
|
||
func checkPlugin(name *string, config kong.Configuration) error { | ||
switch *name { | ||
case "jwt-signer", "vault-auth", "oauth2": | ||
return fmt.Errorf(errPluginIncompatible, *name) | ||
case "application-registration": | ||
return fmt.Errorf("[%s] available in Konnect, but doesn't require this plugin", *name) | ||
case "key-auth-enc": | ||
return fmt.Errorf("[%s] keys are automatically encrypted in Konnect, use the key auth plugin instead", *name) | ||
case "openwhisk": | ||
return fmt.Errorf("[%s] plugin not bundled with Kong Gateway - installed as a LuaRocks package", *name) | ||
case "rate-limiting", "rate-limiting-advanced", "response-ratelimiting", "graphql-rate-limiting-advanced": | ||
if config["strategy"] == "cluster" { | ||
return fmt.Errorf(errPluginNoCluster, *name) | ||
} | ||
default: | ||
} | ||
return nil | ||
} | ||
|
||
func KonnectCompatibility(targetContent *file.Content) []error { | ||
var errs []error | ||
|
||
if targetContent.Workspace != "" { | ||
errs = append(errs, errors.New(errWorkspace)) | ||
} | ||
|
||
if targetContent.Konnect == nil { | ||
errs = append(errs, errors.New(errKonnect)) | ||
} | ||
|
||
versionNumber, err := strconv.ParseFloat(targetContent.FormatVersion, 32) | ||
if err != nil { | ||
errs = append(errs, errors.New(errNoVersion)) | ||
} else { | ||
if versionNumber < supportedVersion { | ||
errs = append(errs, errors.New(errBadVersion)) | ||
} | ||
} | ||
|
||
for _, plugin := range targetContent.Plugins { | ||
if plugin.Enabled != nil && *plugin.Enabled && plugin.Config != nil { | ||
err := checkPlugin(plugin.Name, plugin.Config) | ||
if err != nil { | ||
errs = append(errs, err) | ||
} | ||
} | ||
} | ||
|
||
for _, consumer := range targetContent.Consumers { | ||
for _, plugin := range consumer.Plugins { | ||
if plugin.Enabled != nil && *plugin.Enabled && plugin.Config != nil { | ||
err := checkPlugin(plugin.Name, plugin.Config) | ||
if err != nil { | ||
errs = append(errs, err) | ||
} | ||
} | ||
} | ||
} | ||
|
||
for _, consumerGroup := range targetContent.ConsumerGroups { | ||
for _, plugin := range consumerGroup.Plugins { | ||
err := checkPlugin(plugin.Name, plugin.Config) | ||
if err != nil { | ||
errs = append(errs, err) | ||
} | ||
} | ||
} | ||
|
||
for _, service := range targetContent.Services { | ||
for _, plugin := range service.Plugins { | ||
if plugin.Enabled != nil && *plugin.Enabled && plugin.Config != nil { | ||
err := checkPlugin(plugin.Name, plugin.Config) | ||
if err != nil { | ||
errs = append(errs, err) | ||
} | ||
} | ||
} | ||
} | ||
|
||
for _, service := range targetContent.Services { | ||
for _, route := range service.Routes { | ||
for _, plugin := range route.Plugins { | ||
if plugin.Enabled != nil && *plugin.Enabled && plugin.Config != nil { | ||
err := checkPlugin(plugin.Name, plugin.Config) | ||
if err != nil { | ||
errs = append(errs, err) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
for _, route := range targetContent.Routes { | ||
for _, plugin := range route.Plugins { | ||
if plugin.Enabled != nil && *plugin.Enabled && plugin.Config != nil { | ||
err := checkPlugin(plugin.Name, plugin.Config) | ||
if err != nil { | ||
errs = append(errs, err) | ||
} | ||
} | ||
} | ||
} | ||
|
||
return errs | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
package validate | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/kong/go-database-reconciler/pkg/file" | ||
"github.com/kong/go-kong/kong" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func Test_KonnectCompatibility(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
content *file.Content | ||
expected []error | ||
}{ | ||
{ | ||
name: "version invalid", | ||
content: &file.Content{ | ||
FormatVersion: "2.9", | ||
Workspace: "test", | ||
Konnect: &file.Konnect{ | ||
RuntimeGroupName: "s", | ||
ControlPlaneName: "s", | ||
}, | ||
}, | ||
expected: []error{ | ||
errors.New(errWorkspace), | ||
errors.New(errBadVersion), | ||
}, | ||
}, | ||
{ | ||
name: "no konnect", | ||
content: &file.Content{ | ||
FormatVersion: "3.1", | ||
}, | ||
expected: []error{ | ||
errors.New(errKonnect), | ||
}, | ||
}, | ||
{ | ||
name: "incompatible service plugin", | ||
content: &file.Content{ | ||
FormatVersion: "3.1", | ||
Konnect: &file.Konnect{ | ||
RuntimeGroupName: "s", | ||
ControlPlaneName: "s", | ||
}, | ||
Services: []file.FService{ | ||
{Plugins: []*file.FPlugin{ | ||
{ | ||
Plugin: kong.Plugin{ | ||
Name: kong.String("oauth2"), | ||
Enabled: kong.Bool(true), | ||
Config: kong.Configuration{"config": "config"}, | ||
}, | ||
}, | ||
}}, | ||
}, | ||
}, | ||
expected: []error{ | ||
fmt.Errorf(errPluginIncompatible, "oauth2"), | ||
}, | ||
}, | ||
{ | ||
name: "incompatible service route plugins", | ||
content: &file.Content{ | ||
FormatVersion: "3.1", | ||
Konnect: &file.Konnect{ | ||
RuntimeGroupName: "s", | ||
ControlPlaneName: "s", | ||
}, | ||
Services: []file.FService{ | ||
{Routes: []*file.FRoute{ | ||
{ | ||
Plugins: []*file.FPlugin{ | ||
{ | ||
Plugin: kong.Plugin{ | ||
Name: kong.String("oauth2"), | ||
Enabled: kong.Bool(true), | ||
Config: kong.Configuration{"config": "config"}, | ||
}, | ||
}, | ||
{ | ||
Plugin: kong.Plugin{ | ||
Name: kong.String("key-auth-enc"), | ||
Enabled: kong.Bool(true), | ||
Config: kong.Configuration{"config": "config"}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}}, | ||
}, | ||
}, | ||
expected: []error{ | ||
fmt.Errorf(errPluginIncompatible, "oauth2"), | ||
fmt.Errorf("[%s] keys are automatically encrypted in Konnect, use the key auth plugin instead", "key-auth-enc"), | ||
}, | ||
}, | ||
{ | ||
name: "incompatible top-level and consumer-group plugins", | ||
content: &file.Content{ | ||
FormatVersion: "3.1", | ||
Konnect: &file.Konnect{ | ||
RuntimeGroupName: "s", | ||
ControlPlaneName: "s", | ||
}, | ||
Plugins: []file.FPlugin{ | ||
{ | ||
Plugin: kong.Plugin{ | ||
Name: kong.String("response-ratelimiting"), | ||
Enabled: kong.Bool(true), | ||
Config: kong.Configuration{"strategy": "cluster"}, | ||
}, | ||
}, | ||
}, | ||
ConsumerGroups: []file.FConsumerGroupObject{ | ||
{ | ||
Plugins: []*kong.ConsumerGroupPlugin{ | ||
{ | ||
Name: kong.String("key-auth-enc"), | ||
Config: kong.Configuration{"config": "config"}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
expected: []error{ | ||
fmt.Errorf(errPluginNoCluster, "response-ratelimiting"), | ||
fmt.Errorf("[%s] keys are automatically encrypted in Konnect, use the key auth plugin instead", "key-auth-enc"), | ||
}, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
errs := KonnectCompatibility(tt.content) | ||
assert.Equal(t, tt.expected, errs) | ||
}) | ||
} | ||
} |