mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2026-05-04 22:26:11 +02:00
chore(source/traefik_proxy): code coverage and refactoring (#5380)
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
This commit is contained in:
parent
52382e7183
commit
4ea5f9df60
@ -171,7 +171,7 @@ func NewTraefikSource(ctx context.Context, dynamicKubeClient dynamic.Interface,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ts *traefikSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
||||
func (ts *traefikSource) Endpoints(_ context.Context) ([]*endpoint.Endpoint, error) {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
if ts.ingressRouteInformer != nil {
|
||||
@ -226,54 +226,18 @@ func (ts *traefikSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, e
|
||||
|
||||
// ingressRouteEndpoints extracts endpoints from all IngressRoute objects
|
||||
func (ts *traefikSource) ingressRouteEndpoints() ([]*endpoint.Endpoint, error) {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
irs, err := ts.ingressRouteInformer.Lister().ByNamespace(ts.namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ingressRoutes []*IngressRoute
|
||||
for _, ingressRouteObj := range irs {
|
||||
unstructuredHost, ok := ingressRouteObj.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
return nil, errors.New("could not convert IngressRoute object to unstructured")
|
||||
}
|
||||
|
||||
ingressRoute := &IngressRoute{}
|
||||
err := ts.unstructuredConverter.scheme.Convert(unstructuredHost, ingressRoute, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ingressRoutes = append(ingressRoutes, ingressRoute)
|
||||
}
|
||||
|
||||
ingressRoutes, err = ts.filterIngressRouteByAnnotation(ingressRoutes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to filter IngressRoute: %w", err)
|
||||
}
|
||||
|
||||
for _, ingressRoute := range ingressRoutes {
|
||||
var targets endpoint.Targets
|
||||
|
||||
targets = append(targets, annotations.TargetsFromTargetAnnotation(ingressRoute.Annotations)...)
|
||||
|
||||
fullname := fmt.Sprintf("%s/%s", ingressRoute.Namespace, ingressRoute.Name)
|
||||
|
||||
ingressEndpoints, err := ts.endpointsFromIngressRoute(ingressRoute, targets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ingressEndpoints) == 0 {
|
||||
log.Debugf("No endpoints could be generated from Host %s", fullname)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debugf("Endpoints generated from IngressRoute: %s: %v", fullname, ingressEndpoints)
|
||||
endpoints = append(endpoints, ingressEndpoints...)
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
return extractEndpoints[IngressRoute](
|
||||
ts.ingressRouteInformer.Lister(),
|
||||
ts.namespace,
|
||||
func(u *unstructured.Unstructured) (*IngressRoute, error) {
|
||||
typed := &IngressRoute{}
|
||||
return typed, ts.unstructuredConverter.scheme.Convert(u, typed, nil)
|
||||
},
|
||||
ts.filterIngressRouteByAnnotation,
|
||||
func(r *IngressRoute, targets endpoint.Targets) []*endpoint.Endpoint {
|
||||
return ts.endpointsFromIngressRoute(r, targets)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// ingressRouteTCPEndpoints extracts endpoints from all IngressRouteTCP objects
|
||||
@ -312,10 +276,7 @@ func (ts *traefikSource) ingressRouteTCPEndpoints() ([]*endpoint.Endpoint, error
|
||||
|
||||
fullname := fmt.Sprintf("%s/%s", ingressRouteTCP.Namespace, ingressRouteTCP.Name)
|
||||
|
||||
ingressEndpoints, err := ts.endpointsFromIngressRouteTCP(ingressRouteTCP, targets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ingressEndpoints := ts.endpointsFromIngressRouteTCP(ingressRouteTCP, targets)
|
||||
if len(ingressEndpoints) == 0 {
|
||||
log.Debugf("No endpoints could be generated from Host %s", fullname)
|
||||
continue
|
||||
@ -330,286 +291,85 @@ func (ts *traefikSource) ingressRouteTCPEndpoints() ([]*endpoint.Endpoint, error
|
||||
|
||||
// ingressRouteUDPEndpoints extracts endpoints from all IngressRouteUDP objects
|
||||
func (ts *traefikSource) ingressRouteUDPEndpoints() ([]*endpoint.Endpoint, error) {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
irs, err := ts.ingressRouteUdpInformer.Lister().ByNamespace(ts.namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ingressRouteUDPs []*IngressRouteUDP
|
||||
for _, ingressRouteUDPObj := range irs {
|
||||
unstructuredHost, ok := ingressRouteUDPObj.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
return nil, errors.New("could not convert IngressRouteUDP object to unstructured")
|
||||
}
|
||||
|
||||
ingressRoute := &IngressRouteUDP{}
|
||||
err := ts.unstructuredConverter.scheme.Convert(unstructuredHost, ingressRoute, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ingressRouteUDPs = append(ingressRouteUDPs, ingressRoute)
|
||||
}
|
||||
|
||||
ingressRouteUDPs, err = ts.filterIngressRouteUdpByAnnotations(ingressRouteUDPs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to filter IngressRouteUDP: %w", err)
|
||||
}
|
||||
|
||||
for _, ingressRouteUDP := range ingressRouteUDPs {
|
||||
var targets endpoint.Targets
|
||||
|
||||
targets = append(targets, annotations.TargetsFromTargetAnnotation(ingressRouteUDP.Annotations)...)
|
||||
|
||||
fullname := fmt.Sprintf("%s/%s", ingressRouteUDP.Namespace, ingressRouteUDP.Name)
|
||||
|
||||
ingressEndpoints, err := ts.endpointsFromIngressRouteUDP(ingressRouteUDP, targets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ingressEndpoints) == 0 {
|
||||
log.Debugf("No endpoints could be generated from Host %s", fullname)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debugf("Endpoints generated from IngressRouteUDP: %s: %v", fullname, ingressEndpoints)
|
||||
endpoints = append(endpoints, ingressEndpoints...)
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
return extractEndpoints[IngressRouteUDP](
|
||||
ts.ingressRouteUdpInformer.Lister(),
|
||||
ts.namespace,
|
||||
func(u *unstructured.Unstructured) (*IngressRouteUDP, error) {
|
||||
typed := &IngressRouteUDP{}
|
||||
return typed, ts.unstructuredConverter.scheme.Convert(u, typed, nil)
|
||||
},
|
||||
ts.filterIngressRouteUdpByAnnotations,
|
||||
ts.endpointsFromIngressRouteUDP,
|
||||
)
|
||||
}
|
||||
|
||||
// oldIngressRouteEndpoints extracts endpoints from all IngressRoute objects
|
||||
func (ts *traefikSource) oldIngressRouteEndpoints() ([]*endpoint.Endpoint, error) {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
irs, err := ts.oldIngressRouteInformer.Lister().ByNamespace(ts.namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ingressRoutes []*IngressRoute
|
||||
for _, ingressRouteObj := range irs {
|
||||
unstructuredHost, ok := ingressRouteObj.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
return nil, errors.New("could not convert IngressRoute object to unstructured")
|
||||
}
|
||||
|
||||
ingressRoute := &IngressRoute{}
|
||||
err := ts.unstructuredConverter.scheme.Convert(unstructuredHost, ingressRoute, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ingressRoutes = append(ingressRoutes, ingressRoute)
|
||||
}
|
||||
|
||||
ingressRoutes, err = ts.filterIngressRouteByAnnotation(ingressRoutes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to filter IngressRoute: %w", err)
|
||||
}
|
||||
|
||||
for _, ingressRoute := range ingressRoutes {
|
||||
var targets endpoint.Targets
|
||||
|
||||
targets = append(targets, annotations.TargetsFromTargetAnnotation(ingressRoute.Annotations)...)
|
||||
|
||||
fullname := fmt.Sprintf("%s/%s", ingressRoute.Namespace, ingressRoute.Name)
|
||||
|
||||
ingressEndpoints, err := ts.endpointsFromIngressRoute(ingressRoute, targets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ingressEndpoints) == 0 {
|
||||
log.Debugf("No endpoints could be generated from Host %s", fullname)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debugf("Endpoints generated from IngressRoute: %s: %v", fullname, ingressEndpoints)
|
||||
endpoints = append(endpoints, ingressEndpoints...)
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
return extractEndpoints[IngressRoute](
|
||||
ts.oldIngressRouteInformer.Lister(),
|
||||
ts.namespace,
|
||||
func(u *unstructured.Unstructured) (*IngressRoute, error) {
|
||||
typed := &IngressRoute{}
|
||||
return typed, ts.unstructuredConverter.scheme.Convert(u, typed, nil)
|
||||
},
|
||||
ts.filterIngressRouteByAnnotation,
|
||||
func(r *IngressRoute, targets endpoint.Targets) []*endpoint.Endpoint {
|
||||
return ts.endpointsFromIngressRoute(r, targets)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// oldIngressRouteTCPEndpoints extracts endpoints from all IngressRouteTCP objects
|
||||
func (ts *traefikSource) oldIngressRouteTCPEndpoints() ([]*endpoint.Endpoint, error) {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
irs, err := ts.oldIngressRouteTcpInformer.Lister().ByNamespace(ts.namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ingressRouteTCPs []*IngressRouteTCP
|
||||
for _, ingressRouteTCPObj := range irs {
|
||||
unstructuredHost, ok := ingressRouteTCPObj.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
return nil, errors.New("could not convert IngressRouteTCP object to unstructured")
|
||||
}
|
||||
|
||||
ingressRouteTCP := &IngressRouteTCP{}
|
||||
err := ts.unstructuredConverter.scheme.Convert(unstructuredHost, ingressRouteTCP, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ingressRouteTCPs = append(ingressRouteTCPs, ingressRouteTCP)
|
||||
}
|
||||
|
||||
ingressRouteTCPs, err = ts.filterIngressRouteTcpByAnnotations(ingressRouteTCPs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to filter IngressRouteTCP: %w", err)
|
||||
}
|
||||
|
||||
for _, ingressRouteTCP := range ingressRouteTCPs {
|
||||
var targets endpoint.Targets
|
||||
|
||||
targets = append(targets, annotations.TargetsFromTargetAnnotation(ingressRouteTCP.Annotations)...)
|
||||
|
||||
fullname := fmt.Sprintf("%s/%s", ingressRouteTCP.Namespace, ingressRouteTCP.Name)
|
||||
|
||||
ingressEndpoints, err := ts.endpointsFromIngressRouteTCP(ingressRouteTCP, targets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ingressEndpoints) == 0 {
|
||||
log.Debugf("No endpoints could be generated from Host %s", fullname)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debugf("Endpoints generated from IngressRouteTCP: %s: %v", fullname, ingressEndpoints)
|
||||
endpoints = append(endpoints, ingressEndpoints...)
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
return extractEndpoints[IngressRouteTCP](
|
||||
ts.oldIngressRouteTcpInformer.Lister(),
|
||||
ts.namespace,
|
||||
func(u *unstructured.Unstructured) (*IngressRouteTCP, error) {
|
||||
typed := &IngressRouteTCP{}
|
||||
return typed, ts.unstructuredConverter.scheme.Convert(u, typed, nil)
|
||||
},
|
||||
ts.filterIngressRouteTcpByAnnotations,
|
||||
ts.endpointsFromIngressRouteTCP,
|
||||
)
|
||||
}
|
||||
|
||||
// oldIngressRouteUDPEndpoints extracts endpoints from all IngressRouteUDP objects
|
||||
func (ts *traefikSource) oldIngressRouteUDPEndpoints() ([]*endpoint.Endpoint, error) {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
irs, err := ts.oldIngressRouteUdpInformer.Lister().ByNamespace(ts.namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ingressRouteUDPs []*IngressRouteUDP
|
||||
for _, ingressRouteUDPObj := range irs {
|
||||
unstructuredHost, ok := ingressRouteUDPObj.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
return nil, errors.New("could not convert IngressRouteUDP object to unstructured")
|
||||
}
|
||||
|
||||
ingressRoute := &IngressRouteUDP{}
|
||||
err := ts.unstructuredConverter.scheme.Convert(unstructuredHost, ingressRoute, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ingressRouteUDPs = append(ingressRouteUDPs, ingressRoute)
|
||||
}
|
||||
|
||||
ingressRouteUDPs, err = ts.filterIngressRouteUdpByAnnotations(ingressRouteUDPs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to filter IngressRouteUDP: %w", err)
|
||||
}
|
||||
|
||||
for _, ingressRouteUDP := range ingressRouteUDPs {
|
||||
var targets endpoint.Targets
|
||||
|
||||
targets = append(targets, annotations.TargetsFromTargetAnnotation(ingressRouteUDP.Annotations)...)
|
||||
|
||||
fullname := fmt.Sprintf("%s/%s", ingressRouteUDP.Namespace, ingressRouteUDP.Name)
|
||||
|
||||
ingressEndpoints, err := ts.endpointsFromIngressRouteUDP(ingressRouteUDP, targets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ingressEndpoints) == 0 {
|
||||
log.Debugf("No endpoints could be generated from Host %s", fullname)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debugf("Endpoints generated from IngressRouteUDP: %s: %v", fullname, ingressEndpoints)
|
||||
endpoints = append(endpoints, ingressEndpoints...)
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
return extractEndpoints[IngressRouteUDP](
|
||||
ts.oldIngressRouteUdpInformer.Lister(),
|
||||
ts.namespace,
|
||||
func(u *unstructured.Unstructured) (*IngressRouteUDP, error) {
|
||||
typed := &IngressRouteUDP{}
|
||||
return typed, ts.unstructuredConverter.scheme.Convert(u, typed, nil)
|
||||
},
|
||||
ts.filterIngressRouteUdpByAnnotations,
|
||||
ts.endpointsFromIngressRouteUDP,
|
||||
)
|
||||
}
|
||||
|
||||
// filterIngressRouteByAnnotation filters a list of IngressRoute by a given annotation selector.
|
||||
func (ts *traefikSource) filterIngressRouteByAnnotation(ingressRoutes []*IngressRoute) ([]*IngressRoute, error) {
|
||||
selector, err := annotations.ParseFilter(ts.annotationFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// empty filter returns original list
|
||||
if selector.Empty() {
|
||||
return ingressRoutes, nil
|
||||
}
|
||||
|
||||
filteredList := []*IngressRoute{}
|
||||
|
||||
for _, ingressRoute := range ingressRoutes {
|
||||
// include IngressRoute if its annotations match the selector
|
||||
if selector.Matches(labels.Set(ingressRoute.Annotations)) {
|
||||
filteredList = append(filteredList, ingressRoute)
|
||||
}
|
||||
}
|
||||
|
||||
return filteredList, nil
|
||||
func (ts *traefikSource) filterIngressRouteByAnnotation(input []*IngressRoute) ([]*IngressRoute, error) {
|
||||
return filterResourcesByAnnotations(input, ts.annotationFilter, func(ir *IngressRoute) map[string]string {
|
||||
return ir.Annotations
|
||||
})
|
||||
}
|
||||
|
||||
// filterIngressRouteTcpByAnnotations filters a list of IngressRouteTCP by a given annotation selector.
|
||||
func (ts *traefikSource) filterIngressRouteTcpByAnnotations(ingressRoutes []*IngressRouteTCP) ([]*IngressRouteTCP, error) {
|
||||
selector, err := annotations.ParseFilter(ts.annotationFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// empty filter returns original list
|
||||
if selector.Empty() {
|
||||
return ingressRoutes, nil
|
||||
}
|
||||
|
||||
var filteredList []*IngressRouteTCP
|
||||
|
||||
for _, ingressRoute := range ingressRoutes {
|
||||
// include IngressRoute if its annotations match the selector
|
||||
if selector.Matches(labels.Set(ingressRoute.Annotations)) {
|
||||
filteredList = append(filteredList, ingressRoute)
|
||||
}
|
||||
}
|
||||
|
||||
return filteredList, nil
|
||||
func (ts *traefikSource) filterIngressRouteTcpByAnnotations(input []*IngressRouteTCP) ([]*IngressRouteTCP, error) {
|
||||
return filterResourcesByAnnotations(input, ts.annotationFilter, func(ir *IngressRouteTCP) map[string]string {
|
||||
return ir.Annotations
|
||||
})
|
||||
}
|
||||
|
||||
// filterIngressRouteUdpByAnnotations filters a list of IngressRoute by a given annotation selector.
|
||||
func (ts *traefikSource) filterIngressRouteUdpByAnnotations(ingressRoutes []*IngressRouteUDP) ([]*IngressRouteUDP, error) {
|
||||
selector, err := annotations.ParseFilter(ts.annotationFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// empty filter returns original list
|
||||
if selector.Empty() {
|
||||
return ingressRoutes, nil
|
||||
}
|
||||
|
||||
var filteredList []*IngressRouteUDP
|
||||
|
||||
for _, ingressRoute := range ingressRoutes {
|
||||
// include IngressRoute if its annotations match the selector
|
||||
if selector.Matches(labels.Set(ingressRoute.Annotations)) {
|
||||
filteredList = append(filteredList, ingressRoute)
|
||||
}
|
||||
}
|
||||
|
||||
return filteredList, nil
|
||||
func (ts *traefikSource) filterIngressRouteUdpByAnnotations(input []*IngressRouteUDP) ([]*IngressRouteUDP, error) {
|
||||
return filterResourcesByAnnotations(input, ts.annotationFilter, func(ir *IngressRouteUDP) map[string]string {
|
||||
return ir.Annotations
|
||||
})
|
||||
}
|
||||
|
||||
// endpointsFromIngressRoute extracts the endpoints from a IngressRoute object
|
||||
func (ts *traefikSource) endpointsFromIngressRoute(ingressRoute *IngressRoute, targets endpoint.Targets) ([]*endpoint.Endpoint, error) {
|
||||
func (ts *traefikSource) endpointsFromIngressRoute(ingressRoute *IngressRoute, targets endpoint.Targets) []*endpoint.Endpoint {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
resource := fmt.Sprintf("ingressroute/%s/%s", ingressRoute.Namespace, ingressRoute.Name)
|
||||
@ -626,12 +386,9 @@ func (ts *traefikSource) endpointsFromIngressRoute(ingressRoute *IngressRoute, t
|
||||
}
|
||||
|
||||
for _, route := range ingressRoute.Spec.Routes {
|
||||
match := route.Match
|
||||
|
||||
for _, hostEntry := range traefikHostExtractor.FindAllString(match, -1) {
|
||||
for _, hostEntry := range traefikHostExtractor.FindAllString(route.Match, -1) {
|
||||
for _, host := range traefikValueProcessor.FindAllString(hostEntry, -1) {
|
||||
host = strings.TrimPrefix(host, "`")
|
||||
host = strings.TrimSuffix(host, "`")
|
||||
host = strings.Trim(host, "`")
|
||||
|
||||
// Checking for host = * is required, as Host(`*`) can be set
|
||||
if host != "*" && host != "" {
|
||||
@ -641,11 +398,11 @@ func (ts *traefikSource) endpointsFromIngressRoute(ingressRoute *IngressRoute, t
|
||||
}
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
return endpoints
|
||||
}
|
||||
|
||||
// endpointsFromIngressRouteTCP extracts the endpoints from a IngressRouteTCP object
|
||||
func (ts *traefikSource) endpointsFromIngressRouteTCP(ingressRoute *IngressRouteTCP, targets endpoint.Targets) ([]*endpoint.Endpoint, error) {
|
||||
func (ts *traefikSource) endpointsFromIngressRouteTCP(ingressRoute *IngressRouteTCP, targets endpoint.Targets) []*endpoint.Endpoint {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
resource := fmt.Sprintf("ingressroutetcp/%s/%s", ingressRoute.Namespace, ingressRoute.Name)
|
||||
@ -662,13 +419,9 @@ func (ts *traefikSource) endpointsFromIngressRouteTCP(ingressRoute *IngressRoute
|
||||
}
|
||||
|
||||
for _, route := range ingressRoute.Spec.Routes {
|
||||
match := route.Match
|
||||
|
||||
for _, hostEntry := range traefikHostExtractor.FindAllString(match, -1) {
|
||||
for _, hostEntry := range traefikHostExtractor.FindAllString(route.Match, -1) {
|
||||
for _, host := range traefikValueProcessor.FindAllString(hostEntry, -1) {
|
||||
host = strings.TrimPrefix(host, "`")
|
||||
host = strings.TrimSuffix(host, "`")
|
||||
|
||||
host = strings.Trim(host, "`")
|
||||
// Checking for host = * is required, as HostSNI(`*`) can be set
|
||||
// in the case of TLS passthrough
|
||||
if host != "*" && host != "" {
|
||||
@ -678,11 +431,11 @@ func (ts *traefikSource) endpointsFromIngressRouteTCP(ingressRoute *IngressRoute
|
||||
}
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
return endpoints
|
||||
}
|
||||
|
||||
// endpointsFromIngressRouteUDP extracts the endpoints from a IngressRouteUDP object
|
||||
func (ts *traefikSource) endpointsFromIngressRouteUDP(ingressRoute *IngressRouteUDP, targets endpoint.Targets) ([]*endpoint.Endpoint, error) {
|
||||
func (ts *traefikSource) endpointsFromIngressRouteUDP(ingressRoute *IngressRouteUDP, targets endpoint.Targets) []*endpoint.Endpoint {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
resource := fmt.Sprintf("ingressrouteudp/%s/%s", ingressRoute.Namespace, ingressRoute.Name)
|
||||
@ -698,7 +451,7 @@ func (ts *traefikSource) endpointsFromIngressRouteUDP(ingressRoute *IngressRoute
|
||||
}
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
return endpoints
|
||||
}
|
||||
|
||||
func (ts *traefikSource) AddEventHandler(ctx context.Context, handler func()) {
|
||||
@ -1081,3 +834,119 @@ func (in *IngressRouteUDPList) DeepCopyObject() runtime.Object {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// extractEndpoints is a generic function that extracts endpoints from Kubernetes resources.
|
||||
// It performs the following steps:
|
||||
// 1. Lists all objects in the specified namespace using the provided informer.
|
||||
// 2. Converts the unstructured objects to the desired type using the convertFunc.
|
||||
// 3. Filters the converted objects based on the provided filterFunc.
|
||||
// 4. Generates endpoints for each filtered object using the generateEndpoints function.
|
||||
// Returns a list of generated endpoints or an error if any step fails.
|
||||
func extractEndpoints[T any](
|
||||
informer cache.GenericLister,
|
||||
namespace string,
|
||||
convertFunc func(*unstructured.Unstructured) (*T, error),
|
||||
filterFunc func([]*T) ([]*T, error),
|
||||
generateEndpoints func(*T, endpoint.Targets) []*endpoint.Endpoint,
|
||||
) ([]*endpoint.Endpoint, error) {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
objs, err := informer.ByNamespace(namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var typedObjs []*T
|
||||
for _, obj := range objs {
|
||||
unstructuredObj, ok := obj.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
return nil, errors.New("failed to cast to unstructured.Unstructured")
|
||||
}
|
||||
|
||||
typed, err := convertFunc(unstructuredObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
typedObjs = append(typedObjs, typed)
|
||||
}
|
||||
|
||||
typedObjs, err = filterFunc(typedObjs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, item := range typedObjs {
|
||||
targets := annotations.TargetsFromTargetAnnotation(getAnnotations(item))
|
||||
|
||||
name := getObjectFullName(item)
|
||||
ingressEndpoints := generateEndpoints(item, targets)
|
||||
|
||||
if len(ingressEndpoints) == 0 {
|
||||
log.Debugf("No endpoints could be generated from Host %s", name)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debugf("Endpoints generated from %s: %v", name, ingressEndpoints)
|
||||
endpoints = append(endpoints, ingressEndpoints...)
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
// filterResourcesByAnnotations filters a list of resources based on a given annotation selector.
|
||||
// It performs the following steps:
|
||||
// 1. Parses the annotation filter into a label selector.
|
||||
// 2. Converts the label selector into a Kubernetes selector.
|
||||
// 3. If the selector is empty, returns the original list of resources.
|
||||
// 4. Iterates through the resources and matches their annotations against the selector.
|
||||
// 5. Returns the filtered list of resources or an error if any step fails.
|
||||
func filterResourcesByAnnotations[T any](resources []*T, annotationFilter string, getAnnotations func(*T) map[string]string) ([]*T, error) {
|
||||
labelSelector, err := metav1.ParseToLabelSelector(annotationFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector, err := metav1.LabelSelectorAsSelector(labelSelector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if selector.Empty() {
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
var filteredList []*T
|
||||
for _, resource := range resources {
|
||||
annotations := getAnnotations(resource)
|
||||
if selector.Matches(labels.Set(annotations)) {
|
||||
filteredList = append(filteredList, resource)
|
||||
}
|
||||
}
|
||||
|
||||
return filteredList, nil
|
||||
}
|
||||
|
||||
func getAnnotations(obj interface{}) map[string]string {
|
||||
switch o := obj.(type) {
|
||||
case *IngressRouteUDP:
|
||||
return o.Annotations
|
||||
case *IngressRoute:
|
||||
return o.Annotations
|
||||
case *IngressRouteTCP:
|
||||
return o.Annotations
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func getObjectFullName(obj interface{}) string {
|
||||
switch o := obj.(type) {
|
||||
case *IngressRouteUDP:
|
||||
return fmt.Sprintf("%s/%s", o.Namespace, o.Name)
|
||||
case *IngressRoute:
|
||||
return fmt.Sprintf("%s/%s", o.Namespace, o.Name)
|
||||
case *IngressRouteTCP:
|
||||
return fmt.Sprintf("%s/%s", o.Namespace, o.Name)
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,9 @@ import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@ -1731,3 +1733,80 @@ func TestTraefikAPIGroupDisableFlags(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddEventHandler_AllBranches(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
handlerCalled := false
|
||||
handler := func() { handlerCalled = true }
|
||||
|
||||
inf := testInformer{}
|
||||
fakeInformer := new(FakeInformer)
|
||||
fakeInformer.On("Informer").Return(&inf)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
ts *traefikSource
|
||||
want int
|
||||
}{
|
||||
{"all nil", &traefikSource{}, 0},
|
||||
{"all set", &traefikSource{
|
||||
ingressRouteInformer: fakeInformer,
|
||||
oldIngressRouteInformer: fakeInformer,
|
||||
ingressRouteTcpInformer: fakeInformer,
|
||||
oldIngressRouteTcpInformer: fakeInformer,
|
||||
ingressRouteUdpInformer: fakeInformer,
|
||||
oldIngressRouteUdpInformer: fakeInformer,
|
||||
}, 6},
|
||||
{"some set", &traefikSource{
|
||||
ingressRouteInformer: fakeInformer,
|
||||
oldIngressRouteInformer: fakeInformer,
|
||||
ingressRouteTcpInformer: nil,
|
||||
oldIngressRouteTcpInformer: fakeInformer,
|
||||
ingressRouteUdpInformer: nil,
|
||||
oldIngressRouteUdpInformer: nil,
|
||||
}, 3},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
test.ts.AddEventHandler(ctx, handler)
|
||||
assert.Equal(t, test.want, inf.times)
|
||||
assert.False(t, handlerCalled)
|
||||
|
||||
if test.want > 0 {
|
||||
fakeInformer.AssertExpectations(t)
|
||||
fakeInformer.AssertCalled(t, "Informer")
|
||||
} else {
|
||||
fakeInformer.AssertNotCalled(t, "Informer")
|
||||
}
|
||||
// reset the call count
|
||||
inf.times = 0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type FakeInformer struct {
|
||||
mock.Mock
|
||||
informer cache.SharedIndexInformer
|
||||
lister cache.GenericLister
|
||||
}
|
||||
|
||||
func (f *FakeInformer) Informer() cache.SharedIndexInformer {
|
||||
args := f.Called()
|
||||
return args.Get(0).(cache.SharedIndexInformer)
|
||||
}
|
||||
|
||||
func (f *FakeInformer) Lister() cache.GenericLister {
|
||||
return f.lister
|
||||
}
|
||||
|
||||
type testInformer struct {
|
||||
cache.SharedIndexInformer
|
||||
|
||||
times int
|
||||
}
|
||||
|
||||
func (t *testInformer) AddEventHandler(handler cache.ResourceEventHandler) (cache.ResourceEventHandlerRegistration, error) {
|
||||
t.times += 1
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user