@@ -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