sigs.k8s.io/external-dns@v0.14.1/source/traefik_proxy.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package source
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"regexp"
    23  	"sort"
    24  	"strings"
    25  
    26  	"github.com/pkg/errors"
    27  	log "github.com/sirupsen/logrus"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    30  	"k8s.io/apimachinery/pkg/labels"
    31  	"k8s.io/apimachinery/pkg/runtime"
    32  	"k8s.io/apimachinery/pkg/runtime/schema"
    33  	"k8s.io/client-go/dynamic"
    34  	"k8s.io/client-go/dynamic/dynamicinformer"
    35  	"k8s.io/client-go/informers"
    36  	"k8s.io/client-go/kubernetes"
    37  	"k8s.io/client-go/kubernetes/scheme"
    38  	"k8s.io/client-go/tools/cache"
    39  
    40  	"sigs.k8s.io/external-dns/endpoint"
    41  )
    42  
    43  var (
    44  	ingressrouteGVR = schema.GroupVersionResource{
    45  		Group:    "traefik.io",
    46  		Version:  "v1alpha1",
    47  		Resource: "ingressroutes",
    48  	}
    49  	ingressrouteTCPGVR = schema.GroupVersionResource{
    50  		Group:    "traefik.io",
    51  		Version:  "v1alpha1",
    52  		Resource: "ingressroutetcps",
    53  	}
    54  	ingressrouteUDPGVR = schema.GroupVersionResource{
    55  		Group:    "traefik.io",
    56  		Version:  "v1alpha1",
    57  		Resource: "ingressrouteudps",
    58  	}
    59  	oldIngressrouteGVR = schema.GroupVersionResource{
    60  		Group:    "traefik.containo.us",
    61  		Version:  "v1alpha1",
    62  		Resource: "ingressroutes",
    63  	}
    64  	oldIngressrouteTCPGVR = schema.GroupVersionResource{
    65  		Group:    "traefik.containo.us",
    66  		Version:  "v1alpha1",
    67  		Resource: "ingressroutetcps",
    68  	}
    69  	oldIngressrouteUDPGVR = schema.GroupVersionResource{
    70  		Group:    "traefik.containo.us",
    71  		Version:  "v1alpha1",
    72  		Resource: "ingressrouteudps",
    73  	}
    74  )
    75  
    76  var (
    77  	traefikHostExtractor  = regexp.MustCompile(`(?:HostSNI|HostHeader|Host)\s*\(\s*(\x60.*?\x60)\s*\)`)
    78  	traefikValueProcessor = regexp.MustCompile(`\x60([^,\x60]+)\x60`)
    79  )
    80  
    81  type traefikSource struct {
    82  	annotationFilter           string
    83  	ignoreHostnameAnnotation   bool
    84  	dynamicKubeClient          dynamic.Interface
    85  	ingressRouteInformer       informers.GenericInformer
    86  	ingressRouteTcpInformer    informers.GenericInformer
    87  	ingressRouteUdpInformer    informers.GenericInformer
    88  	oldIngressRouteInformer    informers.GenericInformer
    89  	oldIngressRouteTcpInformer informers.GenericInformer
    90  	oldIngressRouteUdpInformer informers.GenericInformer
    91  	kubeClient                 kubernetes.Interface
    92  	namespace                  string
    93  	unstructuredConverter      *unstructuredConverter
    94  }
    95  
    96  func NewTraefikSource(ctx context.Context, dynamicKubeClient dynamic.Interface, kubeClient kubernetes.Interface, namespace string, annotationFilter string, ignoreHostnameAnnotation bool, disableLegacy bool, disableNew bool) (Source, error) {
    97  	// Use shared informer to listen for add/update/delete of Host in the specified namespace.
    98  	// Set resync period to 0, to prevent processing when nothing has changed.
    99  	informerFactory := dynamicinformer.NewFilteredDynamicSharedInformerFactory(dynamicKubeClient, 0, namespace, nil)
   100  	var ingressRouteInformer, ingressRouteTcpInformer, ingressRouteUdpInformer informers.GenericInformer
   101  	var oldIngressRouteInformer, oldIngressRouteTcpInformer, oldIngressRouteUdpInformer informers.GenericInformer
   102  
   103  	// Add default resource event handlers to properly initialize informers.
   104  	if !disableNew {
   105  		ingressRouteInformer = informerFactory.ForResource(ingressrouteGVR)
   106  		ingressRouteTcpInformer = informerFactory.ForResource(ingressrouteTCPGVR)
   107  		ingressRouteUdpInformer = informerFactory.ForResource(ingressrouteUDPGVR)
   108  		ingressRouteInformer.Informer().AddEventHandler(
   109  			cache.ResourceEventHandlerFuncs{
   110  				AddFunc: func(obj interface{}) {},
   111  			},
   112  		)
   113  		ingressRouteTcpInformer.Informer().AddEventHandler(
   114  			cache.ResourceEventHandlerFuncs{
   115  				AddFunc: func(obj interface{}) {},
   116  			},
   117  		)
   118  		ingressRouteUdpInformer.Informer().AddEventHandler(
   119  			cache.ResourceEventHandlerFuncs{
   120  				AddFunc: func(obj interface{}) {},
   121  			},
   122  		)
   123  	}
   124  	if !disableLegacy {
   125  		oldIngressRouteInformer = informerFactory.ForResource(oldIngressrouteGVR)
   126  		oldIngressRouteTcpInformer = informerFactory.ForResource(oldIngressrouteTCPGVR)
   127  		oldIngressRouteUdpInformer = informerFactory.ForResource(oldIngressrouteUDPGVR)
   128  		oldIngressRouteInformer.Informer().AddEventHandler(
   129  			cache.ResourceEventHandlerFuncs{
   130  				AddFunc: func(obj interface{}) {},
   131  			},
   132  		)
   133  		oldIngressRouteTcpInformer.Informer().AddEventHandler(
   134  			cache.ResourceEventHandlerFuncs{
   135  				AddFunc: func(obj interface{}) {},
   136  			},
   137  		)
   138  		oldIngressRouteUdpInformer.Informer().AddEventHandler(
   139  			cache.ResourceEventHandlerFuncs{
   140  				AddFunc: func(obj interface{}) {},
   141  			},
   142  		)
   143  	}
   144  
   145  	informerFactory.Start((ctx.Done()))
   146  
   147  	// wait for the local cache to be populated.
   148  	if err := waitForDynamicCacheSync(context.Background(), informerFactory); err != nil {
   149  		return nil, err
   150  	}
   151  
   152  	uc, err := newTraefikUnstructuredConverter()
   153  	if err != nil {
   154  		return nil, errors.Wrapf(err, "failed to setup Unstructured Converter")
   155  	}
   156  
   157  	return &traefikSource{
   158  		annotationFilter:           annotationFilter,
   159  		ignoreHostnameAnnotation:   ignoreHostnameAnnotation,
   160  		dynamicKubeClient:          dynamicKubeClient,
   161  		ingressRouteInformer:       ingressRouteInformer,
   162  		ingressRouteTcpInformer:    ingressRouteTcpInformer,
   163  		ingressRouteUdpInformer:    ingressRouteUdpInformer,
   164  		oldIngressRouteInformer:    oldIngressRouteInformer,
   165  		oldIngressRouteTcpInformer: oldIngressRouteTcpInformer,
   166  		oldIngressRouteUdpInformer: oldIngressRouteUdpInformer,
   167  		kubeClient:                 kubeClient,
   168  		namespace:                  namespace,
   169  		unstructuredConverter:      uc,
   170  	}, nil
   171  }
   172  
   173  func (ts *traefikSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) {
   174  	var endpoints []*endpoint.Endpoint
   175  
   176  	if ts.ingressRouteInformer != nil {
   177  		ingressRouteEndpoints, err := ts.ingressRouteEndpoints()
   178  		if err != nil {
   179  			return nil, err
   180  		}
   181  		endpoints = append(endpoints, ingressRouteEndpoints...)
   182  	}
   183  	if ts.oldIngressRouteInformer != nil {
   184  		oldIngressRouteEndpoints, err := ts.oldIngressRouteEndpoints()
   185  		if err != nil {
   186  			return nil, err
   187  		}
   188  		endpoints = append(endpoints, oldIngressRouteEndpoints...)
   189  	}
   190  	if ts.ingressRouteTcpInformer != nil {
   191  		ingressRouteTcpEndpoints, err := ts.ingressRouteTCPEndpoints()
   192  		if err != nil {
   193  			return nil, err
   194  		}
   195  		endpoints = append(endpoints, ingressRouteTcpEndpoints...)
   196  	}
   197  	if ts.oldIngressRouteTcpInformer != nil {
   198  		oldIngressRouteTcpEndpoints, err := ts.oldIngressRouteTCPEndpoints()
   199  		if err != nil {
   200  			return nil, err
   201  		}
   202  		endpoints = append(endpoints, oldIngressRouteTcpEndpoints...)
   203  	}
   204  	if ts.ingressRouteUdpInformer != nil {
   205  		ingressRouteUdpEndpoints, err := ts.ingressRouteUDPEndpoints()
   206  		if err != nil {
   207  			return nil, err
   208  		}
   209  		endpoints = append(endpoints, ingressRouteUdpEndpoints...)
   210  	}
   211  	if ts.oldIngressRouteUdpInformer != nil {
   212  		oldIngressRouteUdpEndpoints, err := ts.oldIngressRouteUDPEndpoints()
   213  		if err != nil {
   214  			return nil, err
   215  		}
   216  		endpoints = append(endpoints, oldIngressRouteUdpEndpoints...)
   217  	}
   218  
   219  	for _, ep := range endpoints {
   220  		sort.Sort(ep.Targets)
   221  	}
   222  
   223  	return endpoints, nil
   224  }
   225  
   226  // ingressRouteEndpoints extracts endpoints from all IngressRoute objects
   227  func (ts *traefikSource) ingressRouteEndpoints() ([]*endpoint.Endpoint, error) {
   228  	var endpoints []*endpoint.Endpoint
   229  
   230  	irs, err := ts.ingressRouteInformer.Lister().ByNamespace(ts.namespace).List(labels.Everything())
   231  	if err != nil {
   232  		return nil, err
   233  	}
   234  
   235  	var ingressRoutes []*IngressRoute
   236  	for _, ingressRouteObj := range irs {
   237  		unstructuredHost, ok := ingressRouteObj.(*unstructured.Unstructured)
   238  		if !ok {
   239  			return nil, errors.New("could not convert IngressRoute object to unstructured")
   240  		}
   241  
   242  		ingressRoute := &IngressRoute{}
   243  		err := ts.unstructuredConverter.scheme.Convert(unstructuredHost, ingressRoute, nil)
   244  		if err != nil {
   245  			return nil, err
   246  		}
   247  		ingressRoutes = append(ingressRoutes, ingressRoute)
   248  	}
   249  
   250  	ingressRoutes, err = ts.filterIngressRouteByAnnotation(ingressRoutes)
   251  	if err != nil {
   252  		return nil, errors.Wrap(err, "failed to filter IngressRoute")
   253  	}
   254  
   255  	for _, ingressRoute := range ingressRoutes {
   256  		var targets endpoint.Targets
   257  
   258  		targets = append(targets, getTargetsFromTargetAnnotation(ingressRoute.Annotations)...)
   259  
   260  		fullname := fmt.Sprintf("%s/%s", ingressRoute.Namespace, ingressRoute.Name)
   261  
   262  		ingressEndpoints, err := ts.endpointsFromIngressRoute(ingressRoute, targets)
   263  		if err != nil {
   264  			return nil, err
   265  		}
   266  		if len(ingressEndpoints) == 0 {
   267  			log.Debugf("No endpoints could be generated from Host %s", fullname)
   268  			continue
   269  		}
   270  
   271  		log.Debugf("Endpoints generated from IngressRoute: %s: %v", fullname, ingressEndpoints)
   272  		ts.setDualstackLabelIngressRoute(ingressRoute, ingressEndpoints)
   273  		endpoints = append(endpoints, ingressEndpoints...)
   274  	}
   275  
   276  	return endpoints, nil
   277  }
   278  
   279  // ingressRouteTCPEndpoints extracts endpoints from all IngressRouteTCP objects
   280  func (ts *traefikSource) ingressRouteTCPEndpoints() ([]*endpoint.Endpoint, error) {
   281  	var endpoints []*endpoint.Endpoint
   282  
   283  	irs, err := ts.ingressRouteTcpInformer.Lister().ByNamespace(ts.namespace).List(labels.Everything())
   284  	if err != nil {
   285  		return nil, err
   286  	}
   287  
   288  	var ingressRouteTCPs []*IngressRouteTCP
   289  	for _, ingressRouteTCPObj := range irs {
   290  		unstructuredHost, ok := ingressRouteTCPObj.(*unstructured.Unstructured)
   291  		if !ok {
   292  			return nil, errors.New("could not convert IngressRouteTCP object to unstructured")
   293  		}
   294  
   295  		ingressRouteTCP := &IngressRouteTCP{}
   296  		err := ts.unstructuredConverter.scheme.Convert(unstructuredHost, ingressRouteTCP, nil)
   297  		if err != nil {
   298  			return nil, err
   299  		}
   300  		ingressRouteTCPs = append(ingressRouteTCPs, ingressRouteTCP)
   301  	}
   302  
   303  	ingressRouteTCPs, err = ts.filterIngressRouteTcpByAnnotations(ingressRouteTCPs)
   304  	if err != nil {
   305  		return nil, errors.Wrap(err, "failed to filter IngressRouteTCP")
   306  	}
   307  
   308  	for _, ingressRouteTCP := range ingressRouteTCPs {
   309  		var targets endpoint.Targets
   310  
   311  		targets = append(targets, getTargetsFromTargetAnnotation(ingressRouteTCP.Annotations)...)
   312  
   313  		fullname := fmt.Sprintf("%s/%s", ingressRouteTCP.Namespace, ingressRouteTCP.Name)
   314  
   315  		ingressEndpoints, err := ts.endpointsFromIngressRouteTCP(ingressRouteTCP, targets)
   316  		if err != nil {
   317  			return nil, err
   318  		}
   319  		if len(ingressEndpoints) == 0 {
   320  			log.Debugf("No endpoints could be generated from Host %s", fullname)
   321  			continue
   322  		}
   323  
   324  		log.Debugf("Endpoints generated from IngressRouteTCP: %s: %v", fullname, ingressEndpoints)
   325  		ts.setDualstackLabelIngressRouteTCP(ingressRouteTCP, ingressEndpoints)
   326  		endpoints = append(endpoints, ingressEndpoints...)
   327  	}
   328  
   329  	return endpoints, nil
   330  }
   331  
   332  // ingressRouteUDPEndpoints extracts endpoints from all IngressRouteUDP objects
   333  func (ts *traefikSource) ingressRouteUDPEndpoints() ([]*endpoint.Endpoint, error) {
   334  	var endpoints []*endpoint.Endpoint
   335  
   336  	irs, err := ts.ingressRouteUdpInformer.Lister().ByNamespace(ts.namespace).List(labels.Everything())
   337  	if err != nil {
   338  		return nil, err
   339  	}
   340  
   341  	var ingressRouteUDPs []*IngressRouteUDP
   342  	for _, ingressRouteUDPObj := range irs {
   343  		unstructuredHost, ok := ingressRouteUDPObj.(*unstructured.Unstructured)
   344  		if !ok {
   345  			return nil, errors.New("could not convert IngressRouteUDP object to unstructured")
   346  		}
   347  
   348  		ingressRoute := &IngressRouteUDP{}
   349  		err := ts.unstructuredConverter.scheme.Convert(unstructuredHost, ingressRoute, nil)
   350  		if err != nil {
   351  			return nil, err
   352  		}
   353  		ingressRouteUDPs = append(ingressRouteUDPs, ingressRoute)
   354  	}
   355  
   356  	ingressRouteUDPs, err = ts.filterIngressRouteUdpByAnnotations(ingressRouteUDPs)
   357  	if err != nil {
   358  		return nil, errors.Wrap(err, "failed to filter IngressRouteUDP")
   359  	}
   360  
   361  	for _, ingressRouteUDP := range ingressRouteUDPs {
   362  		var targets endpoint.Targets
   363  
   364  		targets = append(targets, getTargetsFromTargetAnnotation(ingressRouteUDP.Annotations)...)
   365  
   366  		fullname := fmt.Sprintf("%s/%s", ingressRouteUDP.Namespace, ingressRouteUDP.Name)
   367  
   368  		ingressEndpoints, err := ts.endpointsFromIngressRouteUDP(ingressRouteUDP, targets)
   369  		if err != nil {
   370  			return nil, err
   371  		}
   372  		if len(ingressEndpoints) == 0 {
   373  			log.Debugf("No endpoints could be generated from Host %s", fullname)
   374  			continue
   375  		}
   376  
   377  		log.Debugf("Endpoints generated from IngressRouteUDP: %s: %v", fullname, ingressEndpoints)
   378  		ts.setDualstackLabelIngressRouteUDP(ingressRouteUDP, ingressEndpoints)
   379  		endpoints = append(endpoints, ingressEndpoints...)
   380  	}
   381  
   382  	return endpoints, nil
   383  }
   384  
   385  // oldIngressRouteEndpoints extracts endpoints from all IngressRoute objects
   386  func (ts *traefikSource) oldIngressRouteEndpoints() ([]*endpoint.Endpoint, error) {
   387  	var endpoints []*endpoint.Endpoint
   388  
   389  	irs, err := ts.oldIngressRouteInformer.Lister().ByNamespace(ts.namespace).List(labels.Everything())
   390  	if err != nil {
   391  		return nil, err
   392  	}
   393  
   394  	var ingressRoutes []*IngressRoute
   395  	for _, ingressRouteObj := range irs {
   396  		unstructuredHost, ok := ingressRouteObj.(*unstructured.Unstructured)
   397  		if !ok {
   398  			return nil, errors.New("could not convert IngressRoute object to unstructured")
   399  		}
   400  
   401  		ingressRoute := &IngressRoute{}
   402  		err := ts.unstructuredConverter.scheme.Convert(unstructuredHost, ingressRoute, nil)
   403  		if err != nil {
   404  			return nil, err
   405  		}
   406  		ingressRoutes = append(ingressRoutes, ingressRoute)
   407  	}
   408  
   409  	ingressRoutes, err = ts.filterIngressRouteByAnnotation(ingressRoutes)
   410  	if err != nil {
   411  		return nil, errors.Wrap(err, "failed to filter IngressRoute")
   412  	}
   413  
   414  	for _, ingressRoute := range ingressRoutes {
   415  		var targets endpoint.Targets
   416  
   417  		targets = append(targets, getTargetsFromTargetAnnotation(ingressRoute.Annotations)...)
   418  
   419  		fullname := fmt.Sprintf("%s/%s", ingressRoute.Namespace, ingressRoute.Name)
   420  
   421  		ingressEndpoints, err := ts.endpointsFromIngressRoute(ingressRoute, targets)
   422  		if err != nil {
   423  			return nil, err
   424  		}
   425  		if len(ingressEndpoints) == 0 {
   426  			log.Debugf("No endpoints could be generated from Host %s", fullname)
   427  			continue
   428  		}
   429  
   430  		log.Debugf("Endpoints generated from IngressRoute: %s: %v", fullname, ingressEndpoints)
   431  		ts.setDualstackLabelIngressRoute(ingressRoute, ingressEndpoints)
   432  		endpoints = append(endpoints, ingressEndpoints...)
   433  	}
   434  
   435  	return endpoints, nil
   436  }
   437  
   438  // oldIngressRouteTCPEndpoints extracts endpoints from all IngressRouteTCP objects
   439  func (ts *traefikSource) oldIngressRouteTCPEndpoints() ([]*endpoint.Endpoint, error) {
   440  	var endpoints []*endpoint.Endpoint
   441  
   442  	irs, err := ts.oldIngressRouteTcpInformer.Lister().ByNamespace(ts.namespace).List(labels.Everything())
   443  	if err != nil {
   444  		return nil, err
   445  	}
   446  
   447  	var ingressRouteTCPs []*IngressRouteTCP
   448  	for _, ingressRouteTCPObj := range irs {
   449  		unstructuredHost, ok := ingressRouteTCPObj.(*unstructured.Unstructured)
   450  		if !ok {
   451  			return nil, errors.New("could not convert IngressRouteTCP object to unstructured")
   452  		}
   453  
   454  		ingressRouteTCP := &IngressRouteTCP{}
   455  		err := ts.unstructuredConverter.scheme.Convert(unstructuredHost, ingressRouteTCP, nil)
   456  		if err != nil {
   457  			return nil, err
   458  		}
   459  		ingressRouteTCPs = append(ingressRouteTCPs, ingressRouteTCP)
   460  	}
   461  
   462  	ingressRouteTCPs, err = ts.filterIngressRouteTcpByAnnotations(ingressRouteTCPs)
   463  	if err != nil {
   464  		return nil, errors.Wrap(err, "failed to filter IngressRouteTCP")
   465  	}
   466  
   467  	for _, ingressRouteTCP := range ingressRouteTCPs {
   468  		var targets endpoint.Targets
   469  
   470  		targets = append(targets, getTargetsFromTargetAnnotation(ingressRouteTCP.Annotations)...)
   471  
   472  		fullname := fmt.Sprintf("%s/%s", ingressRouteTCP.Namespace, ingressRouteTCP.Name)
   473  
   474  		ingressEndpoints, err := ts.endpointsFromIngressRouteTCP(ingressRouteTCP, targets)
   475  		if err != nil {
   476  			return nil, err
   477  		}
   478  		if len(ingressEndpoints) == 0 {
   479  			log.Debugf("No endpoints could be generated from Host %s", fullname)
   480  			continue
   481  		}
   482  
   483  		log.Debugf("Endpoints generated from IngressRouteTCP: %s: %v", fullname, ingressEndpoints)
   484  		ts.setDualstackLabelIngressRouteTCP(ingressRouteTCP, ingressEndpoints)
   485  		endpoints = append(endpoints, ingressEndpoints...)
   486  	}
   487  
   488  	return endpoints, nil
   489  }
   490  
   491  // oldIngressRouteUDPEndpoints extracts endpoints from all IngressRouteUDP objects
   492  func (ts *traefikSource) oldIngressRouteUDPEndpoints() ([]*endpoint.Endpoint, error) {
   493  	var endpoints []*endpoint.Endpoint
   494  
   495  	irs, err := ts.oldIngressRouteUdpInformer.Lister().ByNamespace(ts.namespace).List(labels.Everything())
   496  	if err != nil {
   497  		return nil, err
   498  	}
   499  
   500  	var ingressRouteUDPs []*IngressRouteUDP
   501  	for _, ingressRouteUDPObj := range irs {
   502  		unstructuredHost, ok := ingressRouteUDPObj.(*unstructured.Unstructured)
   503  		if !ok {
   504  			return nil, errors.New("could not convert IngressRouteUDP object to unstructured")
   505  		}
   506  
   507  		ingressRoute := &IngressRouteUDP{}
   508  		err := ts.unstructuredConverter.scheme.Convert(unstructuredHost, ingressRoute, nil)
   509  		if err != nil {
   510  			return nil, err
   511  		}
   512  		ingressRouteUDPs = append(ingressRouteUDPs, ingressRoute)
   513  	}
   514  
   515  	ingressRouteUDPs, err = ts.filterIngressRouteUdpByAnnotations(ingressRouteUDPs)
   516  	if err != nil {
   517  		return nil, errors.Wrap(err, "failed to filter IngressRouteUDP")
   518  	}
   519  
   520  	for _, ingressRouteUDP := range ingressRouteUDPs {
   521  		var targets endpoint.Targets
   522  
   523  		targets = append(targets, getTargetsFromTargetAnnotation(ingressRouteUDP.Annotations)...)
   524  
   525  		fullname := fmt.Sprintf("%s/%s", ingressRouteUDP.Namespace, ingressRouteUDP.Name)
   526  
   527  		ingressEndpoints, err := ts.endpointsFromIngressRouteUDP(ingressRouteUDP, targets)
   528  		if err != nil {
   529  			return nil, err
   530  		}
   531  		if len(ingressEndpoints) == 0 {
   532  			log.Debugf("No endpoints could be generated from Host %s", fullname)
   533  			continue
   534  		}
   535  
   536  		log.Debugf("Endpoints generated from IngressRouteUDP: %s: %v", fullname, ingressEndpoints)
   537  		ts.setDualstackLabelIngressRouteUDP(ingressRouteUDP, ingressEndpoints)
   538  		endpoints = append(endpoints, ingressEndpoints...)
   539  	}
   540  
   541  	return endpoints, nil
   542  }
   543  
   544  // filterIngressRouteByAnnotation filters a list of IngressRoute by a given annotation selector.
   545  func (ts *traefikSource) filterIngressRouteByAnnotation(ingressRoutes []*IngressRoute) ([]*IngressRoute, error) {
   546  	labelSelector, err := metav1.ParseToLabelSelector(ts.annotationFilter)
   547  	if err != nil {
   548  		return nil, err
   549  	}
   550  	selector, err := metav1.LabelSelectorAsSelector(labelSelector)
   551  	if err != nil {
   552  		return nil, err
   553  	}
   554  
   555  	// empty filter returns original list
   556  	if selector.Empty() {
   557  		return ingressRoutes, nil
   558  	}
   559  
   560  	filteredList := []*IngressRoute{}
   561  
   562  	for _, ingressRoute := range ingressRoutes {
   563  		// convert the IngressRoute's annotations to an equivalent label selector
   564  		annotations := labels.Set(ingressRoute.Annotations)
   565  
   566  		// include IngressRoute if its annotations match the selector
   567  		if selector.Matches(annotations) {
   568  			filteredList = append(filteredList, ingressRoute)
   569  		}
   570  	}
   571  
   572  	return filteredList, nil
   573  }
   574  
   575  // filterIngressRouteTcpByAnnotations filters a list of IngressRouteTCP by a given annotation selector.
   576  func (ts *traefikSource) filterIngressRouteTcpByAnnotations(ingressRoutes []*IngressRouteTCP) ([]*IngressRouteTCP, error) {
   577  	labelSelector, err := metav1.ParseToLabelSelector(ts.annotationFilter)
   578  	if err != nil {
   579  		return nil, err
   580  	}
   581  	selector, err := metav1.LabelSelectorAsSelector(labelSelector)
   582  	if err != nil {
   583  		return nil, err
   584  	}
   585  
   586  	// empty filter returns original list
   587  	if selector.Empty() {
   588  		return ingressRoutes, nil
   589  	}
   590  
   591  	filteredList := []*IngressRouteTCP{}
   592  
   593  	for _, ingressRoute := range ingressRoutes {
   594  		// convert the IngressRoute's annotations to an equivalent label selector
   595  		annotations := labels.Set(ingressRoute.Annotations)
   596  
   597  		// include IngressRoute if its annotations match the selector
   598  		if selector.Matches(annotations) {
   599  			filteredList = append(filteredList, ingressRoute)
   600  		}
   601  	}
   602  
   603  	return filteredList, nil
   604  }
   605  
   606  // filterIngressRouteUdpByAnnotations filters a list of IngressRoute by a given annotation selector.
   607  func (ts *traefikSource) filterIngressRouteUdpByAnnotations(ingressRoutes []*IngressRouteUDP) ([]*IngressRouteUDP, error) {
   608  	labelSelector, err := metav1.ParseToLabelSelector(ts.annotationFilter)
   609  	if err != nil {
   610  		return nil, err
   611  	}
   612  	selector, err := metav1.LabelSelectorAsSelector(labelSelector)
   613  	if err != nil {
   614  		return nil, err
   615  	}
   616  
   617  	// empty filter returns original list
   618  	if selector.Empty() {
   619  		return ingressRoutes, nil
   620  	}
   621  
   622  	filteredList := []*IngressRouteUDP{}
   623  
   624  	for _, ingressRoute := range ingressRoutes {
   625  		// convert the IngressRoute's annotations to an equivalent label selector
   626  		annotations := labels.Set(ingressRoute.Annotations)
   627  
   628  		// include IngressRoute if its annotations match the selector
   629  		if selector.Matches(annotations) {
   630  			filteredList = append(filteredList, ingressRoute)
   631  		}
   632  	}
   633  
   634  	return filteredList, nil
   635  }
   636  
   637  func (ts *traefikSource) setDualstackLabelIngressRoute(ingressRoute *IngressRoute, endpoints []*endpoint.Endpoint) {
   638  	val, ok := ingressRoute.Annotations[ALBDualstackAnnotationKey]
   639  	if ok && val == ALBDualstackAnnotationValue {
   640  		log.Debugf("Adding dualstack label to IngressRoute %s/%s.", ingressRoute.Namespace, ingressRoute.Name)
   641  		for _, ep := range endpoints {
   642  			ep.Labels[endpoint.DualstackLabelKey] = "true"
   643  		}
   644  	}
   645  }
   646  func (ts *traefikSource) setDualstackLabelIngressRouteTCP(ingressRoute *IngressRouteTCP, endpoints []*endpoint.Endpoint) {
   647  	val, ok := ingressRoute.Annotations[ALBDualstackAnnotationKey]
   648  	if ok && val == ALBDualstackAnnotationValue {
   649  		log.Debugf("Adding dualstack label to IngressRouteTCP %s/%s.", ingressRoute.Namespace, ingressRoute.Name)
   650  		for _, ep := range endpoints {
   651  			ep.Labels[endpoint.DualstackLabelKey] = "true"
   652  		}
   653  	}
   654  }
   655  func (ts *traefikSource) setDualstackLabelIngressRouteUDP(ingressRoute *IngressRouteUDP, endpoints []*endpoint.Endpoint) {
   656  	val, ok := ingressRoute.Annotations[ALBDualstackAnnotationKey]
   657  	if ok && val == ALBDualstackAnnotationValue {
   658  		log.Debugf("Adding dualstack label to IngressRouteUDP %s/%s.", ingressRoute.Namespace, ingressRoute.Name)
   659  		for _, ep := range endpoints {
   660  			ep.Labels[endpoint.DualstackLabelKey] = "true"
   661  		}
   662  	}
   663  }
   664  
   665  // endpointsFromIngressRoute extracts the endpoints from a IngressRoute object
   666  func (ts *traefikSource) endpointsFromIngressRoute(ingressRoute *IngressRoute, targets endpoint.Targets) ([]*endpoint.Endpoint, error) {
   667  	var endpoints []*endpoint.Endpoint
   668  
   669  	resource := fmt.Sprintf("ingressroute/%s/%s", ingressRoute.Namespace, ingressRoute.Name)
   670  
   671  	ttl := getTTLFromAnnotations(ingressRoute.Annotations, resource)
   672  
   673  	providerSpecific, setIdentifier := getProviderSpecificAnnotations(ingressRoute.Annotations)
   674  
   675  	if !ts.ignoreHostnameAnnotation {
   676  		hostnameList := getHostnamesFromAnnotations(ingressRoute.Annotations)
   677  		for _, hostname := range hostnameList {
   678  			endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier, resource)...)
   679  		}
   680  	}
   681  
   682  	for _, route := range ingressRoute.Spec.Routes {
   683  		match := route.Match
   684  
   685  		for _, hostEntry := range traefikHostExtractor.FindAllString(match, -1) {
   686  			for _, host := range traefikValueProcessor.FindAllString(hostEntry, -1) {
   687  				host = strings.TrimPrefix(host, "`")
   688  				host = strings.TrimSuffix(host, "`")
   689  
   690  				// Checking for host = * is required, as Host(`*`) can be set
   691  				if host != "*" && host != "" {
   692  					endpoints = append(endpoints, endpointsForHostname(host, targets, ttl, providerSpecific, setIdentifier, resource)...)
   693  				}
   694  			}
   695  		}
   696  	}
   697  
   698  	return endpoints, nil
   699  }
   700  
   701  // endpointsFromIngressRouteTCP extracts the endpoints from a IngressRouteTCP object
   702  func (ts *traefikSource) endpointsFromIngressRouteTCP(ingressRoute *IngressRouteTCP, targets endpoint.Targets) ([]*endpoint.Endpoint, error) {
   703  	var endpoints []*endpoint.Endpoint
   704  
   705  	resource := fmt.Sprintf("ingressroutetcp/%s/%s", ingressRoute.Namespace, ingressRoute.Name)
   706  
   707  	ttl := getTTLFromAnnotations(ingressRoute.Annotations, resource)
   708  
   709  	providerSpecific, setIdentifier := getProviderSpecificAnnotations(ingressRoute.Annotations)
   710  
   711  	if !ts.ignoreHostnameAnnotation {
   712  		hostnameList := getHostnamesFromAnnotations(ingressRoute.Annotations)
   713  		for _, hostname := range hostnameList {
   714  			endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier, resource)...)
   715  		}
   716  	}
   717  
   718  	for _, route := range ingressRoute.Spec.Routes {
   719  		match := route.Match
   720  
   721  		for _, hostEntry := range traefikHostExtractor.FindAllString(match, -1) {
   722  			for _, host := range traefikValueProcessor.FindAllString(hostEntry, -1) {
   723  				host = strings.TrimPrefix(host, "`")
   724  				host = strings.TrimSuffix(host, "`")
   725  
   726  				// Checking for host = * is required, as HostSNI(`*`) can be set
   727  				// in the case of TLS passthrough
   728  				if host != "*" && host != "" {
   729  					endpoints = append(endpoints, endpointsForHostname(host, targets, ttl, providerSpecific, setIdentifier, resource)...)
   730  				}
   731  			}
   732  		}
   733  	}
   734  
   735  	return endpoints, nil
   736  }
   737  
   738  // endpointsFromIngressRouteUDP extracts the endpoints from a IngressRouteUDP object
   739  func (ts *traefikSource) endpointsFromIngressRouteUDP(ingressRoute *IngressRouteUDP, targets endpoint.Targets) ([]*endpoint.Endpoint, error) {
   740  	var endpoints []*endpoint.Endpoint
   741  
   742  	resource := fmt.Sprintf("ingressrouteudp/%s/%s", ingressRoute.Namespace, ingressRoute.Name)
   743  
   744  	ttl := getTTLFromAnnotations(ingressRoute.Annotations, resource)
   745  
   746  	providerSpecific, setIdentifier := getProviderSpecificAnnotations(ingressRoute.Annotations)
   747  
   748  	if !ts.ignoreHostnameAnnotation {
   749  		hostnameList := getHostnamesFromAnnotations(ingressRoute.Annotations)
   750  		for _, hostname := range hostnameList {
   751  			endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier, resource)...)
   752  		}
   753  	}
   754  
   755  	return endpoints, nil
   756  }
   757  
   758  func (ts *traefikSource) AddEventHandler(ctx context.Context, handler func()) {
   759  	// Right now there is no way to remove event handler from informer, see:
   760  	// https://github.com/kubernetes/kubernetes/issues/79610
   761  	log.Debug("Adding event handler for IngressRoute")
   762  	ts.ingressRouteInformer.Informer().AddEventHandler(eventHandlerFunc(handler))
   763  	ts.oldIngressRouteInformer.Informer().AddEventHandler(eventHandlerFunc(handler))
   764  	log.Debug("Adding event handler for IngressRouteTCP")
   765  	ts.ingressRouteTcpInformer.Informer().AddEventHandler(eventHandlerFunc(handler))
   766  	ts.oldIngressRouteTcpInformer.Informer().AddEventHandler(eventHandlerFunc(handler))
   767  	log.Debug("Adding event handler for IngressRouteUDP")
   768  	ts.ingressRouteUdpInformer.Informer().AddEventHandler(eventHandlerFunc(handler))
   769  	ts.oldIngressRouteUdpInformer.Informer().AddEventHandler(eventHandlerFunc(handler))
   770  }
   771  
   772  // newTraefikUnstructuredConverter returns a new unstructuredConverter initialized
   773  func newTraefikUnstructuredConverter() (*unstructuredConverter, error) {
   774  	uc := &unstructuredConverter{
   775  		scheme: runtime.NewScheme(),
   776  	}
   777  
   778  	// Add the core types we need
   779  	uc.scheme.AddKnownTypes(ingressrouteGVR.GroupVersion(), &IngressRoute{}, &IngressRouteList{})
   780  	uc.scheme.AddKnownTypes(oldIngressrouteGVR.GroupVersion(), &IngressRoute{}, &IngressRouteList{})
   781  	uc.scheme.AddKnownTypes(ingressrouteTCPGVR.GroupVersion(), &IngressRouteTCP{}, &IngressRouteTCPList{})
   782  	uc.scheme.AddKnownTypes(oldIngressrouteTCPGVR.GroupVersion(), &IngressRouteTCP{}, &IngressRouteTCPList{})
   783  	uc.scheme.AddKnownTypes(ingressrouteUDPGVR.GroupVersion(), &IngressRouteUDP{}, &IngressRouteUDPList{})
   784  	uc.scheme.AddKnownTypes(oldIngressrouteUDPGVR.GroupVersion(), &IngressRouteUDP{}, &IngressRouteUDPList{})
   785  	if err := scheme.AddToScheme(uc.scheme); err != nil {
   786  		return nil, err
   787  	}
   788  
   789  	return uc, nil
   790  }
   791  
   792  // Basic redefinition of Traefik 2's CRD: https://github.com/traefik/traefik/tree/v2.8.7/pkg/provider/kubernetes/crd/traefik/v1alpha1
   793  
   794  // traefikIngressRouteSpec defines the desired state of IngressRoute.
   795  type traefikIngressRouteSpec struct {
   796  	// Routes defines the list of routes.
   797  	Routes []traefikRoute `json:"routes"`
   798  }
   799  
   800  // traefikRoute holds the HTTP route configuration.
   801  type traefikRoute struct {
   802  	// Match defines the router's rule.
   803  	// More info: https://doc.traefik.io/traefik/v2.9/routing/routers/#rule
   804  	Match string `json:"match"`
   805  }
   806  
   807  // IngressRoute is the CRD implementation of a Traefik HTTP Router.
   808  type IngressRoute struct {
   809  	metav1.TypeMeta `json:",inline"`
   810  	// Standard object's metadata.
   811  	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
   812  	metav1.ObjectMeta `json:"metadata"`
   813  
   814  	Spec traefikIngressRouteSpec `json:"spec"`
   815  }
   816  
   817  // IngressRouteList is a collection of IngressRoute.
   818  type IngressRouteList struct {
   819  	metav1.TypeMeta `json:",inline"`
   820  	// Standard object's metadata.
   821  	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
   822  	metav1.ListMeta `json:"metadata"`
   823  
   824  	// Items is the list of IngressRoute.
   825  	Items []IngressRoute `json:"items"`
   826  }
   827  
   828  // traefikIngressRouteTCPSpec defines the desired state of IngressRouteTCP.
   829  type traefikIngressRouteTCPSpec struct {
   830  	Routes []traefikRouteTCP `json:"routes"`
   831  }
   832  
   833  // traefikRouteTCP holds the TCP route configuration.
   834  type traefikRouteTCP struct {
   835  	// Match defines the router's rule.
   836  	// More info: https://doc.traefik.io/traefik/v2.9/routing/routers/#rule_1
   837  	Match string `json:"match"`
   838  }
   839  
   840  // IngressRouteTCP is the CRD implementation of a Traefik TCP Router.
   841  type IngressRouteTCP struct {
   842  	metav1.TypeMeta `json:",inline"`
   843  	// Standard object's metadata.
   844  	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
   845  	metav1.ObjectMeta `json:"metadata"`
   846  
   847  	Spec traefikIngressRouteTCPSpec `json:"spec"`
   848  }
   849  
   850  // IngressRouteTCPList is a collection of IngressRouteTCP.
   851  type IngressRouteTCPList struct {
   852  	metav1.TypeMeta `json:",inline"`
   853  	// Standard object's metadata.
   854  	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
   855  	metav1.ListMeta `json:"metadata"`
   856  
   857  	// Items is the list of IngressRouteTCP.
   858  	Items []IngressRouteTCP `json:"items"`
   859  }
   860  
   861  // IngressRouteUDP is a CRD implementation of a Traefik UDP Router.
   862  type IngressRouteUDP struct {
   863  	metav1.TypeMeta `json:",inline"`
   864  	// Standard object's metadata.
   865  	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
   866  	metav1.ObjectMeta `json:"metadata"`
   867  }
   868  
   869  // IngressRouteUDPList is a collection of IngressRouteUDP.
   870  type IngressRouteUDPList struct {
   871  	metav1.TypeMeta `json:",inline"`
   872  	// Standard object's metadata.
   873  	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
   874  	metav1.ListMeta `json:"metadata"`
   875  
   876  	// Items is the list of IngressRouteUDP.
   877  	Items []IngressRouteUDP `json:"items"`
   878  }
   879  
   880  // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
   881  func (in *IngressRoute) DeepCopyInto(out *IngressRoute) {
   882  	*out = *in
   883  	out.TypeMeta = in.TypeMeta
   884  	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
   885  	in.Spec.DeepCopyInto(&out.Spec)
   886  }
   887  
   888  // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressRoute.
   889  func (in *IngressRoute) DeepCopy() *IngressRoute {
   890  	if in == nil {
   891  		return nil
   892  	}
   893  	out := new(IngressRoute)
   894  	in.DeepCopyInto(out)
   895  	return out
   896  }
   897  
   898  // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
   899  func (in *IngressRoute) DeepCopyObject() runtime.Object {
   900  	if c := in.DeepCopy(); c != nil {
   901  		return c
   902  	}
   903  	return nil
   904  }
   905  
   906  // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
   907  func (in *IngressRouteList) DeepCopyInto(out *IngressRouteList) {
   908  	*out = *in
   909  	out.TypeMeta = in.TypeMeta
   910  	in.ListMeta.DeepCopyInto(&out.ListMeta)
   911  	if in.Items != nil {
   912  		in, out := &in.Items, &out.Items
   913  		*out = make([]IngressRoute, len(*in))
   914  		for i := range *in {
   915  			(*in)[i].DeepCopyInto(&(*out)[i])
   916  		}
   917  	}
   918  }
   919  
   920  // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressRouteList.
   921  func (in *IngressRouteList) DeepCopy() *IngressRouteList {
   922  	if in == nil {
   923  		return nil
   924  	}
   925  	out := new(IngressRouteList)
   926  	in.DeepCopyInto(out)
   927  	return out
   928  }
   929  
   930  // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
   931  func (in *IngressRouteList) DeepCopyObject() runtime.Object {
   932  	if c := in.DeepCopy(); c != nil {
   933  		return c
   934  	}
   935  	return nil
   936  }
   937  
   938  // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
   939  func (in *traefikIngressRouteSpec) DeepCopyInto(out *traefikIngressRouteSpec) {
   940  	*out = *in
   941  	if in.Routes != nil {
   942  		in, out := &in.Routes, &out.Routes
   943  		*out = make([]traefikRoute, len(*in))
   944  		for i := range *in {
   945  			(*in)[i].DeepCopyInto(&(*out)[i])
   946  		}
   947  	}
   948  }
   949  
   950  // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressRouteSpec.
   951  func (in *traefikIngressRouteSpec) DeepCopy() *traefikIngressRouteSpec {
   952  	if in == nil {
   953  		return nil
   954  	}
   955  	out := new(traefikIngressRouteSpec)
   956  	in.DeepCopyInto(out)
   957  	return out
   958  }
   959  
   960  // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
   961  func (in *traefikRoute) DeepCopyInto(out *traefikRoute) {
   962  	*out = *in
   963  }
   964  
   965  // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Route.
   966  func (in *traefikRoute) DeepCopy() *traefikRoute {
   967  	if in == nil {
   968  		return nil
   969  	}
   970  	out := new(traefikRoute)
   971  	in.DeepCopyInto(out)
   972  	return out
   973  }
   974  
   975  // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
   976  func (in *IngressRouteTCP) DeepCopyInto(out *IngressRouteTCP) {
   977  	*out = *in
   978  	out.TypeMeta = in.TypeMeta
   979  	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
   980  	in.Spec.DeepCopyInto(&out.Spec)
   981  }
   982  
   983  // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressRouteTCP.
   984  func (in *IngressRouteTCP) DeepCopy() *IngressRouteTCP {
   985  	if in == nil {
   986  		return nil
   987  	}
   988  	out := new(IngressRouteTCP)
   989  	in.DeepCopyInto(out)
   990  	return out
   991  }
   992  
   993  // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
   994  func (in *IngressRouteTCP) DeepCopyObject() runtime.Object {
   995  	if c := in.DeepCopy(); c != nil {
   996  		return c
   997  	}
   998  	return nil
   999  }
  1000  
  1001  // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
  1002  func (in *IngressRouteTCPList) DeepCopyInto(out *IngressRouteTCPList) {
  1003  	*out = *in
  1004  	out.TypeMeta = in.TypeMeta
  1005  	in.ListMeta.DeepCopyInto(&out.ListMeta)
  1006  	if in.Items != nil {
  1007  		in, out := &in.Items, &out.Items
  1008  		*out = make([]IngressRouteTCP, len(*in))
  1009  		for i := range *in {
  1010  			(*in)[i].DeepCopyInto(&(*out)[i])
  1011  		}
  1012  	}
  1013  }
  1014  
  1015  // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressRouteTCPList.
  1016  func (in *IngressRouteTCPList) DeepCopy() *IngressRouteTCPList {
  1017  	if in == nil {
  1018  		return nil
  1019  	}
  1020  	out := new(IngressRouteTCPList)
  1021  	in.DeepCopyInto(out)
  1022  	return out
  1023  }
  1024  
  1025  // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
  1026  func (in *IngressRouteTCPList) DeepCopyObject() runtime.Object {
  1027  	if c := in.DeepCopy(); c != nil {
  1028  		return c
  1029  	}
  1030  	return nil
  1031  }
  1032  
  1033  // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
  1034  func (in *traefikIngressRouteTCPSpec) DeepCopyInto(out *traefikIngressRouteTCPSpec) {
  1035  	*out = *in
  1036  	if in.Routes != nil {
  1037  		in, out := &in.Routes, &out.Routes
  1038  		*out = make([]traefikRouteTCP, len(*in))
  1039  		for i := range *in {
  1040  			(*in)[i].DeepCopyInto(&(*out)[i])
  1041  		}
  1042  	}
  1043  }
  1044  
  1045  // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressRouteTCPSpec.
  1046  func (in *traefikIngressRouteTCPSpec) DeepCopy() *traefikIngressRouteTCPSpec {
  1047  	if in == nil {
  1048  		return nil
  1049  	}
  1050  	out := new(traefikIngressRouteTCPSpec)
  1051  	in.DeepCopyInto(out)
  1052  	return out
  1053  }
  1054  
  1055  // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
  1056  func (in *traefikRouteTCP) DeepCopyInto(out *traefikRouteTCP) {
  1057  	*out = *in
  1058  }
  1059  
  1060  // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteTCP.
  1061  func (in *traefikRouteTCP) DeepCopy() *traefikRouteTCP {
  1062  	if in == nil {
  1063  		return nil
  1064  	}
  1065  	out := new(traefikRouteTCP)
  1066  	in.DeepCopyInto(out)
  1067  	return out
  1068  }
  1069  
  1070  // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
  1071  func (in *IngressRouteUDP) DeepCopyInto(out *IngressRouteUDP) {
  1072  	*out = *in
  1073  	out.TypeMeta = in.TypeMeta
  1074  	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
  1075  }
  1076  
  1077  // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressRouteUDP.
  1078  func (in *IngressRouteUDP) DeepCopy() *IngressRouteUDP {
  1079  	if in == nil {
  1080  		return nil
  1081  	}
  1082  	out := new(IngressRouteUDP)
  1083  	in.DeepCopyInto(out)
  1084  	return out
  1085  }
  1086  
  1087  // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
  1088  func (in *IngressRouteUDP) DeepCopyObject() runtime.Object {
  1089  	if c := in.DeepCopy(); c != nil {
  1090  		return c
  1091  	}
  1092  	return nil
  1093  }
  1094  
  1095  // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
  1096  func (in *IngressRouteUDPList) DeepCopyInto(out *IngressRouteUDPList) {
  1097  	*out = *in
  1098  	out.TypeMeta = in.TypeMeta
  1099  	in.ListMeta.DeepCopyInto(&out.ListMeta)
  1100  	if in.Items != nil {
  1101  		in, out := &in.Items, &out.Items
  1102  		*out = make([]IngressRouteUDP, len(*in))
  1103  		for i := range *in {
  1104  			(*in)[i].DeepCopyInto(&(*out)[i])
  1105  		}
  1106  	}
  1107  }
  1108  
  1109  // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressRouteUDPList.
  1110  func (in *IngressRouteUDPList) DeepCopy() *IngressRouteUDPList {
  1111  	if in == nil {
  1112  		return nil
  1113  	}
  1114  	out := new(IngressRouteUDPList)
  1115  	in.DeepCopyInto(out)
  1116  	return out
  1117  }
  1118  
  1119  // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
  1120  func (in *IngressRouteUDPList) DeepCopyObject() runtime.Object {
  1121  	if c := in.DeepCopy(); c != nil {
  1122  		return c
  1123  	}
  1124  	return nil
  1125  }