Skip to content
Merged
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
13 changes: 7 additions & 6 deletions pkg/gateway/model/model_build_listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,18 +188,19 @@ func (l listenerBuilderImpl) buildListenerRules(stack core.Stack, ls *elbv2model

var albRules []elbv2model.Rule
for _, ruleWithPrecedence := range rulesWithPrecedenceOrder {
route := ruleWithPrecedence.RouteDescriptor
rule := ruleWithPrecedence.Rule
route := ruleWithPrecedence.CommonRulePrecedence.RouteDescriptor
rule := ruleWithPrecedence.CommonRulePrecedence.Rule

var conditionsList []elbv2model.RuleCondition
var err error
switch route.GetRouteKind() {
case routeutils.HTTPRouteKind:
conditionsList, err = routeutils.BuildHttpRuleConditions(ruleWithPrecedence)
if err != nil {
return err
}
// TODO: add case for GRPC
case routeutils.GRPCRouteKind:
conditionsList, err = routeutils.BuildGrpcRuleConditions(ruleWithPrecedence)
}
if err != nil {
return err
}
tags, tagsErr := l.tagHelper.getGatewayTags(lbCfg)
if tagsErr != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/gateway/model/model_build_target_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ func (builder *targetGroupBuilderImpl) buildTargetGroupSpec(gw *gwv1.Gateway, ro
if targetType == elbv2model.TargetTypeIP {
return elbv2model.TargetGroupSpec{}, errors.Errorf("TargetGroup port is empty. Are you using the correct service type?")
}
return elbv2model.TargetGroupSpec{}, errors.Errorf("TargetGroup port is empty. When using Instance targets, your service be must of type 'NodePort' or 'LoadBalancer'")
return elbv2model.TargetGroupSpec{}, errors.Errorf("TargetGroup port is empty. When using Instance targets, your service must be of type 'NodePort' or 'LoadBalancer'")
}
return elbv2model.TargetGroupSpec{
Name: name,
Expand Down
2 changes: 1 addition & 1 deletion pkg/gateway/routeutils/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@ var defaultProtocolToRouteKindMap = map[gwv1.ProtocolType][]RouteKind{
gwv1.UDPProtocolType: {UDPRouteKind},
gwv1.TLSProtocolType: {TLSRouteKind, TCPRouteKind},
gwv1.HTTPProtocolType: {HTTPRouteKind},
gwv1.HTTPSProtocolType: {HTTPRouteKind},
gwv1.HTTPSProtocolType: {HTTPRouteKind, GRPCRouteKind},
}
96 changes: 92 additions & 4 deletions pkg/gateway/routeutils/route_rule_condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
// BuildHttpRuleConditions each match will be mapped to a ruleCondition, conditions within same match will be ANDed
func BuildHttpRuleConditions(rule RulePrecedence) ([]elbv2model.RuleCondition, error) {
match := rule.HTTPMatch
hostnamesStringList := rule.Hostnames
hostnamesStringList := rule.CommonRulePrecedence.Hostnames
var conditions []elbv2model.RuleCondition
if hostnamesStringList != nil && len(hostnamesStringList) > 0 {
conditions = append(conditions, elbv2model.RuleCondition{
Expand Down Expand Up @@ -141,12 +141,100 @@ func buildHttpMethodCondition(method *gwv1.HTTPMethod) []elbv2model.RuleConditio
}
}

// TODO: implement it for GRPCRoute
func buildGrpcRouteRuleConditions(matches RouteRule) ([][]elbv2model.RuleCondition, error) {
var conditions [][]elbv2model.RuleCondition
func BuildGrpcRuleConditions(rule RulePrecedence) ([]elbv2model.RuleCondition, error) {
// handle host header
hostnamesStringList := rule.CommonRulePrecedence.Hostnames
var conditions []elbv2model.RuleCondition
if hostnamesStringList != nil && len(hostnamesStringList) > 0 {
conditions = append(conditions, elbv2model.RuleCondition{
Field: elbv2model.RuleConditionFieldHostHeader,
HostHeaderConfig: &elbv2model.HostHeaderConditionConfig{
Values: hostnamesStringList,
},
})
}

match := rule.GRPCMatch

if match == nil {
// If Method field is not specified, all services and methods will match.
conditions = append(conditions, elbv2model.RuleCondition{
Field: elbv2model.RuleConditionFieldPathPattern,
PathPatternConfig: &elbv2model.PathPatternConditionConfig{
Values: []string{"/*"},
},
})
return conditions, nil
}

// handle method match
if match.Method == nil {
conditions = append(conditions, elbv2model.RuleCondition{
Field: elbv2model.RuleConditionFieldPathPattern,
PathPatternConfig: &elbv2model.PathPatternConditionConfig{
Values: []string{"/*"},
},
})
} else {
methodCondition, err := buildGrpcMethodCondition(match.Method)
if err != nil {
return nil, err
}
conditions = append(conditions, methodCondition...)
}

// handle header match
if match.Headers != nil && len(match.Headers) > 0 {
headerConditions := buildGrpcHeaderCondition(match.Headers)
conditions = append(conditions, headerConditions...)
}

return conditions, nil
}

func buildGrpcHeaderCondition(headers []gwv1.GRPCHeaderMatch) []elbv2model.RuleCondition {
var conditions []elbv2model.RuleCondition
for _, header := range headers {
headerCondition := []elbv2model.RuleCondition{
{
Field: elbv2model.RuleConditionFieldHTTPHeader,
HTTPHeaderConfig: &elbv2model.HTTPHeaderConditionConfig{
HTTPHeaderName: string(header.Name),
// for a given HTTPHeaderName, ALB rule can accept a list of values. However, gateway route headers only accept one value per name, and name cannot duplicate.
Values: []string{header.Value},
},
},
}
conditions = append(conditions, headerCondition...)
}
return conditions
}

// buildGrpcMethodCondition - we handle regex and exact type in same way since regex is taken as-is
// Exact method type will not accept wildcards - this is checked by kubebuilder validation
// Regular expression method type only works with wildcard * and ? for now
func buildGrpcMethodCondition(method *gwv1.GRPCMethodMatch) ([]elbv2model.RuleCondition, error) {
var pathValue string
if method.Service != nil && method.Method != nil {
pathValue = fmt.Sprintf("/%s/%s", *method.Service, *method.Method)
} else if method.Service != nil {
pathValue = fmt.Sprintf("/%s/*", *method.Service)
} else if method.Method != nil {
pathValue = fmt.Sprintf("/*/%s", *method.Method)
} else {
return nil, errors.Errorf("Invalid grpc method match: %v", method)
}

return []elbv2model.RuleCondition{
{
Field: elbv2model.RuleConditionFieldPathPattern,
PathPatternConfig: &elbv2model.PathPatternConditionConfig{
Values: []string{pathValue},
},
},
}, nil
}

// BuildHttpRuleActionsBasedOnFilter only request redirect is supported, header modification is limited due to ALB support level.
func BuildHttpRuleActionsBasedOnFilter(filters []gwv1.HTTPRouteFilter) ([]elbv2model.Action, error) {
for _, filter := range filters {
Expand Down
Loading
Loading