in pkg/ingress/kube/kingress/controller.go [438:566]
func (c *controller) ConvertHTTPRoute(convertOptions *common.ConvertOptions, wrapper *common.WrapperConfig) error {
if convertOptions == nil {
return fmt.Errorf("convertOptions is nil")
}
if wrapper == nil {
return fmt.Errorf("wrapperConfig is nil")
}
cfg := wrapper.Config
KingressV1, ok := cfg.Spec.(ingress.IngressSpec)
if !ok {
common.IncrementInvalidIngress(c.options.ClusterId, common.Unknown)
return fmt.Errorf("convert type is invalid in cluster %s", c.options.ClusterId)
}
if len(KingressV1.Rules) == 0 {
common.IncrementInvalidIngress(c.options.ClusterId, common.EmptyRule)
return fmt.Errorf("invalid ingress rule %s:%s in cluster %s, `rules` must be specified", cfg.Namespace, cfg.Name, c.options.ClusterId)
}
convertOptions.HasDefaultBackend = false
// In one ingress, we will limit the rule conflict.
// When the host, pathType, path of two rule are same, we think there is a conflict event.
definedRules := sets.New[string]()
var (
// But in across ingresses case, we will restrict this limit.
// When the {host, path, headers, method, params} of two rule in different ingress are same, we think there is a conflict event.
tempRuleKey []string
)
for _, rule := range KingressV1.Rules {
for _, rulehost := range rule.Hosts {
if rule.HTTP == nil || len(rule.HTTP.Paths) == 0 {
IngressLog.Warnf("invalid ingress rule %s:%s for host %q in cluster %s, no paths defined", cfg.Namespace, cfg.Name, rulehost, c.options.ClusterId)
continue
}
wrapperVS, exist := convertOptions.VirtualServices[rulehost]
if !exist {
wrapperVS = &common.WrapperVirtualService{
VirtualService: &networking.VirtualService{
Hosts: []string{rulehost},
},
WrapperConfig: wrapper,
}
convertOptions.VirtualServices[rulehost] = wrapperVS
}
wrapperHttpRoutes := make([]*common.WrapperHTTPRoute, 0, len(rule.HTTP.Paths))
for _, httpPath := range rule.HTTP.Paths {
wrapperHttpRoute := &common.WrapperHTTPRoute{
HTTPRoute: &networking.HTTPRoute{},
WrapperConfig: wrapper,
Host: rulehost,
ClusterId: c.options.ClusterId,
}
var pathType common.PathType
originPath := httpPath.Path
pathType = common.Prefix
wrapperHttpRoute.OriginPath = originPath
wrapperHttpRoute.OriginPathType = pathType
wrapperHttpRoute.HTTPRoute = resources.MakeVirtualServiceRoute(transformHosts(rulehost), &httpPath)
wrapperHttpRoute.HTTPRoute.Name = common.GenerateUniqueRouteName(c.options.SystemNamespace, wrapperHttpRoute)
ingressRouteBuilder := convertOptions.IngressRouteCache.New(wrapperHttpRoute)
hostAndPath := wrapperHttpRoute.PathFormat()
key := createRuleKey(cfg.Annotations, hostAndPath)
wrapperHttpRoute.RuleKey = key
if WrapPreIngress, exist := convertOptions.Route2Ingress[key]; exist {
ingressRouteBuilder.PreIngress = WrapPreIngress.Config
ingressRouteBuilder.Event = common.DuplicatedRoute
}
tempRuleKey = append(tempRuleKey, key)
// Two duplicated rules in the same ingress.
if ingressRouteBuilder.Event == common.Normal {
pathFormat := wrapperHttpRoute.PathFormat()
if definedRules.Contains(pathFormat) {
ingressRouteBuilder.PreIngress = cfg
ingressRouteBuilder.Event = common.DuplicatedRoute
}
definedRules.Insert(pathFormat)
}
// backend service check
var event common.Event
destinationConfig := wrapper.AnnotationsConfig.Destination
event = c.IngressRouteBuilderServicesCheck(&httpPath, cfg.Namespace, ingressRouteBuilder, destinationConfig)
if destinationConfig != nil {
wrapperHttpRoute.WeightTotal = int32(destinationConfig.WeightSum)
}
if ingressRouteBuilder.Event != common.Normal {
event = ingressRouteBuilder.Event
}
if event != common.Normal {
common.IncrementInvalidIngress(c.options.ClusterId, event)
ingressRouteBuilder.Event = event
} else {
wrapperHttpRoutes = append(wrapperHttpRoutes, wrapperHttpRoute)
}
convertOptions.IngressRouteCache.Add(ingressRouteBuilder)
}
for idx, item := range tempRuleKey {
if val, exist := convertOptions.Route2Ingress[item]; !exist || strings.Compare(val.RuleKey, tempRuleKey[idx]) != 0 {
convertOptions.Route2Ingress[item] = &common.WrapperConfigWithRuleKey{
Config: cfg,
RuleKey: tempRuleKey[idx],
}
}
}
old, f := convertOptions.HTTPRoutes[rulehost]
if f {
old = append(old, wrapperHttpRoutes...)
convertOptions.HTTPRoutes[rulehost] = old
} else {
convertOptions.HTTPRoutes[rulehost] = wrapperHttpRoutes
}
// Sort, exact -> prefix -> regex
routes := convertOptions.HTTPRoutes[rulehost]
IngressLog.Debugf("routes of host %s is %v", rulehost, routes)
common.SortHTTPRoutes(routes)
}
}
return nil
}