@@ -3,6 +3,7 @@ package backend
33import  (
44	"context" 
55	"fmt" 
6+ 	"net" 
67
78	awssdk "github.com/aws/aws-sdk-go/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 : int64 (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  {
@@ -170,7 +198,7 @@ func (r *defaultEndpointResolver) resolvePodEndpointsWithEndpointsData(ctx conte
170198					containsPotentialReadyEndpoints  =  true 
171199					continue 
172200				}
173- 				podEndpoint  :=  buildPodEndpoint (pod , epAddr , epPort )
201+ 				podEndpoint  :=  buildPodEndpoint (& pod , epAddr , epPort )
174202				if  ep .Conditions .Ready  !=  nil  &&  * ep .Conditions .Ready  {
175203					readyPodEndpoints  =  append (readyPodEndpoints , podEndpoint )
176204					continue 
@@ -214,13 +242,14 @@ func (r *defaultEndpointResolver) resolvePodEndpointsWithEndpointsData(ctx conte
214242}
215243
216244func  (r  * defaultEndpointResolver ) findServiceAndServicePort (ctx  context.Context , svcKey  types.NamespacedName , port  intstr.IntOrString ) (* corev1.Service , corev1.ServicePort , error ) {
217- 	svc  :=  & corev1.Service {}
218- 	if  err  :=  r .k8sClient .Get (ctx , svcKey , svc ); err  !=  nil  {
219- 		if  apierrors .IsNotFound (err ) {
220- 			return  nil , corev1.ServicePort {}, fmt .Errorf ("%w: %v" , ErrNotFound , err .Error ())
221- 		}
245+ 	svc , err  :=  r .FindService (ctx , svcKey )
246+ 	if  err  !=  nil  {
222247		return  nil , corev1.ServicePort {}, err 
223248	}
249+ 	return  r .findServicePort (svc , port )
250+ }
251+ 
252+ func  (r  * defaultEndpointResolver ) findServicePort (svc  * corev1.Service , port  intstr.IntOrString ) (* corev1.Service , corev1.ServicePort , error ) {
224253	svcPort , err  :=  k8s .LookupServicePort (svc , port )
225254	if  err  !=  nil  {
226255		return  nil , corev1.ServicePort {}, fmt .Errorf ("%w: %v" , ErrNotFound , err .Error ())
@@ -229,6 +258,17 @@ func (r *defaultEndpointResolver) findServiceAndServicePort(ctx context.Context,
229258	return  svc , svcPort , nil 
230259}
231260
261+ func  (r  * defaultEndpointResolver ) FindService (ctx  context.Context , svcKey  types.NamespacedName ) (* corev1.Service , error ) {
262+ 	svc  :=  & corev1.Service {}
263+ 	if  err  :=  r .k8sClient .Get (ctx , svcKey , svc ); err  !=  nil  {
264+ 		if  apierrors .IsNotFound (err ) {
265+ 			return  nil , fmt .Errorf ("%w: %v" , ErrNotFound , err .Error ())
266+ 		}
267+ 		return  nil , err 
268+ 	}
269+ 	return  svc , nil 
270+ }
271+ 
232272// filterNodesByReadyConditionStatus will filter out nodes that matches specified ready condition status 
233273func  filterNodesByReadyConditionStatus (nodes  []* corev1.Node , readyCondStatus  corev1.ConditionStatus ) []* corev1.Node  {
234274	var  nodesWithMatchingReadyStatus  []* corev1.Node 
@@ -281,8 +321,8 @@ func buildEndpointsDataFromEndpointSliceList(epsList *discovery.EndpointSliceLis
281321	return  endpointsDataList 
282322}
283323
284- func  buildPodEndpoint (pod  k8s.PodInfo , epAddr  string , port  int32 ) PodEndpoint  {
285- 	return  PodEndpoint {
324+ func  buildPodEndpoint (pod  * k8s.PodInfo , epAddr  string , port  int32 ) IpEndpoint  {
325+ 	return  IpEndpoint {
286326		IP :   epAddr ,
287327		Port : int64 (port ),
288328		Pod :  pod ,
0 commit comments