Fix HostRegexp config for rule syntax v2
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
This commit is contained in:
parent
394f97bc48
commit
8a0c1e614f
4 changed files with 239 additions and 134 deletions
|
@ -297,6 +297,12 @@ func (c *Configuration) SetEffectiveConfiguration() {
|
||||||
c.Providers.KubernetesGateway.EntryPoints = entryPoints
|
c.Providers.KubernetesGateway.EntryPoints = entryPoints
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Defines the default rule syntax for the Kubernetes Ingress Provider.
|
||||||
|
// This allows the provider to adapt the matcher syntax to the desired rule syntax version.
|
||||||
|
if c.Core != nil && c.Providers.KubernetesIngress != nil {
|
||||||
|
c.Providers.KubernetesIngress.DefaultRuleSyntax = c.Core.DefaultRuleSyntax
|
||||||
|
}
|
||||||
|
|
||||||
c.initACMEProvider()
|
c.initACMEProvider()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
kind: Ingress
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: ""
|
||||||
|
namespace: testing
|
||||||
|
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: "*.foobar.com"
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /bar
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: service1
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
pathType: Prefix
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: service1
|
||||||
|
namespace: testing
|
||||||
|
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: EndpointSlice
|
||||||
|
apiVersion: discovery.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: service1-abc
|
||||||
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
|
- addresses:
|
||||||
|
- 10.10.0.1
|
||||||
|
conditions:
|
||||||
|
ready: true
|
|
@ -56,6 +56,9 @@ type Provider struct {
|
||||||
DisableClusterScopeResources bool `description:"Disables the lookup of cluster scope resources (incompatible with IngressClasses and NodePortLB enabled services)." json:"disableClusterScopeResources,omitempty" toml:"disableClusterScopeResources,omitempty" yaml:"disableClusterScopeResources,omitempty" export:"true"`
|
DisableClusterScopeResources bool `description:"Disables the lookup of cluster scope resources (incompatible with IngressClasses and NodePortLB enabled services)." json:"disableClusterScopeResources,omitempty" toml:"disableClusterScopeResources,omitempty" yaml:"disableClusterScopeResources,omitempty" export:"true"`
|
||||||
NativeLBByDefault bool `description:"Defines whether to use Native Kubernetes load-balancing mode by default." json:"nativeLBByDefault,omitempty" toml:"nativeLBByDefault,omitempty" yaml:"nativeLBByDefault,omitempty" export:"true"`
|
NativeLBByDefault bool `description:"Defines whether to use Native Kubernetes load-balancing mode by default." json:"nativeLBByDefault,omitempty" toml:"nativeLBByDefault,omitempty" yaml:"nativeLBByDefault,omitempty" export:"true"`
|
||||||
|
|
||||||
|
// The default rule syntax is initialized with the configuration defined by the user with the core.DefaultRuleSyntax option.
|
||||||
|
DefaultRuleSyntax string `json:"-" toml:"-" yaml:"-" label:"-" file:"-"`
|
||||||
|
|
||||||
lastConfiguration safe.Safe
|
lastConfiguration safe.Safe
|
||||||
|
|
||||||
routerTransform k8s.RouterTransform
|
routerTransform k8s.RouterTransform
|
||||||
|
@ -336,7 +339,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
|
||||||
serviceName := provider.Normalize(ingress.Namespace + "-" + pa.Backend.Service.Name + "-" + portString)
|
serviceName := provider.Normalize(ingress.Namespace + "-" + pa.Backend.Service.Name + "-" + portString)
|
||||||
conf.HTTP.Services[serviceName] = service
|
conf.HTTP.Services[serviceName] = service
|
||||||
|
|
||||||
rt := loadRouter(rule, pa, rtConfig, serviceName)
|
rt := p.loadRouter(rule, pa, rtConfig, serviceName)
|
||||||
|
|
||||||
p.applyRouterTransform(ctxIngress, rt, ingress)
|
p.applyRouterTransform(ctxIngress, rt, ingress)
|
||||||
|
|
||||||
|
@ -432,100 +435,6 @@ func (p *Provider) shouldProcessIngress(ingress *netv1.Ingress, ingressClasses [
|
||||||
len(p.IngressClass) == 0 && ingress.Annotations[annotationKubernetesIngressClass] == traefikDefaultIngressClass
|
len(p.IngressClass) == 0 && ingress.Annotations[annotationKubernetesIngressClass] == traefikDefaultIngressClass
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildHostRule(host string) string {
|
|
||||||
if strings.HasPrefix(host, "*.") {
|
|
||||||
host = strings.Replace(regexp.QuoteMeta(host), `\*\.`, `[a-zA-Z0-9-]+\.`, 1)
|
|
||||||
return fmt.Sprintf("HostRegexp(`^%s$`)", host)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("Host(`%s`)", host)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCertificates(ctx context.Context, ingress *netv1.Ingress, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error {
|
|
||||||
for _, t := range ingress.Spec.TLS {
|
|
||||||
if t.SecretName == "" {
|
|
||||||
log.Ctx(ctx).Debug().Msg("Skipping TLS sub-section: No secret name provided")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
configKey := ingress.Namespace + "-" + t.SecretName
|
|
||||||
if _, tlsExists := tlsConfigs[configKey]; !tlsExists {
|
|
||||||
secret, exists, err := k8sClient.GetSecret(ingress.Namespace, t.SecretName)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to fetch secret %s/%s: %w", ingress.Namespace, t.SecretName, err)
|
|
||||||
}
|
|
||||||
if !exists {
|
|
||||||
return fmt.Errorf("secret %s/%s does not exist", ingress.Namespace, t.SecretName)
|
|
||||||
}
|
|
||||||
|
|
||||||
cert, key, err := getCertificateBlocks(secret, ingress.Namespace, t.SecretName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsConfigs[configKey] = &tls.CertAndStores{
|
|
||||||
Certificate: tls.Certificate{
|
|
||||||
CertFile: types.FileOrContent(cert),
|
|
||||||
KeyFile: types.FileOrContent(key),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCertificateBlocks(secret *corev1.Secret, namespace, secretName string) (string, string, error) {
|
|
||||||
var missingEntries []string
|
|
||||||
|
|
||||||
tlsCrtData, tlsCrtExists := secret.Data["tls.crt"]
|
|
||||||
if !tlsCrtExists {
|
|
||||||
missingEntries = append(missingEntries, "tls.crt")
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsKeyData, tlsKeyExists := secret.Data["tls.key"]
|
|
||||||
if !tlsKeyExists {
|
|
||||||
missingEntries = append(missingEntries, "tls.key")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(missingEntries) > 0 {
|
|
||||||
return "", "", fmt.Errorf("secret %s/%s is missing the following TLS data entries: %s",
|
|
||||||
namespace, secretName, strings.Join(missingEntries, ", "))
|
|
||||||
}
|
|
||||||
|
|
||||||
cert := string(tlsCrtData)
|
|
||||||
if cert == "" {
|
|
||||||
missingEntries = append(missingEntries, "tls.crt")
|
|
||||||
}
|
|
||||||
|
|
||||||
key := string(tlsKeyData)
|
|
||||||
if key == "" {
|
|
||||||
missingEntries = append(missingEntries, "tls.key")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(missingEntries) > 0 {
|
|
||||||
return "", "", fmt.Errorf("secret %s/%s contains the following empty TLS data entries: %s",
|
|
||||||
namespace, secretName, strings.Join(missingEntries, ", "))
|
|
||||||
}
|
|
||||||
|
|
||||||
return cert, key, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTLSConfig(tlsConfigs map[string]*tls.CertAndStores) []*tls.CertAndStores {
|
|
||||||
var secretNames []string
|
|
||||||
for secretName := range tlsConfigs {
|
|
||||||
secretNames = append(secretNames, secretName)
|
|
||||||
}
|
|
||||||
sort.Strings(secretNames)
|
|
||||||
|
|
||||||
var configs []*tls.CertAndStores
|
|
||||||
for _, secretName := range secretNames {
|
|
||||||
configs = append(configs, tlsConfigs[secretName])
|
|
||||||
}
|
|
||||||
|
|
||||||
return configs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) loadService(client Client, namespace string, backend netv1.IngressBackend) (*dynamic.Service, error) {
|
func (p *Provider) loadService(client Client, namespace string, backend netv1.IngressBackend) (*dynamic.Service, error) {
|
||||||
if backend.Resource != nil {
|
if backend.Resource != nil {
|
||||||
// https://kubernetes.io/docs/concepts/services-networking/ingress/#resource-backend
|
// https://kubernetes.io/docs/concepts/services-networking/ingress/#resource-backend
|
||||||
|
@ -698,6 +607,152 @@ func (p *Provider) loadService(client Client, namespace string, backend netv1.In
|
||||||
return svc, nil
|
return svc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) loadRouter(rule netv1.IngressRule, pa netv1.HTTPIngressPath, rtConfig *RouterConfig, serviceName string) *dynamic.Router {
|
||||||
|
rt := &dynamic.Router{
|
||||||
|
Service: serviceName,
|
||||||
|
}
|
||||||
|
|
||||||
|
if rtConfig != nil && rtConfig.Router != nil {
|
||||||
|
rt.RuleSyntax = rtConfig.Router.RuleSyntax
|
||||||
|
rt.Priority = rtConfig.Router.Priority
|
||||||
|
rt.EntryPoints = rtConfig.Router.EntryPoints
|
||||||
|
rt.Middlewares = rtConfig.Router.Middlewares
|
||||||
|
|
||||||
|
if rtConfig.Router.TLS != nil {
|
||||||
|
rt.TLS = rtConfig.Router.TLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rules []string
|
||||||
|
if len(rule.Host) > 0 {
|
||||||
|
if rt.RuleSyntax == "v2" || (rt.RuleSyntax == "" && p.DefaultRuleSyntax == "v2") {
|
||||||
|
rules = append(rules, buildHostRuleV2(rule.Host))
|
||||||
|
} else {
|
||||||
|
rules = append(rules, buildHostRule(rule.Host))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(pa.Path) > 0 {
|
||||||
|
matcher := defaultPathMatcher
|
||||||
|
|
||||||
|
if pa.PathType == nil || *pa.PathType == "" || *pa.PathType == netv1.PathTypeImplementationSpecific {
|
||||||
|
if rtConfig != nil && rtConfig.Router != nil && rtConfig.Router.PathMatcher != "" {
|
||||||
|
matcher = rtConfig.Router.PathMatcher
|
||||||
|
}
|
||||||
|
} else if *pa.PathType == netv1.PathTypeExact {
|
||||||
|
matcher = "Path"
|
||||||
|
}
|
||||||
|
|
||||||
|
rules = append(rules, fmt.Sprintf("%s(`%s`)", matcher, pa.Path))
|
||||||
|
}
|
||||||
|
|
||||||
|
rt.Rule = strings.Join(rules, " && ")
|
||||||
|
return rt
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildHostRuleV2(host string) string {
|
||||||
|
if strings.HasPrefix(host, "*.") {
|
||||||
|
host = strings.Replace(host, "*.", "{subdomain:[a-zA-Z0-9-]+}.", 1)
|
||||||
|
return fmt.Sprintf("HostRegexp(`%s`)", host)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Host(`%s`)", host)
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildHostRule(host string) string {
|
||||||
|
if strings.HasPrefix(host, "*.") {
|
||||||
|
host = strings.Replace(regexp.QuoteMeta(host), `\*\.`, `[a-zA-Z0-9-]+\.`, 1)
|
||||||
|
return fmt.Sprintf("HostRegexp(`^%s$`)", host)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Host(`%s`)", host)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCertificates(ctx context.Context, ingress *netv1.Ingress, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error {
|
||||||
|
for _, t := range ingress.Spec.TLS {
|
||||||
|
if t.SecretName == "" {
|
||||||
|
log.Ctx(ctx).Debug().Msg("Skipping TLS sub-section: No secret name provided")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
configKey := ingress.Namespace + "-" + t.SecretName
|
||||||
|
if _, tlsExists := tlsConfigs[configKey]; !tlsExists {
|
||||||
|
secret, exists, err := k8sClient.GetSecret(ingress.Namespace, t.SecretName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to fetch secret %s/%s: %w", ingress.Namespace, t.SecretName, err)
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("secret %s/%s does not exist", ingress.Namespace, t.SecretName)
|
||||||
|
}
|
||||||
|
|
||||||
|
cert, key, err := getCertificateBlocks(secret, ingress.Namespace, t.SecretName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfigs[configKey] = &tls.CertAndStores{
|
||||||
|
Certificate: tls.Certificate{
|
||||||
|
CertFile: types.FileOrContent(cert),
|
||||||
|
KeyFile: types.FileOrContent(key),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCertificateBlocks(secret *corev1.Secret, namespace, secretName string) (string, string, error) {
|
||||||
|
var missingEntries []string
|
||||||
|
|
||||||
|
tlsCrtData, tlsCrtExists := secret.Data["tls.crt"]
|
||||||
|
if !tlsCrtExists {
|
||||||
|
missingEntries = append(missingEntries, "tls.crt")
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsKeyData, tlsKeyExists := secret.Data["tls.key"]
|
||||||
|
if !tlsKeyExists {
|
||||||
|
missingEntries = append(missingEntries, "tls.key")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(missingEntries) > 0 {
|
||||||
|
return "", "", fmt.Errorf("secret %s/%s is missing the following TLS data entries: %s",
|
||||||
|
namespace, secretName, strings.Join(missingEntries, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
cert := string(tlsCrtData)
|
||||||
|
if cert == "" {
|
||||||
|
missingEntries = append(missingEntries, "tls.crt")
|
||||||
|
}
|
||||||
|
|
||||||
|
key := string(tlsKeyData)
|
||||||
|
if key == "" {
|
||||||
|
missingEntries = append(missingEntries, "tls.key")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(missingEntries) > 0 {
|
||||||
|
return "", "", fmt.Errorf("secret %s/%s contains the following empty TLS data entries: %s",
|
||||||
|
namespace, secretName, strings.Join(missingEntries, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
return cert, key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTLSConfig(tlsConfigs map[string]*tls.CertAndStores) []*tls.CertAndStores {
|
||||||
|
var secretNames []string
|
||||||
|
for secretName := range tlsConfigs {
|
||||||
|
secretNames = append(secretNames, secretName)
|
||||||
|
}
|
||||||
|
sort.Strings(secretNames)
|
||||||
|
|
||||||
|
var configs []*tls.CertAndStores
|
||||||
|
for _, secretName := range secretNames {
|
||||||
|
configs = append(configs, tlsConfigs[secretName])
|
||||||
|
}
|
||||||
|
|
||||||
|
return configs
|
||||||
|
}
|
||||||
|
|
||||||
func getNativeServiceAddress(service corev1.Service, svcPort corev1.ServicePort) (string, error) {
|
func getNativeServiceAddress(service corev1.Service, svcPort corev1.ServicePort) (string, error) {
|
||||||
if service.Spec.ClusterIP == "None" {
|
if service.Spec.ClusterIP == "None" {
|
||||||
return "", fmt.Errorf("no clusterIP on headless service: %s/%s", service.Namespace, service.Name)
|
return "", fmt.Errorf("no clusterIP on headless service: %s/%s", service.Namespace, service.Name)
|
||||||
|
@ -734,45 +789,6 @@ func makeRouterKeyWithHash(key, rule string) (string, error) {
|
||||||
return dupKey, nil
|
return dupKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadRouter(rule netv1.IngressRule, pa netv1.HTTPIngressPath, rtConfig *RouterConfig, serviceName string) *dynamic.Router {
|
|
||||||
var rules []string
|
|
||||||
if len(rule.Host) > 0 {
|
|
||||||
rules = []string{buildHostRule(rule.Host)}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(pa.Path) > 0 {
|
|
||||||
matcher := defaultPathMatcher
|
|
||||||
|
|
||||||
if pa.PathType == nil || *pa.PathType == "" || *pa.PathType == netv1.PathTypeImplementationSpecific {
|
|
||||||
if rtConfig != nil && rtConfig.Router != nil && rtConfig.Router.PathMatcher != "" {
|
|
||||||
matcher = rtConfig.Router.PathMatcher
|
|
||||||
}
|
|
||||||
} else if *pa.PathType == netv1.PathTypeExact {
|
|
||||||
matcher = "Path"
|
|
||||||
}
|
|
||||||
|
|
||||||
rules = append(rules, fmt.Sprintf("%s(`%s`)", matcher, pa.Path))
|
|
||||||
}
|
|
||||||
|
|
||||||
rt := &dynamic.Router{
|
|
||||||
Rule: strings.Join(rules, " && "),
|
|
||||||
Service: serviceName,
|
|
||||||
}
|
|
||||||
|
|
||||||
if rtConfig != nil && rtConfig.Router != nil {
|
|
||||||
rt.RuleSyntax = rtConfig.Router.RuleSyntax
|
|
||||||
rt.Priority = rtConfig.Router.Priority
|
|
||||||
rt.EntryPoints = rtConfig.Router.EntryPoints
|
|
||||||
rt.Middlewares = rtConfig.Router.Middlewares
|
|
||||||
|
|
||||||
if rtConfig.Router.TLS != nil {
|
|
||||||
rt.TLS = rtConfig.Router.TLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rt
|
|
||||||
}
|
|
||||||
|
|
||||||
func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *safe.Pool, eventsChan <-chan interface{}) chan interface{} {
|
func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *safe.Pool, eventsChan <-chan interface{}) chan interface{} {
|
||||||
if throttleDuration == 0 {
|
if throttleDuration == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -32,6 +32,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
allowEmptyServices bool
|
allowEmptyServices bool
|
||||||
disableIngressClassLookup bool
|
disableIngressClassLookup bool
|
||||||
disableClusterScopeResources bool
|
disableClusterScopeResources bool
|
||||||
|
defaultRuleSyntax string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "Empty ingresses",
|
desc: "Empty ingresses",
|
||||||
|
@ -1096,6 +1097,38 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Ingress with wildcard host syntax v2",
|
||||||
|
defaultRuleSyntax: "v2",
|
||||||
|
expected: &dynamic.Configuration{
|
||||||
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
|
Routers: map[string]*dynamic.Router{
|
||||||
|
"testing-foobar-com-bar": {
|
||||||
|
Rule: "HostRegexp(`{subdomain:[a-zA-Z0-9-]+}.foobar.com`) && PathPrefix(`/bar`)",
|
||||||
|
Service: "testing-service1-80",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Services: map[string]*dynamic.Service{
|
||||||
|
"testing-service1-80": {
|
||||||
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
|
PassHostHeader: pointer(true),
|
||||||
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
|
},
|
||||||
|
Servers: []dynamic.Server{
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.1:8080",
|
||||||
|
Scheme: "",
|
||||||
|
Port: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "Ingress with multiple ingressClasses",
|
desc: "Ingress with multiple ingressClasses",
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
|
@ -1505,6 +1538,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
AllowEmptyServices: test.allowEmptyServices,
|
AllowEmptyServices: test.allowEmptyServices,
|
||||||
DisableIngressClassLookup: test.disableIngressClassLookup,
|
DisableIngressClassLookup: test.disableIngressClassLookup,
|
||||||
DisableClusterScopeResources: test.disableClusterScopeResources,
|
DisableClusterScopeResources: test.disableClusterScopeResources,
|
||||||
|
DefaultRuleSyntax: test.defaultRuleSyntax,
|
||||||
}
|
}
|
||||||
conf := p.loadConfigurationFromIngresses(context.Background(), clientMock)
|
conf := p.loadConfigurationFromIngresses(context.Background(), clientMock)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue