@@ -3,6 +3,7 @@ package backend
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "net"
6
7
7
8
awssdk "github.com/aws/aws-sdk-go/aws"
8
9
"github.com/go-logr/logr"
@@ -27,12 +28,17 @@ var ErrNotFound = errors.New("backend not found")
27
28
type EndpointResolver interface {
28
29
// ResolvePodEndpoints will resolve endpoints backed by pods directly.
29
30
// 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 )
32
32
33
33
// ResolveNodePortEndpoints will resolve endpoints backed by nodePort.
34
34
ResolveNodePortEndpoints (ctx context.Context , svcKey types.NamespacedName , port intstr.IntOrString ,
35
35
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 )
36
42
}
37
43
38
44
// NewDefaultEndpointResolver constructs new defaultEndpointResolver
@@ -42,6 +48,7 @@ func NewDefaultEndpointResolver(k8sClient client.Client, podInfoRepo k8s.PodInfo
42
48
podInfoRepo : podInfoRepo ,
43
49
failOpenEnabled : failOpenEnabled ,
44
50
endpointSliceEnabled : endpointSliceEnabled ,
51
+ dnsResolver : net .DefaultResolver ,
45
52
logger : logger ,
46
53
}
47
54
}
@@ -58,13 +65,34 @@ type defaultEndpointResolver struct {
58
65
// [Pod Endpoint] whether to use endpointSlice instead of endpoints
59
66
endpointSliceEnabled bool
60
67
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
61
89
}
62
90
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 ) {
64
92
resolveOpts := defaultEndpointResolveOptions ()
65
93
resolveOpts .ApplyOptions (opts )
66
94
67
- _ , svcPort , err := r .findServiceAndServicePort ( ctx , svcKey , port )
95
+ _ , svcPort , err := r .findServicePort ( svc , port )
68
96
if err != nil {
69
97
return nil , false , err
70
98
}
@@ -140,9 +168,9 @@ func (r *defaultEndpointResolver) computeServiceEndpointsData(ctx context.Contex
140
168
return endpointsDataList , nil
141
169
}
142
170
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
146
174
containsPotentialReadyEndpoints := false
147
175
148
176
for _ , epsData := range endpointsDataList {
@@ -170,7 +198,7 @@ func (r *defaultEndpointResolver) resolvePodEndpointsWithEndpointsData(ctx conte
170
198
containsPotentialReadyEndpoints = true
171
199
continue
172
200
}
173
- podEndpoint := buildPodEndpoint (pod , epAddr , epPort )
201
+ podEndpoint := buildPodEndpoint (& pod , epAddr , epPort )
174
202
if ep .Conditions .Ready != nil && * ep .Conditions .Ready {
175
203
readyPodEndpoints = append (readyPodEndpoints , podEndpoint )
176
204
continue
@@ -214,13 +242,14 @@ func (r *defaultEndpointResolver) resolvePodEndpointsWithEndpointsData(ctx conte
214
242
}
215
243
216
244
func (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 {
222
247
return nil , corev1.ServicePort {}, err
223
248
}
249
+ return r .findServicePort (svc , port )
250
+ }
251
+
252
+ func (r * defaultEndpointResolver ) findServicePort (svc * corev1.Service , port intstr.IntOrString ) (* corev1.Service , corev1.ServicePort , error ) {
224
253
svcPort , err := k8s .LookupServicePort (svc , port )
225
254
if err != nil {
226
255
return nil , corev1.ServicePort {}, fmt .Errorf ("%w: %v" , ErrNotFound , err .Error ())
@@ -229,6 +258,17 @@ func (r *defaultEndpointResolver) findServiceAndServicePort(ctx context.Context,
229
258
return svc , svcPort , nil
230
259
}
231
260
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
+
232
272
// filterNodesByReadyConditionStatus will filter out nodes that matches specified ready condition status
233
273
func filterNodesByReadyConditionStatus (nodes []* corev1.Node , readyCondStatus corev1.ConditionStatus ) []* corev1.Node {
234
274
var nodesWithMatchingReadyStatus []* corev1.Node
@@ -281,8 +321,8 @@ func buildEndpointsDataFromEndpointSliceList(epsList *discovery.EndpointSliceLis
281
321
return endpointsDataList
282
322
}
283
323
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 {
286
326
IP : epAddr ,
287
327
Port : int64 (port ),
288
328
Pod : pod ,
0 commit comments