func()

in pkg/ingress/kube/ingressv1/controller.go [339:476]


func (c *controller) ConvertGateway(convertOptions *common.ConvertOptions, wrapper *common.WrapperConfig, httpsCredentialConfig *cert.Config) error {
	// Ignore canary config.
	if wrapper.AnnotationsConfig.IsCanary() {
		return nil
	}

	cfg := wrapper.Config
	ingressV1, 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(ingressV1.Rules) == 0 && ingressV1.DefaultBackend == nil {
		common.IncrementInvalidIngress(c.options.ClusterId, common.EmptyRule)
		return fmt.Errorf("invalid ingress rule %s:%s in cluster %s, either `defaultBackend` or `rules` must be specified", cfg.Namespace, cfg.Name, c.options.ClusterId)
	}

	for _, rule := range ingressV1.Rules {
		// Need create builder for every rule.
		domainBuilder := &common.IngressDomainBuilder{
			ClusterId: c.options.ClusterId,
			Protocol:  common.HTTP,
			Host:      rule.Host,
			Ingress:   cfg,
			Event:     common.Normal,
		}

		// Extract the previous gateway and builder
		wrapperGateway, exist := convertOptions.Gateways[rule.Host]
		preDomainBuilder, _ := convertOptions.IngressDomainCache.Valid[rule.Host]
		if !exist {
			wrapperGateway = &common.WrapperGateway{
				Gateway:       &networking.Gateway{},
				WrapperConfig: wrapper,
				ClusterId:     c.options.ClusterId,
				Host:          rule.Host,
			}
			if c.options.GatewaySelectorKey != "" {
				wrapperGateway.Gateway.Selector = map[string]string{c.options.GatewaySelectorKey: c.options.GatewaySelectorValue}

			}
			wrapperGateway.Gateway.Servers = append(wrapperGateway.Gateway.Servers, &networking.Server{
				Port: &networking.Port{
					Number:   c.options.GatewayHttpPort,
					Protocol: string(protocol.HTTP),
					Name:     common.CreateConvertedName("http-"+strconv.FormatUint(uint64(c.options.GatewayHttpPort), 10)+"-ingress", string(c.options.ClusterId)),
				},
				Hosts: []string{rule.Host},
			})

			// Add new gateway, builder
			convertOptions.Gateways[rule.Host] = wrapperGateway
			convertOptions.IngressDomainCache.Valid[rule.Host] = domainBuilder
		} else {
			// Fallback to get downstream tls from current ingress.
			if wrapperGateway.WrapperConfig.AnnotationsConfig.DownstreamTLS == nil {
				wrapperGateway.WrapperConfig.AnnotationsConfig.DownstreamTLS = wrapper.AnnotationsConfig.DownstreamTLS
			}
		}

		// There are no tls settings, so just skip.
		if len(ingressV1.TLS) == 0 {
			continue
		}

		// Get tls secret matching the rule host
		secretName := extractTLSSecretName(rule.Host, ingressV1.TLS)
		secretNamespace := cfg.Namespace
		if secretName != "" {
			if httpsCredentialConfig != nil && httpsCredentialConfig.FallbackForInvalidSecret {
				_, err := c.secretController.Lister().Secrets(secretNamespace).Get(secretName)
				if err != nil {
					if k8serrors.IsNotFound(err) {
						// If there is no matching secret, try to get it from configmap.
						matchSecretName := httpsCredentialConfig.MatchSecretNameByDomain(rule.Host)
						if matchSecretName != "" {
							namespace, secret := cert.ParseTLSSecret(matchSecretName)
							if namespace == "" {
								secretNamespace = c.options.SystemNamespace
							} else {
								secretNamespace = namespace
							}
							secretName = secret
						}
					}
				}
			}
		} else {
			// If there is no matching secret, try to get it from configmap.
			if httpsCredentialConfig != nil {
				secretName = httpsCredentialConfig.MatchSecretNameByDomain(rule.Host)
				secretNamespace = c.options.SystemNamespace
				namespace, secret := cert.ParseTLSSecret(secretName)
				if namespace != "" {
					secretNamespace = namespace
					secretName = secret
				}
			}
		}

		if secretName == "" {
			// There no matching secret, so just skip.
			continue
		}

		domainBuilder.Protocol = common.HTTPS
		domainBuilder.SecretName = path.Join(c.options.ClusterId.String(), cfg.Namespace, secretName)

		// There is a matching secret and the gateway has already a tls secret.
		// We should report the duplicated tls secret event.
		if wrapperGateway.IsHTTPS() {
			domainBuilder.Event = common.DuplicatedTls
			domainBuilder.PreIngress = preDomainBuilder.Ingress
			convertOptions.IngressDomainCache.Invalid = append(convertOptions.IngressDomainCache.Invalid,
				domainBuilder.Build())
			continue
		}

		// Append https server
		wrapperGateway.Gateway.Servers = append(wrapperGateway.Gateway.Servers, &networking.Server{
			Port: &networking.Port{
				Number:   uint32(c.options.GatewayHttpsPort),
				Protocol: string(protocol.HTTPS),
				Name:     common.CreateConvertedName("https-"+strconv.FormatUint(uint64(c.options.GatewayHttpsPort), 10)+"-ingress", string(c.options.ClusterId)),
			},
			Hosts: []string{rule.Host},
			Tls: &networking.ServerTLSSettings{
				Mode:           networking.ServerTLSSettings_SIMPLE,
				CredentialName: credentials.ToKubernetesIngressResource(c.options.RawClusterId, secretNamespace, secretName),
			},
		})

		// Update domain builder
		convertOptions.IngressDomainCache.Valid[rule.Host] = domainBuilder
	}

	return nil
}