diff --git a/PROVIDER.md b/PROVIDER.md index ee867ac1..4340e877 100644 --- a/PROVIDER.md +++ b/PROVIDER.md @@ -61,7 +61,10 @@ func (r *resourceReader) ReadResourcesFromFiles(ctx context.Context, customResou ``` 3. Create a struct named `converter` which implements the `ResourceConverter` interface in a file named `converter.go`. The implemented `ToGatewayAPI` function should simply call every registered `featureParser` function, one by one. -Take a look at `ingressnginx/converter.go` for example. +Take a look at `ingressnginx/converter.go` for an example. +The `ImplementationSpecificOptions` struct contains the handlers to customize native ingress implementation-specific fields. +Take a look at `kong/converter.go` for an example. + ```go package examplegateway @@ -74,6 +77,7 @@ type converter struct { conf *i2gw.ProviderConf featureParsers []i2gw.FeatureParser + implementationSpecificOptions i2gw.ProviderImplementationSpecificOptions } // newConverter returns an ingress-nginx converter instance. @@ -83,6 +87,9 @@ func newConverter(conf *i2gw.ProviderConf) *converter { featureParsers: []i2gw.FeatureParser{ // The list of feature parsers comes here. }, + implementationSpecificOptions: i2gw.ProviderImplementationSpecificOptions{ + // The list of the implementationSpecific ingress fields options comes here. + }, } } ``` diff --git a/pkg/i2gw/provider.go b/pkg/i2gw/provider.go index d8bc625c..215b04c7 100644 --- a/pkg/i2gw/provider.go +++ b/pkg/i2gw/provider.go @@ -73,15 +73,15 @@ type ResourceConverter interface { ToGatewayAPI(resources InputResources) (GatewayResources, field.ErrorList) } -// ImplementationSpecificHTTPPathMatchOption is an option to customize the ingress implementationSpecific +// ImplementationSpecificHTTPPathTypeMatchConverter is an option to customize the ingress implementationSpecific // match type conversion. -type ImplementationSpecificHTTPPathMatchOption func(*gatewayv1beta1.HTTPPathMatch) +type ImplementationSpecificHTTPPathTypeMatchConverter func(*gatewayv1beta1.HTTPPathMatch) -// ProviderImplementationSpecificOptions contains all the pointers to implementation-specific -// customization functions. Such functions will be called by the common package to customize -// the provider-specific behavior for all the implementation-specific fields of the API. +// ProviderImplementationSpecificOptions contains customized implementation-specific fields and functions. +// These will be used by the common package to customize the provider-specific behavior for all the +// implementation-specific fields of the ingress API. type ProviderImplementationSpecificOptions struct { - ToImplementationSpecificHTTPPathMatch ImplementationSpecificHTTPPathMatchOption + ToImplementationSpecificHTTPPathTypeMatch ImplementationSpecificHTTPPathTypeMatchConverter } // InputResources contains all Ingress objects, and Provider specific diff --git a/pkg/i2gw/providers/common/converter.go b/pkg/i2gw/providers/common/converter.go index f1ae5a5e..f3ffe35c 100644 --- a/pkg/i2gw/providers/common/converter.go +++ b/pkg/i2gw/providers/common/converter.go @@ -305,7 +305,7 @@ func (rg *ingressRuleGroup) toHTTPRoute(options i2gw.ProviderImplementationSpeci for _, paths := range pathsByMatchGroup { path := paths[0] fieldPath := field.NewPath("spec", "rules").Index(path.ruleIdx).Child(path.ruleType).Child("paths").Index(path.pathIdx) - match, err := toHTTPRouteMatch(path.path, fieldPath, options.ToImplementationSpecificHTTPPathMatch) + match, err := toHTTPRouteMatch(path.path, fieldPath, options.ToImplementationSpecificHTTPPathTypeMatch) if err != nil { errors = append(errors, err) continue @@ -348,7 +348,7 @@ func getPathMatchKey(ip ingressPath) pathMatchKey { return pathMatchKey(fmt.Sprintf("%s/%s", pathType, ip.path.Path)) } -func toHTTPRouteMatch(routePath networkingv1.HTTPIngressPath, path *field.Path, toImplementationSpecificPathMatch i2gw.ImplementationSpecificHTTPPathMatchOption) (*gatewayv1beta1.HTTPRouteMatch, *field.Error) { +func toHTTPRouteMatch(routePath networkingv1.HTTPIngressPath, path *field.Path, toImplementationSpecificPathMatch i2gw.ImplementationSpecificHTTPPathTypeMatchConverter) (*gatewayv1beta1.HTTPRouteMatch, *field.Error) { pmPrefix := gatewayv1beta1.PathMatchPathPrefix pmExact := gatewayv1beta1.PathMatchExact @@ -367,6 +367,11 @@ func toHTTPRouteMatch(routePath networkingv1.HTTPIngressPath, path *field.Path, } else { return nil, field.Invalid(path.Child("pathType"), routePath.PathType, "implementationSpecific path type is not supported in generic translation, and your provider does not provide custom support to translate it") } + default: + // default should never hit, as all the possible cases are already checked + // via proper switch cases. + return nil, field.Invalid(path.Child("pathType"), match.Path.Type, fmt.Sprintf("unsupported path match type: %s", *match.Path.Type)) + } return match, nil diff --git a/pkg/i2gw/providers/kong/converter.go b/pkg/i2gw/providers/kong/converter.go index 3403ba0a..d628d212 100644 --- a/pkg/i2gw/providers/kong/converter.go +++ b/pkg/i2gw/providers/kong/converter.go @@ -27,7 +27,7 @@ type converter struct { conf *i2gw.ProviderConf featureParsers []i2gw.FeatureParser - ImplementationSpecificOptions i2gw.ProviderImplementationSpecificOptions + implementationSpecificOptions i2gw.ProviderImplementationSpecificOptions } // newConverter returns an kong converter instance. @@ -39,8 +39,8 @@ func newConverter(conf *i2gw.ProviderConf) *converter { methodMatchingFeature, pluginsFeature, }, - ImplementationSpecificOptions: i2gw.ProviderImplementationSpecificOptions{ - ToImplementationSpecificHTTPPathMatch: implementationSpecificHTTPPathMatch, + implementationSpecificOptions: i2gw.ProviderImplementationSpecificOptions{ + ToImplementationSpecificHTTPPathTypeMatch: implementationSpecificHTTPPathTypeMatch, }, } } @@ -51,7 +51,7 @@ func (c *converter) ToGatewayAPI(resources i2gw.InputResources) (i2gw.GatewayRes // Convert plain ingress resources to gateway resources, ignoring all // provider-specific features. - gatewayResources, errs := common.ToGateway(resources.Ingresses, c.ImplementationSpecificOptions) + gatewayResources, errs := common.ToGateway(resources.Ingresses, c.implementationSpecificOptions) if len(errs) > 0 { return i2gw.GatewayResources{}, errs } diff --git a/pkg/i2gw/providers/kong/converter_test.go b/pkg/i2gw/providers/kong/converter_test.go index 4d01238e..ad381ca0 100644 --- a/pkg/i2gw/providers/kong/converter_test.go +++ b/pkg/i2gw/providers/kong/converter_test.go @@ -33,7 +33,7 @@ import ( func Test_ToGateway(t *testing.T) { iPrefix := networkingv1.PathTypePrefix - ImplSpecPathType := networkingv1.PathTypeImplementationSpecific + ImplSpecificPathType := networkingv1.PathTypeImplementationSpecific gPathPrefix := gatewayv1beta1.PathMatchPathPrefix gPathRegex := gatewayv1beta1.PathMatchRegularExpression @@ -340,7 +340,7 @@ func Test_ToGateway(t *testing.T) { HTTP: &networkingv1.HTTPIngressRuleValue{ Paths: []networkingv1.HTTPIngressPath{{ Path: "/~/echo/**/test", - PathType: &ImplSpecPathType, + PathType: &ImplSpecificPathType, Backend: networkingv1.IngressBackend{ Service: &networkingv1.IngressServiceBackend{ Name: "test", @@ -425,7 +425,7 @@ func Test_ToGateway(t *testing.T) { HTTP: &networkingv1.HTTPIngressRuleValue{ Paths: []networkingv1.HTTPIngressPath{{ Path: "/echo", - PathType: &ImplSpecPathType, + PathType: &ImplSpecificPathType, Backend: networkingv1.IngressBackend{ Service: &networkingv1.IngressServiceBackend{ Name: "test", diff --git a/pkg/i2gw/providers/kong/header_matching_test.go b/pkg/i2gw/providers/kong/header_matching_test.go index c6b057ac..6e79f74f 100644 --- a/pkg/i2gw/providers/kong/header_matching_test.go +++ b/pkg/i2gw/providers/kong/header_matching_test.go @@ -247,7 +247,7 @@ func TestHeaderMatchingFeature(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { gatewayResources, errs := common.ToGateway(tc.inputResources.Ingresses, i2gw.ProviderImplementationSpecificOptions{ - ToImplementationSpecificHTTPPathMatch: implementationSpecificHTTPPathMatch, + ToImplementationSpecificHTTPPathTypeMatch: implementationSpecificHTTPPathTypeMatch, }) if len(errs) != 0 { t.Errorf("Expected no errors, got %d: %+v", len(errs), errs) diff --git a/pkg/i2gw/providers/kong/implementation_specific.go b/pkg/i2gw/providers/kong/implementation_specific.go index 9292385a..8d5a0de5 100644 --- a/pkg/i2gw/providers/kong/implementation_specific.go +++ b/pkg/i2gw/providers/kong/implementation_specific.go @@ -23,7 +23,7 @@ import ( gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) -func implementationSpecificHTTPPathMatch(path *gatewayv1beta1.HTTPPathMatch) { +func implementationSpecificHTTPPathTypeMatch(path *gatewayv1beta1.HTTPPathMatch) { pmPrefix := gatewayv1beta1.PathMatchPathPrefix pmRegex := gatewayv1beta1.PathMatchRegularExpression if strings.HasPrefix(*path.Value, "/~") { diff --git a/pkg/i2gw/providers/kong/method_matching_test.go b/pkg/i2gw/providers/kong/method_matching_test.go index dae4ba2b..c26173ac 100644 --- a/pkg/i2gw/providers/kong/method_matching_test.go +++ b/pkg/i2gw/providers/kong/method_matching_test.go @@ -190,7 +190,7 @@ func TestMethodMatchingFeature(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { gatewayResources, errs := common.ToGateway(tc.inputResources.Ingresses, i2gw.ProviderImplementationSpecificOptions{ - ToImplementationSpecificHTTPPathMatch: implementationSpecificHTTPPathMatch, + ToImplementationSpecificHTTPPathTypeMatch: implementationSpecificHTTPPathTypeMatch, }) if len(errs) != 0 { t.Errorf("Expected no errors, got %d: %+v", len(errs), errs)