Allow to disable Kubernetes cluster scope resources discovery

Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
This commit is contained in:
Romain 2024-08-01 15:50:04 +02:00 committed by GitHub
parent 930f84850b
commit a50345bf8d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 349 additions and 153 deletions

View file

@ -455,7 +455,7 @@ To enable HTTP/3 on an EntryPoint, please check out the [HTTP/3 configuration](.
In `v2.6`, the [Kubernetes Gateway API provider](../providers/kubernetes-gateway.md) now only supports the version [v1alpha2](https://gateway-api.sigs.k8s.io/v1alpha2/guides/) of the specification and In `v2.6`, the [Kubernetes Gateway API provider](../providers/kubernetes-gateway.md) now only supports the version [v1alpha2](https://gateway-api.sigs.k8s.io/v1alpha2/guides/) of the specification and
[route namespaces](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.RouteNamespaces) selectors, which requires Traefik to fetch and watch the cluster namespaces. [route namespaces](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.RouteNamespaces) selectors, which requires Traefik to fetch and watch the cluster namespaces.
Therefore, the [RBAC](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) and [CRD](../reference/dynamic-configuration/kubernetes-gateway.md#definitions) definitions must be updated. Therefore, the RBAC and CRD definitions must be updated.
## v2.6.0 to v2.6.1 ## v2.6.0 to v2.6.1

View file

@ -10,9 +10,11 @@ description: "Learn the steps needed to migrate to new Traefik Proxy v3 versions
### Kubernetes Provider RBACs ### Kubernetes Provider RBACs
Starting with v3.1, the Kubernetes Providers now use the [EndpointSlices API](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/) (Kubernetes >=v1.21) to discover service endpoint addresses. Starting with v3.1, the Kubernetes Providers now use the [EndpointSlices API](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/) (Kubernetes >=v1.21) to discover service endpoint addresses.
It also brings NodePort load-balancing which requires Nodes resources lookup.
Therefore, in the corresponding RBACs (see [KubernetesIngress](../routing/providers/kubernetes-ingress.md#configuration-example), [KubernetesCRD](../reference/dynamic-configuration/kubernetes-crd.md#rbac), and [KubernetesGateway](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) provider RBACs), Therefore, in the corresponding RBACs (see [KubernetesIngress](../routing/providers/kubernetes-ingress.md#configuration-example), [KubernetesCRD](../reference/dynamic-configuration/kubernetes-crd.md#rbac), and [KubernetesGateway](../reference/dynamic-configuration/kubernetes-gateway-rbac.yml) provider RBACs):
the `endpoints` right has to be removed and the following `endpointslices` right has to be added.
- the `endpoints` right has to be removed and the following `endpointslices` right has to be added:
```yaml ```yaml
... ...
@ -26,6 +28,21 @@ the `endpoints` right has to be removed and the following `endpointslices` right
... ...
``` ```
- the `nodes` right has to be added:
```yaml
...
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
...
```
#### Gateway API: KubernetesGateway Provider #### Gateway API: KubernetesGateway Provider
In v3.1, the KubernetesGateway Provider is no longer an experimental feature. In v3.1, the KubernetesGateway Provider is no longer an experimental feature.
@ -51,3 +68,10 @@ It can be enabled without the associated `experimental.kubernetesgateway` option
The `kubernetesgateway` option should be removed from the experimental section of the static configuration. The `kubernetesgateway` option should be removed from the experimental section of the static configuration.
To configure `kubernetesgateway`, please check out the [KubernetesGateway Provider documentation](../providers/kubernetes-gateway.md). To configure `kubernetesgateway`, please check out the [KubernetesGateway Provider documentation](../providers/kubernetes-gateway.md).
## v3.1.0 to v3.1.1
### IngressClass Lookup
The Kubernetes Ingress provider option `disableIngressClassLookup` has been deprecated in v3.1.1, and will be removed in the next major version.
Please use the `disableClusterScopeResources` option instead to avoid cluster scope resources discovery (IngressClass, Nodes).

View file

@ -287,6 +287,11 @@ providers:
_Optional, Default: false_ _Optional, Default: false_
??? warning "Deprecated"
The Kubernetes Ingress provider option `disableIngressClassLookup` has been deprecated in v3.1, and will be removed in the next major version.
Please use the `disableClusterScopeResources` option instead.
If the parameter is set to `true`, If the parameter is set to `true`,
Traefik will not discover IngressClasses in the cluster. Traefik will not discover IngressClasses in the cluster.
By doing so, it alleviates the requirement of giving Traefik the rights to look IngressClasses up. By doing so, it alleviates the requirement of giving Traefik the rights to look IngressClasses up.
@ -312,6 +317,33 @@ providers:
--providers.kubernetesingress.disableingressclasslookup=true --providers.kubernetesingress.disableingressclasslookup=true
``` ```
### `disableClusterScopeResources`
_Optional, Default: false_
When this parameter is set to `true`,
Traefik will not discover cluster scope resources (`IngressClass` and `Nodes`).
By doing so, it alleviates the requirement of giving Traefik the rights to look up for cluster resources.
Furthermore, Traefik will not handle Ingresses with IngressClass references, therefore such Ingresses will be ignored (please note that annotations are not affected by this option).
This will also prevent from using the `NodePortLB` options on services.
```yaml tab="File (YAML)"
providers:
kubernetesIngress:
disableClusterScopeResources: true
# ...
```
```toml tab="File (TOML)"
[providers.kubernetesIngress]
disableClusterScopeResources = true
# ...
```
```bash tab="CLI"
--providers.kubernetesingress.disableClusterScopeResources=true
```
### `ingressEndpoint` ### `ingressEndpoint`
#### `hostname` #### `hostname`

View file

@ -726,6 +726,9 @@ Allow ExternalName services. (Default: ```false```)
`--providers.kubernetescrd.certauthfilepath`: `--providers.kubernetescrd.certauthfilepath`:
Kubernetes certificate authority file path (not needed for in-cluster client). Kubernetes certificate authority file path (not needed for in-cluster client).
`--providers.kubernetescrd.disableclusterscoperesources`:
Disables the lookup of cluster scope resources (incompatible with IngressClasses and NodePortLB enabled services). (Default: ```false```)
`--providers.kubernetescrd.endpoint`: `--providers.kubernetescrd.endpoint`:
Kubernetes server endpoint (required for external cluster client). Kubernetes server endpoint (required for external cluster client).
@ -798,8 +801,11 @@ Allow ExternalName services. (Default: ```false```)
`--providers.kubernetesingress.certauthfilepath`: `--providers.kubernetesingress.certauthfilepath`:
Kubernetes certificate authority file path (not needed for in-cluster client). Kubernetes certificate authority file path (not needed for in-cluster client).
`--providers.kubernetesingress.disableclusterscoperesources`:
Disables the lookup of cluster scope resources (incompatible with IngressClasses and NodePortLB enabled services). (Default: ```false```)
`--providers.kubernetesingress.disableingressclasslookup`: `--providers.kubernetesingress.disableingressclasslookup`:
Disables the lookup of IngressClasses. (Default: ```false```) Disables the lookup of IngressClasses (Deprecated, please use DisableClusterScopeResources). (Default: ```false```)
`--providers.kubernetesingress.endpoint`: `--providers.kubernetesingress.endpoint`:
Kubernetes server endpoint (required for external cluster client). Kubernetes server endpoint (required for external cluster client).

View file

@ -726,6 +726,9 @@ Allow ExternalName services. (Default: ```false```)
`TRAEFIK_PROVIDERS_KUBERNETESCRD_CERTAUTHFILEPATH`: `TRAEFIK_PROVIDERS_KUBERNETESCRD_CERTAUTHFILEPATH`:
Kubernetes certificate authority file path (not needed for in-cluster client). Kubernetes certificate authority file path (not needed for in-cluster client).
`TRAEFIK_PROVIDERS_KUBERNETESCRD_DISABLECLUSTERSCOPERESOURCES`:
Disables the lookup of cluster scope resources (incompatible with IngressClasses and NodePortLB enabled services). (Default: ```false```)
`TRAEFIK_PROVIDERS_KUBERNETESCRD_ENDPOINT`: `TRAEFIK_PROVIDERS_KUBERNETESCRD_ENDPOINT`:
Kubernetes server endpoint (required for external cluster client). Kubernetes server endpoint (required for external cluster client).
@ -798,8 +801,11 @@ Allow ExternalName services. (Default: ```false```)
`TRAEFIK_PROVIDERS_KUBERNETESINGRESS_CERTAUTHFILEPATH`: `TRAEFIK_PROVIDERS_KUBERNETESINGRESS_CERTAUTHFILEPATH`:
Kubernetes certificate authority file path (not needed for in-cluster client). Kubernetes certificate authority file path (not needed for in-cluster client).
`TRAEFIK_PROVIDERS_KUBERNETESINGRESS_DISABLECLUSTERSCOPERESOURCES`:
Disables the lookup of cluster scope resources (incompatible with IngressClasses and NodePortLB enabled services). (Default: ```false```)
`TRAEFIK_PROVIDERS_KUBERNETESINGRESS_DISABLEINGRESSCLASSLOOKUP`: `TRAEFIK_PROVIDERS_KUBERNETESINGRESS_DISABLEINGRESSCLASSLOOKUP`:
Disables the lookup of IngressClasses. (Default: ```false```) Disables the lookup of IngressClasses (Deprecated, please use DisableClusterScopeResources). (Default: ```false```)
`TRAEFIK_PROVIDERS_KUBERNETESINGRESS_ENDPOINT`: `TRAEFIK_PROVIDERS_KUBERNETESINGRESS_ENDPOINT`:
Kubernetes server endpoint (required for external cluster client). Kubernetes server endpoint (required for external cluster client).

View file

@ -124,6 +124,7 @@
allowEmptyServices = true allowEmptyServices = true
allowExternalNameServices = true allowExternalNameServices = true
disableIngressClassLookup = true disableIngressClassLookup = true
disableClusterScopeResources = true
nativeLBByDefault = true nativeLBByDefault = true
[providers.kubernetesIngress.ingressEndpoint] [providers.kubernetesIngress.ingressEndpoint]
ip = "foobar" ip = "foobar"
@ -141,6 +142,7 @@
throttleDuration = "42s" throttleDuration = "42s"
allowEmptyServices = true allowEmptyServices = true
nativeLBByDefault = true nativeLBByDefault = true
disableClusterScopeResources = true
[providers.kubernetesGateway] [providers.kubernetesGateway]
endpoint = "foobar" endpoint = "foobar"
token = "foobar" token = "foobar"

View file

@ -141,6 +141,7 @@ providers:
allowEmptyServices: true allowEmptyServices: true
allowExternalNameServices: true allowExternalNameServices: true
disableIngressClassLookup: true disableIngressClassLookup: true
disableClusterScopeResources: true
nativeLBByDefault: true nativeLBByDefault: true
kubernetesCRD: kubernetesCRD:
endpoint: foobar endpoint: foobar
@ -156,6 +157,7 @@ providers:
throttleDuration: 42s throttleDuration: 42s
allowEmptyServices: true allowEmptyServices: true
nativeLBByDefault: true nativeLBByDefault: true
disableClusterScopeResources: true
kubernetesGateway: kubernetesGateway:
endpoint: foobar endpoint: foobar
token: foobar token: foobar

View file

@ -204,16 +204,17 @@ func (c *configuration) deprecationNotice(logger zerolog.Logger) bool {
} }
type providers struct { type providers struct {
Docker *docker `json:"docker,omitempty" toml:"docker,omitempty" yaml:"docker,omitempty" label:"allowEmpty" file:"allowEmpty"` Docker *docker `json:"docker,omitempty" toml:"docker,omitempty" yaml:"docker,omitempty" label:"allowEmpty" file:"allowEmpty"`
Swarm *swarm `json:"swarm,omitempty" toml:"swarm,omitempty" yaml:"swarm,omitempty" label:"allowEmpty" file:"allowEmpty"` Swarm *swarm `json:"swarm,omitempty" toml:"swarm,omitempty" yaml:"swarm,omitempty" label:"allowEmpty" file:"allowEmpty"`
Consul *consul `json:"consul,omitempty" toml:"consul,omitempty" yaml:"consul,omitempty" label:"allowEmpty" file:"allowEmpty"` Consul *consul `json:"consul,omitempty" toml:"consul,omitempty" yaml:"consul,omitempty" label:"allowEmpty" file:"allowEmpty"`
ConsulCatalog *consulCatalog `json:"consulCatalog,omitempty" toml:"consulCatalog,omitempty" yaml:"consulCatalog,omitempty" label:"allowEmpty" file:"allowEmpty"` ConsulCatalog *consulCatalog `json:"consulCatalog,omitempty" toml:"consulCatalog,omitempty" yaml:"consulCatalog,omitempty" label:"allowEmpty" file:"allowEmpty"`
Nomad *nomad `json:"nomad,omitempty" toml:"nomad,omitempty" yaml:"nomad,omitempty" label:"allowEmpty" file:"allowEmpty"` Nomad *nomad `json:"nomad,omitempty" toml:"nomad,omitempty" yaml:"nomad,omitempty" label:"allowEmpty" file:"allowEmpty"`
Marathon map[string]any `json:"marathon,omitempty" toml:"marathon,omitempty" yaml:"marathon,omitempty" label:"allowEmpty" file:"allowEmpty"` Marathon map[string]any `json:"marathon,omitempty" toml:"marathon,omitempty" yaml:"marathon,omitempty" label:"allowEmpty" file:"allowEmpty"`
Rancher map[string]any `json:"rancher,omitempty" toml:"rancher,omitempty" yaml:"rancher,omitempty" label:"allowEmpty" file:"allowEmpty"` Rancher map[string]any `json:"rancher,omitempty" toml:"rancher,omitempty" yaml:"rancher,omitempty" label:"allowEmpty" file:"allowEmpty"`
ETCD *etcd `json:"etcd,omitempty" toml:"etcd,omitempty" yaml:"etcd,omitempty" label:"allowEmpty" file:"allowEmpty"` ETCD *etcd `json:"etcd,omitempty" toml:"etcd,omitempty" yaml:"etcd,omitempty" label:"allowEmpty" file:"allowEmpty"`
Redis *redis `json:"redis,omitempty" toml:"redis,omitempty" yaml:"redis,omitempty" label:"allowEmpty" file:"allowEmpty"` Redis *redis `json:"redis,omitempty" toml:"redis,omitempty" yaml:"redis,omitempty" label:"allowEmpty" file:"allowEmpty"`
HTTP *http `json:"http,omitempty" toml:"http,omitempty" yaml:"http,omitempty" label:"allowEmpty" file:"allowEmpty"` HTTP *http `json:"http,omitempty" toml:"http,omitempty" yaml:"http,omitempty" label:"allowEmpty" file:"allowEmpty"`
KubernetesIngress *ingress `json:"kubernetesIngress,omitempty" toml:"kubernetesIngress,omitempty" yaml:"kubernetesIngress,omitempty" file:"allowEmpty"`
} }
func (p *providers) deprecationNotice(logger zerolog.Logger) bool { func (p *providers) deprecationNotice(logger zerolog.Logger) bool {
@ -243,6 +244,7 @@ func (p *providers) deprecationNotice(logger zerolog.Logger) bool {
etcdIncompatible := p.ETCD.deprecationNotice(logger) etcdIncompatible := p.ETCD.deprecationNotice(logger)
redisIncompatible := p.Redis.deprecationNotice(logger) redisIncompatible := p.Redis.deprecationNotice(logger)
httpIncompatible := p.HTTP.deprecationNotice(logger) httpIncompatible := p.HTTP.deprecationNotice(logger)
p.KubernetesIngress.deprecationNotice(logger)
return incompatible || return incompatible ||
dockerIncompatible || dockerIncompatible ||
consulIncompatible || consulIncompatible ||
@ -457,6 +459,22 @@ func (h *http) deprecationNotice(logger zerolog.Logger) bool {
return incompatible return incompatible
} }
type ingress struct {
DisableIngressClassLookup *bool `json:"disableIngressClassLookup,omitempty" toml:"disableIngressClassLookup,omitempty" yaml:"disableIngressClassLookup,omitempty"`
}
func (i *ingress) deprecationNotice(logger zerolog.Logger) {
if i == nil {
return
}
if i.DisableIngressClassLookup != nil {
logger.Error().Msg("Kubernetes Ingress provider `disableIngressClassLookup` option has been deprecated in v3.1, and will be removed in the next major version." +
"Please use the `disableClusterScopeResources` option instead." +
"For more information please read the migration guide: https://doc.traefik.io/traefik/v3.1/migration/v3/#ingressclasslookup")
}
}
type experimental struct { type experimental struct {
HTTP3 *bool `json:"http3,omitempty" toml:"http3,omitempty" yaml:"http3,omitempty"` HTTP3 *bool `json:"http3,omitempty" toml:"http3,omitempty" yaml:"http3,omitempty"`
KubernetesGateway *bool `json:"kubernetesGateway,omitempty" toml:"kubernetesGateway,omitempty" yaml:"kubernetesGateway,omitempty"` KubernetesGateway *bool `json:"kubernetesGateway,omitempty" toml:"kubernetesGateway,omitempty" yaml:"kubernetesGateway,omitempty"`

View file

@ -57,10 +57,12 @@ type clientWrapper struct {
csCrd traefikclientset.Interface csCrd traefikclientset.Interface
csKube kclientset.Interface csKube kclientset.Interface
factoryClusterScope kinformers.SharedInformerFactory clusterScopeFactory kinformers.SharedInformerFactory
factoriesCrd map[string]traefikinformers.SharedInformerFactory disableClusterScopeInformer bool
factoriesKube map[string]kinformers.SharedInformerFactory
factoriesSecret map[string]kinformers.SharedInformerFactory factoriesCrd map[string]traefikinformers.SharedInformerFactory
factoriesKube map[string]kinformers.SharedInformerFactory
factoriesSecret map[string]kinformers.SharedInformerFactory
labelSelector string labelSelector string
@ -237,18 +239,11 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
c.factoriesSecret[ns] = factorySecret c.factoriesSecret[ns] = factorySecret
} }
c.factoryClusterScope = kinformers.NewSharedInformerFactory(c.csKube, resyncPeriod)
_, err := c.factoryClusterScope.Core().V1().Nodes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
for _, ns := range namespaces { for _, ns := range namespaces {
c.factoriesCrd[ns].Start(stopCh) c.factoriesCrd[ns].Start(stopCh)
c.factoriesKube[ns].Start(stopCh) c.factoriesKube[ns].Start(stopCh)
c.factoriesSecret[ns].Start(stopCh) c.factoriesSecret[ns].Start(stopCh)
} }
c.factoryClusterScope.Start(stopCh)
for _, ns := range namespaces { for _, ns := range namespaces {
for t, ok := range c.factoriesCrd[ns].WaitForCacheSync(stopCh) { for t, ok := range c.factoriesCrd[ns].WaitForCacheSync(stopCh) {
@ -270,9 +265,19 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
} }
} }
for t, ok := range c.factoryClusterScope.WaitForCacheSync(stopCh) { if !c.disableClusterScopeInformer {
if !ok { c.clusterScopeFactory = kinformers.NewSharedInformerFactory(c.csKube, resyncPeriod)
return nil, fmt.Errorf("timed out waiting for controller caches to sync %s", t.String()) _, err := c.clusterScopeFactory.Core().V1().Nodes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
c.clusterScopeFactory.Start(stopCh)
for t, ok := range c.clusterScopeFactory.WaitForCacheSync(stopCh) {
if !ok {
return nil, fmt.Errorf("timed out waiting for controller caches to sync %s", t.String())
}
} }
} }
@ -474,7 +479,7 @@ func (c *clientWrapper) GetSecret(namespace, name string) (*corev1.Secret, bool,
} }
func (c *clientWrapper) GetNodes() ([]*corev1.Node, bool, error) { func (c *clientWrapper) GetNodes() ([]*corev1.Node, bool, error) {
nodes, err := c.factoryClusterScope.Core().V1().Nodes().Lister().List(labels.Everything()) nodes, err := c.clusterScopeFactory.Core().V1().Nodes().Lister().List(labels.Everything())
exist, err := translateNotFoundError(err) exist, err := translateNotFoundError(err)
return nodes, exist, err return nodes, exist, err
} }

View file

@ -50,17 +50,18 @@ const (
// Provider holds configurations of the provider. // Provider holds configurations of the provider.
type Provider struct { type Provider struct {
Endpoint string `description:"Kubernetes server endpoint (required for external cluster client)." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"` Endpoint string `description:"Kubernetes server endpoint (required for external cluster client)." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"`
Token types.FileOrContent `description:"Kubernetes bearer token (not needed for in-cluster client). It accepts either a token value or a file path to the token." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"` Token types.FileOrContent `description:"Kubernetes bearer token (not needed for in-cluster client). It accepts either a token value or a file path to the token." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"`
CertAuthFilePath string `description:"Kubernetes certificate authority file path (not needed for in-cluster client)." json:"certAuthFilePath,omitempty" toml:"certAuthFilePath,omitempty" yaml:"certAuthFilePath,omitempty"` CertAuthFilePath string `description:"Kubernetes certificate authority file path (not needed for in-cluster client)." json:"certAuthFilePath,omitempty" toml:"certAuthFilePath,omitempty" yaml:"certAuthFilePath,omitempty"`
Namespaces []string `description:"Kubernetes namespaces." json:"namespaces,omitempty" toml:"namespaces,omitempty" yaml:"namespaces,omitempty" export:"true"` Namespaces []string `description:"Kubernetes namespaces." json:"namespaces,omitempty" toml:"namespaces,omitempty" yaml:"namespaces,omitempty" export:"true"`
AllowCrossNamespace bool `description:"Allow cross namespace resource reference." json:"allowCrossNamespace,omitempty" toml:"allowCrossNamespace,omitempty" yaml:"allowCrossNamespace,omitempty" export:"true"` AllowCrossNamespace bool `description:"Allow cross namespace resource reference." json:"allowCrossNamespace,omitempty" toml:"allowCrossNamespace,omitempty" yaml:"allowCrossNamespace,omitempty" export:"true"`
AllowExternalNameServices bool `description:"Allow ExternalName services." json:"allowExternalNameServices,omitempty" toml:"allowExternalNameServices,omitempty" yaml:"allowExternalNameServices,omitempty" export:"true"` AllowExternalNameServices bool `description:"Allow ExternalName services." json:"allowExternalNameServices,omitempty" toml:"allowExternalNameServices,omitempty" yaml:"allowExternalNameServices,omitempty" export:"true"`
LabelSelector string `description:"Kubernetes label selector to use." json:"labelSelector,omitempty" toml:"labelSelector,omitempty" yaml:"labelSelector,omitempty" export:"true"` LabelSelector string `description:"Kubernetes label selector to use." json:"labelSelector,omitempty" toml:"labelSelector,omitempty" yaml:"labelSelector,omitempty" export:"true"`
IngressClass string `description:"Value of kubernetes.io/ingress.class annotation to watch for." json:"ingressClass,omitempty" toml:"ingressClass,omitempty" yaml:"ingressClass,omitempty" export:"true"` IngressClass string `description:"Value of kubernetes.io/ingress.class annotation to watch for." json:"ingressClass,omitempty" toml:"ingressClass,omitempty" yaml:"ingressClass,omitempty" export:"true"`
ThrottleDuration ptypes.Duration `description:"Ingress refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"` ThrottleDuration ptypes.Duration `description:"Ingress refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"`
AllowEmptyServices bool `description:"Allow the creation of services without endpoints." json:"allowEmptyServices,omitempty" toml:"allowEmptyServices,omitempty" yaml:"allowEmptyServices,omitempty" export:"true"` AllowEmptyServices bool `description:"Allow the creation of services without endpoints." json:"allowEmptyServices,omitempty" toml:"allowEmptyServices,omitempty" yaml:"allowEmptyServices,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"`
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"`
lastConfiguration safe.Safe lastConfiguration safe.Safe
@ -112,6 +113,7 @@ func (p *Provider) newK8sClient(ctx context.Context) (*clientWrapper, error) {
} }
client.labelSelector = p.LabelSelector client.labelSelector = p.LabelSelector
client.disableClusterScopeInformer = p.DisableClusterScopeResources
return client, nil return client, nil
} }

View file

@ -51,11 +51,12 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli
} }
cb := configBuilder{ cb := configBuilder{
client: client, client: client,
allowCrossNamespace: p.AllowCrossNamespace, allowCrossNamespace: p.AllowCrossNamespace,
allowExternalNameServices: p.AllowExternalNameServices, allowExternalNameServices: p.AllowExternalNameServices,
allowEmptyServices: p.AllowEmptyServices, allowEmptyServices: p.AllowEmptyServices,
NativeLBByDefault: p.NativeLBByDefault, nativeLBByDefault: p.NativeLBByDefault,
disableClusterScopeResources: p.DisableClusterScopeResources,
} }
for _, route := range ingressRoute.Spec.Routes { for _, route := range ingressRoute.Spec.Routes {
@ -199,11 +200,12 @@ func (p *Provider) makeMiddlewareKeys(ctx context.Context, ingRouteNamespace str
} }
type configBuilder struct { type configBuilder struct {
client Client client Client
allowCrossNamespace bool allowCrossNamespace bool
allowExternalNameServices bool allowExternalNameServices bool
allowEmptyServices bool allowEmptyServices bool
NativeLBByDefault bool nativeLBByDefault bool
disableClusterScopeResources bool
} }
// buildTraefikService creates the configuration for the traefik service defined in tService, // buildTraefikService creates the configuration for the traefik service defined in tService,
@ -428,7 +430,7 @@ func (c configBuilder) loadServers(parentNamespace string, svc traefikv1alpha1.L
return []dynamic.Server{{URL: fmt.Sprintf("%s://%s", protocol, hostPort)}}, nil return []dynamic.Server{{URL: fmt.Sprintf("%s://%s", protocol, hostPort)}}, nil
} }
nativeLB := c.NativeLBByDefault nativeLB := c.nativeLBByDefault
if svc.NativeLB != nil { if svc.NativeLB != nil {
nativeLB = *svc.NativeLB nativeLB = *svc.NativeLB
} }
@ -448,6 +450,10 @@ func (c configBuilder) loadServers(parentNamespace string, svc traefikv1alpha1.L
var servers []dynamic.Server var servers []dynamic.Server
if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB { if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB {
if c.disableClusterScopeResources {
return nil, errors.New("nodes lookup is disabled")
}
nodes, nodesExists, nodesErr := c.client.GetNodes() nodes, nodesExists, nodesErr := c.client.GetNodes()
if nodesErr != nil { if nodesErr != nil {
return nil, nodesErr return nil, nodesErr

View file

@ -239,6 +239,10 @@ func (p *Provider) loadTCPServers(client Client, namespace string, svc traefikv1
var servers []dynamic.TCPServer var servers []dynamic.TCPServer
if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB { if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB {
if p.DisableClusterScopeResources {
return nil, errors.New("nodes lookup is disabled")
}
nodes, nodesExists, nodesErr := client.GetNodes() nodes, nodesExists, nodesErr := client.GetNodes()
if nodesErr != nil { if nodesErr != nil {
return nil, nodesErr return nil, nodesErr

View file

@ -7446,10 +7446,10 @@ func TestNativeLB(t *testing.T) {
func TestNodePortLB(t *testing.T) { func TestNodePortLB(t *testing.T) {
testCases := []struct { testCases := []struct {
desc string desc string
ingressClass string paths []string
paths []string disableClusterScope bool
expected *dynamic.Configuration expected *dynamic.Configuration
}{ }{
{ {
desc: "Empty", desc: "Empty",
@ -7594,6 +7594,90 @@ func TestNodePortLB(t *testing.T) {
TLS: &dynamic.TLSConfiguration{}, TLS: &dynamic.TLSConfiguration{},
}, },
}, },
{
desc: "HTTP with node port LB, cluster scope resources disabled",
paths: []string{"services.yml", "with_node_port_lb.yml"},
disableClusterScope: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
ServersTransports: map[string]*dynamic.TCPServersTransport{},
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
},
HTTP: &dynamic.HTTPConfiguration{
ServersTransports: map[string]*dynamic.ServersTransport{},
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "TCP with native Service LB, cluster scope resources disabled",
paths: []string{"tcp/services.yml", "tcp/with_node_port_service_lb.yml"},
disableClusterScope: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
ServersTransports: map[string]*dynamic.TCPServersTransport{},
Routers: map[string]*dynamic.TCPRouter{
"default-test.route-fdd3e9338e47a45efefc": {
EntryPoints: []string{"foo"},
Service: "default-test.route-fdd3e9338e47a45efefc",
Rule: "HostSNI(`foo.com`)",
},
},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
},
HTTP: &dynamic.HTTPConfiguration{
ServersTransports: map[string]*dynamic.ServersTransport{},
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "UDP with native Service LB, cluster scope resources disabled",
paths: []string{"udp/services.yml", "udp/with_node_port_service_lb.yml"},
disableClusterScope: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{
"default-test.route-0": {
EntryPoints: []string{"foo"},
Service: "default-test.route-0",
},
},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
ServersTransports: map[string]*dynamic.TCPServersTransport{},
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
},
HTTP: &dynamic.HTTPConfiguration{
ServersTransports: map[string]*dynamic.ServersTransport{},
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
} }
for _, test := range testCases { for _, test := range testCases {
@ -7617,7 +7701,9 @@ func TestNodePortLB(t *testing.T) {
<-eventCh <-eventCh
} }
p := Provider{} p := Provider{
DisableClusterScopeResources: test.disableClusterScope,
}
conf := p.loadConfigurationFromCRD(context.Background(), client) conf := p.loadConfigurationFromCRD(context.Background(), client)
assert.Equal(t, test.expected, conf) assert.Equal(t, test.expected, conf)

View file

@ -123,6 +123,10 @@ func (p *Provider) loadUDPServers(client Client, namespace string, svc traefikv1
var servers []dynamic.UDPServer var servers []dynamic.UDPServer
if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB { if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB {
if p.DisableClusterScopeResources {
return nil, errors.New("nodes lookup is disabled")
}
nodes, nodesExists, nodesErr := client.GetNodes() nodes, nodesExists, nodesErr := client.GetNodes()
if nodesErr != nil { if nodesErr != nil {
return nil, nodesErr return nil, nodesErr

View file

@ -49,14 +49,14 @@ type Client interface {
type clientWrapper struct { type clientWrapper struct {
clientset kclientset.Interface clientset kclientset.Interface
factoryClusterScope kinformers.SharedInformerFactory clusterScopeFactory kinformers.SharedInformerFactory
factoriesKube map[string]kinformers.SharedInformerFactory factoriesKube map[string]kinformers.SharedInformerFactory
factoriesSecret map[string]kinformers.SharedInformerFactory factoriesSecret map[string]kinformers.SharedInformerFactory
factoriesIngress map[string]kinformers.SharedInformerFactory factoriesIngress map[string]kinformers.SharedInformerFactory
clusterFactory kinformers.SharedInformerFactory
ingressLabelSelector string ingressLabelSelector string
isNamespaceAll bool isNamespaceAll bool
disableIngressClassInformer bool disableIngressClassInformer bool // Deprecated.
disableClusterScopeInformer bool
watchedNamespaces []string watchedNamespaces []string
serverVersion *version.Version serverVersion *version.Version
} }
@ -201,58 +201,52 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
c.factoriesSecret[ns] = factorySecret c.factoriesSecret[ns] = factorySecret
} }
c.factoryClusterScope = kinformers.NewSharedInformerFactory(c.clientset, resyncPeriod)
_, err = c.factoryClusterScope.Core().V1().Nodes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
for _, ns := range namespaces { for _, ns := range namespaces {
c.factoriesIngress[ns].Start(stopCh) c.factoriesIngress[ns].Start(stopCh)
c.factoriesKube[ns].Start(stopCh) c.factoriesKube[ns].Start(stopCh)
c.factoriesSecret[ns].Start(stopCh) c.factoriesSecret[ns].Start(stopCh)
} }
c.factoryClusterScope.Start(stopCh)
for _, ns := range namespaces { for _, ns := range namespaces {
for typ, ok := range c.factoriesIngress[ns].WaitForCacheSync(stopCh) { for t, ok := range c.factoriesIngress[ns].WaitForCacheSync(stopCh) {
if !ok { if !ok {
return nil, fmt.Errorf("timed out waiting for controller caches to sync %s in namespace %q", typ, ns) return nil, fmt.Errorf("timed out waiting for controller caches to sync %s in namespace %q", t.String(), ns)
} }
} }
for typ, ok := range c.factoriesKube[ns].WaitForCacheSync(stopCh) { for t, ok := range c.factoriesKube[ns].WaitForCacheSync(stopCh) {
if !ok { if !ok {
return nil, fmt.Errorf("timed out waiting for controller caches to sync %s in namespace %q", typ, ns) return nil, fmt.Errorf("timed out waiting for controller caches to sync %s in namespace %q", t.String(), ns)
} }
} }
for typ, ok := range c.factoriesSecret[ns].WaitForCacheSync(stopCh) { for t, ok := range c.factoriesSecret[ns].WaitForCacheSync(stopCh) {
if !ok { if !ok {
return nil, fmt.Errorf("timed out waiting for controller caches to sync %s in namespace %q", typ, ns) return nil, fmt.Errorf("timed out waiting for controller caches to sync %s in namespace %q", t.String(), ns)
} }
} }
} }
for t, ok := range c.factoryClusterScope.WaitForCacheSync(stopCh) { if !c.disableIngressClassInformer || !c.disableClusterScopeInformer {
if !ok { c.clusterScopeFactory = kinformers.NewSharedInformerFactory(c.clientset, resyncPeriod)
return nil, fmt.Errorf("timed out waiting for controller caches to sync %s", t.String())
}
}
if !c.disableIngressClassInformer { _, err = c.clusterScopeFactory.Networking().V1().IngressClasses().Informer().AddEventHandler(eventHandler)
c.clusterFactory = kinformers.NewSharedInformerFactoryWithOptions(c.clientset, resyncPeriod)
_, err = c.clusterFactory.Networking().V1().IngressClasses().Informer().AddEventHandler(eventHandler)
if err != nil { if err != nil {
return nil, err return nil, err
} }
c.clusterFactory.Start(stopCh) if !c.disableClusterScopeInformer {
_, err = c.clusterScopeFactory.Core().V1().Nodes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
}
for typ, ok := range c.clusterFactory.WaitForCacheSync(stopCh) { c.clusterScopeFactory.Start(stopCh)
for t, ok := range c.clusterScopeFactory.WaitForCacheSync(stopCh) {
if !ok { if !ok {
return nil, fmt.Errorf("timed out waiting for controller caches to sync %s", typ) return nil, fmt.Errorf("timed out waiting for controller caches to sync %s", t.String())
} }
} }
} }
@ -370,18 +364,18 @@ func (c *clientWrapper) GetSecret(namespace, name string) (*corev1.Secret, bool,
} }
func (c *clientWrapper) GetNodes() ([]*corev1.Node, bool, error) { func (c *clientWrapper) GetNodes() ([]*corev1.Node, bool, error) {
nodes, err := c.factoryClusterScope.Core().V1().Nodes().Lister().List(labels.Everything()) nodes, err := c.clusterScopeFactory.Core().V1().Nodes().Lister().List(labels.Everything())
exist, err := translateNotFoundError(err) exist, err := translateNotFoundError(err)
return nodes, exist, err return nodes, exist, err
} }
func (c *clientWrapper) GetIngressClasses() ([]*netv1.IngressClass, error) { func (c *clientWrapper) GetIngressClasses() ([]*netv1.IngressClass, error) {
if c.clusterFactory == nil { if c.clusterScopeFactory == nil {
return nil, errors.New("cluster factory not loaded") return nil, errors.New("cluster factory not loaded")
} }
var ics []*netv1.IngressClass var ics []*netv1.IngressClass
ingressClasses, err := c.clusterFactory.Networking().V1().IngressClasses().Lister().List(labels.Everything()) ingressClasses, err := c.clusterScopeFactory.Networking().V1().IngressClasses().Lister().List(labels.Everything())
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -0,0 +1,45 @@
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: ""
namespace: testing
spec:
rules:
- host: traefik.tchouk
http:
paths:
- path: /bar
backend:
service:
name: service1
port:
number: 8080
pathType: Prefix
---
kind: Service
apiVersion: v1
metadata:
name: service1
namespace: testing
annotations:
traefik.ingress.kubernetes.io/service.nodeportlb: "true"
spec:
ports:
- port: 8080
nodePort: 32456
clusterIP: 10.0.0.1
type: NodePort
externalName: traefik.wtf
---
kind: Node
apiVersion: v1
metadata:
name: traefik-node
status:
addresses:
- type: InternalIP
address: 172.16.4.4

View file

@ -51,8 +51,10 @@ type Provider struct {
ThrottleDuration ptypes.Duration `description:"Ingress refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"` ThrottleDuration ptypes.Duration `description:"Ingress refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"`
AllowEmptyServices bool `description:"Allow creation of services without endpoints." json:"allowEmptyServices,omitempty" toml:"allowEmptyServices,omitempty" yaml:"allowEmptyServices,omitempty" export:"true"` AllowEmptyServices bool `description:"Allow creation of services without endpoints." json:"allowEmptyServices,omitempty" toml:"allowEmptyServices,omitempty" yaml:"allowEmptyServices,omitempty" export:"true"`
AllowExternalNameServices bool `description:"Allow ExternalName services." json:"allowExternalNameServices,omitempty" toml:"allowExternalNameServices,omitempty" yaml:"allowExternalNameServices,omitempty" export:"true"` AllowExternalNameServices bool `description:"Allow ExternalName services." json:"allowExternalNameServices,omitempty" toml:"allowExternalNameServices,omitempty" yaml:"allowExternalNameServices,omitempty" export:"true"`
DisableIngressClassLookup bool `description:"Disables the lookup of IngressClasses." json:"disableIngressClassLookup,omitempty" toml:"disableIngressClassLookup,omitempty" yaml:"disableIngressClassLookup,omitempty" export:"true"` // Deprecated: please use DisableClusterScopeResources.
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"` DisableIngressClassLookup bool `description:"Disables the lookup of IngressClasses (Deprecated, please use DisableClusterScopeResources)." json:"disableIngressClassLookup,omitempty" toml:"disableIngressClassLookup,omitempty" yaml:"disableIngressClassLookup,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"`
lastConfiguration safe.Safe lastConfiguration safe.Safe
@ -114,7 +116,8 @@ func (p *Provider) newK8sClient(ctx context.Context) (*clientWrapper, error) {
} }
cl.ingressLabelSelector = p.LabelSelector cl.ingressLabelSelector = p.LabelSelector
cl.disableIngressClassInformer = p.DisableIngressClassLookup cl.disableIngressClassInformer = p.DisableIngressClassLookup || p.DisableClusterScopeResources
cl.disableClusterScopeInformer = p.DisableClusterScopeResources
return cl, nil return cl, nil
} }
@ -212,7 +215,6 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{}, Services: map[string]*dynamic.Service{},
}, },
TCP: &dynamic.TCPConfiguration{},
} }
var ingressClasses []*netv1.IngressClass var ingressClasses []*netv1.IngressClass
@ -591,6 +593,10 @@ func (p *Provider) loadService(client Client, namespace string, backend netv1.In
} }
if svcConfig.Service.NodePortLB && service.Spec.Type == corev1.ServiceTypeNodePort { if svcConfig.Service.NodePortLB && service.Spec.Type == corev1.ServiceTypeNodePort {
if p.DisableClusterScopeResources {
return nil, errors.New("nodes lookup is disabled")
}
nodes, nodesExists, nodesErr := client.GetNodes() nodes, nodesExists, nodesErr := client.GetNodes()
if nodesErr != nil { if nodesErr != nil {
return nil, nodesErr return nil, nodesErr

View file

@ -35,7 +35,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Empty ingresses", desc: "Empty ingresses",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
@ -46,7 +45,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress one rule host only", desc: "Ingress one rule host only",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
@ -57,7 +55,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with a basic rule on one path", desc: "Ingress with a basic rule on one path",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -90,7 +87,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with annotations", desc: "Ingress with annotations",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -148,7 +144,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with two different rules with one path", desc: "Ingress with two different rules with one path",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -185,7 +180,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with conflicting routers on host", desc: "Ingress with conflicting routers on host",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -222,7 +216,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with conflicting routers on path", desc: "Ingress with conflicting routers on path",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -259,7 +252,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress one rule with two paths", desc: "Ingress one rule with two paths",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -296,7 +288,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress one rule with one path and one host", desc: "Ingress one rule with one path and one host",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -329,7 +320,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with one host without path", desc: "Ingress with one host without path",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -359,7 +349,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress one rule with one host and two paths", desc: "Ingress one rule with one host and two paths",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -396,7 +385,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress Two rules with one host and one path", desc: "Ingress Two rules with one host and one path",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -433,7 +421,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with two services", desc: "Ingress with two services",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -487,7 +474,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
desc: "Ingress with one service without endpoints subset", desc: "Ingress with one service without endpoints subset",
allowEmptyServices: true, allowEmptyServices: true,
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -512,7 +498,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with one service without endpoint", desc: "Ingress with one service without endpoint",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -523,7 +508,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Single Service Ingress (without any rules)", desc: "Single Service Ingress (without any rules)",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -558,7 +542,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with port value in backend and no pod replica", desc: "Ingress with port value in backend and no pod replica",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -591,7 +574,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with port name in backend and no pod replica", desc: "Ingress with port name in backend and no pod replica",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -624,7 +606,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with port name in backend and 2 pod replica", desc: "Ingress with port name in backend and 2 pod replica",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -657,7 +638,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with two paths using same service and different port name", desc: "Ingress with two paths using same service and different port name",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -710,7 +690,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with a named port matching subset of service pods", desc: "Ingress with a named port matching subset of service pods",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -743,7 +722,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "2 ingresses in different namespace with same service name", desc: "2 ingresses in different namespace with same service name",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -796,7 +774,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with unknown service port name", desc: "Ingress with unknown service port name",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -807,7 +784,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with unknown service port", desc: "Ingress with unknown service port",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -818,7 +794,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with port invalid for one service", desc: "Ingress with port invalid for one service",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -848,7 +823,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "TLS support", desc: "TLS support",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -889,7 +863,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with a basic rule on one path with https (port == 443)", desc: "Ingress with a basic rule on one path with https (port == 443)",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -922,7 +895,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with a basic rule on one path with https (portname == https)", desc: "Ingress with a basic rule on one path with https (portname == https)",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -955,7 +927,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with a basic rule on one path with https (portname starts with https)", desc: "Ingress with a basic rule on one path with https (portname starts with https)",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
@ -989,7 +960,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Double Single Service Ingress", desc: "Double Single Service Ingress",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1024,7 +994,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with default traefik ingressClass", desc: "Ingress with default traefik ingressClass",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1054,7 +1023,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress without provider traefik ingressClass and unknown annotation", desc: "Ingress without provider traefik ingressClass and unknown annotation",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -1066,7 +1034,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
desc: "Ingress with non matching provider traefik ingressClass and annotation", desc: "Ingress with non matching provider traefik ingressClass and annotation",
ingressClass: "tchouk", ingressClass: "tchouk",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -1078,7 +1045,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
desc: "Ingress with ingressClass without annotation", desc: "Ingress with ingressClass without annotation",
ingressClass: "tchouk", ingressClass: "tchouk",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -1090,7 +1056,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
desc: "Ingress with ingressClass without annotation", desc: "Ingress with ingressClass without annotation",
ingressClass: "toto", ingressClass: "toto",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -1101,7 +1066,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with wildcard host", desc: "Ingress with wildcard host",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1133,7 +1097,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with multiple ingressClasses", desc: "Ingress with multiple ingressClasses",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1168,7 +1131,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
desc: "Ingress with ingressClasses filter", desc: "Ingress with ingressClasses filter",
ingressClass: "traefik-lb2", ingressClass: "traefik-lb2",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1198,7 +1160,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with prefix pathType", desc: "Ingress with prefix pathType",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1228,7 +1189,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with empty pathType", desc: "Ingress with empty pathType",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1258,7 +1218,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with exact pathType", desc: "Ingress with exact pathType",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1288,7 +1247,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with implementationSpecific pathType", desc: "Ingress with implementationSpecific pathType",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1318,7 +1276,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with ingress annotation", desc: "Ingress with ingress annotation",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1351,7 +1308,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
desc: "Ingress with ingress annotation", desc: "Ingress with ingress annotation",
disableIngressClassLookup: true, disableIngressClassLookup: true,
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1381,7 +1337,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with ingressClass", desc: "Ingress with ingressClass",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1414,7 +1369,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
desc: "Ingress with ingressClass", desc: "Ingress with ingressClass",
disableIngressClassLookup: true, disableIngressClassLookup: true,
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -1425,7 +1379,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with named port", desc: "Ingress with named port",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1455,7 +1408,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with missing ingressClass", desc: "Ingress with missing ingressClass",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -1466,7 +1418,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with defaultbackend", desc: "Ingress with defaultbackend",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1524,7 +1475,6 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) {
{ {
desc: "Ingress with service with externalName", desc: "Ingress with service with externalName",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -1536,7 +1486,6 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) {
desc: "Ingress with service with externalName enabled", desc: "Ingress with service with externalName enabled",
allowExternalNameServices: true, allowExternalNameServices: true,
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1566,7 +1515,6 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) {
{ {
desc: "Ingress with IPv6 endpoints", desc: "Ingress with IPv6 endpoints",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1597,7 +1545,6 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) {
desc: "Ingress with IPv6 endpoints externalname enabled", desc: "Ingress with IPv6 endpoints externalname enabled",
allowExternalNameServices: true, allowExternalNameServices: true,
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1650,7 +1597,6 @@ func TestLoadConfigurationFromIngressesWithNativeLB(t *testing.T) {
{ {
desc: "Ingress with native service lb", desc: "Ingress with native service lb",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1693,14 +1639,13 @@ func TestLoadConfigurationFromIngressesWithNativeLB(t *testing.T) {
func TestLoadConfigurationFromIngressesWithNodePortLB(t *testing.T) { func TestLoadConfigurationFromIngressesWithNodePortLB(t *testing.T) {
testCases := []struct { testCases := []struct {
desc string desc string
ingressClass string clusterScopeDisabled bool
expected *dynamic.Configuration expected *dynamic.Configuration
}{ }{
{ {
desc: "Ingress with node port lb", desc: "Ingress with node port lb",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1725,6 +1670,17 @@ func TestLoadConfigurationFromIngressesWithNodePortLB(t *testing.T) {
}, },
}, },
}, },
{
desc: "Ingress with node port lb cluster scope disabled",
clusterScopeDisabled: true,
expected: &dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{},
Services: map[string]*dynamic.Service{},
},
},
},
} }
for _, test := range testCases { for _, test := range testCases {
@ -1733,7 +1689,7 @@ func TestLoadConfigurationFromIngressesWithNodePortLB(t *testing.T) {
clientMock := newClientMock(generateTestFilename(test.desc)) clientMock := newClientMock(generateTestFilename(test.desc))
p := Provider{IngressClass: test.ingressClass} p := Provider{DisableClusterScopeResources: test.clusterScopeDisabled}
conf := p.loadConfigurationFromIngresses(context.Background(), clientMock) conf := p.loadConfigurationFromIngresses(context.Background(), clientMock)
assert.Equal(t, test.expected, conf) assert.Equal(t, test.expected, conf)
@ -1927,7 +1883,6 @@ func TestLoadConfigurationFromIngressesWithNativeLBByDefault(t *testing.T) {
{ {
desc: "Ingress with native service lb", desc: "Ingress with native service lb",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1955,7 +1910,6 @@ func TestLoadConfigurationFromIngressesWithNativeLBByDefault(t *testing.T) {
{ {
desc: "Ingress with native lb by default", desc: "Ingress with native lb by default",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{