Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions cmd/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,21 @@ func (pr *PrintRunner) PrintGatewayAPIObjects(cmd *cobra.Command, _ []string) er
}

gatewayResources, notificationTablesMap, err := i2gw.ToGatewayAPIResources(cmd.Context(), pr.namespaceFilter, pr.inputFile, pr.providers, pr.getProviderSpecificFlags())
if err != nil {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This enables best-effort conversion and allows users to see what could be converted

return err
}

for _, table := range notificationTablesMap {
fmt.Fprintln(os.Stderr, table)
}

// Output partial results even if there are conversion errors (best-effort conversion)
pr.outputResult(gatewayResources)

// Return error after outputting partial results
if err != nil {
// Silence usage on conversion errors since these are not command usage errors
cmd.SilenceUsage = true
return err
}

return nil
}

Expand Down
3 changes: 2 additions & 1 deletion pkg/i2gw/ingress2gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ func ToGatewayAPIResources(ctx context.Context, namespace string, inputFile stri
}
notificationTablesMap := notifications.NotificationAggr.CreateNotificationTables()
if len(errs) > 0 {
return nil, notificationTablesMap, aggregatedErrs(errs)
// Return partial results along with errors to support best-effort conversion
return gatewayResources, notificationTablesMap, aggregatedErrs(errs)
}

return gatewayResources, notificationTablesMap, nil
Expand Down
3 changes: 0 additions & 3 deletions pkg/i2gw/providers/apisix/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ func (c *resourcesToIRConverter) convertToIR(storage *storage) (intermediate.IR,
// Convert plain ingress resources to gateway resources, ignoring all
// provider-specific features.
ir, errs := common.ToIR(ingressList, storage.ServicePorts, c.implementationSpecificOptions)
if len(errs) > 0 {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This enables best-effort conversion and allows users to see what could be converted

Etc..

return intermediate.IR{}, errs
}

for _, parseFeatureFunc := range c.featureParsers {
// Apply the feature parsing function to the gateway resources, one by one.
Expand Down
3 changes: 0 additions & 3 deletions pkg/i2gw/providers/cilium/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ func (c *resourcesToIRConverter) convertToIR(storage *storage) (intermediate.IR,
// Convert plain ingress resources to gateway resources, ignoring all
// provider-specific features.
ir, errs := common.ToIR(ingressList, storage.ServicePorts, c.implementationSpecificOptions)
if len(errs) > 0 {
return intermediate.IR{}, errs
}

for _, parseFeatureFunc := range c.featureParsers {
// Apply the feature parsing function to the gateway resources, one by one.
Expand Down
5 changes: 1 addition & 4 deletions pkg/i2gw/providers/common/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ func ToIR(ingresses []networkingv1.Ingress, servicePorts map[types.NamespacedNam
}

routes, gateways, errs := aggregator.toHTTPRoutesAndGateways(options)
if len(errs) > 0 {
return intermediate.IR{}, errs
}

routeByKey := make(map[types.NamespacedName]intermediate.HTTPRouteContext)
for _, routeWithSources := range routes {
Expand Down Expand Up @@ -81,7 +78,7 @@ func ToIR(ingresses []networkingv1.Ingress, servicePorts map[types.NamespacedNam
GRPCRoutes: make(map[types.NamespacedName]gatewayv1.GRPCRoute),
BackendTLSPolicies: make(map[types.NamespacedName]gatewayv1.BackendTLSPolicy),
ReferenceGrants: make(map[types.NamespacedName]gatewayv1beta1.ReferenceGrant),
}, nil
}, errs
}

var (
Expand Down
43 changes: 41 additions & 2 deletions pkg/i2gw/providers/common/converter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,8 +446,47 @@ func Test_ToIR(t *testing.T) {
{Namespace: "test", Name: "example2"}: {"http": 8080},
},
expectedIR: intermediate.IR{
Gateways: map[types.NamespacedName]intermediate.GatewayContext{},
HTTPRoutes: map[types.NamespacedName]intermediate.HTTPRouteContext{},
Gateways: map[types.NamespacedName]intermediate.GatewayContext{
{Namespace: "test", Name: "named-ports"}: {
Gateway: gatewayv1.Gateway{
ObjectMeta: metav1.ObjectMeta{Name: "named-ports", Namespace: "test"},
Spec: gatewayv1.GatewaySpec{
GatewayClassName: "named-ports",
Listeners: []gatewayv1.Listener{{
Name: "example-com-http",
Port: 80,
Protocol: gatewayv1.HTTPProtocolType,
Hostname: PtrTo(gatewayv1.Hostname("example.com")),
}},
},
},
},
},
HTTPRoutes: map[types.NamespacedName]intermediate.HTTPRouteContext{
{Namespace: "test", Name: "named-ports-example-com"}: {
HTTPRoute: gatewayv1.HTTPRoute{
ObjectMeta: metav1.ObjectMeta{Name: "named-ports-example-com", Namespace: "test"},
Spec: gatewayv1.HTTPRouteSpec{
CommonRouteSpec: gatewayv1.CommonRouteSpec{
ParentRefs: []gatewayv1.ParentReference{{
Name: "named-ports",
}},
},
Hostnames: []gatewayv1.Hostname{"example.com"},
Rules: []gatewayv1.HTTPRouteRule{{
Matches: []gatewayv1.HTTPRouteMatch{{
Path: &gatewayv1.HTTPPathMatch{
Type: &gPathPrefix,
Value: PtrTo("/foo"),
},
}},
BackendRefs: []gatewayv1.HTTPBackendRef{},
}},
},
},
RuleBackendSources: [][]intermediate.BackendSource{{}},
},
},
},
expectedErrors: field.ErrorList{field.Invalid(field.NewPath(""), "", "")},
},
Expand Down
11 changes: 4 additions & 7 deletions pkg/i2gw/providers/gce/ir_converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,12 @@ func (c *resourcesToIRConverter) convertToIR(storage *storage) (intermediate.IR,

// Convert plain ingress resources to gateway resources, ignoring all
// provider-specific features.
// Continue processing even with errors to support best-effort conversion
ir, errs := common.ToIR(ingressList, storage.ServicePorts, c.implementationSpecificOptions)
if len(errs) > 0 {
return intermediate.IR{}, errs
}

errs = setGCEGatewayClasses(ingressList, ir.Gateways)
if len(errs) > 0 {
return intermediate.IR{}, errs
}
// Accumulate errors from setting GCE gateway classes but continue processing
setGCEErrs := setGCEGatewayClasses(ingressList, ir.Gateways)
errs = append(errs, setGCEErrs...)
buildGceGatewayIR(c.ctx, storage, &ir)
buildGceServiceIR(c.ctx, storage, &ir)
return ir, errs
Expand Down
3 changes: 0 additions & 3 deletions pkg/i2gw/providers/ingressnginx/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ func (c *resourcesToIRConverter) convert(storage *storage) (intermediate.IR, fie
// Convert plain ingress resources to gateway resources, ignoring all
// provider-specific features.
ir, errs := common.ToIR(ingressList, storage.ServicePorts, i2gw.ProviderImplementationSpecificOptions{})
if len(errs) > 0 {
return intermediate.IR{}, errs
}

for _, parseFeatureFunc := range c.featureParsers {
// Apply the feature parsing function to the gateway resources, one by one.
Expand Down
37 changes: 36 additions & 1 deletion pkg/i2gw/providers/ingressnginx/converter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,42 @@ func Test_ToIR(t *testing.T) {
},
},
},
expectedIR: intermediate.IR{},
expectedIR: intermediate.IR{
Gateways: map[types.NamespacedName]intermediate.GatewayContext{
{Namespace: "default", Name: "ingress-nginx"}: {
Gateway: gatewayv1.Gateway{
ObjectMeta: metav1.ObjectMeta{Name: "ingress-nginx", Namespace: "default"},
Spec: gatewayv1.GatewaySpec{
GatewayClassName: "ingress-nginx",
Listeners: []gatewayv1.Listener{{
Name: "test-mydomain-com-http",
Port: 80,
Protocol: gatewayv1.HTTPProtocolType,
Hostname: ptrTo(gatewayv1.Hostname("test.mydomain.com")),
}},
},
},
},
},
HTTPRoutes: map[types.NamespacedName]intermediate.HTTPRouteContext{
{Namespace: "default", Name: "implementation-specific-regex-test-mydomain-com"}: {
HTTPRoute: gatewayv1.HTTPRoute{
ObjectMeta: metav1.ObjectMeta{Name: "implementation-specific-regex-test-mydomain-com", Namespace: "default"},
Spec: gatewayv1.HTTPRouteSpec{
CommonRouteSpec: gatewayv1.CommonRouteSpec{
ParentRefs: []gatewayv1.ParentReference{{
Name: "ingress-nginx",
}},
},
Hostnames: []gatewayv1.Hostname{"test.mydomain.com"},
// Rules is empty because the path conversion failed
Rules: []gatewayv1.HTTPRouteRule{},
},
},
RuleBackendSources: [][]intermediate.BackendSource{},
},
},
},
expectedErrors: field.ErrorList{
{
Type: field.ErrorTypeInvalid,
Expand Down
16 changes: 4 additions & 12 deletions pkg/i2gw/providers/kong/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ func (c *resourcesToIRConverter) convert(storage *storage) (intermediate.IR, fie
// Convert plain ingress resources to gateway resources, ignoring all
// provider-specific features.
ir, errorList := common.ToIR(ingressList, storage.ServicePorts, c.implementationSpecificOptions)
if len(errorList) > 0 {
return intermediate.IR{}, errorList
}

tcpGatewayIR, notificationsAggregator, errs := crds.TCPIngressToGatewayIR(storage.TCPIngresses)
if len(errs) > 0 {
Expand All @@ -66,15 +63,10 @@ func (c *resourcesToIRConverter) convert(storage *storage) (intermediate.IR, fie

dispatchNotification(notificationsAggregator)

if len(errorList) > 0 {
return intermediate.IR{}, errorList
}

ir, errs = intermediate.MergeIRs(ir, tcpGatewayIR)

if len(errs) > 0 {
return intermediate.IR{}, errs
}
// Merge IRs and accumulate errors, continuing best-effort conversion
var mergeErrs field.ErrorList
ir, mergeErrs = intermediate.MergeIRs(ir, tcpGatewayIR)
errorList = append(errorList, mergeErrs...)

for _, parseFeatureFunc := range c.featureParsers {
// Apply the feature parsing function to the gateway resources, one by one.
Expand Down
3 changes: 0 additions & 3 deletions pkg/i2gw/providers/nginx/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@ func (c *resourcesToIRConverter) convert(storage *storage) (intermediate.IR, fie
}

ir, errorList := common.ToIR(ingressList, storage.ServicePorts, c.implementationSpecificOptions)
if len(errorList) > 0 {
return intermediate.IR{}, errorList
}

for _, parseFeatureFunc := range c.featureParsers {
errs := parseFeatureFunc(ingressList, storage.ServicePorts, &ir)
Expand Down