@@ -3,6 +3,7 @@ package backend
33import (
44 "context"
55 "fmt"
6+ "net"
67
78 awssdk "github.com/aws/aws-sdk-go-v2/aws"
89 "github.com/go-logr/logr"
@@ -27,12 +28,17 @@ var ErrNotFound = errors.New("backend not found")
2728type EndpointResolver interface {
2829 // ResolvePodEndpoints will resolve endpoints backed by pods directly.
2930 // returns resolved podEndpoints and whether there are unready endpoints that can potentially turn ready in future reconciles.
30- ResolvePodEndpoints (ctx context.Context , svcKey types.NamespacedName , port intstr.IntOrString ,
31- opts ... EndpointResolveOption ) ([]PodEndpoint , bool , error )
31+ ResolvePodEndpoints (ctx context.Context , svckey types.NamespacedName , svc * corev1.Service , port intstr.IntOrString , opts ... EndpointResolveOption ) ([]IpEndpoint , bool , error )
3232
3333 // ResolveNodePortEndpoints will resolve endpoints backed by nodePort.
3434 ResolveNodePortEndpoints (ctx context.Context , svcKey types.NamespacedName , port intstr.IntOrString ,
3535 opts ... EndpointResolveOption ) ([]NodePortEndpoint , error )
36+
37+ // FindService finds a k8s service
38+ FindService (ctx context.Context , svcKey types.NamespacedName ) (* corev1.Service , error )
39+
40+ // ResolveExternalNameEndpoints will resolve external name using dns
41+ ResolveExternalNameEndpoints (ctx context.Context , svc * corev1.Service , port intstr.IntOrString ) ([]IpEndpoint , error )
3642}
3743
3844// NewDefaultEndpointResolver constructs new defaultEndpointResolver
@@ -42,6 +48,7 @@ func NewDefaultEndpointResolver(k8sClient client.Client, podInfoRepo k8s.PodInfo
4248 podInfoRepo : podInfoRepo ,
4349 failOpenEnabled : failOpenEnabled ,
4450 endpointSliceEnabled : endpointSliceEnabled ,
51+ dnsResolver : net .DefaultResolver ,
4552 logger : logger ,
4653 }
4754}
@@ -58,13 +65,34 @@ type defaultEndpointResolver struct {
5865 // [Pod Endpoint] whether to use endpointSlice instead of endpoints
5966 endpointSliceEnabled bool
6067 logger logr.Logger
68+ // dnsResolver to use for resolving external names
69+ dnsResolver dnsResolver
70+ }
71+
72+ type dnsResolver interface {
73+ LookupHost (ctx context.Context , host string ) (addrs []string , err error )
74+ }
75+
76+ func (r * defaultEndpointResolver ) ResolveExternalNameEndpoints (ctx context.Context , svc * corev1.Service , port intstr.IntOrString ) ([]IpEndpoint , error ) {
77+ if port .Type == intstr .String {
78+ return nil , fmt .Errorf ("port of target group must be numeric for external name" )
79+ }
80+ addrs , err := r .dnsResolver .LookupHost (ctx , svc .Spec .ExternalName )
81+ if err != nil {
82+ return nil , err
83+ }
84+ endpoints := make ([]IpEndpoint , len (addrs ))
85+ for i , ip := range addrs {
86+ endpoints [i ] = IpEndpoint {IP : ip , Port : port .IntVal }
87+ }
88+ return endpoints , nil
6189}
6290
63- func (r * defaultEndpointResolver ) ResolvePodEndpoints (ctx context.Context , svcKey types.NamespacedName , port intstr.IntOrString , opts ... EndpointResolveOption ) ([]PodEndpoint , bool , error ) {
91+ func (r * defaultEndpointResolver ) ResolvePodEndpoints (ctx context.Context , svcKey types.NamespacedName , svc * corev1. Service , port intstr.IntOrString , opts ... EndpointResolveOption ) ([]IpEndpoint , bool , error ) {
6492 resolveOpts := defaultEndpointResolveOptions ()
6593 resolveOpts .ApplyOptions (opts )
6694
67- _ , svcPort , err := r .findServiceAndServicePort ( ctx , svcKey , port )
95+ _ , svcPort , err := r .findServicePort ( svc , port )
6896 if err != nil {
6997 return nil , false , err
7098 }
@@ -140,9 +168,9 @@ func (r *defaultEndpointResolver) computeServiceEndpointsData(ctx context.Contex
140168 return endpointsDataList , nil
141169}
142170
143- func (r * defaultEndpointResolver ) resolvePodEndpointsWithEndpointsData (ctx context.Context , svcKey types.NamespacedName , svcPort corev1.ServicePort , endpointsDataList []EndpointsData , podReadinessGates []corev1.PodConditionType ) ([]PodEndpoint , bool , error ) {
144- var readyPodEndpoints []PodEndpoint
145- var unknownPodEndpoints []PodEndpoint
171+ func (r * defaultEndpointResolver ) resolvePodEndpointsWithEndpointsData (ctx context.Context , svcKey types.NamespacedName , svcPort corev1.ServicePort , endpointsDataList []EndpointsData , podReadinessGates []corev1.PodConditionType ) ([]IpEndpoint , bool , error ) {
172+ var readyPodEndpoints []IpEndpoint
173+ var unknownPodEndpoints []IpEndpoint
146174 containsPotentialReadyEndpoints := false
147175
148176 for _ , epsData := range endpointsDataList {
@@ -171,7 +199,7 @@ func (r *defaultEndpointResolver) resolvePodEndpointsWithEndpointsData(ctx conte
171199 continue
172200 }
173201
174- podEndpoint := buildPodEndpoint (pod , epAddr , epPort )
202+ podEndpoint := buildPodEndpoint (& pod , epAddr , epPort )
175203 // Recommendation from Kubernetes is to consider unknown ready status as ready (ready == nil)
176204 if ep .Conditions .Ready == nil || * ep .Conditions .Ready {
177205 readyPodEndpoints = append (readyPodEndpoints , podEndpoint )
@@ -216,13 +244,14 @@ func (r *defaultEndpointResolver) resolvePodEndpointsWithEndpointsData(ctx conte
216244}
217245
218246func (r * defaultEndpointResolver ) findServiceAndServicePort (ctx context.Context , svcKey types.NamespacedName , port intstr.IntOrString ) (* corev1.Service , corev1.ServicePort , error ) {
219- svc := & corev1.Service {}
220- if err := r .k8sClient .Get (ctx , svcKey , svc ); err != nil {
221- if apierrors .IsNotFound (err ) {
222- return nil , corev1.ServicePort {}, fmt .Errorf ("%w: %v" , ErrNotFound , err .Error ())
223- }
247+ svc , err := r .FindService (ctx , svcKey )
248+ if err != nil {
224249 return nil , corev1.ServicePort {}, err
225250 }
251+ return r .findServicePort (svc , port )
252+ }
253+
254+ func (r * defaultEndpointResolver ) findServicePort (svc * corev1.Service , port intstr.IntOrString ) (* corev1.Service , corev1.ServicePort , error ) {
226255 svcPort , err := k8s .LookupServicePort (svc , port )
227256 if err != nil {
228257 return nil , corev1.ServicePort {}, fmt .Errorf ("%w: %v" , ErrNotFound , err .Error ())
@@ -231,6 +260,17 @@ func (r *defaultEndpointResolver) findServiceAndServicePort(ctx context.Context,
231260 return svc , svcPort , nil
232261}
233262
263+ func (r * defaultEndpointResolver ) FindService (ctx context.Context , svcKey types.NamespacedName ) (* corev1.Service , error ) {
264+ svc := & corev1.Service {}
265+ if err := r .k8sClient .Get (ctx , svcKey , svc ); err != nil {
266+ if apierrors .IsNotFound (err ) {
267+ return nil , fmt .Errorf ("%w: %v" , ErrNotFound , err .Error ())
268+ }
269+ return nil , err
270+ }
271+ return svc , nil
272+ }
273+
234274// filterNodesByReadyConditionStatus will filter out nodes that matches specified ready condition status
235275func filterNodesByReadyConditionStatus (nodes []* corev1.Node , readyCondStatus corev1.ConditionStatus ) []* corev1.Node {
236276 var nodesWithMatchingReadyStatus []* corev1.Node
@@ -283,8 +323,8 @@ func buildEndpointsDataFromEndpointSliceList(epsList *discovery.EndpointSliceLis
283323 return endpointsDataList
284324}
285325
286- func buildPodEndpoint (pod k8s.PodInfo , epAddr string , port int32 ) PodEndpoint {
287- return PodEndpoint {
326+ func buildPodEndpoint (pod * k8s.PodInfo , epAddr string , port int32 ) IpEndpoint {
327+ return IpEndpoint {
288328 IP : epAddr ,
289329 Port : port ,
290330 Pod : pod ,
0 commit comments