func()

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
}